diff options
author | 2021-08-04 13:15:12 -0400 | |
---|---|---|
committer | 2021-08-05 03:15:12 +1000 | |
commit | 57e4628edcda9ae3bec250e4cb2a1887affb2cc8 (patch) | |
tree | bb73797f224f2f022b5fe3d1845da8a2e7dcf780 /src/devices | |
parent | 745206964cc3b33cd6afd1cad4acc24c17f5f3a7 (diff) |
video/upd7220.cpp: Made address space use word addressing, and implemented proper ead/dad/mask support for draw_char. (#8379)
Diffstat (limited to 'src/devices')
-rw-r--r-- | src/devices/bus/compis/hrg.cpp | 12 | ||||
-rw-r--r-- | src/devices/bus/isa/num9rev.cpp | 6 | ||||
-rw-r--r-- | src/devices/video/upd7220.cpp | 256 | ||||
-rw-r--r-- | src/devices/video/upd7220.h | 13 |
4 files changed, 188 insertions, 99 deletions
diff --git a/src/devices/bus/compis/hrg.cpp b/src/devices/bus/compis/hrg.cpp index 1612729e706..9fcd130bec0 100644 --- a/src/devices/bus/compis/hrg.cpp +++ b/src/devices/bus/compis/hrg.cpp @@ -34,14 +34,14 @@ DEFINE_DEVICE_TYPE(COMPIS_UHRG, compis_uhrg_device, "compis_uhrg", "Compis UHRG" void compis_hrg_device::hrg_map(address_map &map) { - map.global_mask(0x7fff); - map(0x00000, 0x7fff).ram().share("video_ram"); + map.global_mask(0x3fff); + map(0x00000, 0x3fff).ram().share("video_ram"); } void compis_uhrg_device::uhrg_map(address_map &map) { - map.global_mask(0x1ffff); - map(0x00000, 0x1ffff).ram().share("video_ram"); + map.global_mask(0xffff); + map(0x00000, 0xffff).ram().share("video_ram"); } @@ -51,7 +51,7 @@ void compis_uhrg_device::uhrg_map(address_map &map) UPD7220_DISPLAY_PIXELS_MEMBER( compis_hrg_device::display_pixels ) { - uint16_t const gfx = m_video_ram[(address & 0x7fff) >> 1]; + uint16_t const gfx = m_video_ram[(address & 0x3fff)]; pen_t const *const pen = m_palette->pens(); for(uint16_t i=0; i<16; i++) @@ -65,7 +65,7 @@ UPD7220_DISPLAY_PIXELS_MEMBER( compis_hrg_device::display_pixels ) UPD7220_DISPLAY_PIXELS_MEMBER( compis_uhrg_device::display_pixels ) { - uint16_t const gfx = m_video_ram[(address & 0x1ffff) >> 1]; + uint16_t const gfx = m_video_ram[(address & 0xffff)]; pen_t const *const pen = m_palette->pens(); for(uint16_t i=0; i<16; i++) diff --git a/src/devices/bus/isa/num9rev.cpp b/src/devices/bus/isa/num9rev.cpp index 632eb8b544b..c7756b8294b 100644 --- a/src/devices/bus/isa/num9rev.cpp +++ b/src/devices/bus/isa/num9rev.cpp @@ -26,11 +26,11 @@ UPD7220_DISPLAY_PIXELS_MEMBER( isa8_number_9_rev_device::hgdc_display_pixels ) { rgb_t color(0); uint16_t overlay; - if(((address << 3) + 0xc0016) > (1024*1024)) + if(((address << 4) + 0xc0016) > (1024*1024)) return; for(int i = 0; i < 16; i++) { - uint32_t addr = (address << 3) + i; + uint32_t addr = (address << 4) + i; overlay = m_ram[addr + 0xc0000] << 1; overlay = m_overlay[overlay + ((m_mode & 8) ? 512 : 0)] | (m_overlay[overlay + 1 + ((m_mode & 8) ? 512 : 0)] << 8); color.set_r(pal->entry_color(m_ram[addr] | ((overlay & 0xf) << 8)).r()); @@ -41,7 +41,7 @@ UPD7220_DISPLAY_PIXELS_MEMBER( isa8_number_9_rev_device::hgdc_display_pixels ) } else { - if(((address << 3) + 16) > (1024*1024)) + if(((address << 4) + 16) > (1024*1024)) return; for(int i = 0; i < 16; i++) bitmap.pix(y, x + i) = pal->entry_color(m_ram[(address << 4) + i]); diff --git a/src/devices/video/upd7220.cpp b/src/devices/video/upd7220.cpp index 8c435dfbeec..d3c0e007b12 100644 --- a/src/devices/video/upd7220.cpp +++ b/src/devices/video/upd7220.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Angelo Salese, Miodrag Milanovic, Carl +// copyright-holders:Angelo Salese, Miodrag Milanovic, Carl, Brian Johnson /********************************************************************** Intel 82720 Graphics Display Controller emulation @@ -190,25 +190,6 @@ const tiny_rom_entry *upd7220_device::device_rom_region() const // INLINE HELPERS //************************************************************************** -//------------------------------------------------- -// readbyte - read a byte at the given address -//------------------------------------------------- - -inline uint8_t upd7220_device::readbyte(offs_t address) -{ - return space().read_byte(address); -} - - -//------------------------------------------------- -// writebyte - write a byte at the given address -//------------------------------------------------- - -inline void upd7220_device::writebyte(offs_t address, uint8_t data) -{ - space().write_byte(address, data); -} - inline uint16_t upd7220_device::readword(offs_t address) { return space().read_word(address); @@ -455,7 +436,7 @@ inline void upd7220_device::reset_figs_param() //------------------------------------------------- inline uint16_t upd7220_device::read_vram() { - uint16_t const data = readword(m_ead*2); + uint16_t const data = readword(m_ead); m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); m_ead &= 0x3ffff; @@ -500,46 +481,46 @@ inline void upd7220_device::rdat(uint8_t type, uint8_t mod) //------------------------------------------------- // write_vram - //------------------------------------------------- -inline void upd7220_device::write_vram(uint8_t type, uint8_t mod, uint16_t data) +inline void upd7220_device::write_vram(uint8_t type, uint8_t mod, uint16_t data, uint16_t mask) { + uint16_t current = readword(m_ead); + switch(mod & 3) { case 0x00: //replace if(type == 0) - writeword(m_ead*2+0, data); + current = (current & (~mask)) | (data & mask); if(type == 2) - writebyte(m_ead*2+0, data & 0xff); + current = (current & ~(mask & 0xff)) | (data & (mask & 0xff)); if(type == 3) - writebyte(m_ead*2+1, data >> 8); + current = (current & ~(mask & 0xff00)) | (data & (mask & 0xff00)); break; case 0x01: //complement if(type == 0) - writeword(m_ead*2+0, readword(m_ead*2+0) ^ data); + current = current ^ (data & mask); if(type == 2) - writebyte(m_ead*2+0, readbyte(m_ead*2+0) ^ (data & 0xff)); + current = current ^ (data & (mask & 0xff)); if(type == 3) - writebyte(m_ead*2+1, readbyte(m_ead*2+1) ^ (data >> 8)); + current = current ^ (data & (mask & 0xff00)); break; case 0x02: //reset to zero if(type == 0) - writeword(m_ead*2+0, readword(m_ead*2+0) & ~data); + current = current & ~(data & mask); if(type == 2) - writebyte(m_ead*2+0, readbyte(m_ead*2+0) & ~(data & 0xff)); + current = current & ~(data & (mask & 0xff)); if(type == 3) - writebyte(m_ead*2+1, readbyte(m_ead*2+1) & ~(data >> 8)); + current = current & ~(data & (mask & 0xff00)); break; case 0x03: //set to one if(type == 0) - writeword(m_ead*2+0, readword(m_ead*2+0) | data); + current = current | (data & mask); if(type == 2) - writebyte(m_ead*2+0, readbyte(m_ead*2+0) | (data & 0xff)); + current = current | (data & (mask & 0xff)); if(type == 3) - writebyte(m_ead*2+1, readbyte(m_ead*2+1) | (data >> 8)); + current = current | (data & (mask & 0xff00)); break; } - - m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); - m_ead &= 0x3ffff; + writeword(m_ead, current); } inline void upd7220_device::wdat(uint8_t type, uint8_t mod) @@ -576,6 +557,8 @@ inline void upd7220_device::wdat(uint8_t type, uint8_t mod) for(int i = 0; i < m_figs.m_dc + 1; i++) { write_vram(type, mod, result); + m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); + m_ead &= 0x3ffff; } } @@ -625,6 +608,7 @@ upd7220_device::upd7220_device(const machine_config &mconfig, const char *tag, d m_write_hsync(*this), m_write_vsync(*this), m_write_blank(*this), + m_pattern(0), m_mask(0), m_pitch(0), m_ead(0), @@ -656,7 +640,7 @@ upd7220_device::upd7220_device(const machine_config &mconfig, const char *tag, d m_disp(0), m_gchr(0), m_bitmap_mod(0), - m_space_config("videoram", ENDIANNESS_LITTLE, 16, 18, 0, address_map_constructor(FUNC(upd7220_device::upd7220_vram), this)) + m_space_config("videoram", ENDIANNESS_LITTLE, 16, 18, -1, address_map_constructor(FUNC(upd7220_device::upd7220_vram), this)) { for (int i = 0; i < 16; i++) { @@ -720,6 +704,7 @@ void upd7220_device::device_start() save_item(NAME(m_lad)); save_item(NAME(m_disp)); save_item(NAME(m_gchr)); + save_item(NAME(m_pattern)); save_item(NAME(m_mask)); save_item(NAME(m_pitch)); save_item(NAME(m_ra_addr)); @@ -814,25 +799,26 @@ void upd7220_device::device_timer(emu_timer &timer, device_timer_id id, int para void upd7220_device::draw_pixel(int x, int y, int xi, uint16_t tile_data) { - uint32_t addr = ((y * (m_pitch << (m_figs.m_gd ? 0 : 1))) + (x >> 3)) & 0x3ffff; + uint32_t addr = (((y * (m_pitch >> m_figs.m_gd)) + (x >> 4))) & 0x3ffff; uint16_t data = readword(addr); uint16_t new_pixel = (tile_data & (1 << (xi & 0xf))) ? (1 << (x & 0xf)) : 0; switch(m_bitmap_mod) { case 0: //replace - writeword(addr, (data & ~(1 << (x & 0xf))) | new_pixel); + data = (data & ~(1 << (x & 0xf))) | new_pixel; break; case 1: //complement - writeword(addr, data ^ new_pixel); + data = data ^ new_pixel; break; case 2: //reset - writeword(addr, data & ~new_pixel); + data = data & ~new_pixel; break; case 3: //set - writeword(addr, data | new_pixel); + data = data | new_pixel; break; } + writeword(addr, data); } @@ -999,58 +985,150 @@ void upd7220_device::draw_rectangle(int x, int y) // draw_char - //------------------------------------------------- -void upd7220_device::draw_char(int x, int y) +void upd7220_device::draw_char() { - int isize,psize; - uint16_t tile_data; + const int8_t dir_change[2][4] = { + {2, 2, -2, -2}, + {1, 3, -3, -1} + }; + const uint8_t type = (m_figs.m_figure_type & 0x10) >> 4; - LOG("uPD7220 char check: %d %d %02x %08x %d %d %02x\n",x,y,m_figs.m_dir,m_ead,m_figs.m_d,m_figs.m_dc,m_figs.m_figure_type); - /* QX10 may require upper bits for psize, VT240 requires the opposite */ - isize = m_figs.m_d; - psize = m_figs.m_dc + 1; + LOG("uPD7220 char check: %08x %04x %02x %02x %d %d %02x\n",m_ead,m_mask,m_bitmap_mod,m_figs.m_dir,m_figs.m_d,m_figs.m_dc,m_figs.m_figure_type); - for(int pi = 0; pi < psize; pi++) + for (int i = 0, di = 0; i < (m_figs.m_dc + 1); ++i) { - tile_data = (m_ra[15-(pi & 7)] << 8) | m_ra[15-(pi & 7)]; - for(int pz = 0; pz <= m_gchr; pz++) + m_pattern = (m_ra[15 - (i & 7)] << 8) | m_ra[15 - (i & 7)]; + for (int zdc = 0; zdc <= m_gchr; ++zdc, ++di) { - int ii = 0, curpixel = 0; - if(pi & 1) - { - ii = isize - 1; - curpixel = (isize * (m_gchr + 1)) - 1; - } - while(pi & 1 ? ii >= 0 : ii < isize) + for (int j = 0; j < m_figs.m_d; ++j) { - for(int iz = 0; iz <= m_gchr; iz++) + const uint16_t pattern = (di % 2) ? get_pattern(15-(j & 0xf)) : get_pattern((j & 0xf)); + for (int zd = 0; zd <= m_gchr; ++zd) { - draw_pixel(x + (curpixel * x_dir[m_figs.m_dir]), y + (curpixel * y_dir[m_figs.m_dir]), ii, tile_data); - if(pi & 1) - curpixel--; - else - curpixel++; + write_vram(0, m_bitmap_mod, pattern, m_mask); + + if (j != (m_figs.m_d - 1) || zd != m_gchr) + next_pixel(m_figs.m_dir); } - if(pi & 1) - ii--; - else - ii++; } - if(m_figs.m_figure_type == 2) + m_figs.m_dir = (((uint16_t)m_figs.m_dir + dir_change[type][(di % 2) << 1]) & 7); + next_pixel(m_figs.m_dir); + m_figs.m_dir = (((uint16_t)m_figs.m_dir + dir_change[type][((di % 2) << 1)+1]) & 7); + } + } +} + + +//------------------------------------------------- +// helper functions used to rotate a uint16_t +//------------------------------------------------- + +static constexpr uint16_t rotate_right(uint16_t value) +{ + return (value>>1) | (value<<( (-1) & 0x0f )); +} + +static constexpr uint16_t rotate_left(uint16_t value) +{ + return (value<<1) | (value>>( (-1) & 0x0f )); +} + + +//------------------------------------------------- +// get_pitch - +//------------------------------------------------- + +uint16_t upd7220_device::get_pitch() +{ + bool mixed = ((m_mode & UPD7220_MODE_DISPLAY_MASK) == UPD7220_MODE_DISPLAY_MIXED); + + if (mixed) + return m_pitch >> m_figs.m_gd; + + return m_pitch; +} + + +//------------------------------------------------- +// get_pattern - +//------------------------------------------------- + +uint16_t upd7220_device::get_pattern(uint8_t cycle) +{ + bool mixed = ((m_mode & UPD7220_MODE_DISPLAY_MASK) == UPD7220_MODE_DISPLAY_MIXED); + bool graphics = ((m_mode & UPD7220_MODE_DISPLAY_MASK) == UPD7220_MODE_DISPLAY_GRAPHICS); + + if ((mixed && m_figs.m_gd) || graphics) + { + return ((m_pattern >> (cycle & 0xf)) & 1) * 0xffff; + } + return m_pattern; +} + + +//------------------------------------------------- +// next_pixel - +//------------------------------------------------- + +void upd7220_device::next_pixel(int direction) +{ + switch(direction & 7) + { + case 0: + m_ead += get_pitch(); + break; + case 1: + m_ead += get_pitch(); + if (m_mask & 0x8000) { - x += x_dir[(m_figs.m_dir + 2) & 7]; - y += y_dir[(m_figs.m_dir + 2) & 7]; + m_ead += 1; } - else + m_mask = rotate_left(m_mask); + break; + case 2: + if (m_mask & 0x8000) { - x += x_dir[(m_figs.m_dir + 1) & 7]; - y += y_dir[(m_figs.m_dir + 1) & 7]; + m_ead += 1; } - } + m_mask = rotate_left(m_mask); + break; + case 3: + m_ead -= get_pitch(); + if (m_mask & 0x8000) + { + m_ead += 1; + } + m_mask = rotate_left(m_mask); + break; + case 4: + m_ead -= get_pitch(); + break; + case 5: + m_ead -= get_pitch(); + if (m_mask & 0x1) + { + m_ead -= 1; + } + m_mask = rotate_right(m_mask); + break; + case 6: + if (m_mask & 0x1) + { + m_ead -= 1; + } + m_mask = rotate_right(m_mask); + break; + case 7: + m_ead += get_pitch(); + if (m_mask & 0x1) + { + m_ead -= 1; + } + m_mask = rotate_right(m_mask); + break; } - - m_ead = (x >> 4) + (y * (m_pitch >> m_figs.m_gd)); - m_dad = (x & 0xf); + m_ead &= 0x3ffff; } @@ -1293,8 +1371,10 @@ void upd7220_device::process_fifo() if(m_param_ptr == 4) { - m_dad = m_pr[3] >> 4; + m_dad = (m_pr[3] >> 4) & 0x0f;; + m_mask = 1 << m_dad; LOG("uPD7220 DAD: %01x\n", m_dad); + LOG("uPD7220 MASK: %04x\n", m_mask); } } break; @@ -1403,7 +1483,7 @@ void upd7220_device::process_fifo() case COMMAND_GCHRD: /* graphics character draw and area filling start */ if((m_figs.m_figure_type & 0xf) == 2) - draw_char(((m_ead % eff_pitch) << 4) | (m_dad & 0xf),(m_ead / eff_pitch)); + draw_char(); else logerror("uPD7220 Unimplemented command GCHRD %02x\n", m_figs.m_figure_type); @@ -1582,6 +1662,8 @@ void upd7220_device::dack_w(uint8_t data) { m_dma_data = ((m_dma_data & 0xff) | data << 8) & m_mask; write_vram(m_dma_type, m_dma_mod, m_dma_data); + m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); + m_ead &= 0x3ffff; } else { @@ -1591,10 +1673,14 @@ void upd7220_device::dack_w(uint8_t data) case 2: m_dma_data = data & (m_mask & 0xff); write_vram(m_dma_type, m_dma_mod, m_dma_data); + m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); + m_ead &= 0x3ffff; break; case 3: m_dma_data = (data << 8) & (m_mask & 0xff00); write_vram(m_dma_type, m_dma_mod, m_dma_data); + m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); + m_ead &= 0x3ffff; break; default: logerror("uPD7220 Invalid DMA Transfer Type\n"); @@ -1706,7 +1792,7 @@ void upd7220_device::draw_graphics_line(bitmap_rgb32 &bitmap, uint32_t addr, int if((sx << 4) < m_aw * 16 && y < al) m_display_cb(bitmap, y, sx << 4, addr); - addr+= (wd + 1) * 2; + addr+= (wd + 1); } } @@ -1754,12 +1840,12 @@ void upd7220_device::update_graphics(bitmap_rgb32 &bitmap, const rectangle &clip // pc98 quarth doesn't seem to use pitch here and it definitely wants bsy to be /2 to make scrolling to work. // pc98 xevious wants the pitch to be fixed at 80, and wants bsy to be /1 // pc98 dbuster contradicts with Xevious with regards of the pitch tho ... - uint32_t const addr = ((sad << 1) & 0x3ffff) + ((y / (mixed ? 1 : m_lr)) * (m_pitch << (im ? 0 : 1))); + uint32_t const addr = (sad & 0x3ffff) + ((y / (mixed ? 1 : m_lr)) * (m_pitch >> (mixed ? 1 : 0))); for(int z = 0; z <= m_disp; ++z) { int yval = (y*zoom)+z + (bsy + m_vbp); if(!m_display_cb.isnull() && yval <= cliprect.bottom()) - draw_graphics_line(bitmap, addr, yval, wd, (m_pitch << interlace)); + draw_graphics_line(bitmap, addr, yval, wd, (m_pitch >> (mixed ? 1 : 0))); } } } diff --git a/src/devices/video/upd7220.h b/src/devices/video/upd7220.h index 77011958ec5..c43a265544f 100644 --- a/src/devices/video/upd7220.h +++ b/src/devices/video/upd7220.h @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Angelo Salese, Miodrag Milanovic, Carl +// copyright-holders:Angelo Salese, Miodrag Milanovic, Carl, Brian Johnson /********************************************************************** NEC uPD7220 Graphics Display Controller emulation @@ -100,8 +100,6 @@ private: TIMER_BLANK }; - inline uint8_t readbyte(offs_t address); - inline void writebyte(offs_t address, uint8_t data); inline uint16_t readword(offs_t address); inline void writeword(offs_t address, uint16_t data); inline void fifo_clear(); @@ -117,15 +115,18 @@ private: 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 write_vram(uint8_t type, uint8_t mod, uint16_t data, uint16_t mask = 0xffff); 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); + uint16_t get_pitch(); + uint16_t get_pattern(uint8_t cycle); + void next_pixel(int direction); void draw_pixel(int x, int y, int xi, uint16_t tile_data); void draw_line(int x, int y); void draw_rectangle(int x, int y); void draw_arc(int x, int y); - void draw_char(int x, int y); + void draw_char(); int translate_command(uint8_t data); void process_fifo(); void continue_command(); @@ -143,6 +144,8 @@ private: devcb_write_line m_write_vsync; devcb_write_line m_write_blank; + uint16_t m_pattern; + 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 |