summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Dirk Best <mail@dirk-best.de>2021-03-15 23:15:57 +0100
committer Dirk Best <mail@dirk-best.de>2021-03-15 23:15:57 +0100
commit62fdcc28dffc83c3a72afeca31c5d3e97c93e05b (patch)
tree09cb251333b7e39de7baff5bbe768dbefc69bf83
parentd26be5231a0f2d078761b61c202d3067e2bf1ffb (diff)
rc759: Major improvements to I82730, hook up SN76489A, preliminary palette
-rw-r--r--src/devices/video/i82730.cpp577
-rw-r--r--src/devices/video/i82730.h136
-rw-r--r--src/mame/drivers/rc759.cpp30
3 files changed, 572 insertions, 171 deletions
diff --git a/src/devices/video/i82730.cpp b/src/devices/video/i82730.cpp
index 5858a7eb0f4..af9209ad04e 100644
--- a/src/devices/video/i82730.cpp
+++ b/src/devices/video/i82730.cpp
@@ -13,14 +13,12 @@
#include "screen.h"
-
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define VERBOSE 1
-#define VERBOSE_COMMANDS 1
-#define VERBOSE_DATASTREAM 0
+#define LOG_GENERAL (1U << 0)
+#define LOG_COMMANDS (1U << 1)
+#define LOG_DATASTREAM (1U << 2)
+//#define VERBOSE (LOG_GENERAL | LOG_COMMANDS | LOG_DATASTREAM)
+#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
//**************************************************************************
@@ -29,22 +27,6 @@
DEFINE_DEVICE_TYPE(I82730, i82730_device, "i82730", "Intel 82730")
-const char *const i82730_device::s_command_names[] =
-{
- /* 00 */ "NOP",
- /* 01 */ "START DISPLAY",
- /* 02 */ "START VIRTUAL DISPLAY",
- /* 03 */ "STOP DISPLAY",
- /* 04 */ "MODE SET",
- /* 05 */ "LOAD CBP",
- /* 06 */ "LOAD INTMASK",
- /* 07 */ "LPEN ENABLE",
- /* 08 */ "READ STATUS",
- /* 09 */ "LD CUR POS",
- /* 0a */ "SELF TEST",
- /* 0b */ "TEST ROW BUFFER"
-};
-
//**************************************************************************
// LIVE DEVICE
@@ -65,26 +47,20 @@ i82730_device::i82730_device(const machine_config &mconfig, const char *tag, dev
m_initialized(false),
m_mode_set(false),
m_ca(0),
+ m_ca_latch(false),
m_sysbus(0x00),
m_ibp(0x0000),
m_cbp(0x0000),
- m_intmask(0xffff),
- m_status(0x0000),
- m_list_switch(0),
- m_auto_line_feed(0),
+ m_list_switch(false),
+ m_auto_line_feed(false),
m_max_dma_count(0),
m_lptr(0),
+ m_status(0x0000),
+ m_intmask(0xffff),
m_sptr(0),
- m_dma_burst_space(0),
- m_dma_burst_length(0),
- m_hfldstrt(0),
- m_margin(0),
- m_lpr(0),
- m_field_attribute_mask(0),
- m_vsyncstp(0),
- m_vfldstrt(0),
- m_vfldstp(0),
- m_frame_int_count(0),
+ m_row(nullptr),
+ m_dma_count(0),
+ m_row_count(0),
m_row_index(0)
{
}
@@ -120,6 +96,7 @@ void i82730_device::device_reset()
m_mode_set = false;
m_ca = 0;
+ m_ca_latch = false;
m_status = 0x0000;
}
@@ -188,66 +165,119 @@ void i82730_device::mode_set()
uint16_t tmp;
tmp = read_word(mptr);
- m_dma_burst_space = tmp & 0x7f;
- m_dma_burst_length = (tmp >> 8) & 0x7f;
+ m_mb.burst_length = (tmp >> 8) & 0x7f;
+ m_mb.burst_space = tmp & 0x7f;
tmp = read_word(mptr + 2);
- uint8_t hsyncstp = tmp & 0xff;
- uint8_t line_length = (tmp >> 8) & 0xff;
+ m_mb.line_length = (tmp >> 8) & 0xff;
+ m_mb.hsyncstp = tmp & 0xff;
tmp = read_word(mptr + 4);
- uint8_t hfldstp = tmp & 0xff;
- m_hfldstrt = (tmp >> 8) & 0xff;
+ m_mb.hfldstrt = (tmp >> 8) & 0xff;
+ m_mb.hfldstp = tmp & 0xff;
tmp = read_word(mptr + 6);
- uint8_t hbrdstp = tmp & 0xff;
- uint8_t hbrdstrt = (tmp >> 8) & 0xff;
+ m_mb.hbrdstrt = (tmp >> 8) & 0xff;
+ m_mb.hbrdstp = tmp & 0xff;
tmp = read_word(mptr + 8);
- m_margin = tmp & 0x1f;
+ m_mb.scroll_margin = tmp & 0x1f;
tmp = read_word(mptr + 10);
- m_lpr = tmp & 0x1f;
+ m_mb.rvv_row = bool(BIT(tmp, 11));
+ m_mb.blk_row = bool(BIT(tmp, 10));
+ m_mb.dbl_hgt = bool(BIT(tmp, 9));
+ m_mb.wdef = bool(BIT(tmp, 8));
+ m_mb.lpr = tmp & 0x1f;
+
+ tmp = read_word(mptr + 12);
+ m_mb.nrmstrt = (tmp >> 8) & 0x1f;
+ m_mb.nrmstp = tmp & 0x1f;
+
+ tmp = read_word(mptr + 14);
+ m_mb.supstrt = (tmp >> 8) & 0x1f;
+ m_mb.supstp = tmp & 0x1f;
+
+ tmp = read_word(mptr + 16);
+ m_mb.substrt = (tmp >> 8) & 0x1f;
+ m_mb.substp = tmp & 0x1f;
+
+ tmp = read_word(mptr + 18);
+ m_mb.cur1strt = (tmp >> 8) & 0x1f;
+ m_mb.cur1stp = tmp & 0x1f;
+
+ tmp = read_word(mptr + 20);
+ m_mb.cur2strt = (tmp >> 8) & 0x1f;
+ m_mb.cur2stp = tmp & 0x1f;
+
+ tmp = read_word(mptr + 22);
+ m_mb.u2_line_sel = (tmp >> 8) & 0x1f;
+ m_mb.u1_line_sel = tmp & 0x1f;
tmp = read_word(mptr + 24);
- m_field_attribute_mask = tmp & 0x7fff;
+ m_mb.field_attribute_mask = tmp & 0x7fff;
tmp = read_word(mptr + 26);
- uint16_t frame_length = tmp & 0x7ff;
+ m_mb.frame_length = tmp & 0x7ff;
tmp = read_word(mptr + 28);
- m_vsyncstp = tmp & 0x7ff;
+ m_mb.vsyncstp = tmp & 0x7ff;
tmp = read_word(mptr + 30);
- m_vfldstrt = tmp & 0x7ff;
+ m_mb.vfldstrt = tmp & 0x7ff;
tmp = read_word(mptr + 32);
- m_vfldstp = tmp & 0x7ff;
+ m_mb.vfldstp = tmp & 0x7ff;
tmp = read_word(mptr + 38);
- m_frame_int_count = tmp & 0x0f;
+ m_mb.duty_cyc_cursor = (tmp >> 12) & 0x0f;
+ m_mb.cursor_blink = (tmp >> 8) & 0x0f;
+ m_mb.frame_int_count = tmp & 0x0f;
+
+ tmp = read_word(mptr + 40);
+ m_mb.duty_cyc_char = (tmp >> 12) & 0x0f;
+ m_mb.char_blink = (tmp >> 8) & 0x0f;
+ m_mb.ile = bool(BIT(tmp, 7));
+ m_mb.rfe = bool(BIT(tmp, 6));
+ m_mb.bpol = bool(BIT(tmp, 5));
+ m_mb.bue = bool(BIT(tmp, 4));
+ m_mb.cr2_cd = bool(BIT(tmp, 3));
+ m_mb.cr1_cd = bool(BIT(tmp, 2));
+ m_mb.cr2_be = bool(BIT(tmp, 1));
+ m_mb.cr1_be = bool(BIT(tmp, 0));
+
+ tmp = read_word(mptr + 40);
+ m_mb.reverse_video = (tmp >> 12) & 0x0f;
+ m_mb.blinking_char = (tmp >> 8) & 0x0f;
+ m_mb.cr2_rvv = bool(BIT(tmp, 3));
+ m_mb.cr1_rvv = bool(BIT(tmp, 2));
+ m_mb.cr2_oe = bool(BIT(tmp, 1));
+ m_mb.cr1_oe = bool(BIT(tmp, 0));
+
+ tmp = read_word(mptr + 42);
+ m_mb.abs_line_count = (tmp >> 12) & 0x0f;
+ m_mb.invisible_char = (tmp >> 8) & 0x0f;
+ m_mb.underline2 = (tmp >> 4) & 0x0f;
+ m_mb.underline1 = tmp & 0x0f;
// setup screen mode
- rectangle visarea(hbrdstrt * 16, hbrdstp * 16 - 1, m_vsyncstp, m_vfldstp + m_margin + 1 + m_lpr - 1);
- attoseconds_t period = HZ_TO_ATTOSECONDS(clock() * 16) * line_length * 16 * frame_length;
- screen().configure(line_length * 16, frame_length, visarea, period);
+ rectangle visarea(m_mb.hbrdstrt * 16, m_mb.hbrdstp * 16 - 1, m_mb.vsyncstp, m_mb.vfldstp + m_mb.scroll_margin + 1 + m_mb.lpr - 1);
+ attoseconds_t period = HZ_TO_ATTOSECONDS(clock() * 16) * m_mb.line_length * 16 * m_mb.frame_length;
+ screen().configure(m_mb.line_length * 16, m_mb.frame_length, visarea, period);
// start display is now valid
m_mode_set = true;
- // adjust timer for the new mode
- m_row_timer->adjust(screen().time_until_pos(0));
-
// output some debug info
if (VERBOSE)
{
- logerror("%s('%s'): ---- setting mode ----\n", shortname(), basetag());
- logerror("%s('%s'): dma burst length %02x, space %02x\n", shortname(), basetag(), m_dma_burst_length, m_dma_burst_space);
- logerror("%s('%s'): margin %02x, lpr %02x\n", shortname(), basetag(), m_margin, m_lpr);
+ logerror("%s('%s'): ---- modeset ----\n", shortname(), basetag());
+ logerror("%s('%s'): dma burst length %02x, space %02x\n", shortname(), basetag(), m_mb.burst_length, m_mb.burst_space);
+ logerror("%s('%s'): margin %02x, lpr %02x\n", shortname(), basetag(), m_mb.scroll_margin, m_mb.lpr);
logerror("%s('%s'): hsyncstp: %02x, line_length: %02x, hfldstrt: %02x, hbrdstart: %02x, hfldstop: %02x, hbrdstop: %02x\n",
- shortname(), basetag(), hsyncstp, line_length, m_hfldstrt, hbrdstrt, hfldstp, hbrdstp);
+ shortname(), basetag(), m_mb.hsyncstp, m_mb.line_length, m_mb.hfldstrt, m_mb.hbrdstrt, m_mb.hfldstp, m_mb.hbrdstp);
logerror("%s('%s'): frame_length %04x, vsyncstp: %04x, vfldstrt: %04x, vfldstp: %04x\n",
- shortname(), basetag(), frame_length, m_vsyncstp, m_vfldstrt, m_vfldstp);
+ shortname(), basetag(), m_mb.frame_length, m_mb.vsyncstp, m_mb.vfldstrt, m_mb.vfldstp);
}
}
@@ -256,16 +286,15 @@ void i82730_device::execute_command()
uint8_t command = read_byte(m_cbp + 1);
uint16_t tmp;
- if (VERBOSE_COMMANDS && command < std::size(s_command_names))
- logerror("%s('%s'): executing command: %s [cbp = %08x]\n", shortname(), basetag(), s_command_names[command], m_cbp);
-
tmp = read_word(m_cbp + 2);
- m_list_switch = BIT(tmp, 6);
- m_auto_line_feed = BIT(tmp, 7);
+ m_list_switch = bool(BIT(tmp, 7));
+ m_auto_line_feed = bool(BIT(tmp, 6));
tmp = read_word(m_cbp + 4);
m_max_dma_count = tmp & 0xff;
+ LOGMASKED(LOG_COMMANDS, "list switch %d, autolf %d, dma count %02x\n", m_list_switch, m_auto_line_feed, m_max_dma_count);
+
switch (command)
{
// NOP
@@ -274,68 +303,83 @@ void i82730_device::execute_command()
// START DISPLAY
case 0x01:
+ LOGMASKED(LOG_COMMANDS, "Executing command START DISPLAY\n");
if (m_mode_set)
+ {
m_status = (m_status & ~VDIP) | DIP;
+ m_row_timer->adjust(screen().time_until_pos(0));
+ }
break;
// START VIRTUAL DISPLAY
case 0x02:
- if (m_mode_set)
- m_status = VDIP | (m_status & ~DIP);
+ LOGMASKED(LOG_COMMANDS, "Executing command START VIRTUAL DISPLAY - not implemented\n");
break;
// STOP DISPLAY
case 0x03:
+ LOGMASKED(LOG_COMMANDS, "Executing command STOP DISPLAY\n");
m_status &= ~(VDIP | DIP);
+ m_row_timer->reset();
break;
// MODE SET
case 0x04:
+ LOGMASKED(LOG_COMMANDS, "Executing command MODE SET\n");
mode_set();
break;
// LOAD CBP
case 0x05:
+ LOGMASKED(LOG_COMMANDS, "Executing command LOAD CBP\n");
m_cbp = (read_word(m_cbp + 16) << 16) | read_word(m_cbp + 14);
+ LOGMASKED(LOG_COMMANDS, "--> New value = %08x\n", m_cbp);
execute_command();
break;
// LOAD INTMASK
case 0x06:
+ LOGMASKED(LOG_COMMANDS, "Executing command LOAD INTMASK\n");
m_intmask = read_word(m_cbp + 22);
- if (VERBOSE_COMMANDS)
- logerror("%s('%s'): intmask now %04x\n", shortname(), basetag(), m_intmask);
+ LOGMASKED(LOG_COMMANDS, "--> New value = %02x\n", m_intmask);
break;
// LPEN ENABLE
case 0x07:
- fatalerror("%s('%s'): Unimplemented command %s\n", shortname(), basetag(), s_command_names[command]);
+ LOGMASKED(LOG_COMMANDS, "Executing command LPEN ENABLE - not implemented\n");
break;
// READ STATUS
case 0x08:
+ LOGMASKED(LOG_COMMANDS, "Executing command READ STATUS\n");
write_word(m_cbp + 18, m_status);
m_status &= (VDIP | DIP);
break;
// LD CUR POS
case 0x09:
- fatalerror("%s('%s'): Unimplemented command %s\n", shortname(), basetag(), s_command_names[command]);
+ LOGMASKED(LOG_COMMANDS, "Executing command LD CUR POS\n");
+ tmp = read_word(m_cbp + 26);
+ m_cursor[0].y = (tmp >> 8) & 0xff;
+ m_cursor[0].x = tmp & 0xff;
+ tmp = read_word(m_cbp + 28);
+ m_cursor[1].y = (tmp >> 8) & 0xff;
+ m_cursor[1].x = tmp & 0xff;
+ LOGMASKED(LOG_COMMANDS, "--> Cursor %d, %d and %d, %d\n", m_cursor[0].x, m_cursor[0].y, m_cursor[1].x, m_cursor[1].y);
break;
// SELF TEST
case 0x0a:
- fatalerror("%s('%s'): Unimplemented command %s\n", shortname(), basetag(), s_command_names[command]);
+ LOGMASKED(LOG_COMMANDS, "Executing command SELF TEST - not implemented\n");
break;
// TEST ROW BUFFER
case 0x0b:
- fatalerror("%s('%s'): Unimplemented command %s\n", shortname(), basetag(), s_command_names[command]);
+ LOGMASKED(LOG_COMMANDS, "Executing command TEST ROW BUFFER - not implemented\n");
break;
default:
- if (VERBOSE_COMMANDS)
- logerror("%s('%s'): executing command: (reserved) [cbp = %08x]\n", shortname(), basetag(), m_cbp);
+ LOGMASKED(LOG_COMMANDS, "Executing command %02x - unknown\n", command);
m_status |= RCC;
update_interrupts();
break;
@@ -345,11 +389,269 @@ void i82730_device::execute_command()
write_word(m_cbp, read_word(m_cbp) & 0xff00);
}
+bool i82730_device::dscmd_endrow()
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command ENDROW\n");
+
+ return true;
+}
+
+bool i82730_device::dscmd_eof()
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command EOF - not implemented\n");
+
+ return false;
+}
+
+bool i82730_device::dscmd_eol()
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command EOL\n");
+
+ m_sptr = (read_word(m_lptr + 2) << 16) | read_word(m_lptr);
+ m_lptr += 4;
+
+ return true;
+}
+
+bool i82730_device::dscmd_fulrowdescrpt(uint8_t param)
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command FULROWDESCRPT %d\n", param);
+
+ uint16_t tmp;
+
+ if (param >= 1)
+ {
+ tmp = read_word(m_sptr);
+ m_sptr += 2;
+ m_mb.rvv_row = bool(BIT(tmp, 11));
+ m_mb.blk_row = bool(BIT(tmp, 10));
+ m_mb.dbl_hgt = bool(BIT(tmp, 9));
+ m_mb.wdef = bool(BIT(tmp, 8));
+ m_mb.lpr = tmp & 0x1f;
+
+ LOGMASKED(LOG_DATASTREAM, "--> RVV_ROW %d, BLK_ROW %d, DBL_HGT %d, WDEF %d, LPR %d\n", m_mb.rvv_row, m_mb.blk_row, m_mb.dbl_hgt, m_mb.wdef, m_mb.lpr);
+ }
+
+ if (param >= 2)
+ {
+ tmp = read_word(m_sptr);
+ m_sptr += 2;
+ m_mb.nrmstrt = (tmp >> 8) & 0x1f;
+ m_mb.nrmstp = tmp & 0x1f;
+
+ LOGMASKED(LOG_DATASTREAM, "--> NRMSTRT %d, NRMSTP %d\n", m_mb.nrmstrt, m_mb.nrmstp);
+ }
+
+ if (param >= 3)
+ {
+ tmp = read_word(m_sptr);
+ m_sptr += 2;
+ m_mb.supstrt = (tmp >> 8) & 0x1f;
+ m_mb.supstp = tmp & 0x1f;
+
+ LOGMASKED(LOG_DATASTREAM, "--> SUPSTRT %d, SUPSTP %d\n", m_mb.supstrt, m_mb.supstp);
+ }
+
+ if (param >= 4)
+ {
+ tmp = read_word(m_sptr);
+ m_sptr += 2;
+ m_mb.substrt = (tmp >> 8) & 0x1f;
+ m_mb.substp = tmp & 0x1f;
+
+ LOGMASKED(LOG_DATASTREAM, "--> SUBSTRT %d, SUBSTP %d\n", m_mb.substrt, m_mb.substp);
+ }
+
+ if (param >= 5)
+ {
+ tmp = read_word(m_sptr);
+ m_sptr += 2;
+ m_mb.cur1strt = (tmp >> 8) & 0x1f;
+ m_mb.cur1stp = tmp & 0x1f;
+
+ LOGMASKED(LOG_DATASTREAM, "--> CUR1STRT %d, CUR1STP %d\n", m_mb.cur1strt, m_mb.cur1stp);
+ }
+
+ if (param >= 6)
+ {
+ tmp = read_word(m_sptr);
+ m_sptr += 2;
+ m_mb.cur2strt = (tmp >> 8) & 0x1f;
+ m_mb.cur2stp = tmp & 0x1f;
+
+ LOGMASKED(LOG_DATASTREAM, "--> CUR2STRT %d, CUR2STP %d\n", m_mb.cur2strt, m_mb.cur2stp);
+ }
+
+ if (param >= 7)
+ {
+ tmp = read_word(m_sptr);
+ m_sptr += 2;
+ m_mb.u2_line_sel = (tmp >> 8) & 0x1f;
+ m_mb.u1_line_sel = tmp & 0x1f;
+
+ LOGMASKED(LOG_DATASTREAM, "--> U2 LINE SEL %d, U1 LINE SEL %d\n", m_mb.u2_line_sel, m_mb.u1_line_sel);
+ }
+
+ return false;
+}
+
+bool i82730_device::dscmd_sl_scroll_strt(uint8_t param)
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command SL SCROLL START %d - not implemented\n", param);
+
+ return false;
+}
+
+bool i82730_device::dscmd_sl_scroll_end(uint8_t param)
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command SL SCROLL END %d - not implemented\n", param);
+
+ return false;
+}
+
+bool i82730_device::dscmd_tab_to(uint8_t param)
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command TAB TO %d - not implemented\n", param);
+
+ return false;
+}
+
+bool i82730_device::dscmd_max_dma_count(uint8_t param)
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command LD MAX DMA COUNT %02x\n", param);
+
+ m_max_dma_count = param;
+
+ return false;
+}
+
+bool i82730_device::dscmd_endstrg()
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command ENDSTRG\n");
+
+ m_sptr = (read_word(m_lptr + 2) << 16) | read_word(m_lptr);
+ m_lptr += 4;
+
+ LOGMASKED(LOG_DATASTREAM, "--> SPTR %08x\n", m_sptr);
+
+ return false;
+}
+
+bool i82730_device::dscmd_skip(uint8_t param)
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command SKIP %d - not implemented\n", param);
+
+ return false;
+}
+
+bool i82730_device::dscmd_repeat(uint8_t param)
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command REPEAT %d\n", param);
+
+ uint16_t data = read_word(m_sptr);
+ m_sptr += 2;
+
+ LOGMASKED(LOG_DATASTREAM, "--> Repeating %02x\n", data);
+
+ while (param--)
+ {
+ if (--m_dma_count && m_row_count < 200)
+ m_row[m_row_count++] = data;
+ else
+ return true;
+ }
+
+ return false;
+}
+
+bool i82730_device::dscmd_sub_sup(uint8_t param)
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command SUP SUB - not implemented\n", param);
+
+ return false;
+}
+
+bool i82730_device::dscmd_rpt_sub_sup(uint8_t param)
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command RPT SUP SUB - not implemented\n", param);
+
+ return false;
+}
+
+bool i82730_device::dscmd_set_gen_pur_attrib(uint8_t param)
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command SET GEN PUR ATTRIB - not implemented\n", param);
+
+ return false;
+}
+
+bool i82730_device::dscmd_set_field_attrib()
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command SET FIELD ATTRIB\n");
+
+ m_mb.field_attribute_mask = read_word(m_sptr) & 0x7fff;
+ m_sptr += 2;
+
+ LOGMASKED(LOG_DATASTREAM, "--> New value = %04x\n", m_mb.field_attribute_mask);
+
+ return false;
+}
+
+bool i82730_device::dscmd_init_next_process()
+{
+ LOGMASKED(LOG_DATASTREAM, "Executing datastream command INIT NEXT PROCESS - not implemented\n");
+
+ return false;
+}
+
+bool i82730_device::execute_datastream_command(uint8_t command, uint8_t param)
+{
+ // RESERVED
+ if (command >= 0x90 && command <= 0xbf)
+ {
+ LOGMASKED(LOG_DATASTREAM, "Executing reserved datastream command %02x\n", command);
+
+ m_status |= RDC;
+ update_interrupts();
+
+ return false;
+ }
+
+ // NOP
+ if (command >= 0xc0)
+ return false;
+
+ // DATASTREAM COMMANDS
+ switch (command)
+ {
+ case 0x80: return dscmd_endrow();
+ case 0x81: return dscmd_eof();
+ case 0x82: return dscmd_eol();
+ case 0x83: return dscmd_fulrowdescrpt(param);
+ case 0x84: return dscmd_sl_scroll_strt(param);
+ case 0x85: return dscmd_sl_scroll_end(param);
+ case 0x86: return dscmd_tab_to(param);
+ case 0x87: return dscmd_max_dma_count(param);
+ case 0x88: return dscmd_endstrg();
+ case 0x89: return dscmd_skip(param);
+ case 0x8a: return dscmd_repeat(param);
+ case 0x8b: return dscmd_sub_sup(param);
+ case 0x8c: return dscmd_rpt_sub_sup(param);
+ case 0x8d: return dscmd_set_gen_pur_attrib(param);
+ case 0x8e: return dscmd_set_field_attrib();
+ case 0x8f: return dscmd_init_next_process();
+ }
+
+ // should never get here
+ return false;
+}
+
void i82730_device::load_row()
{
bool finished = false;
- m_row[m_row_index].count = 0;
+ m_dma_count = m_max_dma_count;
+ m_row_count = 0;
while (!finished)
{
@@ -358,44 +660,37 @@ void i82730_device::load_row()
if (BIT(data, 15))
{
- switch (data >> 8)
- {
- case 0x8e:
- m_field_attribute_mask = read_word(m_sptr) & 0x7fff;
- m_sptr += 2;
-
- if (VERBOSE_DATASTREAM)
- logerror("%s('%s'): SET FIELD ATTRIB to %04x\n", shortname(), basetag(), m_field_attribute_mask);
-
- break;
-
- default:
- fatalerror("%s('%s'): Unimplemented datastream command %02x\n", shortname(), basetag(), data >> 8);
- }
+ finished = execute_datastream_command(data >> 8, data & 0xff);
}
else
{
- // maximum row size is 200
- if (m_row[m_row_index].count < m_max_dma_count && m_row[m_row_index].count < 200)
+ // fetch data
+ if (--m_dma_count > 0)
{
- m_row[m_row_index].data[m_row[m_row_index].count++] = data;
+ if (m_row_count < 200)
+ {
+ m_row[m_row_count++] = data;
+ }
+ else
+ {
+ // buffer overrun
+ m_status |= DBOR;
+ update_interrupts();
+ finished = true;
+ }
}
else
{
-#if 0
- // move to next string?
- if (m_auto_line_feed == 0)
+ if (!m_auto_line_feed)
{
m_sptr = (read_word(m_lptr + 2) << 16) | read_word(m_lptr);
m_lptr += 4;
}
-#endif
+
finished = true;
}
}
}
-
- m_sptr -= 2;
}
TIMER_CALLBACK_MEMBER( i82730_device::row_update )
@@ -408,10 +703,10 @@ TIMER_CALLBACK_MEMBER( i82730_device::row_update )
m_status &= (VDIP | DIP);
// clear field attribute mask
- m_field_attribute_mask = 0;
+ m_mb.field_attribute_mask = 0;
// get listbase
- if (m_list_switch)
+ if (m_list_switch == 0)
m_lptr = (read_word(m_cbp + 8) << 16) | read_word(m_cbp + 6);
else
m_lptr = (read_word(m_cbp + 12) << 16) | read_word(m_cbp + 10);
@@ -421,46 +716,52 @@ TIMER_CALLBACK_MEMBER( i82730_device::row_update )
// fetch initial row
m_row_index = 0;
+ m_row = &m_row_buffer[m_row_index][0];
load_row();
}
- else if (y >= m_vsyncstp && y < m_vfldstrt)
+ else if (y >= m_mb.vsyncstp && y < m_mb.vfldstrt)
{
// blank (top border)
}
- else if (y >= m_vfldstrt && y < m_vfldstp)
+ else if (y >= m_mb.vfldstrt && y < m_mb.vfldstp)
{
- uint8_t lc = (y - m_vfldstrt) % (m_lpr + 1);
+ uint8_t lc = (y - m_mb.vfldstrt) % (m_mb.lpr + 1);
// call driver
- m_update_row_cb(m_bitmap, m_row[m_row_index].data, lc, y - m_vsyncstp, m_row[m_row_index].count);
+ m_update_row_cb(m_bitmap, m_row, lc, y - m_mb.vsyncstp, m_row_count);
// swap buffers at end of row
- if (lc == m_lpr)
+ if (lc == m_mb.lpr)
{
m_row_index ^= 1;
+ m_row = &m_row_buffer[m_row_index][0];
+
+ // load status row data at end of regular display
+ if (y == (m_mb.vfldstp - 1))
+ m_sptr = (read_word(m_cbp + 36) << 16) | read_word(m_cbp + 34);
+
load_row();
}
}
- else if (y >= m_vfldstp && y < m_vfldstp + m_margin + 1)
+ else if (y >= m_mb.vfldstp && y < m_mb.vfldstp + m_mb.scroll_margin + 1)
{
// margin
}
- else if (y >= m_vfldstp + m_margin + 1 && y < m_vfldstp + m_margin + 1 + m_lpr + 1)
+ else if (y >= m_mb.vfldstp + m_mb.scroll_margin + 1 && y < m_mb.vfldstp + m_mb.scroll_margin + 1 + m_mb.lpr + 1)
{
- uint8_t lc = (y - (m_vfldstp + m_margin + 1)) % (m_lpr + 1);
-
- m_sptr = (read_word(m_cbp + 36) << 16) | read_word(m_cbp + 34);
- load_row();
+ uint8_t lc = (y - (m_mb.vfldstp + m_mb.scroll_margin + 1)) % (m_mb.lpr + 1);
// call driver
- m_update_row_cb(m_bitmap, m_row[m_row_index].data, lc, y - m_vsyncstp, m_row[m_row_index].count);
+ m_update_row_cb(m_bitmap, m_row, lc, y - m_mb.vsyncstp, m_row_count);
}
- else if (y == m_vfldstp + m_margin + 1 + m_lpr + 1)
+ else if (y == m_mb.vfldstp + m_mb.scroll_margin + 1 + m_mb.lpr + 1)
{
- // todo: check ca
+ // check ca latch
+ if (m_ca_latch)
+ attention();
// frame interrupt?
- if ((screen().frame_number() % m_frame_int_count) == 0)
+ if ((screen().frame_number() % m_mb.frame_int_count) == 0)
m_status |= EONF;
// check interrupts
@@ -471,16 +772,27 @@ TIMER_CALLBACK_MEMBER( i82730_device::row_update )
// vblank
}
- m_row_timer->adjust(screen().time_until_pos((y + 1) % screen().height()));
+ // schedule next line (if enabled)
+ if (m_status & DIP)
+ m_row_timer->adjust(screen().time_until_pos((y + 1) % screen().height()));
}
-WRITE_LINE_MEMBER( i82730_device::ca_w )
+void i82730_device::attention()
{
- if (VERBOSE)
- logerror("%s('%s'): ca_w %d\n", shortname(), basetag(), state);
+ execute_command();
+ m_ca_latch = false;
+}
+WRITE_LINE_MEMBER( i82730_device::ca_w )
+{
// falling edge
if (m_ca == 1 && state == 0)
+ m_ca_latch = true;
+
+ m_ca = state;
+
+ // check ca every cycle if the display isn't active
+ if (m_ca_latch && ((m_status & DIP) == 0))
{
if (!m_initialized)
{
@@ -490,6 +802,8 @@ WRITE_LINE_MEMBER( i82730_device::ca_w )
// get intermediate block pointer
m_ibp = (read_word(0xfffffffe) << 16) | read_word(0xfffffffc);
+ m_cbp = (read_word(m_ibp + 4) << 16) | read_word(m_ibp + 2);
+
// get system configuration byte
uint8_t scb = read_byte(m_ibp + 6);
@@ -511,26 +825,17 @@ WRITE_LINE_MEMBER( i82730_device::ca_w )
}
}
- // fetch command block pointer
- m_cbp = (read_word(m_ibp + 4) << 16) | read_word(m_ibp + 2);
-
- // and execute command
- execute_command();
+ attention();
}
-
- m_ca = state;
}
WRITE_LINE_MEMBER( i82730_device::irst_w )
{
- if (VERBOSE)
- logerror("%s('%s'): irst_w %d\n", shortname(), basetag(), state);
-
m_sint_handler(0);
}
uint32_t i82730_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- copybitmap(bitmap, m_bitmap, 0, 0, m_hfldstrt * 16, 0, cliprect);
+ copybitmap(bitmap, m_bitmap, 0, 0, m_mb.hfldstrt * 16, 0, cliprect);
return 0;
}
diff --git a/src/devices/video/i82730.h b/src/devices/video/i82730.h
index a107e90461b..27f82eb8d5c 100644
--- a/src/devices/video/i82730.h
+++ b/src/devices/video/i82730.h
@@ -66,8 +66,6 @@ private:
VDIP = 0x100 // virtual display in progress
};
- static const char *const s_command_names[];
-
bool sysbus_16bit() { return BIT(m_sysbus, 0); }
uint8_t read_byte(offs_t address);
@@ -78,7 +76,28 @@ private:
void update_interrupts();
void mode_set();
void execute_command();
+
+ bool dscmd_endrow();
+ bool dscmd_eof();
+ bool dscmd_eol();
+ bool dscmd_fulrowdescrpt(uint8_t param);
+ bool dscmd_sl_scroll_strt(uint8_t param);
+ bool dscmd_sl_scroll_end(uint8_t param);
+ bool dscmd_tab_to(uint8_t param);
+ bool dscmd_max_dma_count(uint8_t param);
+ bool dscmd_endstrg();
+ bool dscmd_skip(uint8_t param);
+ bool dscmd_repeat(uint8_t param);
+ bool dscmd_sub_sup(uint8_t param);
+ bool dscmd_rpt_sub_sup(uint8_t param);
+ bool dscmd_set_gen_pur_attrib(uint8_t param);
+ bool dscmd_set_field_attrib();
+ bool dscmd_init_next_process();
+
+ bool execute_datastream_command(uint8_t command, uint8_t param);
+
void load_row();
+ void attention();
TIMER_CALLBACK_MEMBER(row_update);
@@ -92,48 +111,99 @@ private:
bitmap_rgb32 m_bitmap;
+ // internal registers
bool m_initialized;
bool m_mode_set;
-
int m_ca;
+ bool m_ca_latch;
- // internal registers
uint8_t m_sysbus;
- uint32_t m_ibp;
- uint32_t m_cbp;
- uint16_t m_intmask;
- uint16_t m_status;
+ uint32_t m_ibp; // intermediate block pointer
+ uint32_t m_cbp; // command block pointer
- int m_list_switch;
- int m_auto_line_feed;
+ bool m_list_switch;
+ bool m_auto_line_feed;
uint8_t m_max_dma_count;
-
uint32_t m_lptr;
- uint32_t m_sptr;
-
- int m_dma_burst_space;
- int m_dma_burst_length;
-
- // display parameters
- int m_hfldstrt;
- int m_margin;
- int m_lpr;
- uint16_t m_field_attribute_mask;
- int m_vsyncstp;
- int m_vfldstrt;
- int m_vfldstp;
+ uint16_t m_status;
+ uint16_t m_intmask;
- int m_frame_int_count;
+ uint32_t m_sptr;
- // row buffers
- struct row_buffer
+ struct modeset
{
- uint16_t data[200];
- int count;
- };
-
- row_buffer m_row[2];
- int m_row_index;
+ // horizontal modes
+ uint8_t burst_length;
+ uint8_t burst_space;
+ uint8_t line_length;
+ uint8_t hsyncstp;
+ uint8_t hfldstrt;
+ uint8_t hfldstp;
+ uint8_t hbrdstrt;
+ uint8_t hbrdstp;
+ uint8_t scroll_margin;
+ // char row characteristics
+ bool rvv_row;
+ bool blk_row;
+ bool dbl_hgt;
+ bool wdef;
+ uint8_t lpr;
+ uint8_t nrmstrt;
+ uint8_t nrmstp;
+ uint8_t supstrt;
+ uint8_t supstp;
+ uint8_t substrt;
+ uint8_t substp;
+ uint8_t cur1strt;
+ uint8_t cur1stp;
+ uint8_t cur2strt;
+ uint8_t cur2stp;
+ uint8_t u2_line_sel;
+ uint8_t u1_line_sel;
+ uint16_t field_attribute_mask;
+ // vertical modes
+ uint16_t frame_length;
+ uint16_t vsyncstp;
+ uint16_t vfldstrt;
+ uint16_t vfldstp;
+ // blink control
+ uint8_t duty_cyc_cursor;
+ uint8_t cursor_blink;
+ uint8_t frame_int_count;
+ uint8_t duty_cyc_char;
+ uint8_t char_blink;
+ bool ile;
+ bool rfe;
+ bool bpol;
+ bool bue;
+ bool cr2_cd;
+ bool cr1_cd;
+ bool cr2_be;
+ bool cr1_be;
+ // atrribute bit selects
+ uint8_t reverse_video;
+ uint8_t blinking_char;
+ bool cr2_rvv;
+ bool cr1_rvv;
+ bool cr2_oe;
+ bool cr1_oe;
+ uint8_t abs_line_count;
+ uint8_t invisible_char;
+ uint8_t underline2;
+ uint8_t underline1;
+ } m_mb;
+
+ uint16_t m_row_buffer[2][200];
+ uint16_t *m_row; // pointer to currently active row buffer
+ uint8_t m_dma_count;
+ uint8_t m_row_count; // maximum 200
+ int m_row_index; // 0 or 1
+
+ struct cursor
+ {
+ uint8_t x;
+ uint8_t y;
+ } m_cursor[2];
};
// device type definition
diff --git a/src/mame/drivers/rc759.cpp b/src/mame/drivers/rc759.cpp
index 79a5b59bc00..3872baf18b5 100644
--- a/src/mame/drivers/rc759.cpp
+++ b/src/mame/drivers/rc759.cpp
@@ -6,9 +6,12 @@
TODO:
- Needs better I82730 emulation
- - Sound
+ - Floppy I/O errors
- Many more things
+ Notes:
+ - Press SPACE during self-test for an extended menu
+
***************************************************************************/
#include "emu.h"
@@ -28,6 +31,7 @@
#include "imagedev/cassette.h"
#include "imagedev/floppy.h"
#include "formats/rc759_dsk.h"
+#include "emupal.h"
#include "screen.h"
#include "speaker.h"
@@ -49,6 +53,7 @@ public:
m_nvram(*this, "nvram"),
m_ppi(*this, "ppi"),
m_txt(*this, "txt"),
+ m_palette(*this, "palette"),
m_cas(*this, "cas"),
m_isbx(*this, "isbx"),
m_speaker(*this, "speaker"),
@@ -81,6 +86,7 @@ private:
required_device<nvram_device> m_nvram;
required_device<i8255_device> m_ppi;
required_device<i82730_device> m_txt;
+ required_device<palette_device> m_palette;
required_device<cassette_image_device> m_cas;
required_device<isbx_slot_device> m_isbx;
required_device<speaker_sound_device> m_speaker;
@@ -181,7 +187,8 @@ void rc759_state::rc759_io(address_map &map)
map.unmap_value_high();
map(0x000, 0x003).mirror(0x0c).rw(m_pic, FUNC(pic8259_device::read), FUNC(pic8259_device::write)).umask16(0x00ff);
map(0x020, 0x020).r(m_kbd, FUNC(rc759_kbd_hle_device::read));
-// map(0x056, 0x056)
+ map(0x056, 0x056).w(m_snd, FUNC(sn76494_device::write));
+ map(0x056, 0x057).nopr();
map(0x05a, 0x05a).w(FUNC(rc759_state::rtc_data_w));
map(0x05c, 0x05c).rw(FUNC(rc759_state::rtc_data_r), FUNC(rc759_state::rtc_addr_w));
// map(0x060, 0x06f).w(FUNC(rc759_state::crt_control_w)).umask16(0x00ff);
@@ -264,6 +271,7 @@ void rc759_state::txt_irst_w(uint16_t data)
uint8_t rc759_state::palette_r(offs_t offset)
{
+ // not sure if it's possible to read back
logerror("palette_r(%02x)\n", offset);
return 0xff;
}
@@ -271,6 +279,22 @@ uint8_t rc759_state::palette_r(offs_t offset)
void rc759_state::palette_w(offs_t offset, uint8_t data)
{
logerror("palette_w(%02x): %02x\n", offset, data);
+
+ // two colors/byte. format: IRGBIRGB
+ static constexpr uint8_t val[4] = { 0x00, 0x55, 0xaa, 0xff };
+ int r, g, b;
+
+ r = (BIT(data, 2) << 1) | BIT(data, 3);
+ g = (BIT(data, 1) << 1) | BIT(data, 3);
+ b = (BIT(data, 0) << 1) | BIT(data, 3);
+
+ m_palette->set_pen_color(offset * 2 + 0, rgb_t(val[r], val[g], val[b]));
+
+ r = (BIT(data, 6) << 1) | BIT(data, 7);
+ g = (BIT(data, 5) << 1) | BIT(data, 7);
+ b = (BIT(data, 4) << 1) | BIT(data, 7);
+
+ m_palette->set_pen_color(offset * 2 + 1, rgb_t(val[r], val[g], val[b]));
}
@@ -598,6 +622,8 @@ void rc759_state::rc759(machine_config &config)
m_txt->set_update_row_callback(FUNC(rc759_state::txt_update_row));
m_txt->sint().set(m_pic, FUNC(pic8259_device::ir4_w));
+ PALETTE(config, m_palette).set_entries(64);
+
// sound
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50);