diff --git a/src/mame/sinclair/tsconf.cpp b/src/mame/sinclair/tsconf.cpp index aa62352b510..d06debc7539 100644 --- a/src/mame/sinclair/tsconf.cpp +++ b/src/mame/sinclair/tsconf.cpp @@ -30,8 +30,6 @@ FAQ-RUS: https://forum.tslabs.info/viewtopic.php?f=35&t=157 TODO: - Ram cache - VDos -- INTs not perfect. Currently all signals are invalidated after 32t(3.5MHz). Must only do so for frame, not scanline/DMA -- Palette change in the middle of the frame e.g. zapili-c0 ****************************************************************************/ @@ -96,9 +94,9 @@ void tsconf_state::tsconf_io(address_map &map) map(0xffdf, 0xffdf).lr8(NAME([this]() -> u8 { return ~m_io_mouse[1]->read(); })); map(0x8ff7, 0x8ff7).select(0x7000).w(FUNC(tsconf_state::tsconf_port_f7_w)); // 3:bff7 5:dff7 6:eff7 map(0xbff7, 0xbff7).r(FUNC(tsconf_state::tsconf_port_f7_r)); - map(0x00fb, 0x00fb).mirror(0xff00).w("cent_data_out", FUNC(output_latch_device::write)); - map(0x8000, 0x8000).mirror(0x3ffd).lw8(NAME([this](u8 data) { return m_ay[m_ay_selected]->data_w(data); })); - map(0xc000, 0xc000).mirror(0x3ffd).lr8(NAME([this]() { return m_ay[m_ay_selected]->data_r(); })) + map(0x00fb, 0x00fb).mirror(0xff00).w(m_dac, FUNC(dac_byte_interface::data_w)); + map(0x80fd, 0x80fd).mirror(0x3f00).lw8(NAME([this](u8 data) { return m_ay[m_ay_selected]->data_w(data); })); + map(0xc0fd, 0xc0fd).mirror(0x3f00).lr8(NAME([this]() { return m_ay[m_ay_selected]->data_r(); })) .w(FUNC(tsconf_state::tsconf_ay_address_w)); } @@ -117,9 +115,9 @@ void tsconf_state::tsconf_bank_w(offs_t offset, u8 data) static const gfx_layout spectrum_charlayout = { - 8, 8, // 8 x 8 characters */ - 96, // 96 characters */ - 1, // 1 bits per pixel */ + 8, 8, // 8 x 8 characters + 96, // 96 characters + 1, // 1 bits per pixel {0}, // no bitplanes {STEP8(0, 1)}, // x offsets {STEP8(0, 8)}, // y offsets @@ -145,8 +143,7 @@ static const gfx_layout tsconf_tile_16cpp_layout = 4, {STEP4(0, 1)}, {STEP8(0, 4)}, - {STEP8(0, 256 * 8)}, - // Much more tiles when needed. Because tiles are in RAW format but we don't know region properties. + {STEP8(0, 256 * 8)}, // Much more tiles when needed. Because tiles are in RAW format but we don't know region properties. 8 * 4 }; @@ -287,7 +284,7 @@ void tsconf_state::tsconf(machine_config &config) GLUKRS(config, m_glukrs); - TSCONF_DMA(config, m_dma, 14_MHz_XTAL / 2); + TSCONF_DMA(config, m_dma, 14_MHz_XTAL * 2); m_dma->in_mreq_callback().set(FUNC(tsconf_state::ram_read16)); m_dma->out_mreq_callback().set(FUNC(tsconf_state::ram_write16)); m_dma->in_spireq_callback().set(FUNC(tsconf_state::spi_read16)); @@ -314,9 +311,7 @@ void tsconf_state::tsconf(machine_config &config) .add_route(1, "rspeaker", 0.25) .add_route(2, "rspeaker", 0.50); - CENTRONICS(config, m_centronics, centronics_devices, "covox"); - output_latch_device ¢_data_out(OUTPUT_LATCH(config, "cent_data_out")); - m_centronics->set_output_latch(cent_data_out); + DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "mono", 0.75);; PALETTE(config, "palette", FUNC(tsconf_state::tsconf_palette), 256); m_screen->set_raw(14_MHz_XTAL / 2, 448, with_hblank(0), 448, 320, with_vblank(0), 320); diff --git a/src/mame/sinclair/tsconf.h b/src/mame/sinclair/tsconf.h index 596d76b3d7c..70495c250db 100644 --- a/src/mame/sinclair/tsconf.h +++ b/src/mame/sinclair/tsconf.h @@ -16,10 +16,10 @@ #include "tsconfdma.h" #include "beta_m.h" -#include "bus/centronics/ctronics.h" #include "machine/pckeybrd.h" #include "machine/spi_sdcard.h" #include "sound/ay8910.h" +#include "sound/dac.h" #include "tilemap.h" @@ -39,7 +39,7 @@ public: , m_gfxdecode(*this, "gfxdecode") , m_cram(*this, "cram") , m_sfile(*this, "sfile") - , m_centronics(*this, "centronics") + , m_dac(*this, "dac") , m_ay(*this, "ay%u", 0U) , m_mod_ay(*this, "MOD_AY") { @@ -233,9 +233,9 @@ private: tilemap_t *m_ts_tilemap[3]{}; required_device m_cram; required_device m_sfile; - required_device m_centronics; std::vector m_sprites_cache; + required_device m_dac; required_device_array m_ay; u8 m_ay_selected; required_ioport m_mod_ay; diff --git a/src/mame/sinclair/tsconf_m.cpp b/src/mame/sinclair/tsconf_m.cpp index 102fab8223b..92f9678fd17 100644 --- a/src/mame/sinclair/tsconf_m.cpp +++ b/src/mame/sinclair/tsconf_m.cpp @@ -163,7 +163,6 @@ void tsconf_state::tsconf_update_screen(screen_device &screen, bitmap_rgb32 &bit } else { - bitmap.fill(m_palette->pen_color(get_border_color()), cliprect); tsconf_draw_gfx(bitmap, cliprect); } } @@ -253,7 +252,6 @@ void tsconf_state::tsconf_draw_txt(bitmap_rgb32 &bitmap, const rectangle &clipre void tsconf_state::tsconf_draw_gfx(bitmap_rgb32 &bitmap, const rectangle &cliprect) { u8 pal_offset = m_regs[PAL_SEL] << 4; - const rgb_t transparent = m_palette->pen_color(0); for (u16 vpos = cliprect.top(); vpos <= cliprect.bottom(); vpos++) { u16 y_offset = (OFFS_512(G_Y_OFFS_L) + m_gfx_y_frame_offset + vpos) & 0x1ff; @@ -275,19 +273,11 @@ void tsconf_state::tsconf_draw_gfx(bitmap_rgb32 &bitmap, const rectangle &clipre video_location -= 256; u8 pix = *video_location++; rgb_t pen = m_palette->pen_color(pal_offset | (pix >> 4)); - if (pen != transparent) - { - *bm = pen; - } - bm++; + *bm++ = pen; if (width != 1) { pen = m_palette->pen_color(pal_offset | (pix & 0x0f)); - if (pen != transparent) - { - *bm = pen; - } - bm++; + *bm++ = pen; } } } @@ -298,11 +288,7 @@ void tsconf_state::tsconf_draw_gfx(bitmap_rgb32 &bitmap, const rectangle &clipre if (x_offset == 512) video_location -= 512; rgb_t pen = m_palette->pen_color(*video_location++); - if (pen != transparent) - { - *bm = pen; - } - bm++; + *bm++ = pen; } } } @@ -441,18 +427,18 @@ void tsconf_state::ram_page_write(u8 page, offs_t offset, u8 data) 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); + m_ram->pointer()[ram_addr] = data; } u16 tsconf_state::ram_read16(offs_t offset) { - return (m_ram->read(offset & ~offs_t(1)) << 8) | m_ram->read(offset | 1); + return (m_ram->pointer()[offset & ~offs_t(1)] << 8) | m_ram->pointer()[offset | 1]; } void tsconf_state::ram_write16(offs_t offset, u16 data) { ram_page_write(0, offset & ~offs_t(1), data >> 8); - ram_page_write(0, offset | 1, data & 0xff); + m_ram->pointer()[offset | 1] = data & 0xff; } u16 tsconf_state::spi_read16() @@ -514,7 +500,7 @@ void tsconf_state::tsconf_port_7ffd_w(u8 data) void tsconf_state::tsconf_ula_w(offs_t offset, u8 data) { spectrum_ula_w(offset, data); - tsconf_port_xxaf_w(BORDER << 8, (data & 0x07) | (m_regs[PAL_SEL] << 4)); + tsconf_port_xxaf_w(BORDER << 8, 0xf0 | (data & 0x07)); } u8 tsconf_state::tsconf_port_xxaf_r(offs_t port) @@ -828,7 +814,9 @@ IRQ_CALLBACK_MEMBER(tsconf_state::irq_vector) { u8 vector = 0xff; if (m_int_mask & 1) + { m_int_mask &= ~1; + } else if (m_int_mask & 2) { m_int_mask &= ~2; @@ -841,7 +829,7 @@ IRQ_CALLBACK_MEMBER(tsconf_state::irq_vector) } if (!m_int_mask) - m_maincpu->set_input_line(0, CLEAR_LINE); + m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); return vector; } @@ -849,8 +837,6 @@ IRQ_CALLBACK_MEMBER(tsconf_state::irq_vector) TIMER_CALLBACK_MEMBER(tsconf_state::irq_off) { m_int_mask &= ~1; - if (!m_int_mask) - m_maincpu->set_input_line(0, CLEAR_LINE); } void tsconf_state::update_frame_timer() @@ -862,10 +848,14 @@ void tsconf_state::update_frame_timer() { next = m_screen->time_until_pos(vpos, hpos << 1); if (next >= m_screen->frame_period()) + { next = attotime::zero; + } } else + { next = attotime::never; + } m_frame_irq_timer->adjust(next); } @@ -881,8 +871,7 @@ void tsconf_state::dma_ready(int line) { if (BIT(m_regs[INT_MASK], 2)) { - if (!m_int_mask) - m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); + m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); m_int_mask |= 4; } } @@ -891,8 +880,7 @@ TIMER_CALLBACK_MEMBER(tsconf_state::irq_frame) { if (BIT(m_regs[INT_MASK], 0)) { - if (!m_int_mask) - m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); + m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); m_irq_off_timer->adjust(attotime::from_ticks(32, m_maincpu->unscaled_clock())); m_int_mask |= 1; } @@ -902,8 +890,7 @@ TIMER_CALLBACK_MEMBER(tsconf_state::irq_scanline) { if (BIT(m_regs[INT_MASK], 1)) { - if (!m_int_mask) - m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); + m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); m_int_mask |= 2; } diff --git a/src/mame/sinclair/tsconfdma.cpp b/src/mame/sinclair/tsconfdma.cpp index 854e8a64b5f..69f0dbbb4fd 100644 --- a/src/mame/sinclair/tsconfdma.cpp +++ b/src/mame/sinclair/tsconfdma.cpp @@ -4,11 +4,17 @@ TS-Conf (ZX-Evolution) DMA Controller +TODO: +* Each memory cycle aligned to 7MHz clock and taking 1 tick + **********************************************************************/ #include "emu.h" #include "tsconfdma.h" +#define VERBOSE ( LOG_GENERAL ) +#include "logmacro.h" + tsconfdma_device::tsconfdma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, TSCONF_DMA, tag, owner, clock), m_in_mreq_cb(*this, 0), @@ -36,11 +42,16 @@ void tsconfdma_device::device_start() save_item(NAME(m_m2)); save_item(NAME(m_asz)); save_item(NAME(m_task)); + save_item(NAME(m_tx_s_addr)); + save_item(NAME(m_tx_d_addr)); + save_item(NAME(m_tx_data)); + save_item(NAME(m_tx_block_num)); + save_item(NAME(m_tx_block)); } void tsconfdma_device::device_reset() { - m_dma_clock->adjust(attotime::never); + m_dma_clock->reset(); m_block_num = 0; m_ready = ASSERT_LINE; @@ -98,9 +109,12 @@ void tsconfdma_device::set_block_num_h(u8 num_h) m_block_num = (m_block_num & 0x00ff) | ((num_h & 0x03) << 8); } -void tsconfdma_device::start_tx(u8 dev, bool s_align, bool d_align, bool align_opt) +void tsconfdma_device::start_tx(u8 task, bool s_align, bool d_align, bool align_opt) { - m_task = dev; + if (!m_ready) + LOG("Starting new tx without previous completed\n"); + + m_task = task; m_align_s = s_align; m_align_d = d_align; m_asz = align_opt; @@ -109,127 +123,90 @@ void tsconfdma_device::start_tx(u8 dev, bool s_align, bool d_align, bool align_o m_m2 = m_asz ? 0x0001ff : 0x0000ff; m_ready = CLEAR_LINE; - // TODO Transfers 2 byte/cycle at 7MHz - m_dma_clock->adjust(attotime::from_ticks(m_block_num + 1, 7_MHz_XTAL)); + m_tx_block_num = 0; + m_tx_block = 0; + m_dma_clock->adjust(attotime::from_ticks(1, clock() / 6), 0, attotime::from_ticks(1, clock() / 6)); } TIMER_CALLBACK_MEMBER(tsconfdma_device::dma_clock) { + if (m_tx_block == 0) + { + m_tx_s_addr = m_address_s; + m_tx_d_addr = m_address_d; + } + switch (m_task) { case 0b0001: // Mem -> Mem - for (u16 block = 0; block <= m_block_num; block++) - { - auto s_addr = m_address_s; - auto d_addr = m_address_d; - for (u16 len = 0; len <= m_block_len; len++) - { - m_out_mreq_cb(d_addr, m_in_mreq_cb(s_addr)); - s_addr = m_align_s ? ((s_addr & m_m1) | ((s_addr + 2) & m_m2)) : ((s_addr + 2) & 0x3fffff); - d_addr = m_align_d ? ((d_addr & m_m1) | ((d_addr + 2) & m_m2)) : ((d_addr + 2) & 0x3fffff); - } - 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; - } + m_out_mreq_cb(m_tx_d_addr, m_in_mreq_cb(m_tx_s_addr)); break; case 0b0010: // SPI -> Mem - for (u16 block = 0; block <= m_block_num; block++) - { - auto d_addr = m_address_d; - for (u16 len = 0; len <= m_block_len; len++) - { - m_out_mreq_cb(d_addr, m_in_mspi_cb()); - d_addr = m_align_d ? ((d_addr & m_m1) | ((d_addr + 2) & m_m2)) : ((d_addr + 2) & 0x3fffff); - } - m_address_d = m_align_d ? (m_address_d + m_align) : d_addr; - } + m_out_mreq_cb(m_tx_d_addr, m_in_mspi_cb()); break; case 0b0100: // Fill - for (u16 block = 0; block <= m_block_num; block++) + if (!m_tx_block_num && !m_tx_block) { - u16 data = m_in_mreq_cb(m_address_s); - auto d_addr = m_address_d; - for (u16 len = 0; len <= m_block_len; len++) - { - m_out_mreq_cb(d_addr, data); - d_addr = m_align_d ? ((d_addr & m_m1) | ((d_addr + 2) & m_m2)) : ((d_addr + 2) & 0x3fffff); - } - m_address_d = m_align_d ? (m_address_d + m_align) : d_addr; + m_tx_data = m_in_mreq_cb(m_address_s); } + m_out_mreq_cb(m_tx_d_addr, m_tx_data); break; case 0b1001: // Blt -> Mem - for (u16 block = 0; block <= m_block_num; block++) { - auto s_addr = m_address_s; - auto d_addr = m_address_d; - for (u16 len = 0; len <= m_block_len; len++) + u16 d_val = m_in_mreq_cb(m_tx_d_addr); + u16 s_val = m_in_mreq_cb(m_tx_s_addr); + if (m_asz) { - u16 d_val = m_in_mreq_cb(d_addr); - u16 s_val = m_in_mreq_cb(s_addr); - 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); - } - else - { - d_val = (d_val & 0xfff0) | (((s_val & 0x000f) ? s_val : d_val) & 0x000f); - d_val = (d_val & 0xff0f) | (((s_val & 0x00f0) ? s_val : d_val) & 0x00f0); - d_val = (d_val & 0xf0ff) | (((s_val & 0x0f00) ? s_val : d_val) & 0x0f00); - d_val = (d_val & 0x0fff) | (((s_val & 0xf000) ? s_val : d_val) & 0xf000); - } - m_out_mreq_cb(d_addr, d_val); - s_addr = m_align_s ? ((s_addr & m_m1) | ((s_addr + 2) & m_m2)) : ((s_addr + 2) & 0x3fffff); - d_addr = m_align_d ? ((d_addr & m_m1) | ((d_addr + 2) & m_m2)) : ((d_addr + 2) & 0x3fffff); + 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); } - 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; + else + { + d_val = (d_val & 0xfff0) | (((s_val & 0x000f) ? s_val : d_val) & 0x000f); + d_val = (d_val & 0xff0f) | (((s_val & 0x00f0) ? s_val : d_val) & 0x00f0); + d_val = (d_val & 0xf0ff) | (((s_val & 0x0f00) ? s_val : d_val) & 0x0f00); + d_val = (d_val & 0x0fff) | (((s_val & 0xf000) ? s_val : d_val) & 0xf000); + } + m_out_mreq_cb(m_tx_d_addr, d_val); } break; case 0b1100: // RAM -> CRAM - for (u16 block = 0; block <= m_block_num; block++) - { - auto s_addr = m_address_s; - auto d_addr = m_address_d; - for (u16 len = 0; len <= m_block_len; len++) - { - m_out_cram_cb(d_addr, m_in_mreq_cb(s_addr)); - s_addr = m_align_s ? ((s_addr & m_m1) | ((s_addr + 2) & m_m2)) : ((s_addr + 2) & 0x3fffff); - d_addr = m_align_d ? ((d_addr & m_m1) | ((d_addr + 2) & m_m2)) : ((d_addr + 2) & 0x3fffff); - } - 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; - } + m_out_cram_cb(m_tx_d_addr, m_in_mreq_cb(m_tx_s_addr)); break; case 0b1101: // RAM -> SFILE - for (u16 block = 0; block <= m_block_num; block++) - { - auto s_addr = m_address_s; - auto d_addr = m_address_d; - for (u16 len = 0; len <= m_block_len; len++) - { - m_out_sfile_cb(d_addr, m_in_mreq_cb(s_addr)); - s_addr = m_align_s ? ((s_addr & m_m1) | ((s_addr + 2) & m_m2)) : ((s_addr + 2) & 0x3fffff); - d_addr = m_align_d ? ((d_addr & m_m1) | ((d_addr + 2) & m_m2)) : ((d_addr + 2) & 0x3fffff); - } - 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; - } + m_out_sfile_cb(m_tx_d_addr, m_in_mreq_cb(m_tx_s_addr)); break; default: - logerror("'tsdma': TX %02X: %06X (%02X:%04X) -> %06X\n", m_task, m_address_s, m_block_len, m_block_num, m_address_d); + LOG("Unknown task %02X: %06X (%02X:%04X) -> %06X\n", m_task, m_address_s, m_block_len, m_block_num, m_address_d); + m_tx_block_num = m_block_num; + m_tx_block = m_block_len; break; } - m_dma_clock->adjust(attotime::never); - m_ready = ASSERT_LINE; - m_on_ready_cb(0); + m_tx_s_addr = m_align_s ? ((m_tx_s_addr & m_m1) | ((m_tx_s_addr + 2) & m_m2)) : ((m_tx_s_addr + 2) & 0x3fffff); + m_tx_d_addr = m_align_d ? ((m_tx_d_addr & m_m1) | ((m_tx_d_addr + 2) & m_m2)) : ((m_tx_d_addr + 2) & 0x3fffff); + + ++m_tx_block; + if (m_tx_block > m_block_len) + { + m_address_s = m_align_s ? (m_address_s + m_align) : m_tx_s_addr; + m_address_d = m_align_d ? (m_address_d + m_align) : m_tx_d_addr; + + m_tx_block = 0; + ++m_tx_block_num; + if (m_tx_block_num > m_block_num) + { + m_dma_clock->reset(); + m_ready = ASSERT_LINE; + m_on_ready_cb(1); + } + } } // device type definition diff --git a/src/mame/sinclair/tsconfdma.h b/src/mame/sinclair/tsconfdma.h index 843ee84bcde..387dc2e3c7c 100644 --- a/src/mame/sinclair/tsconfdma.h +++ b/src/mame/sinclair/tsconfdma.h @@ -34,11 +34,11 @@ public: void set_block_len(uint8_t len); void set_block_num_l(uint8_t num_l); 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 task, bool s_align, bool d_align, bool blitting_opt); protected: - virtual void device_start() override; - virtual void device_reset() override; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; devcb_read16 m_in_mreq_cb; devcb_write16 m_out_mreq_cb; @@ -57,6 +57,12 @@ private: u8 m_block_len; u16 m_block_num; + offs_t m_tx_s_addr; + offs_t m_tx_d_addr; + u16 m_tx_data; + u16 m_tx_block_num; + u16 m_tx_block; + emu_timer *m_dma_clock; u8 m_task; bool m_align_s;