diff options
| author | 2023-05-24 20:25:54 -0400 | |
|---|---|---|
| committer | 2023-05-24 20:25:54 -0400 | |
| commit | 5c8a49c92cf009ccf958c6ca37d7bc34536d2693 (patch) | |
| tree | 6e2285cfc8c1100f72a80caab123a56fc7b6c602 /src | |
| parent | 1109aa3c3d28322a88eefd0aa8d7f41f3aae2652 (diff) | |
sinclair/tsconf.cpp: finalize regs delayed updates; fix graphic pages padding (#11248)
- finalize regs delayed updates; fix graphic pages padding
- fix spectrum page switch
Diffstat (limited to 'src')
| -rw-r--r-- | src/mame/sinclair/tsconf.cpp | 13 | ||||
| -rw-r--r-- | src/mame/sinclair/tsconf.h | 9 | ||||
| -rw-r--r-- | src/mame/sinclair/tsconf_m.cpp | 97 | ||||
| -rw-r--r-- | src/mame/sinclair/tsconfdma.cpp | 78 | ||||
| -rw-r--r-- | src/mame/sinclair/tsconfdma.h | 9 |
5 files changed, 119 insertions, 87 deletions
diff --git a/src/mame/sinclair/tsconf.cpp b/src/mame/sinclair/tsconf.cpp index 439e49f0461..21e9a2ccf99 100644 --- a/src/mame/sinclair/tsconf.cpp +++ b/src/mame/sinclair/tsconf.cpp @@ -27,17 +27,6 @@ TsConf: https://github.com/tslabs/zx-evo/blob/master/pentevo/docs/TSconf/tsconf_ FAQ-RUS: https://forum.tslabs.info/viewtopic.php?f=35&t=157 ROM: https://github.com/tslabs/zx-evo/blob/master/pentevo/rom/bin/ts-bios.rom (validated on: 2021-12-14) -HowTo: -# Create SD image "wc.img" -# Copy WC files from archive https://github.com/tslabs/zx-evo/blob/master/pentevo/soft/WC/wc.zip -# Tech Demos (currently *.spg only): http://prods.tslabs.info/index.php?t=4 -$ chdman createhd -i wc.img -o wc.chd -c none -$ mame tsconf -hard wc.chd -# BIOS Setup loads on fresh setup (return to BIOS: RShift+F3) -# Change "Reset To: BD boot.$c" -# Reset (F3) -# Enable keyboard: MAME Setup (Tab) > Keyboard Mode > AT Keyboard: Enabled - TODO: - Ram cache - VDos @@ -56,7 +45,7 @@ TODO: TILE_GET_INFO_MEMBER(tsconf_state::get_tile_info_txt) { - u8 *m_row_location = &m_ram->pointer()[(m_regs[V_PAGE] << 14) + (tile_index / tilemap.cols() * 256)]; + u8 *m_row_location = &m_ram->pointer()[get_vpage_offset() + (tile_index / tilemap.cols() * 256)]; u8 col = tile_index % tilemap.cols(); u8 symbol = m_row_location[col]; tileinfo.set(TM_TS_CHAR, symbol, 0, 0); diff --git a/src/mame/sinclair/tsconf.h b/src/mame/sinclair/tsconf.h index a506fc69934..34ce5cd5df9 100644 --- a/src/mame/sinclair/tsconf.h +++ b/src/mame/sinclair/tsconf.h @@ -150,6 +150,7 @@ private: TILE_GET_INFO_MEMBER(get_tile_info_16c); u8 get_border_color(u16 hpos = ~0, u16 vpos = ~0) override; + u32 get_vpage_offset(); rectangle get_screen_area() override; void spectrum_update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) override; void tsconf_UpdateZxScreenBitmap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); @@ -164,10 +165,10 @@ private: void tsconf_ula_w(offs_t offset, u8 data); u8 tsconf_port_xxaf_r(offs_t reg); void tsconf_port_xxaf_w(offs_t reg, u8 data); - u8 tsconf_port_77_zctr_r(offs_t reg); - void tsconf_port_77_zctr_w(offs_t reg, u8 data); - u8 tsconf_port_57_zctr_r(offs_t reg); - void tsconf_port_57_zctr_w(offs_t reg, u8 data); + u8 tsconf_port_77_zctr_r(); + void tsconf_port_77_zctr_w(u8 data); + u8 tsconf_port_57_zctr_r(); + void tsconf_port_57_zctr_w(u8 data); void tsconf_spi_miso_w(u8 data); u8 tsconf_port_f7_r(offs_t offset); void tsconf_port_f7_w(offs_t offset, u8 data); diff --git a/src/mame/sinclair/tsconf_m.cpp b/src/mame/sinclair/tsconf_m.cpp index d1508905695..b667b239331 100644 --- a/src/mame/sinclair/tsconf_m.cpp +++ b/src/mame/sinclair/tsconf_m.cpp @@ -107,6 +107,11 @@ u8 tsconf_state::get_border_color(u16 hpos, u16 vpos) return m_regs[BORDER]; } +u32 tsconf_state::get_vpage_offset() +{ + return PAGE4K(m_regs[V_PAGE] & ((VM == VM_16C) ? 0xf8 : 0xf0)); +} + /* Layered as: + Border - already updated with screen_update_spectrum() @@ -158,7 +163,7 @@ void tsconf_state::tsconf_UpdateZxScreenBitmap(screen_device &screen, bitmap_ind { u8 pal_offset = m_regs[PAL_SEL] << 4; u8 *screen_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE]); - u8 *attrs_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE]) + 0x1800; + u8 *attrs_location = screen_location + 0x1800; bool invert_attrs = u64(screen.frame_number() / m_frame_invert_count) & 1; for (u16 vpos = cliprect.top(); vpos <= cliprect.bottom(); vpos++) { @@ -215,7 +220,7 @@ void tsconf_state::tsconf_UpdateGfxBitmap(bitmap_ind16 &bitmap, const rectangle { u16 y_offset = (OFFS_512(G_Y_OFFS_L) + m_gfx_y_frame_offset + vpos) & 0x1ff; u16 x_offset = (OFFS_512(G_X_OFFS_L) + (cliprect.left() - get_screen_area().left())) & 0x1ff; - u8 *video_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE]) + ((y_offset * 512 + x_offset) >> (2 - VM)); + u8 *video_location = m_ram->pointer() + get_vpage_offset() + ((y_offset * 512 + x_offset) >> (2 - VM)); u16 *bm = &(bitmap.pix(vpos, cliprect.left())); s16 width = cliprect.width(); if (VM == VM_16C) @@ -347,20 +352,20 @@ void tsconf_state::ram_page_write(u8 page, offs_t offset, u8 data) } else { - if (ram_addr >= PAGE4K(m_regs[T0_G_PAGE]) && ram_addr < PAGE4K(m_regs[T0_G_PAGE] + 8)) + if (ram_addr >= PAGE4K(m_regs[T0_G_PAGE] & 0xf8) && ram_addr < PAGE4K((m_regs[T0_G_PAGE] & 0xf8) + 8)) m_gfxdecode->gfx(TM_TILES0)->mark_all_dirty(); - if (ram_addr >= PAGE4K(m_regs[T1_G_PAGE]) && ram_addr < PAGE4K(m_regs[T1_G_PAGE] + 8)) + if (ram_addr >= PAGE4K(m_regs[T1_G_PAGE] & 0xf8) && ram_addr < PAGE4K((m_regs[T1_G_PAGE] & 0xf8) + 8)) m_gfxdecode->gfx(TM_TILES1)->mark_all_dirty(); } - if (ram_addr >= PAGE4K(m_regs[V_PAGE]) && ram_addr < PAGE4K(m_regs[V_PAGE] + 1)) + if (ram_addr >= get_vpage_offset() && ram_addr < get_vpage_offset() + PAGE4K((VM == VM_16C) ? 8 : 16)) m_ts_tilemap[TM_TS_CHAR]->mark_all_dirty(); if (ram_addr >= PAGE4K(m_regs[m_regs[V_PAGE] ^ 0x01]) && ram_addr < PAGE4K(m_regs[m_regs[V_PAGE] ^ 0x01] + 1)) m_gfxdecode->gfx(TM_TS_CHAR)->mark_all_dirty(); - if (ram_addr >= PAGE4K(m_regs[SG_PAGE]) && ram_addr < PAGE4K(m_regs[SG_PAGE] + 8)) + if (ram_addr >= PAGE4K(m_regs[SG_PAGE] & 0xf8) && ram_addr < PAGE4K((m_regs[SG_PAGE] & 0xf8) + 8)) m_gfxdecode->gfx(TM_SPRITES)->mark_all_dirty(); m_ram->write(ram_addr, data); @@ -379,7 +384,8 @@ void tsconf_state::ram_write16(offs_t offset, u16 data) u16 tsconf_state::spi_read16() { - return (tsconf_port_57_zctr_r(0) << 8) | tsconf_port_57_zctr_r(0); + const u16 data_hi = tsconf_port_57_zctr_r() << 8; + return data_hi | tsconf_port_57_zctr_r(); } void tsconf_state::cram_write(u16 offset, u8 data) @@ -475,11 +481,19 @@ void tsconf_state::tsconf_port_xxaf_w(offs_t port, u8 data) bool delay_update = true; switch (nreg) { - // more registers which marked as *1 in the xls, but rest need to be tested + case V_CONFIG: + case V_PAGE: case G_X_OFFS_L: case G_X_OFFS_H: case G_Y_OFFS_L: case G_Y_OFFS_H: + case PAL_SEL: + case T0_G_PAGE: + case T1_G_PAGE: + case T0_X_OFFSET_L: + case T0_X_OFFSET_H: + case T1_X_OFFSET_L: + case T1_X_OFFSET_H: m_scanline_delayed_regs_update[static_cast<tsconf_regs>(nreg)] = data; break; @@ -575,46 +589,23 @@ void tsconf_state::tsconf_port_xxaf_w(offs_t port, u8 data) switch (nreg) { - case V_CONFIG: - case V_PAGE: - tsconf_update_video_mode(); - break; - case T_MAP_PAGE: m_ts_tilemap[TM_TILES0]->mark_all_dirty(); m_ts_tilemap[TM_TILES1]->mark_all_dirty(); break; - case T0_G_PAGE: - m_gfxdecode->gfx(TM_TILES0)->set_source(m_ram->pointer() + PAGE4K(data)); - break; - - case T0_X_OFFSET_L: - case T0_X_OFFSET_H: - m_ts_tilemap[TM_TILES0]->set_scrollx(OFFS_512(T0_X_OFFSET_L)); - break; - case T0_Y_OFFSET_L: case T0_Y_OFFSET_H: m_ts_tilemap[TM_TILES0]->set_scrolly(OFFS_512(T0_Y_OFFSET_L)); break; - case T1_G_PAGE: - m_gfxdecode->gfx(TM_TILES1)->set_source(m_ram->pointer() + PAGE4K(data)); - break; - - case T1_X_OFFSET_L: - case T1_X_OFFSET_H: - m_ts_tilemap[TM_TILES1]->set_scrollx(OFFS_512(T1_X_OFFSET_L)); - break; - case T1_Y_OFFSET_L: case T1_Y_OFFSET_H: m_ts_tilemap[TM_TILES1]->set_scrolly(OFFS_512(T1_Y_OFFSET_L)); break; case SG_PAGE: - m_gfxdecode->gfx(TM_SPRITES)->set_source(m_ram->pointer() + PAGE4K(data)); + m_gfxdecode->gfx(TM_SPRITES)->set_source(m_ram->pointer() + PAGE4K(data & 0xf8)); break; case SYS_CONFIG: @@ -630,7 +621,6 @@ void tsconf_state::tsconf_port_xxaf_w(offs_t port, u8 data) break; case FMAPS: - case PAL_SEL: case TS_CONFIG: case INT_MASK: // TODO @@ -709,38 +699,38 @@ void tsconf_state::tsconf_port_f7_w(offs_t offset, u8 data) } } -void tsconf_state::tsconf_port_77_zctr_w(offs_t port, u8 data) +void tsconf_state::tsconf_port_77_zctr_w(u8 data) { m_sdcard->spi_ss_w(BIT(data, 0)); m_zctl_cs = BIT(data, 1); } -u8 tsconf_state::tsconf_port_77_zctr_r(offs_t port) +u8 tsconf_state::tsconf_port_77_zctr_r() { return 0x02 | (m_sdcard->get_card_present() ? 0x00 : 0x01); } -void tsconf_state::tsconf_port_57_zctr_w(offs_t port, u8 data) +void tsconf_state::tsconf_port_57_zctr_w(u8 data) { if (!m_zctl_cs) { for (u8 m = 0x80; m; m >>= 1) { - m_sdcard->spi_clock_w(CLEAR_LINE); // 0-S R m_sdcard->spi_mosi_w(data & m ? 1 : 0); + m_sdcard->spi_clock_w(CLEAR_LINE); // 0-S R m_sdcard->spi_clock_w(ASSERT_LINE); // 1-L W } } } -u8 tsconf_state::tsconf_port_57_zctr_r(offs_t port) +u8 tsconf_state::tsconf_port_57_zctr_r() { if (m_zctl_cs) return 0xff; u8 data = m_zctl_di; if (!machine().side_effects_disabled()) - tsconf_port_57_zctr_w(0, 0xff); + tsconf_port_57_zctr_w(0xff); return data; } @@ -844,12 +834,18 @@ TIMER_CALLBACK_MEMBER(tsconf_state::irq_scanline) u16 screen_vpos = m_screen->vpos(); m_scanline_irq_timer->adjust(m_screen->time_until_pos(screen_vpos + 1)); - m_screen->update_now(); + if (!m_scanline_delayed_regs_update.empty()) + m_screen->update_now(); for (const auto &[reg, val] : m_scanline_delayed_regs_update) { m_regs[reg] = val; switch (reg) { + case V_CONFIG: + case V_PAGE: + tsconf_update_video_mode(); + break; + case G_Y_OFFS_L: case G_Y_OFFS_H: m_gfx_y_frame_offset = screen_vpos < get_screen_area().top() @@ -857,6 +853,27 @@ TIMER_CALLBACK_MEMBER(tsconf_state::irq_scanline) : -screen_vpos; break; + case T0_G_PAGE: + m_gfxdecode->gfx(TM_TILES0)->set_source(m_ram->pointer() + PAGE4K(val & 0xf8)); + break; + + case T1_G_PAGE: + m_gfxdecode->gfx(TM_TILES1)->set_source(m_ram->pointer() + PAGE4K(val & 0xf8)); + break; + + case T0_X_OFFSET_L: + case T0_X_OFFSET_H: + m_ts_tilemap[TM_TILES0]->set_scrollx(OFFS_512(T0_X_OFFSET_L)); + break; + + case T1_X_OFFSET_L: + case T1_X_OFFSET_H: + m_ts_tilemap[TM_TILES1]->set_scrollx(OFFS_512(T1_X_OFFSET_L)); + break; + + case G_X_OFFS_L: + case G_X_OFFS_H: + case PAL_SEL: default: break; } diff --git a/src/mame/sinclair/tsconfdma.cpp b/src/mame/sinclair/tsconfdma.cpp index 431142ebdd6..eaf68f508a3 100644 --- a/src/mame/sinclair/tsconfdma.cpp +++ b/src/mame/sinclair/tsconfdma.cpp @@ -22,6 +22,8 @@ tsconfdma_device::tsconfdma_device(const machine_config &mconfig, const char *ta void tsconfdma_device::device_start() { + m_dma_clock = timer_alloc(FUNC(tsconfdma_device::dma_clock), this); + m_in_mreq_cb.resolve_safe(0); m_out_mreq_cb.resolve_safe(); m_in_mspi_cb.resolve_safe(0); @@ -37,10 +39,14 @@ void tsconfdma_device::device_start() save_item(NAME(m_align_s)); save_item(NAME(m_align_d)); save_item(NAME(m_align)); + save_item(NAME(m_asz)); + save_item(NAME(m_task)); } void tsconfdma_device::device_reset() { + m_dma_clock->adjust(attotime::never); + m_block_num = 0; m_ready = ASSERT_LINE; } @@ -52,32 +58,32 @@ int tsconfdma_device::is_ready() void tsconfdma_device::set_saddr_l(u8 addr_l) { - m_address_s = (m_address_s & 0xffffff00) | (addr_l & 0xfe); + m_address_s = (m_address_s & 0x3fff00) | (addr_l & 0xfe); } void tsconfdma_device::set_saddr_h(u8 addr_h) { - m_address_s = (m_address_s & 0xffffc0ff) | ((addr_h & 0x3f) << 8); + m_address_s = (m_address_s & 0x3fc0ff) | ((addr_h & 0x3f) << 8); } void tsconfdma_device::set_saddr_x(u8 addr_x) { - m_address_s = (m_address_s & 0x0003fff) | (addr_x << 14); + m_address_s = (m_address_s & 0x003fff) | (addr_x << 14); } void tsconfdma_device::set_daddr_l(u8 addr_l) { - m_address_d = (m_address_d & 0xffffff00) | (addr_l & 0xfe); + m_address_d = (m_address_d & 0x3fff00) | (addr_l & 0xfe); } void tsconfdma_device::set_daddr_h(u8 addr_h) { - m_address_d = (m_address_d & 0xffffc0ff) | ((addr_h & 0x3f) << 8); + m_address_d = (m_address_d & 0x3fc0ff) | ((addr_h & 0x3f) << 8); } void tsconfdma_device::set_daddr_x(u8 addr_x) { - m_address_d = (m_address_d & 0x0003fff) | (addr_x << 14); + m_address_d = (m_address_d & 0x003fff) | (addr_x << 14); } void tsconfdma_device::set_block_len(u8 len) @@ -99,11 +105,20 @@ void tsconfdma_device::set_block_num_h(u8 num_h) void tsconfdma_device::start_tx(u8 dev, bool s_align, bool d_align, bool align_opt) { + m_task = dev; + m_align_s = s_align; + m_align_d = d_align; + m_asz = align_opt; + m_align = m_asz ? 512 : 256; m_ready = CLEAR_LINE; - m_align = align_opt ? 512 : 256; // TODO Transfers 2 byte/cycle at 7MHz - switch (dev) + m_dma_clock->adjust(attotime::from_ticks(m_block_num + 1, 7_MHz_XTAL)); +} + +TIMER_CALLBACK_MEMBER(tsconfdma_device::dma_clock) +{ + switch (m_task) { case 0b0001: // Mem -> Mem for (u16 block = 0; block <= m_block_num; block++) @@ -113,11 +128,11 @@ void tsconfdma_device::start_tx(u8 dev, bool s_align, bool d_align, bool align_o for (u16 len = 0; len <= m_block_len; len++) { m_out_mreq_cb(d_addr, m_in_mreq_cb(s_addr)); - s_addr += 2; - d_addr += 2; + s_addr = (s_addr + 2) & 0x3fffff; + d_addr = (d_addr + 2) & 0x3fffff; } - m_address_s = s_align ? (m_address_s + m_align) : s_addr; - m_address_d = d_align ? (m_address_d + m_align) : d_addr; + m_address_s = m_align_s ? (m_address_s + m_align) : s_addr; + m_address_d = m_align_d ? (m_address_d + m_align) : d_addr; } break; @@ -127,10 +142,12 @@ void tsconfdma_device::start_tx(u8 dev, bool s_align, bool d_align, bool align_o auto d_addr = m_address_d; for (u16 len = 0; len <= m_block_len; len++) { + if (d_addr == 3801154) + printf("!"); m_out_mreq_cb(d_addr, m_in_mspi_cb()); - d_addr += 2; + d_addr = (d_addr + 2) & 0x3fffff; } - m_address_d = d_align ? (m_address_d + m_align) : d_addr; + m_address_d = m_align_d ? (m_address_d + m_align) : d_addr; } break; @@ -142,9 +159,9 @@ void tsconfdma_device::start_tx(u8 dev, bool s_align, bool d_align, bool align_o for (u16 len = 0; len <= m_block_len; len++) { m_out_mreq_cb(d_addr, data); - d_addr += 2; + d_addr = (d_addr + 2) & 0x3fffff; } - m_address_d = d_align ? (m_address_d + m_align) : d_addr; + m_address_d = m_align_d ? (m_address_d + m_align) : d_addr; } break; @@ -157,7 +174,7 @@ void tsconfdma_device::start_tx(u8 dev, bool s_align, bool d_align, bool align_o { u16 d_val = m_in_mreq_cb(d_addr); u16 s_val = m_in_mreq_cb(s_addr); - if (align_opt) + if (m_asz) { d_val = (d_val & 0xff00) | (((s_val & 0x00ff) ? s_val : d_val) & 0x00ff); d_val = (d_val & 0x00ff) | (((s_val & 0xff00) ? s_val : d_val) & 0xff00); @@ -170,11 +187,11 @@ void tsconfdma_device::start_tx(u8 dev, bool s_align, bool d_align, bool align_o d_val = (d_val & 0x0fff) | (((s_val & 0xf000) ? s_val : d_val) & 0xf000); } m_out_mreq_cb(d_addr, d_val); - s_addr += 2; - d_addr += 2; + s_addr = (s_addr + 2) & 0x3fffff; + d_addr = (d_addr + 2) & 0x3fffff; } - m_address_s = s_align ? (m_address_s + m_align) : s_addr; - m_address_d = d_align ? (m_address_d + m_align) : d_addr; + m_address_s = m_align_s ? (m_address_s + m_align) : s_addr; + m_address_d = m_align_d ? (m_address_d + m_align) : d_addr; } break; @@ -186,11 +203,11 @@ void tsconfdma_device::start_tx(u8 dev, bool s_align, bool d_align, bool align_o for (u16 len = 0; len <= m_block_len; len++) { m_out_cram_cb(d_addr, m_in_mreq_cb(s_addr)); - s_addr += 2; - d_addr += 2; + s_addr = (s_addr + 2) & 0x3fffff; + d_addr = (d_addr + 2) & 0x3fffff; } - m_address_s = s_align ? (m_address_s + m_align) : s_addr; - m_address_d = d_align ? (m_address_d + m_align) : d_addr; + m_address_s = m_align_s ? (m_address_s + m_align) : s_addr; + m_address_d = m_align_d ? (m_address_d + m_align) : d_addr; } break; @@ -202,19 +219,20 @@ void tsconfdma_device::start_tx(u8 dev, bool s_align, bool d_align, bool align_o for (u16 len = 0; len <= m_block_len; len++) { m_out_sfile_cb(d_addr, m_in_mreq_cb(s_addr)); - s_addr += 2; - d_addr += 2; + s_addr = (s_addr + 2) & 0x3fffff; + d_addr = (d_addr + 2) & 0x3fffff; } - m_address_s = s_align ? (m_address_s + m_align) : s_addr; - m_address_d = d_align ? (m_address_d + m_align) : d_addr; + m_address_s = m_align_s ? (m_address_s + m_align) : s_addr; + m_address_d = m_align_d ? (m_address_d + m_align) : d_addr; } break; default: - logerror("'tsdma': TX %02X: %06X (%02X:%04X) -> %06X\n", dev, m_address_s, m_block_len, m_block_num, m_address_d); + logerror("'tsdma': TX %02X: %06X (%02X:%04X) -> %06X\n", m_task, m_address_s, m_block_len, m_block_num, m_address_d); break; } + m_dma_clock->adjust(attotime::never); m_ready = ASSERT_LINE; m_on_ready_cb(0); } diff --git a/src/mame/sinclair/tsconfdma.h b/src/mame/sinclair/tsconfdma.h index 582017fdfff..d76471f95ab 100644 --- a/src/mame/sinclair/tsconfdma.h +++ b/src/mame/sinclair/tsconfdma.h @@ -36,7 +36,7 @@ public: void set_block_num_h(uint8_t num_h); void start_tx(uint8_t dev, bool s_align, bool d_align, bool blitting_opt); -private: +protected: virtual void device_start() override; virtual void device_reset() override; @@ -47,14 +47,21 @@ private: devcb_write16 m_out_sfile_cb; devcb_write_line m_on_ready_cb; +private: + TIMER_CALLBACK_MEMBER(dma_clock); + u8 m_ready; offs_t m_address_s; offs_t m_address_d; u8 m_block_len; u16 m_block_num; + + emu_timer *m_dma_clock; + u8 m_task; bool m_align_s; bool m_align_d; + bool m_asz; u16 m_align; }; |
