sinclair/tsconf.cpp: finalize regs delayed updates; fix graphic pages padding (#11248)

- finalize regs delayed updates; fix graphic pages padding
- fix spectrum page switch
This commit is contained in:
holub 2023-05-24 20:25:54 -04:00 committed by GitHub
parent 1109aa3c3d
commit 5c8a49c92c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 119 additions and 87 deletions

View File

@ -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 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) 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: TODO:
- Ram cache - Ram cache
- VDos - VDos
@ -56,7 +45,7 @@ TODO:
TILE_GET_INFO_MEMBER(tsconf_state::get_tile_info_txt) 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 col = tile_index % tilemap.cols();
u8 symbol = m_row_location[col]; u8 symbol = m_row_location[col];
tileinfo.set(TM_TS_CHAR, symbol, 0, 0); tileinfo.set(TM_TS_CHAR, symbol, 0, 0);

View File

@ -150,6 +150,7 @@ private:
TILE_GET_INFO_MEMBER(get_tile_info_16c); TILE_GET_INFO_MEMBER(get_tile_info_16c);
u8 get_border_color(u16 hpos = ~0, u16 vpos = ~0) override; u8 get_border_color(u16 hpos = ~0, u16 vpos = ~0) override;
u32 get_vpage_offset();
rectangle get_screen_area() override; rectangle get_screen_area() override;
void spectrum_update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) 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); 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); void tsconf_ula_w(offs_t offset, u8 data);
u8 tsconf_port_xxaf_r(offs_t reg); u8 tsconf_port_xxaf_r(offs_t reg);
void tsconf_port_xxaf_w(offs_t reg, u8 data); void tsconf_port_xxaf_w(offs_t reg, u8 data);
u8 tsconf_port_77_zctr_r(offs_t reg); u8 tsconf_port_77_zctr_r();
void tsconf_port_77_zctr_w(offs_t reg, u8 data); void tsconf_port_77_zctr_w(u8 data);
u8 tsconf_port_57_zctr_r(offs_t reg); u8 tsconf_port_57_zctr_r();
void tsconf_port_57_zctr_w(offs_t reg, u8 data); void tsconf_port_57_zctr_w(u8 data);
void tsconf_spi_miso_w(u8 data); void tsconf_spi_miso_w(u8 data);
u8 tsconf_port_f7_r(offs_t offset); u8 tsconf_port_f7_r(offs_t offset);
void tsconf_port_f7_w(offs_t offset, u8 data); void tsconf_port_f7_w(offs_t offset, u8 data);

View File

