video/upd7220.cpp: Added uPD7220A variant with new RESET and BLANK commands.

This commit is contained in:
Nigel Barnes 2024-08-12 22:18:22 +01:00
parent 8b86a6ff78
commit 99687dc40f
2 changed files with 298 additions and 237 deletions

View File

@ -45,16 +45,19 @@
// MACROS / CONSTANTS // MACROS / CONSTANTS
//************************************************************************** //**************************************************************************
// todo typedef // TODO: typedef
enum enum
{ {
COMMAND_INVALID = -1, COMMAND_INVALID = -1,
COMMAND_RESET, COMMAND_RESET,
COMMAND_RESET2,
COMMAND_RESET3,
COMMAND_SYNC, COMMAND_SYNC,
COMMAND_VSYNC, COMMAND_VSYNC,
COMMAND_CCHAR, COMMAND_CCHAR,
COMMAND_START, COMMAND_START,
COMMAND_BCTRL, COMMAND_BLANK,
COMMAND_BLANK2,
COMMAND_ZOOM, COMMAND_ZOOM,
COMMAND_CURS, COMMAND_CURS,
COMMAND_PRAM, COMMAND_PRAM,
@ -69,8 +72,7 @@ enum
COMMAND_LPRD, COMMAND_LPRD,
COMMAND_DMAR, COMMAND_DMAR,
COMMAND_DMAW, COMMAND_DMAW,
COMMAND_5A, COMMAND_5A
COMMAND_05
}; };
enum enum
@ -87,12 +89,14 @@ enum
}; };
#define UPD7220_COMMAND_RESET 0x00 #define UPD7220_COMMAND_RESET 0x00
#define UPD7220_COMMAND_RESET2 0x01
#define UPD7220_COMMAND_RESET3 0x09
#define UPD7220_COMMAND_SYNC 0x0e // & 0xfe #define UPD7220_COMMAND_SYNC 0x0e // & 0xfe
#define UPD7220_COMMAND_VSYNC 0x6e // & 0xfe #define UPD7220_COMMAND_VSYNC 0x6e // & 0xfe
#define UPD7220_COMMAND_CCHAR 0x4b #define UPD7220_COMMAND_CCHAR 0x4b
#define UPD7220_COMMAND_START 0x6b #define UPD7220_COMMAND_START 0x6b
#define UPD7220_COMMAND_BCTRL 0x0c // & 0xfe #define UPD7220_COMMAND_BLANK 0x0c // & 0xfe
#define UPD7220_COMMAND_05 0x05 #define UPD7220_COMMAND_BLANK2 0x05
#define UPD7220_COMMAND_ZOOM 0x46 #define UPD7220_COMMAND_ZOOM 0x46
#define UPD7220_COMMAND_CURS 0x49 #define UPD7220_COMMAND_CURS 0x49
#define UPD7220_COMMAND_PRAM 0x70 // & 0xf0 #define UPD7220_COMMAND_PRAM 0x70 // & 0xf0
@ -142,6 +146,7 @@ static constexpr int y_dir[8] = { 1, 1, 0,-1,-1,-1, 0, 1};
// devices // devices
DEFINE_DEVICE_TYPE(UPD7220, upd7220_device, "upd7220", "NEC uPD7220") DEFINE_DEVICE_TYPE(UPD7220, upd7220_device, "upd7220", "NEC uPD7220")
DEFINE_DEVICE_TYPE(UPD7220A, upd7220a_device, "upd7220a", "NEC uPD7220A")
// default address map // default address map
@ -159,6 +164,11 @@ ROM_START( upd7220 )
ROM_LOAD( "upd7220.bin", 0x000, 0x100, CRC(3c92b218) SHA1(e154b3106a80c9c98d9f2ee18efcd7f4b4aa7d49) ) ROM_LOAD( "upd7220.bin", 0x000, 0x100, CRC(3c92b218) SHA1(e154b3106a80c9c98d9f2ee18efcd7f4b4aa7d49) )
ROM_END ROM_END
ROM_START( upd7220a )
ROM_REGION( 0x100, "upd7220", 0 )
ROM_LOAD( "upd7220a.bin", 0x000, 0x100, NO_DUMP )
ROM_END
//------------------------------------------------- //-------------------------------------------------
// memory_space_config - return a description of // memory_space_config - return a description of
@ -182,6 +192,10 @@ const tiny_rom_entry *upd7220_device::device_rom_region() const
return ROM_NAME( upd7220 ); return ROM_NAME( upd7220 );
} }
const tiny_rom_entry *upd7220a_device::device_rom_region() const
{
return ROM_NAME( upd7220a );
}
//************************************************************************** //**************************************************************************
@ -371,7 +385,7 @@ inline void upd7220_device::recompute_parameters()
else if((m_mode & UPD7220_MODE_INTERLACE_MASK) == UPD7220_MODE_INTERLACE_ON) else if((m_mode & UPD7220_MODE_INTERLACE_MASK) == UPD7220_MODE_INTERLACE_ON)
{ {
// in interlaced mode every line contains both fields // in interlaced mode every line contains both fields
horiz_mult = 8; // TODO this breaks compis uhrg video, characters are 16 pixels wide in interlaced mode too horiz_mult = 8; // TODO this breaks microbx2, compis uhrg video, characters are 16 pixels wide in interlaced mode too
vert_mult = 2; vert_mult = 2;
} }
@ -459,16 +473,16 @@ inline void upd7220_device::rdat(uint8_t type, uint8_t mod)
uint16_t const data = read_vram(); uint16_t const data = read_vram();
switch(type) switch(type)
{ {
case 0: case 0:
queue(data & 0xff, 0); queue(data & 0xff, 0);
queue((data >> 8) & 0xff, 0); queue((data >> 8) & 0xff, 0);
break; break;
case 2: case 2:
queue(data & 0xff, 0); queue(data & 0xff, 0);
break; break;
case 3: case 3:
queue((data >> 8) & 0xff, 0); queue((data >> 8) & 0xff, 0);
break; break;
} }
m_figs.m_dc--; m_figs.m_dc--;
@ -487,38 +501,38 @@ inline void upd7220_device::write_vram(uint8_t type, uint8_t mod, uint16_t data,
switch(mod & 3) switch(mod & 3)
{ {
case 0x00: //replace case 0x00: //replace
if(type == 0) switch (type)
current = (current & (~mask)) | (data & mask); {
if(type == 2) case 0: current = (current & (~mask)) | (data & mask); break;
current = (current & ~(mask & 0xff)) | (data & (mask & 0xff)); case 2: current = (current & ~(mask & 0xff)) | (data & (mask & 0xff)); break;
if(type == 3) case 3: current = (current & ~(mask & 0xff00)) | (data & (mask & 0xff00)); break;
current = (current & ~(mask & 0xff00)) | (data & (mask & 0xff00)); }
break; break;
case 0x01: //complement case 0x01: //complement
if(type == 0) switch (type)
current = current ^ (data & mask); {
if(type == 2) case 0: current = current ^ (data & mask); break;
current = current ^ (data & (mask & 0xff)); case 2: current = current ^ (data & (mask & 0xff)); break;
if(type == 3) case 3: current = current ^ (data & (mask & 0xff00)); break;
current = current ^ (data & (mask & 0xff00)); }
break; break;
case 0x02: //reset to zero case 0x02: //reset to zero
if(type == 0) switch (type)
current = current & ~(data & mask); {
if(type == 2) case 0: current = current & ~(data & mask); break;
current = current & ~(data & (mask & 0xff)); case 2: current = current & ~(data & (mask & 0xff)); break;
if(type == 3) case 3: current = current & ~(data & (mask & 0xff00)); break;
current = current & ~(data & (mask & 0xff00)); }
break; break;
case 0x03: //set to one case 0x03: //set to one
if(type == 0) switch (type)
current = current | (data & mask); {
if(type == 2) case 0: current = current | (data & mask); break;
current = current | (data & (mask & 0xff)); case 2: current = current | (data & (mask & 0xff)); break;
if(type == 3) case 3: current = current | (data & (mask & 0xff00)); break;
current = current | (data & (mask & 0xff00)); }
break; break;
} }
writeword(m_ead, current); writeword(m_ead, current);
} }
@ -535,16 +549,16 @@ inline void upd7220_device::wdat(uint8_t type, uint8_t mod)
switch(type) switch(type)
{ {
case 0: case 0:
result &= m_mask; result &= m_mask;
break; break;
case 2: case 2:
result &= (m_mask & 0xff); result &= (m_mask & 0xff);
break; break;
case 3: case 3:
result <<= 8; result <<= 8;
result &= (m_mask & 0xff00); result &= (m_mask & 0xff00);
break; break;
} }
//if(result) //if(result)
@ -598,8 +612,8 @@ inline void upd7220_device::get_graphics_partition(int index, uint32_t *sad, uin
// upd7220_device - constructor // upd7220_device - constructor
//------------------------------------------------- //-------------------------------------------------
upd7220_device::upd7220_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : upd7220_device::upd7220_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, UPD7220, tag, owner, clock), device_t(mconfig, type, tag, owner, clock),
device_memory_interface(mconfig, *this), device_memory_interface(mconfig, *this),
device_video_interface(mconfig, *this), device_video_interface(mconfig, *this),
m_display_cb(*this), m_display_cb(*this),
@ -657,6 +671,16 @@ upd7220_device::upd7220_device(const machine_config &mconfig, const char *tag, d
memset(&m_figs, 0x00, sizeof(m_figs)); memset(&m_figs, 0x00, sizeof(m_figs));
} }
upd7220_device::upd7220_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: upd7220_device(mconfig, UPD7220, tag, owner, clock)
{
}
upd7220a_device::upd7220a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: upd7220_device(mconfig, UPD7220A, tag, owner, clock)
{
}
//------------------------------------------------- //-------------------------------------------------
// device_start - device-specific startup // device_start - device-specific startup
@ -825,7 +849,7 @@ void upd7220_device::draw_line()
{ {
m_figs.m_dir = (d < 0) ? octant : (octant + 1) & 7; m_figs.m_dir = (d < 0) ? octant : (octant + 1) & 7;
} }
d += ((d < 0 ) ? d1 : d2); d += ((d < 0) ? d1 : d2);
next_pixel(m_figs.m_dir); next_pixel(m_figs.m_dir);
} }
} }
@ -902,7 +926,6 @@ void upd7220_device::draw_char()
}; };
const uint8_t type = (m_figs.m_figure_type & 0x10) >> 4; const uint8_t type = (m_figs.m_figure_type & 0x10) >> 4;
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); 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 i = 0, di = 0; i < (m_figs.m_dc + 1); ++i) for (int i = 0, di = 0; i < (m_figs.m_dc + 1); ++i)
@ -984,58 +1007,58 @@ void upd7220_device::next_pixel(int direction)
{ {
switch(direction & 7) switch(direction & 7)
{ {
case 0: case 0:
m_ead += get_pitch(); m_ead += get_pitch();
break; break;
case 1: case 1:
m_ead += get_pitch(); m_ead += get_pitch();
if (m_mask & 0x8000) if (m_mask & 0x8000)
{ {
m_ead += 1; m_ead += 1;
} }
m_mask = rotate_left(m_mask); m_mask = rotate_left(m_mask);
break; break;
case 2: case 2:
if (m_mask & 0x8000) if (m_mask & 0x8000)
{ {
m_ead += 1; m_ead += 1;
} }
m_mask = rotate_left(m_mask); m_mask = rotate_left(m_mask);
break; break;
case 3: case 3:
m_ead -= get_pitch(); m_ead -= get_pitch();
if (m_mask & 0x8000) if (m_mask & 0x8000)
{ {
m_ead += 1; m_ead += 1;
} }
m_mask = rotate_left(m_mask); m_mask = rotate_left(m_mask);
break; break;
case 4: case 4:
m_ead -= get_pitch(); m_ead -= get_pitch();
break; break;
case 5: case 5:
m_ead -= get_pitch(); m_ead -= get_pitch();
if (m_mask & 0x1) if (m_mask & 0x1)
{ {
m_ead -= 1; m_ead -= 1;
} }
m_mask = rotate_right(m_mask); m_mask = rotate_right(m_mask);
break; break;
case 6: case 6:
if (m_mask & 0x1) if (m_mask & 0x1)
{ {
m_ead -= 1; m_ead -= 1;
} }
m_mask = rotate_right(m_mask); m_mask = rotate_right(m_mask);
break; break;
case 7: case 7:
m_ead += get_pitch(); m_ead += get_pitch();
if (m_mask & 0x1) if (m_mask & 0x1)
{ {
m_ead -= 1; m_ead -= 1;
} }
m_mask = rotate_right(m_mask); m_mask = rotate_right(m_mask);
break; break;
} }
m_ead &= 0x3ffff; m_ead &= 0x3ffff;
} }
@ -1064,13 +1087,12 @@ int upd7220_device::translate_command(uint8_t data)
case UPD7220_COMMAND_CURD: command = COMMAND_CURD; break; case UPD7220_COMMAND_CURD: command = COMMAND_CURD; break;
case UPD7220_COMMAND_LPRD: command = COMMAND_LPRD; break; case UPD7220_COMMAND_LPRD: command = COMMAND_LPRD; break;
case UPD7220_COMMAND_5A: command = COMMAND_5A; break; case UPD7220_COMMAND_5A: command = COMMAND_5A; break;
case UPD7220_COMMAND_05: command = COMMAND_05; break;
default: default:
switch (data & 0xfe) switch (data & 0xfe)
{ {
case UPD7220_COMMAND_SYNC: command = COMMAND_SYNC; break; case UPD7220_COMMAND_SYNC: command = COMMAND_SYNC; break;
case UPD7220_COMMAND_VSYNC: command = COMMAND_VSYNC; break; case UPD7220_COMMAND_VSYNC: command = COMMAND_VSYNC; break;
case UPD7220_COMMAND_BCTRL: command = COMMAND_BCTRL; break; case UPD7220_COMMAND_BLANK: command = COMMAND_BLANK; break;
default: default:
switch (data & 0xf0) switch (data & 0xf0)
{ {
@ -1090,6 +1112,20 @@ int upd7220_device::translate_command(uint8_t data)
return command; return command;
} }
int upd7220a_device::translate_command(uint8_t data)
{
int command = upd7220_device::translate_command(data);
switch (data)
{
case UPD7220_COMMAND_RESET2: command = COMMAND_RESET2; break;
case UPD7220_COMMAND_RESET3: command = COMMAND_RESET3; break;
case UPD7220_COMMAND_BLANK2: command = COMMAND_BLANK2; break;
}
return command;
}
//------------------------------------------------- //-------------------------------------------------
// process_fifo - // process_fifo -
@ -1106,7 +1142,7 @@ void upd7220_device::process_fifo()
if (flag == FIFO_COMMAND) if (flag == FIFO_COMMAND)
{ {
cr = translate_command(data); cr = translate_command(data);
if (cr != COMMAND_BCTRL) // workaround for Rainbow 100 Windows 1.03, needs verification if (cr != COMMAND_BLANK) // workaround for Rainbow 100 Windows 1.03, needs verification
{ {
m_cr = data; m_cr = data;
m_param_ptr = 1; m_param_ptr = 1;
@ -1131,12 +1167,15 @@ void upd7220_device::process_fifo()
break; break;
case COMMAND_RESET: /* reset */ case COMMAND_RESET: /* reset */
case COMMAND_RESET2:
case COMMAND_RESET3:
switch (m_param_ptr) switch (m_param_ptr)
{ {
case 0: case 1:
LOG("uPD7220 RESET\n"); LOG("uPD7220 RESET\n");
m_de = 0; if (cr != COMMAND_RESET3)
m_de = 0;
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;
@ -1156,6 +1195,12 @@ void upd7220_device::process_fifo()
m_pitch = m_aw; m_pitch = m_aw;
if (type() == UPD7220A)
{
m_pitch = ((m_pr[5] & 0x40) << 2) | (m_pitch & 0xff);
m_al += (m_pr[6] >> 6) & 1;
}
LOG("uPD7220 Mode: %02x\n", m_mode); LOG("uPD7220 Mode: %02x\n", m_mode);
LOG("uPD7220 AW: %u\n", m_aw); LOG("uPD7220 AW: %u\n", m_aw);
LOG("uPD7220 HS: %u\n", m_hs); LOG("uPD7220 HS: %u\n", m_hs);
@ -1192,6 +1237,12 @@ void upd7220_device::process_fifo()
m_pitch = m_aw; m_pitch = m_aw;
if (type() == UPD7220A)
{
m_pitch = ((m_pr[5] & 0x40) << 2) | (m_pitch & 0xff);
m_al += (m_pr[6] >> 6) & 1;
}
LOG("uPD7220 Mode: %02x\n", m_mode); LOG("uPD7220 Mode: %02x\n", m_mode);
LOG("uPD7220 AW: %u\n", m_aw); LOG("uPD7220 AW: %u\n", m_aw);
LOG("uPD7220 HS: %u\n", m_hs); LOG("uPD7220 HS: %u\n", m_hs);
@ -1216,32 +1267,32 @@ void upd7220_device::process_fifo()
break; break;
case COMMAND_CCHAR: /* cursor & character characteristics */ case COMMAND_CCHAR: /* cursor & character characteristics */
if(m_param_ptr == 2) switch (m_param_ptr)
{ {
case 2:
m_lr = (m_pr[1] & 0x1f) + 1; m_lr = (m_pr[1] & 0x1f) + 1;
m_dc = BIT(m_pr[1], 7); m_dc = BIT(m_pr[1], 7);
LOG("uPD7220 LR: %u\n", m_lr); LOG("uPD7220 LR: %u\n", m_lr);
LOG("uPD7220 DC: %u\n", m_dc); LOG("uPD7220 DC: %u\n", m_dc);
} break;
if(m_param_ptr == 3) case 3:
{
m_ctop = m_pr[2] & 0x1f; m_ctop = m_pr[2] & 0x1f;
m_sc = BIT(m_pr[2], 5); m_sc = BIT(m_pr[2], 5);
m_br = (m_pr[2] >> 6); /* guess, assume that blink rate clears upper bits (if any) */ m_br = (m_pr[2] >> 6); /* guess, assume that blink rate clears upper bits (if any) */
LOG("uPD7220 CTOP: %u\n", m_ctop); LOG("uPD7220 CTOP: %u\n", m_ctop);
LOG("uPD7220 SC: %u\n", m_sc); LOG("uPD7220 SC: %u\n", m_sc);
} break;
if(m_param_ptr == 4) case 4:
{
m_br = ((m_pr[3] & 0x07) << 2) | (m_pr[2] >> 6); m_br = ((m_pr[3] & 0x07) << 2) | (m_pr[2] >> 6);
m_cbot = m_pr[3] >> 3; m_cbot = m_pr[3] >> 3;
LOG("uPD7220 BR: %u\n", m_br); LOG("uPD7220 BR: %u\n", m_br);
LOG("uPD7220 CBOT: %u\n", m_cbot); LOG("uPD7220 CBOT: %u\n", m_cbot);
break;
} }
break; break;
@ -1251,11 +1302,11 @@ void upd7220_device::process_fifo()
//LOG("uPD7220 '%s' DE: 1\n"); //LOG("uPD7220 '%s' DE: 1\n");
break; break;
case COMMAND_05: case COMMAND_BLANK2:
m_de = 0; m_de = 0;
break; break;
case COMMAND_BCTRL: /* display blanking control */ case COMMAND_BLANK: /* display blanking control */
m_de = data & 0x01; m_de = data & 0x01;
//LOG("uPD7220 DE: %u\n", m_de); //LOG("uPD7220 DE: %u\n", m_de);
@ -1300,10 +1351,11 @@ void upd7220_device::process_fifo()
{ {
LOG("uPD7220 RA%u: %02x\n", m_ra_addr, data); LOG("uPD7220 RA%u: %02x\n", m_ra_addr, data);
if (m_ra_addr == 8) switch (m_ra_addr)
m_pattern = (m_pattern & 0xff00) | data; {
else if (m_ra_addr == 9) case 8: m_pattern = (m_pattern & 0xff00) | data; break;
m_pattern = (m_pattern & 0xff) | (data << 8); case 9: m_pattern = (m_pattern & 0x00ff) | (data << 8); break;
}
m_ra[m_ra_addr] = data; m_ra[m_ra_addr] = data;
m_ra_addr++; m_ra_addr++;
} }
@ -1315,7 +1367,7 @@ void upd7220_device::process_fifo()
case COMMAND_PITCH: /* pitch specification */ case COMMAND_PITCH: /* pitch specification */
if (flag == FIFO_PARAMETER) if (flag == FIFO_PARAMETER)
{ {
m_pitch = data; m_pitch = (m_pitch & 0x100) | data;
LOG("uPD7220 PITCH: %u\n", m_pitch); LOG("uPD7220 PITCH: %u\n", m_pitch);
} }
@ -1351,8 +1403,9 @@ void upd7220_device::process_fifo()
break; break;
case COMMAND_FIGS: /* figure drawing parameters specify */ case COMMAND_FIGS: /* figure drawing parameters specify */
if (m_param_ptr == 2) switch (m_param_ptr)
{ {
case 2:
m_figs.m_dir = m_pr[1] & 0x7; m_figs.m_dir = m_pr[1] & 0x7;
m_figs.m_figure_type = (m_pr[1] & 0xf8) >> 3; m_figs.m_figure_type = (m_pr[1] & 0xf8) >> 3;
@ -1360,62 +1413,53 @@ void upd7220_device::process_fifo()
LOG("uPD7220 FIG: %02x\n", m_figs.m_figure_type); LOG("uPD7220 FIG: %02x\n", m_figs.m_figure_type);
//if(m_figs.m_dir != 2) //if(m_figs.m_dir != 2)
// printf("DIR %02x\n",m_pr[1]); // printf("DIR %02x\n",m_pr[1]);
} break;
// the Decision Mate V during start-up test upload only 2 params before execute the // the Decision Mate V during start-up test upload only 2 params before execute the
// RDAT command, so I assume this is the expected behaviour, but this needs to be verified. // RDAT command, so I assume this is the expected behaviour, but this needs to be verified.
if (m_param_ptr == 3) case 3:
{
m_figs.m_dc = (m_pr[2]) | (m_figs.m_dc & 0x3f00); m_figs.m_dc = (m_pr[2]) | (m_figs.m_dc & 0x3f00);
LOG("uPD7220 DC: %04x\n", m_figs.m_dc); LOG("uPD7220 DC: %04x\n", m_figs.m_dc);
} break;
if (m_param_ptr == 4) case 4:
{
m_figs.m_dc = (m_pr[2]) | ((m_pr[3] & 0x3f) << 8); m_figs.m_dc = (m_pr[2]) | ((m_pr[3] & 0x3f) << 8);
m_figs.m_gd = (m_pr[3] & 0x40) && ((m_mode & UPD7220_MODE_DISPLAY_MASK) == UPD7220_MODE_DISPLAY_MIXED); m_figs.m_gd = (m_pr[3] & 0x40) && ((m_mode & UPD7220_MODE_DISPLAY_MASK) == UPD7220_MODE_DISPLAY_MIXED);
LOG("uPD7220 DC: %04x\n", m_figs.m_dc); LOG("uPD7220 DC: %04x\n", m_figs.m_dc);
LOG("uPD7220 GD: %02x\n", m_figs.m_gd); LOG("uPD7220 GD: %02x\n", m_figs.m_gd);
} break;
if (m_param_ptr == 6) case 6:
{
m_figs.m_d = (m_pr[4]) | ((m_pr[5] & 0x3f) << 8); m_figs.m_d = (m_pr[4]) | ((m_pr[5] & 0x3f) << 8);
LOG("uPD7220 D: %04x\n", m_figs.m_d); LOG("uPD7220 D: %04x\n", m_figs.m_d);
} break;
if (m_param_ptr == 8) case 8:
{
m_figs.m_d2 = (m_pr[6]) | ((m_pr[7] & 0x3f) << 8); m_figs.m_d2 = (m_pr[6]) | ((m_pr[7] & 0x3f) << 8);
LOG("uPD7220 D2: %04x\n", m_figs.m_d2); LOG("uPD7220 D2: %04x\n", m_figs.m_d2);
} break;
if (m_param_ptr == 10) case 10:
{
m_figs.m_d1 = (m_pr[8]) | ((m_pr[9] & 0x3f) << 8); m_figs.m_d1 = (m_pr[8]) | ((m_pr[9] & 0x3f) << 8);
LOG("uPD7220 D1: %04x\n", m_figs.m_d1); LOG("uPD7220 D1: %04x\n", m_figs.m_d1);
} break;
if (m_param_ptr == 12) case 12:
{
m_figs.m_dm = (m_pr[10]) | ((m_pr[11] & 0x3f) << 8); m_figs.m_dm = (m_pr[10]) | ((m_pr[11] & 0x3f) << 8);
LOG("uPD7220 DM: %04x\n", m_figs.m_dm); LOG("uPD7220 DM: %04x\n", m_figs.m_dm);
break;
} }
break; break;
case COMMAND_FIGD: /* figure draw start */ case COMMAND_FIGD: /* figure draw start */
if(m_figs.m_figure_type == 0) switch (m_figs.m_figure_type)
draw_pixel(); {
else if(m_figs.m_figure_type == 1) case 0: draw_pixel(); break;
draw_line(); case 1: draw_line(); break;
else if(m_figs.m_figure_type == 4) case 4: draw_arc(); break;
draw_arc(); case 8: draw_rectangle(); break;
else if(m_figs.m_figure_type == 8) default: logerror("uPD7220 Unimplemented command FIGD %02x\n", m_figs.m_figure_type);
draw_rectangle(); }
else
logerror("uPD7220 Unimplemented command FIGD %02x\n", m_figs.m_figure_type);
reset_figs_param(); reset_figs_param();
m_sr |= UPD7220_SR_DRAWING_IN_PROGRESS; m_sr |= UPD7220_SR_DRAWING_IN_PROGRESS;
break; break;
@ -1439,7 +1483,6 @@ void upd7220_device::process_fifo()
break; break;
case COMMAND_CURD: /* cursor address read */ case COMMAND_CURD: /* cursor address read */
{
fifo_set_direction(FIFO_READ); fifo_set_direction(FIFO_READ);
queue(m_ead & 0xff, 0); queue(m_ead & 0xff, 0);
@ -1450,7 +1493,6 @@ void upd7220_device::process_fifo()
m_sr |= UPD7220_SR_DATA_READY; m_sr |= UPD7220_SR_DATA_READY;
break; break;
}
case COMMAND_LPRD: /* light pen address read */ case COMMAND_LPRD: /* light pen address read */
fifo_set_direction(FIFO_READ); fifo_set_direction(FIFO_READ);
@ -1557,27 +1599,27 @@ uint8_t upd7220_device::dack_r()
uint8_t result = 0; uint8_t result = 0;
switch(m_dma_type) switch(m_dma_type)
{ {
case 0: case 0:
if (m_dma_transfer_length % 2 == 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(); m_dma_data = read_vram();
result = m_dma_data & 0xff; result = m_dma_data & 0xff;
break; }
case 3: else
m_dma_data = read_vram(); {
result = (m_dma_data >> 8) & 0xff; result = (m_dma_data >> 8) & 0xff;
break; }
default: break;
logerror("uPD7220 Invalid DMA Transfer Type\n"); 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) if (--m_dma_transfer_length == 0)
{ {
@ -1595,33 +1637,33 @@ void upd7220_device::dack_w(uint8_t data)
{ {
switch(m_dma_type) switch(m_dma_type)
{ {
case 0: case 0:
if (m_dma_transfer_length % 2) if (m_dma_transfer_length % 2)
{ {
m_dma_data = ((m_dma_data & 0xff) | data << 8) & m_mask; 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
{
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); 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 += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch);
m_ead &= 0x3ffff; m_ead &= 0x3ffff;
break; }
case 3: else
m_dma_data = (data << 8) & (m_mask & 0xff00); {
write_vram(m_dma_type, m_dma_mod, m_dma_data); m_dma_data = (m_dma_data & 0xff00) | data;
m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); }
m_ead &= 0x3ffff; break;
break; case 2:
default: m_dma_data = data & (m_mask & 0xff);
logerror("uPD7220 Invalid DMA Transfer Type\n"); 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");
} }
if (--m_dma_transfer_length == 0) if (--m_dma_transfer_length == 0)
{ {

View File

@ -82,13 +82,17 @@ public:
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
protected: protected:
// device-level overrides upd7220_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device_t overrides
virtual void device_start() override; virtual void device_start() override;
virtual void device_reset() override; virtual void device_reset() override;
virtual const tiny_rom_entry *device_rom_region() const override; virtual const tiny_rom_entry *device_rom_region() const override;
virtual space_config_vector memory_space_config() const override; virtual space_config_vector memory_space_config() const override;
virtual int translate_command(uint8_t data);
TIMER_CALLBACK_MEMBER(hsync_update); TIMER_CALLBACK_MEMBER(hsync_update);
TIMER_CALLBACK_MEMBER(vsync_update); TIMER_CALLBACK_MEMBER(vsync_update);
TIMER_CALLBACK_MEMBER(blank_update); TIMER_CALLBACK_MEMBER(blank_update);
@ -124,7 +128,6 @@ private:
void draw_rectangle(); void draw_rectangle();
void draw_arc(); void draw_arc();
void draw_char(); void draw_char();
int translate_command(uint8_t data);
void process_fifo(); void process_fifo();
void continue_command(); void continue_command();
void update_text(bitmap_rgb32 &bitmap, const rectangle &cliprect); void update_text(bitmap_rgb32 &bitmap, const rectangle &cliprect);
@ -149,45 +152,45 @@ private:
uint32_t m_dma_transfer_length; // DMA transfer length in bytes uint32_t m_dma_transfer_length; // DMA transfer length in bytes
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 uint16_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
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
int m_ra_addr; // parameter RAM address int m_ra_addr; // parameter RAM address
uint8_t m_sr; // status register uint8_t m_sr; // status register
uint8_t m_cr; // command register uint8_t m_cr; // command register
uint8_t m_pr[17]; // parameter byte register uint8_t m_pr[17]; // parameter byte register
int m_param_ptr; // parameter pointer int m_param_ptr; // parameter pointer
uint8_t m_fifo[16]; // FIFO data queue uint8_t m_fifo[16]; // FIFO data queue
int m_fifo_flag[16]; // FIFO flag queue int m_fifo_flag[16]; // FIFO flag queue
int m_fifo_ptr; // FIFO pointer int m_fifo_ptr; // FIFO pointer
int m_fifo_dir; // FIFO direction int m_fifo_dir; // FIFO direction
uint8_t m_mode; // mode of operation uint8_t m_mode; // mode of operation
int m_de; // display enabled int m_de; // display enabled
int m_m; // 0 = accept external vertical sync (slave mode) / 1 = generate & output vertical sync (master mode) int m_m; // 0 = accept external vertical sync (slave mode) / 1 = generate & output vertical sync (master mode)
int m_aw; // active display words per line - 2 (must be even number with bit 0 = 0) int m_aw; // active display words per line - 2 (must be even number with bit 0 = 0)
int m_al; // active display lines per video field int m_al; // active display lines per video field
int m_vs; // vertical sync width - 1 int m_vs; // vertical sync width - 1
int m_vfp; // vertical front porch width - 1 int m_vfp; // vertical front porch width - 1
int m_vbp; // vertical back porch width - 1 int m_vbp; // vertical back porch width - 1
int m_hs; // horizontal sync width - 1 int m_hs; // horizontal sync width - 1
int m_hfp; // horizontal front porch width - 1 int m_hfp; // horizontal front porch width - 1
int m_hbp; // horizontal back porch width - 1 int m_hbp; // horizontal back porch width - 1
int m_dc; // display cursor int m_dc; // display cursor
int m_sc; // 0 = blinking cursor / 1 = steady cursor int m_sc; // 0 = blinking cursor / 1 = steady cursor
int m_br; // blink rate int m_br; // blink rate
int m_ctop; // cursor top line number in the row int m_ctop; // cursor top line number in the row
int m_cbot; // cursor bottom line number in the row (CBOT < LR) int m_cbot; // cursor bottom line number in the row (CBOT < LR)
int m_lr; // lines per character row - 1 int m_lr; // lines per character row - 1
int m_disp; // display zoom factor int m_disp; // display zoom factor
int m_gchr; // zoom factor for graphics character writing and area filling int m_gchr; // zoom factor for graphics character writing and area filling
uint8_t m_bitmap_mod; uint8_t m_bitmap_mod;
@ -211,7 +214,23 @@ private:
}; };
// ======================> upd7220a_device
class upd7220a_device : public upd7220_device
{
public:
// construction/destruction
upd7220a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
virtual const tiny_rom_entry *device_rom_region() const override;
virtual int translate_command(uint8_t data) override;
};
// device type definition // device type definition
DECLARE_DEVICE_TYPE(UPD7220, upd7220_device) DECLARE_DEVICE_TYPE(UPD7220, upd7220_device)
DECLARE_DEVICE_TYPE(UPD7220A, upd7220a_device)
#endif // MAME_VIDEO_UPD7220_H #endif // MAME_VIDEO_UPD7220_H