rainbow.c: New floppy code - uses more reliable 'wd_fdc'. [Bavarese]

i86.c: Four new 8086 opcode aliases: 0xc0 is 0xc2; 0xc1 = 0xc3; 0xc8 = 0xca; 0xc9 = 0xcb as documented at OS 2 Museum. [Bavarese]

rx50_dsk.h/c: Rainbow specific; The RX50 _disk drive_ was used in different architectures.  Floppy format used by Rainbow-100 and -190. Track layout (post-amble, some positions) yet unverified. Currently only raw 400 K disk dumps are supported (*.img).  [Bavarese]
This commit is contained in:
Scott Stone 2014-06-09 00:42:53 +00:00
parent 0f0c004ce8
commit f4d741ca06
7 changed files with 493 additions and 138 deletions

2
.gitattributes vendored
View File

@ -3679,6 +3679,8 @@ src/lib/formats/ql_dsk.c svneol=native#text/plain
src/lib/formats/ql_dsk.h svneol=native#text/plain src/lib/formats/ql_dsk.h svneol=native#text/plain
src/lib/formats/rk_cas.c svneol=native#text/plain src/lib/formats/rk_cas.c svneol=native#text/plain
src/lib/formats/rk_cas.h svneol=native#text/plain src/lib/formats/rk_cas.h svneol=native#text/plain
src/lib/formats/rx50_dsk.c svneol=native#text/plain
src/lib/formats/rx50_dsk.h svneol=native#text/plain
src/lib/formats/sc3000_bit.c svneol=native#text/plain src/lib/formats/sc3000_bit.c svneol=native#text/plain
src/lib/formats/sc3000_bit.h svneol=native#text/plain src/lib/formats/sc3000_bit.h svneol=native#text/plain
src/lib/formats/sf7000_dsk.c svneol=native#text/plain src/lib/formats/sf7000_dsk.c svneol=native#text/plain

View File

@ -1138,10 +1138,12 @@ bool i8086_common_cpu_device::common_op(UINT8 op)
break; break;
// 8086 'invalid opcodes', as documented at http://www.os2museum.com/wp/?p=2147 // 8086 'invalid opcodes', as documented at http://www.os2museum.com/wp/?p=2147
// 0x60 - 0x6f are an alias to 0x70 - 0x7f. // - 0x60 - 0x6f are an alias to 0x70 - 0x7f.
// These instructions are used in the boot sector for some versions of // - 0xc0, 0xc1, 0xc8, 0xc9 are also aliases where the CPU ignores BIT 1 (*).
// MS-DOS 2.01 (e.g. the DEC Rainbow version). //
case 0x60: // Instructions are used in the boot sector for some versions of
// MS-DOS (e.g. the DEC Rainbow-100 version of DOS 2.x)
// case 0x60:
case 0x70: // i_jo case 0x70: // i_jo
JMP( OF); JMP( OF);
break; break;
@ -1670,7 +1672,7 @@ bool i8086_common_cpu_device::common_op(UINT8 op)
CLK(MOV_RI16); CLK(MOV_RI16);
break; break;
case 0xc0: // 0xc0 is 0xc2 - see (*)
case 0xc2: // i_ret_d16 case 0xc2: // i_ret_d16
{ {
UINT32 count = fetch_word(); UINT32 count = fetch_word();
@ -1680,6 +1682,7 @@ bool i8086_common_cpu_device::common_op(UINT8 op)
} }
break; break;
case 0xc1: // 0xc1 is 0xc3 - see (*)
case 0xc3: // i_ret case 0xc3: // i_ret
m_ip = POP(); m_ip = POP();
CLK(RET_NEAR); CLK(RET_NEAR);
@ -1711,7 +1714,7 @@ bool i8086_common_cpu_device::common_op(UINT8 op)
CLKM(MOV_RI16,MOV_MI16); CLKM(MOV_RI16,MOV_MI16);
break; break;
case 0xc8: // 0xc8 = 0xca - see (*)
case 0xca: // i_retf_d16 case 0xca: // i_retf_d16
{ {
UINT32 count = fetch_word(); UINT32 count = fetch_word();
@ -1722,6 +1725,7 @@ bool i8086_common_cpu_device::common_op(UINT8 op)
} }
break; break;
case 0xc9: // 0xc9 = 0xcb - see (*)
case 0xcb: // i_retf case 0xcb: // i_retf
m_ip = POP(); m_ip = POP();
m_sregs[CS] = POP(); m_sregs[CS] = POP();

227
src/lib/formats/rx50_dsk.c Normal file
View File

