diff options
author | 2014-06-09 00:42:53 +0000 | |
---|---|---|
committer | 2014-06-09 00:42:53 +0000 | |
commit | f4d741ca06a7082400927d576ded593f442b33e0 (patch) | |
tree | cde8cbd4e450829246f573ef016ec5f0b755a3e1 | |
parent | 0f0c004ce810e83e603f1fab992dbe726f67f12f (diff) |
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]
-rw-r--r-- | .gitattributes | 2 | ||||
-rw-r--r-- | src/emu/cpu/i86/i86.c | 16 | ||||
-rw-r--r-- | src/lib/formats/rx50_dsk.c | 227 | ||||
-rw-r--r-- | src/lib/formats/rx50_dsk.h | 40 | ||||
-rw-r--r-- | src/lib/lib.mak | 1 | ||||
-rw-r--r-- | src/mess/drivers/rainbow.c | 339 | ||||
-rw-r--r-- | src/mess/machine/dec_lk201.c | 6 |
7 files changed, 493 insertions, 138 deletions
diff --git a/.gitattributes b/.gitattributes index bbfbd010791..85f6635f41b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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/rk_cas.c 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.h svneol=native#text/plain src/lib/formats/sf7000_dsk.c svneol=native#text/plain diff --git a/src/emu/cpu/i86/i86.c b/src/emu/cpu/i86/i86.c index f091ba8fc08..5790e0d7382 100644 --- a/src/emu/cpu/i86/i86.c +++ b/src/emu/cpu/i86/i86.c @@ -1138,10 +1138,12 @@ bool i8086_common_cpu_device::common_op(UINT8 op) break; // 8086 'invalid opcodes', as documented at http://www.os2museum.com/wp/?p=2147 -// 0x60 - 0x6f are an alias to 0x70 - 0x7f. -// These instructions are used in the boot sector for some versions of -// MS-DOS 2.01 (e.g. the DEC Rainbow version). - case 0x60: +// - 0x60 - 0x6f are an alias to 0x70 - 0x7f. +// - 0xc0, 0xc1, 0xc8, 0xc9 are also aliases where the CPU ignores BIT 1 (*). +// +// 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 JMP( OF); break; @@ -1670,7 +1672,7 @@ bool i8086_common_cpu_device::common_op(UINT8 op) CLK(MOV_RI16); break; - + case 0xc0: // 0xc0 is 0xc2 - see (*) case 0xc2: // i_ret_d16 { UINT32 count = fetch_word(); @@ -1680,6 +1682,7 @@ bool i8086_common_cpu_device::common_op(UINT8 op) } break; + case 0xc1: // 0xc1 is 0xc3 - see (*) case 0xc3: // i_ret m_ip = POP(); CLK(RET_NEAR); @@ -1711,7 +1714,7 @@ bool i8086_common_cpu_device::common_op(UINT8 op) CLKM(MOV_RI16,MOV_MI16); break; - + case 0xc8: // 0xc8 = 0xca - see (*) case 0xca: // i_retf_d16 { UINT32 count = fetch_word(); @@ -1722,6 +1725,7 @@ bool i8086_common_cpu_device::common_op(UINT8 op) } break; + case 0xc9: // 0xc9 = 0xcb - see (*) case 0xcb: // i_retf m_ip = POP(); m_sregs[CS] = POP(); diff --git a/src/lib/formats/rx50_dsk.c b/src/lib/formats/rx50_dsk.c new file mode 100644 index 00000000000..cf70b43a9f5 --- /dev/null +++ b/src/lib/formats/rx50_dsk.c @@ -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 §or_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 + +*/
\ No newline at end of file diff --git a/src/lib/formats/rx50_dsk.h b/src/lib/formats/rx50_dsk.h new file mode 100644 index 00000000000..29db583f5b4 --- /dev/null +++ b/src/lib/formats/rx50_dsk.h @@ -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 §or_count); +}; + +extern const floppy_format_type FLOPPY_RX50IMG_FORMAT; + +#endif /* RX50_DSK_H_ */ diff --git a/src/lib/lib.mak b/src/lib/lib.mak index 179fac1e4a8..f01905ba8b8 100644 --- a/src/lib/lib.mak +++ b/src/lib/lib.mak @@ -185,6 +185,7 @@ FORMATSOBJS = \ $(LIBOBJ)/formats/pyldin_dsk.o \ $(LIBOBJ)/formats/ql_dsk.o \ $(LIBOBJ)/formats/rk_cas.o \ + $(LIBOBJ)/formats/rx50_dsk.o \ $(LIBOBJ)/formats/sc3000_bit.o \ $(LIBOBJ)/formats/sf7000_dsk.o \ $(LIBOBJ)/formats/smx_dsk.o \ diff --git a/src/mess/drivers/rainbow.c b/src/mess/drivers/rainbow.c index cffb8f7b8b4..db945196a6a 100644 --- a/src/mess/drivers/rainbow.c +++ b/src/mess/drivers/rainbow.c @@ -4,35 +4,30 @@ Driver-in-progress by R. Belmont and Miodrag Milanovic. 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). While this is OK for the compatible -190, it doesn't do justice to ancient '100 A' hardware. - Currently, there are 2 showstoppers: - (1) IRQ logic for 100-B needs further work (text in RBCONVERT.ZIP has details concerning -A versus -B) - (2) Keyboard emulation incomplete (inhibits the system from booting with ERROR 50). - - - FLOPPY TIMING: 'wd17xx_complete_command' * must * be hard wired to about 13 usecs. - Line 1063 in 'wd17xx.c' has to be changed (until legacy code here is removed): - - w->timer_cmd->adjust(attotime::from_usec(usecs)); - + w->timer_cmd->adjust(attotime::from_usec(13)); + Currently, there are several issues here: + (1) 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?). + (3) Read errors when booting CP/M 2.x or DOS 2.x (secondary boot; read errors beyond T >= 2). + Seek (+ verify) and a number of signals (TRACK > 43 TG43, INDEX etc.) do not work (diag.disk aborts drive test). - NOT WORKING: serial (ERROR 60). - 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. 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): * 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. - * 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 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 @@ -47,9 +42,10 @@ 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. 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 ) - 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): 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). => 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) - 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) 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 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. // 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. -#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. // 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' // EK-PC100-PS-002 (APPENDIX B.2.2); pc100ps2.pdf - -// Workaround not valid for 100-A - +// WORKAROUNDS: +// (1) FORCE LOGO: - not valid for 100-A ROM - //#define FORCE_RAINBOW_B_LOGO +// (2) KEYBOARD_WORKAROUND : also requires FORCE...LOGO ! +//#define KEYBOARD_WORKAROUND +//#define KBD_DELAY 8500 +// ---------------------------------------------------------------------------------------------- #include "emu.h" #include "cpu/i86/i86.h" #include "cpu/z80/z80.h" #include "video/vtvideo.h" -#include "machine/wd17xx.h" -#include "imagedev/flopdrv.h" -#include "formats/basicdsk.h" +#include "machine/wd_fdc.h" +#include "formats/rx50_dsk.h" +#include "imagedev/flopdrv.h" #include "machine/i8251.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 #define LK201_TAG "lk201" +#define FD1793_TAG "fd1793x" +#define INVALID_DRIVE 255 class rainbow_state : public driver_device { public: rainbow_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), +#ifdef KEYBOARD_WORKAROUND + #include "m_kbd1.c" // KEYBOARD_WORKAROUND +#endif m_inp1(*this, "W13"), m_inp2(*this, "W14"), m_inp3(*this, "W15"), @@ -235,7 +239,7 @@ public: m_crtc(*this, "vt100_video"), m_i8088(*this, "maincpu"), m_z80(*this, "subcpu"), - m_fdc(*this, "wd1793"), + m_fdc(*this, FD1793_TAG), m_kbd8251(*this, "kbdser"), m_lk201(*this, LK201_TAG), m_p_ram(*this, "p_ram"), @@ -283,11 +287,15 @@ public: 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); INTERRUPT_GEN_MEMBER(vblank_irq); DECLARE_WRITE_LINE_MEMBER(write_keyboard_clock); TIMER_DEVICE_CALLBACK_MEMBER(motor_tick); + DECLARE_FLOPPY_FORMATS( floppy_formats ); protected: virtual void machine_start(); @@ -305,6 +313,9 @@ private: IRQ_8088_MAX }; +#ifdef KEYBOARD_WORKAROUND + #include "m_kbd2.c" // KEYBOARD_WORKAROUND +#endif required_ioport m_inp1; required_ioport m_inp2; required_ioport m_inp3; @@ -315,11 +326,10 @@ private: required_ioport m_inp8; required_ioport m_inp9; required_ioport m_inp10; - required_device<rainbow_video_device> m_crtc; required_device<cpu_device> m_i8088; 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<lk201_device> m_lk201; required_shared_ptr<UINT8> m_p_ram; @@ -356,20 +366,25 @@ private: virtual void machine_reset(); int m_unit; - legacy_floppy_image_device *m_image[4]; + floppy_image_device *m_floppy; int m_irq_high; 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() { - m_image[0] = subdevice<legacy_floppy_image_device>(FLOPPY_0); - 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); - + MOTOR_DISABLE_counter = 2; // soon resets drv.LEDs COLD_BOOT = 1; m_SCREEN_BLANK = false; @@ -386,6 +401,18 @@ void rainbow_state::machine_start() #ifdef FORCE_RAINBOW_B_LOGO 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) { rom[0xf4174] = 0xeb; // jmps RAINBOW100_LOGO__loc_33D rom[0xf4175] = 0x08; @@ -398,6 +425,9 @@ void rainbow_state::machine_start() rom[0xf437b] = 0xeb; #endif +#ifdef KEYBOARD_WORKAROUND + #include "rainbow_keyboard0.c" +#endif } static ADDRESS_MAP_START( rainbow8088_map, AS_PROGRAM, 8, rainbow_state) @@ -447,9 +477,11 @@ static ADDRESS_MAP_START( rainbow8088_io , AS_IO, 8, rainbow_state) AM_RANGE(0x11, 0x11) AM_DEVREADWRITE("kbdser", i8251_device, status_r, control_w) // UNMAPPED: - // 0x20 - 0x2f ***** EXTENDED COMM. OPTION (option select 1) - // 0x27 (RESET EXTENDED COMM OPTION - - see boot ROM @1EA6) + // 0x20 -> 0x2f ***** EXTENDED COMM. OPTION / Option Select 1. + // See boot rom @1EA6: 0x27 (<- RESET EXTENDED COMM OPTION ) // =========================================================== + // 0x30 -> 0x3f ***** EXTENDED COMM. OPTION / Option Select 3. + // =========================================================== // 0x40 COMMUNICATIONS DATA REGISTER (MPSC) // 0x41 PRINTER DATA REGISTER (MPSC) // 0x42 COMMUNICATIONS CONTROL / STATUS REGISTER (MPSC) @@ -477,6 +509,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 // Buffer and flagged as a parameter. // =========================================================== + // 0x60 -> 0x6f ***** EXTENDED COMM. OPTION / Option Select 2. + // =========================================================== // TODO: hard disc emulation! // ------ Rainbow uses 'WD 1010 AL' (Western Digital 1983) // Register compatible to WD2010 (present in MESS) @@ -492,6 +526,12 @@ static ADDRESS_MAP_START( rainbow8088_io , AS_IO, 8, rainbow_state) // SOFTWARE: // - 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). + // =========================================================== + // 0x70 -> 0x7f ***** EXTENDED COMM. OPTION / Option Select 4. + // =========================================================== +#ifdef KEYBOARD_WORKAROUND + #include "am_range_9x_Ax.c" // KEYBOARD_WORKAROUND +#endif ADDRESS_MAP_END 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(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(0x60, 0x60) AM_DEVREADWRITE("wd1793", fd1793_device ,status_r, command_w) - 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) + AM_RANGE(0x60, 0x63) AM_DEVREADWRITE(FD1793_TAG, fd1793_t, read, write) ADDRESS_MAP_END /* Input ports */ /* DIP switches */ static INPUT_PORTS_START( rainbow100b_in ) + +#ifdef KEYBOARD_WORKAROUND + #include "rainbow_ipt.c" +#endif PORT_START("MONITOR TYPE") PORT_DIPNAME( 0x03, 0x03, "MONOCHROME MONITOR") PORT_DIPSETTING( 0x01, "PAPER WHITE" ) @@ -545,9 +586,9 @@ static INPUT_PORTS_START( rainbow100b_in ) PORT_DIPNAME( 0x01, 0x01, "FLOPPY CONTROLLER") PORT_TOGGLE PORT_DIPSETTING( 0x01, DEF_STR( On ) ) - // BUNDLE_OPTION: COMM.card or hard disc controller extension (marketed later). - // NOTES: - hard disc and COMM.extension exclude each other. - // - connector J4 has 4 select lines. Select option 1 = COMM CARD ? + // BUNDLE_OPTION: EXT.COMM.card -or- hard disk controller (marketed later). + // - hard disc and COMM.extension exclude each other! + // - connector J4 has 4 select lines (Option Select 1-4) PORT_START("BUNDLE OPTION") PORT_DIPNAME( 0x00, 0x00, "BUNDLE OPTION") PORT_TOGGLE PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) @@ -586,33 +627,29 @@ static INPUT_PORTS_START( rainbow100b_in ) PORT_DIPSETTING( 0x02, DEF_STR( On ) ) 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() { + 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 */ address_space &program = m_maincpu->space(AS_PROGRAM); if (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; 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_hold", 0); // led11 - MOTOR_DISABLE_counter = 2; // soon resets drv.LEDs - m_unit = 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) { - // TEST-DEBUG: no screen updates during diskette operations! if (MOTOR_DISABLE_counter) return 0; @@ -780,7 +820,7 @@ READ8_MEMBER(rainbow_state::system_parameter_r) return ( ((m_inp5->read() == 1) ? 0 : 1) | ((m_inp6->read() == 1) ? 0 : 2) | ((m_inp7->read() == 1) ? 0 : 4) | - ((m_inp8->read() > BOARD_RAM) ? 0 : 8) | + ((m_inp8->read() > BOARD_RAM) ? 0 : 8) | 16 | 32 | 64 | 128 // to be verified. ); } @@ -799,9 +839,9 @@ READ8_MEMBER(rainbow_state::comm_control_r) int data; if (COLD_BOOT == 2) data = 0; - else + else data = m_crtc->MHFU(1); - + return ( ( (data > 0) ? 0x00 : 0x20) |// (L): status of MHFU flag => bit pos.5 ( (INT88) ? 0x00 : 0x40 ) | // (L) ( (INTZ80) ? 0x00 : 0x80 ) // (L) @@ -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) 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) - -NOTES: ALL LOW ACTIVE - EXCEPT TR00 */ - // * TRACK 00 * signal for current drive - int tk00 = ( m_image[m_unit]->floppy_tk00_r() == CLEAR_LINE ) ? 0x20 : 0x00; + static int last_track; + 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; + + fdc_ready = m_floppy->ready_r(); + tk00 = ( m_floppy->trk00_r() != CLEAR_LINE ); + } - int data=( 0x80 | // (STEP L) -// ( (fdc_write_gate) ) | - ( (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 ) | ( (INTZ80) ? 0x00 : 0x02 ) | ( (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 " // 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. // D0: DS0 H: " @@ -971,16 +1028,12 @@ READ8_MEMBER(rainbow_state::z80_diskstatus_r) } // (Z80) : PORT 40H * WRITE * - // 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. WRITE8_MEMBER(rainbow_state::z80_diskcontrol_w) { // 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, - // and disk motor is on - for Amstrad, Spectrum, PCW... - int force_ready = ( (data & 4) != 0 ) ? 0 : 1; + //bool force_ready = ( (data & 4) == 0 ) ? true : false; int drive; if ( m_inp10->read() && ((data & 3) < 2) ) @@ -988,18 +1041,23 @@ WRITE8_MEMBER(rainbow_state::z80_diskcontrol_w) else 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) - { selected_drive = drive; - m_fdc->set_drive(selected_drive); - } + floppy_connector *con = machine().device<floppy_connector>(names[drive]); + if (con) + { m_floppy = con->get_device(); + if (m_floppy) + { + selected_drive = drive; - // 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->set_floppy(m_floppy); // Sets new _image device_ + m_floppy->set_rpm(300.); - m_fdc->dden_w(0); /* SEE 'WRITE_TRACK' : 1 = SD; 0 = DD; enable double density */ + // RX50 board has additional 'side select' - ignored by WD emulation? + m_floppy->ss_w((data & 20) ? 1 : 0); + } + } output_set_value("driveled0", (selected_drive == 0) ? 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; - // MOTOR ON flags 1+2 proved to be unreliable in this context. - // So this timeout only disables LEDs. - MOTOR_DISABLE_counter = 10000; // prolonged timeout. DEFAULT: 2400 = 500 ms + if (MOTOR_DISABLE_counter == 0) // "one shot" + MOTOR_DISABLE_counter = 4800; // 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++) { - // Although 1773 does not feature 'motor on' this statement is required: - // CLEAR_LINE = turn motor on - - m_image[f_num]->floppy_mon_w((f_num == selected_drive) ? 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 - ); - } + floppy_connector *con = machine().device<floppy_connector>(names[f_num]); + floppy_image_device *tmp_floppy = con->get_device(); + tmp_floppy->mon_w( (f_num == m_unit) ? CLEAR_LINE : ASSERT_LINE ); } + 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; } @@ -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()); 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)) { @@ -1087,19 +1150,32 @@ WRITE8_MEMBER( rainbow_state::diagnostic_w ) // 8088 (port 0A WRITTEN). Fig.4-28 m_z80->reset(); } - /* Page 197 or 5-13 of formatter description: - ZRESET L : this low input from the 8088 diagnostic write register - resets the formatter controller, loads 03H into the command register, - and resets the not ready (status bit 7). + if(m_unit != INVALID_DRIVE) + { + if ( (m_diagnostic & 1) && !(data & 1) ) + { + m_fdc->soft_reset(); + } + + if ( !(m_diagnostic & 1) && (data & 1) ) + { + 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); - When ZRESET goes high (1), a restore command is executed regardless - of the state of the ready signal from the diskette drive and - 01H is loaded into the sector register. - */ + // 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; } @@ -1107,6 +1183,7 @@ WRITE8_MEMBER( rainbow_state::diagnostic_w ) // 8088 (port 0A WRITTEN). Fig.4-28 // KEYBOARD void rainbow_state::update_kbd_irq() { +#ifndef KEYBOARD_WORKAROUND if ((m_kbd_rx_ready) || (m_kbd_tx_ready)) { raise_8088_irq(IRQ_8088_KBD); @@ -1115,6 +1192,7 @@ void rainbow_state::update_kbd_irq() { lower_8088_irq(IRQ_8088_KBD); } +#endif } WRITE_LINE_MEMBER(rainbow_state::kbd_tx) @@ -1193,12 +1271,6 @@ static GFXDECODE_START( rainbow ) GFXDECODE_ENTRY( "chargen", 0x0000, rainbow_charlayout, 0, 1 ) 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 ) 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_CLEAR_VIDEO_INTERRUPT_CALLBACK(WRITELINE(rainbow_state, clear_video_interrupt)) - MCFG_DEVICE_ADD("wd1793", FD1793, 0) - MCFG_WD17XX_DEFAULT_DRIVE4_TAGS - MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(floppy_intf) + MCFG_FD1793x_ADD(FD1793_TAG, XTAL_24_0734MHz / 24) // no separate 1 Mhz quartz + MCFG_WD_FDC_FORCE_READY + 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_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. // 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. // => absolute addresses of some internal routines have changed. // => 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. // Someone who knows the DEC naming conventions should correct them - diff --git a/src/mess/machine/dec_lk201.c b/src/mess/machine/dec_lk201.c index 3889d3e553a..ee822b10b8f 100644 --- a/src/mess/machine/dec_lk201.c +++ b/src/mess/machine/dec_lk201.c @@ -256,6 +256,8 @@ const rom_entry *lk201_device::device_rom_region() const */ INPUT_PORTS_START( lk201 ) + +#ifndef KEYBOARD_WORKAROUND PORT_START("KBD0") PORT_BIT( 0x01, 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( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F19") PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) + +#endif INPUT_PORTS_END @@ -600,6 +604,7 @@ void lk201_device::send_port(address_space &space, UINT8 offset, UINT8 data) // Check for keyboard read strobe if (((data & 0x40) == 0) && (ports[offset] & 0x40)) { +#ifndef KEYBOARD_WORKAROUND if (ports[0] & 0x1) kbd_data = m_kbd0->read(); if (ports[0] & 0x2) kbd_data = m_kbd1->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[2] & 0x1) kbd_data = m_kbd16->read(); if (ports[2] & 0x2) kbd_data = m_kbd17->read(); +#endif } // Check for LED update strobe if (((data & 0x80) == 0) && (ports[offset] & 0x80)) |