video/upd7220.cpp: Updated FIGD to use ead and mask to calculate drawing location. (#8405)

This commit is contained in:
Brian Johnson 2021-08-12 12:55:20 -04:00 committed by GitHub
parent b3f0a946a5
commit 3e714f3de1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 156 deletions

View File

@ -28,8 +28,6 @@
- honor visible area - honor visible area
- wide mode (32-bit access) - wide mode (32-bit access)
- light pen - light pen
- dad and mask are the same, in figd dad is shifted every step and when msb or lsb are 1 ead is advanced in x dir
*/ */
#include "emu.h" #include "emu.h"
@ -424,9 +422,9 @@ inline void upd7220_device::reset_figs_param()
{ {
m_figs.m_dc = 0x0000; m_figs.m_dc = 0x0000;
m_figs.m_d = 0x0008; m_figs.m_d = 0x0008;
m_figs.m_d1 = 0x0008; m_figs.m_d1 = 0xffff;
m_figs.m_d2 = 0x0000; m_figs.m_d2 = 0x0008;
m_figs.m_dm = 0x0000; m_figs.m_dm = 0xffff;
m_figs.m_gd = 0; m_figs.m_gd = 0;
} }
@ -612,7 +610,6 @@ upd7220_device::upd7220_device(const machine_config &mconfig, const char *tag, d
m_mask(0), m_mask(0),
m_pitch(0), m_pitch(0),
m_ead(0), m_ead(0),
m_dad(0),
m_lad(0), m_lad(0),
m_ra_addr(0), m_ra_addr(0),
m_sr(UPD7220_SR_FIFO_EMPTY), m_sr(UPD7220_SR_FIFO_EMPTY),
@ -700,7 +697,6 @@ void upd7220_device::device_start()
save_item(NAME(m_ctop)); save_item(NAME(m_ctop));
save_item(NAME(m_cbot)); save_item(NAME(m_cbot));
save_item(NAME(m_ead)); save_item(NAME(m_ead));
save_item(NAME(m_dad));
save_item(NAME(m_lad)); save_item(NAME(m_lad));
save_item(NAME(m_disp)); save_item(NAME(m_disp));
save_item(NAME(m_gchr)); save_item(NAME(m_gchr));
@ -797,28 +793,16 @@ void upd7220_device::device_timer(emu_timer &timer, device_timer_id id, int para
// draw_pixel - // draw_pixel -
//------------------------------------------------- //-------------------------------------------------
void upd7220_device::draw_pixel(int x, int y, int xi, uint16_t tile_data) void upd7220_device::draw_pixel()
{ {
uint32_t addr = (((y * (m_pitch >> m_figs.m_gd)) + (x >> 4))) & 0x3ffff; LOG("uPD7220 dot check: %08x %04x %02x %02x %d\n", m_ead, m_mask, m_bitmap_mod, m_figs.m_dir, m_figs.m_dc);
uint16_t data = readword(addr);
uint16_t new_pixel = (tile_data & (1 << (xi & 0xf))) ? (1 << (x & 0xf)) : 0;
switch(m_bitmap_mod) for(int i = 0; i <= m_figs.m_dc; ++i)
{ {
case 0: //replace const uint16_t pattern = get_pattern(i & 0xf);
data = (data & ~(1 << (x & 0xf))) | new_pixel; write_vram(0, m_bitmap_mod, pattern, m_mask);
break; next_pixel(m_figs.m_dir);
case 1: //complement
data = data ^ new_pixel;
break;
case 2: //reset
data = data & ~new_pixel;
break;
case 3: //set
data = data | new_pixel;
break;
} }
writeword(addr, data);
} }
@ -826,158 +810,89 @@ void upd7220_device::draw_pixel(int x, int y, int xi, uint16_t tile_data)
// draw_line - // draw_line -
//------------------------------------------------- //-------------------------------------------------
void upd7220_device::draw_line(int x, int y) void upd7220_device::draw_line()
{ {
int xi, yi;
int d = (m_figs.m_d & 0x2000) ? (int16_t)(m_figs.m_d | 0xe000) : m_figs.m_d; int d = (m_figs.m_d & 0x2000) ? (int16_t)(m_figs.m_d | 0xe000) : m_figs.m_d;
int d1 = (m_figs.m_d1 & 0x2000) ? (int16_t)(m_figs.m_d1 | 0xe000) : m_figs.m_d1; int d1 = (m_figs.m_d1 & 0x2000) ? (int16_t)(m_figs.m_d1 | 0xe000) : m_figs.m_d1;
int d2 = (m_figs.m_d2 & 0x2000) ? (int16_t)(m_figs.m_d2 | 0xe000) : m_figs.m_d2; int d2 = (m_figs.m_d2 & 0x2000) ? (int16_t)(m_figs.m_d2 | 0xe000) : m_figs.m_d2;
uint16_t pattern = (m_ra[8]) | (m_ra[9]<<8); const uint8_t octant = m_figs.m_dir;
const int dot_dir[4] = {1, -1, -1, 1};
LOG("uPD7220 line check: %d %d %02x %08x %d %d %d\n",x,y,m_figs.m_dir,m_ead,d1,m_figs.m_dc,m_bitmap_mod); LOG("uPD7220 line check: %08x %04x %02x %02x %d %d %d %d\n", m_ead, m_mask, m_bitmap_mod, m_figs.m_dir, m_figs.m_dc, d, d1, d2);
for(yi = xi = 0; yi <= m_figs.m_dc; yi++) for(int i = 0; i <= m_figs.m_dc; ++i)
{ {
switch(m_figs.m_dir & 3) const uint16_t pattern = get_pattern(i & 0xf);
write_vram(0, m_bitmap_mod, pattern, m_mask);
if (octant & 1)
{ {
case 1: m_figs.m_dir = (d < 0) ? (octant + 1) & 7 : octant;
case 2:
draw_pixel(yi * dot_dir[((m_figs.m_dir >> 1) + 3) & 3] + x, xi * dot_dir[m_figs.m_dir >> 1] + y, yi, pattern);
break;
default:
draw_pixel(xi * dot_dir[((m_figs.m_dir >> 1) + 3) & 3] + x, yi * dot_dir[m_figs.m_dir >> 1] + y, yi, pattern);
break;
}
if(d > 0)
{
xi++;
d += d2;
} }
else else
d += d1;
}
switch(m_figs.m_dir & 3)
{ {
case 1: m_figs.m_dir = (d < 0) ? octant : (octant + 1) & 7;
case 2: }
x += yi * dot_dir[((m_figs.m_dir >> 1) + 3) & 3]; d += ((d < 0 ) ? d1 : d2);
y += xi * dot_dir[m_figs.m_dir >> 1]; next_pixel(m_figs.m_dir);
break; }
default:
x += xi * dot_dir[((m_figs.m_dir >> 1) + 3) & 3];
y += yi * dot_dir[m_figs.m_dir >> 1];
break;
} }
m_ead = (x >> 4) + (y * (m_pitch >> m_figs.m_gd));
m_dad = x & 0x0f;
}
//------------------------------------------------- //-------------------------------------------------
// draw_arc - // draw_arc -
//------------------------------------------------- //-------------------------------------------------
void upd7220_device::draw_arc(int x, int y) void upd7220_device::draw_arc()
{ {
int xi = 0, err = -m_figs.m_d, d = m_figs.m_d + 1; int err = -m_figs.m_d, d = m_figs.m_d + 1;
uint16_t pattern = (m_ra[8]) | (m_ra[9]<<8);
const int dot_dir[4] = {1, -1, -1, 1};
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); const uint16_t octant = m_figs.m_dir;
for(int yi = 0; yi <= m_figs.m_dc; yi++) LOG("uPD7220 arc check: %08x %04x %02x %02x %d %d %d %d\n", m_ead, m_mask, m_bitmap_mod, m_figs.m_dir, m_figs.m_dc, m_figs.m_d, m_figs.m_d2, m_figs.m_dm);
for (int i = 0; i <= m_figs.m_dc; ++i)
{ {
if(yi >= m_figs.m_dm) const uint16_t pattern = get_pattern(i % 0xf);
if (i >= m_figs.m_dm)
{ {
switch(m_figs.m_dir & 3) write_vram(0, m_bitmap_mod, pattern, m_mask);
{
case 1:
case 2:
draw_pixel(yi * dot_dir[((m_figs.m_dir >> 1) + 3) & 3] + x, xi * dot_dir[m_figs.m_dir >> 1] + y, yi, pattern);
break;
default:
draw_pixel(xi * dot_dir[((m_figs.m_dir >> 1) + 3) & 3] + x, yi * dot_dir[m_figs.m_dir >> 1] + y, yi, pattern);
break;
}
} }
if (err < 0) if (err < 0)
err += (yi + 1) << 1; {
m_figs.m_dir = (octant & 1) ? (octant + 1) & 7 : octant;
}
else else
{ {
xi++; m_figs.m_dir = (octant & 1) ? octant : (octant + 1) & 7;
d--;
err += (yi - d + 1) << 1;
} }
err += (err < 0) ? ((i + 1) << 1) : ((i - --d + 1) << 1);
next_pixel(m_figs.m_dir);
} }
switch(m_figs.m_dir & 3)
{
case 1:
case 2:
x += (m_figs.m_dc + 1) * dot_dir[((m_figs.m_dir >> 1) + 3) & 3];
break;
default:
y += (m_figs.m_dc + 1) * dot_dir[m_figs.m_dir >> 1];
break;
} }
m_ead = (x >> 4) + (y * (m_pitch >> m_figs.m_gd));
m_dad = x & 0x0f;
}
//------------------------------------------------- //-------------------------------------------------
// draw_rectangle - // draw_rectangle -
//------------------------------------------------- //-------------------------------------------------
void upd7220_device::draw_rectangle(int x, int y) void upd7220_device::draw_rectangle()
{ {
const int rect_x_dir[8] = { 0, 1, 0,-1, 1, 1,-1,-1 }; assert(m_figs.m_dc == 3);
const int rect_y_dir[8] = { 1, 0,-1, 0, 1,-1,-1, 1 };
uint8_t rect_type,rect_dir;
uint16_t 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); LOG("uPD7220 rectangle check: %08x %04x %02x %02x %d %d %d\n",m_ead, m_mask, m_bitmap_mod, m_figs.m_dir, m_figs.m_dc, m_figs.m_d, m_figs.m_d2);
rect_type = (m_figs.m_dir & 1) << 2; for (int i = 0; i <= m_figs.m_dc; ++i)
rect_dir = rect_type | (((m_figs.m_dir >> 1) + 0) & 3);
for(int i = 0; i < m_figs.m_d; i++)
{ {
draw_pixel(x,y,i,pattern); const uint16_t dist = (i & 1 ? m_figs.m_d2 : m_figs.m_d);
x+=rect_x_dir[rect_dir]; for (int j = 0; j < dist; ++j)
y+=rect_y_dir[rect_dir]; {
const uint16_t pattern = get_pattern(j & 0xf);
write_vram(0, m_bitmap_mod, pattern, m_mask);
if (i > 0 && j == 0)
m_figs.m_dir = (m_figs.m_dir + 2) & 7;
next_pixel(m_figs.m_dir);
} }
rect_dir = rect_type | (((m_figs.m_dir >> 1) + 1) & 3);
for(int i = 0; i < m_figs.m_d2; i++)
{
draw_pixel(x,y,i,pattern);
x+=rect_x_dir[rect_dir];
y+=rect_y_dir[rect_dir];
} }
rect_dir = rect_type | (((m_figs.m_dir >> 1) + 2) & 3);
for(int i = 0; i < m_figs.m_d; i++)
{
draw_pixel(x,y,i,pattern);
x+=rect_x_dir[rect_dir];
y+=rect_y_dir[rect_dir];
}
rect_dir = rect_type | (((m_figs.m_dir >> 1) + 3) & 3);
for(int i = 0; i < m_figs.m_d2; i++)
{
draw_pixel(x,y,i,pattern);
x+=rect_x_dir[rect_dir];
y+=rect_y_dir[rect_dir];
}
m_ead = (x >> 4) + (y * (m_pitch >> m_figs.m_gd));
m_dad = x & 0x0f;
} }
@ -1190,7 +1105,6 @@ void upd7220_device::process_fifo()
{ {
uint8_t data; uint8_t data;
int flag; int flag;
uint16_t eff_pitch = m_pitch >> m_figs.m_gd;
int cr; int cr;
dequeue(&data, &flag); dequeue(&data, &flag);
@ -1232,7 +1146,6 @@ void upd7220_device::process_fifo()
m_ra[0] = m_ra[1] = m_ra[2] = 0; m_ra[0] = m_ra[1] = m_ra[2] = 0;
m_ra[3] = 0x19; m_ra[3] = 0x19;
m_ead = 0; m_ead = 0;
m_dad = 0;
m_mask = 0; m_mask = 0;
break; break;
@ -1371,9 +1284,7 @@ void upd7220_device::process_fifo()
if(m_param_ptr == 4) if(m_param_ptr == 4)
{ {
m_dad = (m_pr[3] >> 4) & 0x0f;; m_mask = 1 << ((m_pr[3] >> 4) & 0x0f);
m_mask = 1 << m_dad;
LOG("uPD7220 DAD: %01x\n", m_dad);
LOG("uPD7220 MASK: %04x\n", m_mask); LOG("uPD7220 MASK: %04x\n", m_mask);
} }
} }
@ -1466,14 +1377,15 @@ void upd7220_device::process_fifo()
break; break;
case COMMAND_FIGD: /* figure draw start */ case COMMAND_FIGD: /* figure draw start */
m_pattern = (m_ra[8]) | (m_ra[9]<<8);
if(m_figs.m_figure_type == 0) if(m_figs.m_figure_type == 0)
draw_pixel(((m_ead % eff_pitch) << 4) | (m_dad & 0xf),(m_ead / eff_pitch),m_dad,(m_ra[8]) | (m_ra[9]<<8)); draw_pixel();
else if(m_figs.m_figure_type == 1) else if(m_figs.m_figure_type == 1)
draw_line(((m_ead % eff_pitch) << 4) | (m_dad & 0xf),(m_ead / eff_pitch)); draw_line();
else if(m_figs.m_figure_type == 4) else if(m_figs.m_figure_type == 4)
draw_arc(((m_ead % eff_pitch) << 4) | (m_dad & 0xf),(m_ead / eff_pitch)); draw_arc();
else if(m_figs.m_figure_type == 8) else if(m_figs.m_figure_type == 8)
draw_rectangle(((m_ead % eff_pitch) << 4) | (m_dad & 0xf),(m_ead / eff_pitch)); draw_rectangle();
else else
logerror("uPD7220 Unimplemented command FIGD %02x\n", m_figs.m_figure_type); logerror("uPD7220 Unimplemented command FIGD %02x\n", m_figs.m_figure_type);
@ -1501,14 +1413,13 @@ void upd7220_device::process_fifo()
case COMMAND_CURD: /* cursor address read */ case COMMAND_CURD: /* cursor address read */
{ {
uint16_t dad = 1 << m_dad;
fifo_set_direction(FIFO_READ); fifo_set_direction(FIFO_READ);
queue(m_ead & 0xff, 0); queue(m_ead & 0xff, 0);
queue((m_ead >> 8) & 0xff, 0); queue((m_ead >> 8) & 0xff, 0);
queue(m_ead >> 16, 0); queue(m_ead >> 16, 0);
queue(dad & 0xff, 0); queue(m_mask & 0xff, 0);
queue(dad >> 8, 0); queue(m_mask >> 8, 0);
m_sr |= UPD7220_SR_DATA_READY; m_sr |= UPD7220_SR_DATA_READY;
break; break;

View File

@ -122,10 +122,10 @@ private:
uint16_t get_pitch(); uint16_t get_pitch();
uint16_t get_pattern(uint8_t cycle); uint16_t get_pattern(uint8_t cycle);
void next_pixel(int direction); void next_pixel(int direction);
void draw_pixel(int x, int y, int xi, uint16_t tile_data); void draw_pixel();
void draw_line(int x, int y); void draw_line();
void draw_rectangle(int x, int y); void draw_rectangle();
void draw_arc(int x, int y); void draw_arc();
void draw_char(); void draw_char();
int translate_command(uint8_t data); int translate_command(uint8_t data);
void process_fifo(); void process_fifo();
@ -154,7 +154,6 @@ private:
uint16_t m_mask; // mask register uint16_t m_mask; // mask register
uint8_t m_pitch; // number of word addresses in display memory in the horizontal direction uint8_t m_pitch; // number of word addresses in display memory in the horizontal direction
uint32_t m_ead; // execute word address uint32_t m_ead; // execute word address
uint16_t m_dad; // dot address within the word
uint32_t m_lad; // light pen address uint32_t m_lad; // light pen address
uint8_t m_ra[16]; // parameter RAM uint8_t m_ra[16]; // parameter RAM