summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author cracyc <cracyc@users.noreply.github.com>2014-10-13 22:28:15 +0000
committer cracyc <cracyc@users.noreply.github.com>2014-10-13 22:28:15 +0000
commit02c4746e502f990663114acaa8edb56d7eacd542 (patch)
tree4423cbf060b8fcff73fecb72b91a4a6b670f971e
parentf38b72ea7d21405eabb51cdf53fc31296c558e3a (diff)
upd7220: add Bresenham arc and complete char drawing [Carl]
-rw-r--r--src/emu/video/upd7220.c287
-rw-r--r--src/emu/video/upd7220.h6
2 files changed, 113 insertions, 180 deletions
diff --git a/src/emu/video/upd7220.c b/src/emu/video/upd7220.c
index 923549b8094..06d3b7b41ba 100644
--- a/src/emu/video/upd7220.c
+++ b/src/emu/video/upd7220.c
@@ -18,10 +18,8 @@
- DMAR
- DMAW
- incomplete / unimplemented FIGD / GCHRD draw modes
- - Arc
- FIGD character
- slanted character
- - GCHRD character (needs rewrite)
- read-modify-write cycle
- read data
- modify data
@@ -134,9 +132,6 @@ enum
static const int x_dir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
static const int y_dir[8] = { 1, 1, 0,-1,-1,-1, 0, 1};
-static const int x_dir_dot[8] = { 1, 1, 0,-1,-1,-1, 0, 1};
-static const int y_dir_dot[8] = { 0,-1,-1,-1, 0, 1, 1, 1};
-
//**************************************************************************
@@ -206,7 +201,6 @@ inline void upd7220_device::writebyte(offs_t address, UINT8 data)
space().write_byte(address, data);
}
-
//-------------------------------------------------
// fifo_clear -
//-------------------------------------------------
@@ -429,69 +423,6 @@ inline void upd7220_device::reset_figs_param()
//-------------------------------------------------
-// advance_ead -
-//-------------------------------------------------
-
-inline void upd7220_device::advance_ead()
-{
- #define EAD m_ead
- #define DAD m_dad
- #define P x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch)
- #define MSB(value) (BIT(value, 15))
- #define LSB(value) (BIT(value, 0))
- #define LR(value) ((value << 1) | MSB(value))
- #define RR(value) ((LSB(value) << 15) | (value >> 1))
-
- switch (m_draw_mode & 0x07)
- {
- case 0:
- EAD += P;
- break;
-
- case 1:
- EAD += P;
- if (MSB(DAD)) EAD++;
- DAD = LR(DAD);
- break;
-
- case 2:
- if (MSB(DAD)) EAD++;
- DAD = LR(DAD);
- break;
-
- case 3:
- EAD -= P;
- if (MSB(DAD)) EAD++;
- DAD = LR(DAD);
- break;
-
- case 4:
- EAD -= P;
- break;
-
- case 5:
- EAD -= P;
- if (LSB(DAD)) EAD--;
- DAD = RR(DAD);
- break;
-
- case 6:
- if (LSB(DAD)) EAD--;
- DAD = RR(DAD);
- break;
-
- case 7:
- EAD += P;
- if (LSB(DAD)) EAD--;
- DAD = RR(DAD);
- break;
- }
-
- EAD &= 0x3ffff;
-}
-
-
-//-------------------------------------------------
// read_vram -
//-------------------------------------------------
@@ -523,7 +454,8 @@ inline void upd7220_device::read_vram(UINT8 type, UINT8 mod)
}
m_figs.m_dc--;
- advance_ead();
+ 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)
@@ -601,32 +533,13 @@ inline void upd7220_device::write_vram(UINT8 type, UINT8 mod)
break;
}
- advance_ead();
+ m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch);
+ m_ead &= 0x3ffff;
}
}
//-------------------------------------------------
-// check_pattern -
-//-------------------------------------------------
-
-inline UINT16 upd7220_device::check_pattern(UINT16 pattern)
-{
- UINT16 res = 0;
-
- switch (m_bitmap_mod & 3)
- {
- case 0: res = pattern; break; //replace
- case 1: res = pattern; break; //complement
- case 2: res = 0; break; //reset to zero
- case 3: res |= 0xffff; break; //set to one
- }
-
- return res;
-}
-
-
-//-------------------------------------------------
// get_text_partition -
//-------------------------------------------------
@@ -681,7 +594,6 @@ upd7220_device::upd7220_device(const machine_config &mconfig, const char *tag, d
m_fifo_ptr(-1),
m_fifo_dir(0),
m_mode(0),
- m_draw_mode(0),
m_de(0),
m_m(0),
m_aw(0),
@@ -846,24 +758,23 @@ void upd7220_device::device_timer(emu_timer &timer, device_timer_id id, int para
// draw_pixel -
//-------------------------------------------------
-void upd7220_device::draw_pixel(int x, int y, UINT8 tile_data)
+void upd7220_device::draw_pixel(int x, int y, int xi, UINT16 tile_data)
{
UINT32 addr = (y * m_pitch * 2 + (x >> 3)) & 0x3ffff;
- int dad = x & 0x7;
UINT8 data = readbyte(addr);
- UINT8 new_pixel = (tile_data) & (0x80 >> (dad));
+ UINT8 new_pixel = (xi & 8 ? tile_data >> 8 : tile_data & 0xff) & (0x80 >> (xi & 7));
+ new_pixel = new_pixel ? (0xff & (0x80 >> (x & 7))) : 0;
switch(m_bitmap_mod)
{
case 0: //replace
- writebyte(addr, data & ~(0x80 >> (dad)));
- writebyte(addr, data | new_pixel);
+ writebyte(addr, (data & ~(0x80 >> (x & 7))) | new_pixel);
break;
case 1: //complement
- writebyte(addr, data ^ (new_pixel));
+ writebyte(addr, data ^ new_pixel);
break;
case 2: //reset
- writebyte(addr, data & ((new_pixel) ? 0xff : ~(0x80 >> (dad))));
+ writebyte(addr, data & ~new_pixel);
break;
case 3: //set
writebyte(addr, data | new_pixel);
@@ -883,20 +794,19 @@ void upd7220_device::draw_line(int x, int y)
const int line_y_dir[8] = { 1, 0, 0,-1,-1, 0, 0, 1};
const int line_x_step[8] = { 1, 0, 0, 1,-1, 0, 0,-1 };
const int line_y_step[8] = { 0, 1,-1, 0, 0,-1, 1, 0 };
- UINT16 line_pattern;
+ UINT16 pattern = (m_ra[8]) | (m_ra[9]<<8);
int line_step = 0;
- UINT8 dot;
- line_size = m_figs.m_dc + 1;
- line_pattern = check_pattern((m_ra[8]) | (m_ra[9]<<8));
+ LOG(("uPD7220 line check: %d %d %02x %08x %d %d\n",x,y,m_figs.m_dir,m_ead,m_figs.m_d1,m_figs.m_dc));
+
+ line_size = m_figs.m_dc;
for(i = 0;i<line_size;i++)
{
line_step = (m_figs.m_d1 * i);
- line_step/= (m_figs.m_dc + 1);
- line_step >>= 1;
- dot = ((line_pattern >> (i & 0xf)) & 1) << 7;
- draw_pixel(x + (line_step*line_x_step[m_figs.m_dir]),y + (line_step*line_y_step[m_figs.m_dir]),dot >> ((x + line_step*line_x_step[m_figs.m_dir]) & 0x7));
+ line_step/= m_figs.m_dc;
+ ++line_step >>= 1;
+ draw_pixel(x + (line_step*line_x_step[m_figs.m_dir]),y + (line_step*line_y_step[m_figs.m_dir]),i,pattern);
x += line_x_dir[m_figs.m_dir];
y += line_y_dir[m_figs.m_dir];
}
@@ -909,6 +819,70 @@ void upd7220_device::draw_line(int x, int y)
m_dad = x & 0x0f;
}
+//-------------------------------------------------
+// draw_arc -
+//-------------------------------------------------
+
+void upd7220_device::draw_arc(int x, int y)
+{
+ int len, xi = m_figs.m_d + 1, yi = 0, err = -m_figs.m_d;
+ int x0, y0;
+ UINT16 pattern = (m_ra[8]) | (m_ra[9]<<8);
+ const int dot_dir[4] = {1, -1, -1, 1};
+
+ switch(m_figs.m_dir & 3)
+ {
+ case 1:
+ case 2:
+ x0 = x;
+ y0 = y + xi * dot_dir[m_figs.m_dir >> 1];
+ break;
+ default:
+ x0 = x + xi * dot_dir[((m_figs.m_dir >> 1) + 3) & 3];
+ y0 = y;
+ break;
+ }
+
+ LOG(("uPD7220 arc check: %d %d %02x %08x %d %d %d\n",x,y,m_figs.m_dir,m_ead,m_figs.m_dm,m_figs.m_dc,m_figs.m_d));
+
+ for(int i = 0; i < m_figs.m_dc; i++)
+ {
+ if(i >= m_figs.m_dm)
+ {
+ switch(m_figs.m_dir & 3)
+ {
+ case 1:
+ case 2:
+ draw_pixel(yi * dot_dir[((m_figs.m_dir >> 1) + 3) & 3] + x0, xi * dot_dir[m_figs.m_dir >> 1] + y0, i, pattern);
+ break;
+ default:
+ draw_pixel(xi * dot_dir[m_figs.m_dir >> 1] + x0, yi * dot_dir[((m_figs.m_dir >> 1) + 3) & 3] + y0, i, pattern);
+ break;
+ }
+ }
+ yi++;
+ if(err < 0)
+ err += (yi + 1) << 1;
+ else
+ {
+ xi--;
+ err += (yi - xi + 1) << 1;
+ }
+ }
+ switch(m_figs.m_dir & 3)
+ {
+ case 1:
+ case 2:
+ x += m_figs.m_dc * dot_dir[((m_figs.m_dir >> 1) + 3) & 3];
+ break;
+ default:
+ y += m_figs.m_dc * dot_dir[m_figs.m_dir >> 1];
+ break;
+ }
+
+ m_ead = (x >> 4) + (y * m_pitch);
+ m_dad = x & 0x0f;
+}
//-------------------------------------------------
// draw_rectangle -
@@ -920,19 +894,16 @@ void upd7220_device::draw_rectangle(int x, int y)
const int rect_x_dir[8] = { 0, 1, 0,-1, 1, 1,-1,-1 };
const int rect_y_dir[8] = { 1, 0,-1, 0, 1,-1,-1, 1 };
UINT8 rect_type,rect_dir;
- UINT16 line_pattern;
- UINT8 dot;
+ UINT16 pattern = (m_ra[8]) | (m_ra[9]<<8);
LOG(("uPD7220 rectangle check: %d %d %02x %08x\n",x,y,m_figs.m_dir,m_ead));
- line_pattern = check_pattern((m_ra[8]) | (m_ra[9]<<8));
rect_type = (m_figs.m_dir & 1) << 2;
rect_dir = rect_type | (((m_figs.m_dir >> 1) + 0) & 3);
for(i = 0;i < m_figs.m_d;i++)
{
- dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7;
- draw_pixel(x,y,dot >> (x & 0x7));
+ draw_pixel(x,y,i,pattern);
x+=rect_x_dir[rect_dir];
y+=rect_y_dir[rect_dir];
}
@@ -941,8 +912,7 @@ void upd7220_device::draw_rectangle(int x, int y)
for(i = 0;i < m_figs.m_d2;i++)
{
- dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7;
- draw_pixel(x,y,dot >> (x & 0x7));
+ draw_pixel(x,y,i,pattern);
x+=rect_x_dir[rect_dir];
y+=rect_y_dir[rect_dir];
}
@@ -951,8 +921,7 @@ void upd7220_device::draw_rectangle(int x, int y)
for(i = 0;i < m_figs.m_d;i++)
{
- dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7;
- draw_pixel(x,y,dot >> (x & 0x7));
+ draw_pixel(x,y,i,pattern);
x+=rect_x_dir[rect_dir];
y+=rect_y_dir[rect_dir];
}
@@ -961,8 +930,7 @@ void upd7220_device::draw_rectangle(int x, int y)
for(i = 0;i < m_figs.m_d2;i++)
{
- dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7;
- draw_pixel(x,y,dot >> (x & 0x7));
+ draw_pixel(x,y,i,pattern);
x+=rect_x_dir[rect_dir];
y+=rect_y_dir[rect_dir];
}
@@ -979,66 +947,36 @@ void upd7220_device::draw_rectangle(int x, int y)
void upd7220_device::draw_char(int x, int y)
{
- int xi,yi;
- int xsize,ysize;
- UINT8 tile_data;
-
- /* snippet for character checking */
- #if 0
- if((m_figs.m_dir & 7) == 3)
- for(yi=0;yi<8;yi++)
- {
- for(xi=0;xi<8;xi++)
- {
- printf("%d",(m_ra[(yi & 7) | 8] >> xi) & 1);
- }
- printf("\n");
- }
- #endif
+ int isize,psize;
+ UINT16 tile_data = 0;
+
+ LOG(("uPD7220 char check: %d %d %02x %08x %d %d\n",x,y,m_figs.m_dir,m_ead,m_figs.m_d,m_figs.m_dc));
- xsize = m_figs.m_d & 0x3ff;
+ isize = m_figs.m_d & 0x3ff;
/* Guess: D has presumably upper bits for ysize, QX-10 relies on this (TODO: check this on any real HW) */
- ysize = ((m_figs.m_d & 0x400) + m_figs.m_dc) + 1;
+ psize = ((m_figs.m_d & 0x400) + m_figs.m_dc) + 1;
- /* TODO: internal direction, zooming, size stuff bigger than 8, rewrite using draw_pixel function */
- if((m_figs.m_dir & 7) == 0)
- {
- for(yi=0;yi<8;yi++)
- {
- for(xi=0;xi<8;xi++)
- {
- UINT8 dot = (m_ra[((7-xi) & 7) | 8]);
- dot >>= yi;
- dot &= 1;
- dot*=0xff;
- draw_pixel(x+xi,y+yi,dot);
- }
- }
- }
- else
+ for(int pi = 0; pi < psize; pi++)
{
- for(yi=0;yi<ysize;yi++)
+ tile_data = BITSWAP8(m_ra[((psize-1-pi) & 7) | 8],0,1,2,3,4,5,6,7);
+ tile_data = (tile_data << 8) | (tile_data & 0xff);
+ for(int pz = 0; pz <= m_gchr; pz++)
{
- switch(m_figs.m_dir & 7)
+ for(int ii = 0, curpixel = 0; ii < isize; ii++)
{
- case 2: tile_data = BITSWAP8(m_ra[((yi) & 7) | 8],0,1,2,3,4,5,6,7); break;
- case 6: tile_data = BITSWAP8(m_ra[((ysize-1-yi) & 7) | 8],7,6,5,4,3,2,1,0); break;
- default: tile_data = BITSWAP8(m_ra[((yi) & 7) | 8],7,6,5,4,3,2,1,0);
- logerror("upd7220 draw char: %d %d %d\n",m_figs.m_dir,xsize,ysize);
- break;
- }
-
- for(xi=0;xi<xsize;xi++)
- {
- UINT32 addr = ((y+yi) * m_pitch * 2) + ((x+xi) >> 3);
-
- writebyte(addr & 0x3ffff, readbyte(addr & 0x3ffff) & ~(1 << (xi & 7)));
- writebyte(addr & 0x3ffff, readbyte(addr & 0x3ffff) | ((tile_data) & (1 << (xi & 7))));
+ for(int iz = 0; iz <= m_gchr; iz++)
+ {
+ draw_pixel(x + (curpixel * x_dir[m_figs.m_dir]), y + (curpixel * y_dir[m_figs.m_dir]), ii, tile_data);
+ curpixel++;
+ }
}
+ x += x_dir[(m_figs.m_dir + 2) & 7];
+ y += y_dir[(m_figs.m_dir + 2) & 7];
}
}
- m_ead = ((x+8*x_dir_dot[m_figs.m_dir]) >> 4) + ((y+8*y_dir_dot[m_figs.m_dir]) * m_pitch);
- m_dad = ((x+8*x_dir_dot[m_figs.m_dir]) & 0xf);
+
+ m_ead = (x >> 4) + (y * m_pitch);
+ m_dad = (x & 0xf);
}
@@ -1359,15 +1297,12 @@ void upd7220_device::process_fifo()
break;
case COMMAND_FIGD: /* figure draw start */
- if(m_figs.m_figure_type == 0 || m_figs.m_figure_type == 4)
- {
- UINT16 line_pattern = check_pattern((m_ra[8]) | (m_ra[9]<<8));
- UINT8 dot = ((line_pattern >> (0 & 0xf)) & 1) << 7;
-
- draw_pixel(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch),dot);
- }
+ if(m_figs.m_figure_type == 0)
+ draw_pixel(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch),m_dad,(m_ra[8]) | (m_ra[9]<<8));
else if(m_figs.m_figure_type == 1)
draw_line(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch));
+ else if(m_figs.m_figure_type == 4)
+ draw_arc(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch));
else if(m_figs.m_figure_type == 8)
draw_rectangle(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch));
else
diff --git a/src/emu/video/upd7220.h b/src/emu/video/upd7220.h
index 8adf1c64172..05bf1b6388a 100644
--- a/src/emu/video/upd7220.h
+++ b/src/emu/video/upd7220.h
@@ -136,16 +136,15 @@ private:
inline void update_blank_timer(int state);
inline void recompute_parameters();
inline void reset_figs_param();
- inline void advance_ead();
inline void read_vram(UINT8 type, UINT8 mod);
inline void write_vram(UINT8 type, UINT8 mod);
- inline UINT16 check_pattern(UINT16 pattern);
inline void get_text_partition(int index, UINT32 *sad, UINT16 *len, int *im, int *wd);
inline void get_graphics_partition(int index, UINT32 *sad, UINT16 *len, int *im, int *wd);
- void draw_pixel(int x, int y, UINT8 tile_data);
+ void draw_pixel(int x, int y, int xi, UINT16 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);
int translate_command(UINT8 data);
void process_fifo();
@@ -182,7 +181,6 @@ private:
int m_fifo_dir; // FIFO direction
UINT8 m_mode; // mode of operation
- UINT8 m_draw_mode; // mode of drawing
int m_de; // display enabled
int m_m; // 0 = accept external vertical sync (slave mode) / 1 = generate & output vertical sync (master mode)