@ -0,0 +1,227 @@
/**********************************************************************
formats/rx50_dsk.c
Floppies used by Rainbow 100 and 190.
The RX50 drive: 5.25" format; 300 rpm; MFM 250 kbps; 96 - 100 tpi
- single sided with two disk slots (1 drive motor served both).
DEC used the RX50 in entirely different architectures (Pro / PDP-11).
Native Rainbow 100 format:
- SSQD - 80 tracks with 10 sectors per track (512 byte sectors)
- first two tracks are reserved for loader code (DOS / CPM / custom)
- FAT and root directory began immediately on track 2.
- 2:1 sector interleave pattern - except in tracks 0 and 1.
NOTE: PUTR tends to interleave loader tracks 0 + 1. Not recommended!
Jeff's RBIMG is first choice for preservation, TeleDisk is second.
Always check the track layout. Both have problems with weak disks.
A container to handle copy protected RX 50 disks is needed. Some info
can be derived from Mark Hittinger's RBACKUP (CP/M source from Nov-94).
TODO: improve code to accept 40 T / single sided / 9 or 8 sector disks:
a) disks from VT180 (9 sectors; READ ONLY - enforced by BIOS)
b) 8 sector 160k MS-DOS disks (READ + WRITE support on DEC)
FORMAT A: /F:160 on DOS; turn MEDIACHK ON
************************************************************************/
#include "emu.h"
#include "flopimg.h"
#include "formats/rx50_dsk.h"
// Controller: WD1793
// TRACK LAYOUT IS UNVERIFED. SEE SOURCES:
// - 'esq_dsk16' (uses WD 1772)
// - SDC-RX50 Floppy Controller Manual
// - 'PC 100 SYSTEM SPEC' 4.3 - page 42. (*)
const floppy_image_format_t::desc_e rx50img_format::rx50_10_desc[] = {
{ MFM, 0x4e, 80 }, // (*) GAP (1)
{ MFM, 0x00, 12 }, // Value from (*). (?? = unverified)
{ RAW, 0x5224, 3 },
{ MFM, 0xfc, 1 },
{ MFM, 0x4e, 50 },
{ MFM, 0x00, 12 },
{ SECTOR_LOOP_START, 0, 9 }, // 0 ... f.sector_count-1
{ CRC_CCITT_START, 1 },
{ RAW, 0x4489, 3 },
{ MFM, 0xfe, 1 },
{ TRACK_ID },
{ HEAD_ID },
{ SECTOR_ID },
{ SIZE_ID },
{ CRC_END, 1 },
{ CRC, 1 },
{ MFM, 0x4e, 22 }, // (*) POST-ID GAP (2)
{ MFM, 0x00, 12 }, // (*)
{ CRC_CCITT_START, 2 },
{ RAW, 0x4489, 3 },
{ MFM, 0xfb, 1 },
{ SECTOR_DATA, -1 },
{ CRC_END, 2 },
{ CRC, 2 },
{ MFM, 0x4e, 48 }, // GAP (3) - taken from RBACKUP source.
{ MFM, 0x00, 12 },
{ SECTOR_LOOP_END },
{ MFM, 0x4e, 1 }, // UNVERIFIED - ('esq_16' has 170 x $4e)
{ END }
};
rx50img_format::rx50img_format()
{
}
const char *rx50img_format::name() const
{
return "img";
}
const char *rx50img_format::description() const
{
return "DEC Rainbow 100 floppy image";
}
const char *rx50img_format::extensions() const
{
return "img";
}
bool rx50img_format::supports_save() const
{
return true;
}
void rx50img_format::find_size(io_generic *io, UINT8 &track_count, UINT8 &head_count, UINT8 &sector_count)
{
head_count = 1;
UINT32 expected_size = 0;
UINT64 size = io_generic_size(io);
track_count = 80;
sector_count = 10;
expected_size = 512 * track_count * head_count * sector_count;
if (size == expected_size) // standard format has 409600 byte
return;
/*
track_count = 40;
sector_count = 9; // [VT 180]
expected_size = 512 * track_count * head_count * sector_count;
if (size == expected_size)
return;
track_count = 40;
sector_count = 8; // [DOS]
expected_size = 512 * track_count * head_count * sector_count;
if (size == expected_size)
return;
*/
track_count = head_count = sector_count = 0;
}
int rx50img_format::identify(io_generic *io, UINT32 form_factor)
{
UINT8 track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
if(track_count)
return 50;
return 0;
}
// /* Sectors are numbered 1 to 10 */
bool rx50img_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
UINT8 track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
if(track_count == 0)
return false;
UINT8 sectdata[10*512];
desc_s sectors[10];
for(int i=0; i<sector_count; i++) {
sectors[i].data = sectdata + 512*i;
sectors[i].size = 512;
sectors[i].sector_id = i + 1; // SECTOR_ID +1 <===
}
int track_size = sector_count*512;
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
io_generic_read(io, sectdata, (track*head_count + head)*track_size, track_size);
generate_track(rx50_10_desc, track, head, sectors, sector_count, 102064, image); // 98480
}
}
image->set_variant(floppy_image::SSQD);
return true;
}
bool rx50img_format::save(io_generic *io, floppy_image *image)
{
int track_count, head_count, sector_count;
get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count);
if(track_count != 80)
track_count = 80;
// Happens for a fully unformatted floppy
if(!head_count)
head_count = 1;
if(sector_count == 9) // [VT180] 9 sector format : no save!
return false;
if(sector_count != 10) // either 8 or 10 sectors
sector_count = 10; // [STANDARD]
/*
if(sector_count != 10) // either 8 or 10 sectors
{
if(sector_count == 8)
{
track_count = 40; // [DOS]
} else
{
sector_count = 10; // [STANDARD]
}
}
*/
UINT8 sectdata[11*512];
int track_size = sector_count*512;
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
io_generic_write(io, sectdata, (track*head_count + head)*track_size, track_size);
}
}
return true;
}
const floppy_format_type FLOPPY_RX50IMG_FORMAT = &floppy_image_format_creator<rx50img_format>;
/*
// Native 400K format (80 T * 10 S * 512 bytes) on 'quad density' RX50 drives
// ( 5.25" single sided; 300 rpm; MFM 250 kbps; 96 - 100 tpi ).
//
// The BIOS can also * read * VT-180 disks and access MS-DOS 160 k disks (R + W)
// ( 40 tracks; single sided with 9 or 8 sectors per track )
static LEGACY_FLOPPY_OPTIONS_START( dec100_floppy )
LEGACY_FLOPPY_OPTION( dec100_floppy, "td0", "Teledisk floppy disk image", td0_dsk_identify, td0_dsk_construct, td0_dsk_destruct, NULL )
LEGACY_FLOPPY_OPTION( dec100_floppy, "img", "DEC Rainbow 100", basicdsk_identify_default, basicdsk_construct_default, NULL,
HEADS([1])
TRACKS(40/[80])
SECTORS(8/9/[10])
SECTOR_LENGTH([512])
INTERLEAVE([0])
FIRST_SECTOR_ID([1])
)
LEGACY_FLOPPY_OPTIONS_END
*/

View File

@ -0,0 +1,40 @@
/*********************************************************************
formats/rx50_dsk.h
Format for DEC RX50 floppy drive used e.g. by Rainbow 100 and 190
Disk is PC MFM, 80 tracks, single sided, with 10 sectors per track
based on lib/formats/esq16_dsk.h
*********************************************************************/
#ifndef RX50_DSK_H_
#define RX50_DSK_H_
#include "flopimg.h"
class rx50img_format : public floppy_image_format_t
{
public:
rx50img_format();
virtual int identify(io_generic *io, UINT32 form_factor);
virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
virtual bool save(io_generic *io, floppy_image *image);
virtual const char *name() const;
virtual const char *description() const;
virtual const char *extensions() const;
virtual bool supports_save() const;
static const desc_e rx50_10_desc[];
private:
void find_size(io_generic *io, UINT8 &track_count, UINT8 &head_count, UINT8 &sector_count);
};
extern const floppy_format_type FLOPPY_RX50IMG_FORMAT;
#endif /* RX50_DSK_H_ */

View File

@ -185,6 +185,7 @@ FORMATSOBJS = \
$(LIBOBJ)/formats/pyldin_dsk.o \ $(LIBOBJ)/formats/pyldin_dsk.o \
$(LIBOBJ)/formats/ql_dsk.o \ $(LIBOBJ)/formats/ql_dsk.o \
$(LIBOBJ)/formats/rk_cas.o \ $(LIBOBJ)/formats/rk_cas.o \
$(LIBOBJ)/formats/rx50_dsk.o \
$(LIBOBJ)/formats/sc3000_bit.o \ $(LIBOBJ)/formats/sc3000_bit.o \
$(LIBOBJ)/formats/sf7000_dsk.o \ $(LIBOBJ)/formats/sf7000_dsk.o \
$(LIBOBJ)/formats/smx_dsk.o \ $(LIBOBJ)/formats/smx_dsk.o \

View File

