trunk/src/lib/formats/rx50_dsk.c
| r0 | r30902 | |
| 1 | /********************************************************************** |
| 2 | |
| 3 | formats/rx50_dsk.c |
| 4 | Floppies used by Rainbow 100 and 190. |
| 5 | |
| 6 | The RX50 drive: 5.25" format; 300 rpm; MFM 250 kbps; 96 - 100 tpi |
| 7 | - single sided with two disk slots (1 drive motor served both). |
| 8 | |
| 9 | DEC used the RX50 in entirely different architectures (Pro / PDP-11). |
| 10 | Native Rainbow 100 format: |
| 11 | - SSQD - 80 tracks with 10 sectors per track (512 byte sectors) |
| 12 | - first two tracks are reserved for loader code (DOS / CPM / custom) |
| 13 | - FAT and root directory began immediately on track 2. |
| 14 | - 2:1 sector interleave pattern - except in tracks 0 and 1. |
| 15 | NOTE: PUTR tends to interleave loader tracks 0 + 1. Not recommended! |
| 16 | |
| 17 | Jeff's RBIMG is first choice for preservation, TeleDisk is second. |
| 18 | Always check the track layout. Both have problems with weak disks. |
| 19 | |
| 20 | A container to handle copy protected RX 50 disks is needed. Some info |
| 21 | can be derived from Mark Hittinger's RBACKUP (CP/M source from Nov-94). |
| 22 | |
| 23 | TODO: improve code to accept 40 T / single sided / 9 or 8 sector disks: |
| 24 | a) disks from VT180 (9 sectors; READ ONLY - enforced by BIOS) |
| 25 | |
| 26 | b) 8 sector 160k MS-DOS disks (READ + WRITE support on DEC) |
| 27 | FORMAT A: /F:160 on DOS; turn MEDIACHK ON |
| 28 | ************************************************************************/ |
| 29 | |
| 30 | #include "emu.h" |
| 31 | #include "flopimg.h" |
| 32 | #include "formats/rx50_dsk.h" |
| 33 | |
| 34 | // Controller: WD1793 |
| 35 | // TRACK LAYOUT IS UNVERIFED. SEE SOURCES: |
| 36 | // - 'esq_dsk16' (uses WD 1772) |
| 37 | // - SDC-RX50 Floppy Controller Manual |
| 38 | // - 'PC 100 SYSTEM SPEC' 4.3 - page 42. (*) |
| 39 | const floppy_image_format_t::desc_e rx50img_format::rx50_10_desc[] = { |
| 40 | { MFM, 0x4e, 80 }, // (*) GAP (1) |
| 41 | { MFM, 0x00, 12 }, // Value from (*). (?? = unverified) |
| 42 | { RAW, 0x5224, 3 }, |
| 43 | { MFM, 0xfc, 1 }, |
| 44 | { MFM, 0x4e, 50 }, |
| 45 | { MFM, 0x00, 12 }, |
| 46 | { SECTOR_LOOP_START, 0, 9 }, // 0 ... f.sector_count-1 |
| 47 | { CRC_CCITT_START, 1 }, |
| 48 | { RAW, 0x4489, 3 }, |
| 49 | { MFM, 0xfe, 1 }, |
| 50 | { TRACK_ID }, |
| 51 | { HEAD_ID }, |
| 52 | { SECTOR_ID }, |
| 53 | { SIZE_ID }, |
| 54 | { CRC_END, 1 }, |
| 55 | { CRC, 1 }, |
| 56 | { MFM, 0x4e, 22 }, // (*) POST-ID GAP (2) |
| 57 | { MFM, 0x00, 12 }, // (*) |
| 58 | { CRC_CCITT_START, 2 }, |
| 59 | { RAW, 0x4489, 3 }, |
| 60 | { MFM, 0xfb, 1 }, |
| 61 | { SECTOR_DATA, -1 }, |
| 62 | { CRC_END, 2 }, |
| 63 | { CRC, 2 }, |
| 64 | { MFM, 0x4e, 48 }, // GAP (3) - taken from RBACKUP source. |
| 65 | { MFM, 0x00, 12 }, |
| 66 | { SECTOR_LOOP_END }, |
| 67 | { MFM, 0x4e, 1 }, // UNVERIFIED - ('esq_16' has 170 x $4e) |
| 68 | { END } |
| 69 | }; |
| 70 | |
| 71 | rx50img_format::rx50img_format() |
| 72 | { |
| 73 | } |
| 74 | |
| 75 | const char *rx50img_format::name() const |
| 76 | { |
| 77 | return "img"; |
| 78 | } |
| 79 | |
| 80 | const char *rx50img_format::description() const |
| 81 | { |
| 82 | return "DEC Rainbow 100 floppy image"; |
| 83 | } |
| 84 | |
| 85 | const char *rx50img_format::extensions() const |
| 86 | { |
| 87 | return "img"; |
| 88 | } |
| 89 | |
| 90 | bool rx50img_format::supports_save() const |
| 91 | { |
| 92 | return true; |
| 93 | } |
| 94 | |
| 95 | void rx50img_format::find_size(io_generic *io, UINT8 &track_count, UINT8 &head_count, UINT8 §or_count) |
| 96 | { |
| 97 | head_count = 1; |
| 98 | |
| 99 | UINT32 expected_size = 0; |
| 100 | UINT64 size = io_generic_size(io); |
| 101 | |
| 102 | track_count = 80; |
| 103 | sector_count = 10; |
| 104 | expected_size = 512 * track_count * head_count * sector_count; |
| 105 | |
| 106 | if (size == expected_size) // standard format has 409600 byte |
| 107 | return; |
| 108 | /* |
| 109 | track_count = 40; |
| 110 | sector_count = 9; // [VT 180] |
| 111 | expected_size = 512 * track_count * head_count * sector_count; |
| 112 | if (size == expected_size) |
| 113 | return; |
| 114 | |
| 115 | track_count = 40; |
| 116 | sector_count = 8; // [DOS] |
| 117 | expected_size = 512 * track_count * head_count * sector_count; |
| 118 | if (size == expected_size) |
| 119 | return; |
| 120 | */ |
| 121 | track_count = head_count = sector_count = 0; |
| 122 | } |
| 123 | |
| 124 | int rx50img_format::identify(io_generic *io, UINT32 form_factor) |
| 125 | { |
| 126 | UINT8 track_count, head_count, sector_count; |
| 127 | find_size(io, track_count, head_count, sector_count); |
| 128 | |
| 129 | if(track_count) |
| 130 | return 50; |
| 131 | return 0; |
| 132 | } |
| 133 | |
| 134 | // /* Sectors are numbered 1 to 10 */ |
| 135 | bool rx50img_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) |
| 136 | { |
| 137 | UINT8 track_count, head_count, sector_count; |
| 138 | find_size(io, track_count, head_count, sector_count); |
| 139 | if(track_count == 0) |
| 140 | return false; |
| 141 | |
| 142 | UINT8 sectdata[10*512]; |
| 143 | desc_s sectors[10]; |
| 144 | for(int i=0; i<sector_count; i++) { |
| 145 | sectors[i].data = sectdata + 512*i; |
| 146 | sectors[i].size = 512; |
| 147 | sectors[i].sector_id = i + 1; // SECTOR_ID +1 <=== |
| 148 | } |
| 149 | |
| 150 | int track_size = sector_count*512; |
| 151 | for(int track=0; track < track_count; track++) { |
| 152 | for(int head=0; head < head_count; head++) { |
| 153 | io_generic_read(io, sectdata, (track*head_count + head)*track_size, track_size); |
| 154 | generate_track(rx50_10_desc, track, head, sectors, sector_count, 102064, image); // 98480 |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | image->set_variant(floppy_image::SSQD); |
| 159 | |
| 160 | return true; |
| 161 | } |
| 162 | |
| 163 | bool rx50img_format::save(io_generic *io, floppy_image *image) |
| 164 | { |
| 165 | int track_count, head_count, sector_count; |
| 166 | get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count); |
| 167 | |
| 168 | if(track_count != 80) |
| 169 | track_count = 80; |
| 170 | |
| 171 | // Happens for a fully unformatted floppy |
| 172 | if(!head_count) |
| 173 | head_count = 1; |
| 174 | |
| 175 | if(sector_count == 9) // [VT180] 9 sector format : no save! |
| 176 | return false; |
| 177 | |
| 178 | if(sector_count != 10) // either 8 or 10 sectors |
| 179 | sector_count = 10; // [STANDARD] |
| 180 | |
| 181 | /* |
| 182 | if(sector_count != 10) // either 8 or 10 sectors |
| 183 | { |
| 184 | if(sector_count == 8) |
| 185 | { |
| 186 | track_count = 40; // [DOS] |
| 187 | } else |
| 188 | { |
| 189 | sector_count = 10; // [STANDARD] |
| 190 | } |
| 191 | } |
| 192 | */ |
| 193 | UINT8 sectdata[11*512]; |
| 194 | int track_size = sector_count*512; |
| 195 | |
| 196 | for(int track=0; track < track_count; track++) { |
| 197 | for(int head=0; head < head_count; head++) { |
| 198 | get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata); |
| 199 | io_generic_write(io, sectdata, (track*head_count + head)*track_size, track_size); |
| 200 | } |
| 201 | } |
| 202 | return true; |
| 203 | } |
| 204 | |
| 205 | const floppy_format_type FLOPPY_RX50IMG_FORMAT = &floppy_image_format_creator<rx50img_format>; |
| 206 | |
| 207 | |
| 208 | /* |
| 209 | |
| 210 | // Native 400K format (80 T * 10 S * 512 bytes) on 'quad density' RX50 drives |
| 211 | // ( 5.25" single sided; 300 rpm; MFM 250 kbps; 96 - 100 tpi ). |
| 212 | // |
| 213 | // The BIOS can also * read * VT-180 disks and access MS-DOS 160 k disks (R + W) |
| 214 | // ( 40 tracks; single sided with 9 or 8 sectors per track ) |
| 215 | static LEGACY_FLOPPY_OPTIONS_START( dec100_floppy ) |
| 216 | LEGACY_FLOPPY_OPTION( dec100_floppy, "td0", "Teledisk floppy disk image", td0_dsk_identify, td0_dsk_construct, td0_dsk_destruct, NULL ) |
| 217 | LEGACY_FLOPPY_OPTION( dec100_floppy, "img", "DEC Rainbow 100", basicdsk_identify_default, basicdsk_construct_default, NULL, |
| 218 | HEADS([1]) |
| 219 | TRACKS(40/[80]) |
| 220 | SECTORS(8/9/[10]) |
| 221 | SECTOR_LENGTH([512]) |
| 222 | INTERLEAVE([0]) |
| 223 | FIRST_SECTOR_ID([1]) |
| 224 | ) |
| 225 | LEGACY_FLOPPY_OPTIONS_END |
| 226 | |
| 227 | */ |
| | No newline at end of file |
trunk/src/mess/drivers/rainbow.c
| r30901 | r30902 | |
| 4 | 4 | Driver-in-progress by R. Belmont and Miodrag Milanovic. |
| 5 | 5 | Portions (2013-2014) by Karl-Ludwig Deisenhofer (VT attributes, preliminary floppy, keyboard, DIP switches). |
| 6 | 6 | |
| 7 | | STATE AS OF APRIL 2014 |
| 8 | | ---------------------- |
| 7 | STATE AS OF JUNE 2014 |
| 8 | --------------------- |
| 9 | 9 | Driver is based entirely on the DEC-100 'B' variant (DEC-190 and DEC-100 A models are treated as clones). |
| 10 | 10 | While this is OK for the compatible -190, it doesn't do justice to ancient '100 A' hardware. |
| 11 | 11 | |
| 12 | | Currently, there are 2 showstoppers: |
| 13 | | (1) IRQ logic for 100-B needs further work (text in RBCONVERT.ZIP has details concerning -A versus -B) |
| 14 | | (2) Keyboard emulation incomplete (inhibits the system from booting with ERROR 50). |
| 12 | Currently, there are several issues here: |
| 13 | (1) Keyboard emulation incomplete (inhibits the system from booting with ERROR 50). |
| 14 | (2) after fixing (1), IRQ logic for 100-B should be verified (text in RBCONVERT.ZIP has details concerning -A versus -B. |
| 15 | DMA (needed for 'Extended communication option') or Z80-8088 arbitration is non-existent (E11/E13 dumps anyone?). |
| 16 | (3) Read errors when booting CP/M 2.x or DOS 2.x (secondary boot; read errors beyond T >= 2). |
| 17 | Seek (+ verify) and a number of signals (TRACK > 43 TG43, INDEX etc.) do not work (diag.disk aborts drive test). |
| 15 | 18 | |
| 16 | | - FLOPPY TIMING: 'wd17xx_complete_command' * must * be hard wired to about 13 usecs. |
| 17 | | Line 1063 in 'wd17xx.c' has to be changed (until legacy code here is removed): |
| 18 | | - w->timer_cmd->adjust(attotime::from_usec(usecs)); |
| 19 | | + w->timer_cmd->adjust(attotime::from_usec(13)); |
| 20 | | |
| 21 | 19 | - NOT WORKING: serial (ERROR 60). |
| 22 | 20 | - NOT WORKING: printer interface (ERROR 40). Like error 60 not mission-critical. |
| 23 | 21 | |
| 24 | | - NON-CRITICAL: watchdog logic ('MHFU' triggered after 108 ms without interrupts on original machine) does not work. |
| 22 | - NON-CRITICAL: watchdog logic (MHFU - triggered after 108 ms without interrupts on original machine) does not work. |
| 25 | 23 | The timer is reset by TWO sources: the VERT INT L from the DC012, or the MHFU ENB L from the enable flip-flop. |
| 26 | 24 | MHFU gets active if the 8088 has not acknowledged a video processor interrupt within approx. 108 milliseconds |
| 27 | 25 | |
| 28 | | - FIXME: warm boot triggers ERROR 16 (watchdog). BIOS assumes proper power-up only if MHFU detection is _disabled_ |
| 29 | | Apart from power-cycling, Ctrl-Setup (within SETUP) appears to be the only way to reboot the DEC-100. |
| 30 | | |
| 31 | 26 | - TO BE IMPLEMENTED AS SLOT DEVICES (for now, DIP settings affect 'system_parameter_r' only and are disabled): |
| 32 | 27 | * Color graphics option (uses NEC upd7220 GDC). REFERENCE: Programmer's Reference: AA-AE36A-TV. |
| 33 | 28 | 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. |
| 34 | 29 | |
| 35 | | * Extended communication option (1 of 4 possible BUNDLE_OPTIONs) REFERENCE: AA-V172A-TV + Addendum AV-Y890A-TV. |
| 30 | * Extended communication option (occupies BUNDLE_OPTION ports) REFERENCE: AA-V172A-TV + Addendum AV-Y890A-TV. |
| 36 | 31 | See also NEWCOM1.DOC in RBETECDOC.ZIP. Board connected to the front rightmost expansion slot (1 of the expansion |
| 37 | 32 | ports used by the hard disk controller). Thus can't be added to a system that includes the DEC RD50/51. |
| 38 | 33 | => 2 ports, a high-speed RS-422 half-duplex interface (port A) + lower-speed RS-423 full/half-duplex interface |
| r30901 | r30902 | |
| 47 | 42 | Daughterboard, to be plugged into the expansion port where the memory expansion card usually sits. |
| 48 | 43 | If a memory adapter board is present, it has to be plugged into a connector atop the 8087 copro board. |
| 49 | 44 | The 8088 is put into the CPU socket on the coprocessor board. |
| 45 | => see MATH test on 'Design Maturity Diagnostics' disk <= |
| 50 | 46 | |
| 51 | 47 | * 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 ) |
| 52 | | 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'. |
| 48 | 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'. |
| 53 | 49 | |
| 54 | 50 | * NEC_V20 (requires modded BOOT ROM because of - at least 2 - hard coded timing loops): |
| 55 | 51 | 100A: 100B/100+: 100B+ ALTERNATE RECOMMENDATION (fixes RAM size auto-detection problems when V20 is in place. |
| r30901 | r30902 | |
| 69 | 65 | Hard coded CPU loops are to blame. Try values from the alternate patch (right). |
| 70 | 66 | => AAD/AAM - Intel 8088 honors the second byte (operand), NEC V20 ignores it and always uses base 0Ah (10). |
| 71 | 67 | => 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) |
| 72 | | Commercial programs had to be patched back then (as was the case with Loderunner for PC). |
| 73 | 68 | => NEW OPCODES: REPC, REPNC, CHKIND, PREPARE, DISPOSE; BCD string operations (ADD4S, CMP4S, SUB4S), bit-ops (NOT, SET, TEST, ROL4, ROR4) |
| 74 | 69 | WARNING: undoc'd opcodes, INS, EXT and 8080 behaviour are unemulated yet! MESS' CPU source has up-to-date info. |
| 75 | 70 | |
| r30901 | r30902 | |
| 180 | 175 | ****************************************************************************/ |
| 181 | 176 | |
| 182 | 177 | // Define standard and maximum RAM sizes (A, then B model): |
| 183 | | //#define BOARD_RAM 0x10000 // 64 K base RAM (100-A) |
| 178 | //#define BOARD_RAM 0x0ffff // 64 K base RAM (100-A) |
| 184 | 179 | //#define END_OF_RAM 0xcffff // very last byte (100-A) DO NOT CHANGE. |
| 185 | 180 | |
| 186 | 181 | // DEC-100-B probes until a 'flaky' area is found (BOOT ROM around F400:0E04). |
| 187 | 182 | // It is no longer possible to key in the RAM size from within the 100-B BIOS. |
| 188 | | #define BOARD_RAM 0x20000 // 128 K base RAM (100-B) |
| 183 | #define BOARD_RAM 0x1ffff // 128 K base RAM (100-B) |
| 189 | 184 | #define END_OF_RAM 0xdffff // very last byte (100-B) DO NOT CHANGE. |
| 190 | 185 | |
| 191 | 186 | // TROUBLESHOOTING RAM |
| r30901 | r30902 | |
| 194 | 189 | // can be narrowed down with the Diagnostic Disk and codes from the 'Pocket Service Guide' |
| 195 | 190 | // EK-PC100-PS-002 (APPENDIX B.2.2); pc100ps2.pdf |
| 196 | 191 | |
| 197 | | |
| 198 | | // Workaround not valid for 100-A - |
| 192 | // WORKAROUNDS: |
| 193 | // (1) FORCE LOGO: - not valid for 100-A ROM - |
| 199 | 194 | //#define FORCE_RAINBOW_B_LOGO |
| 195 | // (2) KEYBOARD_WORKAROUND : also requires FORCE...LOGO ! |
| 196 | //#define KEYBOARD_WORKAROUND |
| 197 | //#define KBD_DELAY 8500 |
| 200 | 198 | |
| 199 | // ---------------------------------------------------------------------------------------------- |
| 201 | 200 | #include "emu.h" |
| 202 | 201 | #include "cpu/i86/i86.h" |
| 203 | 202 | #include "cpu/z80/z80.h" |
| 204 | 203 | #include "video/vtvideo.h" |
| 205 | 204 | |
| 206 | | #include "machine/wd17xx.h" |
| 207 | | #include "imagedev/flopdrv.h" |
| 208 | | #include "formats/basicdsk.h" |
| 205 | #include "machine/wd_fdc.h" |
| 206 | #include "formats/rx50_dsk.h" |
| 207 | #include "imagedev/flopdrv.h" |
| 209 | 208 | |
| 210 | 209 | #include "machine/i8251.h" |
| 211 | 210 | #include "machine/clock.h" |
| r30901 | r30902 | |
| 215 | 214 | #include "rainbow.lh" // BEZEL - LAYOUT with LEDs for diag 1-7, keyboard 8-11 and floppy 20-23 |
| 216 | 215 | |
| 217 | 216 | #define LK201_TAG "lk201" |
| 217 | #define FD1793_TAG "fd1793x" |
| 218 | #define INVALID_DRIVE 255 |
| 218 | 219 | |
| 219 | 220 | class rainbow_state : public driver_device |
| 220 | 221 | { |
| 221 | 222 | public: |
| 222 | 223 | rainbow_state(const machine_config &mconfig, device_type type, const char *tag) : |
| 223 | 224 | driver_device(mconfig, type, tag), |
| 225 | #ifdef KEYBOARD_WORKAROUND |
| 226 | #include "m_kbd1.c" // KEYBOARD_WORKAROUND |
| 227 | #endif |
| 224 | 228 | m_inp1(*this, "W13"), |
| 225 | 229 | m_inp2(*this, "W14"), |
| 226 | 230 | m_inp3(*this, "W15"), |
| r30901 | r30902 | |
| 235 | 239 | m_crtc(*this, "vt100_video"), |
| 236 | 240 | m_i8088(*this, "maincpu"), |
| 237 | 241 | m_z80(*this, "subcpu"), |
| 238 | | m_fdc(*this, "wd1793"), |
| 242 | m_fdc(*this, FD1793_TAG), |
| 239 | 243 | m_kbd8251(*this, "kbdser"), |
| 240 | 244 | m_lk201(*this, LK201_TAG), |
| 241 | 245 | m_p_ram(*this, "p_ram"), |
| r30901 | r30902 | |
| 283 | 287 | |
| 284 | 288 | DECLARE_WRITE_LINE_MEMBER(irq_hi_w); |
| 285 | 289 | |
| 290 | #ifdef KEYBOARD_WORKAROUND |
| 291 | #include "port9x_Ax.c" // KEYBOARD_WORKAROUND |
| 292 | #endif |
| 286 | 293 | UINT32 screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 287 | 294 | INTERRUPT_GEN_MEMBER(vblank_irq); |
| 288 | 295 | DECLARE_WRITE_LINE_MEMBER(write_keyboard_clock); |
| 289 | 296 | TIMER_DEVICE_CALLBACK_MEMBER(motor_tick); |
| 290 | 297 | |
| 298 | DECLARE_FLOPPY_FORMATS( floppy_formats ); |
| 291 | 299 | protected: |
| 292 | 300 | virtual void machine_start(); |
| 293 | 301 | |
| r30901 | r30902 | |
| 305 | 313 | IRQ_8088_MAX |
| 306 | 314 | }; |
| 307 | 315 | |
| 316 | #ifdef KEYBOARD_WORKAROUND |
| 317 | #include "m_kbd2.c" // KEYBOARD_WORKAROUND |
| 318 | #endif |
| 308 | 319 | required_ioport m_inp1; |
| 309 | 320 | required_ioport m_inp2; |
| 310 | 321 | required_ioport m_inp3; |
| r30901 | r30902 | |
| 315 | 326 | required_ioport m_inp8; |
| 316 | 327 | required_ioport m_inp9; |
| 317 | 328 | required_ioport m_inp10; |
| 318 | | |
| 319 | 329 | required_device<rainbow_video_device> m_crtc; |
| 320 | 330 | required_device<cpu_device> m_i8088; |
| 321 | 331 | required_device<cpu_device> m_z80; |
| 322 | | required_device<fd1793_device> m_fdc; |
| 332 | required_device<fd1793_t> m_fdc; |
| 323 | 333 | required_device<i8251_device> m_kbd8251; |
| 324 | 334 | required_device<lk201_device> m_lk201; |
| 325 | 335 | required_shared_ptr<UINT8> m_p_ram; |
| r30901 | r30902 | |
| 356 | 366 | virtual void machine_reset(); |
| 357 | 367 | |
| 358 | 368 | int m_unit; |
| 359 | | legacy_floppy_image_device *m_image[4]; |
| 369 | floppy_image_device *m_floppy; |
| 360 | 370 | |
| 361 | 371 | int m_irq_high; |
| 362 | 372 | UINT32 m_irq_mask; |
| 363 | 373 | }; |
| 364 | 374 | |
| 375 | FLOPPY_FORMATS_MEMBER( rainbow_state::floppy_formats ) |
| 376 | FLOPPY_TD0_FORMAT, |
| 377 | FLOPPY_RX50IMG_FORMAT |
| 378 | FLOPPY_FORMATS_END |
| 365 | 379 | |
| 380 | static SLOT_INTERFACE_START( rainbow_floppies ) |
| 381 | SLOT_INTERFACE( "525qd", FLOPPY_525_SSQD ) // "525ssdd" |
| 382 | SLOT_INTERFACE_END |
| 383 | |
| 384 | |
| 366 | 385 | void rainbow_state::machine_start() |
| 367 | 386 | { |
| 368 | | m_image[0] = subdevice<legacy_floppy_image_device>(FLOPPY_0); |
| 369 | | m_image[1] = subdevice<legacy_floppy_image_device>(FLOPPY_1); |
| 370 | | m_image[2] = subdevice<legacy_floppy_image_device>(FLOPPY_2); |
| 371 | | m_image[3] = subdevice<legacy_floppy_image_device>(FLOPPY_3); |
| 372 | | |
| 387 | MOTOR_DISABLE_counter = 2; // soon resets drv.LEDs |
| 373 | 388 | COLD_BOOT = 1; |
| 374 | 389 | |
| 375 | 390 | m_SCREEN_BLANK = false; |
| r30901 | r30902 | |
| 386 | 401 | #ifdef FORCE_RAINBOW_B_LOGO |
| 387 | 402 | UINT8 *rom = memregion("maincpu")->base(); |
| 388 | 403 | |
| 404 | rom[0xf4000 + 0x364a]= 2 + 8; // 2 :set ; 4 : reset, 8 : set for 0xf4363 ( 0363 WAIT_FOR_BIT3__loc_35E ) |
| 405 | |
| 406 | rom[0xf4000 + 0x0363]= 0x90; |
| 407 | rom[0xf4000 + 0x0364]= 0x90; |
| 408 | |
| 409 | // If bit 2 = 1 (Efff9), then a keyboard powerup is necessary (=> will lock up in current state) |
| 410 | rom[0xf4000 + 0x3638]= 0x80; // OR instead of TEST |
| 411 | rom[0xf4000 + 0x3639]= 0x0f; // OR instead of TEST |
| 412 | rom[0xf4000 + 0x363a]= 0x08; // 04 => 08 |
| 413 | |
| 414 | rom[0xf4000 + 0x363b]= 0xeb; // COND => JMPS |
| 415 | |
| 389 | 416 | if (rom[0xf4174] == 0x75) |
| 390 | 417 | { rom[0xf4174] = 0xeb; // jmps RAINBOW100_LOGO__loc_33D |
| 391 | 418 | rom[0xf4175] = 0x08; |
| r30901 | r30902 | |
| 398 | 425 | rom[0xf437b] = 0xeb; |
| 399 | 426 | #endif |
| 400 | 427 | |
| 428 | #ifdef KEYBOARD_WORKAROUND |
| 429 | #include "rainbow_keyboard0.c" |
| 430 | #endif |
| 401 | 431 | } |
| 402 | 432 | |
| 403 | 433 | static ADDRESS_MAP_START( rainbow8088_map, AS_PROGRAM, 8, rainbow_state) |
| r30901 | r30902 | |
| 447 | 477 | AM_RANGE(0x11, 0x11) AM_DEVREADWRITE("kbdser", i8251_device, status_r, control_w) |
| 448 | 478 | |
| 449 | 479 | // UNMAPPED: |
| 450 | | // 0x20 - 0x2f ***** EXTENDED COMM. OPTION (option select 1) |
| 451 | | // 0x27 (RESET EXTENDED COMM OPTION - - see boot ROM @1EA6) |
| 480 | // 0x20 -> 0x2f ***** EXTENDED COMM. OPTION / Option Select 1. |
| 481 | // See boot rom @1EA6: 0x27 (<- RESET EXTENDED COMM OPTION ) |
| 452 | 482 | // =========================================================== |
| 483 | // 0x30 -> 0x3f ***** EXTENDED COMM. OPTION / Option Select 3. |
| 484 | // =========================================================== |
| 453 | 485 | // 0x40 COMMUNICATIONS DATA REGISTER (MPSC) |
| 454 | 486 | // 0x41 PRINTER DATA REGISTER (MPSC) |
| 455 | 487 | // 0x42 COMMUNICATIONS CONTROL / STATUS REGISTER (MPSC) |
| r30901 | r30902 | |
| 477 | 509 | // 56h Data written to this port is loaded into the GDC's FIFO |
| 478 | 510 | // Buffer and flagged as a parameter. |
| 479 | 511 | // =========================================================== |
| 512 | // 0x60 -> 0x6f ***** EXTENDED COMM. OPTION / Option Select 2. |
| 513 | // =========================================================== |
| 480 | 514 | // TODO: hard disc emulation! |
| 481 | 515 | // ------ Rainbow uses 'WD 1010 AL' (Western Digital 1983) |
| 482 | 516 | // Register compatible to WD2010 (present in MESS) |
| r30901 | r30902 | |
| 492 | 526 | // SOFTWARE: |
| 493 | 527 | // - MS-DOS 2 allows a maximum partition size of 16 MB (sizes > 15 MB are incompatible to DOS 3) |
| 494 | 528 | // - MS-DOS 3 has a global 1024 cylinder limit (32 MB). |
| 529 | // =========================================================== |
| 530 | // 0x70 -> 0x7f ***** EXTENDED COMM. OPTION / Option Select 4. |
| 531 | // =========================================================== |
| 532 | #ifdef KEYBOARD_WORKAROUND |
| 533 | #include "am_range_9x_Ax.c" // KEYBOARD_WORKAROUND |
| 534 | #endif |
| 495 | 535 | ADDRESS_MAP_END |
| 496 | 536 | |
| 497 | 537 | static ADDRESS_MAP_START(rainbowz80_mem, AS_PROGRAM, 8, rainbow_state) |
| r30901 | r30902 | |
| 506 | 546 | 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. |
| 507 | 547 | AM_RANGE(0x21, 0x21) AM_READWRITE(z80_generalstat_r, z80_diskdiag_write_w) |
| 508 | 548 | AM_RANGE(0x40, 0x40) AM_READWRITE(z80_diskstatus_r, z80_diskcontrol_w) |
| 509 | | AM_RANGE(0x60, 0x60) AM_DEVREADWRITE("wd1793", fd1793_device ,status_r, command_w) |
| 510 | | AM_RANGE(0x61, 0x61) AM_DEVREADWRITE("wd1793", fd1793_device, track_r, track_w) |
| 511 | | AM_RANGE(0x62, 0x62) AM_DEVREADWRITE("wd1793", fd1793_device, sector_r, sector_w) |
| 512 | | AM_RANGE(0x63, 0x63) AM_DEVREADWRITE("wd1793", fd1793_device, data_r, data_w) |
| 549 | AM_RANGE(0x60, 0x63) AM_DEVREADWRITE(FD1793_TAG, fd1793_t, read, write) |
| 513 | 550 | ADDRESS_MAP_END |
| 514 | 551 | |
| 515 | 552 | /* Input ports */ |
| 516 | 553 | |
| 517 | 554 | /* DIP switches */ |
| 518 | 555 | static INPUT_PORTS_START( rainbow100b_in ) |
| 556 | |
| 557 | #ifdef KEYBOARD_WORKAROUND |
| 558 | #include "rainbow_ipt.c" |
| 559 | #endif |
| 519 | 560 | PORT_START("MONITOR TYPE") |
| 520 | 561 | PORT_DIPNAME( 0x03, 0x03, "MONOCHROME MONITOR") |
| 521 | 562 | PORT_DIPSETTING( 0x01, "PAPER WHITE" ) |
| r30901 | r30902 | |
| 545 | 586 | PORT_DIPNAME( 0x01, 0x01, "FLOPPY CONTROLLER") PORT_TOGGLE |
| 546 | 587 | PORT_DIPSETTING( 0x01, DEF_STR( On ) ) |
| 547 | 588 | |
| 548 | | // BUNDLE_OPTION: COMM.card or hard disc controller extension (marketed later). |
| 549 | | // NOTES: - hard disc and COMM.extension exclude each other. |
| 550 | | // - connector J4 has 4 select lines. Select option 1 = COMM CARD ? |
| 589 | // BUNDLE_OPTION: EXT.COMM.card -or- hard disk controller (marketed later). |
| 590 | // - hard disc and COMM.extension exclude each other! |
| 591 | // - connector J4 has 4 select lines (Option Select 1-4) |
| 551 | 592 | PORT_START("BUNDLE OPTION") |
| 552 | 593 | PORT_DIPNAME( 0x00, 0x00, "BUNDLE OPTION") PORT_TOGGLE |
| 553 | 594 | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| r30901 | r30902 | |
| 586 | 627 | PORT_DIPSETTING( 0x02, DEF_STR( On ) ) |
| 587 | 628 | INPUT_PORTS_END |
| 588 | 629 | |
| 589 | | // Native 400K format (80 T * 10 S * 512 bytes) on 'quad density' RX50 drives |
| 590 | | // ( 5.25" single sided; 300 rpm; MFM 250 kbps; 96 - 100 tpi ). |
| 591 | | // |
| 592 | | // Additionally, the BIOS can *read* VT-180 disks and MS-DOS 160 k disks |
| 593 | | // - MS-DOS: FORMAT A: /F:160 and MEDIACHK ON |
| 594 | | // ( 40 tracks; single sided with 9 or 8 sectors per track ) |
| 595 | | static LEGACY_FLOPPY_OPTIONS_START( dec100_floppy ) |
| 596 | | LEGACY_FLOPPY_OPTION( dec100_floppy, "td0", "Teledisk floppy disk image", td0_dsk_identify, td0_dsk_construct, td0_dsk_destruct, NULL ) |
| 597 | | LEGACY_FLOPPY_OPTION( dec100_floppy, "img", "DEC Rainbow 100", basicdsk_identify_default, basicdsk_construct_default, NULL, |
| 598 | | HEADS([1]) |
| 599 | | TRACKS(40/[80]) |
| 600 | | SECTORS(8/9/[10]) |
| 601 | | SECTOR_LENGTH([512]) |
| 602 | | INTERLEAVE([0]) |
| 603 | | FIRST_SECTOR_ID([1]) |
| 604 | | ) |
| 605 | | LEGACY_FLOPPY_OPTIONS_END |
| 606 | 630 | |
| 607 | 631 | void rainbow_state::machine_reset() |
| 608 | 632 | { |
| 633 | m_unit = INVALID_DRIVE; |
| 634 | |
| 635 | m_fdc->reset(); |
| 636 | m_fdc->set_floppy(NULL); |
| 637 | m_fdc->dden_w(0); |
| 638 | //m_fdc->set_force_ready(false); |
| 639 | |
| 609 | 640 | /* configure RAM */ |
| 610 | 641 | address_space &program = m_maincpu->space(AS_PROGRAM); |
| 611 | 642 | if (m_inp8->read() < END_OF_RAM) |
| 612 | 643 | { program.unmap_readwrite(m_inp8->read(), END_OF_RAM); |
| 613 | 644 | } |
| 614 | 645 | |
| 615 | | if (COLD_BOOT == 1) |
| 646 | // BIOS can't handle soft resets (=> triggers ERROR 16). |
| 647 | if ( COLD_BOOT == 2 ) |
| 648 | { // As a fallback, execute a hard reboot - |
| 649 | device().machine().schedule_hard_reset(); |
| 650 | } |
| 651 | |
| 652 | if ( (COLD_BOOT == 1) ) |
| 616 | 653 | { |
| 617 | 654 | COLD_BOOT = 2; |
| 618 | 655 | m_crtc->MHFU(-100); // reset MHFU counter |
| r30901 | r30902 | |
| 647 | 684 | output_set_value("led_lock", 0); // led10 |
| 648 | 685 | output_set_value("led_hold", 0); // led11 |
| 649 | 686 | |
| 650 | | MOTOR_DISABLE_counter = 2; // soon resets drv.LEDs |
| 651 | | m_unit = 0; |
| 652 | 687 | m_irq_mask = 0; |
| 688 | |
| 689 | |
| 653 | 690 | } |
| 654 | 691 | |
| 692 | #ifdef KEYBOARD_WORKAROUND |
| 693 | #include "rainbow_keyboard2.c" |
| 694 | #endif |
| 695 | |
| 655 | 696 | UINT32 rainbow_state::screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 656 | 697 | { |
| 657 | | // TEST-DEBUG: no screen updates during diskette operations! |
| 658 | 698 | if (MOTOR_DISABLE_counter) |
| 659 | 699 | return 0; |
| 660 | 700 | |
| r30901 | r30902 | |
| 780 | 820 | return ( ((m_inp5->read() == 1) ? 0 : 1) | |
| 781 | 821 | ((m_inp6->read() == 1) ? 0 : 2) | |
| 782 | 822 | ((m_inp7->read() == 1) ? 0 : 4) | |
| 783 | | ((m_inp8->read() > BOARD_RAM) ? 0 : 8) | |
| 823 | ((m_inp8->read() > BOARD_RAM) ? 0 : 8) | |
| 784 | 824 | 16 | 32 | 64 | 128 // to be verified. |
| 785 | 825 | ); |
| 786 | 826 | } |
| r30901 | r30902 | |
| 799 | 839 | int data; |
| 800 | 840 | if (COLD_BOOT == 2) |
| 801 | 841 | data = 0; |
| 802 | | else |
| 842 | else |
| 803 | 843 | data = m_crtc->MHFU(1); |
| 804 | | |
| 844 | |
| 805 | 845 | return ( ( (data > 0) ? 0x00 : 0x20) |// (L): status of MHFU flag => bit pos.5 |
| 806 | 846 | ( (INT88) ? 0x00 : 0x40 ) | // (L) |
| 807 | 847 | ( (INTZ80) ? 0x00 : 0x80 ) // (L) |
| r30901 | r30902 | |
| 891 | 931 | D2 : INT88 L: (bit reads the INT88 bit sent by Z80 to interrupt 8088) |
| 892 | 932 | D1 : INTZ80 L: (bit reads the INTZ80 bit sent by 8088 to interrupt Z80) |
| 893 | 933 | D0 : ZFLIP L: (read from the diagnostic control register of Z80A) |
| 894 | | |
| 895 | | NOTES: ALL LOW ACTIVE - EXCEPT TR00 |
| 896 | 934 | */ |
| 897 | | // * TRACK 00 * signal for current drive |
| 898 | | int tk00 = ( m_image[m_unit]->floppy_tk00_r() == CLEAR_LINE ) ? 0x20 : 0x00; |
| 935 | static int last_track; |
| 936 | int track = m_fdc->track_r( space, 0); |
| 937 | int fdc_step = 0; |
| 938 | int fdc_ready = 0; |
| 939 | int tk00 = 0; |
| 899 | 940 | |
| 900 | | int fdc_ready = m_image[m_unit]->floppy_drive_get_flag_state( FLOPPY_DRIVE_READY); |
| 941 | if(m_unit != INVALID_DRIVE) |
| 942 | { |
| 943 | if (track != last_track) |
| 944 | fdc_step = 1; |
| 945 | last_track = track; |
| 901 | 946 | |
| 902 | | int data=( 0x80 | // (STEP L) |
| 903 | | // ( (fdc_write_gate) ) | |
| 904 | | ( (tk00) ) | |
| 905 | | // ( fdc_direction) | |
| 906 | | ( (fdc_ready)? 0x00 : 0x08 ) | |
| 947 | fdc_ready = m_floppy->ready_r(); |
| 948 | tk00 = ( m_floppy->trk00_r() != CLEAR_LINE ); |
| 949 | } |
| 950 | |
| 951 | int last_dir = 0; // FAKE LAST_DIR + WRITE_GATE FOR NOW. |
| 952 | int fdc_write_gate = 1; |
| 953 | |
| 954 | // ***** ALL LOW ACTIVE - EXCEPT tk00 : |
| 955 | int data=( |
| 956 | ( (fdc_step) ? 0x00 : 0x80 ) | |
| 957 | ( (fdc_write_gate == 1) ? 0x00 : 0x40 ) | |
| 958 | ( (tk00) ? 0x20 : 0x00 ) | |
| 959 | ( (last_dir == 1) ? 0x00 : 0x10 ) | |
| 960 | ( (fdc_ready) ? 0x00 : 0x08 ) | |
| 907 | 961 | ( (INT88) ? 0x00 : 0x04 ) | |
| 908 | 962 | ( (INTZ80) ? 0x00 : 0x02 ) | |
| 909 | 963 | ( (m_zflip) ? 0x00 : 0x01 ) |
| r30901 | r30902 | |
| 963 | 1017 | // D3: MOTOR 0 ON L: 0 = indicates MOTOR 0 ON bit is set in drive " |
| 964 | 1018 | |
| 965 | 1019 | // D2: TG43 L : 0 = INDICATES TRACK > 43 SIGNAL FROM FDC TO DISK DRIVE. |
| 966 | | data |= ( track > 43) ? 0x00 : 0x04; |
| 1020 | if ( track > 43) |
| 1021 | data = data & (255 - 4); |
| 1022 | else |
| 1023 | data = data | 4; |
| 967 | 1024 | |
| 968 | 1025 | // D1: DS1 H: reflect status of bits 0 and 1 form disk.control reg. |
| 969 | 1026 | // D0: DS0 H: " |
| r30901 | r30902 | |
| 971 | 1028 | } |
| 972 | 1029 | |
| 973 | 1030 | // (Z80) : PORT 40H * WRITE * |
| 974 | | |
| 975 | 1031 | // RX-50 has head A and head B (1 for each of the 2 disk slots in a RX-50). |
| 976 | | |
| 977 | 1032 | // TODO: find out how head load and drive select really work. |
| 978 | 1033 | WRITE8_MEMBER(rainbow_state::z80_diskcontrol_w) |
| 979 | 1034 | { |
| 980 | 1035 | // FORCE_READY = 0 : assert DRIVE READY on FDC (diagnostic override; USED BY BIOS!) |
| 981 | | // 1 : set ready only if drive is present, disk is in the drive, |
| 982 | | // and disk motor is on - for Amstrad, Spectrum, PCW... |
| 983 | | int force_ready = ( (data & 4) != 0 ) ? 0 : 1; |
| 1036 | //bool force_ready = ( (data & 4) == 0 ) ? true : false; |
| 984 | 1037 | |
| 985 | 1038 | int drive; |
| 986 | 1039 | if ( m_inp10->read() && ((data & 3) < 2) ) |
| r30901 | r30902 | |
| 988 | 1041 | else |
| 989 | 1042 | drive = data & 3; |
| 990 | 1043 | |
| 991 | | int selected_drive = 255; |
| 1044 | int selected_drive = INVALID_DRIVE; |
| 1045 | static const char *names[] = { FD1793_TAG ":0", FD1793_TAG ":1", FD1793_TAG ":2", FD1793_TAG ":3" }; |
| 992 | 1046 | |
| 993 | | if (floppy_get_device( machine(), drive )->flopimg_get_image() != NULL) |
| 994 | | { selected_drive = drive; |
| 995 | | m_fdc->set_drive(selected_drive); |
| 996 | | } |
| 1047 | floppy_connector *con = machine().device<floppy_connector>(names[drive]); |
| 1048 | if (con) |
| 1049 | { m_floppy = con->get_device(); |
| 1050 | if (m_floppy) |
| 1051 | { |
| 1052 | selected_drive = drive; |
| 997 | 1053 | |
| 998 | | // WD emulation (wd17xx.c) will ignore 'side select' if set to WD1793. |
| 999 | | // Is it safe to * always assume * single sided 400 K disks? |
| 1000 | | m_fdc->set_side((data & 20) ? 1 : 0); |
| 1054 | m_fdc->set_floppy(m_floppy); // Sets new _image device_ |
| 1055 | m_floppy->set_rpm(300.); |
| 1001 | 1056 | |
| 1002 | | m_fdc->dden_w(0); /* SEE 'WRITE_TRACK' : 1 = SD; 0 = DD; enable double density */ |
| 1057 | // RX50 board has additional 'side select' - ignored by WD emulation? |
| 1058 | m_floppy->ss_w((data & 20) ? 1 : 0); |
| 1059 | } |
| 1060 | } |
| 1003 | 1061 | |
| 1004 | 1062 | output_set_value("driveled0", (selected_drive == 0) ? 1 : 0 ); |
| 1005 | 1063 | output_set_value("driveled1", (selected_drive == 1) ? 1 : 0 ); |
| r30901 | r30902 | |
| 1011 | 1069 | { |
| 1012 | 1070 | m_unit = selected_drive; |
| 1013 | 1071 | |
| 1014 | | // MOTOR ON flags 1+2 proved to be unreliable in this context. |
| 1015 | | // So this timeout only disables LEDs. |
| 1016 | | MOTOR_DISABLE_counter = 10000; // prolonged timeout. DEFAULT: 2400 = 500 ms |
| 1072 | if (MOTOR_DISABLE_counter == 0) // "one shot" |
| 1073 | MOTOR_DISABLE_counter = 4800; // 2400 = 500 ms |
| 1017 | 1074 | |
| 1075 | // m_fdc->set_force_ready(force_ready); |
| 1076 | } else |
| 1077 | { |
| 1078 | // m_fdc->set_force_ready(false); |
| 1079 | } |
| 1080 | |
| 1018 | 1081 | for(int f_num=0; f_num <= 3; f_num++) |
| 1019 | 1082 | { |
| 1020 | | // Although 1773 does not feature 'motor on' this statement is required: |
| 1021 | | // CLEAR_LINE = turn motor on - |
| 1022 | | m_image[f_num]->floppy_mon_w((f_num == selected_drive) ? CLEAR_LINE : ASSERT_LINE); |
| 1083 | floppy_connector *con = machine().device<floppy_connector>(names[f_num]); |
| 1084 | floppy_image_device *tmp_floppy = con->get_device(); |
| 1085 | tmp_floppy->mon_w( (f_num == m_unit) ? CLEAR_LINE : ASSERT_LINE ); |
| 1086 | } |
| 1023 | 1087 | |
| 1024 | | // Parameters: DRIVE, STATE, FLAG |
| 1025 | | m_image[f_num]->floppy_drive_set_ready_state( |
| 1026 | | (f_num == selected_drive) ? 1 : 0, |
| 1027 | | (f_num == selected_drive) ? force_ready : 0 |
| 1028 | | ); |
| 1088 | if(m_unit == INVALID_DRIVE) |
| 1089 | { |
| 1090 | data = data & (255 -3); |
| 1091 | data = data | 8; // MOTOR 0 OFF |
| 1092 | data = data | 16; // MOTOR 1 OFF |
| 1093 | }else |
| 1094 | { data = ( data & (255 -3) ) | m_unit; |
| 1095 | |
| 1096 | if(m_unit < 2) |
| 1097 | data = data & (255 - 8); // MOTOR 0 (for A or B) |
| 1098 | |
| 1099 | if(m_unit > 1) |
| 1100 | data = data & (255 - 16); // MOTOR 1 (for C or D) |
| 1029 | 1101 | } |
| 1030 | | } |
| 1031 | | |
| 1032 | 1102 | m_z80_diskcontrol = data; |
| 1033 | 1103 | } |
| 1034 | 1104 | |
| r30901 | r30902 | |
| 1065 | 1135 | // printf("%02x to diag port (PC=%x)\n", data, space.device().safe_pc()); |
| 1066 | 1136 | m_SCREEN_BLANK = (data & 2) ? false : true; |
| 1067 | 1137 | |
| 1068 | | // SAVE / PROGRAM NVM: transfer data from volatile memory to NVM |
| 1069 | | if ( !(data & 0x40) && (m_diagnostic & 0x40) ) |
| 1070 | | memcpy( m_p_nvram, m_p_vol_ram, 256); |
| 1071 | 1138 | |
| 1072 | | // READ / RECALL NVM: transfer data from NVM to volatile memory |
| 1073 | | if ( (data & 0x80) && !(m_diagnostic & 0x80) ) |
| 1074 | | memcpy( m_p_vol_ram, m_p_nvram, 256); |
| 1075 | | |
| 1076 | 1139 | if (!(data & 1)) |
| 1077 | 1140 | { |
| 1078 | 1141 | m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| r30901 | r30902 | |
| 1087 | 1150 | m_z80->reset(); |
| 1088 | 1151 | } |
| 1089 | 1152 | |
| 1090 | | /* Page 197 or 5-13 of formatter description: |
| 1091 | | ZRESET L : this low input from the 8088 diagnostic write register |
| 1092 | | resets the formatter controller, loads 03H into the command register, |
| 1093 | | and resets the not ready (status bit 7). |
| 1153 | if(m_unit != INVALID_DRIVE) |
| 1154 | { |
| 1155 | if ( (m_diagnostic & 1) && !(data & 1) ) |
| 1156 | { |
| 1157 | m_fdc->soft_reset(); |
| 1158 | } |
| 1094 | 1159 | |
| 1095 | | When ZRESET goes high (1), a restore command is executed regardless |
| 1096 | | of the state of the ready signal from the diskette drive and |
| 1097 | | 01H is loaded into the sector register. |
| 1098 | | */ |
| 1160 | if ( !(m_diagnostic & 1) && (data & 1) ) |
| 1161 | { |
| 1162 | m_fdc->soft_reset(); // See formatter description p.197 or 5-13 |
| 1163 | } |
| 1164 | } |
| 1165 | // MISSING BITS (* not vital for normal operation, see diag.disk) - |
| 1166 | // BIT 2: GRF VID SEL (0 = system module; 1 = graphics option) |
| 1167 | // BIT 3: PARITY TEST (1 = enables parity test on memory option board) |
| 1168 | // * BIT 4: DIAG LOOPBACK (0 at power-up; 1 directs RX50 and DC12 output to printer port) |
| 1169 | // * BIT 5: PORT LOOPBACK (1 enables loopback for COMM, PRINTER, KEYBOARD ports) |
| 1099 | 1170 | |
| 1100 | | // reset device when going from high to low, |
| 1101 | | // restore command when going from low to high : |
| 1102 | | m_fdc->mr_w((data & 1) ? 1 : 0); |
| 1171 | // BIT 6: Transfer data from volatile memory to NVM |
| 1172 | if ( !(data & 0x40) && (m_diagnostic & 0x40) ) |
| 1173 | memcpy( m_p_nvram, m_p_vol_ram, 256); |
| 1174 | |
| 1175 | // BIT 7: Transfer data from NVM to volatile memory |
| 1176 | if ( (data & 0x80) && !(m_diagnostic & 0x80) ) |
| 1177 | memcpy( m_p_vol_ram, m_p_nvram, 256); |
| 1178 | |
| 1103 | 1179 | m_diagnostic = data; |
| 1104 | 1180 | } |
| 1105 | 1181 | |
| r30901 | r30902 | |
| 1107 | 1183 | // KEYBOARD |
| 1108 | 1184 | void rainbow_state::update_kbd_irq() |
| 1109 | 1185 | { |
| 1186 | #ifndef KEYBOARD_WORKAROUND |
| 1110 | 1187 | if ((m_kbd_rx_ready) || (m_kbd_tx_ready)) |
| 1111 | 1188 | { |
| 1112 | 1189 | raise_8088_irq(IRQ_8088_KBD); |
| r30901 | r30902 | |
| 1115 | 1192 | { |
| 1116 | 1193 | lower_8088_irq(IRQ_8088_KBD); |
| 1117 | 1194 | } |
| 1195 | #endif |
| 1118 | 1196 | } |
| 1119 | 1197 | |
| 1120 | 1198 | WRITE_LINE_MEMBER(rainbow_state::kbd_tx) |
| r30901 | r30902 | |
| 1193 | 1271 | GFXDECODE_ENTRY( "chargen", 0x0000, rainbow_charlayout, 0, 1 ) |
| 1194 | 1272 | GFXDECODE_END |
| 1195 | 1273 | |
| 1196 | | static const floppy_interface floppy_intf = |
| 1197 | | { |
| 1198 | | FLOPPY_STANDARD_5_25_SSDD_80, |
| 1199 | | LEGACY_FLOPPY_OPTIONS_NAME( dec100_floppy ), |
| 1200 | | "floppy_5_25" |
| 1201 | | }; |
| 1202 | 1274 | |
| 1203 | 1275 | static MACHINE_CONFIG_START( rainbow, rainbow_state ) |
| 1204 | 1276 | MCFG_DEFAULT_LAYOUT(layout_rainbow) |
| r30901 | r30902 | |
| 1229 | 1301 | MCFG_VT_VIDEO_RAM_CALLBACK(READ8(rainbow_state, read_video_ram_r)) |
| 1230 | 1302 | MCFG_VT_VIDEO_CLEAR_VIDEO_INTERRUPT_CALLBACK(WRITELINE(rainbow_state, clear_video_interrupt)) |
| 1231 | 1303 | |
| 1232 | | MCFG_DEVICE_ADD("wd1793", FD1793, 0) |
| 1233 | | MCFG_WD17XX_DEFAULT_DRIVE4_TAGS |
| 1234 | | MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(floppy_intf) |
| 1304 | MCFG_FD1793x_ADD(FD1793_TAG, XTAL_24_0734MHz / 24) // no separate 1 Mhz quartz |
| 1305 | MCFG_WD_FDC_FORCE_READY |
| 1306 | MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":0", rainbow_floppies, "525qd", rainbow_state::floppy_formats) |
| 1307 | MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":1", rainbow_floppies, "525qd", rainbow_state::floppy_formats) |
| 1308 | MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":2", rainbow_floppies, "525qd", rainbow_state::floppy_formats) |
| 1309 | MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":3", rainbow_floppies, "525qd", rainbow_state::floppy_formats) |
| 1235 | 1310 | MCFG_SOFTWARE_LIST_ADD("flop_list","rainbow") |
| 1236 | 1311 | |
| 1237 | 1312 | MCFG_DEVICE_ADD("kbdser", I8251, 0) |
| r30901 | r30902 | |
| 1294 | 1369 | |
| 1295 | 1370 | // CHANGES: the 'Boot 2.4' manual mentions 'recent ROM changes for MASS 11' in January 1985. |
| 1296 | 1371 | // Older ROMs like 04.03.11 (for PC-100-A) or 05.03 (100-B) obviously do not incorporate these. |
| 1297 | | |
| 1298 | 1372 | // => jump tables (F4000-F40083 and FC000-FC004D) were not extended. |
| 1299 | 1373 | // => absolute addresses of some internal routines have changed. |
| 1300 | 1374 | // => programs that do not rely on specific ROM versions should be compatible. |
| 1375 | // MASS was a VAX word processor, so changes likely affected terminal emulation. |
| 1301 | 1376 | |
| 1302 | 1377 | // FIXME: ROM names are made up. |
| 1303 | 1378 | // Someone who knows the DEC naming conventions should correct them - |