1 // license:GPL-2.0+
2 // copyright-holders:Miodrag Milanovic,Karl-Ludwig Deisenhofer
3 /***************************************************************************************************
4 DEC Rainbow 100
5 
6 Driver-in-progress by R. Belmont and Miodrag Milanovic.
7 Portions (2013 - 2018) by Karl-Ludwig Deisenhofer (Floppy, ClikClok RTC, NVRAM, DIPs, hard disk, Color Graphics).
8 Baud rate generator by AJR (2018) and Shattered (2016), keyboard & GDC fixes by Cracyc (June - Nov. 2016).
9 
10 Model B implementation has a workaround prevents a side effect of ERROR 13 to unlock floppy drives A-D.
11 
12 Native single sided 5.25" images with 80 tracks, 10 sectors are well tested (*.IMD / *.TD0=TeleDisk / *.IMG with 400 K).
13 VT180 images (184.320 Bytes) are very unreliable in CP/M - though a real machine can read them.
14 5.25 MFM PC style drives and 720 K (3.5 " DS-DD MFM PC formatted disks) (on slots 3 + 4) show regressions / bugs
15   as of Dec.2018 (file content bad while dir is OK, seek errors, write fault errors when copying _to_ hard disk).
16 
17 ALWAYS USE THE RIGHT SLOT AND SAVE YOUR DATA BEFORE MOUNTING FOREIGN DISK FORMATS!
18 
19 You * should * also reassign SETUP (away from F3, where it sits on a LK201).
20 DATA LOSS POSSIBLE: when in partial emulation mode, F3 performs a hard reset!
21 
22 STATE AS OF DECEMBER 2018
23 -------------------------
24 Driver is based entirely on the DEC-100 'B' variant (DEC-190 and DEC-100 A models are treated as clones).
25 While this is OK for the compatible -190, it doesn't do justice to ancient '100 A' hardware.
26 The public domain file RBCONVERT.ZIP documents how model 'A' differs from version B.
27 NVRAM files from -A and -B machines are not interchangeable. If problems arise, delete the NVRAM file.
28 
29 Venix 86-R (BSW) is working, just follow https://github.com/bsdimp/venix/blob/master/doc/MESS-RB-INSTALL.md
30 
31 CPM 2.1 / DOS2.11 / DOS 3.x / diag disks boot. UCSD systems (fort_sys, pas_sys) boot, but expect 4 QD drives
32   loaded with disks (reassign slots, reset and mount three empty 400 K images before startup at #2, #3, #4).
33 
34 It is possible to boot DOS 3.10 from floppy A: and later use a hard disk attached to E:.
35 
36 NB.: a single hard disk (5 - 67 MB, 512 byte sectors) may be attached before startup. It should remain there
37 until shutdown. "Hot swapping" wasn't possible on the original system (our GUI just doesn't forbid it).
38 
39 To create a DEC RD50/ST506 compatible image (153 cylinders, 4 heads, 16 sectors, standard 512 byte sectors) enter
40 >chdman createhd -c none -chs 153,4,16 -ss 512 -o RD50_ST506.chd
41 NOTE: use -c none parameter for no compression. No more than 8 heads or 1024 cylinders.
42 
43 Some BUGS remain: BIOS autoboot doesnt work at all. It is not possible to boot from a properly formatted
44  winchester with "W" (CPU crash). So there's an issue with the secondary boot loader (for hard disks)...
45 
46 CTRL-SETUP (soft reboot) always triggers ERROR 19 (64 K RAM err.). One explanation is that ZFLIP/ZRESET is
47 handled wrongly, so shared mem. just below $8000 is tainted by Z80 stack data. A reentrance problem?
48 
49 Occassionally, ERROR 13 -keyboard stuck- appears (for reasons yet unknown).
50 
51 
52 CORVUS HARD DISK
53 ----------------
54 Up to 4 Corvus Disks with up to 20 MB each can be emulated (to be mounted as hard disks 2 - 5).
55 MS DOS 2.x and CP/M v2.x were once supported, but are untested (in part because no binary drivers have survived).
56 
57 To get a Corvus 11 drive up and running under CP/M 1.x, you'll need drcdutil.td0 from Donald Maslin's Archive.
58 
59 First, create a 11 MB hard disk:
60 >Chdman createhd -c none -chs 306,4,20 -ss 512 -o CORVUS11.chd
61 [ -chs 306,2,20 for the 6 MB model and  -chs 306,6,20 for the 20 MB type ]
62 
63 Then make a copy of your CP/M 86-80 V1.x boot disk. This copy must be patched to make the Corvus hard drive usable!
64 With 'drcdutil.td0' mounted in A: and a write enabled (non TeleDisk) image of CPM 1.x in B: type:
65 b:>SUBMIT A:hinstall
66 
67 This replaces the following CP/M files on B:
68    B:Z80CCP.SYS  <- A:HZ80CCP.SYS
69    B:Z80.SYS     <- A:HZ80.SYS
70    B:PRMTVPV.SYS <- A:HPRMTVPV.SYS
71 
72 Due to a missing drive specification in HINSTALL.SUB, the last PIP must be invoked manually:
73 b:>PIP B:PRMTVPVT.SYS=A:HPRMTVPV.SYS[V]
74 
75 Finally, boot from the newly patched CP/M disk and type CLINK2TN (a step necessary after each cold boot).
76 CLINK2TN can only be used together with a Corvus 11 MB hard disk. It needs a patched CP/M 1.x disk and won't run on CP/M 2.x.
77 [ use CLINK2FV for the 6 MB model and CLINK2TW for the 20 MB type ]
78 
79 Two steps are needed to initialize the new disk:
80 Step 1: invoke PUTGET, then press "f". Enter "Drive no: 1", "HEX BYTE? e5", "Starting disc address?  2320", "Number of Sectors? 64"
81 Step 2: invoke PUTGET, then press "f". Enter "Drive no: 1", "HEX BYTE? e5", "Starting disc address?  48592", "Number of Sectors? 64"
82 Done.
83 
84 Required steps vary with 5 and 20 MB models (look into the *.DOC files in DRCDUTIL.TD0 / CLINK86.A86 / DRIVEL.COM).
85 Parameters for initialization can be taken from Chapter 2 of the Disk System Installion Guide for TRS-80 II (same type H drives).
86 
87 
88 COLOR EMULATION (NEC 7220 + extra hardware)
89 -------------------------------------------
90 
91 -------------------- Differences to VT240: ---------------------------------------------------
92    - Registers of graphics option not directly mapped (indirect access via mode register)
93    - write mask is 16 bits wide (not only 8)
94    - scroll register is 8 bits wide - not 16.
95    - no "LINE ERASE MODE", 7220 DMA lines are unused. No ZOOM hardware (factor must always be 1)
96 
97    Two modes: highres and medres mode (different bank length..?)
98    - MEDRES: palette of 16 colors out of 4096.   384 x 240
99    - HIGRES: palette of  4 colors out of 4096.   800 x 240
100    Palette takes 2 byte per palette entry. CLUT ("color map") is 32 byte long.
101 ------------------------------------------------------------------------------------------------
102 
103 DEC 'R-M-B' COLOR CABLE VS. THE UNOFFICIAL 'R-G-B' MODE (a bit of history)
104    (1) the standard DEC "color cable" connected the green gun of a VR241 to the mono output of the Rainbow
105    (2) an unofficial DIY cable enabled R-G-B graphics + seperate text
106 
107 EMULATION SPECIFIC
108    (1) COLOR_MONITOR reflects DEC's recommendation (R-M-B with VR241 above)
109    (2) DUAL MONITOR enables both screens, even if onboard graphics has been accidently shut off
110        (also helps debugging semi broken programs, for example Doodle).
111    (3) AUTODETECT (DIP setting) snoops the color palette and chooses the correct 'wiring'
112 
113 SCREEN 1 vs. SCREEN 2 IN EMULATION
114    All GDC 7220 output is displayed on the right. Be it color or monochrome, Option Graphics output is on screen 2.
115    If you select MONO_MONITOR via DIP, output from GDC will appear on screen 2 in 16 shades of grey.
116    The type of monochrome monitor (VR-210 A, B or C) is selectable via another DIP (coarsly simulates a phosphor color).
117 
118 BUGS
119 - GDC diagnostic disk fails on 9 of 13 tests (tests 4 and 6 - 13).
120 
121 Details
122 a. (Rainbow driver) : interaction between DEC's external hardware and the NEC 7220 isn't fully understood (see page 173 of AA-AE36A)
123    It is also unclear what port $50 actually does when it 'synchronizes R-M-W cycles'.
124    For now, we provide sane defaults for both vector and bitmap units without disturbing display mode(s) or the NEC 7220.
125 b. the Hblank / Vblank ratio is plainly wrong (quick test / subtest #6),
126 c. IRQs are flagged as 'erratic' (quick test / subtest #12).
127 d. (7220) : incorrect fifo stati are handed out (GDC reports FIFO_EMPTY instead of _FULL when quick test #4 floods the queue)
128 e. (7220) : RDAT with MOD 2 used extensively here, but unimplemented (modes other than 0 undocumented by NEC / Intel)
129 
130 UNIMPLEMENTED:
131 - Rainbow 100 A palette quirks (2 bit palette... applies to certain modes only)
132 
133 UNKNOWN IMPLEMENTATION DETAILS:
134 1. READBACK (hard copy programs like JOBSDUMP definitely use it. See also GDC diagnostics).  VRAM_R...?
135 
136 2. UNVERIFIED DIVIDERS (31.188 Mhz / 32) is at least close to 1 Mhz (as on the VT240, which uses a very similar design)
137 
138 3. UPD7220 / CORE oddities
139 
140 To obtain pixel exact graphics use 'Graphics Only' in Video Options and cmd.line switches -nowindow -aspect1 auto -nokeepaspect
141 (Over-Under or Side-by-Side modes always distorted on my 1600 x 900 laptop)
142 
143 
144 CURRENTY UNEMULATED
145 -------------------
146 (a) the serial printer on port B prints garbage. It is worth to mention that port B relies on XON/XOFF,
147     while DTR_L (CTS B) means 'printer ready'. There is also a ROM patch in place...
148 
149 (b1) LOOPBACK circuit not emulated (used in startup tests).
150 
151 (b2) system interaction tests HALT Z80 CPU at location $0211 (forever). Boot the RX50 diag.disk
152  to see what happens (key 3 - individual tests, then 12 - system interaction). Uses LOOPBACK too?
153 
154 (c) arbitration chip (E11; in 100-A schematics or E13 in -B) is dumped, but yet unemulated.
155 It is a 6308 OTP ROM (2048 bit, 256 x 8) used as a lookup table (LUT) with the address pins (A)
156 used as inputs and the data pins (D) as output.
157 
158 Plays a role in DMA access to lower memory (limited to 64 K; Extended communication option only).
159 Arbiter is also involved in refresh and shared memory contention (affects Z80/8088 CPU cycles).
160 
161 => INPUTS on E13 (PC-100 B):
162 
163 SH5 RF SH REQ H   -> Pin 19 (A7) shared memory request / refresh ?
164      1K -> +5 V   -> Pin 18 (A6) < UNUSED >
165 SH 2 BDL ACK (L)  -> Pin 17 (A5) BUNDLE OPTION: IRQ acknowledged
166 SH 2 NONSHRCYC H  -> Pin 5 (A4) unshared memory cycle is in progress
167 SH 2 PRECHARGE H  -> Pin 4 (A3)
168 SH 2 SHMUX 88 ENB -> Pin 3 (A2) shared memory
169 SH2 DO REFRESH H  -> Pin 2 (A1) indicates that extended memory must be refreshed -> on J6 as (L)
170 SH10 BDL REQ (L)  -> Pin 1 (A0) BUNDLE OPTION wishes to use shared memory
171 
172 HARDWARE UPGRADES WORTH EMULATING (should be implemented as SLOT DEVICES):
173 * Extended communication option (occupies BUNDLE_OPTION 1 + 2)  REFERENCE: AA-V172A-TV + Addendum AV-Y890A-TV.
174 Two ports, a high-speed RS-422 half-duplex interface (port A) + lower-speed RS-423 full/half-duplex interface
175 with modem control (port B). A 5 Mhz. 8237 DMA controller transfers data into and out of shared memory (not: optional RAM).
176 
177 Uses SHRAM, SHMA, BDL SH WR L, NONSHARED CYCLE. Implementation requires DMA and arbitration logic (using dump of E11/E13 ?).
178 Can't be added if RD51 hard disk controller present (J4 + J5). For programming info see NEWCOM1.DOC (-> RBETECDOC.ZIP).
179 
180 * ( NO DUMP YET ) PC CHARACTER SET (Suitable Solutions?). Supported by IBM PC software emulator named CodeBlue (see 3.1 patch)
181 
182 * ( NO DUMP YET ) TECHNICAL CHARACTER SET (TCS; available for Rainbow 100, 100B, 100+; $95 from DEC)
183 Source: price list of a DEC reseller.
184 Contains 94 graphic characters from $A1 - $FE, including symbols and characters used in technical applications,
185  see http://support.attachmate.com/techdocs/1184.html and http://vt100.net/charsets/technical.html
186 
187 * 8087  Numerical Data Coprocessor daughterboard.       REFERENCE: EK-PCNDP-IN-PRE
188 Daughterboard, to be plugged into the expansion port where the memory expansion card usually sits (J6).
189 If a memory adapter board is present, it has to be plugged into a connector atop the 8087 copro board.
190 The 8088 is put into the CPU socket on the coprocessor board.
191 SOFTWARE: MATH test on 'Design Maturity Diagnostics'; AutoCad, TurboPascal and Fortran.
192 
193 * Suitable Solutions TURBOW286: 12 Mhz, 68-pin, low power AMD N80L286-12 and WAYLAND/EDSUN EL286-88-10-B ( 80286 to 8088 Processor Signal Converter )
194 plus DC 7174 or DT 7174 (barely readable). Add-on card, replaces main 8088 cpu (via ribbon cable). Patched V5.03 BOOT ROM labeled 'TBSS1.3 - 3ED4'.
195 
196 * NEC_V20 (requires modded BOOT ROM because of - at least 2 - hard coded timing loops):
197 100A:         100B/100+:                       100B+ ALTERNATE RECOMMENDATION (fixes RAM size auto-detection problems when V20 is in place.
198 Tested on a 30+ year old live machine. Your mileage may vary)
199 
200 Location Data  Location Data                   Loc.|Data
201 ....     ..    ....     ..  ------------------ 00C6 46 [ increases 'wait for Z80' from approx. 27,5 ms (old value 40) to 30,5 ms ]
202 ....     ..    ....     ..  ------------------ 0303 00 [ disable CHECKSUM ]
203 043F     64    072F     64 <-----------------> 072F 73 [ increases minimum cycle time from 2600 (64) to 3000 ms (73) ]
204 067D     20    0B36     20 <-----------------> 0B36 20 [ USE A VALUE OF 20 FOR THE NEC - as in the initial patch! CHANGES CAUSE VFR-ERROR 10 ]
205 1FFE     2B    3FFE     1B  (BIOS CHECKSUM)
206 1FFF     70    3FFF     88  (BIOS CHECKSUM)
207 
208 --------------------------------------------------------------
209 Meaning of Diagnostics LEDs (from PC100ESV1.PDF found, e.g.,
210 on ftp://ftp.update.uu.se/pub/rainbow/doc/rainbow-docs/
211 
212 Internal Diagnostic Messages                               F
213 Msg Message                               Lights Display   A
214 No.                                       * = on o = off   T
215 ..........................................- = on or off    A
216 ..........................................1 2 3 4 5 6 7    L
217 --------------------------------------------------------------
218 .1  Main Board (Video)                    o * * o * o *   Yes
219 .2  Main Board* (unsolicited interrupt)   * * * * o * o   Yes
220 .3  Drive A or B (index)                  o o * o o * *
221 .4  Drive A or B (motor)                  * * o o o * *
222 .5  Drive A or B (seek)                   o * o o o * *
223 .6  Drive A or B (read)                   * o o o o * *
224 .7  Drive A or B (restore)                o * * o o * *
225 .8  Drive A or B (step)                   * o * o o * *
226 .9  System Load incomplete+ (System Load) o o o o o o o
227 10  Main Board (video, vfr)               * * * o * o *   Yes
228 11  System Load incomplete+ (Boot Load)   o o o o o o o
229 12  Drive A or B (not ready)              o o o o o * *
230 13  Keyboard                              * * o * o * o   Yes
231 14  Main Board (nvm data)                 * * * * o * *
232 15  (no msg. 15 in that table)
233 16  Interrupts off*                       * * * o o o o   Cond.
234 17  Main Board (video RAM)                * * * o * * o   Yes
235 18  Main Board (Z80 crc)                  * * * * o o *   Yes
236 19  Main Board RAM (0-64K)                - - - * * o *   Yes
237 20  Main Board (unsolicited int., Z80)    * * * o o o *   Yes
238 21  Drive Not Ready+                      o o o o o o o
239 22  Remove Card or Diskette               o * * o o o *
240 23  Non-System Diskette+                  o o o o o o o
241 24  new memory size = nnnK                o o o o o o o
242 25  Set Up Defaults stored                o o o o o o o
243 26  Main Board (RAM arbitration)          * * * o * o o   Yes
244 27  Main Board (RAM option)               - - - * * o o
245 28  RX50 controller board                 * * * o o * *
246 29  Main Board* (Z80 response)            * * * * o o o
247 30  Main Board (ROM crc, ROM 0)           * * * * * * *   Yes
248 31  Main Board (ROM crc, ROM 1)           * * * * * * o   Yes
249 -   Main Board (ROM crc, ROM 2)           * * * o * * *   Yes
250 33  Main Board (contention)               o o o o o * o   Yes
251 40  Main Board (printer port)             * o * * o * o
252 50  Main Board (keyboard port)            o o * * o * o   Yes
253 60  Main Board (comm port)                o * * * o * o
254 --------------------------------------------------------------
255 *   These errors can occur at any time because the circuits
256 are monitored constantly
257 +   These messages may occur during power-up if auto boot is
258 selected
259 
260 PCB layout
261 ==========
262 
263 DEC-100 model B
264 = part no.70-19974-02 according to document EK-RB100-TM_001
265 
266 PCB # 5416206 / 5016205-01C1:
267 
268 7-6-5-4 |3-2-1
269 DIAGNOSTIC-LEDs |J3   | |J2     | |J1    |
270 |------|----8088|Z80-|--|VIDEO|-|PRINTER|-|SERIAL|----|
271 |  2 x 64 K             |/KBD.|                  !!!!!|
272 |  R  A  M              NEC D7201C            |P|!W90!|
273 |                                             |O|!!!!!|
274 |   [W6]    ROM 1       INTEL 8088            |W|     |
275 |           (23-020e5-00)                     |E|     |
276 |                                             |R|     |
277 | ...J5..   BOOT ROM 0      ...J4...          =J8     |
278 |           (23-022e5-00)                             |
279 | ...J6...                                            |
280 | [W5]                                                |
281 |                                                     |
282 |     INTEL 8251A   ZILOG Z 80A                       |
283 |                [W18]                                |
284 | A  4x                74 LS 244                      |
285 | M  S           [W15]                                |
286 | 9  -   DEC-DC011     74 LS 245                      |
287 | 1  R           [W14]                                |
288 | 2  A                  [W13]                         |
289 | 8  M   CHARGEN.-                                    |
290 |        ROM (4K)            ...J7...  | ...J9 = RX50 |
291 |                                                     |
292 |-------------PCB# 5416206 / 5016205-01C1-------------|
293 
294 CONNECTORS ("J"):
295     ...J5... ...J4... both: RD51 controller (hard disk)
296     ...J5... ...J4... both: EXTENDED COMM. controller
297 
298     ...J6... is the MEMORY OPTION connector (52 pin)
299     ...J7... is the GRAPHICS OPTION connector (40 pin)
300     ...J9... RX50 FLOPPY CONTROLLER (40 pin; REQUIRED)
301 
302 JUMPERS (labeled "W"):
303   W5 + W6 are out when 16K x 8 EPROMS are used
304 / W5 + W6 installed => 32 K x 8 EPROMs (pin 27 = A14)
305 
306 W13, W14, W15, W18 = for manufacturing tests.
307 => W13 - W15 affect diagnostic read register (port $0a)
308 => W18 pulls DSR to ground and affects 8251A - port $11 (bit 7)
309 
310 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
311 !! DO NOT SHORT JUMPER / CONNECTOR [W90] ON LIVE HARDWARE  !!
312 !!                                                         !!
313 !! WARNING:  CIRCUIT DAMAGE could occur if this jumper is  !!
314 !! set by end users.        See PDF document AA-V523A-TV.  !!
315 !!                                                         !!
316 !! W90 connects to pin 2 (Voltage Bias on PWR connector J8)!!
317 !! and is designed FOR ===> FACTORY TESTS OF THE PSU <===  !!
318 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
319 
320 WIRE CONNECTORS - SEEN ON SCHEMATICS - NOT PRESENT ON DEC-100 B (-A only?):
321 W16 pulls J2 printer port pin 1 to GND when set (chassis to logical GND).
322 W17 pulls J1 serial  port pin 1 to GND when set (chassis to logical GND).
323 ****************************************************************************/
324 #include "emu.h"
325 
326 #include "cpu/i86/i86.h"
327 #include "cpu/z80/z80.h"
328 #include "video/vtvideo.h"
329 #include "video/upd7220.h"
330 
331 #include "machine/wd_fdc.h"
332 #include "formats/rx50_dsk.h"
333 #include "formats/pc_dsk.h" // PC Formats
334 #include "imagedev/floppy.h"
335 
336 #include "imagedev/harddriv.h"
337 #include "machine/wd2010.h"
338 #include "machine/corvushd.h"
339 
340 #include "machine/z80sio.h"
341 #include "bus/rs232/rs232.h"
342 #include "imagedev/bitbngr.h"
343 #include "machine/com8116.h"
344 #include "bus/rs232/hlemouse.h"
345 #include "bus/rs232/terminal.h"
346 
347 #include "machine/i8251.h"
348 #include "machine/dec_lk201.h"
349 #include "machine/nvram.h"
350 #include "machine/ripple_counter.h"
351 #include "machine/timer.h"
352 #include "machine/ram.h"
353 
354 #include "machine/ds1315.h"
355 #include "emupal.h"
356 #include "softlist.h"
357 #include "screen.h"
358 
359 #include "rainbow.lh" // BEZEL - LAYOUT with LEDs for diag 1-7, keyboard 8-11 and floppy 20-23
360 
361 #define RD51_MAX_HEAD 8
362 #define RD51_MAX_CYLINDER 1024
363 #define RD51_SECTORS_PER_TRACK 17
364 
365 #define RTC_ENABLED
366 // Tested drivers (from Suitable Solutions distribution disk and Latrobe archive), preferred first -
367 // File.........Version / author ------------------- YY/YYYY ----- Read only RTC_BASE ---- Platform
368 // RBCLIK21.COM Author: Vincent Esser. With source.. 4 digits (Y2K)..Y.......$fc000/fe000..100-B (default cfg.)
369 // CLIKA.COM .. V1.03A (C) 1987 Suitable Solutions.. 2 digits........N (*)...$ed000........100-A
370 // CLIKCLOK.COM V1.01 (C) 1986,87 Suitable Solutions 2 digits........N (*)...$fc000/fe000..100-B (default   " )
371 // CLIKF4.COM . V1.0  (C) 1986 Suitable Solutions... 2 digits........N (*)...$f4000........100-B (alternate " )
372 // (*)   Time or date changes are not persistent in emulation. To prove the setter works, changes are logged.
373 
374 // (Y2K) DS1315 unit only holds 2 digits, so Vincent Esser's freeware employs a windowing technique.
375 //       While Suitable's DOS 3.10 accepts dates > 2000, don't take that for granted with software from the 80s.
376 //  Model B can have an RTC mapped at 0xF4000 instead - ClikClok V1.0 / CLIKF4.COM
377 
378 // ----------------------------------------------------------------------------------------------
379 // * MHFU disabled by writing a _sensible_ value to port 0x10C (instead of port 0x0c)
380 // Note: documentation incorrectly claims that zero must be written to 0x10C.
381 
382 // * MHFU re-enabled by writing to 0x0c.
383 // DEC says that MHFU is also re-enabled 'automatically after STI' (when under BIOS control?)
384 
385 // Schematics show "VERT FREQ INT" (= DC012 output, pin 2) and MHFU ENBL L are evaluated,
386 //  as well as the power good signal from the PSU (AC_OK). MS_TO_POWER_GOOD is a guess:
387 #define MS_TO_POWER_GOOD 350
388 // Reset duration of 108 ms from documentation -
389 #define RESET_DURATION_MS 108
390 
391 // Driver uses an IRQ callback from the 8088 -and a counter- to determine if the CPU is alive.
392 // Counter is reset by writing to 0x10c, or by acknowledging (!) a VBL IRQ within 108 ms.
393 #define MHFU_IS_ENABLED 1
394 #define MHFU_COUNT -1
395 #define MHFU_VALUE -2
396 #define MHFU_RESET_and_ENABLE   -100
397 #define MHFU_RESET_and_DISABLE  -200
398 #define MHFU_RESET              -250
399 
400 // ----------------------------------------------------------------------------------------------
401 // NEC 7220 GDC     *************************************
402 
403 // Indirect Register, port $53, see page 181 of AA-AE36A (PDF):
404 // (actual values : see comments)
405 #define GDC_SELECT_WRITE_BUFFER  0x01 // 0xFE
406 #define GDC_SELECT_PATTERN_MULTIPLIER 0x02 // 0xFD
407 #define GDC_SELECT_PATTERN       0x04 // 0xFB
408 #define GDC_SELECT_FG_BG         0x08 // 0xF7
409 #define GDC_SELECT_ALU_PS        0x10 // 0xEF
410 #define GDC_SELECT_COLOR_MAP     0x20 // 0xDF
411 #define GDC_SELECT_MODE_REGISTER 0x40 // 0xBF
412 #define GDC_SELECT_SCROLL_MAP    0x80 // 0x7F
413 
414 // MODE REGISTER
415 #define GDC_MODE_HIGHRES        0x01
416 #define GDC_MODE_VECTOR         0x02
417 
418 // ( " ) READBACK OPERATION  (if ENABLE_WRITES = 0):
419 #define GDC_MODE_ENABLE_WRITES       0x10
420 #define GDC_MODE_READONLY_SCROLL_MAP 0x20
421 
422 // ( " )  READBACK OPERATION  (plane select = bit mask in bits 2 + 3 of MODE register):
423 #define GDC_MODE_READBACK_PLANE_MASK 12
424 #define GDC_MODE_READBACK_PLANE_00  0x00
425 #define GDC_MODE_READBACK_PLANE_01  0x04
426 #define GDC_MODE_READBACK_PLANE_02  0x08
427 #define GDC_MODE_READBACK_PLANE_03  0x0c
428 
429 #define GDC_MODE_ENABLE_VSYNC_IRQ 0x40
430 #define GDC_MODE_ENABLE_VIDEO   0x80
431 
432 // ALU_PS REGISTER (bits 5 + 4):
433 #define ALU_PS_MODE_MASK 48
434 #define REPLACE_MODE    00
435 #define COMPLEMENT_MODE 16
436 #define OVERLAY_MODE    32
437 
438 // ----------------------------------------------------------------------------------------------
439 #define LK201_TAG   "lk201"
440 #define FD1793_TAG  "fd1793x"
441 
442 #define INVALID_DRIVE 255
443 #define MAX_FLOPPIES 4
444 
445 // Monitor configurations -> see DIP switches. New: auto-detect color palette (last option).
446 static constexpr int MONO_MONITOR = 0x01;  // Tetris-M and Pacman-M need this setting (no auto-detection)
447 static constexpr int COLOR_MONITOR = 0x02; // DEC recommendation. GWBASIC and most old libraries. Superseded by later development
448 static constexpr int DUAL_MONITOR = 0x03;  // Debugging, AutoCad, 'newer' freeware. Green is missing with unpatched software (for technical reasons)
449 static constexpr int AUTODETECT_MONITOR = 0x04;  // Snoop palette, then choose best output.
450 
451 class rainbow_base_state : public driver_device
452 {
453 public:
rainbow_base_state(const machine_config & mconfig,device_type type,const char * tag)454 	rainbow_base_state(const machine_config &mconfig, device_type type, const char *tag) :
455 		driver_device(mconfig, type, tag),
456 
457 		m_inp1(*this, "W13"),
458 		m_inp2(*this, "W14"),
459 		m_inp3(*this, "W15"),
460 		m_inp4(*this, "W18"),
461 		m_inp5(*this, "DEC_HARD_DISK"), // DO NOT CHANGE ORDER
462 		m_inp6(*this, "CORVUS_HARD_DISKS"), // DO NOT CHANGE ORDER
463 		m_inp7(*this, "GRAPHICS_OPTION"),   // DO NOT CHANGE ORDER
464 		m_inp9(*this, "MONO_MONITOR_TYPE"),
465 		m_inp10(*this, "J17"),
466 		m_inp11(*this, "CLIKCLOK"),
467 		m_inp12(*this, "WATCHDOG"),
468 		m_inp13(*this, "MONITOR_CONFIGURATION"),
469 
470 		m_crtc(*this, "vt100_video"),
471 
472 		m_i8088(*this, "maincpu"),
473 		m_z80(*this, "subcpu"),
474 		m_ram(*this, "ram"),
475 
476 		m_fdc(*this, FD1793_TAG),
477 		m_floppies(*this, FD1793_TAG ":%u", 0U),
478 		m_hdc(*this, "hdc"),
479 		m_corvus_hdc(*this, "corvus"),
480 
481 		m_mpsc(*this, "mpsc"),
482 		m_dbrg(*this, "dbrg"),
483 		m_comm_port(*this, "comm"),
484 
485 		m_kbd8251(*this, "kbdser"),
486 		m_lk201(*this, LK201_TAG),
487 
488 		m_p_ram(*this, "p_ram"),
489 
490 		m_p_vol_ram(*this, "vol_ram"),
491 		m_p_nvram(*this, "nvram"),
492 
493 		m_rtc(*this, "rtc"),
494 		m_hgdc(*this, "upd7220"), // GDC
495 
496 		m_screen2(*this, "screen2"),
497 		m_palette2(*this, "palette2"), // GDC
498 		m_video_ram(*this, "vram"),
499 
500 		m_digits(*this, "digit%u", 0U),
501 		m_leds(*this, "led%u", 1U),
502 		m_driveleds(*this, "driveled%u", 0U)
503 	{
504 	}
505 
506 	void rainbow_base(machine_config &config);
507 
508 protected:
509 	virtual void machine_start() override;
510 	virtual void machine_reset() override;
511 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
512 
513 	void rainbow8088_base_map(address_map &map);
514 	void rainbow8088_base_io(address_map &map);
515 
516 	uint8_t ext_ram_r(offs_t offset);
517 
518 	void rtc_w(offs_t offset, uint8_t data);
519 
520 	uint8_t read_video_ram_r(offs_t offset);
521 	DECLARE_WRITE_LINE_MEMBER(video_interrupt);
522 
523 	uint8_t diagnostic_r();
524 	void diagnostic_w(uint8_t data);
525 
526 	uint8_t comm_control_r();
527 	void comm_control_w(uint8_t data);
528 
529 	uint8_t share_z80_r(offs_t offset);
530 	void share_z80_w(offs_t offset, uint8_t data);
531 
532 	// 'RD51' MFM CONTROLLER (WD1010) *************************************
533 	uint8_t hd_status_60_r(); // TRI STATE DATA PORT (R/W)
534 	void hd_status_60_w(uint8_t data);
535 
536 	uint8_t hd_status_68_r(); // EXTRA REGISTER 0x68 (R/W 8088)
537 	void hd_status_68_w(uint8_t data);
538 
539 	uint8_t hd_status_69_r(); // EXTRA REGISTER 0x69 (R/- 8088)
540 
541 	DECLARE_WRITE_LINE_MEMBER(bundle_irq);
542 	DECLARE_WRITE_LINE_MEMBER(hdc_bdrq);  // BUFFER DATA REQUEST (FROM WD)
543 	DECLARE_WRITE_LINE_MEMBER(hdc_bcr);   // BUFFER COUNTER RESET (FROM WD)
544 
545 	DECLARE_WRITE_LINE_MEMBER(hdc_step);
546 	DECLARE_WRITE_LINE_MEMBER(hdc_direction);
547 
548 	DECLARE_WRITE_LINE_MEMBER(hdc_read_sector);
549 	DECLARE_WRITE_LINE_MEMBER(hdc_write_sector);
550 
551 	DECLARE_READ_LINE_MEMBER(hdc_drive_ready);
552 	DECLARE_READ_LINE_MEMBER(hdc_write_fault);
553 
554 	uint8_t corvus_status_r();
555 
556 	uint8_t i8088_latch_r();
557 	void i8088_latch_w(uint8_t data);
558 	uint8_t z80_latch_r();
559 	void z80_latch_w(uint8_t data);
560 
561 	void z80_diskdiag_read_w(uint8_t data);
562 	void z80_diskdiag_write_w(uint8_t data);
563 
564 	uint8_t z80_generalstat_r();
565 
566 	uint8_t z80_diskstatus_r();
567 	void z80_diskcontrol_w(uint8_t data);
568 
569 	DECLARE_WRITE_LINE_MEMBER(kbd_tx);
570 	DECLARE_WRITE_LINE_MEMBER(kbd_rxready_w);
571 	DECLARE_WRITE_LINE_MEMBER(kbd_txready_w);
572 
573 	uint8_t rtc_reset();
574 	uint8_t rtc_enable();
575 
576 	DECLARE_WRITE_LINE_MEMBER(mpsc_irq);
577 	void comm_bitrate_w(uint8_t data);
578 	void printer_bitrate_w(uint8_t data);
579 	void bitrate_counter_w(uint8_t data);
580 	DECLARE_WRITE_LINE_MEMBER(dbrg_fr_w);
581 	DECLARE_WRITE_LINE_MEMBER(dbrg_ft_w);
582 
583 	void GDC_EXTRA_REGISTER_w(offs_t offset, uint8_t data);
584 	uint8_t GDC_EXTRA_REGISTER_r(offs_t offset);
585 
586 	uint32_t screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
587 	IRQ_CALLBACK_MEMBER(irq_callback);
588 
589 	TIMER_DEVICE_CALLBACK_MEMBER(hd_motor_tick);
590 
591 	DECLARE_FLOPPY_FORMATS(floppy_formats);
592 
593 	UPD7220_DISPLAY_PIXELS_MEMBER( hgdc_display_pixels );
594 	uint16_t vram_r(offs_t offset);
595 	void vram_w(offs_t offset, uint16_t data);
596 	DECLARE_WRITE_LINE_MEMBER(GDC_vblank_irq);
597 
598 	void rainbowz80_io(address_map &map);
599 	void rainbowz80_mem(address_map &map);
600 	void upd7220_map(address_map &map);
601 	enum
602 	{   // LOWEST PRIORITY
603 		// Mnemonic - - - - - -  TYPE  ADDRESS - Source
604 		//                      [1][0]  [1][0] <= Depends on DTR(L) output of keyboard PUSART (on Rainbow-100 B)
605 		IRQ_8088_MAILBOX = 0, // 27/A7  9C/29C  - [built-in] Interrupt from Z80A
606 		IRQ_8088_KBD,         // 26/A6  98/298  - [built-in] KEYBOARD Interrupt - 8251A
607 		IRQ_BDL_INTR_L,       // 25/A5  94/294  - [ext. BUNDLE OPTION] Hard disk or Extended communication IRQ (no DMA)
608 		IRQ_COMM_PTR_INTR_L,  // 24/A4  90/290  - [built-in 7201] Communication/Printer interrupt
609 		IRQ_DMAC_INTR_L,      // 23/A3  8C/28C  - [ext. COMM.BOARD only] - external DMA Controller (8237) interrupt
610 		IRQ_GRF_INTR_L,       // 22/A2  88/288  - [ext. COLOR GRAPHICS]
611 		IRQ_BDL_INTR_1L,      // 21/A1  84/284  - [ext. COMM.BOARD only]
612 		IRQ_8088_VBL,         // 20/A0  80/280  - [built-in DC012] - VERT INTR L (= schematics)
613 		IRQ_8088_NMI          // 02/02  08/08   - [external MEMORY EXTENSION] - PARITY ERROR L
614 	};  // HIGHEST PRIORITY
615 
616 	required_ioport m_inp1;
617 	required_ioport m_inp2;
618 	required_ioport m_inp3;
619 	required_ioport m_inp4;
620 	required_ioport m_inp5;
621 	required_ioport m_inp6;
622 	required_ioport m_inp7;
623 	required_ioport m_inp9;
624 	required_ioport m_inp10;
625 	required_ioport m_inp11;
626 	required_ioport m_inp12;
627 	required_ioport m_inp13;
628 	required_device<rainbow_video_device> m_crtc;
629 	required_device<cpu_device> m_i8088;
630 	required_device<cpu_device> m_z80;
631 	required_device<ram_device> m_ram;
632 
633 	required_device<fd1793_device> m_fdc;
634 	required_device_array<floppy_connector, 4> m_floppies;
635 	optional_device<wd2010_device> m_hdc;
636 
637 	required_device<corvus_hdc_device> m_corvus_hdc;
638 
639 	required_device<upd7201_device> m_mpsc;
640 	required_device<com8116_003_device> m_dbrg;
641 	required_device<rs232_port_device> m_comm_port;
642 
643 	required_device<i8251_device> m_kbd8251;
644 	required_device<lk201_device> m_lk201;
645 	required_shared_ptr<uint8_t> m_p_ram;
646 	required_shared_ptr<uint8_t> m_p_vol_ram;
647 	required_shared_ptr<uint8_t> m_p_nvram;
648 
649 	optional_device<ds1315_device> m_rtc;
650 
651 	required_device<upd7220_device> m_hgdc;  // GDC
652 	required_device<screen_device> m_screen2;
653 	required_device<palette_device> m_palette2;
654 	required_shared_ptr<uint16_t> m_video_ram;
655 
656 	output_finder<2> m_digits;
657 	output_finder<7> m_leds;
658 	output_finder<4> m_driveleds;
659 
660 	void raise_8088_irq(int ref);
661 	void lower_8088_irq(int ref);
662 
663 	void update_mpsc_irq();
664 	int m_mpsc_irq;
665 	void update_8088_irqs();
666 
667 	void update_bundle_irq(); // RD51 or COMM.OPTION!
668 	int do_write_sector();
669 	void hdc_buffer_counter_reset();
670 	void hdc_reset();
671 
672 	hard_disk_file *rainbow_hdc_file(int ref);
673 
674 	uint8_t m_gdc_write_buffer[16]; // 16 x 8 bits for CPU, 8 x 16 for GDC
675 	uint8_t m_gdc_color_map[32];
676 	uint8_t m_gdc_scroll_buffer[256];
677 
678 	uint8_t  m_gdc_indirect_register;
679 	uint8_t  m_gdc_mode_register;
680 	uint8_t  m_gdc_scroll_index;
681 	uint8_t  m_gdc_color_map_index;
682 	uint8_t  m_gdc_write_buffer_index;
683 	uint8_t  m_gdc_alu_ps_register;
684 	uint8_t  m_gdc_fg_bg;
685 	uint8_t  m_vpat, m_patmult, m_patcnt, m_patidx;
686 
687 	uint16_t m_gdc_write_mask;
688 
689 	bool m_onboard_video_selected;   // (internal switch, on board video to mono out)
690 	bool m_screen_blank;
691 
692 	uint8_t m_monitor_suggested;
693 
694 	int m_int88;
695 	int m_intz80;
696 
697 	bool m_zflip;                   // Z80 alternate memory map with A15 inverted
698 	bool m_z80_halted;
699 	int  m_z80_diskcontrol;         // retains values needed for status register
700 
701 	uint8_t m_printer_bitrate;
702 
703 	bool m_kbd_tx_ready, m_kbd_rx_ready;
704 	int m_KBD;
705 
706 	uint8_t m_diagnostic;
707 
708 	uint8_t m_z80_private[0x800];     // Z80 private 2K
709 	uint8_t m_z80_mailbox, m_8088_mailbox;
710 
711 	void update_kbd_irq();
712 
713 	int m_present_drive;
714 	floppy_image_device *m_floppy;
715 
716 	int m_irq_high;
717 	uint32_t m_irq_mask;
718 
719 	int m_bdl_irq;
720 	int m_hdc_buf_offset;
721 
722 	bool m_hdc_index_latch;
723 	bool m_hdc_step_latch;
724 	int m_hdc_direction;
725 	bool m_hdc_write_gate;
726 
727 	bool m_hdc_drive_ready;
728 	bool m_hdc_write_fault;
729 
730 	uint8_t m_hdc_buffer[2048];
731 
732 	bool m_power_good;
733 	emu_timer   *cmd_timer;
734 	emu_timer   *switch_off_timer;
735 
736 	const int vectors[9] = { 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x02 };
737 
738 	// VIDEO LEVELS:  0 is 100 % output; F is 0 % output. Range of 0...255.
739 	// LIMITED RANGE levels for 100-A model (valid only for all mono + green out on COLOR MONITOR):
740 	//const uint8_t A_MONO_GREEN_video_levels[16] = { 255 , 185,  166, 21, 255 , 185,  166, 21, 255 , 185,  166, 21, 255 , 185,  166, 21};
741 
742 	// FULL RANGE video levels for 100-B model, taken from page 46 of PDF
743 	const uint8_t video_levels[16] = { 255, 217,  201,186, 171, 156, 140, 125, 110, 97, 79, 66, 54, 31, 18, 0 };
744 
745 	const int comm_rates[16] = { 50,75,110,134,150,200,300,600,1200,1800,2000,2400,3600,4800,9600,19200 };
746 };
747 
748 class rainbow_modela_state : public rainbow_base_state
749 {
750 public:
rainbow_modela_state(const machine_config & mconfig,device_type type,const char * tag)751 	rainbow_modela_state(const machine_config &mconfig, device_type type, const char *tag) :
752 		rainbow_base_state(mconfig, type, tag)
753 	{
754 	}
755 
756 	void rainbow_modela(machine_config &config);
757 
758 private:
759 	virtual void machine_reset() override;
760 
761 	void rainbow8088_map(address_map &map);
762 	void rainbow8088_io(address_map &map);
763 
764 	void ext_ram_w(offs_t offset, uint8_t data);
765 	uint8_t rtc_r(offs_t offset);
766 	DECLARE_WRITE_LINE_MEMBER(irq_hi_w);
767 	uint8_t system_parameter_r();
768 };
769 
770 class rainbow_modelb_state : public rainbow_base_state
771 {
772 public:
rainbow_modelb_state(const machine_config & mconfig,device_type type,const char * tag)773 	rainbow_modelb_state(const machine_config &mconfig, device_type type, const char *tag) :
774 		rainbow_base_state(mconfig, type, tag)
775 	{
776 	}
777 
778 	void rainbow_modelb(machine_config &config);
779 
780 private:
781 	virtual void machine_reset() override;
782 
783 	void rainbow8088_map(address_map &map);
784 	void rainbow8088_io(address_map &map);
785 
786 	void ext_ram_w(offs_t offset, uint8_t data);
787 	uint8_t rtc_r(offs_t offset);
788 	DECLARE_WRITE_LINE_MEMBER(irq_hi_w);
789 	uint8_t system_parameter_r();
790 };
791 
792 // It * should be * OK to RESET the SCROLL_BUFFER and the COLOR_MAP (at least with WELL WRITTEN programs)
793 
794 // Situation less clear for vector mode (some programs work extensively * before * OPTION_GRFX_RESET
795 
796 // THIS MACRO * RESETS *  the PATTERN TO DEFAULT.
797 // NOTE 2: m_patmult  MUST BE LOADED BEFORE !!
798 #define OPTION_RESET_PATTERNS \
799 	m_vpat = 0xff;                              \
800 	if (m_patmult == 0)  m_patmult = 0x01;      \
801 	if (m_patcnt == 0)   m_patcnt = m_patmult;  \
802 	if (m_patidx == 0)   m_patidx = 7;
803 
804 
805 // GDC RESET MACRO - used in  "machine_reset"  & GDC_EXTRA_REGISTER_w   !
806 #define OPTION_GRFX_RESET                                   \
807 	lower_8088_irq(IRQ_GRF_INTR_L);                         \
808 	m_monitor_suggested = m_inp13->read();                  \
809 	m_gdc_indirect_register = 0;                            \
810 	m_gdc_color_map_index = 0;                              \
811 	for (int i = 0; i < 256; i++)                           \
812 		m_gdc_scroll_buffer[i] = i;                         \
813 	m_gdc_scroll_index = 0;                                 \
814 	m_gdc_write_buffer_index = 0;                           \
815 	m_gdc_write_mask = 0x00;                                \
816 	m_gdc_alu_ps_register = 0x0F;                           \
817 	m_gdc_fg_bg = 0xF0;                                     \
818 	m_gdc_mode_register &= GDC_MODE_VECTOR | GDC_MODE_HIGHRES | GDC_MODE_ENABLE_WRITES | GDC_MODE_READONLY_SCROLL_MAP;\
819 	m_gdc_mode_register |= GDC_MODE_ENABLE_VIDEO;           \
820 	logerror("\n** OPTION GRFX. RESET **\n");
821 
UPD7220_DISPLAY_PIXELS_MEMBER(rainbow_base_state::hgdc_display_pixels)822 UPD7220_DISPLAY_PIXELS_MEMBER( rainbow_base_state::hgdc_display_pixels )
823 {
824 	if(m_inp7->read() == 0)
825 		return;
826 
827 	const rgb_t *paletteX = m_palette2->palette()->entry_list_raw();
828 
829 	uint16_t plane0, plane1, plane2, plane3;
830 	uint8_t pen;
831 
832 	if (m_onboard_video_selected && (m_inp13->read() != DUAL_MONITOR))
833 	{
834 		for (int xi = 0; xi < 16; xi++) // blank screen when VT102 output active (..)
835 		{
836 			if (bitmap.cliprect().contains(x + xi, y))
837 				bitmap.pix(y, x + xi) = 0;
838 		}
839 		return; // no output from graphics option
840 	}
841 
842 	// ********************* GET BITMAP DATA FOR 4 PLANES ***************************************
843 	// _READ_ BIT MAP  from 2 or 4 planes (plane 0 is least, plane 3 most significant). See page 42 / 43
844 	if (m_gdc_mode_register & GDC_MODE_HIGHRES)
845 	{
846 		address = ( m_gdc_scroll_buffer[ ((address & 0x7FC0) >> 7) & 0xff ] << 7) |  (address & 0x7F);
847 		plane0 = m_video_ram[((address & 0x7fff) + 0x00000) >> 1];
848 		plane1 = m_video_ram[((address & 0x7fff) + 0x10000) >> 1];
849 		plane2 = plane3 = 0;
850 	}
851 	else
852 	{
853 		address = ( m_gdc_scroll_buffer[ ((address & 0x3FC0) >> 7) & 0xff ] << 7) |  (address & 0x7F);
854 		// MED.RESOLUTION (4 planes, 4 color bits, 16 color map entries / 16 -or 4- MONOCHROME SHADES)
855 		plane0 = m_video_ram[((address & 0x3fff) + 0x00000) >> 1];
856 		plane1 = m_video_ram[((address & 0x3fff) + 0x10000) >> 1];
857 		plane2 = m_video_ram[((address & 0x3fff) + 0x20000) >> 1];
858 		plane3 = m_video_ram[((address & 0x3fff) + 0x30000) >> 1];
859 	}
860 
861 	bool mono = (m_monitor_suggested == MONO_MONITOR) ? true : false; // 1 = MONO, 2 = COLOR, 3 = DUAL MONITOR; 4 = AUTO
862 
863 	for (int xi = 0; xi < 16; xi++)
864 	{
865 		pen = BIT(plane0 ,xi) |
866 			 (BIT(plane1 ,xi) << 1) |
867 			 (BIT(plane2 ,xi) << 2) |
868 			 (BIT(plane3 ,xi) << 3);
869 
870 		if (bitmap.cliprect().contains(x + xi, y))
871 			bitmap.pix(y, x + xi) = paletteX[mono ? (pen + 16) : pen];
872 	}
873 }
874 
FLOPPY_FORMATS_MEMBER(rainbow_base_state::floppy_formats)875 FLOPPY_FORMATS_MEMBER(rainbow_base_state::floppy_formats)
876 FLOPPY_RX50IMG_FORMAT,
877 FLOPPY_TD0_FORMAT,
878 FLOPPY_IMD_FORMAT,
879 FLOPPY_PC_FORMAT
880 FLOPPY_FORMATS_END
881 
882 static void rainbow_floppies(device_slot_interface &device)
883 {
884 	device.option_add("525qd", FLOPPY_525_QD); // QD means 80 tracks with DD data rate (single or double sided).
885 	device.option_add("525dd", FLOPPY_525_DD); // mimic a 5.25" PC (40 track) drive. Requires IDrive5.SYS.
886 	device.option_add("35dd", FLOPPY_35_DD); // mimic 3.5" PC drive (720K, double density). Use Impdrv3.SYS.
887 	device.option_add("525ssdd", FLOPPY_525_SSDD); // to read a single sided, (160K) PC-DOS 1 disk with MediaMaster
888 }
889 
machine_start()890 void rainbow_base_state::machine_start()
891 {
892 	m_power_good = false; // Simulate AC_OK signal from power supply.
893 	cmd_timer = timer_alloc(0);
894 	cmd_timer->adjust(attotime::from_msec(MS_TO_POWER_GOOD));
895 
896 	switch_off_timer = timer_alloc(1);
897 	switch_off_timer->adjust(attotime::from_msec(10));
898 
899 	m_digits.resolve();
900 	m_leds.resolve();
901 	m_driveleds.resolve();
902 
903 	m_screen_blank = false;
904 
905 	auto *printer_port = subdevice<rs232_port_device>("printer");
906 	printer_port->write_dtr(0);
907 	printer_port->write_rts(0);
908 
909 	save_item(NAME(m_z80_private));
910 	save_item(NAME(m_z80_mailbox));
911 	save_item(NAME(m_8088_mailbox));
912 	save_item(NAME(m_zflip));
913 	save_item(NAME(m_printer_bitrate));
914 	save_item(NAME(m_kbd_tx_ready));
915 	save_item(NAME(m_kbd_rx_ready));
916 	save_item(NAME(m_irq_high));
917 	save_item(NAME(m_irq_mask));
918 }
919 
920 
921 
rainbow8088_base_map(address_map & map)922 void rainbow_base_state::rainbow8088_base_map(address_map &map)
923 {
924 	map.unmap_value_high();
925 
926 	// There is a 2212 (256 x 4 bit) NVRAM from 0xed000 to 0xed0ff (*)
927 	// shadowed at $ec000 - $ecfff and from $ed100 - $edfff.
928 
929 	// (*) ED000 - ED0FF is the area the DEC-100-B Bios accesses and checks
930 
931 	//  - Specs say that the CPU has direct access to volatile RAM only.
932 	//    So NVRAM is hidden and loads & saves are triggered within the
933 	//    'diagnostic_w' handler (similar to real hardware).
934 
935 	//  - Address bits 8-12 are ignored (-> mirror()).
936 	map(0xed000, 0xed0ff).ram().share("vol_ram"); //.mirror(0x1f00);
937 	map(0xed100, 0xed1ff).ram().share("nvram");
938 
939 	map(0xee000, 0xeffff).ram().share("p_ram");
940 	map(0xf0000, 0xfffff).rom();
941 }
942 
rainbow8088_map(address_map & map)943 void rainbow_modela_state::rainbow8088_map(address_map &map)
944 {
945 	rainbow8088_base_map(map);
946 	map(0x00000, 0xcffff).rw(FUNC(rainbow_modela_state::ext_ram_r), FUNC(rainbow_modela_state::ext_ram_w));
947 
948 #ifdef RTC_ENABLED
949 	// *********************************** / DS1315 'PHANTOM CLOCK' IMPLEMENTATION FOR 'DEC-100-A' ***************************************
950 	map(0xed000, 0xed000).r(FUNC(rainbow_modela_state::rtc_r));
951 	map(0xed0fe, 0xed0ff).w(FUNC(rainbow_modela_state::rtc_w));
952 	// *********************************** / DS1315 'PHANTOM CLOCK' IMPLEMENTATION FOR 'DEC-100-A' ***************************************
953 #endif
954 }
955 
956 // DEC-100-B probes until a 'flaky' area is found (BOOT ROM around F400:0E04).
957 // It is no longer possible to key in the RAM size from within the 100-B BIOS.
rainbow8088_map(address_map & map)958 void rainbow_modelb_state::rainbow8088_map(address_map &map)
959 {
960 	rainbow8088_base_map(map);
961 	map(0x00000, 0xdffff).rw(FUNC(rainbow_modelb_state::ext_ram_r), FUNC(rainbow_modelb_state::ext_ram_w));
962 
963 #ifdef RTC_ENABLED
964 	// *********************************** / DS1315 'PHANTOM CLOCK' IMPLEMENTATION FOR 'DEC-100-B' ***************************************
965 	// No address space needed ( -> IRQs must be disabled to block ROM accesses during reads ).
966 	map(0xfc000, 0xfe104).r(FUNC(rainbow_modelb_state::rtc_r));
967 	// *********************************** / DS1315 'PHANTOM CLOCK' IMPLEMENTATION FOR 'DEC-100-B' ***************************************
968 #endif
969 }
970 
rainbow8088_base_io(address_map & map)971 void rainbow_base_state::rainbow8088_base_io(address_map &map)
972 {
973 	map.unmap_value_high();
974 	map.global_mask(0x1ff);
975 	map(0x00, 0x00).rw(FUNC(rainbow_base_state::i8088_latch_r), FUNC(rainbow_base_state::i8088_latch_w));
976 	map(0x02, 0x02).rw(FUNC(rainbow_base_state::comm_control_r), FUNC(rainbow_base_state::comm_control_w)); // Communication status / control register (8088)
977 	map(0x04, 0x04).w(m_crtc, FUNC(rainbow_video_device::dc011_w));
978 
979 	map(0x06, 0x06).w(FUNC(rainbow_base_state::comm_bitrate_w));
980 
981 	map(0x0a, 0x0a).rw(FUNC(rainbow_base_state::diagnostic_r), FUNC(rainbow_base_state::diagnostic_w));
982 	map(0x0c, 0x0c).select(0x100).w(m_crtc, FUNC(rainbow_video_device::dc012_w));
983 
984 	map(0x0e, 0x0e).w(FUNC(rainbow_base_state::printer_bitrate_w));
985 
986 	map(0x10, 0x11).rw(m_kbd8251, FUNC(i8251_device::read), FUNC(i8251_device::write));
987 
988 	// ===========================================================
989 	// There are 4 select lines for Option Select 1 to 4
990 	// Option Select ------------------- Bundle Option Present
991 	// 1 2 3 4:                          BDL PRES (L):
992 	// X X o o Communication Option----- X
993 	// o X o o RD51 hard disk controller X --------- (X = SELECT)
994 	// ===========================================================
995 	// 0x20 -> 0x2f ***** EXTENDED COMM. OPTION / Option Select 1.
996 	// See boot rom @1EA6: 0x27 (<- RESET EXTENDED COMM OPTION  )
997 
998 	// Corvus B/H harddisk controller (incompatible with EXT.COMM OPTION):
999 	map(0x20, 0x20).rw(m_corvus_hdc, FUNC(corvus_hdc_device::read), FUNC(corvus_hdc_device::write));
1000 	map(0x21, 0x21).r(FUNC(rainbow_base_state::corvus_status_r));
1001 
1002 	// ===========================================================
1003 	// 0x30 -> 0x3f ***** Option Select 3
1004 	// ===========================================================
1005 	// 0x40  COMMUNICATIONS DATA REGISTER (MPSC)
1006 	// 0x41  PRINTER DATA REGISTER (MPSC)
1007 	// 0x42  COMMUNICATIONS CONTROL / STATUS REGISTER (MPSC)
1008 	// 0x43  PRINTER CONTROL / STATUS REGISTER (MPSC)
1009 	// ===========================================================
1010 	// 0x50 - 0x57 ***** COLOR GRAPHICS OPTION:
1011 
1012 	// * Color graphics option (NEC upd7220 GDC plus external hw.). See Programmer's Reference AA-AE36A-TV.
1013 	// Either 384 x 240 x 16 or 800 x 240 x 4 colors (out of 4096). 8 x 64 K video RAM.
1014 	// (Write Buffer, Pattern Register/Multiplier, ALU/PS, Color Map, readback and offset/scroll hardware):
1015 	map(0x50, 0x57).rw(FUNC(rainbow_base_state::GDC_EXTRA_REGISTER_r), FUNC(rainbow_base_state::GDC_EXTRA_REGISTER_w));
1016 
1017 	// ===========================================================
1018 	// 0x60 -> 0x6f ***** EXTENDED COMM. OPTION / Option Select 2.
1019 	// ===========================================================
1020 	// 0x60 -> 0x6f ***** RD51 HD. CONTROLLER   / Option Select 2.
1021 	map(0x60, 0x67).rw(m_hdc, FUNC(wd2010_device::read), FUNC(wd2010_device::write)).mirror(0x100);
1022 	map(0x68, 0x68).rw(FUNC(rainbow_base_state::hd_status_68_r), FUNC(rainbow_base_state::hd_status_68_w));
1023 	map(0x69, 0x69).r(FUNC(rainbow_base_state::hd_status_69_r));
1024 	// ===========================================================
1025 	// THE RD51 CONTROLLER: WD1010AL - 00 (WDC '83)
1026 	// + 2 K x 8 SRAM (SY2128-4 or Japan 8328) 21-17872-01
1027 	// + 74(L)Sxxx glue logic (drive/head select, buffers etc.)
1028 	// + 10 Mhz Quartz (/2)
1029 	// SERVICE JUMPERS (not to be removed for normal operation):
1030 	//   JUMPER "W1" : bridge between 10 Mhz master clock and board
1031 	//   JUMPER "W2" : bridges SYNC within Read Data Circuit
1032 	//   JUMPER "W3" : bridges 'drive read data' (from hard disk)
1033 	// Later RD51 boards (> '83 week 28 ?) have no jumpers at all.
1034 	// ===========================================================
1035 	// DEC RD TYPE (MByte) CYL ---- HEADS ---- MODEL (typical)
1036 	// DEC RD50 (5 Mbyte): 153 cyl. 4 heads -- ST506
1037 	// DEC RD51(10 Mbyte); 306 cyl. 4 heads -- ST412
1038 	// DEC RD31(20 Mbyte); 615 cyl. 4 heads -- ST225
1039 	// DEC RD52(32 Mbyte); 512 cyl. 8 heads -- Q540  [!]
1040 	// DEC RD32(40 Mbyte); 820 cyl. 6 heads -- ST251 [!]
1041 	// DEC RD53(67 Mbyte); 1024 cyl.8 heads -- 1325  [!]
1042 	// [!] More than 4 heads. Prepare with WUTIL and / or DSKPREP.
1043 
1044 	// SIZE RESTRICTIONS
1045 	// * HARDWARE:
1046 	//      WD1010 controller has a built-in limit of 8 heads / 1024 cylinders.
1047 	// * BOOT LOADERS:
1048 	//   - the DEC boot loader (and FDISK from DOS 3.10) initially allowed a maximum hard disc size of 20 MB.
1049 	//   - the custom boot loader that comes with 'WUTIL 3.2' allows 117 MB and 8 surfaces.
1050 	// * SOFTWARE:
1051 	//   - MS-DOS 2 allows a maximum partition size of 16 MB (sizes > 15 MB are incompatible to DOS 3)
1052 	//     [ no more than 4 partitions of 8 MB size on one hard disk possible ]
1053 	//   - MS-DOS 3 - and Concurrent CPM - have a global 32 MB (1024 cylinder) limit
1054 	//   - a CP/M-86-80 partition can have up to 8 MB (all CP/M partitions together must not exceed 10 MB)
1055 	// ===========================================================
1056 	// 0x70 -> 0x7f ***** Option Select 4
1057 	// ===========================================================
1058 	// 0x10c -> (MHFU disable register handled by 0x0c + select())
1059 }
1060 
rainbow8088_io(address_map & map)1061 void rainbow_modela_state::rainbow8088_io(address_map &map)
1062 {
1063 	rainbow_base_state::rainbow8088_base_io(map);
1064 	map(0x08, 0x08).r(FUNC(rainbow_modela_state::system_parameter_r));
1065 }
1066 
rainbow8088_io(address_map & map)1067 void rainbow_modelb_state::rainbow8088_io(address_map &map)
1068 {
1069 	rainbow_base_state::rainbow8088_base_io(map);
1070 	map(0x08, 0x08).r(FUNC(rainbow_modelb_state::system_parameter_r));
1071 }
1072 
rainbowz80_mem(address_map & map)1073 void rainbow_base_state::rainbowz80_mem(address_map &map)
1074 {
1075 	map.unmap_value_high();
1076 	map(0x0000, 0xffff).rw(FUNC(rainbow_base_state::share_z80_r), FUNC(rainbow_base_state::share_z80_w));
1077 }
1078 
rainbowz80_io(address_map & map)1079 void rainbow_base_state::rainbowz80_io(address_map &map)
1080 {
1081 	map.unmap_value_high();
1082 	map.global_mask(0xff);
1083 	map(0x00, 0x00).rw(FUNC(rainbow_base_state::z80_latch_r), FUNC(rainbow_base_state::z80_latch_w));
1084 	map(0x20, 0x20).rw(FUNC(rainbow_base_state::z80_generalstat_r), FUNC(rainbow_base_state::z80_diskdiag_read_w)); // read to port 0x20 used by MS-DOS 2.x diskette loader.
1085 	map(0x21, 0x21).rw(FUNC(rainbow_base_state::z80_generalstat_r), FUNC(rainbow_base_state::z80_diskdiag_write_w));
1086 	map(0x40, 0x40).rw(FUNC(rainbow_base_state::z80_diskstatus_r), FUNC(rainbow_base_state::z80_diskcontrol_w));
1087 	map(0x60, 0x63).rw(m_fdc, FUNC(fd1793_device::read), FUNC(fd1793_device::write));
1088 
1089 	// Z80 I/O shadow area > $80
1090 	map(0x80, 0x80).rw(FUNC(rainbow_base_state::z80_latch_r), FUNC(rainbow_base_state::z80_latch_w));
1091 	map(0xA0, 0xA0).rw(FUNC(rainbow_base_state::z80_generalstat_r), FUNC(rainbow_base_state::z80_diskdiag_read_w)); // read to port 0x20 used by MS-DOS 2.x diskette loader.
1092 	map(0xA1, 0xA1).rw(FUNC(rainbow_base_state::z80_generalstat_r), FUNC(rainbow_base_state::z80_diskdiag_write_w));
1093 	map(0xC0, 0xC0).rw(FUNC(rainbow_base_state::z80_diskstatus_r), FUNC(rainbow_base_state::z80_diskcontrol_w));
1094 	map(0xE0, 0xE3).rw(m_fdc, FUNC(fd1793_device::read), FUNC(fd1793_device::write));
1095 }
1096 
1097 /* Input ports */
1098 
1099 /* DIP switches */
1100 static INPUT_PORTS_START(rainbow100b_in)
1101 
1102 	PORT_START("MONO_MONITOR_TYPE")
1103 	PORT_DIPNAME(0x03, 0x03, "MONO MONITOR TYPE")
1104 	PORT_DIPSETTING(0x01, "WHITE (VR201-A)")
1105 	PORT_DIPSETTING(0x02, "GREEN (VR201-B)")
1106 	PORT_DIPSETTING(0x03, "AMBER (VR201-C)")
1107 
1108 	// FLOPPY, BUNDLE, GRAPHICS affect 'system_parameter_r':
1109 
1110 	// EXT.COMM.card -or- RD51 HD. controller (marketed later).
1111 	PORT_START("DEC_HARD_DISK") // BUNDLE_OPTION
1112 	PORT_DIPNAME(0x01, 0x00, "DEC HARD DISK (#1)") PORT_TOGGLE
DEF_STR(Off)1113 	PORT_DIPSETTING(0x00, DEF_STR(Off))
1114 	PORT_DIPSETTING(0x01, DEF_STR(On))
1115 
1116 	PORT_START("CORVUS_HARD_DISKS")
1117 	PORT_DIPNAME(0x01, 0x00, "CORVUS HARD DISKS (#2 to #5)") PORT_TOGGLE
1118 	PORT_DIPSETTING(0x00, DEF_STR(Off))
1119 	PORT_DIPSETTING(0x01, DEF_STR(On))
1120 
1121 	PORT_START("CLIKCLOK") // DS1315 RTC
1122 	PORT_DIPNAME(0x01, 0x00, "REAL TIME CLOCK (CLIKCLOK)") PORT_TOGGLE
1123 	PORT_DIPSETTING(0x00, DEF_STR(Off))
1124 	PORT_DIPSETTING(0x01, DEF_STR(On))
1125 
1126 	PORT_START("GRAPHICS_OPTION") // GDC
1127 	PORT_DIPNAME(0x01, 0x00, "GRAPHICS OPTION") PORT_TOGGLE
1128 	PORT_DIPSETTING(0x00, DEF_STR(Off))
1129 	PORT_DIPSETTING(0x01, DEF_STR(On))
1130 
1131 	// W13 - W18 are used for factory tests and affect the boot process -
1132 	PORT_START("W13")
1133 	PORT_DIPNAME(0x02, 0x02, "W13 (FACTORY TEST A, LEAVE OFF)") PORT_TOGGLE
1134 	PORT_DIPSETTING(0x02, DEF_STR(Off))
1135 	PORT_DIPSETTING(0x00, DEF_STR(On))
1136 
1137 	PORT_START("W14")
1138 	PORT_DIPNAME(0x04, 0x04, "W14 (FACTORY TEST B, LEAVE OFF)") PORT_TOGGLE
1139 	PORT_DIPSETTING(0x04, DEF_STR(Off))
1140 	PORT_DIPSETTING(0x00, DEF_STR(On))
1141 	PORT_START("W15")
1142 	PORT_DIPNAME(0x08, 0x08, "W15 (FACTORY TEST C, LEAVE OFF)") PORT_TOGGLE
1143 	PORT_DIPSETTING(0x08, DEF_STR(Off))
1144 	PORT_DIPSETTING(0x00, DEF_STR(On))
1145 
1146 	PORT_START("W18") // DSR = 1 when switch is OFF - see i8251.c
1147 	PORT_DIPNAME(0x01, 0x00, "W18 (FACTORY TEST D, LEAVE OFF) (8251A: DSR)") PORT_TOGGLE
1148 	PORT_DIPSETTING(0x00, DEF_STR(Off))
1149 	PORT_DIPSETTING(0x01, DEF_STR(On))
1150 	PORT_WRITE_LINE_DEVICE_MEMBER("kbdser", i8251_device, write_dsr)
1151 
1152 	// J17 jumper on FDC controller board shifts drive select (experimental) -
1153 	PORT_START("J17")
1154 	PORT_DIPNAME(0x02, 0x00, "J17 DRIVE SELECT (A => C and B => D)") PORT_TOGGLE
1155 	PORT_DIPSETTING(0x00, DEF_STR(Off))
1156 	PORT_DIPSETTING(0x02, DEF_STR(On))
1157 
1158 	PORT_START("WATCHDOG")
1159 	PORT_DIPNAME(0x01, 0x00, "WATCHDOG ENABLED (MHFU)") PORT_TOGGLE
1160 	PORT_DIPSETTING(0x00, DEF_STR(Off))
1161 	PORT_DIPSETTING(0x01, DEF_STR(On))
1162 
1163 	PORT_START("MONITOR_CONFIGURATION") // GDC
1164 	PORT_DIPNAME(0x0F, 0x04, "MONITOR CONFIGURATION")
1165 	PORT_DIPSETTING(0x04, "AUTODETECT")
1166 	PORT_DIPSETTING(0x01, "MONO ONLY / 4 to 16 monochrome shades (single VR-201)")
1167 	PORT_DIPSETTING(0x02, "COLOR ONLY (single VR-241 with BCC-17 cable)")
1168 	PORT_DIPSETTING(0x03, "DUAL MONITOR (SCREEN 1: TEXT;  SCREEN 2: R-G-B)")
1169 INPUT_PORTS_END
1170 
1171 void rainbow_base_state::machine_reset()
1172 {
1173 	// 'F3' (in partial emulation) here replaces 'CTRL-SETUP' (soft reboot on an original Rainbow)
1174 	// FIXME: BIOS reports error 19 when CTRL-SETUP is pressed (Z80 or flags aren't fully reset then?)
1175 	popmessage("Reset");
1176 
1177 	m_crtc->MHFU(MHFU_RESET_and_DISABLE);
1178 
1179 	m_rtc->chip_reset();     // * Reset RTC to a defined state *
1180 
1181 	//  *********** HARD DISK CONTROLLERS...
1182 	address_space &io = m_i8088->space(AS_IO);
1183 	if (m_inp5->read() == 0x01) // ...PRESENT?
1184 	{
1185 		// Install 8088 read / write handler
1186 		io.unmap_readwrite(0x60, 0x60);
1187 		io.install_read_handler(0x60, 0x60, read8smo_delegate(*this, FUNC(rainbow_base_state::hd_status_60_r)));
1188 		io.install_write_handler(0x60, 0x60, write8smo_delegate(*this, FUNC(rainbow_base_state::hd_status_60_w)));
1189 
1190 		hdc_reset();
1191 		m_hdc_drive_ready = true;
1192 		m_hdc_write_fault = false;
1193 
1194 		hard_disk_file *local_hard_disk;
1195 		local_hard_disk = rainbow_hdc_file(0); // one hard disk for now.
1196 
1197 		m_leds[0] = 0;
1198 		switch_off_timer->adjust(attotime::from_msec(500));
1199 
1200 		if (local_hard_disk)
1201 		{
1202 			hard_disk_info *info;
1203 			if ((info = hard_disk_get_info(local_hard_disk)))
1204 			{
1205 				m_leds[0] = 1;
1206 
1207 				uint32_t max_sector = (info->cylinders) * (info->heads) * (info->sectors);
1208 				popmessage("DEC %u (%3.2f) MB HARD DISK MOUNTED.\nGEOMETRY: %d HEADS (1..%d ARE OK).\n%d CYLINDERS (151 to %d ARE OK).\n%d SECTORS / TRACK (up to %d ARE OK). \n%d BYTES / SECTOR (128 to 1024 ARE OK).\n",
1209 					max_sector * info->sectorbytes / 1000000,
1210 					(float)max_sector * (float)info->sectorbytes / 1048576.0f,
1211 					info->heads, RD51_MAX_HEAD,
1212 					info->cylinders, RD51_MAX_CYLINDER,
1213 					info->sectors, RD51_SECTORS_PER_TRACK,
1214 					info->sectorbytes);
1215 			}
1216 		}
1217 	}
1218 
1219 	if (m_inp6->read() == 0x00) // Unmap port if Corvus not present
1220 			io.unmap_readwrite(0x20, 0x20);
1221 
1222 	// *********** FLOPPY DISK CONTROLLER [ NOT OPTIONAL ]
1223 	m_present_drive = INVALID_DRIVE;
1224 	m_fdc->reset();
1225 	m_fdc->set_floppy(nullptr);
1226 	m_fdc->dden_w(0);
1227 
1228 	// *********** NEC 7220 DISPLAY CONTROLLER [ OPTIONAL ]
1229 	OPTION_GRFX_RESET
1230 	OPTION_RESET_PATTERNS
1231 
1232 	for (int i = 0; i < 32; i++)
1233 		m_gdc_color_map[i] = 0x00;
1234 	m_gdc_color_map_index = 0;
1235 	// *********** Z80
1236 
1237 	m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
1238 	m_z80_halted = true;
1239 
1240 	m_zflip = true; // ZRESET high on startup
1241 	m_diagnostic = 0;   // DIAGNOSTIC_R/W registers (shouldn't it be 1?)
1242 
1243 	m_intz80 = false;
1244 	m_int88 = false;
1245 
1246 	// *********** SERIAL COMM. (7201)
1247 	m_mpsc->reset();
1248 	m_mpsc_irq = 0;
1249 	m_printer_bitrate = 0;
1250 
1251 	// *********** KEYBOARD + IRQ
1252 	m_kbd_tx_ready = m_kbd_rx_ready = false;
1253 	m_kbd8251->write_cts(0);
1254 	m_KBD = 0;
1255 
1256 	m_irq_high = 0;
1257 	m_irq_mask = 0;
1258 
1259 	// RESET RED LEDs
1260 	m_leds[0] = 1;
1261 	m_leds[1] = 1;
1262 	m_leds[2] = 1;
1263 	m_leds[3] = 1;
1264 	m_leds[4] = 1;
1265 	m_leds[5] = 1;
1266 	m_leds[6] = 1;
1267 
1268 	// GREEN KEYBOARD LEDs (see machine/dec_lk201.cpp)
1269 }
1270 
machine_reset()1271 void rainbow_modela_state::machine_reset()
1272 {
1273 	rainbow_base_state::machine_reset();
1274 	logerror("*** RAINBOW A MODEL ASSUMED (64 - 832 K RAM).\n");
1275 }
1276 
machine_reset()1277 void rainbow_modelb_state::machine_reset()
1278 {
1279 	rainbow_base_state::machine_reset();
1280 	logerror("*** RAINBOW B MODEL ASSUMED (128 - 896 K RAM)\n");
1281 }
1282 
1283 // Simulate AC_OK signal (power good) and RESET after ~ 108 ms.
device_timer(emu_timer & timer,device_timer_id tid,int param,void * ptr)1284 void rainbow_base_state::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
1285 {
1286 	switch (tid)
1287 	{
1288 	case 0:
1289 		cmd_timer->adjust(attotime::never);
1290 
1291 		if (m_power_good == false)
1292 		{
1293 			m_power_good = true;
1294 			logerror("**** POWER GOOD ****\n");
1295 		}
1296 		else
1297 		{
1298 			logerror("**** WATCHDOG: CPU RESET ****\n");
1299 			m_i8088->reset(); // gives 'ERROR_16 - INTERRUPTS OFF' (indicates hardware failure or software bug).
1300 		}
1301 		break; // case 0
1302 
1303 	case 1:
1304 
1305 		switch_off_timer->adjust(attotime::never);
1306 
1307 		m_driveleds[0] = 0; // DRIVE 0 (A)
1308 		m_driveleds[1] = 0; // DRIVE 1 (B)
1309 		m_driveleds[2] = 0; // DRIVE 2 (C)
1310 		m_driveleds[3] = 0; // DRIVE 3 (D)
1311 
1312 		m_leds[0] = 1;  // 1 = OFF (One of the CPU LEDs as drive LED for DEC hard disk)
1313 		m_leds[1] = 1;  // 1 = OFF (One of the CPU LEDs as drive LED for Corvus HD)
1314 
1315 		break; // case 1
1316 
1317 	} // switch (timer ID)
1318 }
1319 
screen_update_rainbow(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)1320 uint32_t rainbow_base_state::screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
1321 {
1322 	static int old_monitor;
1323 
1324 	if ((m_monitor_suggested < 1) || (m_monitor_suggested > 3))
1325 			m_monitor_suggested = COLOR_MONITOR;
1326 
1327 	if (m_monitor_suggested != old_monitor)
1328 	{
1329 		old_monitor = m_monitor_suggested;
1330 		if (m_monitor_suggested == 1)
1331 			popmessage("MONOCHROME MONITOR");
1332 		if (m_monitor_suggested == 2)
1333 			popmessage("COLOR MONITOR");
1334 		if (m_monitor_suggested == 3)
1335 			popmessage("DUAL MONITOR");
1336 	}
1337 
1338 	int palette_selected;
1339 	if (m_onboard_video_selected && (m_monitor_suggested == COLOR_MONITOR))
1340 		 palette_selected = 2; // Color monitor; green text
1341 	else
1342 		 palette_selected = m_inp9->read();
1343 
1344 	m_crtc->palette_select(palette_selected);
1345 	m_crtc->video_update(bitmap, cliprect);
1346 
1347 	if (m_screen_blank || ((!m_onboard_video_selected) && (m_inp13->read() != DUAL_MONITOR))) // dual monitor: never blank all
1348 		m_crtc->video_blanking(bitmap, cliprect);
1349 	else
1350 		m_crtc->video_update(bitmap, cliprect);
1351 	return 0;
1352 }
1353 
1354 // Interrupt handling and arbitration.  See 3.1.3.8 OF PC-100 spec.
update_8088_irqs()1355 void rainbow_base_state::update_8088_irqs()
1356 {
1357 	if (m_irq_mask != 0)
1358 	{
1359 		for (int i = IRQ_8088_VBL; i >= 0; i--)
1360 		{
1361 			if (m_irq_mask & (1 << i))
1362 			{
1363 				m_i8088->set_input_line_and_vector(INPUT_LINE_INT0, ASSERT_LINE, vectors[i] | m_irq_high); // I8088
1364 				break;
1365 			}
1366 		}
1367 	}
1368 	else
1369 	{
1370 		m_i8088->set_input_line(INPUT_LINE_INT0, CLEAR_LINE);
1371 	}
1372 }
1373 
1374 
raise_8088_irq(int ref)1375 void rainbow_base_state::raise_8088_irq(int ref)
1376 {
1377 	m_irq_mask |= (1 << ref);
1378 	update_8088_irqs();
1379 }
1380 
lower_8088_irq(int ref)1381 void rainbow_base_state::lower_8088_irq(int ref)
1382 {
1383 	m_irq_mask &= ~(1 << ref);
1384 	update_8088_irqs();
1385 }
1386 
1387 
1388 // IRQ service for 7201 (commm / printer)
update_mpsc_irq()1389 void rainbow_base_state::update_mpsc_irq()
1390 {
1391 	if (m_mpsc_irq == 0)
1392 		lower_8088_irq(IRQ_COMM_PTR_INTR_L);
1393 	else
1394 		raise_8088_irq(IRQ_COMM_PTR_INTR_L);
1395 }
1396 
WRITE_LINE_MEMBER(rainbow_base_state::mpsc_irq)1397 WRITE_LINE_MEMBER(rainbow_base_state::mpsc_irq)
1398 {
1399 	m_mpsc_irq = state;
1400 	update_mpsc_irq();
1401 }
1402 
1403 // PORT 0x06 : Communication bit rates (see page 21 of PC 100 SPEC)
comm_bitrate_w(uint8_t data)1404 void rainbow_base_state::comm_bitrate_w(uint8_t data)
1405 {
1406 	m_dbrg->str_w(data & 0x0f);  // PDF is wrong, low nibble is RECEIVE clock (verified in SETUP).
1407 	logerror("\n(COMM.) receive bitrate = %d ($%02x)\n", comm_rates[data & 0x0f] , data & 0x0f);
1408 
1409 	m_dbrg->stt_w( ((data & 0xf0) >> 4) );
1410 	logerror("(COMM.) transmit bitrate = %d ($%02x)\n", comm_rates[((data & 0xf0) >> 4)] ,(data & 0xf0) >> 4);
1411 }
1412 
1413 // PORT 0x0e : Printer bit rates
printer_bitrate_w(uint8_t data)1414 void rainbow_base_state::printer_bitrate_w(uint8_t data)
1415 {
1416 	m_printer_bitrate = data & 7;
1417 	// bits 0 - 2 = 0: nominally 75 bps, actually 75.35 bps
1418 	// bits 0 - 2 = 1: nominally 150 bps, actually 150.7 bps
1419 	// bits 0 - 2 = 2: nominally 300 bps, actually 301.4 bps
1420 	// bits 0 - 2 = 3: nominally 600 bps, actually 602.8 bps
1421 	// bits 0 - 2 = 4: nominally 1200 bps, actually 1205.6 bps
1422 	// bits 0 - 2 = 5: nominally 2400 bps, actually 2411.2 bps
1423 	// bits 0 - 2 = 6: nominally 4800 bps, actually 4822.4 bps (keyboard is tied to this rate)
1424 	// bits 0 - 2 = 7: nominally 9600 bps, actually 9644.8 bps
1425 	// TX and RX rate cannot be programmed independently.
1426 	logerror("\n(PRINTER) receive = transmit bitrate: %d ($%02x)", 9600 / ( 1 << (7 - (data & 7))) , data & 7);
1427 
1428 	// "bit 3 controls the communications port clock (RxC,TxC). External clock when 1, internal when 0"
1429 	logerror(" - CLOCK (0 = internal): %02x", data & 8);
1430 }
1431 
WRITE_LINE_MEMBER(rainbow_base_state::dbrg_fr_w)1432 WRITE_LINE_MEMBER(rainbow_base_state::dbrg_fr_w)
1433 {
1434 	m_mpsc->rxca_w(state);
1435 }
1436 
WRITE_LINE_MEMBER(rainbow_base_state::dbrg_ft_w)1437 WRITE_LINE_MEMBER(rainbow_base_state::dbrg_ft_w)
1438 {
1439 	m_mpsc->txca_w(state);
1440 }
1441 
bitrate_counter_w(uint8_t data)1442 void rainbow_base_state::bitrate_counter_w(uint8_t data)
1443 {
1444 	bool prt_rxtxc = BIT(data, 7 - m_printer_bitrate);
1445 	bool kbd_rxtxc = BIT(data, 1);
1446 
1447 	m_mpsc->rxcb_w(prt_rxtxc);
1448 	m_mpsc->txcb_w(prt_rxtxc);
1449 
1450 	m_kbd8251->write_rxc(kbd_rxtxc);
1451 	m_kbd8251->write_txc(kbd_rxtxc);
1452 }
1453 
1454 // Only Z80 * private SRAM * is wait state free
1455 // (= fast enough to allow proper I/O to the floppy)
1456 
1457 // Shared memory is contended by refresh, concurrent
1458 //    8088 accesses and arbitration logic (DMA).
share_z80_r(offs_t offset)1459 uint8_t rainbow_base_state::share_z80_r(offs_t offset)
1460 {
1461 	if (m_zflip)
1462 	{
1463 		if (offset < 0x8000)
1464 		{
1465 			return m_ram->read(offset + 0x8000);
1466 		}
1467 		else if (offset < 0x8800)
1468 		{
1469 			return m_z80_private[offset & 0x7ff]; // SRAM
1470 		}
1471 
1472 		return m_ram->read(offset ^ 0x8000);
1473 	}
1474 	else
1475 	{
1476 		if (offset < 0x800)
1477 		{
1478 			return m_z80_private[offset]; // SRAM
1479 		}
1480 
1481 		return m_ram->read(offset);
1482 	}
1483 }
1484 
share_z80_w(offs_t offset,uint8_t data)1485 void rainbow_base_state::share_z80_w(offs_t offset, uint8_t data)
1486 {
1487 	if (m_zflip)
1488 	{
1489 		if (offset < 0x8000)
1490 		{
1491 			m_ram->write(offset + 0x8000, data);
1492 			return; // [!]
1493 		}
1494 		else if (offset < 0x8800)
1495 		{
1496 			m_z80_private[offset & 0x7ff] = data; // SRAM
1497 			return; // [!]
1498 		}
1499 
1500 		m_ram->write(offset ^ 0x8000, data);
1501 	}
1502 	else
1503 	{
1504 		if (offset < 0x800)
1505 			m_z80_private[offset] = data; // SRAM
1506 		else
1507 			m_ram->write(offset, data);
1508 	}
1509 	return;
1510 }
1511 
ext_ram_r(offs_t offset)1512 uint8_t rainbow_base_state::ext_ram_r(offs_t offset)
1513 {
1514 	if (offset < m_ram->size())
1515 		return m_ram->read(offset);
1516 	return 0;
1517 }
1518 
ext_ram_w(offs_t offset,uint8_t data)1519 void rainbow_modela_state::ext_ram_w(offs_t offset, uint8_t data)
1520 {
1521 	if (offset < m_ram->size())
1522 		m_ram->write(offset, data);
1523 }
1524 
1525 // NMI logic (parity test)
ext_ram_w(offs_t offset,uint8_t data)1526 void rainbow_modelb_state::ext_ram_w(offs_t offset, uint8_t data)
1527 {
1528 	if (offset < m_ram->size())
1529 		m_ram->write(offset, data);
1530 
1531 	if (m_diagnostic & 0x08)
1532 		if (offset >= 0x10000)
1533 			m_i8088->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
1534 }
1535 
1536 // ------------------------ClikClok (for 100-A; DS1315) ------------------------------------------
1537 // Version for 100-A plugs into NVRAM chip socket. There is a socket on the ClikClok for the NVRAM
1538 
1539 // Requires a short program from the Suitable Solutions ClikClok distribution disk (CLIKA.COM)
1540 // - also needed to set time/date (*).                   Reads $ed000, writes ed0fe/ed0ff.
rtc_w(offs_t offset,uint8_t data)1541 void rainbow_base_state::rtc_w(offs_t offset, uint8_t data)
1542 {
1543 	if (m_inp11->read() == 0x01) // if enabled...
1544 	{
1545 		switch (offset)
1546 		{
1547 		case 0x00: // Write to 0xED0FE
1548 			if (m_rtc->chip_enable())
1549 				m_rtc->write_data(offset & 0x01); // Transfer data to DS1315 (data = offset):
1550 			else
1551 				m_rtc->read_0(); // (RTC ACTIVATION) read magic pattern 0
1552 			break;
1553 
1554 		case 0x01: // Write to 0xED0FF
1555 			if (m_rtc->chip_enable())
1556 				m_rtc->write_data(offset & 0x01); // Transfer data to DS1315 (data = offset):
1557 			else
1558 				m_rtc->read_1(); // (RTC ACTIVATION) read magic pattern 1
1559 			break;
1560 		}
1561 	}
1562 	m_p_vol_ram[offset] = data;  // Poke value into VOL_RAM.
1563 }
1564 
1565 // ------------------------ClikClok (for 100-B; DS1315)  ------------------------------------------------
1566 // Add-on hardware, occupies one of the EPROM sockets of the 100-B. TODO: check address decoders on board
1567 // Requires CLIKCLOK.COM or RBCLIK21.COM (freeware from Latrobe).                       Uses FC000/FE000.
rtc_r(offs_t offset)1568 uint8_t rainbow_modela_state::rtc_r(offs_t offset)
1569 {
1570 	if (m_inp11->read() == 0x01) // if enabled...
1571 	{
1572 		if (offset == 0x00) // read time/date from 0xED000 (ClikClok for 100-A)
1573 		{
1574 			if (m_rtc->chip_enable())
1575 				return m_rtc->read_data() & 0x01;
1576 			 else
1577 				m_rtc->chip_reset();
1578 		}
1579 	}
1580 
1581 	return m_p_vol_ram[offset];  // return volatile RAM
1582 }
1583 
rtc_r(offs_t offset)1584 uint8_t rainbow_modelb_state::rtc_r(offs_t offset)
1585 {
1586 	if (m_inp11->read() == 0x01) // if enabled...
1587 	{
1588 		switch (offset)
1589 		{
1590 		// Transfer data to DS1315 (data = offset):
1591 		case 0x0000:  // RTC_WRITE_DATA_0 0xFC000
1592 		case 0x2000:  // RTC_WRITE_DATA_0 0xFE000 (MIRROR)
1593 
1594 		case 0x0001:  // RTC_WRITE_DATA_1 0xFC001
1595 		case 0x2001:  // RTC_WRITE_DATA_1 0xFE001 (MIRROR)
1596 			m_rtc->write_data(offset & 0x01);
1597 			break;
1598 
1599 		// Read actual time/date from ClikClok:
1600 		case 0x0004:  // 0xFC004
1601 		case 0x2004:  // 0xFE004 (MIRROR)
1602 			if (m_rtc->chip_enable())
1603 				return (m_rtc->read_data() & 0x01);
1604 
1605 		// (RTC ACTIVATION) read magic pattern 0
1606 		case 0x0100:  // 0xFC100
1607 		case 0x2100:  // 0xFE100 (MIRROR)
1608 			m_rtc->read_0();
1609 			break;
1610 
1611 		// (RTC ACTIVATION) read magic pattern 1
1612 		case 0x0101:  // 0xFC101
1613 		case 0x2101:  // 0xFE101 (MIRROR)
1614 			m_rtc->read_1();
1615 			break;
1616 
1617 		// RESET
1618 		case 0x0104:  // 0xFC104
1619 		case 0x2104:  // 0xFE104 (MIRROR)
1620 			m_rtc->chip_reset();
1621 			break;
1622 		}
1623 	}
1624 
1625 	uint8_t *rom = memregion("maincpu")->base();
1626 	return rom[0xfc000 + offset];  // return ROM
1627 }
1628 // ------------------------/ ClikClok (for model B; DS1315)  -------------------------------
1629 
1630 
1631 // --------------------------------- Corvus (B/H)  -----------------------------------------
1632 // PORT 0x21 : Corvus status register (ready / direction)
corvus_status_r()1633 uint8_t rainbow_base_state::corvus_status_r()
1634 {
1635 	if (m_inp6->read() == 0) // Corvus controller
1636 	{
1637 		popmessage("Corvus controller invoked - but switched OFF.\nCheck DIP and perform a reset.\n\nIncompatible software also triggers this warning (illegal access to port $21)");
1638 		return 0;
1639 	}
1640 	else
1641 	{
1642 		m_leds[1] = 0;
1643 		switch_off_timer->adjust(attotime::from_msec(500));
1644 
1645 		uint8_t status = m_corvus_hdc->status_r();
1646 		uint8_t data = BIT(status, 7); // 0x80 BUSY (Set = Busy, Clear = Ready)
1647 		data |= BIT(status, 6) << 1; // 0x40 DIR. (Controller -> Host, or Host->Controller)
1648 		return data;
1649 	}
1650 }
1651 // ---------------------------------/ Corvus (B/H)  ----------------------------------------
1652 
1653 
1654 // ---------------------------- RD51 HARD DISK CONTROLLER ----------------------------------
1655 static const int SECTOR_SIZES[4] = { 256, 512, 1024, 128 };
1656 
hdc_reset()1657 void rainbow_base_state::hdc_reset()
1658 {
1659 //  logerror(">> HARD DISC CONTROLLER RESET <<\n");
1660 	m_hdc->reset();
1661 
1662 	m_bdl_irq = 0;
1663 	update_bundle_irq(); // reset INTRQ
1664 
1665 	m_hdc_buf_offset = 0;
1666 	m_hdc_direction = 0;
1667 
1668 	m_hdc->buffer_ready(false);
1669 	m_hdc_write_gate = false;
1670 
1671 	m_hdc_step_latch = false;
1672 	m_hdc_index_latch = false;
1673 }
1674 
1675 // Return 'hard_disk_file' object for harddisk 1 (fixed).
1676 // < nullptr if geometry is insane or other errors occured >
rainbow_hdc_file(int drv)1677 hard_disk_file *rainbow_base_state::rainbow_hdc_file(int drv)
1678 {
1679 	m_hdc_drive_ready = false;
1680 
1681 	if (m_inp5->read() != 0x01) // ...PRESENT?
1682 		return nullptr;
1683 
1684 	if (drv != 0)
1685 		return nullptr;
1686 
1687 	harddisk_image_device *img = dynamic_cast<harddisk_image_device *>(subdevice("decharddisk1"));
1688 
1689 	if (!img)
1690 		return nullptr;
1691 
1692 	if (!img->exists())
1693 		return nullptr;
1694 
1695 	hard_disk_file *file = img->get_hard_disk_file();
1696 	hard_disk_info *info = hard_disk_get_info(file);
1697 
1698 	// MFM ALLOWS UP TO 17 SECTORS / TRACK.
1699 	// CYLINDERS: 151 (~ 5 MB) to 1024 (max. cylinders on WD1010 controller)
1700 	if (((info->sectors <= RD51_SECTORS_PER_TRACK)) &&
1701 		((info->heads >= 1) && (info->heads <= RD51_MAX_HEAD)) &&            // HEADS WITHIN 1...8
1702 		((info->cylinders > 150) && (info->cylinders <= RD51_MAX_CYLINDER)))
1703 	{
1704 		m_hdc_drive_ready = true;
1705 		return file;  // HAS SANE GEOMETRY
1706 	}
1707 	else
1708 	{
1709 		uint32_t max_sector = info->cylinders * info->heads * info->sectors;
1710 		popmessage("DEC %u (%3.2f) MB HARD DISK REJECTED.\nGEOMETRY: %d HEADS (1..%d ARE OK).\n%d CYLINDERS (151 to %d ARE OK).\n%d SECTORS / TRACK (up to %d ARE OK). \n%d BYTES / SECTOR (128 to 1024 ARE OK).\n",
1711 					max_sector * info->sectorbytes / 1000000,
1712 					(float)max_sector * (float)info->sectorbytes / 1048576.0f,
1713 					info->heads, RD51_MAX_HEAD,
1714 					info->cylinders, RD51_MAX_CYLINDER,
1715 					info->sectors, RD51_SECTORS_PER_TRACK,
1716 					info->sectorbytes);
1717 		logerror("<<< === HARD DISK IMAGE REJECTED = (invalid geometry) === >>>\n");
1718 		return nullptr;
1719 	}
1720 }
1721 
1722 // LBA sector from CHS
get_and_print_lbasector(device_t * device,hard_disk_info * info,uint16_t cylinder,uint8_t head,uint8_t sector_number)1723 static uint32_t get_and_print_lbasector(device_t *device, hard_disk_info *info, uint16_t cylinder, uint8_t head, uint8_t sector_number)
1724 {
1725 	if (info == nullptr)
1726 		return 0;
1727 
1728 	// LBA_ADDRESS = (C * HEADS + H) * NUMBER_SECTORS + (S - 1)
1729 	uint32_t lbasector = (double)cylinder * info->heads; // LBA : ( x 4 )
1730 	lbasector += head;
1731 	lbasector *= info->sectors;   // LBA : ( x 16 )
1732 	lbasector += (sector_number - 1); // + (sector number - 1)
1733 
1734 //  device->logerror(" CYLINDER %u - HEAD %u - SECTOR NUMBER %u (LBA-SECTOR %u) ", cylinder, head, sector_number, lbasector);
1735 	return lbasector;
1736 }
1737 
1738 // READ SECTOR (on BCS 1 -> 0 transition)
WRITE_LINE_MEMBER(rainbow_base_state::hdc_read_sector)1739 WRITE_LINE_MEMBER(rainbow_base_state::hdc_read_sector)
1740 {
1741 	static int last_state;
1742 	int read_status = 1;
1743 
1744 	if (!m_hdc_write_gate) // do not read when WRITE GATE is on
1745 	{
1746 		uint8_t sdh = (m_hdc->read(0x06));
1747 		int drv = (sdh & (8 + 16)) >> 3; // get DRIVE from SDH register
1748 
1749 		if ((state == 0) && (last_state == 1) && (drv == 0))
1750 		{
1751 			read_status = 2; //          logerror("\nTRYING TO READ");
1752 			m_leds[0] = 0;
1753 			switch_off_timer->adjust(attotime::from_msec(500));
1754 
1755 			int hi = (m_hdc->read(0x05)) & 0x07;
1756 			uint16_t cylinder = (m_hdc->read(0x04)) | (hi << 8);
1757 			uint8_t sector_number = m_hdc->read(0x03);
1758 
1759 			hard_disk_file *local_hard_disk;
1760 			local_hard_disk = rainbow_hdc_file(0); // one hard disk for now.
1761 
1762 			if (local_hard_disk)
1763 			{
1764 				read_status = 3;
1765 
1766 				hard_disk_info *info;
1767 				if ((info = hard_disk_get_info(local_hard_disk)))
1768 				{
1769 					read_status = 4;
1770 					m_leds[0] = 1;
1771 
1772 					// Pointer to info + C + H + S
1773 					uint32_t lbasector = get_and_print_lbasector(this, info, cylinder, sdh & 0x07, sector_number);
1774 
1775 					if ((cylinder <= info->cylinders) &&                          // filter invalid ranges
1776 						(SECTOR_SIZES[(sdh >> 5) & 0x03] == info->sectorbytes)    // may not vary in image!
1777 						)
1778 					{
1779 						read_status = 5;
1780 						if (hard_disk_read(local_hard_disk, lbasector, m_hdc_buffer)) // accepts LBA sector (uint32_t) !
1781 							read_status = 0; //  logerror("...success!\n");
1782 					}
1783 				}
1784 				m_hdc_buf_offset = 0;
1785 				m_hdc->buffer_ready(true);
1786 			} // if valid  (..)
1787 
1788 			if (read_status != 0)
1789 			{
1790 				logerror("...** READ FAILED WITH STATUS %u ** (CYLINDER %u - HEAD %u - SECTOR # %u - SECTOR_SIZE %u ) ***\n",
1791 					read_status, cylinder, sdh & 0x07, sector_number, SECTOR_SIZES[(sdh >> 5) & 0x03]
1792 				);
1793 			}
1794 
1795 		} //   (on BCS 1 -> 0)
1796 
1797 	} // do not read when WRITE GATE is on
1798 
1799 	last_state = state;
1800 }
1801 
1802 
1803 // WRITE SECTOR
1804 // ...IF WRITE_GATE (WG) TRANSITS FROM 1 -> 0
1805 
1806 // NO PROVISIONS for  sector sizes != 512 or MULTIPLE DRIVES (> 0) !!!
WRITE_LINE_MEMBER(rainbow_base_state::hdc_write_sector)1807 WRITE_LINE_MEMBER(rainbow_base_state::hdc_write_sector)
1808 {
1809 	int success = 0;
1810 	static int wg_last;
1811 
1812 	if (state == 0)
1813 		m_hdc_write_gate = false;
1814 	else
1815 		m_hdc_write_gate = true;
1816 
1817 	int drv = ((m_hdc->read(0x06)) & (8 + 16)) >> 3; // get DRIVE from SDH register
1818 
1819 	if (state == 0 && wg_last == 1 && drv == 0)  // Check correct state transition and DRIVE 0 ....
1820 	{
1821 		m_leds[0] = 0;  // (1 = OFF ) =HARD DISK ACTIVITY =
1822 		switch_off_timer->adjust(attotime::from_msec(500));
1823 
1824 		if (rainbow_hdc_file(0) != nullptr)
1825 		{
1826 			success = do_write_sector();
1827 			if (success < 88)
1828 				logerror("! SECTOR WRITE (or FORMAT) FAULT !  ERROR CODE %i.\n", success);
1829 
1830 			m_hdc_buf_offset = 0;
1831 			m_hdc->buffer_ready(false);
1832 		}
1833 
1834 		// CHD WRITE FAILURES  or  UNMOUNTED HARDDSIK TRIGGER A PERMANENT ERROR.
1835 		if (success < 50)
1836 			m_hdc_write_fault = true; // reset only by HDC RESET!
1837 	}
1838 
1839 	wg_last = state;  // remember state
1840 }
1841 
1842 
1843 // Initiated by 'hdc_write_sector' (below)
1844 // - in turn invoked by a WG: 1 -> 0 transit.
1845 // STATUS CODES:
1846 //   0 = DEFAULT ERROR (no HARD DISK FILE ?)
1847 //   10 = CHD WRITE FAILURE (?)
1848 
1849 //  50 = SANITY CHECK FAILED (cylinder limit / <> 512 sectors?)
1850 
1851 //  88 = (LOW LEVEL) WRITE/FORMAT (sector_count != 1 IGNORED)
1852 //  99 = SUCCESS : SECTOR WRITTEN
1853 
1854 // * RELIES * ON THE FACT THAT THERE WILL BE NO MULTI SECTOR TRANSFERS (!)
do_write_sector()1855 int rainbow_base_state::do_write_sector()
1856 {
1857 	int feedback = 0; // no error
1858 	m_leds[0] = 0; // ON
1859 	switch_off_timer->adjust(attotime::from_msec(500));
1860 
1861 	hard_disk_file *local_hard_disk = rainbow_hdc_file(0); // one hard disk for now.
1862 
1863 	if (local_hard_disk)
1864 	{
1865 		hard_disk_info *info = hard_disk_get_info(local_hard_disk);
1866 		if (info)
1867 		{
1868 			feedback = 10;
1869 			m_leds[0] = 1; // OFF
1870 
1871 			uint8_t sdh = (m_hdc->read(0x06));
1872 
1873 			int hi = (m_hdc->read(0x05)) & 0x07;
1874 			uint16_t cylinder = (m_hdc->read(0x04)) | (hi << 8);
1875 
1876 			int sector_number = m_hdc->read(0x03);
1877 			int sector_count = m_hdc->read(0x02); // (1 = single sector)
1878 
1879 			if (!(cylinder <= info->cylinders &&                     // filter invalid cylinders
1880 				SECTOR_SIZES[(sdh >> 5) & 0x03] == info->sectorbytes // 512, may not vary
1881 				))
1882 			{
1883 				logerror("...*** SANITY CHECK FAILED (CYLINDER %u vs. info->cylinders %u - - SECTOR_SIZE %u vs. info->sectorbytes %u) ***\n",
1884 					cylinder, info->cylinders, SECTOR_SIZES[(sdh >> 5) & 0x03], info->sectorbytes);
1885 				return 50;
1886 			}
1887 			// Pointer to info + C + H + S
1888 			uint32_t lbasector = get_and_print_lbasector(this, info, cylinder, sdh & 0x07, sector_number);
1889 
1890 			if (sector_count != 1) // ignore all SECTOR_COUNTS != 1
1891 				return 88; // logerror(" - ** IGNORED (SECTOR_COUNT !=1) **\n");
1892 
1893 			if (hard_disk_write(local_hard_disk, lbasector, m_hdc_buffer))  // accepts LBA sector (uint32_t) !
1894 				feedback = 99; // success
1895 			else
1896 				logerror("...FAILURE **** \n");
1897 
1898 		} // IF 'info' not nullptr
1899 	} // IF hard disk present
1900 	return feedback;
1901 }
1902 
1903 
hd_status_60_r()1904 uint8_t rainbow_base_state::hd_status_60_r()
1905 {
1906 	int data = m_hdc_buffer[m_hdc_buf_offset];
1907 	//logerror("HARD DISK DISK BUFFER: READ offset %04x | data = %02x\n", m_hdc_buf_offset, data); // ! DO NOT CHANGE ORDER !
1908 
1909 	m_hdc_buf_offset += 1;
1910 	if (m_hdc_buf_offset >= 1024) // 1 K enforced by controller
1911 	{
1912 		m_hdc_buf_offset = 0;
1913 		m_hdc->buffer_ready(true);
1914 	}
1915 	return data;
1916 }
1917 
hd_status_60_w(uint8_t data)1918 void rainbow_base_state::hd_status_60_w(uint8_t data)
1919 {
1920 	//logerror("HARD DISK BUFFER: WRITE offset %04x | data = %02x\n", m_hdc_buf_offset, data);
1921 
1922 	m_hdc_buffer[m_hdc_buf_offset] = data;
1923 	m_hdc_buf_offset += 1;
1924 
1925 	if (m_hdc_buf_offset >= 1024) // 1 K enforced by controller
1926 	{
1927 		m_hdc_buf_offset = 0;
1928 		m_hdc->buffer_ready(true);
1929 	}
1930 }
1931 
1932 
1933 // Secondary Command / Status Registers(68H) is...
1934 //   (A) a write - only register for commands
1935 //   (B) a read - only register for status signals
1936 // Holds the status of the following signals:
1937 // - 3 hard-wired controller module identification bits.
1938 // - signals from the WD1010 chip,
1939 // - disk drive(latched status signals)
hd_status_68_r()1940 uint8_t rainbow_base_state::hd_status_68_r()
1941 {
1942 	// (*) Bits 5-7 : HARD WIRED IDENTIFICATION BITS, bits 5+7 = 1 and bit 6 = 0  (= 101 f?r RD51 module)
1943 	int data = 0xe0; // 111 gives DRIVE NOT READY (when W is pressed on boot screen)
1944 	if (m_inp5->read() == 0x01 && rainbow_hdc_file(0) != nullptr)
1945 		data = 0xa0; // A0 : OK, DRIVE IS READY (!)
1946 
1947 	int my_offset = 0x07;
1948 	int stat = m_hdc->read(my_offset);
1949 //  logerror("(x68) WD1010 register %04x (STATUS) read, result : %04x\n", my_offset, stat);
1950 
1951 	// NOTE: SEEK COMPLETE IS CURRENTLY HARD WIRED / NOT FULLY EMULATED -
1952 	// Bit 4 : SEEK COMPLETE: This status bit indicates that the disk drive positioned the R/W heads over the desired track on the disk surface.
1953 
1954 	// (ALT.TEXT): "Seek Complete - When this signal from the disk drive goes low(0), it indicates that the R /W heads settled on the correct track.
1955 	// Writing is inhibited until this signal goes low(0).  Seek complete is high(1) during normal seek operation.
1956 	if (stat & 16) // SEEK COMPLETE (bit 4)?
1957 		data |= 16;
1958 
1959 	// Bit 3 : DIRECTION : This bit indicates the direction the read/write heads in the disk
1960 	//                     drive will move when the WD1010 chip issues step pulse(s). When high(1), the R / W heads will move toward the spindle.
1961 	//                     When low (0), the heads will move away from the spindle, towards track O.
1962 	if (m_hdc_direction)
1963 		data |= 8;
1964 
1965 	// Bit 2 :  LATCHED STEP PULSE: This status bit from the step pulse latch indicates if the WD1010
1966 	//              chip issued a step pulse since the last time the 8088 processor cleared the step pulse latch.
1967 	if (m_hdc_step_latch)
1968 		data |= 4;
1969 
1970 	// Bit 1 :  LATCHED INDEX : This status bit from the index latch indicates if the disk drive
1971 	//                  encountered an index mark since the last time the 8088 processor cleared the index latch.
1972 	if (m_hdc_index_latch)
1973 		data |= 2;
1974 
1975 	// Bit 0 :  CTRL BUSY : indicates that the WD 1010 chip is accessing the sector buffer. When this bit is set,
1976 	//          the 8088 cannot access the WD 1010 registers.
1977 	if (stat & 128) // BUSY (bit 7)?
1978 		data |= 1;
1979 
1980 	return data;
1981 }
1982 
1983 
1984 // 68 (WRITE): Secondary Command Registers (68H) - -  "write-only register for commands"
1985 // - see TABLE 4.8 (4-24)
hd_status_68_w(uint8_t data)1986 void rainbow_base_state::hd_status_68_w(uint8_t data)
1987 {
1988 	// Bit 4-7 : --- not used / reserved
1989 
1990 	// Bit 3 :  CLEAR STEP LATCH : This bit BAD<3>H clears out the step pulse latch. The step pulse
1991 	//latch is set every time the WD1010 chip issues a step pulse.The output of the step pulse latch is sent to the secondary status register.
1992 	if (data & 0x08)
1993 		m_hdc_step_latch = false;
1994 
1995 	// Bit 2 :  CLEAR INDEX LATCH : This bit BAD<2>H clears out the index latch. The index latch is
1996 	//set when the disk drive senses the index position on the disk.The index latch output is sent to the secondary status register.
1997 	if (data & 0x04)
1998 		m_hdc_index_latch = false;
1999 
2000 	// * Bit 1 :  SOFTWARE INITIALIZE: The BAD<I>H bit sets this bit. This bit, when set, initializes the
2001 	// controller. The controller cannot be accessed for 7 microseconds(us) after the 8088 issues the software initialize.
2002 	if (data & 0x02)
2003 		hdc_reset();
2004 
2005 	// * Bit 0 :  SET BUFFER READY : READ SECTOR command: this bit, when set, tells the WDI010 chip that the sector buffer was emptied which would then end the
2006 	//          command. WRITE SECTOR / FORMAT CMD: bit tells the WD1010 that the sector buffer now contains valid data for transfer to the disk drive.
2007 
2008 	// * SET BY BIOS:  2 : (WD1010 IRQ based transfer operation?)  @ 0810
2009 	//                 1 : see  @ 088D after 'READ_SECTOR_OK'
2010 	if (data & 0x01)
2011 	{
2012 		m_leds[0] = 0;  // 1 = OFF (One of the CPU LEDs as DRIVE LED) = HARD DISK ACTIVITY =
2013 		switch_off_timer->adjust(attotime::from_msec(500));
2014 
2015 		m_hdc->buffer_ready(true);
2016 	}
2017 }
2018 
2019 
2020 /*
2021 / READ ONLY REGISTER (HEX 69)
2022 
2023 The drive status register at I/O address 69H is a read-only register
2024 that monitors the status of control and error signals to/from the disk drive.
2025 
2026 0 Drive Select - high (1) indicates that the controller module is selecting the drive.
2027 
2028 1-3 Head Select - These 3 bits are the binary head address of the R/W head
2029 selected for the current read/write operation. The RD51 drive has 4 heads.
2030 
2031 4 Write Gate - The WDlOI0 chip asserts this bit high (1) to inform the 8088 of
2032 data being written on the disk. Signal also enables write current in disk drive.
2033 
2034 5 Drive Write Fault - The disk drive asserts this bit high (1) to indicate that a condition
2035 exists at the drive that may cause improper writing on the disk.
2036 Inhibits further writing until the error is corrected (.. until RESET?) [Bavarese]
2037 
2038 6 Drive Ready - When the disk drive together with SEEK COMPLETE asserts this
2039 bit high (1), it indicates that the drive is ready to read, write, or
2040 seek. When this bit is low (0), all reading, writing, and seeking are
2041 inhibited.
2042 
2043 7 Track 0 - The disk drive sets this bit high (1) when the R/W heads are
2044 positioned over cylinder 0 (the data track furthest away from the spindle).
2045 */
hd_status_69_r()2046 uint8_t rainbow_base_state::hd_status_69_r()
2047 {
2048 	int hs = m_hdc->read(0x06) & (1 + 2 + 4); // SDH bits 0-2 = HEAD #
2049 //  logerror("(x69 READ) %i = HEAD SELECT WD1010\n", hs);
2050 
2051 	uint8_t data = (hs << 1);
2052 
2053 	// DRIVE SELECT: 2 bits in SDH register of WDx010 could address 4 drives.
2054 	// External circuit supports 1 drive here (DRIVE 0 selected or deselected)
2055 	int drv = ((m_hdc->read(0x06) >> 3) & 0x01);  // 0x03 gives error R6 with DIAG.DISK
2056 	if (drv == 0)
2057 		data |= 1; //      logerror("(x69 READ) %i = _DRIVE # 0_ SELECT! \n", drv);
2058 
2059 	if (m_hdc_write_gate) // WRITE GATE (cached here)
2060 		data |= 16;
2061 
2062 	if (m_hdc_write_fault)
2063 		data |= 32;
2064 
2065 	if (m_hdc_drive_ready)
2066 		data |= 64;
2067 
2068 	// Fake TRACK 0 signal  (normally FROM DRIVE)
2069 	if ((m_hdc->read(0x04) == 0) && (m_hdc->read(0x05) == 0)) // CYL.LO - CYL.HI
2070 		data |= 128; //      logerror("(x69 READ) TRACK 00 detected\n");
2071 
2072 	return data;
2073 }
2074 
2075 // TREAT SIGNALS FROM / TO CONTROLLER
WRITE_LINE_MEMBER(rainbow_base_state::hdc_step)2076 WRITE_LINE_MEMBER(rainbow_base_state::hdc_step)
2077 {
2078 	m_hdc_step_latch = true;
2079 
2080 	m_leds[0] = 0;  // 1 = OFF (One of the CPU LEDs as DRIVE LED)  = HARD DISK ACTIVITY =
2081 	switch_off_timer->adjust(attotime::from_msec(500));
2082 }
2083 
WRITE_LINE_MEMBER(rainbow_base_state::hdc_direction)2084 WRITE_LINE_MEMBER(rainbow_base_state::hdc_direction)
2085 {
2086 	m_hdc_direction = state; // (0 = OUT)
2087 }
2088 
READ_LINE_MEMBER(rainbow_base_state::hdc_drive_ready)2089 READ_LINE_MEMBER(rainbow_base_state::hdc_drive_ready)
2090 {
2091 	return m_hdc_drive_ready;
2092 }
2093 
READ_LINE_MEMBER(rainbow_base_state::hdc_write_fault)2094 READ_LINE_MEMBER(rainbow_base_state::hdc_write_fault)
2095 {
2096 	return m_hdc_write_fault;
2097 }
2098 
2099 // Buffer counter reset when BCR goes from 0 -> 1
WRITE_LINE_MEMBER(rainbow_base_state::hdc_bcr)2100 WRITE_LINE_MEMBER(rainbow_base_state::hdc_bcr)
2101 {
2102 	static int bcr_state;
2103 	if (bcr_state == 0 && state == 1)
2104 		hdc_buffer_counter_reset();
2105 	bcr_state = state;
2106 }
2107 
hdc_buffer_counter_reset()2108 void rainbow_base_state::hdc_buffer_counter_reset()
2109 {
2110 	m_hdc->buffer_ready(false);
2111 	m_hdc_buf_offset = 0;
2112 }
2113 
2114 // DATA REQUEST - When high (..) initiates data transfers
2115 // to or from the sector buffer. On a READ, this signal
2116 // goes high AFTER the sector buffer is filled.
2117 
2118 // On a WRITE / FORMAT command, signal goes high when the WD1010
2119 // chip is READY TO ACCESS the information in the sector buffer.
WRITE_LINE_MEMBER(rainbow_base_state::hdc_bdrq)2120 WRITE_LINE_MEMBER(rainbow_base_state::hdc_bdrq)
2121 {
2122 	static int old_state;
2123 //  logerror("BDRQ - BUFFER DATA REQUEST OBTAINED: %u\n", state);
2124 
2125 	if (state == 1 && old_state == 0)
2126 	{
2127 		hdc_buffer_counter_reset();
2128 
2129 		m_bdl_irq = state;
2130 		update_bundle_irq(); // TRIGGER AN INTERRUPT
2131 	}
2132 	old_state = state;
2133 }
2134 // ---------------------------- / RD51 HARD DISK CONTROLLER ----------------------------------
2135 
2136 
2137 // IRQ service for both RD51 and COMM. OPTION
update_bundle_irq()2138 void rainbow_base_state::update_bundle_irq()
2139 {
2140 	if (m_bdl_irq == 0)
2141 	{
2142 		lower_8088_irq(IRQ_BDL_INTR_L);
2143 
2144 		if (m_inp5->read() == 0x01)
2145 			hdc_buffer_counter_reset();
2146 	}
2147 	else
2148 	{
2149 		raise_8088_irq(IRQ_BDL_INTR_L);
2150 	}
2151 }
2152 
WRITE_LINE_MEMBER(rainbow_base_state::bundle_irq)2153 WRITE_LINE_MEMBER(rainbow_base_state::bundle_irq)
2154 {
2155 	m_bdl_irq = state;
2156 	update_bundle_irq();
2157 }
2158 
2159 
system_parameter_r()2160 uint8_t rainbow_modela_state::system_parameter_r()
2161 {
2162 	/*  Info about option boards is in bits 0 - 3:
2163 	SYSTEM PARAMETER INFORMATION: see AA-P308A-TV page 92 section 14.0
2164 	Bundle card (1) | Floppy (2) | Graphics (4) | Memory option (8)
2165 	0 1 2 3 4 5 6 7
2166 	B F G M
2167 	(bit SET means NOT present; 4-7 reserved )
2168 
2169 	B : no separation between the 2 available 'bundle cards' (HD controller / COMM.OPTION) ?
2170 
2171 	M : old RAM extension (128 / 192 K ?) detected with OPTION_PRESENT bit, newer models 'by presence'.
2172 	BIOS uses a seperate IRQ vector for RAM board detection (at least on a 100-B).
2173 	*/
2174 	return ((m_inp5->read() == 1 ? 0 : 1) |
2175 			(m_inp7->read() == 1 ? 0 : 4) | // Floppy is always present (bit 1 zero)
2176 			(m_ram->size() > 0x10000 ? 0 : 8) |
2177 			0xf0); // unverified
2178 }
2179 
system_parameter_r()2180 uint8_t rainbow_modelb_state::system_parameter_r()
2181 {
2182 	/*  Info about option boards is in bits 0 - 3:
2183 	SYSTEM PARAMETER INFORMATION: see AA-P308A-TV page 92 section 14.0
2184 	Bundle card (1) | Floppy (2) | Graphics (4) | Memory option (8)
2185 	0 1 2 3 4 5 6 7
2186 	B F G M
2187 	(bit SET means NOT present; 4-7 reserved )
2188 
2189 	B : no separation between the 2 available 'bundle cards' (HD controller / COMM.OPTION) ?
2190 
2191 	M : old RAM extension (128 / 192 K ?) detected with OPTION_PRESENT bit, newer models 'by presence'.
2192 	BIOS uses a seperate IRQ vector for RAM board detection (at least on a 100-B).
2193 	*/
2194 	return ((m_inp5->read() == 1 ? 0 : 1) |
2195 			(m_inp7->read() == 1 ? 0 : 4) | // Floppy is always present (bit 1 zero)
2196 			0xf8); // unverified
2197 }
2198 
2199 //  [02] COMMUNICATIONS STATUS REGISTER - PAGE 154 (**** READ **** )
2200 //  Used to read status of SERIAL port, IRQ line of each CPU, and MHFU logic enable signal.
2201 
2202 // 0 COMM RI   (reflects status of RI line at COMM port)
2203 // 1 COMM SI / SCF(reflects status of speed indicator line or
2204 //                 the secondary receive line signal detect at COMM port)
2205 // 2 COMM DSR  (reflects status of DSR at COMM)
2206 // 3 COMM CTS  (reflects status of CTS at COMM)
2207 // 4 COMM RLSD (receive line signal detect at COMM; also connected to DCDA on MPSC)
comm_control_r()2208 uint8_t rainbow_base_state::comm_control_r()
2209 {
2210 	bool is_mhfu_enabled = false;
2211 	if (m_power_good)
2212 		is_mhfu_enabled = m_crtc->MHFU(MHFU_IS_ENABLED);
2213 
2214 	return (m_comm_port->ri_r() ? 0x01 : 0x00) |
2215 		   (m_comm_port->si_r() ? 0x02 : 0x00) |
2216 		   (m_comm_port->dsr_r() ? 0x04 : 0x00) |
2217 		   (m_comm_port->cts_r() ? 0x08 : 0x00) |
2218 		   (m_comm_port->dcd_r() ? 0x10 : 0x00) |
2219 		   (is_mhfu_enabled ? 0x00 : 0x20) |   // (L) status of MHFU flag => bit pos.5
2220 		   (m_int88 ? 0x00 : 0x40) |           // (L)
2221 		   (m_intz80 ? 0x00 : 0x80);           // (L)
2222 
2223 }
2224 
2225 //  Communication control register of -COMM- port (when written):
2226 // (these 4 bits talk DIRECTLY to the COMM port according to schematics):
2227 // 0 COMM SPD SEL H (controls speed select line of COMM port)
2228 // 1 COMM SRTS H     (controls secondary request to send line of COMM)
2229 // 2 COMM DTR L      (controls terminal ready line of COMM)
2230 // 3 COMM RTS        (controls request to send line of COMM)
comm_control_w(uint8_t data)2231 void rainbow_base_state::comm_control_w(uint8_t data)
2232 {
2233 	logerror("%02x to COMM.CONTROL REGISTER ", data);
2234 
2235 	m_comm_port->write_spds(BIT(data, 0));
2236 	// SRTS not currently emulated
2237 	m_comm_port->write_dtr(BIT(data, 2));
2238 	m_comm_port->write_rts(BIT(data, 3));
2239 
2240 	/* 8088 LEDs:
2241 	5  7  6  4    <- BIT POSITION
2242 	D6 -D5-D4-D3  <- INTERNAL LED NUMBER (DEC PDF)
2243 	-4--5--6--7-  <- NUMBERS EMBOSSED ON BACK OF PLASTIC HOUSING (see error chart)
2244 	*/
2245 	m_leds[3] = BIT(data, 5); // LED "D6"
2246 	m_leds[4] = BIT(data, 7); // LED "D5"
2247 	m_leds[5] = BIT(data, 6); // LED "D4"
2248 	m_leds[6] = BIT(data, 4); // LED "D3"
2249 }
2250 
2251 // 8088 writes to port 0x00 (interrupts Z80)
2252 // See page 133 (4-34)
i8088_latch_w(uint8_t data)2253 void rainbow_base_state::i8088_latch_w(uint8_t data)
2254 {
2255 	// logerror("%02x to Z80 mailbox\n", data);
2256 
2257 	// The interrupt vector address(F7H) placed on the bus is hardwired into the Z80A interrupt vector encoder.
2258 	// The F7H interrupt vector address causes the Z80A processor to perform an RST 30 instruction in
2259 	// interrupt mode 0
2260 	m_z80->set_input_line_and_vector(0, ASSERT_LINE, 0xf7); // Z80
2261 	m_z80_mailbox = data;
2262 
2263 	m_intz80 = true;
2264 }
2265 
2266 // Z80 reads port 0x00
2267 // See page 134 (4-35)
z80_latch_r()2268 uint8_t rainbow_base_state::z80_latch_r()
2269 {
2270 	// logerror("Read %02x from Z80 mailbox\n", m_z80_mailbox);
2271 	m_z80->set_input_line(0, CLEAR_LINE);
2272 
2273 	m_intz80 = false;
2274 	return m_z80_mailbox;
2275 }
2276 
2277 // Z80 writes to port 0x00 (interrupts 8088)
2278 // See page 134 (4-35)
z80_latch_w(uint8_t data)2279 void rainbow_base_state::z80_latch_w(uint8_t data)
2280 {
2281 	// logerror("%02x to 8088 mailbox\n", data);
2282 	raise_8088_irq(IRQ_8088_MAILBOX);
2283 	m_8088_mailbox = data;
2284 
2285 	m_int88 = true;
2286 }
2287 
2288 // 8088 reads port 0x00. See page 133 (4-34)
i8088_latch_r()2289 uint8_t rainbow_base_state::i8088_latch_r()
2290 {
2291 	// logerror("Read %02x from 8088 mailbox\n", m_8088_mailbox);
2292 	lower_8088_irq(IRQ_8088_MAILBOX);
2293 
2294 	m_int88 = false;
2295 	return m_8088_mailbox;
2296 }
2297 
2298 // (Z80) : WRITE to 0x20
z80_diskdiag_read_w(uint8_t data)2299 void rainbow_base_state::z80_diskdiag_read_w(uint8_t data)
2300 {
2301 	m_zflip = true; //  "a write to 20H will _SET_ ZFLIP"
2302 }
2303 
2304 // (Z80) : PORT 21H * WRITE *
z80_diskdiag_write_w(uint8_t data)2305 void rainbow_base_state::z80_diskdiag_write_w(uint8_t data)
2306 {
2307 	/*   Z80 LEDs:
2308 	4   5   6  <- bit #
2309 	D11 D10 -D9 <- INTERNAL LED NUMBER (see PDF)
2310 	-1 --2-- 3  <- NUMBERS EMBOSSED ON BACK OF PLASTIC HOUSING (see error chart)
2311 	*/
2312 	m_leds[0] = BIT(data, 4); // LED "D11"
2313 	m_leds[1] = BIT(data, 5); // LED "D10"
2314 	m_leds[2] = BIT(data, 6); // LED "D9"
2315 
2316 	m_zflip = false; // "a write to 21H will reset ZFLIP"
2317 }
2318 
2319 // (Z80) : PORT 20H / 21H  _READ_
z80_generalstat_r()2320 uint8_t rainbow_base_state::z80_generalstat_r()
2321 {
2322 	/*
2323 	General / diag.status register Z80 / see page 157 (table 4-18).
2324 	---- BITS FROM RX50 CONTROLLER CARD:
2325 	D7 : STEP L : reflects status of STEP signal _FROM FDC_
2326 	(when this 2us output pulse is low, the stepper will move into DIR)
2327 	D6 : WRITE GATE L :reflects status of WRITE GATE signal _FROM FDC_
2328 	(asserted low before data can be written on the diskette)
2329 	D5 : TR00: reflects status of TRACK 0 signal (= 1) * from the disk drive *
2330 	D4 : DIR L: reflects status of DIRECTION signal * FROM FDC * to disk
2331 	(when low, the head will step towards the center)
2332 	D3 : READY L: reflects status of READY L signal * from the disk drive *
2333 	(low active, asserts when disk is inserted and door is closed)
2334 	---- BITS BELOW FROM MAINBOARD:
2335 	D2 : INT88 L: (bit reads the INT88 bit sent by Z80 to interrupt 8088)
2336 	D1 : INTZ80 L: (bit reads the INTZ80 bit sent by 8088 to interrupt Z80)
2337 	D0 : ZFLIP L: (read from the diagnostic control register of Z80A)
2338 	*/
2339 	static int last_track;
2340 	int track = 0;
2341 
2342 	int fdc_step = 0;
2343 	int fdc_ready = 0;
2344 	int tk00 = 0;
2345 	int fdc_write_gate = 0;
2346 	int last_dir = 0;
2347 
2348 	uint8_t fdc_status;
2349 
2350 	if (m_fdc)
2351 	{
2352 		track = m_fdc->track_r();
2353 		if (track == 0)
2354 			tk00 = 1;
2355 
2356 		if (track != last_track)
2357 			fdc_step = 1;  // calculate STEP (sic)
2358 
2359 		last_dir = track > last_track ? 0 : 1; // see WD_FDC
2360 		last_track = track;
2361 
2362 		fdc_status = m_fdc->status_r();
2363 
2364 		if ((fdc_status & 0x80) == 0) // (see WD_FDC: S_WP = 0x40, S_NRDY = 0x80, S_TR00 = 0x04)
2365 			fdc_ready = 1;
2366 
2367 		if (fdc_ready && ((fdc_status & 0x40) == 0) && m_power_good)
2368 			fdc_write_gate = 1; // "valid only when drive is selected" !
2369 	}
2370 	// logerror(" RDY:%x  WG:%d ",fdc_ready,fdc_write_gate);
2371 	int data = (fdc_step ? 0x00 : 0x80) |
2372 			   (fdc_write_gate ? 0x00 : 0x40) |
2373 			   (tk00 ? 0x20 : 0x00) |  // ***** ALL LOW ACTIVE - EXCEPT tk00 :
2374 			   (last_dir ? 0x00 : 0x10) |
2375 			   (fdc_ready ? 0x00 : 0x08) |
2376 			   (m_int88 ? 0x00 : 0x04) |
2377 			   (m_intz80 ? 0x00 : 0x02) |
2378 			   (m_zflip ? 0x00 : 0x01);
2379 
2380 	return data;
2381 }
2382 
2383 
2384 // (Z80) : PORT 40H _READ_
2385 // 40H diskette status Register **** READ ONLY *** ( 4-60 of TM100.pdf )
z80_diskstatus_r()2386 uint8_t rainbow_base_state::z80_diskstatus_r()
2387 {
2388 	int track = 0xEE;
2389 	int data = m_z80_diskcontrol & (255 - 0x80 - 0x40 - 0x20 - 0x04); // 00011011
2390 
2391 	// D7: DRQ: reflects status of DATA REQUEST signal from FDC.
2392 	// '1' indicates that FDC has read data OR requires new write data.
2393 
2394 	// D6: IRQ: indicates INTERRUPT REQUEST signal from FDC. Indicates that a
2395 	//          status bit has changed. Set to 1 at the completion of any
2396 	//          command (.. see page 207 or 5-25).
2397 	if (m_fdc)
2398 	{
2399 		data |= m_fdc->drq_r()   ? 0x80 : 0x00;
2400 		data |= m_fdc->intrq_r() ? 0x40 : 0x00;
2401 		track = m_fdc->track_r();
2402 
2403 		// D2: TG43 * LOW ACTIVE * :  0 = INDICATES TRACK > 43 SIGNAL FROM FDC TO DISK DRIVE.
2404 		// (asserted when writing data to tracks 44 through 79)
2405 		data |= (track > 43) ? 0x00 : 0x04;  // ! LOW ACTIVE !
2406 	}
2407 
2408 	// D5: SIDE 0 * HIGH ACTIVE *: status of side select signal at J2 + J3 of RX50 controller.
2409 	//              For 1 sided drives, this bit will always read low (0).
2410 	if (m_floppy != nullptr)
2411 		data |= m_floppy->ss_r() ? 0x20 : 0x00;
2412 
2413 	// *LOW ACTIVE *
2414 	// D4: MOTOR 1 ON L: 0 = indicates MOTOR 1 ON bit is set in drive control reg.
2415 	// D3: MOTOR 0 ON L: 0 = indicates MOTOR 0 ON bit is set in drive  "
2416 
2417 	// Print HEX track number
2418 	static uint8_t bcd2hex[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 };
2419 	// 0...9 ,A (0x77), b (0x7c), C (0x39) , d (0x5e), E (0x79), F (0x71)
2420 	m_digits[0] = bcd2hex[(track >> 4) & 0x0f];
2421 	m_digits[1] = bcd2hex[track & 0x0f];
2422 
2423 	// D1: DS1 H: reflect status of bits 0 and 1 from disk.control reg.
2424 	// D0: DS0 H: "
2425 	return data;
2426 }
2427 
2428 
2429 // (Z80) : PORT 40H  * WRITE *
2430 // NOTE: routine will accept invalid drive letters...
2431 
2432 // ALL SIGNALS ARE HIGH ACTIVE (H), EXCEPT:
2433 // BIT 5 : SIDE 0 L : For single sided drives, this bit is always set to 0 for side O.
z80_diskcontrol_w(uint8_t data)2434 void rainbow_base_state::z80_diskcontrol_w(uint8_t data)
2435 {
2436 	int enable_start;
2437 	int disable_start; // set defaults
2438 
2439 	int selected_drive = INVALID_DRIVE;
2440 
2441 	int drive = 0;
2442 	if (m_inp10->read() && ((data & 3) < 2))
2443 		drive = (data & 1) + 2;
2444 	else
2445 		drive = data & 3;
2446 
2447 	if (m_floppies[drive])
2448 	{
2449 		m_floppy = m_floppies[drive]->get_device();
2450 		if (m_floppy)
2451 			selected_drive = drive;
2452 	}
2453 
2454 	if (selected_drive == INVALID_DRIVE)
2455 	{
2456 		logerror("(m_present_drive = %i)   ** SELECTED DRIVE ** INVALID. (selected drive = %i)\n", m_present_drive, selected_drive);
2457 
2458 		m_present_drive = INVALID_DRIVE;
2459 		m_floppy = nullptr;
2460 	}
2461 
2462 	for (int i = 0; i < 4; i++)
2463 		m_driveleds[i] = (selected_drive == i) ? 1 : 0;
2464 	switch_off_timer->adjust(attotime::from_msec(500));
2465 
2466 	if (m_floppy != nullptr)
2467 	{
2468 		m_fdc->set_floppy(m_floppy);  // Sets new  _image device_
2469 		m_fdc->dden_w(0); // 0 = MFM
2470 		m_floppy->ss_w((data & 0x20) ? 1 : 0); // RX50 board in Rainbow has 'side select'
2471 		m_floppy->set_rpm(300.);
2472 
2473 		if ( !m_floppy->exists() && (selected_drive > 1) )
2474 			popmessage("NO IMAGE ATTACHED TO %c\n", 65 + selected_drive );
2475 	}
2476 
2477 	if (selected_drive < MAX_FLOPPIES)
2478 	{
2479 		m_present_drive = selected_drive;
2480 
2481 		bool force_ready = ((data & 4) == 0) ? true : false;
2482 		m_fdc->set_force_ready(force_ready); // 1 : assert DRIVE READY on FDC (diagnostic override)
2483 
2484 		if (selected_drive < 2)
2485 		{
2486 			data |= 8;
2487 			enable_start = 0;
2488 			disable_start = 2;
2489 		}
2490 		else
2491 		{
2492 			data |= 16;
2493 			enable_start = 2;
2494 			disable_start = 4;
2495 		}
2496 
2497 		// RX-50 has head A and head B (1 for each of the 2 disk slots in a RX-50).
2498 		// Assume the other one is switched off -
2499 		for (int f_num = 0; f_num < MAX_FLOPPIES; f_num++)
2500 		{
2501 		floppy_image_device *tmp_floppy = m_floppies[f_num]->get_device();
2502 
2503 		if (!tmp_floppy)
2504 			continue;
2505 		tmp_floppy->mon_w(ASSERT_LINE);
2506 		if ((f_num >= enable_start) && (f_num < disable_start))
2507 			tmp_floppy->mon_w(CLEAR_LINE); // enable
2508 		}
2509 	}
2510 
2511 	data = (data & (255 - 3)); // invalid drive = DRIVE 0 ?!
2512 
2513 	if (m_present_drive == INVALID_DRIVE)
2514 		logerror("**** INVALID DRIVE ****\n");
2515 	else
2516 		data = data | m_present_drive;
2517 
2518 	m_z80_diskcontrol = data;
2519 }
2520 // --------- END OF Z80 --------------------
2521 
read_video_ram_r(offs_t offset)2522 uint8_t rainbow_base_state::read_video_ram_r(offs_t offset)
2523 {
2524 	return m_p_ram[offset];
2525 }
2526 
2527 
2528 
2529 
2530 // **************************************************
2531 // VIDEO INTERRUPT HANDLING
2532 // **************************************************
2533 
2534 // CPU acknowledge of VBL IRQ resets counter
IRQ_CALLBACK_MEMBER(rainbow_base_state::irq_callback)2535 IRQ_CALLBACK_MEMBER(rainbow_base_state::irq_callback)
2536 {
2537 	int intnum = -1;
2538 	for (int i = IRQ_8088_VBL; i >= 0; i--)
2539 	{
2540 			if (m_irq_mask & (1 << i))
2541 			{
2542 				if (i == IRQ_8088_VBL)  // If VBL IRQ acknowledged...
2543 					m_crtc->MHFU(MHFU_RESET); // ...reset counter (also: DC012_W)
2544 
2545 				intnum = vectors[i] | m_irq_high;
2546 				break;
2547 			}
2548 	}
2549 	return intnum;
2550 }
2551 
2552 // NEC7220 Vsync IRQ ***************************************** GDC
2553 
2554 // VERIFY: SCROLL_MAP & COLOR_MAP are updated at the next VSYNC (not immediately)... Are there more registers?
WRITE_LINE_MEMBER(rainbow_base_state::GDC_vblank_irq)2555 WRITE_LINE_MEMBER(rainbow_base_state::GDC_vblank_irq)
2556 {
2557 	// VERIFICATION NEEDED: IRQ raised before or after new palette loaded...?
2558 	if (m_gdc_mode_register & GDC_MODE_ENABLE_VSYNC_IRQ) // 0x40
2559 		raise_8088_irq(IRQ_GRF_INTR_L);
2560 	else
2561 		lower_8088_irq(IRQ_GRF_INTR_L);
2562 
2563 	m_monitor_suggested = m_inp13->read();
2564 	if (m_monitor_suggested < 1 || m_monitor_suggested > 3)
2565 		m_monitor_suggested = COLOR_MONITOR;
2566 
2567 	int mono_sum = 0;
2568 	int green_sum = 0;
2569 	for (uint8_t xi = 0; xi < 16; xi++) // DELAYED LOAD OF PALETTE ...
2570 	{
2571 		uint8_t colordata1  = m_gdc_color_map[xi];
2572 		uint8_t colordata2 = m_gdc_color_map[xi + 16];      // Does it matter if the palette is incomplete...?
2573 
2574 		//              Color map:  32 x 8
2575 		//              2nd 16 Byte     1st 16 Bytes (colordata1)
2576 		//              -----------     ------------
2577 		//              7..4  3..0      7..4  3..0
2578 		//              Mono  Blue      Red   Green
2579 		// NOTE: 2nd 16 BYTES ARE MONO PALETTE, 1st 16 ARE COLOR PALETTE * HERE * (on the VT240 driver, it is the other way round)
2580 
2581 		uint8_t mono = (colordata2 & 0xF0) >> 4;  // FIXME: limit palette in appropriate modes on 100-A
2582 		mono_sum += mono;
2583 
2584 		uint8_t blue = (colordata2 & 0x0F);
2585 
2586 		uint8_t red  = (colordata1 & 0xF0) >> 4;
2587 		uint8_t green =(colordata1 & 0x0F);
2588 		green_sum += green;
2589 
2590 		switch (m_monitor_suggested)
2591 		{
2592 		case MONO_MONITOR:
2593 			switch (m_inp9->read()) //  - monochrome monitor (phosphor) type  (1,2,3)
2594 			{
2595 			case 1: // BLACK & WHITE
2596 				m_palette2->set_pen_color(xi + 16, pal4bit(mono), pal4bit(mono), pal4bit(mono) );
2597 				break;
2598 
2599 			case 2: // GREEN SHADES. Hand picked value from vtvideo coarsly transformed into a RGB value:
2600 				red   = uint8_t( ( 35.0f / 100.0f) *  ( video_levels[ mono ] / 2.55f) );
2601 				green = uint8_t( (145.0f / 100.0f) *  ( video_levels[ mono ] / 2.55f) );
2602 				blue  = uint8_t( ( 75.0f / 100.0f) *  ( video_levels[ mono ] / 2.55f) );
2603 				m_palette2->set_pen_color(xi + 16, rgb_t( red, green, blue) );
2604 				break;
2605 
2606 			case 3: // AMBER. Assumption: "normal" value at 80 % is 213, 146, 82 (decimal)
2607 				red   = uint8_t( (213.0f / 100.0f) *  ( video_levels[ mono ] / 2.55f) );
2608 				green = uint8_t( (146.0f / 100.0f) *  ( video_levels[ mono ] / 2.55f) );
2609 				blue  = uint8_t( ( 82.0f / 100.0f) *  ( video_levels[ mono ] / 2.55f) );
2610 				m_palette2->set_pen_color(xi + 16, rgb_t( red, green, blue) );
2611 				break;
2612 			}
2613 			break;
2614 
2615 		case COLOR_MONITOR:
2616 			if (!(m_gdc_mode_register & GDC_MODE_ENABLE_VIDEO))
2617 				red = blue = 0; // Page 21 of AA-AE36A (PDF) explains why
2618 
2619 			m_palette2->set_pen_color(xi, pal4bit(red) , pal4bit(mono) , pal4bit(blue));
2620 			break;
2621 
2622 		case DUAL_MONITOR:
2623 			m_palette2->set_pen_color(xi, pal4bit(red), pal4bit(green), pal4bit(blue));
2624 			break;
2625 		}
2626 	} // palette (loop)
2627 
2628 	if (green_sum > 0 && green_sum == mono_sum) // (R-G-B + M) palette (split cable). Examples: PACMAN, AutoCad
2629 	{
2630 		if (m_monitor_suggested == MONO_MONITOR)
2631 			logerror("\n[HINT: COLOR PALETTE DETECTED - SUITABLE FOR DUAL MONITOR] ");
2632 		if (m_inp13->read() == AUTODETECT_MONITOR)
2633 			m_monitor_suggested = DUAL_MONITOR;
2634 	}
2635 
2636 	if (green_sum == 0 && mono_sum > 0)  // No green = original DEC spec. Example: NLANDER. All older libaries use R-M-B.
2637 	{
2638 		if (m_inp13->read() == AUTODETECT_MONITOR)
2639 			m_monitor_suggested = COLOR_MONITOR;
2640 		if (m_monitor_suggested == DUAL_MONITOR)
2641 			logerror("\n[HINT: SINGLE COLOR MONITOR ONLY!  GREEN MISSING => NO SPLIT CABLE]");
2642 	}
2643 
2644 } // 7220 vblank IRQ
2645 
2646 
WRITE_LINE_MEMBER(rainbow_base_state::video_interrupt)2647 WRITE_LINE_MEMBER(rainbow_base_state::video_interrupt)
2648 {
2649 	if (state == ASSERT_LINE)
2650 		raise_8088_irq(IRQ_8088_VBL);
2651 	else
2652 		lower_8088_irq(IRQ_8088_VBL);
2653 
2654 	if (state == ASSERT_LINE && m_power_good && m_crtc->MHFU(MHFU_IS_ENABLED)) // If enabled...
2655 	{
2656 		if (m_crtc->MHFU(MHFU_VALUE) > 10) // + more than (10 * 16.666) msecs gone (108 ms would be by the book)
2657 		{
2658 			m_crtc->MHFU(MHFU_RESET_and_DISABLE);
2659 			popmessage("**** WATCHDOG TRIPPED:nVBL IRQ not acknowledged within (at least) 108 milliseconds. ****");
2660 
2661 			if (m_inp12->read() == 0x01) // (DIP) for watchdog active?
2662 				cmd_timer->adjust(attotime::from_msec(RESET_DURATION_MS));
2663 		}
2664 	}
2665 }
2666 
2667 // Reflects bits from 'diagnostic_w' (1:1), except test jumpers
diagnostic_r()2668 uint8_t rainbow_base_state::diagnostic_r() // 8088 (port 0A READ). Fig.4-29 + table 4-15
2669 {
2670 	return ((m_diagnostic & 0xf1) | m_inp1->read() | m_inp2->read() | m_inp3->read());
2671 }
2672 
diagnostic_w(uint8_t data)2673 void rainbow_base_state::diagnostic_w(uint8_t data) // 8088 (port 0A WRITTEN). Fig.4-28 + table 4-15
2674 {
2675 	//    logerror("%02x to diag port (PC=%x)\n", data, m_i8088->pc());
2676 
2677 	// ZRESET from 8088 to Z80 - - HIGH at powerup!
2678 	if (!(data & 1))
2679 	{
2680 		m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
2681 		m_z80_halted = true;
2682 	}
2683 
2684 	if ((data & 1) && (m_z80_halted))
2685 	{
2686 		m_zflip = true;
2687 		m_z80_halted = false;
2688 
2689 		m_z80->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
2690 		m_z80->reset();
2691 	}
2692 
2693 	if ((m_diagnostic & 1) && !(data & 1)) // ZRESET goes LOW...
2694 	{
2695 		logerror("FDC ** RESET **\n");
2696 		m_fdc->reset();
2697 	}
2698 
2699 	if (!(m_diagnostic & 1) && (data & 1)) // ZRESET goes HIGH...
2700 	{
2701 		logerror("FDC RESTORE\n");
2702 		m_fdc->reset(); // See formatter description p.197 or 5-13
2703 	}
2704 
2705 	m_screen_blank = BIT(data, 1)? false : true; // inverse logic
2706 
2707 	// Switch determines how the monochrome output pin is taken from:
2708 	//    0  = M(ono) out from system module (DC011/DC012). Default, also used to setup dual monitors.
2709 	//    1  = M(ono) output from GRAPHICS OPTION. (G)reen remains unused with a single COLOR monitor.
2710 	m_onboard_video_selected = (data & 0x04) ? false : true;
2711 	if (!m_onboard_video_selected)
2712 	{
2713 		if (m_inp7->read() == 1)
2714 		{
2715 			logerror("HINT: GRAPHICS OPTION ON. TEXT ONLY (DC011/DC012) OUTPUT NOW DISABLED.\n");
2716 		}
2717 		else
2718 		{       logerror("ALARM: GRAPHICS OPTION * SWITCHED OFF * VIA DIP. TEXT OUTPUT STILL ENABLED!\n");
2719 			m_onboard_video_selected = true;
2720 		}
2721 		logerror("DATA: %x (PC=%x)\n", data, m_i8088->pc());
2722 	}
2723 
2724 	// BIT 3: PARITY (1 enables parity test on memory board. Usually 64K per bank). -> ext_ram_w.
2725 	if (data & 0x08)
2726 		logerror("*** PARITY TEST [on RAM EXTENSION] - (bit 3 - diagnostic_w)\n");
2727 
2728 	// MISSING BITS (* not vital for normal operation, see diag.disk) -
2729 	// * BIT 4: DIAG LOOPBACK (0 at power-up; 1 directs RX50 and DC12 output to printer port)
2730 	// * BIT 5: PORT LOOPBACK (1 enables loopback for COMM, PRINTER, KEYBOARD ports)
2731 
2732 	/* 2.1.7.3 DIAGNOSTIC LOOPBACK Maintenance Bit - The DIAGNOSTIC LOOPBACK bit is a
2733 	maintenance bit that is cleared on power - up.This bit, when set to 1,
2734 	allows the floppy data separator and the serial video output to be tested
2735 	through the use of the printer port. The following table shows how signals are routed.
2736 
2737 	DIAGNOSTIC LOOPBACK = 0     DIAGNOSTIC LOOPBACK = 1     SIGNAL INPUT
2738 	SIGNAL SOURCE               SIGNAL SOURCE               TO
2739 	FROM                        FROM
2740 	PRT RDATA(J2)               VIDEO OUT                   PRT RXD(7201)
2741 	PRT RXTXC                   500 KHZ                     PRT RXTXC(7201)
2742 	MASTER CLK                  250 KHZ                     VIDEO CLK(DCO11)
2743 	FLOPPY RAW DATA             PRT TXD(7201)               FLOPPY DATA SEPARATOR
2744 
2745 	During Diagnostic Loopback, the - TEST input of the 8088 is connected to the
2746 	interrupt output of the MPSC.Thus, using the 8088's WAIT instruction in a
2747 	polled I / O loop, the diagnostic firmware will be able to keep up with the
2748 	500 Kb data rate on the MPSC.
2749 	*/
2750 	if (data & 16)
2751 	{
2752 		logerror("WARNING: UNEMULATED DIAG LOOPBACK (directs RX50 and DC12 output to printer port) ****\n");
2753 	}
2754 
2755 	address_space &io = m_i8088->space(AS_IO);
2756 	if (data & 32)
2757 	{
2758 		/* BIT 5: PORT LOOPBACK (1 enables loopback for COMM, PRINTER, KEYBOARD ports)
2759 		2.1.7.2. of AA-V523A-TV (PDF Mar83) says how the signals are routed:
2760 		port_loopback_0  |  port_loopback_1   SIGNAL INPUT TO
2761 		COMM RCV DATA.......COMM TXD..........COMM_RXD
2762 		PRT  RCV DATA.......KBD TXD...........PRT RDATA
2763 		KBD  RCV DATA.......PRT TXD...........KBD RXD
2764 		*/
2765 		logerror("WARNING: UNEMULATED PORT LOOPBACK (COMM, PRINTER, KEYBOARD ports) ****\n");
2766 
2767 		io.unmap_readwrite(0x40, 0x43);  // unmap MPSC handlers to prevent CPU crashes ("INTERRUPTS OFF")
2768 	}
2769 
2770 	// Install 8088 read / write handler once loopback test is over
2771 	if ( !(data & 32) && (m_diagnostic & 32) )
2772 	{
2773 			io.install_readwrite_handler(0x40, 0x43, read8sm_delegate(*m_mpsc, FUNC(upd7201_device::cd_ba_r)), write8sm_delegate(*m_mpsc, FUNC(upd7201_device::cd_ba_w)));
2774 			logerror("\n **** COMM HANDLER INSTALLED **** ");
2775 			//popmessage("Autoboot from drive %c", m_p_nvram[0xab] ? (64 + m_p_nvram[0xab]) : 0x3F );
2776 	}
2777 
2778 	// BIT 6: Transfer data from volatile memory to NVM  (PROGRAM: 1 => 0   BIT 6)
2779 	if (!(data & 0x40) && (m_diagnostic & 0x40))
2780 		memcpy(m_p_nvram, m_p_vol_ram, 256);
2781 
2782 	// BIT 7: Transfer data from NVM to volatile memory (RECALL 0 => 1     BIT 7)
2783 	if ((data & 0x80) && !(m_diagnostic & 0x80))
2784 		memcpy(m_p_vol_ram, m_p_nvram, 256);
2785 
2786 	m_diagnostic = data;
2787 }
2788 
2789 // KEYBOARD
update_kbd_irq()2790 void rainbow_base_state::update_kbd_irq()
2791 {
2792 	if ((m_kbd_rx_ready) || (m_kbd_tx_ready))
2793 		raise_8088_irq(IRQ_8088_KBD);
2794 	else
2795 		lower_8088_irq(IRQ_8088_KBD);
2796 }
2797 
WRITE_LINE_MEMBER(rainbow_base_state::kbd_tx)2798 WRITE_LINE_MEMBER(rainbow_base_state::kbd_tx)
2799 {
2800 	m_lk201->rx_w(state);
2801 }
2802 
WRITE_LINE_MEMBER(rainbow_base_state::kbd_rxready_w)2803 WRITE_LINE_MEMBER(rainbow_base_state::kbd_rxready_w)
2804 {
2805 	m_kbd_rx_ready = (state == 1) ? true : false;
2806 	update_kbd_irq();
2807 }
2808 
WRITE_LINE_MEMBER(rainbow_base_state::kbd_txready_w)2809 WRITE_LINE_MEMBER(rainbow_base_state::kbd_txready_w)
2810 {
2811 	m_kbd_tx_ready = (state == 1) ? true : false;
2812 	update_kbd_irq();
2813 }
2814 
TIMER_DEVICE_CALLBACK_MEMBER(rainbow_base_state::hd_motor_tick)2815 TIMER_DEVICE_CALLBACK_MEMBER(rainbow_base_state::hd_motor_tick)
2816 {
2817 	if (m_power_good)
2818 		m_crtc->MHFU(MHFU_COUNT); // // Increment IF ENABLED and POWER_GOOD, return count
2819 
2820 	m_hdc_index_latch = true; // HDC drive index signal (not working ?)
2821 }
2822 
WRITE_LINE_MEMBER(rainbow_modela_state::irq_hi_w)2823 WRITE_LINE_MEMBER(rainbow_modela_state::irq_hi_w)
2824 {
2825 	m_irq_high = 0;
2826 }
2827 
2828 // on 100-B, DTR from the keyboard 8051 controls bit 7 of IRQ vectors
WRITE_LINE_MEMBER(rainbow_modelb_state::irq_hi_w)2829 WRITE_LINE_MEMBER(rainbow_modelb_state::irq_hi_w)
2830 {
2831 	m_irq_high = (state == ASSERT_LINE) ? 0x80 : 0;
2832 }
2833 
2834 
2835 // ********************************* NEC UPD7220 ***********************************************
2836 // Readback mode: correct place?  Not for vector mode (really)...?
2837 
2838 // NOTE: "More than one plane at a time can be enabled for a write operation; however,
2839 //        only one plane can be enabled for a read operation at anyone time."
2840 
vram_r(offs_t offset)2841 uint16_t rainbow_base_state::vram_r(offs_t offset)
2842 {
2843 	if ((!(m_gdc_mode_register & GDC_MODE_VECTOR)) || machine().side_effects_disabled())  // (NOT VECTOR MODE)
2844 	{
2845 		// SCROLL_MAP IN BITMAP MODE ONLY...?
2846 		if (m_gdc_mode_register & GDC_MODE_HIGHRES)
2847 			offset = (m_gdc_scroll_buffer[(offset & 0x3FC0) >> 6] << 6) | (offset & 0x3F);
2848 		else
2849 			offset = (m_gdc_scroll_buffer[(offset & 0x1FC0) >> 6] << 6) | (offset & 0x3F);
2850 
2851 		int readback_plane = 0;
2852 
2853 		if (!(m_gdc_mode_register & GDC_MODE_ENABLE_WRITES)) // 0x10           // READBACK OPERATION - if ENABLE_WRITES NOT SET
2854 		   readback_plane = (m_gdc_mode_register & GDC_MODE_READBACK_PLANE_MASK) >> 2; // READBACK PLANE 00..02, mask in bits 2+3
2855 
2856 		return m_video_ram[ (offset & 0x7fff)  + (0x8000 * readback_plane)];
2857 	}
2858 	return 0xffff;
2859 }
2860 
2861 // NOTE: Rainbow has separate registers for fore and background.
vram_w(offs_t offset,uint16_t data)2862 void rainbow_base_state::vram_w(offs_t offset, uint16_t data)
2863 {
2864 	if (m_gdc_mode_register & GDC_MODE_HIGHRES)
2865 		offset = (m_gdc_scroll_buffer[(offset & 0x3FC0) >> 6] << 6) | (offset & 0x3F);
2866 	else
2867 		offset = (m_gdc_scroll_buffer[(offset & 0x1FC0) >> 6] << 6) | (offset & 0x3F);
2868 
2869 	offset &= 0xffff; // same as in VT240?
2870 	uint16_t chr = data; // VT240 : uint8_t
2871 
2872 	if (m_gdc_mode_register & GDC_MODE_VECTOR) // VT240 : if(SELECT_VECTOR_PATTERN_REGISTER)
2873 	{
2874 		chr = bitswap<8>(m_vpat, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx);
2875 		chr |= (chr << 8);
2876 		if (m_patcnt-- == 0)
2877 		{
2878 			m_patcnt = m_patmult;
2879 			if (m_patidx-- == 0)
2880 				m_patidx = 7;
2881 		}
2882 	}
2883 	else
2884 	{
2885 		chr = m_gdc_write_buffer[ m_gdc_write_buffer_index++ ];
2886 		m_gdc_write_buffer_index &= 0xf;
2887 
2888 		chr |= (m_gdc_write_buffer[m_gdc_write_buffer_index++] << 8);
2889 		m_gdc_write_buffer_index &= 0xf;
2890 	}
2891 
2892 	if (m_gdc_mode_register & GDC_MODE_ENABLE_WRITES) // 0x10
2893 	{
2894 		// ALU_PS register: controls logic used in writing to the bitmap / inhibiting of writing to specified planes.
2895 		//     plane select and logic operations on write buffer... (and more)  **** SEE  PAGE 36 ****
2896 		int ps = m_gdc_alu_ps_register & 0x0F; // PLANE SELECT 0..3    // VT 240 : ~m_gdc_alu_ps_register & 3;
2897 		uint8_t fore = ((m_gdc_fg_bg & 0xf0)) >> 4;
2898 		uint8_t back =  (m_gdc_fg_bg & 0x0f);      // background : 0..3 confirmed, see p.39 AA-AE36A (PDF)
2899 
2900 		for (int i = 0; i <= 3; i++)
2901 		{
2902 			if (BIT(ps, i)) // 1 means don't touch (bits already inverted)
2903 			{
2904 				uint16_t mem = m_video_ram[(offset & 0xffff) + (0x8000 * i)];
2905 
2906 				uint16_t out = 0; // VT240 : uint8_t
2907 				for (int j = 0; j <= 15; j++)  // REPLACE MODE : one replaced by FG, zero by BG ( 16 instead of 8 bit on VT240 )
2908 					out |= BIT(chr, j) ? ((fore & 1) << j) : ((back & 1) << j);
2909 
2910 				switch ((m_gdc_alu_ps_register) & ALU_PS_MODE_MASK)
2911 				{
2912 				case OVERLAY_MODE: // (OR)
2913 					out |= mem;
2914 					break;
2915 
2916 				case COMPLEMENT_MODE: // (XOR)
2917 					out ^= ~mem;
2918 					break;
2919 
2920 				default: // ALL ELSE
2921 					break;
2922 				}
2923 
2924 				if (!(m_gdc_mode_register & GDC_MODE_VECTOR)) // 0 : Text Mode and Write Mask Batch
2925 					out = (out & ~m_gdc_write_mask) | (mem & m_gdc_write_mask);
2926 				else
2927 					out = (out & ~data) | (mem & data);
2928 
2929 				if (m_gdc_mode_register & GDC_MODE_ENABLE_WRITES) // 0x10
2930 					m_video_ram[(offset & 0xffff) + (0x8000 * i)] = out;
2931 		   } // if plane selected
2932 
2933 			fore >>= 1;
2934 			back >>= 1;
2935 
2936 		} // plane select (LOOP)
2937 		return;
2938 	} // if enable_writes
2939 }
2940 
2941 // (READ)
2942 // Read  scroll buffer (see GDC Diagnostic Disk, SCROLL BUFFER test)
GDC_EXTRA_REGISTER_r(offs_t offset)2943 uint8_t rainbow_base_state::GDC_EXTRA_REGISTER_r(offs_t offset)
2944 {
2945 	uint8_t data = 0;
2946 	switch (offset)
2947 	{
2948 	case 0:
2949 		data = m_gdc_mode_register; // ?
2950 		break;
2951 
2952 	case 1:
2953 		if (m_gdc_indirect_register & GDC_SELECT_SCROLL_MAP ) // 0x80
2954 		{
2955 			// Documentation says it is always incremented (read and write):
2956 			data = m_gdc_scroll_buffer[m_gdc_scroll_index++]; // // * READ * SCROLL_MAP ( 256 x 8 )
2957 			m_gdc_scroll_index &= 0xFF; // 0...255  (CPU accesses 256 bytes)
2958 			break;
2959 		}
2960 		else
2961 			logerror("\n * UNEXPECTED CASE: READ REGISTER 50..55 with INDIRECT_REGISTER $%02x and OFFSET $%02x *", m_gdc_indirect_register, offset);
2962 		break;
2963 
2964 	case 6:
2965 	case 7:
2966 		data = m_hgdc->read(offset & 0x01);
2967 		break;
2968 
2969 	default:
2970 		logerror("\n * UNHANDLED CASE: READ REGISTER 50..55 with INDIRECT_REGISTER $%02x and OFFSET $%02x *", m_gdc_indirect_register, offset);
2971 		break;
2972 	} // switch
2973 	return data;
2974 }
2975 
GDC_EXTRA_REGISTER_w(offs_t offset,uint8_t data)2976 void rainbow_base_state::GDC_EXTRA_REGISTER_w(offs_t offset, uint8_t data)
2977 {
2978 	static int last_message, last_mode, last_readback, last_scroll_index;
2979 
2980 	if (offset > 0) // Port $50 reset done @ boot ROM 1EB4/8 regardless if option present.
2981 	{
2982 		if (m_inp7->read() != 1)
2983 		{
2984 			if (last_message != 1)
2985 			{
2986 				popmessage("\nCOLOR GRAPHICS ADAPTER INVOKED.  PLEASE TURN ON THE APPROPRIATE DIP SWITCH, THEN REBOOT.\n");
2987 				logerror("OFFSET: %x (PC=%x)\n", 0x50 +offset , m_i8088->pc());
2988 				last_message = 1;
2989 			}
2990 			return;
2991 		}
2992 	}
2993 
2994 	switch (offset)
2995 	{
2996 	case 0: // Mode register must be reloaded following any write to port 50 (software reset).
2997 		// FIXME: "Any write to this port also resynchronizes the
2998 		//        read/modify/write memory cycles of the Graphics Option to those of the GDC." (?)
2999 
3000 		if (data & 1) // PDF QV069 suggests 1 -> 0 -> 1. Most programs just set bit 0 (PACMAN).
3001 		{
3002 			// Graphics option software reset (separate from GDC reset...)
3003 			OPTION_GRFX_RESET
3004 			OPTION_RESET_PATTERNS
3005 		}
3006 		break;
3007 
3008 	case 1: //  51h = DATA loaded into (a register previously addressed by a write to 53h)
3009 		if (m_gdc_indirect_register & GDC_SELECT_WRITE_BUFFER) // 0x01
3010 		{
3011 			m_gdc_write_buffer_index = 0;                   // (writing to 51h  CLEARS  the index counter)
3012 			break;
3013 		}
3014 
3015 		if (m_gdc_indirect_register & GDC_SELECT_COLOR_MAP) // 0x20
3016 		{
3017 			m_gdc_color_map[m_gdc_color_map_index++] = ~data; // tilde data verified by DIAGNOSTIC!
3018 			if (m_gdc_color_map_index == 32)
3019 			{
3020 				m_gdc_color_map_index = 0; // 0...31  (CPU accesses 32 bytes
3021 
3022 				logerror("* COLOR MAP FULLY LOADED *\n");
3023 				for (int zi = 0; zi < 16; zi++)
3024 				{
3025 					int g =  m_gdc_color_map[zi] & 0x0F;
3026 					int r = (m_gdc_color_map[zi] & 0xF0) >> 4;
3027 
3028 					int b =  m_gdc_color_map[zi + 16] & 0x0F;
3029 					int m =  (m_gdc_color_map[zi + 16] & 0xF0) >> 4;
3030 					logerror("[%d] %1x %1x %1x  %1x (1:1)\n", zi, r, g, b, m);
3031 				}
3032 				logerror("------------------------------\n");
3033 			} // if all colors present
3034 			break;
3035 		}
3036 
3037 		if (m_gdc_indirect_register & GDC_SELECT_SCROLL_MAP) // 0x80
3038 		{
3039 			if (!(m_gdc_mode_register & GDC_MODE_READONLY_SCROLL_MAP)) // ? READONLY / WRITE logic  correct...?
3040 			{
3041 				m_gdc_scroll_buffer[m_gdc_scroll_index] = data; // // WRITE TO SCROLL_MAP ( 256 x 8 )
3042 
3043 				if (m_gdc_scroll_index == 255)
3044 					logerror("---- SCROLL MAP FULLY LOADED ---*\n");
3045 				m_gdc_scroll_index++;
3046 				m_gdc_scroll_index &= 0xFF; // 0...255  (CPU accesses 256 bytes)
3047 			}
3048 			break;
3049 		}
3050 
3051 		// -----------------PATTERN + MULTIPLIER USED IN VECTOR MODE ONLY!
3052 		// SEE PAGE 37 OF AA-AE36A (PDF).
3053 		if (m_gdc_indirect_register & GDC_SELECT_PATTERN_MULTIPLIER) // 0x02
3054 		{
3055 			// On a Rainbow, 12 indicates a multiplier of 16-12 = 4 (example)
3056 			m_patmult = 16 - (data & 15); // 4 bit register  // VT240: "patmult_w"
3057 			break;
3058 		}
3059 
3060 		if (m_gdc_indirect_register & GDC_SELECT_PATTERN) // 0x04
3061 		{
3062 			// NOTE : Pattern Multiplier MUST BE LOADED before (!)
3063 			m_vpat = data;
3064 			break;
3065 		}
3066 
3067 		if (m_gdc_indirect_register & GDC_SELECT_FG_BG) // 0x08
3068 		{
3069 			m_gdc_fg_bg = data;  // Neither bitswap nor negated (and also not both)...
3070 			break; //  Next: prepare FG / BG (4 bits each) + plane  in  ALU - PLANE_SELECT register.
3071 		}
3072 
3073 		if (m_gdc_indirect_register & GDC_SELECT_ALU_PS) // 0x10
3074 		{
3075 			m_gdc_alu_ps_register = ~data;  // Negated...
3076 			break;
3077 		}
3078 
3079 		if (m_gdc_indirect_register & GDC_SELECT_MODE_REGISTER) // 0x40
3080 		{
3081 			m_gdc_mode_register =  data; // Neither bitswap nor negated (and also not both)...
3082 
3083 			if (data & GDC_MODE_HIGHRES) // 0x01
3084 			{
3085 				if (last_message != 2)
3086 				{
3087 					last_message = 2;
3088 					logerror("* HIGH RESOLUTION *\n");
3089 				}
3090 			}
3091 			else
3092 			{
3093 				if (last_message != 3)
3094 				{
3095 					last_message = 3;
3096 					logerror("MEDIUM RESOLUTION\n");
3097 				}
3098 			}
3099 
3100 			if (last_mode != (data & GDC_MODE_VECTOR)) // 0x02
3101 			{
3102 				last_mode = data & GDC_MODE_VECTOR;
3103 				if (data & GDC_MODE_VECTOR)
3104 					logerror(" VECTOR MODE ");
3105 				else
3106 					logerror(" WORD MODE ");
3107 			}
3108 
3109 			if (last_readback != (data & GDC_MODE_ENABLE_WRITES)) // 0x10
3110 			{
3111 				last_readback = data & GDC_MODE_ENABLE_WRITES;
3112 				if (data & GDC_MODE_ENABLE_WRITES) // 0x10
3113 					logerror(" READBACK: OFF - ENABLE_WRITES ");
3114 				else    // READBACK PLANE 00..02 - mask in bits 2+3:
3115 					logerror(" READBACK MODE; plane = %02x ", m_gdc_mode_register & GDC_MODE_READBACK_PLANE_MASK); // unsure if PLANE is set... already?!
3116 			}
3117 
3118 			if (last_scroll_index != m_gdc_scroll_index)
3119 			{
3120 				last_scroll_index = m_gdc_scroll_index;
3121 				if (data & GDC_MODE_READONLY_SCROLL_MAP) // 0x20
3122 				   logerror(" SCROLL MAP READ_ONLY. Index : %02x ", m_gdc_scroll_index);
3123 				 else
3124 				   logerror(" SCROLL MAP IS WRITABLE. Index : %02x ", m_gdc_scroll_index);
3125 			}
3126 
3127 			if (!(data & GDC_MODE_ENABLE_VSYNC_IRQ)) // 0x40
3128 				lower_8088_irq(IRQ_GRF_INTR_L); // also clears the interrupt
3129 
3130 			// case 0x80 :  If this bit is a 1 red and blue outputs are enabled. If this bit is a 0 red and blue outputs are disabled (page 20 of AA-AE36A)
3131 			break;
3132 		} // GDC_SELECT_MODE_REGISTER
3133 
3134 		logerror("\n* UNIMPLEMENTED CASE. MODE = %02x / m_gdc_indirect_register = %02x\n",m_gdc_mode_register, m_gdc_indirect_register);
3135 		break;
3136 
3137 	case 2:
3138 		//  52h   Data written to this port is loaded into the Write Buffer
3139 		//        While the CPU accesses the Write Buffer as sixteen 8-bit bytes,
3140 		//        the GDC accesses the buffer as eight 16-bit words.
3141 		//        A 16-bit Write Mask gives the GDC control over individual bits of a word.
3142 		// --------------------  WRITE BUFFER USED IN WORD MODE ONLY !
3143 		// "OUTPUT WRITE BUFFER IS THE INVERSE OF THE INPUT" (quote from 4-3 of the PDF)
3144 		//  BITSWAP SEEMS NECESSARY (see digits in DOODLE)... !
3145 		m_gdc_write_buffer[m_gdc_write_buffer_index++] = ~bitswap<8>(data, 0, 1, 2, 3, 4, 5, 6, 7);
3146 		m_gdc_write_buffer_index &= 0xf; // write up to 16 bytes to port 52h.
3147 		break;
3148 
3149 	case 3: //  53h   Indirect Register; address selection for indirect addressing. See 51h.
3150 		m_gdc_indirect_register = data ^ 0xff;
3151 
3152 		// Index to WRITE_BUFFER is reset via dummy write to port 51h (not here!).
3153 
3154 		if (m_gdc_indirect_register & GDC_SELECT_COLOR_MAP) // 0x20
3155 			m_gdc_color_map_index = 0;                      // (also clears the index counter)
3156 		// NEXT: 32 BYTE COLOR MAP, LOADED TO $51
3157 
3158 		//if (m_gdc_indirect_register & GDC_SELECT_MODE_REGISTER) // 0x40
3159 		//      logerror(" *** SELECT MODE REGISTER");
3160 
3161 		if (m_gdc_indirect_register & GDC_SELECT_SCROLL_MAP) // 0x80
3162 		{
3163 			if (last_scroll_index != m_gdc_scroll_index)
3164 			{
3165 				last_scroll_index =  m_gdc_scroll_index;
3166 				logerror(" *** SCROLL INDEX COUNTER RESET, old value = %d", m_gdc_scroll_index);
3167 			}
3168 			m_gdc_scroll_index = 0;                         // (also clears the index counter)
3169 		}  // NEXT: LOAD 256 BYTE SCROLL MAP INTO $51
3170 		break;
3171 
3172 	// --------- WRITE MASK (2 x 8 = 16 bits) USED IN WORD MODE ONLY !
3173 	// There is no specific order for the WRITE_MASK (according to txt/code samples in DEC's PDF).
3174 	// NOTE: LOW <-> HI JUXTAPOSITION!
3175 	case 4: // 54h   Write Mask LOW
3176 		m_gdc_write_mask = ( bitswap<8>(data, 0, 1, 2, 3, 4, 5, 6, 7) << 8 )  | ( m_gdc_write_mask & 0x00FF );
3177 		break;
3178 	case 5: // 55h   Write Mask HIGH
3179 		m_gdc_write_mask = ( m_gdc_write_mask & 0xFF00 ) | bitswap<8>(data, 0, 1, 2, 3, 4, 5, 6, 7);
3180 		break;
3181 
3182 	case 6:
3183 	case 7:
3184 		m_hgdc->write(offset & 0x01, data);
3185 		break;
3186 	} // switch
3187 
3188 }
3189 
3190 
3191 /* F4 Character Displayer */
3192 static const gfx_layout rainbow_charlayout =
3193 {
3194 	8, 10,          /* 8 x 16 characters */
3195 	256,            /* 256 characters */
3196 	1,              /* 1 bits per pixel */
3197 	{ 0 },          /* no bitplanes */
3198 			/* x offsets */
3199 	{ 0, 1, 2, 3, 4, 5, 6, 7 },
3200 	/* y offsets */
3201 	{ 15 * 8, 0 * 8, 1 * 8, 2 * 8, 3 * 8, 4 * 8, 5 * 8, 6 * 8, 7 * 8, 8 * 8 },
3202 	8 * 16      /* every char takes 16 bytes */
3203 };
3204 
3205 static GFXDECODE_START(gfx_rainbow)
3206 	GFXDECODE_ENTRY("chargen", 0x0000, rainbow_charlayout, 0, 1)
3207 GFXDECODE_END
3208 
3209 // Allocate 512 K (4 x 64 K x 16 bit) of memory (GDC):
upd7220_map(address_map & map)3210 void rainbow_base_state::upd7220_map(address_map &map)
3211 {
3212 	map(0x00000, 0x3ffff).rw(FUNC(rainbow_base_state::vram_r), FUNC(rainbow_base_state::vram_w)).share("vram");
3213 }
3214 
rainbow_base(machine_config & config)3215 void rainbow_base_state::rainbow_base(machine_config &config)
3216 {
3217 	config.set_default_layout(layout_rainbow);
3218 
3219 	/* basic machine hardware */
3220 	I8088(config, m_i8088, 24.0734_MHz_XTAL / 5); // approximately 4.815 MHz
3221 	m_i8088->set_irq_acknowledge_callback(FUNC(rainbow_base_state::irq_callback));
3222 
3223 	Z80(config, m_z80, 24.0734_MHz_XTAL / 6);
3224 	m_z80->set_addrmap(AS_PROGRAM, &rainbow_base_state::rainbowz80_mem);
3225 	m_z80->set_addrmap(AS_IO, &rainbow_base_state::rainbowz80_io);
3226 
3227 	/* video hardware */
3228 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
3229 	screen.set_raw(24.0734_MHz_XTAL / 6, 442, 0, 400, 264, 0, 240); // ~NTSC compatible video timing (?)
3230 	screen.set_screen_update(FUNC(rainbow_base_state::screen_update_rainbow));
3231 	screen.set_palette("vt100_video:palette");
3232 	GFXDECODE(config, "gfxdecode", "vt100_video:palette", gfx_rainbow);
3233 
3234 	RAINBOW_VIDEO(config, m_crtc, 24.0734_MHz_XTAL);
3235 	m_crtc->set_screen("screen");
3236 	m_crtc->set_chargen("chargen");
3237 	m_crtc->ram_rd_callback().set(FUNC(rainbow_base_state::read_video_ram_r));
3238 	m_crtc->vert_freq_intr_wr_callback().set(FUNC(rainbow_base_state::video_interrupt));
3239 
3240 	// *************************** COLOR GRAPHICS (OPTION) **************************************
3241 	// While the OSC frequency is confirmed, the divider is not (refresh rate is ~60 Hz with 32).
3242 	UPD7220(config, m_hgdc, 31188000 / 32); // Duell schematics shows a 31.188 Mhz oscillator (confirmed by RFKA).
3243 	m_hgdc->vsync_wr_callback().set(FUNC(rainbow_base_state::GDC_vblank_irq)); // "The vsync callback line needs to be below the 7220 DEVICE_ADD line."
3244 
3245 	m_hgdc->set_addrmap(0, &rainbow_base_state::upd7220_map);
3246 	m_hgdc->set_display_pixels(FUNC(rainbow_base_state::hgdc_display_pixels));
3247 	m_hgdc->set_screen(m_screen2); // set_screen needs to be added after 7720 device in the machine config, not after the screen.
3248 
3249 	PALETTE(config, m_palette2).set_entries(32);
3250 
3251 	SCREEN(config, m_screen2, SCREEN_TYPE_RASTER);
3252 	m_screen2->set_video_attributes(VIDEO_UPDATE_AFTER_VBLANK | VIDEO_ALWAYS_UPDATE);
3253 
3254 	// VR241 color monitor is specified for 20 MHz bandwidth ( 60 Hz / 15.72 kHz horizontal rate )
3255 	// - sufficient for 800 x 240 non-interlaced at 60 Hz (non interlaced).
3256 	//m_screen2->set_raw(31188000 / 2 , 992, 0, 800, 262, 0, 240);
3257 
3258 	// Alternate configuration:
3259 	m_screen2->set_raw(31188000 / 4 , 496, 0, 400, 262, 0, 240);
3260 
3261 	m_screen2->set_screen_update("upd7220", FUNC(upd7220_device::screen_update));
3262 
3263 	FD1793(config, m_fdc, 24.0734_MHz_XTAL / 24); // no separate 1 Mhz quartz
3264 	FLOPPY_CONNECTOR(config, FD1793_TAG ":0", rainbow_floppies, "525qd", rainbow_base_state::floppy_formats);
3265 	FLOPPY_CONNECTOR(config, FD1793_TAG ":1", rainbow_floppies, "525qd", rainbow_base_state::floppy_formats);
3266 	FLOPPY_CONNECTOR(config, FD1793_TAG ":2", rainbow_floppies, "525qd", rainbow_base_state::floppy_formats);
3267 	FLOPPY_CONNECTOR(config, FD1793_TAG ":3", rainbow_floppies, "525qd", rainbow_base_state::floppy_formats);
3268 	//FLOPPY_CONNECTOR(config, FD1793_TAG ":2", rainbow_floppies, "525dd", rainbow_base_state::floppy_formats);
3269 	//FLOPPY_CONNECTOR(config, FD1793_TAG ":3", rainbow_floppies, "35dd", rainbow_base_state::floppy_formats);
3270 	SOFTWARE_LIST(config, "flop_list").set_original("rainbow");
3271 
3272 	/// ********************************* HARD DISK CONTROLLER *****************************************
3273 	WD2010(config, m_hdc, 5000000); // 10 Mhz quartz on controller (divided by 2 for WCLK)
3274 	m_hdc->out_intrq_callback().set(FUNC(rainbow_base_state::bundle_irq)); // FIRST IRQ SOURCE (OR'ed with DRQ)
3275 	m_hdc->out_bdrq_callback().set(FUNC(rainbow_base_state::hdc_bdrq));  // BUFFER DATA REQUEST
3276 
3277 	// SIGNALS -FROM- WD CONTROLLER:
3278 	m_hdc->out_bcs_callback().set(FUNC(rainbow_base_state::hdc_read_sector)); // Problem: OUT_BCS_CB = WRITE8 ... (!)
3279 	m_hdc->out_bcr_callback().set(FUNC(rainbow_base_state::hdc_bcr));         // BUFFER COUNTER RESET (pulses)
3280 
3281 	m_hdc->out_wg_callback().set(FUNC(rainbow_base_state::hdc_write_sector));   // WRITE GATE
3282 	m_hdc->out_step_callback().set(FUNC(rainbow_base_state::hdc_step));         // STEP PULSE
3283 	m_hdc->out_dirin_callback().set(FUNC(rainbow_base_state::hdc_direction));
3284 
3285 	// WF + DRDY are actually wired to a routine here:
3286 	m_hdc->in_wf_callback().set(FUNC(rainbow_base_state::hdc_write_fault));   // WRITE FAULT (fatal until next reset)
3287 	m_hdc->in_drdy_callback().set(FUNC(rainbow_base_state::hdc_drive_ready)); // DRIVE_READY (VCC = ready)
3288 
3289 	// Always set seek complete and track 00 signal (not super clean, but does not affect operation):
3290 	m_hdc->in_sc_callback().set_constant(1);                             // SEEK COMPLETE (VCC = complete)
3291 	m_hdc->in_tk000_callback().set_constant(1);                  // TRACK 00 signal (= from drive)
3292 
3293 	HARDDISK(config, "decharddisk1");
3294 	/// ******************************** / HARD DISK CONTROLLER ****************************************
3295 
3296 	CORVUS_HDC(config, m_corvus_hdc, 0);
3297 	HARDDISK(config, "harddisk1", "corvus_hdd");
3298 	HARDDISK(config, "harddisk2", "corvus_hdd");
3299 	HARDDISK(config, "harddisk3", "corvus_hdd");
3300 	HARDDISK(config, "harddisk4", "corvus_hdd");
3301 
3302 	DS1315(config, m_rtc, 0); // DS1315 (ClikClok for DEC-100 B)   * OPTIONAL *
3303 
3304 	COM8116_003(config, m_dbrg, 24.0734_MHz_XTAL / 4); // 6.01835 MHz (nominally 6 MHz)
3305 	m_dbrg->fr_handler().set(FUNC(rainbow_base_state::dbrg_fr_w));
3306 	m_dbrg->ft_handler().set(FUNC(rainbow_base_state::dbrg_ft_w));
3307 
3308 	UPD7201(config, m_mpsc, 24.0734_MHz_XTAL / 5 / 2); // 2.4073 MHz (nominally 2.5 MHz)
3309 	m_mpsc->out_int_callback().set(FUNC(rainbow_base_state::mpsc_irq));
3310 	m_mpsc->out_txda_callback().set(m_comm_port, FUNC(rs232_port_device::write_txd));
3311 	m_mpsc->out_txdb_callback().set("printer", FUNC(rs232_port_device::write_txd));
3312 	// RTS and DTR outputs are not connected
3313 
3314 	RS232_PORT(config, m_comm_port, default_rs232_devices, nullptr);
3315 	m_comm_port->rxd_handler().set(m_mpsc, FUNC(upd7201_device::rxa_w));
3316 	m_comm_port->cts_handler().set(m_mpsc, FUNC(upd7201_device::ctsa_w));
3317 	m_comm_port->dcd_handler().set(m_mpsc, FUNC(upd7201_device::dcda_w));
3318 
3319 	rs232_port_device &printer(RS232_PORT(config, "printer", default_rs232_devices, nullptr));
3320 	printer.rxd_handler().set(m_mpsc, FUNC(upd7201_device::rxb_w));
3321 	printer.dcd_handler().set(m_mpsc, FUNC(upd7201_device::ctsb_w)); // actually DTR
3322 
3323 	m_comm_port->option_add("microsoft_mouse", MSFT_HLE_SERIAL_MOUSE);
3324 	m_comm_port->option_add("logitech_mouse", LOGITECH_HLE_SERIAL_MOUSE);
3325 	m_comm_port->option_add("msystems_mouse", MSYSTEMS_HLE_SERIAL_MOUSE);
3326 	m_comm_port->set_default_option("logitech_mouse");
3327 
3328 	printer.set_default_option("printer");
3329 
3330 	I8251(config, m_kbd8251, 24.0734_MHz_XTAL / 5 / 2);
3331 	m_kbd8251->txd_handler().set(FUNC(rainbow_base_state::kbd_tx));
3332 	m_kbd8251->rxrdy_handler().set(FUNC(rainbow_base_state::kbd_rxready_w));
3333 	m_kbd8251->txrdy_handler().set(FUNC(rainbow_base_state::kbd_txready_w));
3334 
3335 	LK201(config, m_lk201, 0);
3336 	m_lk201->tx_handler().set(m_kbd8251, FUNC(i8251_device::write_rxd));
3337 
3338 	ripple_counter_device &prtbrg(RIPPLE_COUNTER(config, "prtbrg", 24.0734_MHz_XTAL / 6 / 13)); // 74LS393 at E17 (both halves)
3339 	// divided clock should ideally be 307.2 kHz, but is actually approximately 308.6333 kHz
3340 	prtbrg.set_stages(8);
3341 	prtbrg.count_out_cb().set(FUNC(rainbow_base_state::bitrate_counter_w));
3342 
3343 	TIMER(config, "motor").configure_periodic(FUNC(rainbow_base_state::hd_motor_tick), attotime::from_hz(60));
3344 
3345 	NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
3346 }
3347 
rainbow_modela(machine_config & config)3348 void rainbow_modela_state::rainbow_modela(machine_config &config)
3349 {
3350 	rainbow_base(config);
3351 	m_i8088->set_addrmap(AS_PROGRAM, &rainbow_modela_state::rainbow8088_map);
3352 	m_i8088->set_addrmap(AS_IO, &rainbow_modela_state::rainbow8088_io);
3353 	RAM(config, m_ram).set_default_size("64K").set_extra_options("64K,128K,192K,256K,320K,384K,448K,512K,576K,640K,704K,768K");
3354 	m_kbd8251->dtr_handler().set(FUNC(rainbow_modela_state::irq_hi_w));
3355 }
3356 
rainbow_modelb(machine_config & config)3357 void rainbow_modelb_state::rainbow_modelb(machine_config &config)
3358 {
3359 	rainbow_base(config);
3360 	m_i8088->set_addrmap(AS_PROGRAM, &rainbow_modelb_state::rainbow8088_map);
3361 	m_i8088->set_addrmap(AS_IO, &rainbow_modelb_state::rainbow8088_io);
3362 	RAM(config, m_ram).set_default_size("128K").set_extra_options("128K,192K,256K,320K,384K,448K,512K,576K,640K,704K,768K,832K,896K");
3363 	m_kbd8251->dtr_handler().set(FUNC(rainbow_modelb_state::irq_hi_w));
3364 }
3365 
3366 //----------------------------------------------------------------------------------------
3367 // 'Rainbow 100-A' (system module 70-19974-00, PSU H7842-A)
3368 // - first generation hardware (introduced May '82) with ROM 04.03.11
3369 // - inability to boot from hard disc (mind the inadequate PSU)
3370 //----------------------------------------------------------------------------------------
3371 // AVAILABLE RAM: 64 K on board (versus 128 K on model 'B').
3372 
3373 // Two compatible memory expansions were sold by DEC:
3374 // (PCIXX-AA) : 64 K (usable on either Rainbow 100-A or 100-B) *
3375 // (PCIXX-AB) : 192 K ( " )  *
3376 // Totals to 256 K on a 100-A, while the RAM limit appears to be 832 K.
3377 
3378 // * DEC changed the way signals are handled on J6 (memory connector) later:
3379 //  "Whether a PC100-A or PC100-B memory module is installed on the PC100-B system module
3380 //   affects the functions the signals on 5 pins (29, 30, 32, 43, and 47) of the J6 connector
3381 //   will perform." (from 'EK-RB100_TM_001 Addendum for PC100-A_PC100-B Dec.84' page 120).
3382 //----------------------------------------------------------------------------------------
3383 // KNOWN DIFFERENCES TO 100-B:
3384 // - cannot control bit 7 of IRQ vector (prevents DOS > 2.01 from booting on unmodified hardware)
3385 // - 4 color palette with graphics option (instead of 16 colors on later models)
3386 // - smaller ROMs (3 x 2764) with fewer routines (no documented way to beep...)
3387 // - socketed NVRAM chip: X2212D 8238AES
3388 ROM_START(rainbow100a)
3389 	ROM_REGION(0x100000, "maincpu", 0)
3390 
3391 	ROM_LOAD("23-176e4-00.e89", 0xfa000, 0x2000, CRC(405e9619) SHA1(86604dccea84b46e05d705abeda25b12f7cc8c59)) // ROM (FA000-FBFFF) (E89) 8 K
3392 	ROM_LOAD("23-177e4-00.e90", 0xfc000, 0x2000, CRC(1ec72a66) SHA1(ed19944ae711e97d6bec34c885be04c4c3c95852)) // ROM (FC000-FDFFF) (E90) 8 K
3393 	ROM_FILL(0xfa26d, 1, 0x00) // [0xFA000 + 0x026d] disable CRC check   [100-A ROM]
3394 	ROM_FILL(0xfadea, 1, 0x00) // [0xFA000 + 0x0dea] Floppy workaround: in case of Z80 RESPONSE FAILURE ($80 bit set in AL), don't block floppy access
3395 
3396 	// SOCKETED LANGUAGE ROM (E91) with 1 single localization per ROM -
3397 	ROM_LOAD("23-092e4-00.e91", 0xfe000, 0x2000, CRC(c269175a) SHA1(e82cf69b811f1e376621277f81db28e299fe06f0))  // ROM (FE000-FFFFF) (E91) 8 K - English (?)
3398 	// See also MP-01491-00 - PC100A FIELD MAINTENANCE SET. Appendix A of EK-RB100 Rainbow
3399 	// Technical Manual Addendum f.100A and 100B (Dec.84) lists 15 localizations / part numbers
3400 
3401 	ROM_REGION(0x1000, "chargen", 0) // [E98] 2732 (4 K) EPROM
3402 	ROM_LOAD("23-020e3-00.e98", 0x0000, 0x1000, CRC(b5ee2824) SHA1(8e940e32f39ec5c51cae0351ddd59ab06416d5c6))
3403 
3404 	// Z80 ARBITRATION PROM
3405 	ROM_REGION(0x100, "prom", 0)
3406 	ROM_LOAD("23-090b1.mmi6308-ij.e11", 0x0000, 0x0100, CRC(cac3a7e3) SHA1(2d0468cda36fa287f705364c56dbf62f548d2e4c) ) // MMI 6308-IJ; Silkscreen stamp: "LM8413 // 090B1"; 256x8 Open Collector prom @E11, same prom is @E13 on 100-B
3407 ROM_END
3408 
3409 
3410 //----------------------------------------------------------------------------------------
3411 // ROM definition for 100-B (system module 70-19974-02, PSU H7842-D)
3412 // Built until ~ May 1986 (from MP-01491-00)
3413 // - 32 K ROM (version 5.03)
3414 // - 128 K base and 896 K max. mem.
3415 ROM_START(rainbow)
3416 	ROM_REGION(0x100000, "maincpu", 0)
3417 
3418 	// Note that the 'Field Maintenance Print Set 1984' also lists alternate revision 'A1' with
3419 	//              23-063e3-00 (for chargen) and '23-074e5-00' / '23-073e5-00' for E5-01 / E5-02.
3420 
3421 	// Part numbers 22E5, 20E5 and 37E3 verified to match revision "B" (FCC ID : A0994Q - PC100 - B).
3422 
3423 	// BOOT ROM
3424 	ROM_LOAD("23-022e5-00.bin", 0xf0000, 0x4000, CRC(9d1332b4) SHA1(736306d2a36bd44f95a39b36ebbab211cc8fea6e))
3425 	ROM_RELOAD(0xf4000, 0x4000)
3426 	ROM_FILL(0xf4303, 1, 0x00) // [0xf4000 + 0x0303] disable CRC check   [100-B ROM]
3427 	ROM_FILL(0xf535e, 1, 0x00) // [0xf4000 + 0x135e] Floppy workaround: in case of Z80 RESPONSE FAILURE ($80 bit set in AL), don't block floppy access
3428 
3429 
3430 	// LANGUAGE ROM
3431 	ROM_LOAD("23-020e5-00.bin", 0xf8000, 0x4000, CRC(8638712f) SHA1(8269b0d95dc6efbe67d500dac3999df4838625d8)) // German, French, English
3432 	//ROM_LOAD( "23-015e5-00.bin", 0xf8000, 0x4000, NO_DUMP) // Dutch, French, English
3433 	//ROM_LOAD( "23-016e5-00.bin", 0xf8000, 0x4000, NO_DUMP) // Finish, Swedish, English
3434 	//ROM_LOAD( "23-017e5-00.bin", 0xf8000, 0x4000, NO_DUMP) // Danish, Norwegian, English
3435 	//ROM_LOAD( "23-018e5-00.bin", 0xf8000, 0x4000, NO_DUMP) // Spanish, Italian, English
3436 	ROM_RELOAD(0xfc000, 0x4000)
3437 
3438 	// CHARACTER GENERATOR (E3-03)
3439 	ROM_REGION(0x1000, "chargen", 0)
3440 	ROM_LOAD("23-037e3.bin", 0x0000, 0x1000, CRC(1685e452) SHA1(bc299ff1cb74afcededf1a7beb9001188fdcf02f)) // the 'invalid character' symbol and the yen symbol were changed vs 23-020e3 from 100a
3441 
3442 	// Z80 ARBITRATION PROM
3443 	ROM_REGION(0x100, "prom", 0)
3444 	ROM_LOAD("23-090b1.mmi6308-ij.e13", 0x0000, 0x0100, CRC(cac3a7e3) SHA1(2d0468cda36fa287f705364c56dbf62f548d2e4c) ) // MMI 6308-IJ; Silkscreen stamp: "LM8413 // 090B1"; 256x8 Open Collector prom @E13, same prom is @E11 on 100-A
3445 ROM_END
3446 
3447 //----------------------------------------------------------------------------------------
3448 // 'Rainbow 190 B' (announced March 1985) is identical to 100-B, with alternate ROM v5.05.
3449 // According to an article in Wall Street Journal it came with a 10 MB HD and 640 K RAM.
3450 
3451 // All programs not dependent on specific ROM addresses should work. A first glance:
3452 // - jump tables (F4000-F40083 and FC000-FC004D) were not extended
3453 // - absolute addresses of some internal routines have changed (affects BOOT 2.x / 3.x dual boot)
3454 
3455 // A Readme from January 1985 mentions 'recent ROM changes for MASS 11' (a VAX word processor).
3456 // It is *likely* that the sole differences between 5.05 and 5.03 affect terminal emulation.
3457 
3458 ROM_START(rainbow190)
3459 	ROM_REGION(0x100000, "maincpu", 0)
3460 	ROM_LOAD("dec190rom0.bin", 0xf0000, 0x4000, CRC(fac191d2) SHA1(4aff5b1e031d3b5eafc568b23e68235270bb34de)) //FIXME: need correct rom name
3461 	ROM_RELOAD(0xf4000, 0x4000)
3462 	ROM_LOAD("dec190rom1.bin", 0xf8000, 0x4000, CRC(5ce59632) SHA1(d29793f7014c57a4e7cb77bbf6e84f9113635ed2)) //FIXME: need correct rom name
3463 
3464 	ROM_RELOAD(0xfc000, 0x4000)
3465 	ROM_REGION(0x1000, "chargen", 0)
3466 	ROM_LOAD("23-037e3.bin", 0x0000, 0x1000, CRC(1685e452) SHA1(bc299ff1cb74afcededf1a7beb9001188fdcf02f))
3467 
3468 	// Z80 ARBITRATION PROM
3469 	ROM_REGION(0x100, "prom", 0)
3470 	ROM_LOAD("23-090b1.mmi6308-ij.e13", 0x0000, 0x0100, CRC(cac3a7e3) SHA1(2d0468cda36fa287f705364c56dbf62f548d2e4c) ) // MMI 6308-IJ; Silkscreen stamp: "LM8413 // 090B1"; 256x8 Open Collector prom @E13, same prom is @E11 on 100-A
3471 ROM_END
3472 //----------------------------------------------------------------------------------------
3473 
3474 /* Driver */
3475 
3476 /*   YEAR  NAME         PARENT   COMPAT  MACHINE         INPUT           STATE                 INIT        COMPANY                          FULLNAME         FLAGS */
3477 COMP(1982, rainbow100a, rainbow, 0,      rainbow_modela, rainbow100b_in, rainbow_modela_state, empty_init, "Digital Equipment Corporation", "Rainbow 100-A", MACHINE_IS_SKELETON)
3478 COMP(1983, rainbow,     0,       0,      rainbow_modelb, rainbow100b_in, rainbow_modelb_state, empty_init, "Digital Equipment Corporation", "Rainbow 100-B", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_COLORS)
3479 COMP(1985, rainbow190,  rainbow, 0,      rainbow_modelb, rainbow100b_in, rainbow_modelb_state, empty_init, "Digital Equipment Corporation", "Rainbow 190-B", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_COLORS)
3480