summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author Brian Johnson <brijohn@gmail.com>2021-08-04 13:15:12 -0400
committer GitHub <noreply@github.com>2021-08-05 03:15:12 +1000
commit57e4628edcda9ae3bec250e4cb2a1887affb2cc8 (patch)
treebb73797f224f2f022b5fe3d1845da8a2e7dcf780 /src/devices
parent745206964cc3b33cd6afd1cad4acc24c17f5f3a7 (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.cpp12
-rw-r--r--src/devices/bus/isa/num9rev.cpp6
-rw-r--r--src/devices/video/upd7220.cpp256
-rw-r--r--src/devices/video/upd7220.h13
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