@ -4,35 +4,30 @@
Driver-in-progress by R. Belmont and Miodrag Milanovic. Driver-in-progress by R. Belmont and Miodrag Milanovic.
Portions (2013-2014) by Karl-Ludwig Deisenhofer (VT attributes, preliminary floppy, keyboard, DIP switches). Portions (2013-2014) by Karl-Ludwig Deisenhofer (VT attributes, preliminary floppy, keyboard, DIP switches).
STATE AS OF APRIL 2014 STATE AS OF JUNE 2014
---------------------- ---------------------
Driver is based entirely on the DEC-100 'B' variant (DEC-190 and DEC-100 A models are treated as clones). Driver is based entirely on the DEC-100 'B' variant (DEC-190 and DEC-100 A models are treated as clones).
While this is OK for the compatible -190, it doesn't do justice to ancient '100 A' hardware. While this is OK for the compatible -190, it doesn't do justice to ancient '100 A' hardware.
Currently, there are 2 showstoppers: Currently, there are several issues here:
(1) IRQ logic for 100-B needs further work (text in RBCONVERT.ZIP has details concerning -A versus -B) (1) Keyboard emulation incomplete (inhibits the system from booting with ERROR 50).
(2) Keyboard emulation incomplete (inhibits the system from booting with ERROR 50). (2) after fixing (1), IRQ logic for 100-B should be verified (text in RBCONVERT.ZIP has details concerning -A versus -B.
DMA (needed for 'Extended communication option') or Z80-8088 arbitration is non-existent (E11/E13 dumps anyone?).
- FLOPPY TIMING: 'wd17xx_complete_command' * must * be hard wired to about 13 usecs. (3) Read errors when booting CP/M 2.x or DOS 2.x (secondary boot; read errors beyond T >= 2).
Line 1063 in 'wd17xx.c' has to be changed (until legacy code here is removed): Seek (+ verify) and a number of signals (TRACK > 43 TG43, INDEX etc.) do not work (diag.disk aborts drive test).
- w->timer_cmd->adjust(attotime::from_usec(usecs));
+ w->timer_cmd->adjust(attotime::from_usec(13));
- NOT WORKING: serial (ERROR 60). - NOT WORKING: serial (ERROR 60).
- NOT WORKING: printer interface (ERROR 40). Like error 60 not mission-critical. - NOT WORKING: printer interface (ERROR 40). Like error 60 not mission-critical.
- NON-CRITICAL: watchdog logic ('MHFU' triggered after 108 ms without interrupts on original machine) does not work. - NON-CRITICAL: watchdog logic (MHFU - triggered after 108 ms without interrupts on original machine) does not work.
The timer is reset by TWO sources: the VERT INT L from the DC012, or the MHFU ENB L from the enable flip-flop. The timer is reset by TWO sources: the VERT INT L from the DC012, or the MHFU ENB L from the enable flip-flop.
MHFU gets active if the 8088 has not acknowledged a video processor interrupt within approx. 108 milliseconds MHFU gets active if the 8088 has not acknowledged a video processor interrupt within approx. 108 milliseconds
- FIXME: warm boot triggers ERROR 16 (watchdog). BIOS assumes proper power-up only if MHFU detection is _disabled_
Apart from power-cycling, Ctrl-Setup (within SETUP) appears to be the only way to reboot the DEC-100.
- TO BE IMPLEMENTED AS SLOT DEVICES (for now, DIP settings affect 'system_parameter_r' only and are disabled): - TO BE IMPLEMENTED AS SLOT DEVICES (for now, DIP settings affect 'system_parameter_r' only and are disabled):
* Color graphics option (uses NEC upd7220 GDC). REFERENCE: Programmer's Reference: AA-AE36A-TV. * Color graphics option (uses NEC upd7220 GDC). REFERENCE: Programmer's Reference: AA-AE36A-TV.
Either 384 x 240 x 16 or 800 x 240 x 4 colors (out of 4096). 8 × 64 K video RAM. Pallette limited to 4 colors on 100-A. Either 384 x 240 x 16 or 800 x 240 x 4 colors (out of 4096). 8 × 64 K video RAM. Pallette limited to 4 colors on 100-A.
* Extended communication option (1 of 4 possible BUNDLE_OPTIONs) REFERENCE: AA-V172A-TV + Addendum AV-Y890A-TV. * Extended communication option (occupies BUNDLE_OPTION ports) REFERENCE: AA-V172A-TV + Addendum AV-Y890A-TV.
See also NEWCOM1.DOC in RBETECDOC.ZIP. Board connected to the front rightmost expansion slot (1 of the expansion See also NEWCOM1.DOC in RBETECDOC.ZIP. Board connected to the front rightmost expansion slot (1 of the expansion
ports used by the hard disk controller). Thus can't be added to a system that includes the DEC RD50/51. ports used by the hard disk controller). Thus can't be added to a system that includes the DEC RD50/51.
=> 2 ports, a high-speed RS-422 half-duplex interface (port A) + lower-speed RS-423 full/half-duplex interface => 2 ports, a high-speed RS-422 half-duplex interface (port A) + lower-speed RS-423 full/half-duplex interface
@ -47,9 +42,10 @@
Daughterboard, to be plugged into the expansion port where the memory expansion card usually sits. Daughterboard, to be plugged into the expansion port where the memory expansion card usually sits.
If a memory adapter board is present, it has to be plugged into a connector atop the 8087 copro board. If a memory adapter board is present, it has to be plugged into a connector atop the 8087 copro board.
The 8088 is put into the CPU socket on the coprocessor board. The 8088 is put into the CPU socket on the coprocessor board.
=> see MATH test on 'Design Maturity Diagnostics' disk <=
* 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 ) * 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 )
plus DC 7174 or DT 7174 (barely readable). Add-on card, replaces main 8088 cpu (via ribbon cable). Patched 5.0x BOOT ROM labeled 'TBSS1.3 - 3ED4'. 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'.
* NEC_V20 (requires modded BOOT ROM because of - at least 2 - hard coded timing loops): * NEC_V20 (requires modded BOOT ROM because of - at least 2 - hard coded timing loops):
100A: 100B/100+: 100B+ ALTERNATE RECOMMENDATION (fixes RAM size auto-detection problems when V20 is in place. 100A: 100B/100+: 100B+ ALTERNATE RECOMMENDATION (fixes RAM size auto-detection problems when V20 is in place.
@ -69,7 +65,6 @@
Hard coded CPU loops are to blame. Try values from the alternate patch (right). Hard coded CPU loops are to blame. Try values from the alternate patch (right).
=> AAD/AAM - Intel 8088 honors the second byte (operand), NEC V20 ignores it and always uses base 0Ah (10). => AAD/AAM - Intel 8088 honors the second byte (operand), NEC V20 ignores it and always uses base 0Ah (10).
=> UNDOCUMENTED: NEC V20 does not have "POP CS" (opcode 0F). There are more differences (opcode D6; the 2 byte POP: 8F Cx; FF Fx instructions) => UNDOCUMENTED: NEC V20 does not have "POP CS" (opcode 0F). There are more differences (opcode D6; the 2 byte POP: 8F Cx; FF Fx instructions)
Commercial programs had to be patched back then (as was the case with Loderunner for PC).
=> NEW OPCODES: REPC, REPNC, CHKIND, PREPARE, DISPOSE; BCD string operations (ADD4S, CMP4S, SUB4S), bit-ops (NOT, SET, TEST, ROL4, ROR4) => NEW OPCODES: REPC, REPNC, CHKIND, PREPARE, DISPOSE; BCD string operations (ADD4S, CMP4S, SUB4S), bit-ops (NOT, SET, TEST, ROL4, ROR4)
WARNING: undoc'd opcodes, INS, EXT and 8080 behaviour are unemulated yet! MESS' CPU source has up-to-date info. WARNING: undoc'd opcodes, INS, EXT and 8080 behaviour are unemulated yet! MESS' CPU source has up-to-date info.
@ -180,12 +175,12 @@ W17 pulls J1 serial port pin 1 to GND when set (chassis to logical GND).
****************************************************************************/ ****************************************************************************/
// Define standard and maximum RAM sizes (A, then B model): // Define standard and maximum RAM sizes (A, then B model):
//#define BOARD_RAM 0x10000 // 64 K base RAM (100-A) //#define BOARD_RAM 0x0ffff // 64 K base RAM (100-A)
//#define END_OF_RAM 0xcffff // very last byte (100-A) DO NOT CHANGE. //#define END_OF_RAM 0xcffff // very last byte (100-A) DO NOT CHANGE.
// DEC-100-B probes until a 'flaky' area is found (BOOT ROM around F400:0E04). // DEC-100-B probes until a 'flaky' area is found (BOOT ROM around F400:0E04).
// It is no longer possible to key in the RAM size from within the 100-B BIOS. // It is no longer possible to key in the RAM size from within the 100-B BIOS.
#define BOARD_RAM 0x20000 // 128 K base RAM (100-B) #define BOARD_RAM 0x1ffff // 128 K base RAM (100-B)
#define END_OF_RAM 0xdffff // very last byte (100-B) DO NOT CHANGE. #define END_OF_RAM 0xdffff // very last byte (100-B) DO NOT CHANGE.
// TROUBLESHOOTING RAM // TROUBLESHOOTING RAM
@ -194,18 +189,22 @@ W17 pulls J1 serial port pin 1 to GND when set (chassis to logical GND).
// can be narrowed down with the Diagnostic Disk and codes from the 'Pocket Service Guide' // can be narrowed down with the Diagnostic Disk and codes from the 'Pocket Service Guide'
// EK-PC100-PS-002 (APPENDIX B.2.2); pc100ps2.pdf // EK-PC100-PS-002 (APPENDIX B.2.2); pc100ps2.pdf
// WORKAROUNDS:
// Workaround not valid for 100-A - // (1) FORCE LOGO: - not valid for 100-A ROM -
//#define FORCE_RAINBOW_B_LOGO //#define FORCE_RAINBOW_B_LOGO
// (2) KEYBOARD_WORKAROUND : also requires FORCE...LOGO !
//#define KEYBOARD_WORKAROUND
//#define KBD_DELAY 8500
// ----------------------------------------------------------------------------------------------
#include "emu.h" #include "emu.h"
#include "cpu/i86/i86.h" #include "cpu/i86/i86.h"
#include "cpu/z80/z80.h" #include "cpu/z80/z80.h"
#include "video/vtvideo.h" #include "video/vtvideo.h"
#include "machine/wd17xx.h" #include "machine/wd_fdc.h"
#include "formats/rx50_dsk.h"
#include "imagedev/flopdrv.h" #include "imagedev/flopdrv.h"
#include "formats/basicdsk.h"
#include "machine/i8251.h" #include "machine/i8251.h"
#include "machine/clock.h" #include "machine/clock.h"
@ -215,12 +214,17 @@ W17 pulls J1 serial port pin 1 to GND when set (chassis to logical GND).
#include "rainbow.lh" // BEZEL - LAYOUT with LEDs for diag 1-7, keyboard 8-11 and floppy 20-23 #include "rainbow.lh" // BEZEL - LAYOUT with LEDs for diag 1-7, keyboard 8-11 and floppy 20-23
#define LK201_TAG "lk201" #define LK201_TAG "lk201"
#define FD1793_TAG "fd1793x"
#define INVALID_DRIVE 255
class rainbow_state : public driver_device class rainbow_state : public driver_device
{ {
public: public:
rainbow_state(const machine_config &mconfig, device_type type, const char *tag) : rainbow_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag), driver_device(mconfig, type, tag),
#ifdef KEYBOARD_WORKAROUND
#include "m_kbd1.c" // KEYBOARD_WORKAROUND
#endif
m_inp1(*this, "W13"), m_inp1(*this, "W13"),
m_inp2(*this, "W14"), m_inp2(*this, "W14"),
m_inp3(*this, "W15"), m_inp3(*this, "W15"),
@ -235,7 +239,7 @@ public:
m_crtc(*this, "vt100_video"), m_crtc(*this, "vt100_video"),
m_i8088(*this, "maincpu"), m_i8088(*this, "maincpu"),
m_z80(*this, "subcpu"), m_z80(*this, "subcpu"),
m_fdc(*this, "wd1793"), m_fdc(*this, FD1793_TAG),
m_kbd8251(*this, "kbdser"), m_kbd8251(*this, "kbdser"),
m_lk201(*this, LK201_TAG), m_lk201(*this, LK201_TAG),
m_p_ram(*this, "p_ram"), m_p_ram(*this, "p_ram"),
@ -283,11 +287,15 @@ public:
DECLARE_WRITE_LINE_MEMBER(irq_hi_w); DECLARE_WRITE_LINE_MEMBER(irq_hi_w);
#ifdef KEYBOARD_WORKAROUND
#include "port9x_Ax.c" // KEYBOARD_WORKAROUND
#endif
UINT32 screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); UINT32 screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(vblank_irq); INTERRUPT_GEN_MEMBER(vblank_irq);
DECLARE_WRITE_LINE_MEMBER(write_keyboard_clock); DECLARE_WRITE_LINE_MEMBER(write_keyboard_clock);
TIMER_DEVICE_CALLBACK_MEMBER(motor_tick); TIMER_DEVICE_CALLBACK_MEMBER(motor_tick);
DECLARE_FLOPPY_FORMATS( floppy_formats );
protected: protected:
virtual void machine_start(); virtual void machine_start();
@ -305,6 +313,9 @@ private:
IRQ_8088_MAX IRQ_8088_MAX
}; };
#ifdef KEYBOARD_WORKAROUND
#include "m_kbd2.c" // KEYBOARD_WORKAROUND
#endif
required_ioport m_inp1; required_ioport m_inp1;
required_ioport m_inp2; required_ioport m_inp2;
required_ioport m_inp3; required_ioport m_inp3;
@ -315,11 +326,10 @@ private:
required_ioport m_inp8; required_ioport m_inp8;
required_ioport m_inp9; required_ioport m_inp9;
required_ioport m_inp10; required_ioport m_inp10;
required_device<rainbow_video_device> m_crtc; required_device<rainbow_video_device> m_crtc;
required_device<cpu_device> m_i8088; required_device<cpu_device> m_i8088;
required_device<cpu_device> m_z80; required_device<cpu_device> m_z80;
required_device<fd1793_device> m_fdc; required_device<fd1793_t> m_fdc;
required_device<i8251_device> m_kbd8251; required_device<i8251_device> m_kbd8251;
required_device<lk201_device> m_lk201; required_device<lk201_device> m_lk201;
required_shared_ptr<UINT8> m_p_ram; required_shared_ptr<UINT8> m_p_ram;
@ -356,20 +366,25 @@ private:
virtual void machine_reset(); virtual void machine_reset();
int m_unit; int m_unit;
legacy_floppy_image_device *m_image[4]; floppy_image_device *m_floppy;
int m_irq_high; int m_irq_high;
UINT32 m_irq_mask; UINT32 m_irq_mask;
}; };
FLOPPY_FORMATS_MEMBER( rainbow_state::floppy_formats )
FLOPPY_TD0_FORMAT,
FLOPPY_RX50IMG_FORMAT
FLOPPY_FORMATS_END
static SLOT_INTERFACE_START( rainbow_floppies )
SLOT_INTERFACE( "525qd", FLOPPY_525_SSQD ) // "525ssdd"
SLOT_INTERFACE_END
void rainbow_state::machine_start() void rainbow_state::machine_start()
{ {
m_image[0] = subdevice<legacy_floppy_image_device>(FLOPPY_0); MOTOR_DISABLE_counter = 2; // soon resets drv.LEDs
m_image[1] = subdevice<legacy_floppy_image_device>(FLOPPY_1);
m_image[2] = subdevice<legacy_floppy_image_device>(FLOPPY_2);
m_image[3] = subdevice<legacy_floppy_image_device>(FLOPPY_3);
COLD_BOOT = 1; COLD_BOOT = 1;
m_SCREEN_BLANK = false; m_SCREEN_BLANK = false;
@ -386,6 +401,18 @@ void rainbow_state::machine_start()
#ifdef FORCE_RAINBOW_B_LOGO #ifdef FORCE_RAINBOW_B_LOGO
UINT8 *rom = memregion("maincpu")->base(); UINT8 *rom = memregion("maincpu")->base();
rom[0xf4000 + 0x364a]= 2 + 8; // 2 :set ; 4 : reset, 8 : set for 0xf4363 ( 0363 WAIT_FOR_BIT3__loc_35E )
rom[0xf4000 + 0x0363]= 0x90;
rom[0xf4000 + 0x0364]= 0x90;
// If bit 2 = 1 (Efff9), then a keyboard powerup is necessary (=> will lock up in current state)
rom[0xf4000 + 0x3638]= 0x80; // OR instead of TEST
rom[0xf4000 + 0x3639]= 0x0f; // OR instead of TEST
rom[0xf4000 + 0x363a]= 0x08; // 04 => 08
rom[0xf4000 + 0x363b]= 0xeb; // COND => JMPS
if (rom[0xf4174] == 0x75) if (rom[0xf4174] == 0x75)
{ rom[0xf4174] = 0xeb; // jmps RAINBOW100_LOGO__loc_33D { rom[0xf4174] = 0xeb; // jmps RAINBOW100_LOGO__loc_33D
rom[0xf4175] = 0x08; rom[0xf4175] = 0x08;
@ -398,6 +425,9 @@ void rainbow_state::machine_start()
rom[0xf437b] = 0xeb; rom[0xf437b] = 0xeb;
#endif #endif
#ifdef KEYBOARD_WORKAROUND
#include "rainbow_keyboard0.c"
#endif
} }
static ADDRESS_MAP_START( rainbow8088_map, AS_PROGRAM, 8, rainbow_state) static ADDRESS_MAP_START( rainbow8088_map, AS_PROGRAM, 8, rainbow_state)
@ -447,8 +477,10 @@ static ADDRESS_MAP_START( rainbow8088_io , AS_IO, 8, rainbow_state)
AM_RANGE(0x11, 0x11) AM_DEVREADWRITE("kbdser", i8251_device, status_r, control_w) AM_RANGE(0x11, 0x11) AM_DEVREADWRITE("kbdser", i8251_device, status_r, control_w)
// UNMAPPED: // UNMAPPED:
// 0x20 - 0x2f ***** EXTENDED COMM. OPTION (option select 1) // 0x20 -> 0x2f ***** EXTENDED COMM. OPTION / Option Select 1.
// 0x27 (RESET EXTENDED COMM OPTION - - see boot ROM @1EA6) // See boot rom @1EA6: 0x27 (<- RESET EXTENDED COMM OPTION )
// ===========================================================
// 0x30 -> 0x3f ***** EXTENDED COMM. OPTION / Option Select 3.
// =========================================================== // ===========================================================
// 0x40 COMMUNICATIONS DATA REGISTER (MPSC) // 0x40 COMMUNICATIONS DATA REGISTER (MPSC)
// 0x41 PRINTER DATA REGISTER (MPSC) // 0x41 PRINTER DATA REGISTER (MPSC)
@ -476,6 +508,8 @@ static ADDRESS_MAP_START( rainbow8088_io , AS_IO, 8, rainbow_state)
// 56h Data written to this port is loaded into the GDC's FIFO // 56h Data written to this port is loaded into the GDC's FIFO
// Buffer and flagged as a parameter. // Buffer and flagged as a parameter.
// ===========================================================
// 0x60 -> 0x6f ***** EXTENDED COMM. OPTION / Option Select 2.
// =========================================================== // ===========================================================
// TODO: hard disc emulation! // TODO: hard disc emulation!
// ------ Rainbow uses 'WD 1010 AL' (Western Digital 1983) // ------ Rainbow uses 'WD 1010 AL' (Western Digital 1983)
@ -492,6 +526,12 @@ static ADDRESS_MAP_START( rainbow8088_io , AS_IO, 8, rainbow_state)
// SOFTWARE: // SOFTWARE:
// - MS-DOS 2 allows a maximum partition size of 16 MB (sizes > 15 MB are incompatible to DOS 3) // - MS-DOS 2 allows a maximum partition size of 16 MB (sizes > 15 MB are incompatible to DOS 3)
// - MS-DOS 3 has a global 1024 cylinder limit (32 MB). // - MS-DOS 3 has a global 1024 cylinder limit (32 MB).
// ===========================================================
// 0x70 -> 0x7f ***** EXTENDED COMM. OPTION / Option Select 4.
// ===========================================================
#ifdef KEYBOARD_WORKAROUND
#include "am_range_9x_Ax.c" // KEYBOARD_WORKAROUND
#endif
ADDRESS_MAP_END ADDRESS_MAP_END
static ADDRESS_MAP_START(rainbowz80_mem, AS_PROGRAM, 8, rainbow_state) static ADDRESS_MAP_START(rainbowz80_mem, AS_PROGRAM, 8, rainbow_state)
@ -506,16 +546,17 @@ static ADDRESS_MAP_START( rainbowz80_io, AS_IO, 8, rainbow_state)
AM_RANGE(0x20, 0x20) AM_READWRITE(z80_generalstat_r, z80_diskdiag_read_w) // read to port 0x20 used by MS-DOS 2.x diskette loader. AM_RANGE(0x20, 0x20) AM_READWRITE(z80_generalstat_r, z80_diskdiag_read_w) // read to port 0x20 used by MS-DOS 2.x diskette loader.
AM_RANGE(0x21, 0x21) AM_READWRITE(z80_generalstat_r, z80_diskdiag_write_w) AM_RANGE(0x21, 0x21) AM_READWRITE(z80_generalstat_r, z80_diskdiag_write_w)
AM_RANGE(0x40, 0x40) AM_READWRITE(z80_diskstatus_r, z80_diskcontrol_w) AM_RANGE(0x40, 0x40) AM_READWRITE(z80_diskstatus_r, z80_diskcontrol_w)
AM_RANGE(0x60, 0x60) AM_DEVREADWRITE("wd1793", fd1793_device ,status_r, command_w) AM_RANGE(0x60, 0x63) AM_DEVREADWRITE(FD1793_TAG, fd1793_t, read, write)
AM_RANGE(0x61, 0x61) AM_DEVREADWRITE("wd1793", fd1793_device, track_r, track_w)
AM_RANGE(0x62, 0x62) AM_DEVREADWRITE("wd1793", fd1793_device, sector_r, sector_w)
AM_RANGE(0x63, 0x63) AM_DEVREADWRITE("wd1793", fd1793_device, data_r, data_w)
ADDRESS_MAP_END ADDRESS_MAP_END
/* Input ports */ /* Input ports */
/* DIP switches */ /* DIP switches */
static INPUT_PORTS_START( rainbow100b_in ) static INPUT_PORTS_START( rainbow100b_in )
#ifdef KEYBOARD_WORKAROUND
#include "rainbow_ipt.c"
#endif
PORT_START("MONITOR TYPE") PORT_START("MONITOR TYPE")
PORT_DIPNAME( 0x03, 0x03, "MONOCHROME MONITOR") PORT_DIPNAME( 0x03, 0x03, "MONOCHROME MONITOR")
PORT_DIPSETTING( 0x01, "PAPER WHITE" ) PORT_DIPSETTING( 0x01, "PAPER WHITE" )
@ -545,9 +586,9 @@ static INPUT_PORTS_START( rainbow100b_in )
PORT_DIPNAME( 0x01, 0x01, "FLOPPY CONTROLLER") PORT_TOGGLE PORT_DIPNAME( 0x01, 0x01, "FLOPPY CONTROLLER") PORT_TOGGLE
PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_DIPSETTING( 0x01, DEF_STR( On ) )
// BUNDLE_OPTION: COMM.card or hard disc controller extension (marketed later). // BUNDLE_OPTION: EXT.COMM.card -or- hard disk controller (marketed later).
// NOTES: - hard disc and COMM.extension exclude each other. // - hard disc and COMM.extension exclude each other!
// - connector J4 has 4 select lines. Select option 1 = COMM CARD ? // - connector J4 has 4 select lines (Option Select 1-4)
PORT_START("BUNDLE OPTION") PORT_START("BUNDLE OPTION")
PORT_DIPNAME( 0x00, 0x00, "BUNDLE OPTION") PORT_TOGGLE PORT_DIPNAME( 0x00, 0x00, "BUNDLE OPTION") PORT_TOGGLE
PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
@ -586,33 +627,29 @@ static INPUT_PORTS_START( rainbow100b_in )
PORT_DIPSETTING( 0x02, DEF_STR( On ) ) PORT_DIPSETTING( 0x02, DEF_STR( On ) )
INPUT_PORTS_END INPUT_PORTS_END
// Native 400K format (80 T * 10 S * 512 bytes) on 'quad density' RX50 drives
// ( 5.25" single sided; 300 rpm; MFM 250 kbps; 96 - 100 tpi ).
//
// Additionally, the BIOS can *read* VT-180 disks and MS-DOS 160 k disks
// - MS-DOS: FORMAT A: /F:160 and MEDIACHK ON
// ( 40 tracks; single sided with 9 or 8 sectors per track )
static LEGACY_FLOPPY_OPTIONS_START( dec100_floppy )
LEGACY_FLOPPY_OPTION( dec100_floppy, "td0", "Teledisk floppy disk image", td0_dsk_identify, td0_dsk_construct, td0_dsk_destruct, NULL )
LEGACY_FLOPPY_OPTION( dec100_floppy, "img", "DEC Rainbow 100", basicdsk_identify_default, basicdsk_construct_default, NULL,
HEADS([1])
TRACKS(40/[80])
SECTORS(8/9/[10])
SECTOR_LENGTH([512])
INTERLEAVE([0])
FIRST_SECTOR_ID([1])
)
LEGACY_FLOPPY_OPTIONS_END
void rainbow_state::machine_reset() void rainbow_state::machine_reset()
{ {
m_unit = INVALID_DRIVE;
m_fdc->reset();
m_fdc->set_floppy(NULL);
m_fdc->dden_w(0);
//m_fdc->set_force_ready(false);
/* configure RAM */ /* configure RAM */
address_space &program = m_maincpu->space(AS_PROGRAM); address_space &program = m_maincpu->space(AS_PROGRAM);
if (m_inp8->read() < END_OF_RAM) if (m_inp8->read() < END_OF_RAM)
{ program.unmap_readwrite(m_inp8->read(), END_OF_RAM); { program.unmap_readwrite(m_inp8->read(), END_OF_RAM);
} }
if (COLD_BOOT == 1) // BIOS can't handle soft resets (=> triggers ERROR 16).
if ( COLD_BOOT == 2 )
{ // As a fallback, execute a hard reboot -
device().machine().schedule_hard_reset();
}
if ( (COLD_BOOT == 1) )
{ {
COLD_BOOT = 2; COLD_BOOT = 2;
m_crtc->MHFU(-100); // reset MHFU counter m_crtc->MHFU(-100); // reset MHFU counter
@ -647,14 +684,17 @@ void rainbow_state::machine_reset()
output_set_value("led_lock", 0); // led10 output_set_value("led_lock", 0); // led10
output_set_value("led_hold", 0); // led11 output_set_value("led_hold", 0); // led11
MOTOR_DISABLE_counter = 2; // soon resets drv.LEDs
m_unit = 0;
m_irq_mask = 0; m_irq_mask = 0;
} }
#ifdef KEYBOARD_WORKAROUND
#include "rainbow_keyboard2.c"
#endif
UINT32 rainbow_state::screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) UINT32 rainbow_state::screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{ {
// TEST-DEBUG: no screen updates during diskette operations!
if (MOTOR_DISABLE_counter) if (MOTOR_DISABLE_counter)
return 0; return 0;
@ -891,19 +931,33 @@ D3 : READY L: reflects status of READY L signal * from the disk drive *
D2 : INT88 L: (bit reads the INT88 bit sent by Z80 to interrupt 8088) D2 : INT88 L: (bit reads the INT88 bit sent by Z80 to interrupt 8088)
D1 : INTZ80 L: (bit reads the INTZ80 bit sent by 8088 to interrupt Z80) D1 : INTZ80 L: (bit reads the INTZ80 bit sent by 8088 to interrupt Z80)
D0 : ZFLIP L: (read from the diagnostic control register of Z80A) D0 : ZFLIP L: (read from the diagnostic control register of Z80A)
NOTES: ALL LOW ACTIVE - EXCEPT TR00
*/ */
// * TRACK 00 * signal for current drive static int last_track;
int tk00 = ( m_image[m_unit]->floppy_tk00_r() == CLEAR_LINE ) ? 0x20 : 0x00; int track = m_fdc->track_r( space, 0);
int fdc_step = 0;
int fdc_ready = 0;
int tk00 = 0;
int fdc_ready = m_image[m_unit]->floppy_drive_get_flag_state( FLOPPY_DRIVE_READY); if(m_unit != INVALID_DRIVE)
{
if (track != last_track)
fdc_step = 1;
last_track = track;
int data=( 0x80 | // (STEP L) fdc_ready = m_floppy->ready_r();
// ( (fdc_write_gate) ) | tk00 = ( m_floppy->trk00_r() != CLEAR_LINE );
( (tk00) ) | }
// ( fdc_direction) |
( (fdc_ready)? 0x00 : 0x08 ) | int last_dir = 0; // FAKE LAST_DIR + WRITE_GATE FOR NOW.
int fdc_write_gate = 1;
// ***** ALL LOW ACTIVE - EXCEPT tk00 :
int data=(
( (fdc_step) ? 0x00 : 0x80 ) |
( (fdc_write_gate == 1) ? 0x00 : 0x40 ) |
( (tk00) ? 0x20 : 0x00 ) |
( (last_dir == 1) ? 0x00 : 0x10 ) |
( (fdc_ready) ? 0x00 : 0x08 ) |
( (INT88) ? 0x00 : 0x04 ) | ( (INT88) ? 0x00 : 0x04 ) |
( (INTZ80) ? 0x00 : 0x02 ) | ( (INTZ80) ? 0x00 : 0x02 ) |
( (m_zflip) ? 0x00 : 0x01 ) ( (m_zflip) ? 0x00 : 0x01 )
@ -963,7 +1017,10 @@ READ8_MEMBER(rainbow_state::z80_diskstatus_r)
// D3: MOTOR 0 ON L: 0 = indicates MOTOR 0 ON bit is set in drive " // D3: MOTOR 0 ON L: 0 = indicates MOTOR 0 ON bit is set in drive "
// D2: TG43 L : 0 = INDICATES TRACK > 43 SIGNAL FROM FDC TO DISK DRIVE. // D2: TG43 L : 0 = INDICATES TRACK > 43 SIGNAL FROM FDC TO DISK DRIVE.
data |= ( track > 43) ? 0x00 : 0x04; if ( track > 43)
data = data & (255 - 4);
else
data = data | 4;
// D1: DS1 H: reflect status of bits 0 and 1 form disk.control reg. // D1: DS1 H: reflect status of bits 0 and 1 form disk.control reg.
// D0: DS0 H: " // D0: DS0 H: "
@ -971,16 +1028,12 @@ READ8_MEMBER(rainbow_state::z80_diskstatus_r)
} }
// (Z80) : PORT 40H * WRITE * // (Z80) : PORT 40H * WRITE *
// RX-50 has head A and head B (1 for each of the 2 disk slots in a RX-50). // RX-50 has head A and head B (1 for each of the 2 disk slots in a RX-50).
// TODO: find out how head load and drive select really work. // TODO: find out how head load and drive select really work.
WRITE8_MEMBER(rainbow_state::z80_diskcontrol_w) WRITE8_MEMBER(rainbow_state::z80_diskcontrol_w)
{ {
// FORCE_READY = 0 : assert DRIVE READY on FDC (diagnostic override; USED BY BIOS!) // FORCE_READY = 0 : assert DRIVE READY on FDC (diagnostic override; USED BY BIOS!)
// 1 : set ready only if drive is present, disk is in the drive, //bool force_ready = ( (data & 4) == 0 ) ? true : false;
// and disk motor is on - for Amstrad, Spectrum, PCW...
int force_ready = ( (data & 4) != 0 ) ? 0 : 1;
int drive; int drive;
if ( m_inp10->read() && ((data & 3) < 2) ) if ( m_inp10->read() && ((data & 3) < 2) )
@ -988,18 +1041,23 @@ WRITE8_MEMBER(rainbow_state::z80_diskcontrol_w)
else else
drive = data & 3; drive = data & 3;
int selected_drive = 255; int selected_drive = INVALID_DRIVE;
static const char *names[] = { FD1793_TAG ":0", FD1793_TAG ":1", FD1793_TAG ":2", FD1793_TAG ":3" };
if (floppy_get_device( machine(), drive )->flopimg_get_image() != NULL) floppy_connector *con = machine().device<floppy_connector>(names[drive]);
{ selected_drive = drive; if (con)
m_fdc->set_drive(selected_drive); { m_floppy = con->get_device();
if (m_floppy)
{
selected_drive = drive;
m_fdc->set_floppy(m_floppy); // Sets new _image device_
m_floppy->set_rpm(300.);
// RX50 board has additional 'side select' - ignored by WD emulation?
m_floppy->ss_w((data & 20) ? 1 : 0);
}
} }
// WD emulation (wd17xx.c) will ignore 'side select' if set to WD1793.
// Is it safe to * always assume * single sided 400 K disks?
m_fdc->set_side((data & 20) ? 1 : 0);
m_fdc->dden_w(0); /* SEE 'WRITE_TRACK' : 1 = SD; 0 = DD; enable double density */
output_set_value("driveled0", (selected_drive == 0) ? 1 : 0 ); output_set_value("driveled0", (selected_drive == 0) ? 1 : 0 );
output_set_value("driveled1", (selected_drive == 1) ? 1 : 0 ); output_set_value("driveled1", (selected_drive == 1) ? 1 : 0 );
@ -1011,24 +1069,36 @@ WRITE8_MEMBER(rainbow_state::z80_diskcontrol_w)
{ {
m_unit = selected_drive; m_unit = selected_drive;
// MOTOR ON flags 1+2 proved to be unreliable in this context. if (MOTOR_DISABLE_counter == 0) // "one shot"
// So this timeout only disables LEDs. MOTOR_DISABLE_counter = 4800; // 2400 = 500 ms
MOTOR_DISABLE_counter = 10000; // prolonged timeout. DEFAULT: 2400 = 500 ms
// m_fdc->set_force_ready(force_ready);
} else
{
// m_fdc->set_force_ready(false);
}
for(int f_num=0; f_num <= 3; f_num++) for(int f_num=0; f_num <= 3; f_num++)
{ {
// Although 1773 does not feature 'motor on' this statement is required: floppy_connector *con = machine().device<floppy_connector>(names[f_num]);
// CLEAR_LINE = turn motor on - floppy_image_device *tmp_floppy = con->get_device();
m_image[f_num]->floppy_mon_w((f_num == selected_drive) ? CLEAR_LINE : ASSERT_LINE); tmp_floppy->mon_w( (f_num == m_unit) ? CLEAR_LINE : ASSERT_LINE );
// Parameters: DRIVE, STATE, FLAG
m_image[f_num]->floppy_drive_set_ready_state(
(f_num == selected_drive) ? 1 : 0,
(f_num == selected_drive) ? force_ready : 0
);
}
} }
if(m_unit == INVALID_DRIVE)
{
data = data & (255 -3);
data = data | 8; // MOTOR 0 OFF
data = data | 16; // MOTOR 1 OFF
}else
{ data = ( data & (255 -3) ) | m_unit;
if(m_unit < 2)
data = data & (255 - 8); // MOTOR 0 (for A or B)
if(m_unit > 1)
data = data & (255 - 16); // MOTOR 1 (for C or D)
}
m_z80_diskcontrol = data; m_z80_diskcontrol = data;
} }
@ -1065,13 +1135,6 @@ WRITE8_MEMBER( rainbow_state::diagnostic_w ) // 8088 (port 0A WRITTEN). Fig.4-28
// printf("%02x to diag port (PC=%x)\n", data, space.device().safe_pc()); // printf("%02x to diag port (PC=%x)\n", data, space.device().safe_pc());
m_SCREEN_BLANK = (data & 2) ? false : true; m_SCREEN_BLANK = (data & 2) ? false : true;
// SAVE / PROGRAM NVM: transfer data from volatile memory to NVM
if ( !(data & 0x40) && (m_diagnostic & 0x40) )
memcpy( m_p_nvram, m_p_vol_ram, 256);
// READ / RECALL NVM: transfer data from NVM to volatile memory
if ( (data & 0x80) && !(m_diagnostic & 0x80) )
memcpy( m_p_vol_ram, m_p_nvram, 256);
if (!(data & 1)) if (!(data & 1))
{ {
@ -1087,19 +1150,32 @@ WRITE8_MEMBER( rainbow_state::diagnostic_w ) // 8088 (port 0A WRITTEN). Fig.4-28
m_z80->reset(); m_z80->reset();
} }
/* Page 197 or 5-13 of formatter description: if(m_unit != INVALID_DRIVE)
ZRESET L : this low input from the 8088 diagnostic write register {
resets the formatter controller, loads 03H into the command register, if ( (m_diagnostic & 1) && !(data & 1) )
and resets the not ready (status bit 7). {
m_fdc->soft_reset();
}
When ZRESET goes high (1), a restore command is executed regardless if ( !(m_diagnostic & 1) && (data & 1) )
of the state of the ready signal from the diskette drive and {
01H is loaded into the sector register. m_fdc->soft_reset(); // See formatter description p.197 or 5-13
*/ }
}
// MISSING BITS (* not vital for normal operation, see diag.disk) -
// BIT 2: GRF VID SEL (0 = system module; 1 = graphics option)
// BIT 3: PARITY TEST (1 = enables parity test on memory option board)
// * BIT 4: DIAG LOOPBACK (0 at power-up; 1 directs RX50 and DC12 output to printer port)
// * BIT 5: PORT LOOPBACK (1 enables loopback for COMM, PRINTER, KEYBOARD ports)
// BIT 6: Transfer data from volatile memory to NVM
if ( !(data & 0x40) && (m_diagnostic & 0x40) )
memcpy( m_p_nvram, m_p_vol_ram, 256);
// BIT 7: Transfer data from NVM to volatile memory
if ( (data & 0x80) && !(m_diagnostic & 0x80) )
memcpy( m_p_vol_ram, m_p_nvram, 256);
// reset device when going from high to low,
// restore command when going from low to high :
m_fdc->mr_w((data & 1) ? 1 : 0);
m_diagnostic = data; m_diagnostic = data;
} }
@ -1107,6 +1183,7 @@ WRITE8_MEMBER( rainbow_state::diagnostic_w ) // 8088 (port 0A WRITTEN). Fig.4-28
// KEYBOARD // KEYBOARD
void rainbow_state::update_kbd_irq() void rainbow_state::update_kbd_irq()
{ {
#ifndef KEYBOARD_WORKAROUND
if ((m_kbd_rx_ready) || (m_kbd_tx_ready)) if ((m_kbd_rx_ready) || (m_kbd_tx_ready))
{ {
raise_8088_irq(IRQ_8088_KBD); raise_8088_irq(IRQ_8088_KBD);
@ -1115,6 +1192,7 @@ void rainbow_state::update_kbd_irq()
{ {
lower_8088_irq(IRQ_8088_KBD); lower_8088_irq(IRQ_8088_KBD);
} }
#endif
} }
WRITE_LINE_MEMBER(rainbow_state::kbd_tx) WRITE_LINE_MEMBER(rainbow_state::kbd_tx)
@ -1193,12 +1271,6 @@ static GFXDECODE_START( rainbow )
GFXDECODE_ENTRY( "chargen", 0x0000, rainbow_charlayout, 0, 1 ) GFXDECODE_ENTRY( "chargen", 0x0000, rainbow_charlayout, 0, 1 )
GFXDECODE_END GFXDECODE_END
static const floppy_interface floppy_intf =
{
FLOPPY_STANDARD_5_25_SSDD_80,
LEGACY_FLOPPY_OPTIONS_NAME( dec100_floppy ),
"floppy_5_25"
};
static MACHINE_CONFIG_START( rainbow, rainbow_state ) static MACHINE_CONFIG_START( rainbow, rainbow_state )
MCFG_DEFAULT_LAYOUT(layout_rainbow) MCFG_DEFAULT_LAYOUT(layout_rainbow)
@ -1229,9 +1301,12 @@ static MACHINE_CONFIG_START( rainbow, rainbow_state )
MCFG_VT_VIDEO_RAM_CALLBACK(READ8(rainbow_state, read_video_ram_r)) MCFG_VT_VIDEO_RAM_CALLBACK(READ8(rainbow_state, read_video_ram_r))
MCFG_VT_VIDEO_CLEAR_VIDEO_INTERRUPT_CALLBACK(WRITELINE(rainbow_state, clear_video_interrupt)) MCFG_VT_VIDEO_CLEAR_VIDEO_INTERRUPT_CALLBACK(WRITELINE(rainbow_state, clear_video_interrupt))
MCFG_DEVICE_ADD("wd1793", FD1793, 0) MCFG_FD1793x_ADD(FD1793_TAG, XTAL_24_0734MHz / 24) // no separate 1 Mhz quartz
MCFG_WD17XX_DEFAULT_DRIVE4_TAGS MCFG_WD_FDC_FORCE_READY
MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(floppy_intf) MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":0", rainbow_floppies, "525qd", rainbow_state::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":1", rainbow_floppies, "525qd", rainbow_state::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":2", rainbow_floppies, "525qd", rainbow_state::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":3", rainbow_floppies, "525qd", rainbow_state::floppy_formats)
MCFG_SOFTWARE_LIST_ADD("flop_list","rainbow") MCFG_SOFTWARE_LIST_ADD("flop_list","rainbow")
MCFG_DEVICE_ADD("kbdser", I8251, 0) MCFG_DEVICE_ADD("kbdser", I8251, 0)
@ -1294,10 +1369,10 @@ ROM_END
// CHANGES: the 'Boot 2.4' manual mentions 'recent ROM changes for MASS 11' in January 1985. // CHANGES: the 'Boot 2.4' manual mentions 'recent ROM changes for MASS 11' in January 1985.
// Older ROMs like 04.03.11 (for PC-100-A) or 05.03 (100-B) obviously do not incorporate these. // Older ROMs like 04.03.11 (for PC-100-A) or 05.03 (100-B) obviously do not incorporate these.
// => jump tables (F4000-F40083 and FC000-FC004D) were not extended. // => jump tables (F4000-F40083 and FC000-FC004D) were not extended.
// => absolute addresses of some internal routines have changed. // => absolute addresses of some internal routines have changed.
// => programs that do not rely on specific ROM versions should be compatible. // => programs that do not rely on specific ROM versions should be compatible.
// MASS was a VAX word processor, so changes likely affected terminal emulation.
// FIXME: ROM names are made up. // FIXME: ROM names are made up.
// Someone who knows the DEC naming conventions should correct them - // Someone who knows the DEC naming conventions should correct them -

View File

@ -256,6 +256,8 @@ const rom_entry *lk201_device::device_rom_region() const
*/ */
INPUT_PORTS_START( lk201 ) INPUT_PORTS_START( lk201 )
#ifndef KEYBOARD_WORKAROUND
PORT_START("KBD0") PORT_START("KBD0")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
@ -435,6 +437,8 @@ INPUT_PORTS_START( lk201 )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F19") PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F19")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
#endif
INPUT_PORTS_END INPUT_PORTS_END
@ -600,6 +604,7 @@ void lk201_device::send_port(address_space &space, UINT8 offset, UINT8 data)
// Check for keyboard read strobe // Check for keyboard read strobe
if (((data & 0x40) == 0) && (ports[offset] & 0x40)) if (((data & 0x40) == 0) && (ports[offset] & 0x40))
{ {
#ifndef KEYBOARD_WORKAROUND
if (ports[0] & 0x1) kbd_data = m_kbd0->read(); if (ports[0] & 0x1) kbd_data = m_kbd0->read();
if (ports[0] & 0x2) kbd_data = m_kbd1->read(); if (ports[0] & 0x2) kbd_data = m_kbd1->read();
if (ports[0] & 0x4) kbd_data = m_kbd2->read(); if (ports[0] & 0x4) kbd_data = m_kbd2->read();
@ -618,6 +623,7 @@ void lk201_device::send_port(address_space &space, UINT8 offset, UINT8 data)
if (ports[1] & 0x80) kbd_data = m_kbd15->read(); if (ports[1] & 0x80) kbd_data = m_kbd15->read();
if (ports[2] & 0x1) kbd_data = m_kbd16->read(); if (ports[2] & 0x1) kbd_data = m_kbd16->read();
if (ports[2] & 0x2) kbd_data = m_kbd17->read(); if (ports[2] & 0x2) kbd_data = m_kbd17->read();
#endif
} }
// Check for LED update strobe // Check for LED update strobe
if (((data & 0x80) == 0) && (ports[offset] & 0x80)) if (((data & 0x80) == 0) && (ports[offset] & 0x80))