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