@ -107,6 +107,11 @@ u8 tsconf_state::get_border_color(u16 hpos, u16 vpos)
return m_regs[BORDER]; return m_regs[BORDER];
} }
u32 tsconf_state::get_vpage_offset()
{
return PAGE4K(m_regs[V_PAGE] & ((VM == VM_16C) ? 0xf8 : 0xf0));
}
/* /*
Layered as: Layered as:
+ Border - already updated with screen_update_spectrum() + 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 pal_offset = m_regs[PAL_SEL] << 4;
u8 *screen_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE]); 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; bool invert_attrs = u64(screen.frame_number() / m_frame_invert_count) & 1;
for (u16 vpos = cliprect.top(); vpos <= cliprect.bottom(); vpos++) 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 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; 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())); u16 *bm = &(bitmap.pix(vpos, cliprect.left()));
s16 width = cliprect.width(); s16 width = cliprect.width();
if (VM == VM_16C) if (VM == VM_16C)
@ -347,20 +352,20 @@ void tsconf_state::ram_page_write(u8 page, offs_t offset, u8 data)
} }
else 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(); 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(); 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(); 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)) 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(); 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_gfxdecode->gfx(TM_SPRITES)->mark_all_dirty();
m_ram->write(ram_addr, data); 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() 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) 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; bool delay_update = true;
switch (nreg) 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_L:
case G_X_OFFS_H: case G_X_OFFS_H:
case G_Y_OFFS_L: case G_Y_OFFS_L:
case G_Y_OFFS_H: 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; m_scanline_delayed_regs_update[static_cast<tsconf_regs>(nreg)] = data;
break; break;
@ -575,46 +589,23 @@ void tsconf_state::tsconf_port_xxaf_w(offs_t port, u8 data)
switch (nreg) switch (nreg)
{ {
case V_CONFIG:
case V_PAGE:
tsconf_update_video_mode();
break;
case T_MAP_PAGE: case T_MAP_PAGE:
m_ts_tilemap[TM_TILES0]->mark_all_dirty(); m_ts_tilemap[TM_TILES0]->mark_all_dirty();
m_ts_tilemap[TM_TILES1]->mark_all_dirty(); m_ts_tilemap[TM_TILES1]->mark_all_dirty();
break; 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_L:
case T0_Y_OFFSET_H: case T0_Y_OFFSET_H:
m_ts_tilemap[TM_TILES0]->set_scrolly(OFFS_512(T0_Y_OFFSET_L)); m_ts_tilemap[TM_TILES0]->set_scrolly(OFFS_512(T0_Y_OFFSET_L));
break; 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_L:
case T1_Y_OFFSET_H: case T1_Y_OFFSET_H:
m_ts_tilemap[TM_TILES1]->set_scrolly(OFFS_512(T1_Y_OFFSET_L)); m_ts_tilemap[TM_TILES1]->set_scrolly(OFFS_512(T1_Y_OFFSET_L));
break; break;
case SG_PAGE: 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; break;
case SYS_CONFIG: case SYS_CONFIG:
@ -630,7 +621,6 @@ void tsconf_state::tsconf_port_xxaf_w(offs_t port, u8 data)
break; break;
case FMAPS: case FMAPS:
case PAL_SEL:
case TS_CONFIG: case TS_CONFIG:
case INT_MASK: case INT_MASK:
// TODO // 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_sdcard->spi_ss_w(BIT(data, 0));
m_zctl_cs = BIT(data, 1); 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); 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) if (!m_zctl_cs)
{ {
for (u8 m = 0x80; m; m >>= 1) 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_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 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) if (m_zctl_cs)
return 0xff; return 0xff;
u8 data = m_zctl_di; u8 data = m_zctl_di;
if (!machine().side_effects_disabled()) if (!machine().side_effects_disabled())
tsconf_port_57_zctr_w(0, 0xff); tsconf_port_57_zctr_w(0xff);
return data; return data;
} }
@ -844,12 +834,18 @@ TIMER_CALLBACK_MEMBER(tsconf_state::irq_scanline)
u16 screen_vpos = m_screen->vpos(); u16 screen_vpos = m_screen->vpos();
m_scanline_irq_timer->adjust(m_screen->time_until_pos(screen_vpos + 1)); m_scanline_irq_timer->adjust(m_screen->time_until_pos(screen_vpos + 1));
if (!m_scanline_delayed_regs_update.empty())
m_screen->update_now(); m_screen->update_now();
for (const auto &[reg, val] : m_scanline_delayed_regs_update) for (const auto &[reg, val] : m_scanline_delayed_regs_update)
{ {
m_regs[reg] = val; m_regs[reg] = val;
switch (reg) switch (reg)
{ {
case V_CONFIG:
case V_PAGE:
tsconf_update_video_mode();
break;
case G_Y_OFFS_L: case G_Y_OFFS_L:
case G_Y_OFFS_H: case G_Y_OFFS_H:
m_gfx_y_frame_offset = screen_vpos < get_screen_area().top() m_gfx_y_frame_offset = screen_vpos < get_screen_area().top()
@ -857,6 +853,27 @@ TIMER_CALLBACK_MEMBER(tsconf_state::irq_scanline)
: -screen_vpos; : -screen_vpos;
break; 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: default:
break; break;
} }

View File

@ -22,6 +22,8 @@ tsconfdma_device::tsconfdma_device(const machine_config &mconfig, const char *ta
void tsconfdma_device::device_start() void tsconfdma_device::device_start()
{ {
m_dma_clock = timer_alloc(FUNC(tsconfdma_device::dma_clock), this);
m_in_mreq_cb.resolve_safe(0); m_in_mreq_cb.resolve_safe(0);
m_out_mreq_cb.resolve_safe(); m_out_mreq_cb.resolve_safe();
m_in_mspi_cb.resolve_safe(0); 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_s));
save_item(NAME(m_align_d)); save_item(NAME(m_align_d));
save_item(NAME(m_align)); save_item(NAME(m_align));
save_item(NAME(m_asz));
save_item(NAME(m_task));
} }
void tsconfdma_device::device_reset() void tsconfdma_device::device_reset()
{ {
m_dma_clock->adjust(attotime::never);
m_block_num = 0; m_block_num = 0;
m_ready = ASSERT_LINE; m_ready = ASSERT_LINE;
} }
@ -52,32 +58,32 @@ int tsconfdma_device::is_ready()
void tsconfdma_device::set_saddr_l(u8 addr_l) 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) 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) 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) 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) 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) 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) 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) 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_ready = CLEAR_LINE;
m_align = align_opt ? 512 : 256;
// TODO Transfers 2 byte/cycle at 7MHz // 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 case 0b0001: // Mem -> Mem
for (u16 block = 0; block <= m_block_num; block++) 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++) for (u16 len = 0; len <= m_block_len; len++)
{ {
m_out_mreq_cb(d_addr, m_in_mreq_cb(s_addr)); m_out_mreq_cb(d_addr, m_in_mreq_cb(s_addr));
s_addr += 2; s_addr = (s_addr + 2) & 0x3fffff;
d_addr += 2; d_addr = (d_addr + 2) & 0x3fffff;
} }
m_address_s = s_align ? (m_address_s + m_align) : s_addr; m_address_s = m_align_s ? (m_address_s + m_align) : s_addr;
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; 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; auto d_addr = m_address_d;
for (u16 len = 0; len <= m_block_len; len++) for (u16 len = 0; len <= m_block_len; len++)
{ {
if (d_addr == 3801154)
printf("!");
m_out_mreq_cb(d_addr, m_in_mspi_cb()); 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; 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++) for (u16 len = 0; len <= m_block_len; len++)
{ {
m_out_mreq_cb(d_addr, data); 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; 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 d_val = m_in_mreq_cb(d_addr);
u16 s_val = m_in_mreq_cb(s_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 & 0xff00) | (((s_val & 0x00ff) ? s_val : d_val) & 0x00ff);
d_val = (d_val & 0x00ff) | (((s_val & 0xff00) ? s_val : d_val) & 0xff00); 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); d_val = (d_val & 0x0fff) | (((s_val & 0xf000) ? s_val : d_val) & 0xf000);
} }
m_out_mreq_cb(d_addr, d_val); m_out_mreq_cb(d_addr, d_val);
s_addr += 2; s_addr = (s_addr + 2) & 0x3fffff;
d_addr += 2; d_addr = (d_addr + 2) & 0x3fffff;
} }
m_address_s = s_align ? (m_address_s + m_align) : s_addr; m_address_s = m_align_s ? (m_address_s + m_align) : s_addr;
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; 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++) for (u16 len = 0; len <= m_block_len; len++)
{ {
m_out_cram_cb(d_addr, m_in_mreq_cb(s_addr)); m_out_cram_cb(d_addr, m_in_mreq_cb(s_addr));
s_addr += 2; s_addr = (s_addr + 2) & 0x3fffff;
d_addr += 2; d_addr = (d_addr + 2) & 0x3fffff;
} }
m_address_s = s_align ? (m_address_s + m_align) : s_addr; m_address_s = m_align_s ? (m_address_s + m_align) : s_addr;
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; 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++) for (u16 len = 0; len <= m_block_len; len++)
{ {
m_out_sfile_cb(d_addr, m_in_mreq_cb(s_addr)); m_out_sfile_cb(d_addr, m_in_mreq_cb(s_addr));
s_addr += 2; s_addr = (s_addr + 2) & 0x3fffff;
d_addr += 2; d_addr = (d_addr + 2) & 0x3fffff;
} }
m_address_s = s_align ? (m_address_s + m_align) : s_addr; m_address_s = m_align_s ? (m_address_s + m_align) : s_addr;
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; break;
default: 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; break;
} }
m_dma_clock->adjust(attotime::never);
m_ready = ASSERT_LINE; m_ready = ASSERT_LINE;
m_on_ready_cb(0); m_on_ready_cb(0);
} }

View File

@ -36,7 +36,7 @@ public:
void set_block_num_h(uint8_t num_h); void set_block_num_h(uint8_t num_h);
void start_tx(uint8_t dev, bool s_align, bool d_align, bool blitting_opt); 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_start() override;
virtual void device_reset() override; virtual void device_reset() override;
@ -47,14 +47,21 @@ private:
devcb_write16 m_out_sfile_cb; devcb_write16 m_out_sfile_cb;
devcb_write_line m_on_ready_cb; devcb_write_line m_on_ready_cb;
private:
TIMER_CALLBACK_MEMBER(dma_clock);
u8 m_ready; u8 m_ready;
offs_t m_address_s; offs_t m_address_s;
offs_t m_address_d; offs_t m_address_d;
u8 m_block_len; u8 m_block_len;
u16 m_block_num; u16 m_block_num;
emu_timer *m_dma_clock;
u8 m_task;
bool m_align_s; bool m_align_s;
bool m_align_d; bool m_align_d;
bool m_asz;
u16 m_align; u16 m_align;
}; };