From 62fdcc28dffc83c3a72afeca31c5d3e97c93e05b Mon Sep 17 00:00:00 2001 From: Dirk Best Date: Mon, 15 Mar 2021 23:15:57 +0100 Subject: [PATCH] rc759: Major improvements to I82730, hook up SN76489A, preliminary palette --- src/devices/video/i82730.cpp | 577 ++++++++++++++++++++++++++--------- src/devices/video/i82730.h | 134 ++++++-- src/mame/drivers/rc759.cpp | 30 +- 3 files changed, 571 insertions(+), 170 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())); +} + +void i82730_device::attention() +{ + execute_command(); + m_ca_latch = false; } WRITE_LINE_MEMBER( i82730_device::ca_w ) { - if (VERBOSE) - logerror("%s('%s'): ca_w %d\n", shortname(), basetag(), state); - // 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; + uint16_t m_status; + uint16_t m_intmask; + 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; - - int m_frame_int_count; - - // row buffers - struct row_buffer + struct modeset { - uint16_t data[200]; - int count; - }; + // 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; - row_buffer m_row[2]; - int m_row_index; + 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 m_nvram; required_device m_ppi; required_device m_txt; + required_device m_palette; required_device m_cas; required_device m_isbx; required_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);