From 63aae42c2c95eda7f94822f6fd93db41d2f5c22c Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Tue, 20 Apr 2021 12:36:52 -0400 Subject: [PATCH 1/2] upd7220: Fixed mixed mode display area partition parsing --- src/devices/video/upd7220.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/devices/video/upd7220.cpp b/src/devices/video/upd7220.cpp index 19bd0c083a1..b09cee24651 100644 --- a/src/devices/video/upd7220.cpp +++ b/src/devices/video/upd7220.cpp @@ -21,7 +21,6 @@ - read data - modify data - write data - - QX-10 diagnostic test has positioning bugs with the bitmap display test; - QX-10 diagnostic test misses the zooming factor (external pin); - compis2 SAD address for bitmap is 0x20000 for whatever reason (presumably missing banking); - A5105 has a FIFO bug with the RDAT, should be a lot larger when it scrolls up. @@ -1648,8 +1647,6 @@ void upd7220_device::update_graphics(bitmap_rgb32 &bitmap, const rectangle &clip if (im || force_bitmap) { - //get_graphics_partition(area, &sad, &len, &im, &wd); - if(area >= 3) // TODO: most likely to be correct, Quarth (PC-98xx) definitely draws with area 2. We might see an area 3 someday ... break; @@ -1670,8 +1667,6 @@ void upd7220_device::update_graphics(bitmap_rgb32 &bitmap, const rectangle &clip } else { - get_text_partition(area, &sad, &len, &im, &wd); - if(m_lr) { for (y = 0; y < len; y+=m_lr) From 7c1ed8c6e065b78238edaae427343e3b5b0fb9b8 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Tue, 20 Apr 2021 12:37:20 -0400 Subject: [PATCH 2/2] upd7220: Support DMAW and DMAR commands --- src/devices/video/upd7220.cpp | 195 ++++++++++++++++++++++++---------- src/devices/video/upd7220.h | 13 ++- src/mame/drivers/qx10.cpp | 21 +--- 3 files changed, 152 insertions(+), 77 deletions(-) diff --git a/src/devices/video/upd7220.cpp b/src/devices/video/upd7220.cpp index b09cee24651..0d20e578cc4 100644 --- a/src/devices/video/upd7220.cpp +++ b/src/devices/video/upd7220.cpp @@ -11,9 +11,6 @@ TODO: - implement FIFO as ring buffer - - commands - - DMAR - - DMAW - incomplete / unimplemented FIGD / GCHRD draw modes - FIGD character - slanted character @@ -456,9 +453,20 @@ inline void upd7220_device::reset_figs_param() //------------------------------------------------- // read_vram - //------------------------------------------------- - -inline void upd7220_device::read_vram(uint8_t type, uint8_t mod) +inline uint16_t upd7220_device::read_vram() { + uint16_t data; + + data = readword(m_ead*2); + m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); + m_ead &= 0x3ffff; + + return data; +} + +inline void upd7220_device::rdat(uint8_t type, uint8_t mod) +{ + uint16_t data; if (type == 1) { LOG("uPD7220 invalid type 1 RDAT parameter\n"); @@ -470,35 +478,74 @@ inline void upd7220_device::read_vram(uint8_t type, uint8_t mod) while (m_figs.m_dc && m_fifo_ptr < (type ? 15 : 14)) { + data = read_vram(); switch(type) { case 0: - queue(readbyte(m_ead*2), 0); - queue(readbyte(m_ead*2+1), 0); + queue(data & 0xff, 0); + queue((data >> 8) & 0xff, 0); break; case 2: - queue(readbyte(m_ead*2), 0); + queue(data & 0xff, 0); break; case 3: - queue(readbyte(m_ead*2+1), 0); + queue((data >> 8) & 0xff, 0); break; } m_figs.m_dc--; - m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); - m_ead &= 0x3ffff; } if (m_figs.m_dc == 0) reset_figs_param(); } - //------------------------------------------------- // write_vram - //------------------------------------------------- +inline void upd7220_device::write_vram(uint8_t type, uint8_t mod, uint16_t data) +{ + switch(mod & 3) + { + case 0x00: //replace + if(type == 0) + writeword(m_ead*2+0, data); + if(type == 2) + writebyte(m_ead*2+0, data & 0xff); + if(type == 3) + writebyte(m_ead*2+1, data >> 8); + break; + case 0x01: //complement + if(type == 0) + writeword(m_ead*2+0, readword(m_ead*2+0) ^ data); + if(type == 2) + writebyte(m_ead*2+0, readbyte(m_ead*2+0) ^ (data & 0xff)); + if(type == 3) + writebyte(m_ead*2+1, readbyte(m_ead*2+1) ^ (data >> 8)); + break; + case 0x02: //reset to zero + if(type == 0) + writeword(m_ead*2+0, readword(m_ead*2+0) & ~data); + if(type == 2) + writebyte(m_ead*2+0, readbyte(m_ead*2+0) & ~(data & 0xff)); + if(type == 3) + writebyte(m_ead*2+1, readbyte(m_ead*2+1) & ~(data >> 8)); + break; + case 0x03: //set to one + if(type == 0) + writeword(m_ead*2+0, readword(m_ead*2+0) | data); + if(type == 2) + writebyte(m_ead*2+0, readbyte(m_ead*2+0) | (data & 0xff)); + if(type == 3) + writebyte(m_ead*2+1, readbyte(m_ead*2+1) | (data >> 8)); + break; + } -inline void upd7220_device::write_vram(uint8_t type, uint8_t mod) + m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); + m_ead &= 0x3ffff; +} + +inline void upd7220_device::wdat(uint8_t type, uint8_t mod) { uint16_t result; @@ -535,44 +582,7 @@ inline void upd7220_device::write_vram(uint8_t type, uint8_t mod) for(int i = 0; i < m_figs.m_dc + 1; i++) { - switch(mod & 3) - { - case 0x00: //replace - if(type == 0) - writeword(m_ead*2+0, result); - if(type == 2) - writebyte(m_ead*2+0, result & 0xff); - if(type == 3) - writebyte(m_ead*2+1, result >> 8); - break; - case 0x01: //complement - if(type == 0) - writeword(m_ead*2+0, readword(m_ead*2+0) ^ result); - if(type == 2) - writebyte(m_ead*2+0, readbyte(m_ead*2+0) ^ (result & 0xff)); - if(type == 3) - writebyte(m_ead*2+1, readbyte(m_ead*2+1) ^ (result >> 8)); - break; - case 0x02: //reset to zero - if(type == 0) - writeword(m_ead*2+0, readword(m_ead*2+0) & ~result); - if(type == 2) - writebyte(m_ead*2+0, readbyte(m_ead*2+0) & ~(result & 0xff)); - if(type == 3) - writebyte(m_ead*2+1, readbyte(m_ead*2+1) & ~(result >> 8)); - break; - case 0x03: //set to one - if(type == 0) - writeword(m_ead*2+0, readword(m_ead*2+0) | result); - if(type == 2) - writebyte(m_ead*2+0, readbyte(m_ead*2+0) | (result & 0xff)); - if(type == 3) - writebyte(m_ead*2+1, readbyte(m_ead*2+1) | (result >> 8)); - break; - } - - m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); - m_ead &= 0x3ffff; + write_vram(type, mod, result); } } @@ -1334,7 +1344,7 @@ void upd7220_device::process_fifo() LOG("%02x = %02x %02x (%c) %06x %04x\n",m_cr,m_pr[2],m_pr[1],m_pr[1]?m_pr[1]:' ',m_ead,m_figs.m_dc); fifo_set_direction(FIFO_WRITE); - write_vram((m_cr & 0x18) >> 3,m_cr & 3); + wdat((m_cr & 0x18) >> 3,m_cr & 3); reset_figs_param(); m_param_ptr = 1; } @@ -1413,7 +1423,7 @@ void upd7220_device::process_fifo() case COMMAND_RDAT: /* read data from display memory */ fifo_set_direction(FIFO_READ); - read_vram((m_cr & 0x18) >> 3,m_cr & 3); + rdat((m_cr & 0x18) >> 3,m_cr & 3); m_sr |= UPD7220_SR_DATA_READY; break; @@ -1445,11 +1455,17 @@ void upd7220_device::process_fifo() break; case COMMAND_DMAR: /* DMA read request */ - logerror("uPD7220 Unimplemented command DMAR\n"); + m_dma_type = (m_cr >> 3) & 3; + m_dma_mod = m_cr & 3; + m_dma_transfer_length = (m_figs.m_dc + 1) * (m_figs.m_d + 2); + start_dma(); break; case COMMAND_DMAW: /* DMA write request */ - logerror("uPD7220 Unimplemented command DMAW\n"); + m_dma_type = (m_cr >> 3) & 3; + m_dma_mod = m_cr & 3; + m_dma_transfer_length = (m_figs.m_dc + 1) * (m_figs.m_d + 1); + start_dma(); break; } } @@ -1464,7 +1480,7 @@ void upd7220_device::continue_command() // continue RDAT command when data to read are larger than the FIFO (a5105 and dmv text scrolling) if (m_figs.m_dc && translate_command(m_cr) == COMMAND_RDAT) { - read_vram((m_cr & 0x18) >> 3, m_cr & 3); + rdat((m_cr & 0x18) >> 3, m_cr & 3); m_sr |= UPD7220_SR_DATA_READY; } } @@ -1494,7 +1510,6 @@ uint8_t upd7220_device::read(offs_t offset) /* TODO: timing of these */ m_sr &= ~UPD7220_SR_DRAWING_IN_PROGRESS; - m_sr &= ~UPD7220_SR_DMA_EXECUTE; } return data; @@ -1530,7 +1545,31 @@ void upd7220_device::write(offs_t offset, uint8_t data) uint8_t upd7220_device::dack_r() { - return 0; + uint8_t result = 0; + switch(m_dma_type) { + case 0: + if (m_dma_transfer_length % 2 == 0) { + m_dma_data = read_vram(); + result = m_dma_data & 0xff; + } else { + result = (m_dma_data >> 8) & 0xff; + } + break; + case 2: + m_dma_data = read_vram(); + result = m_dma_data & 0xff; + break; + case 3: + m_dma_data = read_vram(); + result = (m_dma_data >> 8) & 0xff; + break; + default: + logerror("uPD7220 Invalid DMA Transfer Type\n"); + } + if (--m_dma_transfer_length == 0) { + stop_dma(); + } + return result; } @@ -1540,6 +1579,46 @@ uint8_t upd7220_device::dack_r() void upd7220_device::dack_w(uint8_t data) { + switch(m_dma_type) { + case 0: + if (m_dma_transfer_length % 2) { + m_dma_data = ((m_dma_data & 0xff) | data << 8) & m_mask; + write_vram(m_dma_type, m_dma_mod, m_dma_data); + } else { + m_dma_data = (m_dma_data & 0xff00) | data; + } + break; + case 2: + m_dma_data = data & (m_mask & 0xff); + write_vram(m_dma_type, m_dma_mod, m_dma_data); + break; + case 3: + m_dma_data = (data << 8) & (m_mask & 0xff); + write_vram(m_dma_type, m_dma_mod, m_dma_data); + break; + default: + logerror("uPD7220 Invalid DMA Transfer Type\n"); + } + if (--m_dma_transfer_length == 0) { + stop_dma(); + } +} + +void upd7220_device::start_dma() +{ + if ((m_sr & UPD7220_SR_DMA_EXECUTE) == 0) { + m_write_drq(ASSERT_LINE); + m_sr |= UPD7220_SR_DMA_EXECUTE; + } +} + +void upd7220_device::stop_dma() +{ + if ((m_sr & UPD7220_SR_DMA_EXECUTE) == UPD7220_SR_DMA_EXECUTE) { + m_write_drq(CLEAR_LINE); + m_sr &= ~UPD7220_SR_DMA_EXECUTE; + reset_figs_param(); + } } diff --git a/src/devices/video/upd7220.h b/src/devices/video/upd7220.h index d1f8806c6ac..77011958ec5 100644 --- a/src/devices/video/upd7220.h +++ b/src/devices/video/upd7220.h @@ -90,6 +90,8 @@ protected: virtual const tiny_rom_entry *device_rom_region() const override; virtual space_config_vector memory_space_config() const override; + void start_dma(); + void stop_dma(); private: enum { @@ -112,8 +114,10 @@ private: inline void update_blank_timer(int state); inline void recompute_parameters(); inline void reset_figs_param(); - inline void read_vram(uint8_t type, uint8_t mod); - inline void write_vram(uint8_t type, uint8_t mod); + inline void rdat(uint8_t type, uint8_t mod); + inline uint16_t read_vram(); + inline void wdat(uint8_t type, uint8_t mod); + inline void write_vram(uint8_t type, uint8_t mod, uint16_t data); inline void get_text_partition(int index, uint32_t *sad, uint16_t *len, int *im, int *wd); inline void get_graphics_partition(int index, uint32_t *sad, uint16_t *len, int *im, int *wd); @@ -139,6 +143,11 @@ private: devcb_write_line m_write_vsync; devcb_write_line m_write_blank; + uint8_t m_dma_type; // DMA transfer type + uint8_t m_dma_mod; // DMA transfer mode + uint16_t m_dma_data; // current word transferred via DMA + uint32_t m_dma_transfer_length; // DMA transfer length in bytes + uint16_t m_mask; // mask register uint8_t m_pitch; // number of word addresses in display memory in the horizontal direction uint32_t m_ead; // execute word address diff --git a/src/mame/drivers/qx10.cpp b/src/mame/drivers/qx10.cpp index b2e413679ad..4e51c18afc9 100644 --- a/src/mame/drivers/qx10.cpp +++ b/src/mame/drivers/qx10.cpp @@ -112,8 +112,6 @@ private: DECLARE_WRITE_LINE_MEMBER( qx10_upd765_interrupt ); void fdd_motor_w(uint8_t data); uint8_t qx10_30_r(); - uint8_t gdc_dack_r(); - void gdc_dack_w(uint8_t data); DECLARE_WRITE_LINE_MEMBER( tc_w ); uint8_t mc146818_r(offs_t offset); void mc146818_w(offs_t offset, uint8_t data); @@ -445,17 +443,6 @@ WRITE_LINE_MEMBER(qx10_state::dma_hrq_changed) m_dma_1->hack_w(state); } -uint8_t qx10_state::gdc_dack_r() -{ - logerror("GDC DACK read\n"); - return 0; -} - -void qx10_state::gdc_dack_w(uint8_t data) -{ - logerror("GDC DACK write %02x\n", data); -} - WRITE_LINE_MEMBER( qx10_state::tc_w ) { /* floppy terminal count */ @@ -674,6 +661,7 @@ void qx10_state::machine_start() void qx10_state::machine_reset() { m_dma_1->dreq0_w(1); + m_dma_1->dreq1_w(1); m_spkr_enable = 0; m_pit1_out0 = 1; @@ -836,11 +824,9 @@ void qx10_state::qx10(machine_config &config) m_dma_1->in_memr_callback().set(FUNC(qx10_state::memory_read_byte)); m_dma_1->out_memw_callback().set(FUNC(qx10_state::memory_write_byte)); m_dma_1->in_ior_callback<0>().set(m_fdc, FUNC(upd765a_device::dma_r)); - m_dma_1->in_ior_callback<1>().set(FUNC(qx10_state::gdc_dack_r)); - //m_dma_1->in_ior_callback<2>().set(m_hgdc, FUNC(upd7220_device::dack_r)); + m_dma_1->in_ior_callback<1>().set(m_hgdc, FUNC(upd7220_device::dack_r)); m_dma_1->out_iow_callback<0>().set(m_fdc, FUNC(upd765a_device::dma_w)); - m_dma_1->out_iow_callback<1>().set(FUNC(qx10_state::gdc_dack_w)); - //m_dma_1->out_iow_callback<2>().set(m_hgdc, FUNC(upd7220_device::dack_w)); + m_dma_1->out_iow_callback<1>().set(m_hgdc, FUNC(upd7220_device::dack_w)); AM9517A(config, m_dma_2, MAIN_CLK/4); I8255(config, m_ppi, 0); @@ -849,6 +835,7 @@ void qx10_state::qx10(machine_config &config) m_hgdc->set_addrmap(0, &qx10_state::upd7220_map); m_hgdc->set_display_pixels(FUNC(qx10_state::hgdc_display_pixels)); m_hgdc->set_draw_text(FUNC(qx10_state::hgdc_draw_text)); + m_hgdc->drq_wr_callback().set(m_dma_1, FUNC(am9517a_device::dreq1_w)).invert(); m_hgdc->set_screen("screen"); MC146818(config, m_rtc, 32.768_kHz_XTAL);