diff options
author | 2022-05-13 03:21:15 -0400 | |
---|---|---|
committer | 2022-05-13 17:21:15 +1000 | |
commit | 51a0b7020883510300296cf77e3c8c22f70a6a02 (patch) | |
tree | d125288fea5d49dc5432f434c694af9253780975 | |
parent | 98b14fa8ae8451ccf1bb6ff6b82c1db775b9d8cf (diff) |
zx spectrum drivers: Restore irq length == 32 / border timings. (#9711)
-rw-r--r-- | src/mame/drivers/pentagon.cpp | 4 | ||||
-rw-r--r-- | src/mame/drivers/spec128.cpp | 19 | ||||
-rw-r--r-- | src/mame/drivers/specpls3.cpp | 5 | ||||
-rw-r--r-- | src/mame/drivers/spectrum.cpp | 16 | ||||
-rw-r--r-- | src/mame/includes/spectrum.h | 6 | ||||
-rw-r--r-- | src/mame/machine/tsconf.cpp | 10 | ||||
-rw-r--r-- | src/mame/video/agat7.cpp | 2 | ||||
-rw-r--r-- | src/mame/video/agat9.cpp | 4 | ||||
-rw-r--r-- | src/mame/video/spectrum.cpp | 37 | ||||
-rw-r--r-- | src/mame/video/timex.cpp | 2 |
10 files changed, 69 insertions, 36 deletions
diff --git a/src/mame/drivers/pentagon.cpp b/src/mame/drivers/pentagon.cpp index 9040db14f7f..22df60484dd 100644 --- a/src/mame/drivers/pentagon.cpp +++ b/src/mame/drivers/pentagon.cpp @@ -217,8 +217,8 @@ void pentagon_state::machine_reset() void pentagon_state::video_start() { - m_frame_invert_count = 16; - m_screen_location = m_ram->pointer() + (5 << 14); + spectrum_128_state::video_start(); + m_contention_pattern = {}; } static const gfx_layout spectrum_charlayout = diff --git a/src/mame/drivers/spec128.cpp b/src/mame/drivers/spec128.cpp index 4c545b9adb4..f22f6b2af68 100644 --- a/src/mame/drivers/spec128.cpp +++ b/src/mame/drivers/spec128.cpp @@ -167,9 +167,9 @@ resulting mess can be seen in the F4 viewer display. void spectrum_128_state::video_start() { - m_frame_invert_count = 16; + spectrum_state::video_start(); m_screen_location = m_ram->pointer() + (5 << 14); - m_contention_pattern = {6, 5, 4, 3, 2, 1, 0, 0}; + m_border4t_render_at = 6; } uint8_t spectrum_128_state::spectrum_128_pre_opcode_fetch_r(offs_t offset) @@ -230,8 +230,6 @@ void spectrum_128_state::spectrum_128_port_7ffd_w(offs_t offset, uint8_t data) /* disable paging? */ if (m_port_7ffd_data & 0x20) return; - if ((m_port_7ffd_data ^ data) & 0x08) m_screen->update_now(); - /* store new state */ m_port_7ffd_data = data; @@ -293,6 +291,10 @@ void spectrum_128_state::spectrum_128_fetch(address_map &map) void spectrum_128_state::machine_start() { + spectrum_state::machine_start(); + + save_item(NAME(m_port_7ffd_data)); + /* rom 0 is 128K rom, rom 1 is 48 BASIC */ memory_region *rom = memregion("maincpu"); m_bank_rom[0]->configure_entries(0, 2, rom->base() + 0x10000, 0x4000); @@ -313,22 +315,19 @@ void spectrum_128_state::machine_reset() /* set initial ram config */ m_port_7ffd_data = 0; - m_port_1ffd_data = -1; spectrum_128_update_memory(); } bool spectrum_128_state::is_vram_write(offs_t offset) { - // TODO respect banks 2,5 mapped to 0xc000 - return (BIT(m_port_7ffd_data, 3)) - ? offset >= 0x8000 && offset < 0x9b00 + return (BIT(m_port_7ffd_data, 3) && m_bank_ram[3]->entry() == 7) + ? offset >= 0xc000 && offset < 0xdb00 : spectrum_state::is_vram_write(offset); } bool spectrum_128_state::is_contended(offs_t offset) { - // Memory banks 1,3,5 and 7 are contended u8 bank = m_bank_ram[3]->entry(); return spectrum_state::is_contended(offset) - || ((offset >= 0xc000 && offset <= 0xffff) && (bank && 1)); + || ((offset >= 0xc000 && offset <= 0xffff) && (bank && 1)); // Memory banks 1,3,5 and 7 are contended } static const gfx_layout spectrum_charlayout = diff --git a/src/mame/drivers/specpls3.cpp b/src/mame/drivers/specpls3.cpp index ac8f1a99db6..a65c8faf458 100644 --- a/src/mame/drivers/specpls3.cpp +++ b/src/mame/drivers/specpls3.cpp @@ -266,8 +266,6 @@ void specpls3_state::port_7ffd_w(offs_t offset, uint8_t data) /* paging disabled? */ if (m_port_7ffd_data & 0x20) return; - if ((m_port_7ffd_data ^ data) & 0x08) m_screen->update_now(); - /* store new state */ m_port_7ffd_data = data; @@ -342,6 +340,8 @@ void specpls3_state::machine_start() { spectrum_128_state::machine_start(); + save_item(NAME(m_port_1ffd_data)); + // reconfigure ROMs memory_region *rom = memregion("maincpu"); m_bank_rom[0]->configure_entries(0, 4, rom->base() + 0x10000, 0x4000); @@ -352,6 +352,7 @@ void specpls3_state::machine_start() void specpls3_state::machine_reset() { /* Initial configuration */ + m_port_fe_data = -1; m_port_7ffd_data = 0; m_port_1ffd_data = 0; plus3_update_memory(); diff --git a/src/mame/drivers/spectrum.cpp b/src/mame/drivers/spectrum.cpp index 4b1d5cecac2..b99227983df 100644 --- a/src/mame/drivers/spectrum.cpp +++ b/src/mame/drivers/spectrum.cpp @@ -727,10 +727,14 @@ void spectrum_state::init_spectrum() void spectrum_state::machine_start() { save_item(NAME(m_port_fe_data)); + save_item(NAME(m_int_at)); } void spectrum_state::machine_reset() { + /* Initial value/behaviour of FE port is not confirmed. Startup of real devices produce 'random' border + color which need to be investigated. */ + m_port_fe_data = -1; m_port_7ffd_data = -1; m_port_1ffd_data = -1; } @@ -756,8 +760,10 @@ void spectrum_state::device_timer(emu_timer &timer, device_timer_id id, int para switch (id) { case TIMER_IRQ_ON: - m_maincpu->set_input_line(0, HOLD_LINE); - timer_set(m_maincpu->clocks_to_attotime(32), TIMER_IRQ_OFF, 0); + m_int_at = m_maincpu->total_cycles(); + m_int_at -= m_maincpu->attotime_to_cycles(m_maincpu->local_time() - machine().time()); + m_maincpu->set_input_line(0, ASSERT_LINE); + m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32)); break; case TIMER_IRQ_OFF: m_maincpu->set_input_line(0, CLEAR_LINE); @@ -767,13 +773,9 @@ void spectrum_state::device_timer(emu_timer &timer, device_timer_id id, int para } } -attotime spectrum_state::time_until_int() { - return m_screen->time_until_pos(0, get_screen_area().left()); -}; - INTERRUPT_GEN_MEMBER(spectrum_state::spec_interrupt) { - timer_set(time_until_int(), TIMER_IRQ_ON, 0); + timer_set(m_screen->time_until_pos(0, get_screen_area().left()), TIMER_IRQ_ON); } void spectrum_state::spectrum_common(machine_config &config) diff --git a/src/mame/includes/spectrum.h b/src/mame/includes/spectrum.h index 0478c845598..27fa6e3be3a 100644 --- a/src/mame/includes/spectrum.h +++ b/src/mame/includes/spectrum.h @@ -115,8 +115,13 @@ protected: int m_ROMSelection = 0; // FIXME: this is used for various things in derived classes, but not by this base class, and should be removed std::vector<u8> m_contention_pattern; + /* Pixel offset in 8px chunk (4T) when current chunk is rendered. */ + u8 m_border4t_render_at = 0; /* Defines offset in CPU cycles from screen left side. Early model (48/128/+2) typically use -1, later (+2A/+3) +1 */ s8 m_contention_offset = -1; + u64 m_int_at; + + emu_timer *m_irq_off_timer; uint8_t m_ram_disabled_by_beta; uint8_t pre_opcode_fetch_r(offs_t offset); @@ -140,7 +145,6 @@ protected: void spectrum_palette(palette_device &palette) const; virtual u32 screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); INTERRUPT_GEN_MEMBER(spec_interrupt); - virtual attotime time_until_int(); DECLARE_SNAPSHOT_LOAD_MEMBER(snapshot_cb); DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb); diff --git a/src/mame/machine/tsconf.cpp b/src/mame/machine/tsconf.cpp index 99bcb99c8c3..3540708fbf8 100644 --- a/src/mame/machine/tsconf.cpp +++ b/src/mame/machine/tsconf.cpp @@ -755,7 +755,7 @@ void tsconf_state::update_frame_timer() INTERRUPT_GEN_MEMBER(tsconf_state::tsconf_vblank_interrupt) { update_frame_timer(); - m_line_irq_timer->adjust(m_screen->time_until_pos(0)); + m_line_irq_timer->adjust(attotime::zero); } void tsconf_state::dma_ready(int line) @@ -763,7 +763,7 @@ void tsconf_state::dma_ready(int line) if (BIT(m_regs[INT_MASK], 4)) { m_maincpu->set_input_line_and_vector(line, ASSERT_LINE, 0xfb); - timer_set(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))), TIMER_IRQ_OFF, 0); + m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03)))); } } @@ -776,7 +776,7 @@ void tsconf_state::device_timer(emu_timer &timer, device_timer_id id, int param) if (BIT(m_regs[INT_MASK], 0)) { m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xff); - timer_set(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))), TIMER_IRQ_OFF, 0); + m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03)))); } break; } @@ -788,12 +788,12 @@ void tsconf_state::device_timer(emu_timer &timer, device_timer_id id, int param) { m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xfd); // Not quite precise. Scanline can't be skipped. - timer_set(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))), TIMER_IRQ_OFF, 0); + m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03)))); } if (BIT(m_regs[INT_MASK], 0) && OFFS_512(VS_INT_L) == screen_vpos && m_regs[HS_INT] == 0) { m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xff); - timer_set(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))), TIMER_IRQ_OFF, 0); + m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03)))); } m_screen->update_now(); diff --git a/src/mame/video/agat7.cpp b/src/mame/video/agat7.cpp index 38ca3db5d8d..038cbc180d0 100644 --- a/src/mame/video/agat7.cpp +++ b/src/mame/video/agat7.cpp @@ -87,7 +87,7 @@ void agat7video_device::device_start() void agat7video_device::device_reset() { - // XXX to be confirmed + // TODO to be confirmed m_video_mode = TEXT_LORES; m_start_address = 0x7800; } diff --git a/src/mame/video/agat9.cpp b/src/mame/video/agat9.cpp index af90147acbf..4c8f5f023df 100644 --- a/src/mame/video/agat9.cpp +++ b/src/mame/video/agat9.cpp @@ -135,7 +135,7 @@ void agat9video_device::device_start() void agat9video_device::device_reset() { - // XXX to be confirmed + // TODO to be confirmed m_video_mode = TEXT_LORES; m_start_address = 0x7800; m_mode = palette_index = 0; @@ -152,7 +152,7 @@ uint8_t agat9video_device::read(offs_t offset) { if(!machine().side_effects_disabled()) do_io(offset); - // XXX only 'Moscow' revision + // FIXME only 'Moscow' revision return m_mode; } diff --git a/src/mame/video/spectrum.cpp b/src/mame/video/spectrum.cpp index b16ebcc3f06..3bb40efe737 100644 --- a/src/mame/video/spectrum.cpp +++ b/src/mame/video/spectrum.cpp @@ -24,9 +24,13 @@ ***************************************************************************/ void spectrum_state::video_start() { + m_irq_off_timer = timer_alloc(TIMER_IRQ_OFF); + m_frame_invert_count = 16; m_screen_location = m_video_ram; m_contention_pattern = {6, 5, 4, 3, 2, 1, 0, 0}; + m_contention_offset = -1; + m_border4t_render_at = 2; } /*************************************************************************** @@ -116,14 +120,17 @@ u32 spectrum_state::screen_update_spectrum(screen_device &screen, bitmap_ind16 & void spectrum_state::spectrum_update_border(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &border) { - u8 mod = m_contention_pattern.empty() ? 1 : m_contention_pattern.size(); + u8 mod = m_contention_pattern.empty() ? 1 : 8; + u8 at = m_contention_pattern.empty() ? 0 : m_border4t_render_at; for (auto y = border.top(); y <= border.bottom(); y++) { u16 *pix = &(bitmap.pix(y, border.left())); for (auto x = border.left(); x <= border.right(); ) { - if (x % mod == 0) + if (x % mod == at) { + pix -= at; + x -= at; for (auto m = 0; m < mod; m++, x++) *pix++ = get_border_color(y, x); } @@ -136,6 +143,14 @@ void spectrum_state::spectrum_update_border(screen_device &screen, bitmap_ind16 } } +/* ULA reads screen data in 16px (8T) chunks as following: + T: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | +px: | 0 | 1 | 2 | 3 |*4*| 5 | 6 | 7 |*0*| 1 | 2 | 3 | 4 | 5 | 6 | 7 | + | << !right << | char1 | attr1 | char2 | attr2 | >> right >> | + +TODO Curren implementation only tracks char switch position. In order to track both (char and attr) we need to share + some state between screen->update() events. +*/ void spectrum_state::spectrum_update_screen(screen_device &screen_d, bitmap_ind16 &bitmap, const rectangle &screen) { u8 *attrs_location = m_screen_location + 0x1800; @@ -144,17 +159,26 @@ void spectrum_state::spectrum_update_screen(screen_device &screen_d, bitmap_ind1 { u16 hpos = screen.left(); u16 x = hpos - get_screen_area().left(); - if (x % 8) + bool chunk_right = x & 8; + if (x % 8 <= (chunk_right ? 0 : 4)) + { + u8 shift = x % 8; + x -= shift; + hpos -= shift; + } + else { u8 shift = 8 - (x % 8); x += shift; hpos += shift; + chunk_right = !chunk_right; } u16 y = vpos - get_screen_area().top(); u8 *scr = &m_screen_location[((y & 7) << 8) | ((y & 0x38) << 2) | ((y & 0xc0) << 5) | (x >> 3)]; u8 *attr = &attrs_location[((y & 0xf8) << 2) | (x >> 3)]; u16 *pix = &(bitmap.pix(vpos, hpos)); - while (hpos <= screen.right()) + + while ((hpos + (chunk_right ? 0 : 4)) <= screen.right()) { u16 ink = ((*attr >> 3) & 0x08) | (*attr & 0x07); u16 pap = (*attr >> 3) & 0x0f; @@ -164,6 +188,7 @@ void spectrum_state::spectrum_update_screen(screen_device &screen_d, bitmap_ind1 *pix++ = (pix8 & b) ? ink : pap; scr++; attr++; + chunk_right = !chunk_right; } } } @@ -182,7 +207,7 @@ void spectrum_state::content_early(s8 shift) if (m_contention_pattern.empty() || vpos < get_screen_area().top() || vpos > get_screen_area().bottom()) return; - u64 now = m_maincpu->attotime_to_clocks(m_screen->frame_period() - time_until_int()) + shift; + u64 now = m_maincpu->total_cycles() - m_int_at + shift; u64 cf = vpos * m_screen->width() * m_maincpu->clock() / m_screen->clock() + m_contention_offset; u64 ct = cf + get_screen_area().width() * m_maincpu->clock() / m_screen->clock(); @@ -200,7 +225,7 @@ void spectrum_state::content_late() if (m_contention_pattern.empty() || vpos < get_screen_area().top() || vpos > get_screen_area().bottom()) return; - u64 now = m_maincpu->attotime_to_clocks(m_screen->frame_period() - time_until_int()) + 1; + u64 now = m_maincpu->total_cycles() - m_int_at + 1; u64 cf = vpos * m_screen->width() * m_maincpu->clock() / m_screen->clock() + m_contention_offset; u64 ct = cf + get_screen_area().width() * m_maincpu->clock() / m_screen->clock(); for(auto i = 0x04; i; i >>= 1) diff --git a/src/mame/video/timex.cpp b/src/mame/video/timex.cpp index fb690a0c0c6..e3c92ee88c4 100644 --- a/src/mame/video/timex.cpp +++ b/src/mame/video/timex.cpp @@ -29,6 +29,8 @@ inline void tc2048_state::spectrum_plot_pixel(bitmap_ind16 &bitmap, int x, int y /* Update FLASH status for ts2068. Assumes flash update every 1/2s. */ void ts2068_state::video_start() { + m_irq_off_timer = timer_alloc(TIMER_IRQ_OFF); + m_frame_invert_count = 30; m_screen_location = m_video_ram; } |