summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author cracyc <cracyc@users.noreply.github.com>2016-10-02 20:40:44 -0500
committer cracyc <cracyc@users.noreply.github.com>2016-10-02 20:40:44 -0500
commit83517be327eb7663fe75d106a595098707828a56 (patch)
tree68720576b4000b1bb7d3a7454ba1775b30271459 /src
parente2e65c9613d3f11513c2409a1a02cabeec19d1e2 (diff)
rainbow: Add color board [Bavarese]
* first incarnatation of the Color Graphics Option for Rainbow-100 B * Clock, VRAM reads/writes + values of uninitialized registers still unverified * (see BUGS section in main driver). vis: checkpoint (nw)
Diffstat (limited to 'src')
-rw-r--r--src/devices/bus/isa/mcd.cpp243
-rw-r--r--src/devices/bus/isa/mcd.h30
-rw-r--r--src/mame/drivers/rainbow.cpp888
-rw-r--r--src/mame/drivers/vis.cpp10
-rw-r--r--src/mame/layout/rainbow.lay30
5 files changed, 1020 insertions, 181 deletions
diff --git a/src/devices/bus/isa/mcd.cpp b/src/devices/bus/isa/mcd.cpp
index 9d4b33fc004..67fbba6ee28 100644
--- a/src/devices/bus/isa/mcd.cpp
+++ b/src/devices/bus/isa/mcd.cpp
@@ -49,6 +49,7 @@ void mcd_isa_device::device_start()
{
cdrom_image_device::device_start();
set_isa_device();
+ m_isa->set_dma_channel(5, this, FALSE);
m_isa->install_device(0x0310, 0x0311, *this, &mcd_isa_device::map, 16);
}
@@ -58,41 +59,91 @@ void mcd_isa_device::device_start()
void mcd_isa_device::device_reset()
{
- m_data = false;
- m_stat = m_cdrom_handle ? STAT_READY : 0;
- m_flag = FLAG_STAT;
- m_rd_count = 0;
+ m_stat = m_cdrom_handle ? STAT_READY | STAT_CHANGE : 0;
+ m_cmdrd_count = 0;
+ m_cmdbuf_count = 0;
m_buf_count = 0;
m_curtoctrk = 1;
m_dma = 0;
m_irq = 0;
+ m_conf = 0;
+ m_dmalen = 2048;
m_locked = false;
+ m_change = true;
+ m_newstat = true;
+ m_data = false;
+}
+
+bool mcd_isa_device::read_sector()
+{
+ if(!m_readcount)
+ {
+ m_isa->drq5_w(CLEAR_LINE);
+ if(m_irq & IRQ_DATACOMP)
+ m_isa->irq5_w(ASSERT_LINE);
+ m_data = false;
+ m_cmdbuf[0] = STAT_SPIN | STAT_READY;
+ m_cmdbuf_count = 1;
+ return false;
+ }
+ UINT32 lba = msf_to_lba(m_readmsf);
+ cdrom_read_data(m_cdrom_handle, lba - 150, m_buf, m_mode & 0x40 ? CD_TRACK_MODE1_RAW : CD_TRACK_MODE1);
+ m_readmsf = lba_to_msf(lba + 1);
+ m_buf_count = m_dmalen + 1;
+ m_buf_idx = 0;
+ m_data = true;
+ m_readcount--;
+ if(m_dma)
+ m_isa->drq5_w(ASSERT_LINE);
+ if(m_irq & IRQ_DATAREADY)
+ m_isa->irq5_w(ASSERT_LINE);
+ return true;
}
READ8_MEMBER(mcd_isa_device::flag_r)
{
- UINT8 ret = m_flag;
- m_flag = 0;
+ UINT8 ret = 0;
+ if(!m_buf_count || !m_data)
+ ret |= FLAG_NODATA;
+ if(m_buf_count == m_dmalen + 1)
+ ret |= FLAG_DATAREADY;
+ if(!m_cmdbuf_count || !m_newstat)
+ ret |= FLAG_NOSTAT; // all command results are status
return ret;
}
READ8_MEMBER(mcd_isa_device::data_r)
{
- if(!m_data)
+ m_isa->irq5_w(CLEAR_LINE);
+ if(m_cmdbuf_count)
{
- if(m_buf_count)
- {
- m_flag = FLAG_DATA;
- m_data = true;
- }
- return m_stat;
+ m_cmdbuf_count--;
+ return m_cmdbuf[m_cmdbuf_idx++];
}
else if(m_buf_count)
{
- UINT8 ret = m_buf[m_buf_idx++];
+ UINT8 ret = m_buf_idx < 2352 ? m_buf[m_buf_idx++] : 0;
m_buf_count--;
- if(m_buf_count)
- m_flag = FLAG_DATA;
+ if(!m_buf_count)
+ read_sector();
+ return ret;
+ }
+ return m_stat;
+}
+
+UINT16 mcd_isa_device::dack16_r(int line)
+{
+ if(m_buf_count & ~1)
+ {
+ UINT16 ret = 0;
+ if(m_buf_idx < 2351)
+ {
+ ret = m_buf[m_buf_idx++];
+ ret |= (m_buf[m_buf_idx++] << 8);
+ }
+ m_buf_count -= 2;
+ if(!m_buf_count)
+ read_sector();
return ret;
}
return 0;
@@ -105,27 +156,34 @@ WRITE8_MEMBER(mcd_isa_device::reset_w)
WRITE8_MEMBER(mcd_isa_device::cmd_w)
{
- if(m_rd_count)
+ if(m_cmdrd_count)
{
- m_rd_count--;
+ m_cmdrd_count--;
switch(m_cmd)
{
case CMD_SET_MODE:
m_mode = data;
- m_buf[0] = 0;
- m_buf_count = 1;
+ m_cmdbuf[1] = 0;
+ m_cmdbuf_count = 2;
break;
case CMD_LOCK:
m_locked = data & 1 ? true : false;
- m_buf[0] = 0;
- m_buf[1] = 0;
- m_buf_count = 2;
+ m_cmdbuf[1] = 0;
+ m_cmdbuf[2] = 0;
+ m_cmdbuf_count = 3;
break;
case CMD_CONFIG:
- switch(m_rd_count)
+ switch(m_cmdrd_count)
{
case 1:
+ if(m_conf == 1)
+ {
+ m_dmalen = data << 8;
+ break;
+ }
m_conf = data;
+ if(m_conf == 1)
+ m_cmdrd_count++;
break;
case 0:
switch(m_conf)
@@ -133,50 +191,69 @@ WRITE8_MEMBER(mcd_isa_device::cmd_w)
case 0x10:
m_irq = data;
break;
+ case 0x01:
+ m_dmalen |= data;
+ break;
case 0x02:
m_dma = data;
break;
}
- m_buf[0] = 0;
- m_buf_count = 1;
+ m_cmdbuf[1] = 0;
+ m_cmdbuf_count = 2;
+ m_conf = 0;
break;
}
+ break;
+ case CMD_READ1X:
+ case CMD_READ2X:
+ switch(m_cmdrd_count)
+ {
+ case 5:
+ m_readmsf = 0;
+ case 4:
+ case 3:
+ m_readmsf |= bcd_2_dec(data) << ((m_cmdrd_count - 3) * 8);
+ break;
+ case 0:
+ m_readcount = data + 1;
+ read_sector();
+ m_cmdbuf_count = 1;
+ m_cmdbuf[0] = STAT_SPIN | STAT_READY;
+ break;
+ }
+ break;
}
- if(!m_rd_count)
- {
- m_data = false;
- m_flag = FLAG_STAT;
- m_stat = m_cdrom_handle ? STAT_READY : 0;
- }
+ if(!m_cmdrd_count)
+ m_stat = m_cdrom_handle ? (STAT_READY | (m_change ? STAT_CHANGE : 0)) : 0;
return;
}
m_cmd = data;
- m_buf_idx = 0;
- m_rd_count = 0;
- m_buf_count = 0;
- m_stat = m_cdrom_handle ? STAT_READY : 0;
+ m_cmdbuf_idx = 0;
+ m_cmdrd_count = 0;
+ m_cmdbuf_count = 1;
+ m_cmdbuf[0] = m_cdrom_handle ? (STAT_READY | (m_change ? STAT_CHANGE : 0)) : 0;
+ m_data = false;
switch(data)
{
case CMD_GET_INFO:
if(m_cdrom_handle)
{
UINT32 first = lba_to_msf(150), last = lba_to_msf(cdrom_get_track_start(m_cdrom_handle, 0xaa));
- m_buf[0] = 1;
- m_buf[1] = dec_2_bcd(cdrom_get_last_track(m_cdrom_handle));
- m_buf[2] = dec_2_bcd((first >> 16) & 0xff);
- m_buf[3] = dec_2_bcd((first >> 8) & 0xff);
- m_buf[4] = dec_2_bcd(first & 0xff);
- m_buf[5] = dec_2_bcd((last >> 16) & 0xff);
- m_buf[6] = dec_2_bcd((last >> 8) & 0xff);
- m_buf[7] = dec_2_bcd(last & 0xff);
- m_buf[8] = 0;
- m_buf_count = 9;
+ m_cmdbuf[1] = 1;
+ m_cmdbuf[2] = dec_2_bcd(cdrom_get_last_track(m_cdrom_handle));
+ m_cmdbuf[3] = dec_2_bcd((last >> 16) & 0xff);
+ m_cmdbuf[4] = dec_2_bcd((last >> 8) & 0xff);
+ m_cmdbuf[5] = dec_2_bcd(last & 0xff);
+ m_cmdbuf[6] = dec_2_bcd((first >> 16) & 0xff);
+ m_cmdbuf[7] = dec_2_bcd((first >> 8) & 0xff);
+ m_cmdbuf[8] = dec_2_bcd(first & 0xff);
+ m_cmdbuf[9] = 0;
+ m_cmdbuf_count = 10;
}
else
{
- m_buf_count = 1;
- m_buf[0] = 0;
- m_stat = STAT_CMD_CHECK;
+ m_cmdbuf_count = 1;
+ m_cmdbuf[0] = STAT_CMD_CHECK;
}
break;
case CMD_GET_Q:
@@ -185,29 +262,31 @@ WRITE8_MEMBER(mcd_isa_device::cmd_w)
int tracks = cdrom_get_last_track(m_cdrom_handle);
UINT32 start = lba_to_msf(cdrom_get_track_start(m_cdrom_handle, m_curtoctrk));
UINT32 end = lba_to_msf(cdrom_get_track_start(m_cdrom_handle, m_curtoctrk < tracks ? m_curtoctrk + 1 : 0xaa));
- m_buf[0] = 1; // track type?
- m_buf[1] = 0; // track num except when reading toc
- m_buf[2] = dec_2_bcd(m_curtoctrk); // index
- m_buf[3] = dec_2_bcd((start >> 16) & 0xff);
- m_buf[4] = dec_2_bcd((start >> 8) & 0xff);
- m_buf[5] = dec_2_bcd(start & 0xff);
- m_buf[6] = 0;
- m_buf[7] = dec_2_bcd((end >> 16) & 0xff);
- m_buf[8] = dec_2_bcd((end >> 8) & 0xff);
- m_buf[9] = dec_2_bcd(end & 0xff);
+ m_cmdbuf[1] = (cdrom_get_adr_control(m_cdrom_handle, m_curtoctrk) << 4) & 0xf0;
+ m_cmdbuf[2] = 0; // track num except when reading toc
+ m_cmdbuf[3] = dec_2_bcd(m_curtoctrk); // index
+ m_cmdbuf[4] = dec_2_bcd((start >> 16) & 0xff);
+ m_cmdbuf[5] = dec_2_bcd((start >> 8) & 0xff);
+ m_cmdbuf[6] = dec_2_bcd(start & 0xff);
+ m_cmdbuf[7] = 0;
+ m_cmdbuf[8] = dec_2_bcd((end >> 16) & 0xff);
+ m_cmdbuf[9] = dec_2_bcd((end >> 8) & 0xff);
+ m_cmdbuf[10] = dec_2_bcd(end & 0xff);
if(m_curtoctrk >= tracks)
m_curtoctrk = 1;
- m_buf_count = 10;
+ m_cmdbuf_count = 11;
}
else
- m_stat = STAT_CMD_CHECK;
+ {
+ m_cmdbuf_count = 1;
+ m_cmdbuf[0] = STAT_CMD_CHECK;
+ }
break;
case CMD_GET_STAT:
- m_buf[0] = m_stat;
- m_buf_count = 1;
+ m_change = false;
break;
case CMD_SET_MODE:
- m_rd_count = 1;
+ m_cmdrd_count = 1;
break;
case CMD_STOPCDDA:
case CMD_STOP:
@@ -215,32 +294,34 @@ WRITE8_MEMBER(mcd_isa_device::cmd_w)
m_curtoctrk = 1;
break;
case CMD_CONFIG:
- m_rd_count = 2;
- break;
- case CMD_READ:
- m_drvmode = DRV_MODE_READ;
+ m_cmdrd_count = 2;
break;
- case CMD_READCDDA:
- m_drvmode = DRV_MODE_CDDA;
+ case CMD_READ1X:
+ case CMD_READ2X:
+ if(m_cdrom_handle)
+ {
+ m_drvmode = DRV_MODE_READ;
+ m_cmdrd_count = 6;
+ }
+ else
+ {
+ m_cmdbuf_count = 1;
+ m_cmdbuf[0] = STAT_CMD_CHECK;
+ }
break;
case CMD_GET_VER:
- m_buf[0] = 1; // ?
- m_buf[1] = 'D';
- m_buf[2] = 0;
- m_buf_count = 3;
+ m_cmdbuf[1] = 1; // ?
+ m_cmdbuf[2] = 'D';
+ m_cmdbuf[3] = 0;
+ m_cmdbuf_count = 4;
break;
case CMD_EJECT:
break;
case CMD_LOCK:
- m_rd_count = 1;
+ m_cmdrd_count = 1;
break;
default:
- m_stat |= STAT_CMD_CHECK;
+ m_cmdbuf[0] = m_stat | STAT_CMD_CHECK;
break;
}
- if(!m_rd_count)
- {
- m_data = false;
- m_flag = FLAG_STAT;
- }
}
diff --git a/src/devices/bus/isa/mcd.h b/src/devices/bus/isa/mcd.h
index a7d0fb3e313..aae4d3b638c 100644
--- a/src/devices/bus/isa/mcd.h
+++ b/src/devices/bus/isa/mcd.h
@@ -31,23 +31,33 @@ public:
DECLARE_READ8_MEMBER(flag_r);
DECLARE_WRITE8_MEMBER(cmd_w);
DECLARE_WRITE8_MEMBER(reset_w);
+ virtual UINT16 dack16_r(int line) override;
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
private:
+ bool read_sector();
+
+ bool m_change;
+ bool m_newstat;
bool m_data;
UINT8 m_stat;
- UINT8 m_flag;
- UINT8 m_buf[2048];
+ UINT8 m_buf[2352];
int m_buf_count;
int m_buf_idx;
- int m_rd_count;
+ UINT8 m_cmdbuf[16];
+ int m_cmdbuf_count;
+ int m_cmdrd_count;
+ int m_cmdbuf_idx;
UINT8 m_mode;
UINT8 m_cmd;
UINT8 m_conf;
UINT8 m_irq;
UINT8 m_dma;
+ UINT16 m_dmalen;
+ UINT32 m_readmsf;
+ UINT8 m_readcount;
bool m_locked;
int m_drvmode;
int m_curtoctrk;
@@ -70,8 +80,8 @@ private:
CMD_STOPCDDA = 0x70,
CMD_CONFIG = 0x90,
CMD_SET_VOL = 0xae,
- CMD_READ = 0xc0,
- CMD_READCDDA = 0xc1,
+ CMD_READ1X = 0xc0,
+ CMD_READ2X = 0xc1,
CMD_GET_VER = 0xdc,
CMD_STOP = 0xf0,
CMD_EJECT = 0xf6,
@@ -90,10 +100,16 @@ private:
DRV_MODE_CDDA
};
enum {
- FLAG_DATA = 2,
- FLAG_STAT = 4,
+ FLAG_NODATA = 2,
+ FLAG_NOSTAT = 4,
+ FLAG_DATAREADY = 8, //??
FLAG_OPEN = 16
};
+ enum {
+ IRQ_DATAREADY = 1,
+ IRQ_DATACOMP = 2,
+ IRQ_ERROR = 4
+ };
};
diff --git a/src/mame/drivers/rainbow.cpp b/src/mame/drivers/rainbow.cpp
index de3c7e9ea08..0c625e9d948 100644
--- a/src/mame/drivers/rainbow.cpp
+++ b/src/mame/drivers/rainbow.cpp
@@ -1,3 +1,74 @@
+// Define suppresses costly smooth scroll / updates when debugging:
+// ENABLE BY UNCOMMENTING. ADDITIONALLY, SET SMOOTH SCROLL IN EMULATION (DISABLE BY SETTING JUMP SCROLL. To enter SETUP hit ScrollLock)-
+//#define BOOST_DEBUG_PERFORMANCE
+
+
+/* NEW COLOR EMULATION (state as of Oct. 1st 2016):
+
+//-------------------- Differences to VT240: ---------------------------------------------------
+// - Registers of graphics option not directly mapped (indirect access via mode register)
+// - write mask is 16 bits wide (not only 8)
+// - scroll register is 8 bits wide - not 16. Probably also different semantics (see UNTESTED *)
+// - There appears to be NO "DMA scroll mode" and no "line erase mode" (so code sections were deleted). Really?
+
+// Two modes: highres and medres mode (different bank length..?)
+// - MEDRES: palette of 16 colors out of 4096. 384 x 240
+// - HIGRES: palette of 4 colors out of 4096. 800 x 240
+// Palette takes 2 byte per palette entry. CLUT ("color map") is 32 byte long.
+------------------------------------------------------------------------------------------------
+
+SCREEN 1 vs. SCREEN 2 IN EMULATION
+// All GDC 7220 output is displayed on the right. Be it color or monochrome, Option Graphics output is on screen 2.
+// If you select MONO_MONITOR via DIP, output from GDC will appear on screen 2 in 16 shades of grey.
+// The type of monochrome monitor (VR-210 A, B or C) is selectable via another DIP (coarsly simulates a phosphor color).
+
+THE DEC 'R-M-B' COLOR CABLE VS. THE UNOFFICIAL 'R-G-B' MODE (A BIT OF HISTORY)
+// VR-241 came with a standard DEC "color cable", where the green gun is wired to the mono output (DIP switch COLOR_MONITOR).
+// Port $0A decides whether the mono out pin on the back of the Rainbow holds graphics signals or simple text.
+//
+// An unofficial DIY cable gave R-G-B graphics plus seperate text (emulated by DIP setting: DUAL MONITOR).
+// Unfortunately, popular programs like AutoCAD and GWBASIC were initially written for 1 single VR201 or VT241 monitor.
+// A 'R-M-B' cable is expected, and thus writes go to M(ono) instead of G(reen). An awful tint results on R-G-B.
+
+// DEC decided not to support this mode. Nevertheless, AutoCad 2.6 offers a true dual monitor mode.
+// A patch from one of the archives corrects the GWBASIC palette problem when using 2 monitors [Bavarese].
+
+EMULATION SPECIFIC
+// A log message informs the user if text output is disabled. Means: software is not ready / patched for dual monitor use.
+// In our emulation, DUAL MONITOR enables both screens, even if onboard graphics has been accidently shut off
+// (helps debugging semi broken programs, try Doodle).
+
+BUGS
+- HIRES-MODE WRONG. MEDRES SEMI-CORRECT.
+BROKEN SPRITES / NO BORDER GRAPHICS IN "PACMAN" (freeware clone; MEDRES; borders probably drawn in vector mode)
+
+- VECTOR MODE SEEMS TO DISPLAY NOTHING AT ALL (16 bit access botched?)
+- CLEARING THE SCREEN DOES NOT WORK (bug in VRAM_W...?)
+
+UNIMPLEMENTED:
+// - Video levels for color modes.
+// - Rainbow 100 A palette quirks (2 bit palette... in MEDRES only...?)
+
+UNKNOWN IMPLEMENTATION DETAILS:
+// a. READBACK (hard copy programs like JOBSDUMP definitely use it. See also GDC diagnostics). VRAM_R ?
+
+// b. SCROLL BUFFER initialization (details) unclear. What happens when a programs does not write all 256 bytes? Value of uninitialized areas?
+ Play, then retry (y) SCRAM to see the effect. Scram doesn't seem to write all (256) bytes, a GDC RESET is only executed at startup...
+ (PAGE 48 OF PDF HAS A SUPERFICIAL DESCRIPTION OF THE SCROLL BUFFER)
+
+// c. UNVERIFIED XTAL / CLOCK:
+// There is a 31.188 Mhz crystal in DUELL's hand written Option Graphics circuit (31.188 possibly measured, as it cannot be found in XTAL).
+// According to the datasheet, the NEC 7220 was certified for 4.0 , 5.0, and 5.5 Mhz and the 7220A for 6.0, 7.0, and 8.0 Mhz
+
+// d. UPD7220 oddities: * refresh rate much too fast at 32Mhz/4 (Upd7220 LOG says 492 Mhz?!).
+// * 7220 pixel stretch / visible area looks odd (pixels stretched out too wide at 384 x 240. Compare the real SCRAM screenshot online)
+
+// e. FIXME (MAME/MESS): what happens when the left screen is at 50 Hz and the right at 60 Hz?
+// According to Haze: "if you have 2 screens running at different refresh rates one of them won't update properly
+// (the partial update system gets very confused because it expects both the screens to end at the same time
+// and if that isn't the case large parts of one screen end up not updating at all)
+*/
+
// license:GPL-2.0+
// copyright-holders:Miodrag Milanovic,Karl-Ludwig Deisenhofer
/***************************************************************************************************
@@ -10,7 +81,7 @@ Portions (2013 - 2016) by Karl-Ludwig Deisenhofer (Floppy, ClikClok RTC, NVRAM,
To unlock floppy drives A-D compile with WORKAROUND_RAINBOW_B (prevents a side effect of ERROR 13).
Native single sided 5.25" images with 80 tracks, 10 sectors are well tested (*.IMD / *.TD0=TeleDisk / *.IMG with 400 K).
-IMG files of DOS 180K, 360 K and VT180 disks are largely untested (note that VT disks must be mounted "read only").
+IMG files of DOS 180K, 360 K and VT180 disks are essentially untested (note that VT disks must be mounted "read only").
To read a 40 track, PC-DOS formatted 5.25" image (*.TD0 preferred) mounted on drive slot 3 add:
DEVICE=A:\idrive5.sys
@@ -81,15 +152,7 @@ SH 2 SHMUX 88 ENB -> Pin 3 (A2) shared memory
SH2 DO REFRESH H -> Pin 2 (A1) indicates that extended memory must be refreshed -> on J6 as (L)
SH10 BDL REQ (L) -> Pin 1 (A0) BUNDLE OPTION wishes to use shared memory
-
HARDWARE UPGRADES WORTH EMULATING (should be implemented as SLOT DEVICES):
-* Color graphics option (uses NEC upd7220 GDC). REFERENCE: Programmer's Reference: AA-AE36A-TV.
-Either 240 X 380 x 16 or 240 x 800 x 4 colors (out of 4096). 8 x 64 K video RAM.
-On a 100-A, pallette limited to 4 shades (LSB 2 bits; applies to medium resolution mode 240 X 380 pixels only).
-Graphics output independent from monochrome output. Single and dual monitor configurations possible.
-
-NOTE: there is a DIP switch for COLOR GRAPHICS which affects "system_parameter_r" only (and is disabled).
-
* Extended communication option (occupies BUNDLE_OPTION 1 + 2) REFERENCE: AA-V172A-TV + Addendum AV-Y890A-TV.
Two ports, a high-speed RS-422 half-duplex interface (port A) + lower-speed RS-423 full/half-duplex interface
with modem control (port B). A 5 Mhz. 8237 DMA controller transfers data into and out of shared memory (not: optional RAM).
@@ -99,8 +162,10 @@ Can't be added if RD51 hard disk controller present (J4 + J5). For programming i
* ( NO DUMP YET ) PC CHARACTER SET (Suitable Solutions?). Supported by IBM PC software emulator named CodeBlue (see 3.1 patch)
-* ( NO DUMP YET ) TECHNICAL CHARACTER SET (TCS; '$95 from DEC, for Rainbow 100, 100B, 100+ ; separate docs available')
-Source: price list of a DEC reseller. Possibly identical to http://vt100.net/charsets/technical.html
+* ( NO DUMP YET ) TECHNICAL CHARACTER SET (TCS; available for Rainbow 100, 100B, 100+; $95 from DEC)
+Source: price list of a DEC reseller.
+Contains 94 graphic characters from $A1 - $FE, including symbols and characters used in technical applications,
+ see http://support.attachmate.com/techdocs/1184.html and http://vt100.net/charsets/technical.html
* 8087 Numerical Data Coprocessor daughterboard. REFERENCE: EK-PCNDP-IN-PRE
Daughterboard, to be plugged into the expansion port where the memory expansion card usually sits (J6).
@@ -208,7 +273,7 @@ DIAGNOSTIC-LEDs |J3 | |J2 | |J1 |
| ROM (4K) ...J7... | ...J9 = RX50 |
| |
|-------------PCB# 5416206 / 5016205-01C1-------------|
-
+
CONNECTORS ("J"):
...J5... ...J4... both: RD51 controller (hard disk)
...J5... ...J4... both: EXTENDED COMM. controller
@@ -283,10 +348,54 @@ W17 pulls J1 serial port pin 1 to GND when set (chassis to logical GND).
#define MHFU_RESET -250
// ----------------------------------------------------------------------------------------------
+// NEC 7220 GDC ***************** GDC-NEW ********************
+
+// Indirect Register, port $53, see page 181 of AA-AE36A (PDF):
+// (actual values : see comments)
+#define GDC_SELECT_WRITE_BUFFER 0x01 // 0xFE
+#define GDC_SELECT_PATTERN_MULTIPLIER 0x02 // 0xFD
+#define GDC_SELECT_PATTERN 0x04 // 0xFB
+#define GDC_SELECT_FG_BG 0x08 // 0xF7
+#define GDC_SELECT_ALU_PS 0x10 // 0xEF
+#define GDC_SELECT_COLOR_MAP 0x20 // 0xDF
+#define GDC_SELECT_MODE_REGISTER 0x40 // 0xBF
+#define GDC_SELECT_SCROLL_MAP 0x80 // 0x7F
+
+// MODE REGISTER
+#define GDC_MODE_HIGHRES 0x01
+#define GDC_MODE_VECTOR 0x02
+
+// ( " ) READBACK OPERATION (if ENABLE_WRITES = 0):
+#define GDC_MODE_ENABLE_WRITES 0x10
+#define GDC_MODE_READONLY_SCROLL_MAP 0x20
+
+// ( " ) READBACK OPERATION (plane select = bit mask in bits 2 + 3 of MODE register):
+#define GDC_MODE_READBACK_PLANE_MASK 12
+#define GDC_MODE_READBACK_PLANE_00 0x00
+#define GDC_MODE_READBACK_PLANE_01 0x04
+#define GDC_MODE_READBACK_PLANE_02 0x08
+#define GDC_MODE_READBACK_PLANE_03 0x0c
+
+#define GDC_MODE_ENABLE_VSYNC_IRQ 0x40
+#define GDC_MODE_ENABLE_VIDEO 0x80
+
+// ALU_PS REGISTER (bits 5 + 4):
+#define ALU_PS_MODE_MASK 48
+#define REPLACE_MODE 00
+#define COMPLEMENT_MODE 16
+#define OVERLAY_MODE 32
+
+// MONITOR CONFIGURATION (DIP SWITCH!):
+#define MONO_MONITOR 0x01
+#define COLOR_MONITOR 0x02
+#define DUAL_MONITOR 0x03
+
+// ----------------------------------------------------------------------------------------------
#include "emu.h"
#include "cpu/i86/i86.h"
#include "cpu/z80/z80.h"
#include "video/vtvideo.h"
+#include "video/upd7220.h"
#include "machine/wd_fdc.h"
#include "formats/rx50_dsk.h"
@@ -331,12 +440,14 @@ public:
m_inp6(*this, "FLOPPY CONTROLLER"), // DO NOT CHANGE ORDER
m_inp7(*this, "GRAPHICS OPTION"), // DO NOT CHANGE ORDER
m_inp8(*this, "MEMORY PRESENT"), // DO NOT CHANGE ORDER
- m_inp9(*this, "MONITOR TYPE"),
+ m_inp9(*this, "MONO MONITOR TYPE"),
m_inp10(*this, "J17"),
m_inp11(*this, "CLIKCLOK"),
m_inp12(*this, "WATCHDOG"),
+ m_inp13(*this, "MONITOR CONFIGURATION"),
m_crtc(*this, "vt100_video"),
+
m_i8088(*this, "maincpu"),
m_z80(*this, "subcpu"),
@@ -345,8 +456,10 @@ public:
m_mpsc(*this, "upd7201"),
m_dbrg(*this, "com8116"),
+
m_kbd8251(*this, "kbdser"),
m_lk201(*this, LK201_TAG),
+
m_p_ram(*this, "p_ram"),
m_p_vol_ram(*this, "vol_ram"),
@@ -354,7 +467,12 @@ public:
m_shared(*this, "sh_ram"),
- m_rtc(*this, "rtc")
+ m_rtc(*this, "rtc"),
+ m_hgdc(*this, "upd7220"), // GDC-NEW
+
+ m_screen2(*this, "screen2"),
+ m_palette2(*this, "palette2"), // GDC-NEW
+ m_video_ram(*this, "vram")
{
}
@@ -423,6 +541,8 @@ public:
DECLARE_WRITE_LINE_MEMBER( com8116_a_fr_w );
DECLARE_WRITE_LINE_MEMBER( com8116_a_ft_w );
+ DECLARE_WRITE8_MEMBER(GDC_EXTRA_REGISTER_w);
+
UINT32 screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(vblank_irq);
IRQ_CALLBACK_MEMBER(irq_callback);
@@ -431,10 +551,16 @@ public:
TIMER_DEVICE_CALLBACK_MEMBER(motor_tick);
DECLARE_FLOPPY_FORMATS(floppy_formats);
+
+ UPD7220_DISPLAY_PIXELS_MEMBER( hgdc_display_pixels );
+ DECLARE_READ16_MEMBER(vram_r);
+ DECLARE_WRITE16_MEMBER(vram_w);
+ DECLARE_WRITE_LINE_MEMBER(GDC_vblank_irq);
+
protected:
virtual void machine_start() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
+
private:
enum
{ // LOWEST PRIORITY
@@ -463,6 +589,7 @@ private:
required_ioport m_inp10;
required_ioport m_inp11;
required_ioport m_inp12;
+ required_ioport m_inp13;
required_device<rainbow_video_device> m_crtc;
required_device<cpu_device> m_i8088;
required_device<cpu_device> m_z80;
@@ -480,6 +607,11 @@ private:
required_shared_ptr<UINT8> m_shared;
optional_device<ds1315_device> m_rtc;
+
+ required_device<upd7220_device> m_hgdc; // GDC-NEW
+ required_device<screen_device> m_screen2;
+ required_device<palette_device> m_palette2;
+ required_shared_ptr<UINT16> m_video_ram;
void raise_8088_irq(int ref);
void lower_8088_irq(int ref);
@@ -495,6 +627,19 @@ private:
hard_disk_file *rainbow_hdc_file(int ref);
+ UINT8 m_GDC_WRITE_BUFFER[16]; // 16 x 8 bits for CPU, 8 x 16 for GDC
+ UINT8 m_GDC_COLOR_MAP[32];
+ UINT8 m_GDC_SCROLL_BUFFER_PRELOAD[256];
+ UINT8 m_GDC_SCROLL_BUFFER[256];
+
+ UINT8 m_GDC_INDIRECT_REGISTER, m_GDC_MODE_REGISTER, m_GDC_scroll_index, m_GDC_color_map_index, m_GDC_write_buffer_index;
+ UINT8 m_GDC_ALU_PS_REGISTER, m_GDC_FG_BG;
+ UINT8 m_vpat, m_patmult, m_patcnt, m_patidx;
+
+ UINT16 m_GDC_WRITE_MASK;
+ bool m_scroll_buffer_changed, m_color_map_changed;
+ bool m_ONBOARD_GRAPHICS_SELECTED; // (internal switch, on board video to mono out)
+
bool m_SCREEN_BLANK;
int INT88, INTZ80;
@@ -528,7 +673,6 @@ private:
bool m_hdc_index_latch;
bool m_hdc_step_latch;
int m_hdc_direction;
- bool m_hdc_track0;
bool m_hdc_write_gate;
bool m_hdc_drive_ready;
@@ -540,7 +684,85 @@ private:
emu_timer *cmd_timer;
const int vectors[9] = { 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x02 };
-};
+};
+
+
+// GDC RESET MACRO - used in "machine_reset" & GDC_EXTRA_REGISTER_w !
+#define GDC_RESET_MACRO \
+m_GDC_INDIRECT_REGISTER = 0; \
+m_GDC_MODE_REGISTER = 0; \
+m_GDC_WRITE_MASK = 0; \
+m_GDC_write_buffer_index = 0; \
+m_GDC_scroll_index = 0; \
+m_GDC_color_map_index = 0; \
+m_GDC_ALU_PS_REGISTER = 0; \
+m_vpat = 0; \
+m_patmult = 0; \
+m_patcnt = 0; \
+m_patidx = 7; \
+m_GDC_FG_BG = 0; \
+m_color_map_changed = true; \
+for(int i=0; i <256; i++) { m_GDC_SCROLL_BUFFER[i] = m_GDC_SCROLL_BUFFER_PRELOAD[i] = i; };\
+m_scroll_buffer_changed = true; \
+printf("\n** NEC 7220 GDC RESET **\n");
+
+UPD7220_DISPLAY_PIXELS_MEMBER( rainbow_state::hgdc_display_pixels )
+{
+#ifdef BOOST_DEBUG_PERFORMANCE
+ UINT8 *ram = memregion("maincpu")->base();
+ if( !(m_p_vol_ram[0x84] == 0x00) )
+ {
+ if( (MOTOR_DISABLE_counter) || (ram[0xEFFFE] & 16) ) // if HDD/FDD ACTIVITY -OR- SMOOTH SCROLL IN PROGRESS
+ return;
+ }
+#endif
+
+ const rgb_t *paletteX = m_palette2->palette()->entry_list_raw();
+
+ int xi;
+ UINT16 plane0, plane1, plane2, plane3;
+ UINT8 pen;
+
+ if(!(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_VIDEO))
+ return; // no output from graphics option
+
+ // ********************* GET BITMAP DATA FOR 4 PLANES ***************************************
+ // _READ_ BIT MAP from 2 or 4 planes (plane 0 is least, plane 3 most significant). See page 42 / 43
+ if(m_GDC_MODE_REGISTER & GDC_MODE_HIGHRES)
+ {
+ // HIGH RES (2 planes, 2 color bits, 4 color map entries / 4 MONOCHROME SHADES)
+ // MANUAL: (GDC "sees" 2 planes X 16 bits X 16K words)!
+
+ // !!! m_video_ram is defined as UINT16 !!!
+ plane0 = m_video_ram[ ((address & 0x7fff) + 0x00000) >> 1 ]; // Video Ram is defined as LITTLE_ENDIAN, 16 (?):
+ plane1 = m_video_ram[ ((address & 0x7fff) + 0x20000) >> 1 ]; // 8 x 32 K is 0x40000, see page 16
+ plane2 = 0;
+ plane3 = 0;
+ }
+ else
+ {
+ // MED.RESOLUTION (4 planes, 4 color bits, 16 color map entries / 16 (4) MONOCHROME SHADES)
+ // MANUAL SAYS: (GDC "sees" 4 planes X 16 bits X 8K words)!
+ plane0 = m_video_ram[((address & 0x3fff) + 0x00000) >> 1];
+ plane1 = m_video_ram[((address & 0x3fff) + 0x10000) >> 1]; // 8 x 16 K is 0x20000, see page 16 // OLD: 0x10000
+ plane2 = m_video_ram[((address & 0x3fff) + 0x20000) >> 1]; // OLD: 0x20000
+ plane3 = m_video_ram[((address & 0x3fff) + 0x30000) >> 1]; // OLD: 0x30000
+ }
+ // ********************* GET BITMAP DATA per PLANE ***************************************
+
+ bool mono = (m_inp13->read() == MONO_MONITOR) ? true : false; // 1 = MONO, 2 = COLOR, 3 = DUAL MONITOR
+
+ for(xi=0;xi<16;xi++)
+ {
+ pen = BIT(plane0 , xi) |
+ ( BIT(plane1 , xi) << 1 ) |
+ ( BIT(plane2 , xi) << 2 ) |
+ ( BIT(plane3 , xi) << 3 );
+
+ if (bitmap.cliprect().contains(x + xi, y))
+ bitmap.pix32(y, x + xi) = paletteX[mono ? (pen + 16) : pen];
+ }
+}
FLOPPY_FORMATS_MEMBER(rainbow_state::floppy_formats)
FLOPPY_RX50IMG_FORMAT,
@@ -552,6 +774,7 @@ FLOPPY_FORMATS_END
static SLOT_INTERFACE_START(rainbow_floppies)
SLOT_INTERFACE("525qd0", FLOPPY_525_QD) // QD means 80 tracks with DD data rate (single or double sided).
SLOT_INTERFACE("525qd1", FLOPPY_525_QD)
+//SLOT_INTERFACE("525sd", FLOPPY_525_SD) // mimic a 5.25 DEC Robin (40 track SINGLE SIDED drive). BIOS DETECTED?
SLOT_INTERFACE("525dd", FLOPPY_525_DD) // mimic a 5.25" PC (40 track) drive. Requires IDrive5.SYS.
SLOT_INTERFACE("35dd", FLOPPY_35_DD) // mimic 3.5" PC drive (720K, double density). Use Impdrv3.SYS.
SLOT_INTERFACE_END
@@ -648,26 +871,21 @@ AM_RANGE(0x11, 0x11) AM_DEVREADWRITE("kbdser", i8251_device, status_r, control_w
// 0x43 PRINTER CONTROL / STATUS REGISTER (MPSC)
// ===========================================================
// 0x50 - 0x57 ***** COLOR GRAPHICS OPTION:
-// 50h Graphics option software reset. Any write to this
-// port also resynchronizes the read/modify/write memory
-// cycles of the Graphics Option to those of the GDC (*)
-// * see boot ROM @1EB4/8
-// 51h Data written to this port is loaded into the area
-// selected by the previous write to port 53h.
-// 52h Data written to this port is loaded into the Write Buffer.
+// * Color graphics option (uses NEC upd7220 GDC). REFERENCE: Programmer's Reference: AA-AE36A-TV.
+// Either 384 x 240 x 16 or 800 x 240 x 4 colors (out of 4096). 8 x 64 K video RAM.
-// 53h Data written to this port provides address selection
-// for indirect addressing (see Indirect Register).
+// Color graphics independent from text output if 8088 port $0a (bit 2) is zero.
-// 54h Data written to this port is loaded into the low-order
-// byte of the Write Mask.
+// This driver offers a DIP switch to enable or disable COLOR GRAPHICS altogether (affects "system_parameter_r" ...)
-// 55h Data written to this port is loaded into the high-order
-// byte of the Write Mask.
+// EXTRA HARDWARE (Write Buffer, Pattern Register/Multiplier, ALU/PS, Color Map, readback and offset/scroll hardware):
+AM_RANGE(0x50, 0x55) AM_WRITE(GDC_EXTRA_REGISTER_w)
+
+// 56h Data written is loaded into the GDC's FIFO and flagged as a parameter.
+// 57h Data written is loaded into the GDC's FIFO and flagged as a command.
+AM_RANGE (0x56, 0x57) AM_DEVREADWRITE("upd7220", upd7220_device, read, write) // GDC-NEW
-// 56h Data written to this port is loaded into the GDC's FIFO
-// Buffer and flagged as a parameter.
// ===========================================================
// 0x60 -> 0x6f ***** EXTENDED COMM. OPTION / Option Select 2.
// ===========================================================
@@ -739,11 +957,11 @@ ADDRESS_MAP_END
/* DIP switches */
static INPUT_PORTS_START(rainbow100b_in)
-PORT_START("MONITOR TYPE")
-PORT_DIPNAME(0x03, 0x03, "MONOCHROME MONITOR")
-PORT_DIPSETTING(0x01, "WHITE")
-PORT_DIPSETTING(0x02, "GREEN")
-PORT_DIPSETTING(0x03, "AMBER")
+PORT_START("MONO MONITOR TYPE")
+PORT_DIPNAME(0x03, 0x03, "MONO MONITOR TYPE")
+PORT_DIPSETTING(0x01, "WHITE (VR201-A)")
+PORT_DIPSETTING(0x02, "GREEN (VR201-B)")
+PORT_DIPSETTING(0x03, "AMBER (VR201-C)")
// MEMORY, FLOPPY, BUNDLE, GRAPHICS affect 'system_parameter_r':
PORT_START("MEMORY PRESENT")
@@ -778,8 +996,8 @@ PORT_DIPNAME(0x01, 0x00, "REAL TIME CLOCK (CLIKCLOK)") PORT_TOGGLE
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x01, DEF_STR(On))
-PORT_START("GRAPHICS OPTION") // NEC COLOR GRAPHICS not implemented yet
-PORT_DIPNAME(0x00, 0x00, "GRAPHICS OPTION") PORT_TOGGLE
+PORT_START("GRAPHICS OPTION") // GDC-NEW
+PORT_DIPNAME(0x01, 0x00, "GRAPHICS OPTION") PORT_TOGGLE
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x01, DEF_STR(On))
@@ -815,8 +1033,13 @@ PORT_DIPNAME(0x01, 0x00, "WATCHDOG ENABLED (MHFU)") PORT_TOGGLE
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x01, DEF_STR(On))
+PORT_START("MONITOR CONFIGURATION") // GDC-NEW
+PORT_DIPNAME(0x03, 0x03, "MONITOR CONFIGURATION")
+PORT_DIPSETTING(0x01, "MONO ONLY (SCREEN 2: 16 monochrome shades)")
+PORT_DIPSETTING(0x02, "COLOR ONLY (SCREEN 2: R-G-B; mono -> green)")
+PORT_DIPSETTING(0x03, "DUAL MONITOR (SCREEN 1: TEXT; SCREEN 2: R-G-B)")
INPUT_PORTS_END
-
+
void rainbow_state::machine_reset()
{
// Configure RAM
@@ -898,13 +1121,17 @@ void rainbow_state::machine_reset()
}
}
- // *********** FLOPPY DISK CONTROLLER
+ // *********** FLOPPY DISK CONTROLLER [ NOT OPTIONAL ]
m_unit = INVALID_DRIVE;
m_fdc->reset();
m_fdc->set_floppy(nullptr);
m_fdc->dden_w(0);
+ // *********** NEC 7220 DISPLAY CONTROLLER [ OPTIONAL ]
+ GDC_RESET_MACRO
+
// *********** Z80
+
m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
m_z80_halted = true;
@@ -969,16 +1196,46 @@ void rainbow_state::device_timer(emu_timer &timer, device_timer_id tid, int para
UINT32 rainbow_state::screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
- m_crtc->palette_select(m_inp9->read());
+ static int old_palette, old_monitor;
+
+#ifdef BOOST_DEBUG_PERFORMANCE
+ UINT8 *ram = memregion("maincpu")->base();
+ if( !(m_p_vol_ram[0x84] == 0x00) )
+ {
+ if( (MOTOR_DISABLE_counter) || (ram[0xEFFFE] & 16) ) // if HDD/FDD ACTIVITY -OR- SMOOTH SCROLL IN PROGRESS
+ return 0;
+ }
+#endif
- if (m_SCREEN_BLANK)
+ int monitor_selected = m_inp13->read();
+ if(monitor_selected != old_monitor)
+ {
+ old_monitor = monitor_selected;
+ m_color_map_changed = true;
+ }
+
+ int palette_selected = m_inp9->read();
+ if(palette_selected != old_palette)
+ {
+ old_palette = palette_selected;
+ m_color_map_changed = true;
+ }
+
+ m_crtc->palette_select(palette_selected);
+
+ // GDC-NEW
+ // NEC 7220 output (MONO or COLOR) can only be shown on the RIGHT hand side,
+ // so disable TEXT out if 'dual monitor' is unselected.
+ // BLANK SCREEN : ONLY IF 1) graphics option output selected AND 2) no multi monitor setup selected
+ if( m_SCREEN_BLANK ||
+ ( (!m_ONBOARD_GRAPHICS_SELECTED) && (monitor_selected != 3))
+ )
m_crtc->video_blanking(bitmap, cliprect);
else
m_crtc->video_update(bitmap, cliprect);
return 0;
}
-
// Interrupt handling and arbitration. See 3.1.3.8 OF PC-100 spec.
void rainbow_state::update_8088_irqs()
{
@@ -1150,7 +1407,7 @@ READ8_MEMBER(rainbow_state::rtc_r)
if (m_rtc->chip_enable())
return (m_rtc->read_data(space, 0) & 0x01);
- // (RTC ACTIVATION) READ MAGIC PATTERN 0
+ // (RTC ACTIVATION) READ MAGIC PATTERN 0
case 0x0100: // 0xFC100
case 0x2100: // 0xFE100 (MIRROR)
m_rtc->read_0(space, 0);
@@ -1199,8 +1456,6 @@ void rainbow_state::hdc_reset()
m_hdc_step_latch = false;
m_hdc_index_latch = false;
-
- m_hdc_track0 = true; // set true to avoid stepping
}
// Return 'hard_disk_file' object for harddisk 1 (fixed).
@@ -1277,9 +1532,7 @@ WRITE_LINE_MEMBER(rainbow_state::hdc_read_sector)
if ((state == 0) && (last_state == 1) && (drv == 0))
{
- read_status = 2;
-
-// logerror("\nTRYING TO READ");
+ read_status = 2; // logerror("\nTRYING TO READ");
output().set_value("led1", 0);
int hi = (m_hdc->read(generic_space(), 0x05)) & 0x07;
@@ -1308,10 +1561,7 @@ WRITE_LINE_MEMBER(rainbow_state::hdc_read_sector)
{
read_status = 5;
if (hard_disk_read(local_hard_disk, lbasector, m_hdc_buffer)) // accepts LBA sector (UINT32) !
- {
- read_status = 0;
-// logerror("...success!\n");
- }
+ read_status = 0; // logerror("...success!\n");
}
}
m_hdc_buf_offset = 0;
@@ -1401,7 +1651,6 @@ int rainbow_state::do_write_sector()
if ((info = hard_disk_get_info(local_hard_disk)))
{
feedback = 10;
-// logerror("\n* TRYING TO WRITE * ");
output().set_value("led1", 1); // OFF
UINT8 SDH = (m_hdc->read(generic_space(), 0x06));
@@ -1546,8 +1795,6 @@ WRITE8_MEMBER(rainbow_state::hd_status_68_w)
// 1 : see @ 088D after 'READ_SECTOR_OK'
if (data & 0x01)
{
-// logerror(">> HARD DISC * SET BUFFER READY * <<\n");
-
output().set_value("led1", 0); // 1 = OFF (One of the CPU LEDs as DRIVE LED) = HARD DISK ACTIVITY =
MOTOR_DISABLE_counter = 20;
@@ -1593,10 +1840,7 @@ READ8_MEMBER(rainbow_state::hd_status_69_r)
// External circuit supports 1 drive here (DRIVE 0 selected or deselected)
int DRV = ((m_hdc->read(space, 0x06) >> 3) & 0x01); // 0x03 gives error R6 with DIAG.DISK
if (DRV == 0)
- {
-// logerror("(x69 READ) %i = _DRIVE # 0_ SELECT! \n", DRV);
- data |= 1;
- }
+ data |= 1; // logerror("(x69 READ) %i = _DRIVE # 0_ SELECT! \n", DRV);
if (m_hdc_write_gate) // WRITE GATE (cached here)
data |= 16;
@@ -1607,18 +1851,9 @@ READ8_MEMBER(rainbow_state::hd_status_69_r)
if (m_hdc_drive_ready)
data |= 64;
- m_hdc_track0 = false; // Fake TRACK 0 signal (normally FROM DRIVE)
-
- int stat1 = m_hdc->read(space, 0x04); // CYL LO
- int stat2 = m_hdc->read(space, 0x05); // CYL HI
- if ((stat1 == 0) && (stat2 == 0))
- m_hdc_track0 = true;
-
- if (m_hdc_track0)
- {
- data |= 128;
-// logerror("(x69 READ) TRACK 00 detected\n");
- }
+ // Fake TRACK 0 signal (normally FROM DRIVE)
+ if ((m_hdc->read(space, 0x04) == 0) && (m_hdc->read(space, 0x05) == 0)) // CYL.LO - CYL.HI
+ data |= 128; // logerror("(x69 READ) TRACK 00 detected\n");
return data;
}
@@ -1671,8 +1906,8 @@ void rainbow_state::hdc_buffer_counter_reset()
WRITE_LINE_MEMBER(rainbow_state::hdc_bdrq)
{
static int old_state;
-
// logerror("BDRQ - BUFFER DATA REQUEST OBTAINED: %u\n", state);
+
if ((state == 1) && (old_state == 0))
{
hdc_buffer_counter_reset();
@@ -2037,13 +2272,13 @@ WRITE8_MEMBER(rainbow_state::z80_diskcontrol_w)
int disable_start = 2; // set defaults
bool motor_on = false;
- if (selected_drive < 2)// WAR: (data & 8) // MOTOR 0
+ if (selected_drive < 2)
{
motor_on = true;
data |= 8;
}
- if (selected_drive > 1) // WAR: if (data & 16) // MOTOR 1
+ if (selected_drive > 1)
{
motor_on = true;
data |= 16;
@@ -2084,6 +2319,8 @@ READ8_MEMBER(rainbow_state::read_video_ram_r)
}
+
+
// **************************************************
// VIDEO INTERRUPT HANDLING
// **************************************************
@@ -2106,6 +2343,94 @@ IRQ_CALLBACK_MEMBER(rainbow_state::irq_callback)
return intnum;
}
+// NEC7220 Vsync IRQ ***************************************** GDC-NEW
+
+// VERIFY: SCROLL_MAP & COLOR_MAP are updated at the next VSYNC (not immediately)... Are there more registers?
+WRITE_LINE_MEMBER(rainbow_state::GDC_vblank_irq)
+{
+ UINT8 red, green, blue, mono;
+ int xi;
+
+ // VIDEO LEVELS: 0 is 100 % output; F is 0 % output
+ // Levels for 100-B model, taken from page 46 of PDF, multiplied by 2.55 to obtain a range of 0...255
+ const int v_levels[16] = { 255, 217, 201,186, 171, 156, 140, 125, 110, 97, 79, 66, 54, 31, 18, 0 };
+
+ if(m_scroll_buffer_changed)
+ {
+ m_scroll_buffer_changed = false;
+
+ for(xi = 0; xi < 256; xi++) // LOAD REAL SCROLL BUFFER FROM PRELOAD BUFFER:
+ m_GDC_SCROLL_BUFFER[xi] = m_GDC_SCROLL_BUFFER_PRELOAD[xi];
+ }
+
+ if(m_color_map_changed)
+ {
+ m_color_map_changed = false;
+
+ for(xi=0;xi<16;xi++) // DELAYED LOAD OF PALETTE ...
+ {
+ UINT8 colordata1 = m_GDC_COLOR_MAP[xi];
+ UINT8 colordata2 = m_GDC_COLOR_MAP[xi + 16]; // Does it matter if the palette is incomplete...?
+
+ // Color map: 32 x 8
+ // 2nd 16 Byte 1st 16 Bytes (colordata1)
+ // ----------- ------------
+ // 7..4 3..0 7..4 3..0
+ // Mono Blue Red Green
+ mono = (colordata2 & 0xF0) >> 4; // FIXME: limit palette in appropriate modes on 100-A
+ blue = (colordata2 & 0x0F);
+
+ red = (colordata1 & 0xF0) >> 4;
+ green =(colordata1 & 0x0F);
+ // NOTE: SECOND 16 BYTES ARE MONO PALETTE, _FIRST_ 16 ARE COLOR PALETTE * HERE * (on the VT240 driver, it is the other way round)
+
+ switch( m_inp13->read())
+ {
+ case MONO_MONITOR: // FIXME: bad colors!
+ {
+ switch( m_inp9->read() ) // - monochrome monitor (phosphor) type (1,2,3)
+ {
+ case 1: // BLACK & WHITE
+ m_palette2->set_pen_color(xi + 16, pal4bit(mono), pal4bit(mono), pal4bit(mono) );
+ break;
+
+ case 2: // SHADES OF GREEN
+ // For now, a hand picked value from VTVIDEO * is coarsly transformed into a RGB value.
+ red = UINT8( ( 35.0f / 80.0f) * ( v_levels[ mono ] / 3.19f) ); // 80 % = NORMAL *
+ green = UINT8( (145.0f / 80.0f) * ( v_levels[ mono ] / 3.19f) );
+ blue = UINT8( ( 75.0f / 80.0f) * ( v_levels[ mono ] / 3.19f) );
+ m_palette2->set_pen_color(xi + 16, rgb_t( red, green, blue) );
+ break;
+
+ case 3: // AMBER. Assumption: "normal" value at 80 % is 213, 146, 82 (decimal)
+ red = UINT8( (213.0f / 80.0f) * ( v_levels[ mono ] / 3.19f) ); // 80 % = NORMAL * is 3.19f (100 % would be 2.55f)
+ green = UINT8( (146.0f / 80.0f) * ( v_levels[ mono ] / 3.19f) );
+ blue = UINT8( ( 82.0f / 80.0f) * ( v_levels[ mono ] / 3.19f) );
+ m_palette2->set_pen_color(xi + 16, rgb_t( red, green, blue) );
+ break;
+ }
+ // 255 durch 2.55 ist 100 255 durch x ist 80
+ }
+ case COLOR_MONITOR: // w.official COLOR CABLE (mono out wired to green gun)
+ m_palette2->set_pen_color(xi, pal4bit( red ) , pal4bit( mono ) , pal4bit( blue ) );
+ break;
+
+ case DUAL_MONITOR: // Dual monitor configuration with homebrew cable (R G B, separate onboard circuit is mono)
+ m_palette2->set_pen_color(xi, pal4bit( red ), pal4bit( green ), pal4bit( blue ) );
+ break;
+ }
+
+ } // palette (loop)
+ } // color map changed?
+
+ // Raising it aftwards seems more reasonable.
+ // ....but there is a chance to introduce timing issues with the current code -
+
+ // IRQ raised before or after new palette loaded...?
+ if(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_VSYNC_IRQ) // 0x40
+ raise_8088_irq(IRQ_GRF_INTR_L);
+}
+
INTERRUPT_GEN_MEMBER(rainbow_state::vblank_irq)
{
raise_8088_irq(IRQ_8088_VBL);
@@ -2143,7 +2468,6 @@ READ8_MEMBER(rainbow_state::diagnostic_r) // 8088 (port 0A READ). Fig.4-29 + tab
WRITE8_MEMBER(rainbow_state::diagnostic_w) // 8088 (port 0A WRITTEN). Fig.4-28 + table 4-15
{
// printf("%02x to diag port (PC=%x)\n", data, space.device().safe_pc());
- m_SCREEN_BLANK = (data & 2) ? false : true;
// ZRESET from 8088 to Z80 - - HIGH at powerup!
if (!(data & 1))
@@ -2173,14 +2497,30 @@ WRITE8_MEMBER(rainbow_state::diagnostic_w) // 8088 (port 0A WRITTEN). Fig.4-28 +
m_fdc->reset(); // See formatter description p.197 or 5-13
}
- if (data & 0x04) // GRF_VID_SEL
- printf("\n*** UNEMULATED GRAPHICS [on GRAPHICS OPTION]. (bit 2 in diagnostic_w) = %i (0 = system module; else graphics option) ",data & 4);
+ m_SCREEN_BLANK = (data & 2) ? false : true;
+ // Switch determines how the monochrome output pin is taken from:
+ // 0 = M(ono) out from system module (DC011/DC012). Default, also used to setup dual monitors.
+ // 1 = M(ono) output from GRAPHICS OPTION. (G)reen remains unused with a single COLOR monitor.
+ m_ONBOARD_GRAPHICS_SELECTED = (data & 0x04) ? false : true;
+ if(!m_ONBOARD_GRAPHICS_SELECTED)
+ {
+ if(m_inp7->read() == 1)
+ printf("\nHINT: GRAPHICS OPTION ON. TEXT ONLY (DC011/DC012) OUTPUT NOW DISABLED.\n");
+ else
+ { printf("\nALARM: GRAPHICS OPTION * SWITCHED OFF * VIA DIP. TEXT OUTPUT STILL ENABLED!\n");
+ m_ONBOARD_GRAPHICS_SELECTED = true;
+ }
+ printf("DATA: %x (PC=%x)\n", data, machine().device("maincpu")->safe_pc());
+ }
+
// BIT 3: PARITY TEST (1 = enables parity test on memory option board).
- // FIXME: parity test = NMI? When should NMI fire? Whole bank tested?
- if (data & 0x08)
+ if(data & 0x08)
+ {
printf("\n*** UNEMULATED PARITY TEST [on RAM EXTENSION] - (bit 3 in diagnostic_w) ");
- // m_i8088->set_input_line_and_vector(INPUT_LINE_NMI, ASSERT_LINE, 0x02);
+ // FIXME: parity test = NMI? When should NMI fire? Per RAM bank?
+ // m_i8088->set_input_line_and_vector(INPUT_LINE_NMI, ASSERT_LINE, 0x02);
+ }
// MISSING BITS (* not vital for normal operation, see diag.disk) -
// * BIT 4: DIAG LOOPBACK (0 at power-up; 1 directs RX50 and DC12 output to printer port)
@@ -2305,6 +2645,362 @@ WRITE_LINE_MEMBER(rainbow_state::irq_hi_w)
#endif
}
+
+// ********************************* NEC UPD7220 ***********************************************
+// Readback mode: correct place? Not for vector mode (really)...?
+
+// NOTE: "More than one plane at a time can be enabled for a write operation; however,
+// only one plane can be enabled for a read operation at anyone time."
+
+READ16_MEMBER(rainbow_state::vram_r)
+{
+ if((!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR)) || space.debugger_access()) // (NOT VECTOR MODE)
+ {
+ //offset = ((offset & 0x18000) >> 1) | (offset & 0x3fff); // VT 240
+
+//*******************************************************************************************************************************
+// NEW SCROLL_MAP - "valid for reading, writing, and refreshing"
+// SEE PAGE 48 OF PDF FOR A DESCRIPTION OF THE SCROLL_MAP / SCROLL BUFFER:
+ offset = ( m_GDC_SCROLL_BUFFER[ ( (offset & 0x3FC0) >> 6 ) ] << 6) | (offset & 0x3F);
+//*******************************************************************************************************************************
+
+ int readback_plane = 0;
+
+ // READBACK CODE DISABLED, FOR BETTER DEBUGGING (CANT SEE ANYTHING...):
+ if( !(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_WRITES) ) // 0x10 // READBACK OPERATION - if ENABLE_WRITES NOT SET
+ {
+ readback_plane = (m_GDC_MODE_REGISTER & GDC_MODE_READBACK_PLANE_MASK) >> 2; // READBACK PLANE 00..02, mask in bits 2+3
+// printf(" READBACK MODE * ON *; plane selected: %02x ", readback_plane);
+ }
+ return m_video_ram[ (offset & 0xffff) + (0x8000 * readback_plane)];
+ //return m_video_ram[(offset & 0x7fff) + (0x8000 * readback_plane)]; // VT240
+ }
+ return 0;
+}
+
+// NOT PRESENT: enable line erase (10) / DMA scroll (11)
+// ??? VT 240 ???: LOGIC UNIT SELECT
+// SELECT_VECTOR_PATTERN_REGISTER -> IS_VECTOR_MODE !
+
+// Rainbow has separate registers for fore and background.
+WRITE16_MEMBER(rainbow_state::vram_w)
+{
+ //UINT8 *video_ram8 = (UINT8 *)(&m_video_ram[0]);
+
+ if(!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR)) // NOT VECTOR MODE
+ {
+
+//*******************************************************************************************************************************
+// NEW SCROLL_MAP - "valid for reading, writing, and refreshing"
+// SEE PAGE 48 OF PDF FOR A DESCRIPTION OF THE SCROLL_MAP / SCROLL BUFFER:
+ offset = ( m_GDC_SCROLL_BUFFER[ ( (offset & 0x3FC0) >> 6 ) ] << 6) | (offset & 0x3F);
+//*******************************************************************************************************************************
+
+ offset |= BIT(offset, 16); // leftover from VT240 (GDC has 18 bit, Duell schematics dont show if A16 und A17 are connected...)
+ }
+ else
+ {
+ if(data & 0xff00)
+ {
+ data >>= 8;
+ offset += 1;
+ }
+ else
+ data &= 0xff;
+ }
+
+ offset &= 0xffff; // same as in VT240?
+ UINT16 chr = data; // VT240 : UINT8
+
+ if(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR) // VT240 : if(SELECT_VECTOR_PATTERN_REGISTER)
+ {
+ chr = BITSWAP8(m_vpat, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx);
+ if(m_patcnt-- == 0)
+ {
+ m_patcnt = m_patmult;
+ if(m_patidx-- == 0)
+ m_patidx = 7;
+ }
+ }
+ else
+ {
+ chr = m_GDC_WRITE_BUFFER[ m_GDC_write_buffer_index++ ];
+ m_GDC_write_buffer_index &= 0xf;
+
+ chr |= (m_GDC_WRITE_BUFFER[m_GDC_write_buffer_index++] << 8);
+ m_GDC_write_buffer_index &= 0xf;
+ }
+
+ if(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_WRITES) // 0x10
+ {
+ // ALU_PS register: controls logic used in writing to the bitmap / inhibiting of writing to specified planes.
+ // plane select and logic operations on write buffer... (and more) **** SEE PAGE 36 ****
+ int ps = ~m_GDC_ALU_PS_REGISTER & 0x0F; // PLANE SELECT 0..3 // VT 240 : ~m_GDC_ALU_PS_REGISTER & 3;
+ UINT8 fore = ( (m_GDC_FG_BG & 0xf0) ) >> 4;
+ UINT8 back = (m_GDC_FG_BG & 0x0f); // background : 0..3 confirmed, see p.39 AA-AE36A (PDF)
+
+ for(int i = 0; i <= 3; i++)
+ {
+ if( BIT(ps,i ) )
+ {
+ UINT16 mem = m_video_ram[(offset & 0xffff) + (0x8000 * i)]; // VT240
+
+ UINT16 out = 0; // VT240 : UINT8
+ for(int j = 0; j <= 15; j++) // REPLACE MODE : one replaced by FG, zero by BG ( 16 instead of 8 bit on VT240 )
+ out |= BIT(chr, j) ? ((fore & 1) << j) : ((back & 1) << j);
+
+ switch (m_GDC_ALU_PS_REGISTER & ALU_PS_MODE_MASK)
+ {
+ case OVERLAY_MODE: // (OR)
+ out |= mem;
+ break;
+
+ case COMPLEMENT_MODE: // (XOR)
+ out ^= ~mem;
+ break;
+
+ default: // ALL ELSE
+ break;
+ }
+
+ if(!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR)) // 0 : (NOT VECTOR MODE) Text Mode and Write Mask Batch
+ out = (out & ~m_GDC_WRITE_MASK) | (mem & m_GDC_WRITE_MASK); // // M_MASK (1st use)
+ else
+ out = (out & data) | (mem & ~data); // VECTOR MODE !
+
+ if(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_WRITES) // 0x10
+ m_video_ram[(offset & 0xffff) + (0x8000 * i)] = out;
+ } // if plane selected
+
+ fore >>= 1;
+ back >>= 1;
+
+ } // plane select (LOOP)
+ return; // ??
+ }
+
+
+ if(!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR))
+ data = (chr & ~m_GDC_WRITE_MASK) | (m_video_ram[offset] & m_GDC_WRITE_MASK);
+ else
+ data = (chr & data) | (m_video_ram[offset] & ~data);
+
+ // < scroll thingy from VT240 omitted >
+
+ m_video_ram[offset] = data;
+
+}
+
+
+WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
+{
+ static int last_message, last_mode, last_readback, last_scroll_index;
+// rectangle curvisarea = m_screen2->visible_area();
+// int vert_pix_total = 256; // should be 240
+// int horiz_pix_total;
+
+ if(offset > 0) // Port $50 reset done @ boot ROM 1EB4/8 regardless if option present.
+ if (m_inp7->read() != 1)
+ {
+ if(last_message != 1)
+ {
+ printf("\nCOLOR GRAPHICS ADAPTER INVOKED. PLEASE TURN ON THE APPROPRIATE DIP SWITCH, THEN RESTART.\n");
+ printf("OFFSET: %x (PC=%x)\n", 0x50 +offset , machine().device("maincpu")->safe_pc());
+ last_message = 1;
+ }
+ return;
+ }
+
+ switch(offset)
+ {
+ case 0: // Mode Register must be reloaded following any write to port 50 (software reset).
+ // Graphics option software reset. Any write to this port also resynchronizes the
+ // read/modify/write memory cycles of the Graphics Option to those of the GDC.
+ GDC_RESET_MACRO
+ break;
+
+ case 1: // 51h - DATA loaded into register previously written to 53h.
+ if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_WRITE_BUFFER) // 0x01
+ {
+ m_GDC_write_buffer_index = 0; // (writing to 51h CLEARS the index counter)
+ break;
+ }
+
+ if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_COLOR_MAP ) // 0x20
+ {
+ m_color_map_changed = true;
+
+ m_GDC_COLOR_MAP[m_GDC_color_map_index++] = ~data; // tilde data verified by DIAGNOSTIC!
+ if(m_GDC_color_map_index == 32)
+ {
+ m_GDC_color_map_index = 0; // 0...31 (CPU accesses 32 bytes
+
+ printf("\n * COLOR MAP FULLY LOADED *");
+ for(int zi =0; zi <16; zi++)
+ {
+ int g = m_GDC_COLOR_MAP[zi] & 0x0F;
+ int r = (m_GDC_COLOR_MAP[zi] & 0xF0) >> 4;
+
+ int b = m_GDC_COLOR_MAP[zi + 16] & 0x0F;
+ int m = (m_GDC_COLOR_MAP[zi + 16] & 0xF0) >> 4;
+ printf("\n[%d] %1x %1x %1x %1x (1:1)", zi, r , g , b , m);
+ }
+ printf("\n------------------------------");
+ } // if all colors present
+ break;
+ }
+
+ if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_SCROLL_MAP ) // 0x80
+ {
+ if(!( m_GDC_MODE_REGISTER & GDC_MODE_READONLY_SCROLL_MAP)) // ? READONLY / WRITE logic correct...?
+ {
+ m_GDC_SCROLL_BUFFER_PRELOAD[m_GDC_scroll_index] = data; // // WRITE TO SCROLL_MAP ( 256 x 8 )
+
+ if(m_GDC_scroll_index == 255)
+ printf("\n ---- SCROLL MAP FULLY LOADED ---*");
+ m_GDC_scroll_index++;
+ m_GDC_scroll_index &= 0xFF; // 0...255 (CPU accesses 256 bytes)
+
+ m_scroll_buffer_changed = true;
+ }
+ break;
+ }
+
+ // -----------------PATTERN + MULTIPLIER USED IN VECTOR MODE ONLY!
+ // SEE PAGE 37 OF AA-AE36A (PDF).
+ // NOTE : Pattern Multiplier MUST BE LOADED before loading PATTERN.
+ if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_PATTERN_MULTIPLIER)
+ {
+ // On a Rainbow, 12 indicates a multiplier of 16-12 = 4 (example)
+ m_patmult = 16 - (data & 15); // 4 bit register // VT240: "patmult_w"
+ break;
+ }
+
+ if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_PATTERN)
+ {
+ m_vpat = data; // VGl. "vpat_w" im Original!
+ m_patcnt = m_patmult;
+ m_patidx = 7; // correct...?
+ break;
+ }
+
+ if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_FG_BG) // 2 x 4
+ {
+ m_GDC_FG_BG = data; // Neither bitswap nor negated (and also not both)...
+ break; // Next: prepare FG / BG and PLANE in ALU - PLANE_SELECT register.
+ }
+
+ if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_ALU_PS)
+ {
+ m_GDC_ALU_PS_REGISTER = data; // Neither bitswap nor negated (and also not both)...
+ break;
+ }
+
+ if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_MODE_REGISTER)
+ {
+ m_GDC_MODE_REGISTER = data; // Neither bitswap nor negated (and also not both)...
+
+ if(last_message != 2)
+ {
+ last_message = 2;
+
+ if(data & GDC_MODE_HIGHRES)
+ {
+// horiz_pix_total = 800;
+ printf(" * HIGH RESOLUTION * ");
+ }
+ else
+ {
+// horiz_pix_total = 384;
+ printf(" MEDIUM RESOLUTION ");
+ }
+ }
+ // DOES NOT WORK - at least for medres the screen is too far stretched :
+// curvisarea.set(0, horiz_pix_total - 1, 0, vert_pix_total - 1);
+// subdevice<screen_device>("screen2")->configure(horiz_pix_total, vert_pix_total, curvisarea, HZ_TO_ATTOSECONDS(60));
+
+ if(last_mode != (data & GDC_MODE_VECTOR))
+ {
+ last_mode = data & GDC_MODE_VECTOR;
+ if(data & GDC_MODE_VECTOR)
+ printf(" VECTOR MODE ");
+ else
+ printf(" WORD MODE ");
+ }
+
+ if(last_readback != (data & GDC_MODE_ENABLE_WRITES))
+ {
+ last_readback = data & GDC_MODE_ENABLE_WRITES;
+ if(data & GDC_MODE_ENABLE_WRITES) // 0x10
+ printf(" READBACK: OFF - ENABLE_WRITES ");
+ else // READBACK PLANE 00..02 - mask in bits 2+3:
+ printf(" READBACK MODE; plane = %02x ", m_GDC_MODE_REGISTER & GDC_MODE_READBACK_PLANE_MASK); // unsure if PLANE is set... already?!
+ }
+
+ if(last_scroll_index != m_GDC_scroll_index)
+ {
+ last_scroll_index = m_GDC_scroll_index;
+ if(data & GDC_MODE_READONLY_SCROLL_MAP) // 0x20
+ { //printf(" SCROLL MAP READ_ONLY. Index : %02x ", m_GDC_scroll_index);
+ } else
+ { printf(" SCROLL MAP IS WRITABLE. Index : %02x ", m_GDC_scroll_index);
+ }
+ }
+
+ if(!(data & GDC_MODE_ENABLE_VSYNC_IRQ)) // 0x40
+ lower_8088_irq(IRQ_GRF_INTR_L); // also clears the interrupt
+
+ break;
+ } // GDC_SELECT_MODE_REGISTER
+
+ printf("\n* UNIMPLEMENTED CASE. MODE = %02x / m_GDC_INDIRECT_REGISTER = %02x\n",m_GDC_MODE_REGISTER, m_GDC_INDIRECT_REGISTER);
+ break;
+
+ case 2:
+ // 52h Data written to this port is loaded into the Write Buffer
+ // While the CPU accesses the Write Buffer as sixteen 8-bit bytes,
+ // the GDC accesses the buffer as eight 16-bit words.
+ // A 16-bit Write Mask gives the GDC control over individual bits of a word.
+ // -------------------- WRITE BUFFER USED IN WORD MODE ONLY !
+ // "OUTPUT WRITE BUFFER IS THE INVERSE OF THE INPUT" (quote from 4-3 of the PDF)
+ // BITSWAP SEEMS NECESSARY (see digits in DOODLE)... !
+ m_GDC_WRITE_BUFFER[m_GDC_write_buffer_index++] = ~BITSWAP8(data, 0, 1, 2, 3, 4, 5, 6, 7); // see BITSWAP on VT240;
+ m_GDC_write_buffer_index &= 0xf; // write up to 16 bytes to port 52h.
+ break;
+
+ case 3: // 53h Indirect Register; address selection for indirect addressing. See 51h.
+ m_GDC_INDIRECT_REGISTER = data ^ 0xff;
+
+ // Index to WRITE_BUFFER is reset via dummy write to port 51h (not here!).
+
+ if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_COLOR_MAP ) // 0x20
+ m_GDC_color_map_index = 0; // (also clears the index counter)
+ // NEXT: 32 BYTE COLOR MAP, LOADED TO $51
+
+ if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_SCROLL_MAP ) // 0x80
+ {
+ if(last_scroll_index != m_GDC_scroll_index)
+ {
+ last_scroll_index = m_GDC_scroll_index;
+ printf(" *** SCROLL INDEX COUNTER RESET, old value = %d", m_GDC_scroll_index);
+ }
+ m_GDC_scroll_index = 0; // (also clears the index counter)
+ } // NEXT: LOAD 256 BYTE SCROLL MAP INTO $51
+ break;
+
+ // --------- WRITE MASK (2 x 8 = 16 bits) USED IN WORD MODE ONLY !
+ // NOTE: there is NO specific order for the WRITE_MASK (according to txt/code samples in PDF)!
+ // LOW... HI VERIFED
+ case 4: // 54h Write Mask LOW
+ m_GDC_WRITE_MASK = ( m_GDC_WRITE_MASK & 0xFF00 ) | BITSWAP8(~data, 0, 1, 2, 3, 4, 5, 6, 7);
+ break;
+ case 5: // 55h Write Mask HIGH
+ m_GDC_WRITE_MASK = ( BITSWAP8(~data, 0, 1, 2, 3, 4, 5, 6, 7) << 8 ) | ( m_GDC_WRITE_MASK & 0x00FF );
+ break;
+ }
+}
+
+
/* F4 Character Displayer */
static const gfx_layout rainbow_charlayout =
{
@@ -2323,6 +3019,10 @@ static GFXDECODE_START(rainbow)
GFXDECODE_ENTRY("chargen", 0x0000, rainbow_charlayout, 0, 1)
GFXDECODE_END
+// Allocate 512 K (4 x 64 K x 16 bit) of memory (GDC-NEW):
+static ADDRESS_MAP_START( upd7220_map, AS_0, 16, rainbow_state)
+ AM_RANGE(0x00000, 0x3ffff) AM_READWRITE(vram_r, vram_w) AM_SHARE("vram")
+ADDRESS_MAP_END
static MACHINE_CONFIG_START(rainbow, rainbow_state)
MCFG_DEFAULT_LAYOUT(layout_rainbow)
@@ -2331,11 +3031,11 @@ MCFG_DEFAULT_LAYOUT(layout_rainbow)
MCFG_CPU_ADD("maincpu", I8088, XTAL_24_0734MHz / 5)
MCFG_CPU_PROGRAM_MAP(rainbow8088_map)
MCFG_CPU_IO_MAP(rainbow8088_io)
-MCFG_CPU_VBLANK_INT_DRIVER("screen", rainbow_state, vblank_irq)
MCFG_CPU_ADD("subcpu", Z80, XTAL_24_0734MHz / 6)
MCFG_CPU_PROGRAM_MAP(rainbowz80_mem)
MCFG_CPU_IO_MAP(rainbowz80_io)
+MCFG_CPU_VBLANK_INT_DRIVER("screen", rainbow_state, vblank_irq)
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
@@ -2343,19 +3043,40 @@ MCFG_SCREEN_REFRESH_RATE(60)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
MCFG_SCREEN_SIZE(132 * 10, 49 * 10)
MCFG_SCREEN_VISIBLE_AREA(0, 80 * 10 - 1, 0, 48 * 10 - 1)
+
MCFG_SCREEN_UPDATE_DRIVER(rainbow_state, screen_update_rainbow)
MCFG_SCREEN_PALETTE("vt100_video:palette")
MCFG_GFXDECODE_ADD("gfxdecode", "vt100_video:palette", rainbow)
MCFG_DEVICE_ADD("vt100_video", RAINBOW_VIDEO, 0)
+
MCFG_VT_SET_SCREEN("screen")
MCFG_VT_CHARGEN("chargen")
MCFG_VT_VIDEO_RAM_CALLBACK(READ8(rainbow_state, read_video_ram_r))
MCFG_VT_VIDEO_CLEAR_VIDEO_INTERRUPT_CALLBACK(WRITELINE(rainbow_state, clear_video_interrupt))
+// *************************** COLOR GRAPHICS (OPTION) **************************************
+MCFG_DEVICE_ADD("upd7220", UPD7220, XTAL_32MHz / 4) // WAR: 31188000 / 4 TO BE VERIFIED. Duell schematics shows 31.188 (?) Mhz (/ 4 = 7.797 Mhz)
+MCFG_UPD7220_VSYNC_CALLBACK(WRITELINE(rainbow_state, GDC_vblank_irq)) // "The vsync callback line needs to be below the 7220 DEVICE_ADD line."
+
+MCFG_DEVICE_ADDRESS_MAP(AS_0, upd7220_map)
+MCFG_UPD7220_DISPLAY_PIXELS_CALLBACK_OWNER(rainbow_state, hgdc_display_pixels)
+MCFG_VIDEO_SET_SCREEN("screen2") // SET_SCREEN needs to be added after 7720 device in the machine config, not after the screen.
+MCFG_PALETTE_ADD("palette2", 32)
+
+MCFG_SCREEN_ADD("screen2", RASTER)
+MCFG_SCREEN_VIDEO_ATTRIBUTES(VIDEO_UPDATE_AFTER_VBLANK | VIDEO_ALWAYS_UPDATE)
+MCFG_SCREEN_REFRESH_RATE(60)
+MCFG_SCREEN_UPDATE_DEVICE("upd7220", upd7220_device, screen_update)
+
+MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) // not accurate
+MCFG_SCREEN_SIZE(800, 256) // should be 240
+MCFG_SCREEN_VISIBLE_AREA(0, 800-1, 0, 256-1) // should be 240
+
MCFG_FD1793_ADD(FD1793_TAG, XTAL_24_0734MHz / 24) // no separate 1 Mhz quartz
MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":0", rainbow_floppies, "525qd0", rainbow_state::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":1", rainbow_floppies, "525qd1", rainbow_state::floppy_formats)
+//MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":1", rainbow_floppies, "525sd", rainbow_state::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":2", rainbow_floppies, "525dd", rainbow_state::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":3", rainbow_floppies, "35dd", rainbow_state::floppy_formats)
MCFG_SOFTWARE_LIST_ADD("flop_list", "rainbow")
@@ -2425,7 +3146,6 @@ MCFG_I8251_TXRDY_HANDLER(WRITELINE(rainbow_state, kbd_txready_w))
MCFG_DEVICE_ADD(LK201_TAG, LK201, 0)
MCFG_LK201_TX_HANDLER(DEVWRITELINE("kbdser", i8251_device, write_rxd))
-
MCFG_DEVICE_ADD("keyboard_clock", CLOCK, 4800 * 16) // 8251 is set to /16 on the clock input
MCFG_CLOCK_SIGNAL_HANDLER(WRITELINE(rainbow_state, write_keyboard_clock))
diff --git a/src/mame/drivers/vis.cpp b/src/mame/drivers/vis.cpp
index 2aeb348e79f..706e39ae71b 100644
--- a/src/mame/drivers/vis.cpp
+++ b/src/mame/drivers/vis.cpp
@@ -19,7 +19,7 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void dack16_w(int line, UINT16 data) override { m_sample[m_samples++] = data; if(m_samples == 2) m_isa->drq7_w(CLEAR_LINE); }
+ virtual void dack16_w(int line, UINT16 data) override { if(m_samples < 2) m_sample[m_samples++] = data; else m_isa->drq7_w(CLEAR_LINE); }
virtual machine_config_constructor device_mconfig_additions() const override;
private:
required_device<dac_device> m_dacr;
@@ -30,8 +30,8 @@ private:
UINT8 m_data[2][16];
UINT8 m_mode;
UINT8 m_stat;
- int m_sample_byte;
- int m_samples;
+ unsigned int m_sample_byte;
+ unsigned int m_samples;
emu_timer *m_pcm;
};
@@ -164,13 +164,13 @@ WRITE8_MEMBER(vis_audio_device::pcm_w)
m_mode = data;
break;
case 0x02:
- m_data[0][m_index[0]] = data;
+ m_data[0][m_index[0] & 0xf] = data;
break;
case 0x03:
m_index[0] = data;
break;
case 0x04:
- m_data[1][m_index[1]] = data;
+ m_data[1][m_index[1] & 0xf] = data;
break;
case 0x05:
m_index[1] = data;
diff --git a/src/mame/layout/rainbow.lay b/src/mame/layout/rainbow.lay
index f0b804bda26..ba4d43ceeef 100644
--- a/src/mame/layout/rainbow.lay
+++ b/src/mame/layout/rainbow.lay
@@ -1,4 +1,3 @@
-<?xml version="1.0"?>
<mamelayout version="2">
<element name="driveled" defstate="0">
<disk state="1">
@@ -115,7 +114,7 @@
<view name="Default Layout">
<screen index="0">
- <bounds x="30" y="0" width="640" height="480" />
+ <bounds x="30" y="0" width="~scr0width~" height="~scr0height~" />
</screen>
<bezel name="driveled0" element="driveled">
@@ -221,10 +220,33 @@
</bezel>
</view>
- <view name="Screen Only">
+ <view name="Text Only">
<screen index="0">
- <bounds x="0" y="0" width="640" height="480" />
+ <bounds x="30" y="0" width="~scr0width~" height="~scr0height~" />
</screen>
</view>
+ <view name="Graphics Only">
+ <screen index="1">
+ <bounds x="0" y="0" width="~scr1width~" height="~scr1height~" />
+ </screen>
+ </view>
+
+ <view name="Dual Side-by-Side">
+ <screen index="0">
+ <bounds x="0" y="0" width="~scr0width~" height="~scr0height~" />
+ </screen>
+ <screen index="1">
+ <bounds x="~scr0width~" y="0" width="~scr1width~" height="~scr1height~" />
+ </screen>
+ </view>
+
+ <view name="Dual Over-Under">
+ <screen index="0">
+ <bounds x="30" y="0" width="~scr0width~" height="~scr0height~" />
+ </screen>
+ <screen index="1">
+ <bounds x="30" y="~scr0height~" width="~scr1width~" height="~scr1height~" />
+ </screen>
+ </view>
</mamelayout>