trunk/src/mess/drivers/rainbow.c
| r26664 | r26665 | |
| 1 | | /*************************************************************************** |
| 2 | | |
| 1 | /*************************************************************************************************** |
| 3 | 2 | DEC Rainbow 100 |
| 4 | 3 | |
| 5 | | Driver-in-progress by R. Belmont and Miodrag Milanovic with additions by Karl-Ludwig Deisenhofer. |
| 4 | Driver-in-progress by R. Belmont and Miodrag Milanovic. |
| 5 | Portions (2013) by Karl-Ludwig Deisenhofer (VT video, floppy, preliminary keyboard, DIP switches). |
| 6 | 6 | |
| 7 | | STATE AS OF NOVEMBER 2013 |
| 7 | STATE AS OF DECEMBER 2013 |
| 8 | 8 | -------------------------- |
| 9 | | - FATAL: keyboard emulation incomplete (inhibits the system from booting with ERROR 50 on cold or ERROR 13 on warm boot). |
| 10 | | - NOT WORKING: serial (ERROR 60). |
| 9 | - FLOPPY TIMING: 'wd17xx_complete_command' * must * be hard wired to about 13 usecs. |
| 10 | Line 1063 in 'wd17xx.c' has to be changed (until legacy code here is removed): |
| 11 | - w->timer_cmd->adjust(attotime::from_usec(usecs)); |
| 12 | + w->timer_cmd->adjust(attotime::from_usec(13)); |
| 13 | |
| 14 | - WORKAROUND AVAILABLE: keyboard emulation incomplete (inhibits the system from booting with ERROR 50 on cold or ERROR 13 on warm boot). |
| 15 | - NOT WORKING: serial (ERROR 60). |
| 11 | 16 | - NOT WORKING: printer interface (ERROR 40). Like error 60 not mission-critical. |
| 12 | 17 | |
| 13 | | - NON-CRITICAL: watchdog logic (triggered after 108 ms without interrupts) still not exactly by the book. |
| 18 | - NON-CRITICAL: watchdog logic (triggered after 108 ms without interrupts on original machine) still does not work as intended. |
| 14 | 19 | |
| 15 | 20 | Timer is reset by TWO sources: the VERT INT L from the DC012, or the MHFU ENB L from the enable flip-flop. |
| 16 | 21 | The MHFU gets active if the 8088 has not acknowledged a video processor interrupt within approx. 108 milliseconds. |
| 17 | 22 | |
| 18 | 23 | BIOS assumes a power-up reset if MHFU detection is disabled - and assumes a MHFU reset if MHFU detection is ENABLED. |
| 19 | | Therefore a 'warm boot' within MESS (F3) causes ERROR 16. |
| 24 | |
| 25 | As there is no reset switch, only a limited software reset exists on a real DEC-100 (CTRL-SETUP within SETUP). |
| 20 | 26 | |
| 21 | | - SHOULD BE IMPLEMENTED AS SLOT DEVICES (for now, DIP settings affect 'system_parameter_r' only and are disabled): |
| 27 | - TO BE IMPLEMENTED AS SLOT DEVICES (for now, DIP settings affect 'system_parameter_r' only and are disabled): |
| 22 | 28 | * Color graphics option (uses NEC upd7220 GDC) |
| 23 | 29 | * Extended communication option (same as BUNDLE_OPTION ?) |
| 24 | 30 | |
| 25 | 31 | - OTHER UPGRADES (NEC_V20 should be easy, the TURBOW is harder to come by) |
| 26 | 32 | * 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 ) |
| 27 | | plus DC 7174 or DT 7174 (barely readable). Add-on card, replaces main 8088 cpu (via ribbon cable). Changed BOOT ROM labeled 'TBSS1.3 - 3ED4'. |
| 33 | plus DC 7174 or DT 7174 (barely readable). Add-on card, replaces main 8088 cpu (via ribbon cable). Altered BOOT ROM labeled 'TBSS1.3 - 3ED4'. |
| 28 | 34 | |
| 29 | 35 | * NEC_V20 (requires modded BOOT ROM because of - at least 2 - hard coded timing loops): |
| 30 | 36 | 100A: 100B/100+: 100B+ ALTERNATE RECOMMENDATION (fixes RAM size auto-detection problems when V20 is in place. |
| r26664 | r26665 | |
| 154 | 160 | W17 pulls J1 serial port pin 1 to GND when set (chassis to logical GND). |
| 155 | 161 | ****************************************************************************/ |
| 156 | 162 | |
| 157 | | /* |
| 158 | | HARD DISC SIZES AND LIMITS |
| 159 | | HARDWARE: the Rainbow winchester controller has a built-in limit of 8 heads and 1024 cylinders (67 MB). Standard geometry is 4 surfaces. |
| 163 | // Workarounds DO NOT APPLY to the 190-B ROM. Only enable when compiling the 'rainbow' driver - |
| 164 | //#define FORCE_RAINBOW_100_LOGO |
| 165 | #define KBD_DELAY 875 // (debounce delay). Recommended: 875. |
| 160 | 166 | |
| 161 | | SOFTWARE: the original DEC boot loader (and FDISK from DOS 3.10) initially allowed a maximum hard disc size of 20 MB. |
| 162 | | - DOS 3 has a 1024 cylinder limit (32 MB). |
| 163 | | - the custom boot loader that comes with 'WUTIL 3.2' stretches limits to 117 MB and 8 surfaces. |
| 164 | | */ |
| 165 | | |
| 166 | | |
| 167 | 167 | #include "emu.h" |
| 168 | 168 | #include "cpu/i86/i86.h" |
| 169 | 169 | #include "cpu/z80/z80.h" |
| 170 | 170 | #include "video/vtvideo.h" |
| 171 | |
| 171 | 172 | #include "machine/wd17xx.h" |
| 172 | 173 | #include "imagedev/flopdrv.h" |
| 174 | #include "formats/basicdsk.h" |
| 175 | |
| 173 | 176 | #include "machine/i8251.h" |
| 174 | 177 | #include "machine/dec_lk201.h" |
| 175 | 178 | #include "sound/beep.h" |
| 176 | 179 | #include "machine/nvram.h" |
| 177 | 180 | |
| 178 | | #include "rainbow.lh" // BEZEL - LAYOUT with LEDs for diag 1-7, keyboard 8-11 and floppy 20-21 |
| 181 | #include "rainbow.lh" // BEZEL - LAYOUT with LEDs for diag 1-7, keyboard 8-11 and floppy 20-23 |
| 179 | 182 | |
| 180 | 183 | class rainbow_state : public driver_device |
| 181 | 184 | { |
| r26664 | r26665 | |
| 248 | 251 | DECLARE_READ8_MEMBER(floating_bus_r); |
| 249 | 252 | DECLARE_WRITE8_MEMBER(floating_bus_w); |
| 250 | 253 | |
| 254 | DECLARE_READ8_MEMBER(hd_status_68_r); |
| 251 | 255 | // EMULATOR TRAP TO INTERCEPT KEYBOARD cmd in AH and PARAMETER in AL (port 90 = AL / port 91 = AH) |
| 252 | 256 | // TODO: beeper and led handling should better be handled by LK201 code. |
| 253 | 257 | DECLARE_WRITE8_MEMBER(PORT90_W); |
| r26664 | r26665 | |
| 261 | 265 | DECLARE_WRITE8_MEMBER(z80_diskdiag_read_w); |
| 262 | 266 | DECLARE_WRITE8_MEMBER(z80_diskdiag_write_w); |
| 263 | 267 | |
| 264 | | DECLARE_WRITE8_MEMBER(z80_diskcontrol_write_w); |
| 268 | DECLARE_READ8_MEMBER(z80_generalstat_r); |
| 269 | |
| 270 | DECLARE_READ8_MEMBER(z80_diskstatus_r); |
| 271 | DECLARE_WRITE8_MEMBER(z80_diskcontrol_w); |
| 272 | |
| 265 | 273 | DECLARE_READ8_MEMBER(system_parameter_r); |
| 266 | 274 | |
| 267 | 275 | DECLARE_READ_LINE_MEMBER(dsr_r); |
| r26664 | r26665 | |
| 273 | 281 | |
| 274 | 282 | bool m_SCREEN_BLANK; |
| 275 | 283 | |
| 284 | int INT88, INTZ80; |
| 285 | |
| 276 | 286 | bool m_zflip; // Z80 alternate memory map with A15 inverted |
| 277 | 287 | bool m_z80_halted; |
| 288 | int m_z80_diskcontrol; // retains values needed for status register |
| 289 | |
| 278 | 290 | bool m_kbd_tx_ready, m_kbd_rx_ready; |
| 291 | int m_KBD; |
| 279 | 292 | |
| 280 | | int m_KBD; |
| 281 | 293 | int m_beep_counter; |
| 294 | int MOTOR_DISABLE_counter; |
| 282 | 295 | |
| 283 | | int MHFU_counter; |
| 284 | | |
| 296 | int COLD_BOOT; |
| 285 | 297 | private: |
| 286 | 298 | UINT8 m_z80_private[0x800]; // Z80 private 2K |
| 287 | 299 | UINT8 m_z80_mailbox, m_8088_mailbox; |
| 288 | 300 | |
| 289 | 301 | void update_kbd_irq(); |
| 290 | 302 | virtual void machine_reset(); |
| 291 | | void MHFU_reset(); |
| 303 | |
| 304 | int m_unit; |
| 305 | device_t *m_image[4]; |
| 306 | |
| 292 | 307 | public: |
| 293 | 308 | UINT32 screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 294 | 309 | INTERRUPT_GEN_MEMBER(vblank_irq); |
| r26664 | r26665 | |
| 296 | 311 | required_device<cpu_device> m_maincpu; |
| 297 | 312 | }; |
| 298 | 313 | |
| 314 | |
| 299 | 315 | void rainbow_state::machine_start() |
| 300 | 316 | { |
| 317 | m_image[0] = subdevice(FLOPPY_0); |
| 318 | m_image[1] = subdevice(FLOPPY_1); |
| 319 | m_image[2] = subdevice(FLOPPY_2); |
| 320 | m_image[3] = subdevice(FLOPPY_3); |
| 321 | |
| 322 | COLD_BOOT = 1; |
| 323 | |
| 301 | 324 | m_SCREEN_BLANK = false; |
| 302 | 325 | |
| 303 | 326 | save_item(NAME(m_z80_private)); |
| r26664 | r26665 | |
| 309 | 332 | |
| 310 | 333 | UINT8 *rom = memregion("maincpu")->base(); |
| 311 | 334 | |
| 335 | |
| 336 | #ifdef FORCE_RAINBOW_100_LOGO |
| 337 | rom[0xf4174]=0xeb; // jmps RAINBOW100_LOGO__loc_33D |
| 338 | rom[0xf4175]=0x08; |
| 339 | |
| 340 | rom[0xf4000 + 0x364a]= 0x0a; |
| 341 | rom[0xf4384]=0xeb; // JMPS => BOOT80 |
| 342 | #endif |
| 343 | |
| 312 | 344 | // Enables PORT90_W + PORT91_W via BIOS call (offset +$21 in HIGH ROM) |
| 313 | 345 | // F8 / FC ROM REGION (CHECK + PATCH) |
| 314 | 346 | if(rom[0xfc000 + 0x0022] == 0x22 && rom[0xfc000 + 0x0023] == 0x28) |
| 315 | 347 | { |
| 316 | 348 | rom[0xf4303]=0x00; // Disable CRC CHECK (F0 / F4 ROM) |
| 317 | 349 | |
| 318 | | rom[0xfc000 + 0x0022] =0xe2; // jmp to offset $3906 |
| 319 | | rom[0xfc000 + 0x0023] =0x38; |
| 350 | rom[0xfc000 + 0x0022] =0xfe; // jmp to offset $1922 |
| 351 | rom[0xfc000 + 0x0023] =0x18; |
| 320 | 352 | |
| 321 | | rom[0xfc000 + 0x3906] =0xe6; // out 90,al |
| 322 | | rom[0xfc000 + 0x3907] =0x90; |
| 353 | rom[0xfc000 + 0x1922] =0xe6; // out 90,al |
| 354 | rom[0xfc000 + 0x1923] =0x90; |
| 323 | 355 | |
| 324 | | rom[0xfc000 + 0x3908] =0x86; // xchg al,ah |
| 325 | | rom[0xfc000 + 0x3909] =0xc4; |
| 356 | rom[0xfc000 + 0x1924] =0x86; // xchg al,ah |
| 357 | rom[0xfc000 + 0x1925] =0xc4; |
| 326 | 358 | |
| 327 | | rom[0xfc000 + 0x390a] =0xe6; // out 91,al |
| 328 | | rom[0xfc000 + 0x390b] =0x91; |
| 359 | rom[0xfc000 + 0x1926] =0xe6; // out 91,al |
| 360 | rom[0xfc000 + 0x1927] =0x91; |
| 329 | 361 | |
| 330 | | rom[0xfc000 + 0x390c] =0x86; // xchg al,ah |
| 331 | | rom[0xfc000 + 0x390d] =0xc4; |
| 362 | rom[0xfc000 + 0x1928] =0x86; // xchg al,ah |
| 363 | rom[0xfc000 + 0x1929] =0xc4; |
| 332 | 364 | |
| 333 | | rom[0xfc000 + 0x390e] =0xe9; // jmp (original jump offset $2846) |
| 334 | | rom[0xfc000 + 0x390f] =0x35; |
| 335 | | rom[0xfc000 + 0x3910] =0xef; |
| 365 | rom[0xfc000 + 0x192a] =0xe9; // jmp (original jump offset $2846) e9 + 19 0f |
| 366 | rom[0xfc000 + 0x192b] =0x19; |
| 367 | rom[0xfc000 + 0x192c] =0x0f; |
| 336 | 368 | } |
| 369 | |
| 337 | 370 | } |
| 338 | 371 | |
| 339 | 372 | static ADDRESS_MAP_START( rainbow8088_map, AS_PROGRAM, 8, rainbow_state) |
| r26664 | r26665 | |
| 374 | 407 | // 0x04 Video processor DC011 |
| 375 | 408 | AM_RANGE (0x04, 0x04) AM_DEVWRITE("vt100_video", rainbow_video_device, dc011_w) |
| 376 | 409 | |
| 410 | // TODO: unmapped [06] : Communication bit rates (see page 21 of PC 100 SPEC) |
| 411 | |
| 377 | 412 | AM_RANGE (0x08, 0x08) AM_READ(system_parameter_r) |
| 378 | 413 | |
| 379 | 414 | AM_RANGE (0x0a, 0x0a) AM_READWRITE(diagnostic_r, diagnostic_w) |
| r26664 | r26665 | |
| 381 | 416 | // 0x0C Video processor DC012 |
| 382 | 417 | AM_RANGE (0x0c, 0x0c) AM_DEVWRITE("vt100_video", rainbow_video_device, dc012_w) |
| 383 | 418 | |
| 419 | // TODO: unmapped [0e] : PRINTER BIT RATE REGISTER (WO) |
| 420 | |
| 384 | 421 | AM_RANGE(0x10, 0x10) AM_DEVREADWRITE("kbdser", i8251_device, data_r, data_w) |
| 385 | 422 | AM_RANGE(0x11, 0x11) AM_DEVREADWRITE("kbdser", i8251_device, status_r, control_w) |
| 386 | 423 | |
| 424 | // UNMAPPED: |
| 425 | // 0x20 - 0x2f ***** EXTENDED COMM. OPTION (option select 1)- for example: |
| 426 | // 0x27 (RESET EXTENDED COMM OPTION) - OUT 27 @ offset 1EA7 |
| 427 | |
| 428 | // 0x40 COMMUNICATIONS DATA REGISTER (MPSC) |
| 429 | // 0x41 PRINTER DATA REGISTER (MPSC) |
| 430 | // 0x42 COMMUNICATIONS CONTROL / STATUS REGISTER (MPSC) |
| 431 | // 0x43 PRINTER CONTROL / STATUS REGISTER (MPSC) |
| 432 | |
| 433 | // 0x50 - 0xf ***** OPTIONAL COLOR GRAPHICS - for example: |
| 434 | // 0x50 (RESET_GRAPH. OPTION) - OUT 50 @ offsets F5EB5 + F5EB9 |
| 435 | |
| 436 | // =========================================================== |
| 437 | // TODO: hard disc emulation! |
| 438 | // ------ Rainbow uses 'WD 1010 AL' (Western Digital 1983) |
| 439 | // Register compatible to WD2010 (present in MESS) |
| 440 | // R/W REGISTERS 60 - 68 (?) |
| 441 | // =========================================================== |
| 442 | // HARD DISC SIZES AND LIMITS |
| 443 | // HARDWARE: |
| 444 | // Controller has a built-in limit of 8 heads / 1024 cylinders (67 MB). Standard geometry is 4 surfaces. |
| 445 | // SOFTWARE: the DEC boot loader (and FDISK from DOS 3.10) initially allowed a maximum hard disc size of 20 MB. |
| 446 | // - DOS 3 has a 1024 cylinder limit (32 MB). |
| 447 | // - the custom boot loader that comes with 'WUTIL 3.2' allows 117 MB and 8 surfaces. |
| 448 | AM_RANGE (0x68, 0x68) AM_READ(hd_status_68_r) |
| 449 | |
| 387 | 450 | AM_RANGE (0x90, 0x90) AM_WRITE(PORT90_W) |
| 388 | 451 | AM_RANGE (0x91, 0x91) AM_WRITE(PORT91_W) |
| 389 | 452 | ADDRESS_MAP_END |
| r26664 | r26665 | |
| 397 | 460 | ADDRESS_MAP_UNMAP_HIGH |
| 398 | 461 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
| 399 | 462 | AM_RANGE(0x00, 0x00) AM_READWRITE(z80_latch_r, z80_latch_w) |
| 400 | | AM_RANGE(0x20, 0x20) AM_WRITE(z80_diskdiag_read_w) |
| 401 | | AM_RANGE(0x21, 0x21) AM_WRITE(z80_diskdiag_write_w) |
| 402 | | AM_RANGE(0x40, 0x40) AM_WRITE(z80_diskcontrol_write_w) |
| 463 | 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. |
| 464 | AM_RANGE(0x21, 0x21) AM_READWRITE(z80_generalstat_r, z80_diskdiag_write_w) |
| 465 | AM_RANGE(0x40, 0x40) AM_READWRITE(z80_diskstatus_r, z80_diskcontrol_w) |
| 403 | 466 | AM_RANGE(0x60, 0x60) AM_DEVREADWRITE_LEGACY("wd1793", wd17xx_status_r, wd17xx_command_w) |
| 404 | 467 | AM_RANGE(0x61, 0x61) AM_DEVREADWRITE_LEGACY("wd1793", wd17xx_track_r, wd17xx_track_w) |
| 405 | 468 | AM_RANGE(0x62, 0x62) AM_DEVREADWRITE_LEGACY("wd1793", wd17xx_sector_r, wd17xx_sector_w) |
| r26664 | r26665 | |
| 407 | 470 | ADDRESS_MAP_END |
| 408 | 471 | |
| 409 | 472 | /* Input ports */ |
| 410 | | static INPUT_PORTS_START( rainbow ) |
| 473 | |
| 474 | /* KEYBOARD (preliminary - transfer to DEC_LK201.xx as soon as possible) */ |
| 475 | static INPUT_PORTS_START( rainbow100b_in ) |
| 476 | /* DIP switches */ |
| 411 | 477 | PORT_START("MONITOR TYPE") |
| 412 | 478 | PORT_DIPNAME( 0x03, 0x03, "MONOCHROME MONITOR") |
| 413 | 479 | PORT_DIPSETTING( 0x01, "PAPER WHITE" ) |
| 414 | 480 | PORT_DIPSETTING( 0x02, "GREEN" ) |
| 415 | 481 | PORT_DIPSETTING( 0x03, "AMBER" ) |
| 416 | 482 | |
| 417 | | PORT_START("FLOPPY CONTROLLER") |
| 418 | | PORT_DIPNAME( 0x02, 0x02, "FLOPPY CONTROLLER") PORT_TOGGLE |
| 419 | | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| 420 | | PORT_DIPSETTING( 0x02, DEF_STR( On ) ) |
| 421 | | |
| 422 | | PORT_START("GRAPHICS OPTION") |
| 423 | | PORT_DIPNAME( 0x00, 0x00, "GRAPHICS OPTION") PORT_TOGGLE |
| 424 | | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| 425 | | PORT_DIPSETTING( 0x04, DEF_STR( On ) ) |
| 426 | | |
| 427 | | PORT_START("BUNDLE OPTION") |
| 428 | | PORT_DIPNAME( 0x00, 0x00, "BUNDLE OPTION") PORT_TOGGLE |
| 429 | | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| 430 | | PORT_DIPSETTING( 0x01, DEF_STR( On ) ) |
| 431 | | |
| 432 | 483 | PORT_START("MEMORY PRESENT") |
| 433 | 484 | PORT_DIPNAME( 0xF000, 0x2000, "MEMORY PRESENT") |
| 434 | 485 | PORT_DIPSETTING( 0x2000, "128 K (BOARD DEFAULT)" ) // NOTE: 0x2000 hard coded in 'system_parameter_r' |
| r26664 | r26665 | |
| 445 | 496 | PORT_DIPSETTING( 0xD000, "832 K (MEMORY OPTION)" ) |
| 446 | 497 | PORT_DIPSETTING( 0xE000, "896 K (MEMORY OPTION)" ) |
| 447 | 498 | |
| 448 | | PORT_START("W13") |
| 499 | PORT_START("GRAPHICS OPTION") |
| 500 | PORT_DIPNAME( 0x00, 0x00, "GRAPHICS OPTION") PORT_TOGGLE |
| 501 | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| 502 | PORT_DIPSETTING( 0x04, DEF_STR( On ) ) |
| 503 | |
| 504 | PORT_START("BUNDLE OPTION") |
| 505 | PORT_DIPNAME( 0x00, 0x00, "BUNDLE OPTION") PORT_TOGGLE |
| 506 | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| 507 | PORT_DIPSETTING( 0x01, DEF_STR( On ) ) |
| 508 | |
| 509 | PORT_START("W13") // W13 - W18 affect 'system_parameter_r' |
| 449 | 510 | PORT_DIPNAME( 0x02, 0x02, "W13 (FACTORY TEST A, LEAVE OFF)") PORT_TOGGLE |
| 450 | 511 | PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) |
| 451 | 512 | PORT_DIPSETTING( 0x00, DEF_STR( On ) ) |
| r26664 | r26665 | |
| 462 | 523 | PORT_DIPNAME( 0x01, 0x00, "W18 (FACTORY TEST D, LEAVE OFF) (8251A: DSR)") PORT_TOGGLE |
| 463 | 524 | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| 464 | 525 | PORT_DIPSETTING( 0x01, DEF_STR( On ) ) |
| 526 | |
| 527 | // J17 jumper on FDC controller board shifts drive select (experimental) - |
| 528 | PORT_START("FLOPPY CONTROLLER") |
| 529 | PORT_DIPNAME( 0x02, 0x00, "J17 DRIVE SELECT (A => C and B => D)") PORT_TOGGLE |
| 530 | PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) |
| 531 | PORT_DIPSETTING( 0x02, DEF_STR( On ) ) |
| 465 | 532 | INPUT_PORTS_END |
| 466 | 533 | |
| 467 | | |
| 468 | | void rainbow_state::MHFU_reset() |
| 469 | | { |
| 470 | | MHFU_counter = 530; // 528 = 110ms |
| 471 | | } |
| 472 | | |
| 534 | // 800K native format (80 * 10). Also reads VT-180 disks and PC-DOS 360 k disks |
| 535 | // ( both: 512 byte sectors, single sided, 9 sectors per track, 40 tracks ) |
| 536 | static LEGACY_FLOPPY_OPTIONS_START( dec100_floppy ) |
| 537 | LEGACY_FLOPPY_OPTION( dec100_floppy, "td0", "Teledisk floppy disk image", td0_dsk_identify, td0_dsk_construct, td0_dsk_destruct, NULL ) |
| 538 | LEGACY_FLOPPY_OPTION( dec100_floppy, "img", "DEC Rainbow 100", basicdsk_identify_default, basicdsk_construct_default, NULL, |
| 539 | HEADS([1]) |
| 540 | TRACKS(40/[80]) |
| 541 | SECTORS(9/[10]) |
| 542 | SECTOR_LENGTH([512]) |
| 543 | INTERLEAVE([0]) |
| 544 | FIRST_SECTOR_ID([1]) |
| 545 | ) |
| 546 | LEGACY_FLOPPY_OPTIONS_END |
| 547 | |
| 473 | 548 | void rainbow_state::machine_reset() |
| 474 | 549 | { |
| 475 | | MHFU_reset(); |
| 550 | if (COLD_BOOT == 1) |
| 551 | { |
| 552 | COLD_BOOT = 2; |
| 553 | m_crtc->MHFU(-100); // reset MHFU counter |
| 554 | } |
| 476 | 555 | |
| 477 | 556 | m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); |
| 478 | 557 | |
| 558 | INT88 = false; |
| 559 | INTZ80 = false; |
| 560 | |
| 479 | 561 | m_zflip = true; |
| 480 | 562 | m_z80_halted = true; |
| 481 | 563 | m_kbd_tx_ready = m_kbd_rx_ready = false; |
| r26664 | r26665 | |
| 500 | 582 | output_set_value("led10", 1); |
| 501 | 583 | output_set_value("led11", 1); |
| 502 | 584 | |
| 503 | | output_set_value("led20", 1); // DRIVE 0 (A) |
| 504 | | output_set_value("led21", 1); // DRIVE 1 (B) |
| 585 | MOTOR_DISABLE_counter = 2; // soon resets drv.LEDs |
| 586 | m_unit = 0; |
| 587 | |
| 505 | 588 | } |
| 506 | 589 | |
| 507 | 590 | UINT32 rainbow_state::screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 508 | 591 | { |
| 592 | // TEST-DEBUG: no screen updates during diskette operations! |
| 593 | if (MOTOR_DISABLE_counter) |
| 594 | return 0; |
| 595 | |
| 509 | 596 | m_crtc->palette_select( m_inp9->read() ); |
| 510 | 597 | |
| 511 | 598 | if ( m_SCREEN_BLANK ) |
| r26664 | r26665 | |
| 516 | 603 | } |
| 517 | 604 | |
| 518 | 605 | // It is no longer possible to key in the RAM size on the 100-B. |
| 519 | | // The DEC-100-B boot ROM probes until a 'flaky' area is found (around F400:xxxx). |
| 606 | // The DEC-100-B boot ROM probes until a 'flaky' area is found (around F400:0E04). |
| 520 | 607 | |
| 521 | 608 | // Unexpected low RAM sizes are an indication of option RAM (at worst: 128 K on board) failure. |
| 522 | 609 | // While motherboard errors often render the system unbootable, bad option RAM (> 128 K) |
| 523 | | // can be narrowed down with a diagnostic disk and codes from the 'Pocket Service Guide' |
| 610 | // can be narrowed down with the Diagnostic Disk and codes from the 'Pocket Service Guide' |
| 524 | 611 | // EK-PC100-PS-002 (APPENDIX B.2.2); pc100ps2.pdf |
| 525 | | |
| 526 | | // Simulate floating bus for initial RAM detection: |
| 612 | // ================================================================ |
| 613 | // - Simulate floating bus for initial RAM detection - |
| 614 | // FIXME: code valid ONLY within ROM section F4Exxx. |
| 615 | // |
| 616 | // NOTE: MS-DOS 2.x unfortunately probes RAM in a similar way. |
| 617 | // => SET OPTION RAM to 896 K for unknown applications (and DOS) <= |
| 618 | // ================================================================ |
| 527 | 619 | READ8_MEMBER(rainbow_state::floating_bus_r) |
| 528 | 620 | { |
| 529 | | if ( m_maincpu->state_int(I8086_CS) != 0xF400) |
| 530 | | return space.read_byte(offset); |
| 621 | int pc = space.device().safe_pc(); |
| 531 | 622 | |
| 532 | | if ( m_maincpu->state_int(I8086_DS) < m_inp8->read() ) |
| 623 | if ( ((pc & 0xFFF00) == 0xF4E00) && |
| 624 | ( m_maincpu->state_int(I8086_DS) >= m_inp8->read() ) |
| 625 | ) |
| 533 | 626 | { |
| 627 | return (offset>>16) + 2; |
| 628 | } |
| 629 | else |
| 534 | 630 | return space.read_byte(offset); |
| 535 | | } else |
| 536 | | { |
| 537 | | return (offset>>16) + 2; |
| 538 | | } |
| 539 | 631 | } |
| 540 | 632 | |
| 541 | 633 | WRITE8_MEMBER(rainbow_state::floating_bus_w) |
| 542 | 634 | { |
| 543 | | space.write_byte(offset,data); |
| 635 | space.write_byte(offset,data); |
| 544 | 636 | } |
| 545 | 637 | |
| 546 | 638 | |
| r26664 | r26665 | |
| 600 | 692 | } |
| 601 | 693 | } |
| 602 | 694 | |
| 695 | // Until a full-blown hard-disc emulation evolves, deliver an error message: |
| 696 | READ8_MEMBER(rainbow_state::hd_status_68_r) |
| 697 | { |
| 698 | // Top 3 bits = status / error code |
| 699 | // SEE -> W_INCHESTER__loc_80E |
| 700 | |
| 701 | // return 0xa0; // A0 : OK, DRIVE IS READY (!) |
| 702 | |
| 703 | return 0xe0; // => 21 DRIVE NOT READY (BIOS; when W is pressed on boot screen) |
| 704 | } |
| 705 | |
| 603 | 706 | READ8_MEMBER(rainbow_state::system_parameter_r) |
| 604 | 707 | { |
| 605 | 708 | /* Info about option boards is in bits 0 - 3: |
| r26664 | r26665 | |
| 610 | 713 | ( 1 means NOT present ) |
| 611 | 714 | */ |
| 612 | 715 | // Hard coded value 0x2000 - see DIP switch setup! |
| 613 | | return 0x0f - m_inp5->read() - m_inp6->read() - m_inp7->read() - ( |
| 614 | | (m_inp8->read() > 0x2000) ? 8 : 0 |
| 615 | | ); |
| 716 | return 0x0f - m_inp5->read() |
| 717 | - 0 // floppy is hard coded in emulator. |
| 718 | - m_inp7->read() |
| 719 | - (m_inp8->read() > 0x2000) ? 8 : 0; |
| 616 | 720 | } |
| 617 | 721 | |
| 618 | 722 | READ8_MEMBER(rainbow_state::comm_control_r) |
| 619 | 723 | { |
| 620 | | /* |
| 621 | | --> What the specs says on how MHFU detection is disabled: |
| 622 | | // 1. by first disabling interrupts with CLI |
| 623 | | // 2. by writing 0x00 to port 0x10C (handled by 'dc012_w' in vtvideo) |
| 624 | | // (3.) MHFU is re-enabled by writing to 0x0c (or automatically after STI - when under BIOS control ?) |
| 625 | | */ |
| 626 | | return ( ( m_crtc->dc012_MHFU() << 5) // shift status of DC012 - MHFU flag to bit pos.5 |
| 627 | | ); |
| 724 | /* [02] COMMUNICATIONS STATUS REGISTER - PAGE 154 (**** READ **** ) |
| 725 | Used to read status of SERIAL port, IRQ line of each CPU, and MHFU logic enable signal. |
| 726 | |
| 727 | // What the specs says on how MHFU detection is disabled: |
| 728 | // 1. by first disabling interrupts with CLI |
| 729 | // 2. by writing 0x00 to port 0x10C (handled by 'dc012_w' in vtvideo) |
| 730 | // (3.) MHFU is re-enabled by writing to 0x0c (or automatically after STI - when under BIOS control ?) |
| 731 | */ |
| 732 | // During boot phase 2, do not consider MHFU ENABLE. Prevents ERROR 16. |
| 733 | int data; |
| 734 | if (COLD_BOOT == 2) |
| 735 | data = 0; |
| 736 | else |
| 737 | data = m_crtc->MHFU(1); |
| 738 | |
| 739 | return ( ( (data > 0) ? 0x00 : 0x20) |// (L): status of MHFU flag => bit pos.5 |
| 740 | ( (INT88) ? 0x00 : 0x40 ) | // (L) |
| 741 | ( (INTZ80) ? 0x00 : 0x80 ) // (L) |
| 742 | ); |
| 628 | 743 | } |
| 629 | 744 | |
| 630 | 745 | WRITE8_MEMBER(rainbow_state::comm_control_w) |
| r26664 | r26665 | |
| 651 | 766 | |
| 652 | 767 | m_KBD = 0; // reset previous command. |
| 653 | 768 | |
| 654 | | if (data == 0xfd) { // Powerup (beep) |
| 655 | | m_beep->set_state(1); |
| 656 | | m_beep_counter=600; // BELL = 125 ms |
| 769 | if(MOTOR_DISABLE_counter == 0) |
| 770 | { |
| 771 | |
| 772 | if (data == LK_CMD_POWER_UP) { // Powerup (beep) |
| 773 | //m_beep->set_state(1); |
| 774 | //m_beep_counter=600; // BELL = 125 ms |
| 657 | 775 | } |
| 658 | 776 | |
| 659 | | if (data == 0xa7) { |
| 660 | | m_beep->set_state(1); |
| 777 | if (data == LK_CMD_BELL) { |
| 778 | m_KBD = data; |
| 779 | m_beep->set_state(1); |
| 661 | 780 | m_beep_counter=600; // BELL = 125 ms |
| 662 | 781 | } |
| 663 | 782 | |
| 664 | | if (data == 0x9f) { // emit a keyclick (2ms) |
| 783 | if (data == LK_CMD_SOUND_CLK) { // emit a keyclick (2ms) |
| 784 | m_KBD = data; |
| 665 | 785 | m_beep->set_state(1); |
| 666 | 786 | m_beep_counter=25; // longer than calculated ( 9,6 ) |
| 667 | 787 | } |
| 668 | 788 | |
| 669 | | if (data == 0x13) { // light LEDs - |
| 670 | | m_KBD = 0x13; |
| 789 | if (data == LK_CMD_ENB_BELL) { // enable the bell - PARAMETER: VOLUME! |
| 790 | m_KBD = data; |
| 671 | 791 | } |
| 672 | | if (data == 0x11) { // switch off LEDs - |
| 673 | | m_KBD = 0x11; |
| 792 | |
| 793 | if (data == LK_CMD_ENB_KEYCLK) { // enable the keyclick- PARAMETER: VOLUME! |
| 794 | m_KBD = data; |
| 674 | 795 | } |
| 796 | |
| 797 | if (data == LK_CMD_LEDS_ON ) { // light LEDs - |
| 798 | m_KBD = data; |
| 799 | } |
| 800 | if (data == LK_CMD_LEDS_OFF) { // switch off LEDs - |
| 801 | m_KBD = data; |
| 802 | } |
| 803 | |
| 804 | } // prevent beeps during disk load operations |
| 675 | 805 | } |
| 676 | 806 | |
| 677 | 807 | WRITE8_MEMBER(rainbow_state::PORT91_W) |
| 678 | 808 | { |
| 679 | | //printf("KBD PARAM %02x to AH (91) \n", data); |
| 680 | | |
| 681 | 809 | // 4 leds, represented in the low 4 bits of a byte |
| 682 | | if (m_KBD == 0x13) { // light LEDs - |
| 810 | if (m_KBD == LK_CMD_LEDS_ON) { // light LEDs - |
| 683 | 811 | if (data & 1) { output_set_value("led8", 0); } // KEYBOARD : "Wait" LED |
| 684 | 812 | if (data & 2) { output_set_value("led9", 0); } // KEYBOARD : "Compose" LED |
| 685 | 813 | if (data & 4) { output_set_value("led10", 0); } // KEYBOARD : "Lock" LED |
| 686 | 814 | if (data & 8) { output_set_value("led11", 0); } // KEYBOARD : "Hold" LED |
| 687 | 815 | m_KBD = 0; // reset previous command. |
| 688 | 816 | } |
| 689 | | if (m_KBD == 0x11) { // switch off LEDs - |
| 817 | if (m_KBD == LK_CMD_LEDS_OFF) { // switch off LEDs - |
| 690 | 818 | if (data & 1) { output_set_value("led8", 1); } // KEYBOARD : "Wait" LED |
| 691 | 819 | if (data & 2) { output_set_value("led9", 1); } // KEYBOARD : "Compose" LED |
| 692 | 820 | if (data & 4) { output_set_value("led10", 1); } // KEYBOARD : "Lock" LED |
| r26664 | r26665 | |
| 694 | 822 | m_KBD = 0; // reset previous command. |
| 695 | 823 | } |
| 696 | 824 | |
| 697 | | if (m_KBD == 0x1b) { /* enable the keyclick */ |
| 698 | | /* max volume is 0, lowest is 0x7 */ |
| 825 | // NVRAM offet $A8 : BELL VOLUME (=> ENABLE BELL 0x23) |
| 826 | if ( (m_KBD == LK_CMD_BELL) || (m_KBD == LK_CMD_ENB_BELL) ) /* BOTH sound or enable bell have a parameter */ |
| 827 | { /* max volume is 0, lowest is 0x7 */ |
| 828 | // printf("\n%02x BELL CMD has bell volume = %02x\n", m_KBD, 8 - (data & 7)); |
| 699 | 829 | m_KBD = 0; // reset previous command. |
| 700 | 830 | } |
| 831 | |
| 832 | // NVRAM offet $A9 = KEYCLICK VOLUME (=> ENABLE CLK 0x1b) |
| 833 | // NVRAM offset $8C = KEYCLICK ENABLE / DISABLE (0/1) |
| 834 | if ( ( m_KBD == LK_CMD_ENB_KEYCLK ) || ( m_KBD == LK_CMD_SOUND_CLK ) ) /* BOTH keyclick cmds have a parameter */ |
| 835 | { // max volume is 0, lowest is 0x7 - 87 (BELL VOL:1) and 80 (BELL VOL:8) |
| 836 | // printf("\n%02x CLICK CMD - keyclick volume = %02x\n", m_KBD, 8 - (data & 7)); |
| 837 | m_KBD = 0; // reset previous command. |
| 838 | } |
| 839 | |
| 840 | if (m_KBD > 0) |
| 841 | printf("UNHANDLED PARAM FOR MODE: %02x / KBD PARAM %02x to AH (91) \n", m_KBD, data); |
| 842 | |
| 701 | 843 | } |
| 702 | | |
| 844 | // 8088 reads port 0x00. See page 133 (4-34) |
| 703 | 845 | READ8_MEMBER(rainbow_state::i8088_latch_r) |
| 704 | 846 | { |
| 705 | 847 | // printf("Read %02x from 8088 mailbox\n", m_8088_mailbox); |
| 706 | 848 | m_i8088->set_input_line(INPUT_LINE_INT0, CLEAR_LINE); |
| 849 | |
| 850 | INT88 = false; // BISLANG: INTZ80 = false; // |
| 707 | 851 | return m_8088_mailbox; |
| 708 | 852 | } |
| 709 | 853 | |
| 854 | // 8088 writes port 0x00. See page 133 (4-34) |
| 710 | 855 | WRITE8_MEMBER(rainbow_state::i8088_latch_w) |
| 711 | 856 | { |
| 712 | 857 | // printf("%02x to Z80 mailbox\n", data); |
| 713 | 858 | m_z80->set_input_line_and_vector(0, ASSERT_LINE, 0xf7); |
| 714 | 859 | m_z80_mailbox = data; |
| 860 | |
| 861 | INTZ80 = true; // |
| 715 | 862 | } |
| 716 | 863 | |
| 864 | // Z80 reads port 0x00 |
| 865 | // See page 134 (4-35) |
| 717 | 866 | READ8_MEMBER(rainbow_state::z80_latch_r) |
| 718 | 867 | { |
| 719 | 868 | // printf("Read %02x from Z80 mailbox\n", m_z80_mailbox); |
| 720 | 869 | m_z80->set_input_line(0, CLEAR_LINE); |
| 870 | |
| 871 | INTZ80 = false; // BISLANG: INT88 = false; |
| 721 | 872 | return m_z80_mailbox; |
| 722 | 873 | } |
| 723 | 874 | |
| 875 | // Z80 writes to port 0x00 |
| 876 | // See page 134 (4-35) |
| 724 | 877 | WRITE8_MEMBER(rainbow_state::z80_latch_w) |
| 725 | 878 | { |
| 726 | | // printf("%02x to 8088 mailbox\n", data); |
| 879 | // printf("%02x to 8088 mailbox\n", data); |
| 727 | 880 | m_i8088->set_input_line_and_vector(INPUT_LINE_INT0, ASSERT_LINE, 0x27); |
| 728 | 881 | m_8088_mailbox = data; |
| 882 | |
| 883 | INT88 = true; |
| 729 | 884 | } |
| 730 | 885 | |
| 886 | // WRITE to 0x20 |
| 731 | 887 | WRITE8_MEMBER(rainbow_state::z80_diskdiag_read_w) |
| 732 | 888 | { |
| 733 | 889 | m_zflip = true; |
| 734 | 890 | } |
| 735 | 891 | |
| 892 | // (Z80) : PORT 21H _READ_ |
| 893 | READ8_MEMBER(rainbow_state::z80_generalstat_r) |
| 894 | { |
| 895 | /* |
| 896 | General / diag.status register Z80 / see page 157 (table 4-18). |
| 897 | |
| 898 | D7 : STEP L : reflects status of STEP signal _FROM FDC_ |
| 899 | (when this 2us output pulse is low, the stepper will move into DIR) |
| 900 | D6 : WRITE GATE L :reflects status of WRITE GATE signal _FROM FDC_ |
| 901 | (asserted low before data can be written on the diskette) |
| 902 | D5 : TR00: reflects status of TRACK 0 signal (= 1) * from the disk drive * |
| 903 | D4 : DIR L: reflects status of DIRECTION signal * FROM FDC * to disk |
| 904 | (when low, the head will step towards the center) |
| 905 | D3 : READY L: reflects status of READY L signal * from the disk drive * |
| 906 | (low active, asserts when disk is inserted and door is closed) |
| 907 | D2 : INT88 L: (bit reads the INT88 bit sent by Z80 to interrupt 8088) |
| 908 | D1 : INTZ80 L: (bit reads the INTZ80 bit sent by 8088 to interrupt Z80) |
| 909 | D0 : ZFLIP L: (read from the diagnostic control register of Z80A) |
| 910 | |
| 911 | NOTES: ALL LOW ACTIVE - EXCEPT TR00 |
| 912 | */ |
| 913 | // * TRACK 00 * signal for current drive |
| 914 | int tk00 = ( floppy_tk00_r( m_image[m_unit] ) == CLEAR_LINE ) ? 0x20 : 0x00; |
| 915 | |
| 916 | int fdc_ready = floppy_drive_get_flag_state( m_image[m_unit] , FLOPPY_DRIVE_READY); |
| 917 | |
| 918 | int data=( 0x80 | // (STEP L) |
| 919 | // ( (fdc_write_gate) ) | |
| 920 | ( (tk00) ) | |
| 921 | // ( fdc_direction) | |
| 922 | ( (fdc_ready)? 0x00 : 0x08 ) | |
| 923 | ( (INT88) ? 0x00 : 0x04 ) | |
| 924 | ( (INTZ80) ? 0x00 : 0x02 ) | |
| 925 | ( (m_zflip) ? 0x00 : 0x01 ) |
| 926 | ); |
| 927 | |
| 928 | return data; |
| 929 | } |
| 930 | |
| 931 | // (Z80) : PORT 21H * WRITE * |
| 736 | 932 | WRITE8_MEMBER(rainbow_state::z80_diskdiag_write_w) |
| 737 | 933 | { |
| 738 | 934 | /* Z80 LEDs: |
| r26664 | r26665 | |
| 747 | 943 | m_zflip = false; |
| 748 | 944 | } |
| 749 | 945 | |
| 750 | | WRITE8_MEMBER(rainbow_state::z80_diskcontrol_write_w) |
| 946 | // (Z80) : PORT 40H _READ_ |
| 947 | |
| 948 | // ********************************************************************** |
| 949 | // POLARITY OF _DRQ_ AND _IRQ_ (depends on controller type!) |
| 950 | // ********************************************************************** |
| 951 | READ8_MEMBER(rainbow_state::z80_diskstatus_r) |
| 751 | 952 | { |
| 752 | | //printf("%02x to z80 DISK CONTROL (W)\n", data); |
| 953 | static int last_track; |
| 954 | int track = wd17xx_track_r(m_fdc, space, 0); |
| 753 | 955 | |
| 754 | | // TODO: this logic is a bit primitive. According to the spec, the RX-50 drive LED only turns on if |
| 755 | | // (a) spindle motor runs (b) disk is in drive (c) door closed (d) drive side is selected |
| 756 | | if ( (data & 1) && (data & 8) ) |
| 757 | | output_set_value("led20", 0); // DISKETTE 0 SELECTED & MOTOR 0 ON => LIGHT "DRIVE A" |
| 956 | if (track != last_track) |
| 957 | printf("\n%02d",track); |
| 958 | last_track = track; |
| 959 | |
| 960 | // 40H diskette status Register **** READ ONLY *** ( 4-60 of TM100.pdf ) |
| 961 | |
| 962 | // AND 00111011 - return what was WRITTEN to D5-D3, D1, D0 previously |
| 963 | // (except D7,D6,D2) |
| 964 | int data = m_z80_diskcontrol && 0x3b; |
| 965 | |
| 966 | // D7: DRQ: reflects status of DATA REQUEST signal from FDC. |
| 967 | // '1' indicates that FDC has read data OR requires new write data. |
| 968 | data |= wd17xx_drq_r(m_fdc) ? 0x80 : 0x00; |
| 969 | |
| 970 | // D6: IRQ: indicates INTERRUPT REQUEST signal from FDC. Indicates that a |
| 971 | // status bit has changed. Set to 1 at the completion of any |
| 972 | // command (.. see page 207 or 5-25). |
| 973 | data |= wd17xx_intrq_r(m_fdc) ? 0x40 : 0x00; |
| 974 | |
| 975 | // D5: SIDE 0H: status of side select signal at J2 + J3 of RX50 controller. |
| 976 | // For 1 sided drives, this bit will always read low (0). |
| 977 | |
| 978 | // D4: MOTOR 1 ON L: 0 = indicates MOTOR 1 ON bit is set in drive control reg. |
| 979 | // D3: MOTOR 0 ON L: 0 = indicates MOTOR 0 ON bit is set in drive " |
| 980 | |
| 981 | // D2: TG43 L : 0 = INDICATES TRACK > 43 SIGNAL FROM FDC TO DISK DRIVE. |
| 982 | data |= ( track > 43) ? 0x00 : 0x04; |
| 983 | |
| 984 | // D1: DS1 H: reflect status of bits 0 and 1 form disk.control reg. |
| 985 | // D0: DS0 H: " |
| 986 | return data; |
| 987 | } |
| 988 | |
| 989 | // (Z80) : PORT 40H * WRITE * |
| 990 | |
| 991 | // RX-50 has head A and head B (1 for each of the 2 disk slots in a RX-50). |
| 992 | |
| 993 | // TODO: find out how head load and drive select really work. |
| 994 | WRITE8_MEMBER(rainbow_state::z80_diskcontrol_w) |
| 995 | { |
| 996 | // FORCE_READY = 0 : assert DRIVE READY on FDC (diagnostic override; USED BY BIOS!) |
| 997 | // 1 : set ready only if drive is present, disk is in the drive, |
| 998 | // and disk motor is on - for Amstrad, Spectrum, PCW... |
| 999 | int force_ready = ( (data & 4) != 0 ) ? 0 : 1; |
| 1000 | |
| 1001 | int drive; |
| 1002 | if ( m_inp6->read() && ((data & 3) < 2) ) |
| 1003 | drive = (data & 1) + 2; |
| 758 | 1004 | else |
| 759 | | output_set_value("led20", 1); |
| 1005 | drive = data & 3; |
| 760 | 1006 | |
| 761 | | if ( (data & 2) && (data & 8) ) |
| 762 | | output_set_value("led21", 0); // DISKETTE 1 SELECTED & MOTOR 0 ON => LIGHT "DRIVE B" |
| 763 | | else |
| 764 | | output_set_value("led21", 1); |
| 1007 | int selected_drive = 255; |
| 1008 | |
| 1009 | if (flopimg_get_image( floppy_get_device( machine(), drive ) ) != NULL) |
| 1010 | { selected_drive = drive; |
| 1011 | wd17xx_set_drive(m_fdc, selected_drive); |
| 1012 | } |
| 1013 | |
| 1014 | // WD emulation (wd17xx.c) will ignore 'side select' if set to WD1793. |
| 1015 | // Is it safe to * always assume * single sided 400 K disks? |
| 1016 | wd17xx_set_side(m_fdc, (data & 20) ? 1 : 0); |
| 1017 | |
| 1018 | wd17xx_dden_w(m_fdc, 0); /* SEE 'WRITE_TRACK' : 1 = SD; 0 = DD; enable double density */ |
| 1019 | |
| 1020 | output_set_value("driveled0", (selected_drive == 0) ? 1 : 0 ); |
| 1021 | output_set_value("driveled1", (selected_drive == 1) ? 1 : 0 ); |
| 1022 | |
| 1023 | output_set_value("driveled2", (selected_drive == 2) ? 1 : 0 ); |
| 1024 | output_set_value("driveled3", (selected_drive == 3) ? 1 : 0 ); |
| 1025 | |
| 1026 | if (selected_drive < 4) |
| 1027 | { |
| 1028 | m_unit = selected_drive; |
| 1029 | |
| 1030 | // MOTOR ON flags 1+2 proved to be unreliable in this context. |
| 1031 | // So this timeout only disables LEDs. |
| 1032 | MOTOR_DISABLE_counter = 10000; // prolonged timeout. DEFAULT: 2400 = 500 ms |
| 1033 | |
| 1034 | for(int f_num=0; f_num <= 3; f_num++) |
| 1035 | { |
| 1036 | // Although 1773 does not feature 'motor on' this statement is required: |
| 1037 | // CLEAR_LINE = turn motor on - |
| 1038 | floppy_mon_w(m_image[f_num], (f_num == selected_drive) ? CLEAR_LINE : ASSERT_LINE); |
| 1039 | |
| 1040 | // Parameters: DRIVE, STATE, FLAG |
| 1041 | floppy_drive_set_ready_state( m_image[f_num], |
| 1042 | (f_num == selected_drive) ? 1 : 0, |
| 1043 | (f_num == selected_drive) ? force_ready : 0 |
| 1044 | ); |
| 1045 | } |
| 1046 | } |
| 1047 | |
| 1048 | m_z80_diskcontrol = data; |
| 765 | 1049 | } |
| 766 | 1050 | |
| 767 | 1051 | READ8_MEMBER( rainbow_state::read_video_ram_r ) |
| r26664 | r26665 | |
| 772 | 1056 | INTERRUPT_GEN_MEMBER(rainbow_state::vblank_irq) |
| 773 | 1057 | { |
| 774 | 1058 | device.execute().set_input_line_and_vector(INPUT_LINE_INT0, ASSERT_LINE, 0x20); |
| 775 | | |
| 776 | | MHFU_reset(); |
| 777 | 1059 | } |
| 778 | 1060 | |
| 779 | 1061 | WRITE8_MEMBER( rainbow_state::clear_video_interrupt ) |
| r26664 | r26665 | |
| 797 | 1079 | // printf("%02x to diag port (PC=%x)\n", data, space.device().safe_pc()); |
| 798 | 1080 | m_SCREEN_BLANK = (data & 2) ? false : true; |
| 799 | 1081 | |
| 800 | | if ( !(data & 0x40) && (m_diagnostic & 0x40) ) // if set to 1 (first) and later set to 0... |
| 801 | | { |
| 802 | | // SAVE / PROGRAM NVM: transfer data from volatile memory to NVM |
| 1082 | // SAVE / PROGRAM NVM: transfer data from volatile memory to NVM |
| 1083 | if ( !(data & 0x40) && (m_diagnostic & 0x40) ) |
| 803 | 1084 | memcpy( m_p_nvram, m_p_vol_ram, 256); |
| 804 | | } |
| 805 | 1085 | |
| 806 | | if ( (data & 0x80) && !(m_diagnostic & 0x80) ) // if set to 0 (first) and later set to 1... |
| 807 | | { |
| 808 | | // READ / RECALL NVM: transfer data from NVM to volatile memory |
| 1086 | // READ / RECALL NVM: transfer data from NVM to volatile memory |
| 1087 | if ( (data & 0x80) && !(m_diagnostic & 0x80) ) |
| 809 | 1088 | memcpy( m_p_vol_ram, m_p_nvram, 256); |
| 810 | | } |
| 811 | 1089 | |
| 812 | 1090 | if (!(data & 1)) |
| 813 | 1091 | { |
| r26664 | r26665 | |
| 823 | 1101 | m_z80->reset(); |
| 824 | 1102 | } |
| 825 | 1103 | |
| 1104 | /* Page 197 or 5-13 of formatter description: |
| 1105 | ZRESET L : this low input from the 8088 diagnostic write register |
| 1106 | resets the formatter controller, loads 03H into the command register, |
| 1107 | and resets the not ready (status bit 7). |
| 1108 | |
| 1109 | When ZRESET goes high (1), a restore command is executed regardless |
| 1110 | of the state of the ready signal from the diskette drive and |
| 1111 | 01H is loaded into the sector register. |
| 1112 | */ |
| 1113 | |
| 1114 | // reset device when going from high to low, |
| 1115 | // restore command when going from low to high : |
| 1116 | wd17xx_mr_w(m_fdc, (data & 1) ? 1 : 0); |
| 1117 | |
| 826 | 1118 | m_diagnostic = data; |
| 827 | 1119 | } |
| 828 | 1120 | |
| r26664 | r26665 | |
| 876 | 1168 | m_kbd8251->transmit_clock(); |
| 877 | 1169 | m_kbd8251->receive_clock(); |
| 878 | 1170 | |
| 879 | | if ( m_crtc->dc012_MHFU() ) // MHFU ENABLED? |
| 880 | | { |
| 881 | | if (MHFU_counter) |
| 882 | | MHFU_counter--; |
| 1171 | if (MOTOR_DISABLE_counter) |
| 1172 | MOTOR_DISABLE_counter--; |
| 883 | 1173 | |
| 884 | | if (MHFU_counter == 1) // resets ONCE. |
| 885 | | { |
| 886 | | printf("*** CPU RESET: MASSIVE HARDWARE FAILURE DETECTED (MHFU LOGIC ~108 ms)\n"); |
| 887 | | m_i8088->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); |
| 888 | | } |
| 1174 | if (MOTOR_DISABLE_counter == 1) |
| 1175 | { |
| 1176 | output_set_value("driveled0", 0); // DRIVE 0 (A) |
| 1177 | output_set_value("driveled1", 0); // DRIVE 1 (B) |
| 1178 | output_set_value("driveled2", 0); // DRIVE 2 (C) |
| 1179 | output_set_value("driveled3", 0); // DRIVE 3 (D) |
| 889 | 1180 | } |
| 890 | 1181 | |
| 1182 | if ( m_crtc->MHFU(1) ) // MHFU ENABLED ? |
| 1183 | { |
| 1184 | /* int data = m_crtc->MHFU(-1); // increment MHFU, return new value |
| 1185 | // if (data > 480) ... |
| 1186 | // m_crtc->MHFU(-100); |
| 1187 | // machine().schedule_hard_reset(); // not exactly a proper watchdog reset |
| 1188 | */ |
| 1189 | } |
| 1190 | |
| 891 | 1191 | if (m_beep_counter > 1) |
| 892 | 1192 | m_beep_counter--; |
| 893 | 1193 | else |
| r26664 | r26665 | |
| 928 | 1228 | DEVCB_NULL, |
| 929 | 1229 | DEVCB_NULL, |
| 930 | 1230 | DEVCB_NULL, |
| 931 | | {FLOPPY_0, FLOPPY_1} |
| 1231 | {FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3} |
| 932 | 1232 | }; |
| 933 | 1233 | |
| 934 | 1234 | static const floppy_interface floppy_intf = |
| r26664 | r26665 | |
| 938 | 1238 | DEVCB_NULL, |
| 939 | 1239 | DEVCB_NULL, |
| 940 | 1240 | DEVCB_NULL, |
| 941 | | FLOPPY_STANDARD_5_25_SSDD, |
| 942 | | LEGACY_FLOPPY_OPTIONS_NAME(default), |
| 1241 | FLOPPY_STANDARD_5_25_SSDD_80, |
| 1242 | LEGACY_FLOPPY_OPTIONS_NAME( dec100_floppy ), |
| 943 | 1243 | "floppy_5_25", |
| 944 | 1244 | NULL |
| 945 | 1245 | }; |
| r26664 | r26665 | |
| 988 | 1288 | MCFG_SOUND_ROUTE(ALL_OUTPUTS,"mono",0.50) |
| 989 | 1289 | |
| 990 | 1290 | MCFG_FD1793_ADD("wd1793", rainbow_wd17xx_interface ) |
| 991 | | MCFG_LEGACY_FLOPPY_2_DRIVES_ADD(floppy_intf) |
| 1291 | MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(floppy_intf) |
| 992 | 1292 | MCFG_SOFTWARE_LIST_ADD("flop_list","rainbow") |
| 993 | 1293 | |
| 994 | 1294 | MCFG_I8251_ADD("kbdser", i8251_intf) |
| r26664 | r26665 | |
| 998 | 1298 | MCFG_NVRAM_ADD_0FILL("nvram") |
| 999 | 1299 | MACHINE_CONFIG_END |
| 1000 | 1300 | |
| 1001 | | /* ROM definition */ |
| 1301 | |
| 1302 | |
| 1303 | // ROM definition for 100-B |
| 1002 | 1304 | ROM_START( rainbow ) |
| 1003 | 1305 | ROM_REGION(0x100000,"maincpu", 0) |
| 1004 | 1306 | ROM_LOAD( "23-022e5-00.bin", 0xf0000, 0x4000, CRC(9d1332b4) SHA1(736306d2a36bd44f95a39b36ebbab211cc8fea6e)) |
| r26664 | r26665 | |
| 1013 | 1315 | ROM_LOAD( "chargen.bin", 0x0000, 0x1000, CRC(1685e452) SHA1(bc299ff1cb74afcededf1a7beb9001188fdcf02f)) |
| 1014 | 1316 | ROM_END |
| 1015 | 1317 | |
| 1318 | // 'Rainbow 190 B' (announced March 1985) is identical hardware with alternate ROM v5.05 |
| 1319 | // According to an article in Wall Street Journal, it came with a 10 MB HD and 640 K RAM. |
| 1320 | |
| 1321 | // We have no version history. The BOOT 2.4 README reveals 'recent ROM changes for MASS 11' |
| 1322 | // in January 1985. These were not contained in the older version 04.03.11 (for PC-100-A) |
| 1323 | // and also not present in version 05.03 (from PC-100B / PC100B+). |
| 1324 | |
| 1325 | // A first glance: |
| 1326 | // => jump tables (F4000-F40083 and FC000-FC004D) were not extended. |
| 1327 | // => absolute addresses of some internal routines have changed. |
| 1328 | // => programs that do not rely on specific ROM versions should be compatible. |
| 1329 | ROM_START( rainb190 ) |
| 1330 | ROM_REGION(0x100000,"maincpu", 0) |
| 1331 | ROM_LOAD( "dec190rom0.bin", 0xf0000, 0x4000, CRC(FAC191D2) ) |
| 1332 | ROM_RELOAD(0xf4000,0x4000) |
| 1333 | ROM_LOAD( "dec190rom1.bin", 0xf8000, 0x4000, CRC(5CE59632) ) |
| 1334 | |
| 1335 | ROM_RELOAD(0xfc000,0x4000) |
| 1336 | ROM_REGION(0x1000, "chargen", 0) |
| 1337 | ROM_LOAD( "chargen.bin", 0x0000, 0x1000, CRC(1685e452) SHA1(bc299ff1cb74afcededf1a7beb9001188fdcf02f)) |
| 1338 | ROM_END |
| 1339 | |
| 1016 | 1340 | /* Driver */ |
| 1017 | 1341 | |
| 1018 | | /* YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS */ |
| 1019 | | COMP( 1982, rainbow, 0, 0, rainbow, rainbow, driver_device, 0, "Digital Equipment Corporation", "Rainbow 100B", GAME_NOT_WORKING | GAME_IMPERFECT_COLORS) |
| 1342 | /* YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS */ |
| 1343 | COMP( 1983, rainbow , 0 , 0, rainbow, rainbow100b_in, driver_device, 0, "Digital Equipment Corporation", "Rainbow 100-B", GAME_NOT_WORKING | GAME_IMPERFECT_COLORS) |
| 1344 | COMP( 1985, rainb190, rainbow, 0, rainbow, rainbow100b_in, driver_device, 0, "Digital Equipment Corporation", "Rainbow 190-B", GAME_NOT_WORKING | GAME_IMPERFECT_COLORS) |
| | No newline at end of file |