(MESS) Rainbow 100 updates: [Bavarese]

- added DEC-190-B model
- preliminary floppy (TD0 / IMG)
- corrected LK201 keyboard matrix (C12, Do + cursor keys)
- MHFU changes; character display speedups
- nicer bezel with 'C' + 'D' drive leds
This commit is contained in:
R. Belmont 2013-12-20 03:30:14 +00:00
parent 10be53e45e
commit 17d7b519a6
8 changed files with 678 additions and 255 deletions

View File

@ -34,6 +34,7 @@
#define FLOPPY_STANDARD_5_25_SSSD { FLOPPY_DRIVE_5_25_INCH, 1, 42, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_5_25_DSSD { FLOPPY_DRIVE_5_25_INCH, 2, 42, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_5_25_SSDD_40 { FLOPPY_DRIVE_5_25_INCH, 1, 42, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_SSDD_80 { FLOPPY_DRIVE_5_25_INCH, 1, 83, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_DSDD_40 { FLOPPY_DRIVE_5_25_INCH, 2, 42, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_SSDD { FLOPPY_DRIVE_5_25_INCH, 1, 83, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_DSDD { FLOPPY_DRIVE_5_25_INCH, 2, 83, FLOPPY_DRIVE_DD }

View File

@ -1,30 +1,36 @@
/***************************************************************************
/***************************************************************************************************
DEC Rainbow 100
Driver-in-progress by R. Belmont and Miodrag Milanovic with additions by Karl-Ludwig Deisenhofer.
Driver-in-progress by R. Belmont and Miodrag Milanovic.
Portions (2013) by Karl-Ludwig Deisenhofer (VT video, floppy, preliminary keyboard, DIP switches).
STATE AS OF NOVEMBER 2013
STATE AS OF DECEMBER 2013
--------------------------
- FATAL: keyboard emulation incomplete (inhibits the system from booting with ERROR 50 on cold or ERROR 13 on warm boot).
- NOT WORKING: serial (ERROR 60).
- 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));
- WORKAROUND AVAILABLE: keyboard emulation incomplete (inhibits the system from booting with ERROR 50 on cold or ERROR 13 on warm boot).
- NOT WORKING: serial (ERROR 60).
- NOT WORKING: printer interface (ERROR 40). Like error 60 not mission-critical.
- NON-CRITICAL: watchdog logic (triggered after 108 ms without interrupts) still not exactly by the book.
- NON-CRITICAL: watchdog logic (triggered after 108 ms without interrupts on original machine) still does not work as intended.
Timer is reset by TWO sources: the VERT INT L from the DC012, or the MHFU ENB L from the enable flip-flop.
The MHFU gets active if the 8088 has not acknowledged a video processor interrupt within approx. 108 milliseconds.
BIOS assumes a power-up reset if MHFU detection is disabled - and assumes a MHFU reset if MHFU detection is ENABLED.
Therefore a 'warm boot' within MESS (F3) causes ERROR 16.
As there is no reset switch, only a limited software reset exists on a real DEC-100 (CTRL-SETUP within SETUP).
- SHOULD BE IMPLEMENTED AS SLOT DEVICES (for now, DIP settings affect 'system_parameter_r' only and are disabled):
- TO BE IMPLEMENTED AS SLOT DEVICES (for now, DIP settings affect 'system_parameter_r' only and are disabled):
* Color graphics option (uses NEC upd7220 GDC)
* Extended communication option (same as BUNDLE_OPTION ?)
- OTHER UPGRADES (NEC_V20 should be easy, the TURBOW is harder to come by)
* 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). Changed BOOT ROM labeled 'TBSS1.3 - 3ED4'.
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'.
* 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.
@ -154,28 +160,25 @@ W16 pulls J2 printer port pin 1 to GND when set (chassis to logical GND).
W17 pulls J1 serial port pin 1 to GND when set (chassis to logical GND).
****************************************************************************/
/*
HARD DISC SIZES AND LIMITS
HARDWARE: the Rainbow winchester controller has a built-in limit of 8 heads and 1024 cylinders (67 MB). Standard geometry is 4 surfaces.
SOFTWARE: the original DEC boot loader (and FDISK from DOS 3.10) initially allowed a maximum hard disc size of 20 MB.
- DOS 3 has a 1024 cylinder limit (32 MB).
- the custom boot loader that comes with 'WUTIL 3.2' stretches limits to 117 MB and 8 surfaces.
*/
// Workarounds DO NOT APPLY to the 190-B ROM. Only enable when compiling the 'rainbow' driver -
//#define FORCE_RAINBOW_100_LOGO
#define KBD_DELAY 875 // (debounce delay). Recommended: 875.
#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/i8251.h"
#include "machine/dec_lk201.h"
#include "sound/beep.h"
#include "machine/nvram.h"
#include "rainbow.lh" // BEZEL - LAYOUT with LEDs for diag 1-7, keyboard 8-11 and floppy 20-21
#include "rainbow.lh" // BEZEL - LAYOUT with LEDs for diag 1-7, keyboard 8-11 and floppy 20-23
class rainbow_state : public driver_device
{
@ -248,6 +251,7 @@ public:
DECLARE_READ8_MEMBER(floating_bus_r);
DECLARE_WRITE8_MEMBER(floating_bus_w);
DECLARE_READ8_MEMBER(hd_status_68_r);
// EMULATOR TRAP TO INTERCEPT KEYBOARD cmd in AH and PARAMETER in AL (port 90 = AL / port 91 = AH)
// TODO: beeper and led handling should better be handled by LK201 code.
DECLARE_WRITE8_MEMBER(PORT90_W);
@ -261,7 +265,11 @@ public:
DECLARE_WRITE8_MEMBER(z80_diskdiag_read_w);
DECLARE_WRITE8_MEMBER(z80_diskdiag_write_w);
DECLARE_WRITE8_MEMBER(z80_diskcontrol_write_w);
DECLARE_READ8_MEMBER(z80_generalstat_r);
DECLARE_READ8_MEMBER(z80_diskstatus_r);
DECLARE_WRITE8_MEMBER(z80_diskcontrol_w);
DECLARE_READ8_MEMBER(system_parameter_r);
DECLARE_READ_LINE_MEMBER(dsr_r);
@ -273,22 +281,29 @@ public:
bool m_SCREEN_BLANK;
int INT88, INTZ80;
bool m_zflip; // Z80 alternate memory map with A15 inverted
bool m_z80_halted;
int m_z80_diskcontrol; // retains values needed for status register
bool m_kbd_tx_ready, m_kbd_rx_ready;
int m_KBD;
int m_beep_counter;
int MOTOR_DISABLE_counter;
int MHFU_counter;
int COLD_BOOT;
private:
UINT8 m_z80_private[0x800]; // Z80 private 2K
UINT8 m_z80_mailbox, m_8088_mailbox;
void update_kbd_irq();
virtual void machine_reset();
void MHFU_reset();
int m_unit;
device_t *m_image[4];
public:
UINT32 screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(vblank_irq);
@ -296,8 +311,16 @@ public:
required_device<cpu_device> m_maincpu;
};
void rainbow_state::machine_start()
{
m_image[0] = subdevice(FLOPPY_0);
m_image[1] = subdevice(FLOPPY_1);
m_image[2] = subdevice(FLOPPY_2);
m_image[3] = subdevice(FLOPPY_3);
COLD_BOOT = 1;
m_SCREEN_BLANK = false;
save_item(NAME(m_z80_private));
@ -309,31 +332,41 @@ void rainbow_state::machine_start()
UINT8 *rom = memregion("maincpu")->base();
#ifdef FORCE_RAINBOW_100_LOGO
rom[0xf4174]=0xeb; // jmps RAINBOW100_LOGO__loc_33D
rom[0xf4175]=0x08;
rom[0xf4000 + 0x364a]= 0x0a;
rom[0xf4384]=0xeb; // JMPS => BOOT80
#endif
// Enables PORT90_W + PORT91_W via BIOS call (offset +$21 in HIGH ROM)
// F8 / FC ROM REGION (CHECK + PATCH)
if(rom[0xfc000 + 0x0022] == 0x22 && rom[0xfc000 + 0x0023] == 0x28)
{
rom[0xf4303]=0x00; // Disable CRC CHECK (F0 / F4 ROM)
rom[0xfc000 + 0x0022] =0xe2; // jmp to offset $3906
rom[0xfc000 + 0x0023] =0x38;
rom[0xfc000 + 0x0022] =0xfe; // jmp to offset $1922
rom[0xfc000 + 0x0023] =0x18;
rom[0xfc000 + 0x3906] =0xe6; // out 90,al
rom[0xfc000 + 0x3907] =0x90;
rom[0xfc000 + 0x1922] =0xe6; // out 90,al
rom[0xfc000 + 0x1923] =0x90;
rom[0xfc000 + 0x3908] =0x86; // xchg al,ah
rom[0xfc000 + 0x3909] =0xc4;
rom[0xfc000 + 0x1924] =0x86; // xchg al,ah
rom[0xfc000 + 0x1925] =0xc4;
rom[0xfc000 + 0x390a] =0xe6; // out 91,al
rom[0xfc000 + 0x390b] =0x91;
rom[0xfc000 + 0x1926] =0xe6; // out 91,al
rom[0xfc000 + 0x1927] =0x91;
rom[0xfc000 + 0x390c] =0x86; // xchg al,ah
rom[0xfc000 + 0x390d] =0xc4;
rom[0xfc000 + 0x1928] =0x86; // xchg al,ah
rom[0xfc000 + 0x1929] =0xc4;
rom[0xfc000 + 0x390e] =0xe9; // jmp (original jump offset $2846)
rom[0xfc000 + 0x390f] =0x35;
rom[0xfc000 + 0x3910] =0xef;
rom[0xfc000 + 0x192a] =0xe9; // jmp (original jump offset $2846) e9 + 19 0f
rom[0xfc000 + 0x192b] =0x19;
rom[0xfc000 + 0x192c] =0x0f;
}
}
static ADDRESS_MAP_START( rainbow8088_map, AS_PROGRAM, 8, rainbow_state)
@ -374,6 +407,8 @@ static ADDRESS_MAP_START( rainbow8088_io , AS_IO, 8, rainbow_state)
// 0x04 Video processor DC011
AM_RANGE (0x04, 0x04) AM_DEVWRITE("vt100_video", rainbow_video_device, dc011_w)
// TODO: unmapped [06] : Communication bit rates (see page 21 of PC 100 SPEC)
AM_RANGE (0x08, 0x08) AM_READ(system_parameter_r)
AM_RANGE (0x0a, 0x0a) AM_READWRITE(diagnostic_r, diagnostic_w)
@ -381,9 +416,37 @@ static ADDRESS_MAP_START( rainbow8088_io , AS_IO, 8, rainbow_state)
// 0x0C Video processor DC012
AM_RANGE (0x0c, 0x0c) AM_DEVWRITE("vt100_video", rainbow_video_device, dc012_w)
// TODO: unmapped [0e] : PRINTER BIT RATE REGISTER (WO)
AM_RANGE(0x10, 0x10) AM_DEVREADWRITE("kbdser", i8251_device, data_r, data_w)
AM_RANGE(0x11, 0x11) AM_DEVREADWRITE("kbdser", i8251_device, status_r, control_w)
// UNMAPPED:
// 0x20 - 0x2f ***** EXTENDED COMM. OPTION (option select 1)- for example:
// 0x27 (RESET EXTENDED COMM OPTION) - OUT 27 @ offset 1EA7
// 0x40 COMMUNICATIONS DATA REGISTER (MPSC)
// 0x41 PRINTER DATA REGISTER (MPSC)
// 0x42 COMMUNICATIONS CONTROL / STATUS REGISTER (MPSC)
// 0x43 PRINTER CONTROL / STATUS REGISTER (MPSC)
// 0x50 - 0xf ***** OPTIONAL COLOR GRAPHICS - for example:
// 0x50 (RESET_GRAPH. OPTION) - OUT 50 @ offsets F5EB5 + F5EB9
// ===========================================================
// TODO: hard disc emulation!
// ------ Rainbow uses 'WD 1010 AL' (Western Digital 1983)
// Register compatible to WD2010 (present in MESS)
// R/W REGISTERS 60 - 68 (?)
// ===========================================================
// HARD DISC SIZES AND LIMITS
// HARDWARE:
// Controller has a built-in limit of 8 heads / 1024 cylinders (67 MB). Standard geometry is 4 surfaces.
// SOFTWARE: the DEC boot loader (and FDISK from DOS 3.10) initially allowed a maximum hard disc size of 20 MB.
// - DOS 3 has a 1024 cylinder limit (32 MB).
// - the custom boot loader that comes with 'WUTIL 3.2' allows 117 MB and 8 surfaces.
AM_RANGE (0x68, 0x68) AM_READ(hd_status_68_r)
AM_RANGE (0x90, 0x90) AM_WRITE(PORT90_W)
AM_RANGE (0x91, 0x91) AM_WRITE(PORT91_W)
ADDRESS_MAP_END
@ -397,9 +460,9 @@ static ADDRESS_MAP_START( rainbowz80_io, AS_IO, 8, rainbow_state)
ADDRESS_MAP_UNMAP_HIGH
ADDRESS_MAP_GLOBAL_MASK(0xff)
AM_RANGE(0x00, 0x00) AM_READWRITE(z80_latch_r, z80_latch_w)
AM_RANGE(0x20, 0x20) AM_WRITE(z80_diskdiag_read_w)
AM_RANGE(0x21, 0x21) AM_WRITE(z80_diskdiag_write_w)
AM_RANGE(0x40, 0x40) AM_WRITE(z80_diskcontrol_write_w)
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_LEGACY("wd1793", wd17xx_status_r, wd17xx_command_w)
AM_RANGE(0x61, 0x61) AM_DEVREADWRITE_LEGACY("wd1793", wd17xx_track_r, wd17xx_track_w)
AM_RANGE(0x62, 0x62) AM_DEVREADWRITE_LEGACY("wd1793", wd17xx_sector_r, wd17xx_sector_w)
@ -407,28 +470,16 @@ static ADDRESS_MAP_START( rainbowz80_io, AS_IO, 8, rainbow_state)
ADDRESS_MAP_END
/* Input ports */
static INPUT_PORTS_START( rainbow )
/* KEYBOARD (preliminary - transfer to DEC_LK201.xx as soon as possible) */
static INPUT_PORTS_START( rainbow100b_in )
/* DIP switches */
PORT_START("MONITOR TYPE")
PORT_DIPNAME( 0x03, 0x03, "MONOCHROME MONITOR")
PORT_DIPSETTING( 0x01, "PAPER WHITE" )
PORT_DIPSETTING( 0x02, "GREEN" )
PORT_DIPSETTING( 0x03, "AMBER" )
PORT_START("FLOPPY CONTROLLER")
PORT_DIPNAME( 0x02, 0x02, "FLOPPY CONTROLLER") PORT_TOGGLE
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x02, DEF_STR( On ) )
PORT_START("GRAPHICS OPTION")
PORT_DIPNAME( 0x00, 0x00, "GRAPHICS OPTION") PORT_TOGGLE
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
PORT_START("BUNDLE OPTION")
PORT_DIPNAME( 0x00, 0x00, "BUNDLE OPTION") PORT_TOGGLE
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
PORT_START("MEMORY PRESENT")
PORT_DIPNAME( 0xF000, 0x2000, "MEMORY PRESENT")
PORT_DIPSETTING( 0x2000, "128 K (BOARD DEFAULT)" ) // NOTE: 0x2000 hard coded in 'system_parameter_r'
@ -445,7 +496,17 @@ static INPUT_PORTS_START( rainbow )
PORT_DIPSETTING( 0xD000, "832 K (MEMORY OPTION)" )
PORT_DIPSETTING( 0xE000, "896 K (MEMORY OPTION)" )
PORT_START("W13")
PORT_START("GRAPHICS OPTION")
PORT_DIPNAME( 0x00, 0x00, "GRAPHICS OPTION") PORT_TOGGLE
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
PORT_START("BUNDLE OPTION")
PORT_DIPNAME( 0x00, 0x00, "BUNDLE OPTION") PORT_TOGGLE
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
PORT_START("W13") // W13 - W18 affect 'system_parameter_r'
PORT_DIPNAME( 0x02, 0x02, "W13 (FACTORY TEST A, LEAVE OFF)") PORT_TOGGLE
PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
@ -462,20 +523,41 @@ static INPUT_PORTS_START( rainbow )
PORT_DIPNAME( 0x01, 0x00, "W18 (FACTORY TEST D, LEAVE OFF) (8251A: DSR)") PORT_TOGGLE
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
// J17 jumper on FDC controller board shifts drive select (experimental) -
PORT_START("FLOPPY CONTROLLER")
PORT_DIPNAME( 0x02, 0x00, "J17 DRIVE SELECT (A => C and B => D)") PORT_TOGGLE
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x02, DEF_STR( On ) )
INPUT_PORTS_END
void rainbow_state::MHFU_reset()
{
MHFU_counter = 530; // 528 = 110ms
}
// 800K native format (80 * 10). Also reads VT-180 disks and PC-DOS 360 k disks
// ( both: 512 byte sectors, single sided, 9 sectors per track, 40 tracks )
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(9/[10])
SECTOR_LENGTH([512])
INTERLEAVE([0])
FIRST_SECTOR_ID([1])
)
LEGACY_FLOPPY_OPTIONS_END
void rainbow_state::machine_reset()
{
MHFU_reset();
if (COLD_BOOT == 1)
{
COLD_BOOT = 2;
m_crtc->MHFU(-100); // reset MHFU counter
}
m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
INT88 = false;
INTZ80 = false;
m_zflip = true;
m_z80_halted = true;
m_kbd_tx_ready = m_kbd_rx_ready = false;
@ -500,12 +582,17 @@ void rainbow_state::machine_reset()
output_set_value("led10", 1);
output_set_value("led11", 1);
output_set_value("led20", 1); // DRIVE 0 (A)
output_set_value("led21", 1); // DRIVE 1 (B)
MOTOR_DISABLE_counter = 2; // soon resets drv.LEDs
m_unit = 0;
}
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;
m_crtc->palette_select( m_inp9->read() );
if ( m_SCREEN_BLANK )
@ -516,31 +603,36 @@ UINT32 rainbow_state::screen_update_rainbow(screen_device &screen, bitmap_ind16
}
// It is no longer possible to key in the RAM size on the 100-B.
// The DEC-100-B boot ROM probes until a 'flaky' area is found (around F400:xxxx).
// The DEC-100-B boot ROM probes until a 'flaky' area is found (around F400:0E04).
// Unexpected low RAM sizes are an indication of option RAM (at worst: 128 K on board) failure.
// While motherboard errors often render the system unbootable, bad option RAM (> 128 K)
// can be narrowed down with a diagnostic disk and codes from the 'Pocket Service Guide'
// can be narrowed down with the Diagnostic Disk and codes from the 'Pocket Service Guide'
// EK-PC100-PS-002 (APPENDIX B.2.2); pc100ps2.pdf
// Simulate floating bus for initial RAM detection:
// ================================================================
// - Simulate floating bus for initial RAM detection -
// FIXME: code valid ONLY within ROM section F4Exxx.
//
// NOTE: MS-DOS 2.x unfortunately probes RAM in a similar way.
// => SET OPTION RAM to 896 K for unknown applications (and DOS) <=
// ================================================================
READ8_MEMBER(rainbow_state::floating_bus_r)
{
if ( m_maincpu->state_int(I8086_CS) != 0xF400)
return space.read_byte(offset);
int pc = space.device().safe_pc();
if ( m_maincpu->state_int(I8086_DS) < m_inp8->read() )
{
return space.read_byte(offset);
} else
if ( ((pc & 0xFFF00) == 0xF4E00) &&
( m_maincpu->state_int(I8086_DS) >= m_inp8->read() )
)
{
return (offset>>16) + 2;
}
}
else
return space.read_byte(offset);
}
WRITE8_MEMBER(rainbow_state::floating_bus_w)
{
space.write_byte(offset,data);
space.write_byte(offset,data);
}
@ -600,6 +692,17 @@ WRITE8_MEMBER(rainbow_state::share_z80_w)
}
}
// Until a full-blown hard-disc emulation evolves, deliver an error message:
READ8_MEMBER(rainbow_state::hd_status_68_r)
{
// Top 3 bits = status / error code
// SEE -> W_INCHESTER__loc_80E
// return 0xa0; // A0 : OK, DRIVE IS READY (!)
return 0xe0; // => 21 DRIVE NOT READY (BIOS; when W is pressed on boot screen)
}
READ8_MEMBER(rainbow_state::system_parameter_r)
{
/* Info about option boards is in bits 0 - 3:
@ -610,21 +713,33 @@ READ8_MEMBER(rainbow_state::system_parameter_r)
( 1 means NOT present )
*/
// Hard coded value 0x2000 - see DIP switch setup!
return 0x0f - m_inp5->read() - m_inp6->read() - m_inp7->read() - (
(m_inp8->read() > 0x2000) ? 8 : 0
);
return 0x0f - m_inp5->read()
- 0 // floppy is hard coded in emulator.
- m_inp7->read()
- (m_inp8->read() > 0x2000) ? 8 : 0;
}
READ8_MEMBER(rainbow_state::comm_control_r)
{
/*
--> What the specs says on how MHFU detection is disabled:
// 1. by first disabling interrupts with CLI
// 2. by writing 0x00 to port 0x10C (handled by 'dc012_w' in vtvideo)
// (3.) MHFU is re-enabled by writing to 0x0c (or automatically after STI - when under BIOS control ?)
*/
return ( ( m_crtc->dc012_MHFU() << 5) // shift status of DC012 - MHFU flag to bit pos.5
);
/* [02] COMMUNICATIONS STATUS REGISTER - PAGE 154 (**** READ **** )
Used to read status of SERIAL port, IRQ line of each CPU, and MHFU logic enable signal.
// What the specs says on how MHFU detection is disabled:
// 1. by first disabling interrupts with CLI
// 2. by writing 0x00 to port 0x10C (handled by 'dc012_w' in vtvideo)
// (3.) MHFU is re-enabled by writing to 0x0c (or automatically after STI - when under BIOS control ?)
*/
// During boot phase 2, do not consider MHFU ENABLE. Prevents ERROR 16.
int data;
if (COLD_BOOT == 2)
data = 0;
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)
);
}
WRITE8_MEMBER(rainbow_state::comm_control_w)
@ -651,42 +766,55 @@ WRITE8_MEMBER(rainbow_state::PORT90_W)
m_KBD = 0; // reset previous command.
if (data == 0xfd) { // Powerup (beep)
if(MOTOR_DISABLE_counter == 0)
{
if (data == LK_CMD_POWER_UP) { // Powerup (beep)
//m_beep->set_state(1);
//m_beep_counter=600; // BELL = 125 ms
}
if (data == LK_CMD_BELL) {
m_KBD = data;
m_beep->set_state(1);
m_beep_counter=600; // BELL = 125 ms
}
if (data == 0xa7) {
m_beep->set_state(1);
m_beep_counter=600; // BELL = 125 ms
}
if (data == 0x9f) { // emit a keyclick (2ms)
if (data == LK_CMD_SOUND_CLK) { // emit a keyclick (2ms)
m_KBD = data;
m_beep->set_state(1);
m_beep_counter=25; // longer than calculated ( 9,6 )
}
if (data == 0x13) { // light LEDs -
m_KBD = 0x13;
if (data == LK_CMD_ENB_BELL) { // enable the bell - PARAMETER: VOLUME!
m_KBD = data;
}
if (data == 0x11) { // switch off LEDs -
m_KBD = 0x11;
if (data == LK_CMD_ENB_KEYCLK) { // enable the keyclick- PARAMETER: VOLUME!
m_KBD = data;
}
if (data == LK_CMD_LEDS_ON ) { // light LEDs -
m_KBD = data;
}
if (data == LK_CMD_LEDS_OFF) { // switch off LEDs -
m_KBD = data;
}
} // prevent beeps during disk load operations
}
WRITE8_MEMBER(rainbow_state::PORT91_W)
{
//printf("KBD PARAM %02x to AH (91) \n", data);
// 4 leds, represented in the low 4 bits of a byte
if (m_KBD == 0x13) { // light LEDs -
if (m_KBD == LK_CMD_LEDS_ON) { // light LEDs -
if (data & 1) { output_set_value("led8", 0); } // KEYBOARD : "Wait" LED
if (data & 2) { output_set_value("led9", 0); } // KEYBOARD : "Compose" LED
if (data & 4) { output_set_value("led10", 0); } // KEYBOARD : "Lock" LED
if (data & 8) { output_set_value("led11", 0); } // KEYBOARD : "Hold" LED
m_KBD = 0; // reset previous command.
}
if (m_KBD == 0x11) { // switch off LEDs -
if (m_KBD == LK_CMD_LEDS_OFF) { // switch off LEDs -
if (data & 1) { output_set_value("led8", 1); } // KEYBOARD : "Wait" LED
if (data & 2) { output_set_value("led9", 1); } // KEYBOARD : "Compose" LED
if (data & 4) { output_set_value("led10", 1); } // KEYBOARD : "Lock" LED
@ -694,45 +822,113 @@ WRITE8_MEMBER(rainbow_state::PORT91_W)
m_KBD = 0; // reset previous command.
}
if (m_KBD == 0x1b) { /* enable the keyclick */
/* max volume is 0, lowest is 0x7 */
// NVRAM offet $A8 : BELL VOLUME (=> ENABLE BELL 0x23)
if ( (m_KBD == LK_CMD_BELL) || (m_KBD == LK_CMD_ENB_BELL) ) /* BOTH sound or enable bell have a parameter */
{ /* max volume is 0, lowest is 0x7 */
// printf("\n%02x BELL CMD has bell volume = %02x\n", m_KBD, 8 - (data & 7));
m_KBD = 0; // reset previous command.
}
}
// NVRAM offet $A9 = KEYCLICK VOLUME (=> ENABLE CLK 0x1b)
// NVRAM offset $8C = KEYCLICK ENABLE / DISABLE (0/1)
if ( ( m_KBD == LK_CMD_ENB_KEYCLK ) || ( m_KBD == LK_CMD_SOUND_CLK ) ) /* BOTH keyclick cmds have a parameter */
{ // max volume is 0, lowest is 0x7 - 87 (BELL VOL:1) and 80 (BELL VOL:8)
// printf("\n%02x CLICK CMD - keyclick volume = %02x\n", m_KBD, 8 - (data & 7));
m_KBD = 0; // reset previous command.
}
if (m_KBD > 0)
printf("UNHANDLED PARAM FOR MODE: %02x / KBD PARAM %02x to AH (91) \n", m_KBD, data);
}
// 8088 reads port 0x00. See page 133 (4-34)
READ8_MEMBER(rainbow_state::i8088_latch_r)
{
// printf("Read %02x from 8088 mailbox\n", m_8088_mailbox);
m_i8088->set_input_line(INPUT_LINE_INT0, CLEAR_LINE);
INT88 = false; // BISLANG: INTZ80 = false; //
return m_8088_mailbox;
}
// 8088 writes port 0x00. See page 133 (4-34)
WRITE8_MEMBER(rainbow_state::i8088_latch_w)
{
// printf("%02x to Z80 mailbox\n", data);
m_z80->set_input_line_and_vector(0, ASSERT_LINE, 0xf7);
m_z80_mailbox = data;
INTZ80 = true; //
}
// Z80 reads port 0x00
// See page 134 (4-35)
READ8_MEMBER(rainbow_state::z80_latch_r)
{
// printf("Read %02x from Z80 mailbox\n", m_z80_mailbox);
m_z80->set_input_line(0, CLEAR_LINE);
INTZ80 = false; // BISLANG: INT88 = false;
return m_z80_mailbox;
}
// Z80 writes to port 0x00
// See page 134 (4-35)
WRITE8_MEMBER(rainbow_state::z80_latch_w)
{
// printf("%02x to 8088 mailbox\n", data);
// printf("%02x to 8088 mailbox\n", data);
m_i8088->set_input_line_and_vector(INPUT_LINE_INT0, ASSERT_LINE, 0x27);
m_8088_mailbox = data;
INT88 = true;
}
// WRITE to 0x20
WRITE8_MEMBER(rainbow_state::z80_diskdiag_read_w)
{
m_zflip = true;
}
// (Z80) : PORT 21H _READ_
READ8_MEMBER(rainbow_state::z80_generalstat_r)
{
/*
General / diag.status register Z80 / see page 157 (table 4-18).
D7 : STEP L : reflects status of STEP signal _FROM FDC_
(when this 2us output pulse is low, the stepper will move into DIR)
D6 : WRITE GATE L :reflects status of WRITE GATE signal _FROM FDC_
(asserted low before data can be written on the diskette)
D5 : TR00: reflects status of TRACK 0 signal (= 1) * from the disk drive *
D4 : DIR L: reflects status of DIRECTION signal * FROM FDC * to disk
(when low, the head will step towards the center)
D3 : READY L: reflects status of READY L signal * from the disk drive *
(low active, asserts when disk is inserted and door is closed)
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 = ( floppy_tk00_r( m_image[m_unit] ) == CLEAR_LINE ) ? 0x20 : 0x00;
int fdc_ready = floppy_drive_get_flag_state( m_image[m_unit] , FLOPPY_DRIVE_READY);
int data=( 0x80 | // (STEP L)
// ( (fdc_write_gate) ) |
( (tk00) ) |
// ( fdc_direction) |
( (fdc_ready)? 0x00 : 0x08 ) |
( (INT88) ? 0x00 : 0x04 ) |
( (INTZ80) ? 0x00 : 0x02 ) |
( (m_zflip) ? 0x00 : 0x01 )
);
return data;
}
// (Z80) : PORT 21H * WRITE *
WRITE8_MEMBER(rainbow_state::z80_diskdiag_write_w)
{
/* Z80 LEDs:
@ -747,21 +943,109 @@ WRITE8_MEMBER(rainbow_state::z80_diskdiag_write_w)
m_zflip = false;
}
WRITE8_MEMBER(rainbow_state::z80_diskcontrol_write_w)
// (Z80) : PORT 40H _READ_
// **********************************************************************
// POLARITY OF _DRQ_ AND _IRQ_ (depends on controller type!)
// **********************************************************************
READ8_MEMBER(rainbow_state::z80_diskstatus_r)
{
//printf("%02x to z80 DISK CONTROL (W)\n", data);
static int last_track;
int track = wd17xx_track_r(m_fdc, space, 0);
// TODO: this logic is a bit primitive. According to the spec, the RX-50 drive LED only turns on if
// (a) spindle motor runs (b) disk is in drive (c) door closed (d) drive side is selected
if ( (data & 1) && (data & 8) )
output_set_value("led20", 0); // DISKETTE 0 SELECTED & MOTOR 0 ON => LIGHT "DRIVE A"
else
output_set_value("led20", 1);
if (track != last_track)
printf("\n%02d",track);
last_track = track;
if ( (data & 2) && (data & 8) )
output_set_value("led21", 0); // DISKETTE 1 SELECTED & MOTOR 0 ON => LIGHT "DRIVE B"
// 40H diskette status Register **** READ ONLY *** ( 4-60 of TM100.pdf )
// AND 00111011 - return what was WRITTEN to D5-D3, D1, D0 previously
// (except D7,D6,D2)
int data = m_z80_diskcontrol && 0x3b;
// D7: DRQ: reflects status of DATA REQUEST signal from FDC.
// '1' indicates that FDC has read data OR requires new write data.
data |= wd17xx_drq_r(m_fdc) ? 0x80 : 0x00;
// D6: IRQ: indicates INTERRUPT REQUEST signal from FDC. Indicates that a
// status bit has changed. Set to 1 at the completion of any
// command (.. see page 207 or 5-25).
data |= wd17xx_intrq_r(m_fdc) ? 0x40 : 0x00;
// D5: SIDE 0H: status of side select signal at J2 + J3 of RX50 controller.
// For 1 sided drives, this bit will always read low (0).
// D4: MOTOR 1 ON L: 0 = indicates MOTOR 1 ON bit is set in drive control reg.
// 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;
// D1: DS1 H: reflect status of bits 0 and 1 form disk.control reg.
// D0: DS0 H: "
return data;
}
// (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;
int drive;
if ( m_inp6->read() && ((data & 3) < 2) )
drive = (data & 1) + 2;
else
output_set_value("led21", 1);
drive = data & 3;
int selected_drive = 255;
if (flopimg_get_image( floppy_get_device( machine(), drive ) ) != NULL)
{ selected_drive = drive;
wd17xx_set_drive(m_fdc, selected_drive);
}
// WD emulation (wd17xx.c) will ignore 'side select' if set to WD1793.
// Is it safe to * always assume * single sided 400 K disks?
wd17xx_set_side(m_fdc, (data & 20) ? 1 : 0);
wd17xx_dden_w(m_fdc, 0); /* SEE 'WRITE_TRACK' : 1 = SD; 0 = DD; enable double density */
output_set_value("driveled0", (selected_drive == 0) ? 1 : 0 );
output_set_value("driveled1", (selected_drive == 1) ? 1 : 0 );
output_set_value("driveled2", (selected_drive == 2) ? 1 : 0 );
output_set_value("driveled3", (selected_drive == 3) ? 1 : 0 );
if (selected_drive < 4)
{
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
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 -
floppy_mon_w(m_image[f_num], (f_num == selected_drive) ? CLEAR_LINE : ASSERT_LINE);
// Parameters: DRIVE, STATE, FLAG
floppy_drive_set_ready_state( m_image[f_num],
(f_num == selected_drive) ? 1 : 0,
(f_num == selected_drive) ? force_ready : 0
);
}
}
m_z80_diskcontrol = data;
}
READ8_MEMBER( rainbow_state::read_video_ram_r )
@ -772,8 +1056,6 @@ READ8_MEMBER( rainbow_state::read_video_ram_r )
INTERRUPT_GEN_MEMBER(rainbow_state::vblank_irq)
{
device.execute().set_input_line_and_vector(INPUT_LINE_INT0, ASSERT_LINE, 0x20);
MHFU_reset();
}
WRITE8_MEMBER( rainbow_state::clear_video_interrupt )
@ -797,17 +1079,13 @@ WRITE8_MEMBER( rainbow_state::diagnostic_w )
// printf("%02x to diag port (PC=%x)\n", data, space.device().safe_pc());
m_SCREEN_BLANK = (data & 2) ? false : true;
if ( !(data & 0x40) && (m_diagnostic & 0x40) ) // if set to 1 (first) and later set to 0...
{
// SAVE / PROGRAM NVM: transfer data from volatile memory to NVM
// 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);
}
if ( (data & 0x80) && !(m_diagnostic & 0x80) ) // if set to 0 (first) and later set to 1...
{
// READ / RECALL NVM: transfer data from NVM to volatile memory
// 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))
{
@ -823,6 +1101,20 @@ WRITE8_MEMBER( rainbow_state::diagnostic_w )
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).
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.
*/
// reset device when going from high to low,
// restore command when going from low to high :
wd17xx_mr_w(m_fdc, (data & 1) ? 1 : 0);
m_diagnostic = data;
}
@ -876,16 +1168,24 @@ TIMER_DEVICE_CALLBACK_MEMBER(rainbow_state::keyboard_tick)
m_kbd8251->transmit_clock();
m_kbd8251->receive_clock();
if ( m_crtc->dc012_MHFU() ) // MHFU ENABLED?
{
if (MHFU_counter)
MHFU_counter--;
if (MOTOR_DISABLE_counter)
MOTOR_DISABLE_counter--;
if (MHFU_counter == 1) // resets ONCE.
{
printf("*** CPU RESET: MASSIVE HARDWARE FAILURE DETECTED (MHFU LOGIC ~108 ms)\n");
m_i8088->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
}
if (MOTOR_DISABLE_counter == 1)
{
output_set_value("driveled0", 0); // DRIVE 0 (A)
output_set_value("driveled1", 0); // DRIVE 1 (B)
output_set_value("driveled2", 0); // DRIVE 2 (C)
output_set_value("driveled3", 0); // DRIVE 3 (D)
}
if ( m_crtc->MHFU(1) ) // MHFU ENABLED ?
{
/* int data = m_crtc->MHFU(-1); // increment MHFU, return new value
// if (data > 480) ...
// m_crtc->MHFU(-100);
// machine().schedule_hard_reset(); // not exactly a proper watchdog reset
*/
}
if (m_beep_counter > 1)
@ -928,7 +1228,7 @@ const wd17xx_interface rainbow_wd17xx_interface =
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
{FLOPPY_0, FLOPPY_1}
{FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3}
};
static const floppy_interface floppy_intf =
@ -938,8 +1238,8 @@ static const floppy_interface floppy_intf =
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
FLOPPY_STANDARD_5_25_SSDD,
LEGACY_FLOPPY_OPTIONS_NAME(default),
FLOPPY_STANDARD_5_25_SSDD_80,
LEGACY_FLOPPY_OPTIONS_NAME( dec100_floppy ),
"floppy_5_25",
NULL
};
@ -988,7 +1288,7 @@ static MACHINE_CONFIG_START( rainbow, rainbow_state )
MCFG_SOUND_ROUTE(ALL_OUTPUTS,"mono",0.50)
MCFG_FD1793_ADD("wd1793", rainbow_wd17xx_interface )
MCFG_LEGACY_FLOPPY_2_DRIVES_ADD(floppy_intf)
MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(floppy_intf)
MCFG_SOFTWARE_LIST_ADD("flop_list","rainbow")
MCFG_I8251_ADD("kbdser", i8251_intf)
@ -998,7 +1298,9 @@ static MACHINE_CONFIG_START( rainbow, rainbow_state )
MCFG_NVRAM_ADD_0FILL("nvram")
MACHINE_CONFIG_END
/* ROM definition */
// ROM definition for 100-B
ROM_START( rainbow )
ROM_REGION(0x100000,"maincpu", 0)
ROM_LOAD( "23-022e5-00.bin", 0xf0000, 0x4000, CRC(9d1332b4) SHA1(736306d2a36bd44f95a39b36ebbab211cc8fea6e))
@ -1013,7 +1315,30 @@ ROM_START( rainbow )
ROM_LOAD( "chargen.bin", 0x0000, 0x1000, CRC(1685e452) SHA1(bc299ff1cb74afcededf1a7beb9001188fdcf02f))
ROM_END
// 'Rainbow 190 B' (announced March 1985) is identical hardware with alternate ROM v5.05
// According to an article in Wall Street Journal, it came with a 10 MB HD and 640 K RAM.
// We have no version history. The BOOT 2.4 README reveals 'recent ROM changes for MASS 11'
// in January 1985. These were not contained in the older version 04.03.11 (for PC-100-A)
// and also not present in version 05.03 (from PC-100B / PC100B+).
// A first glance:
// => 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.
ROM_START( rainb190 )
ROM_REGION(0x100000,"maincpu", 0)
ROM_LOAD( "dec190rom0.bin", 0xf0000, 0x4000, CRC(FAC191D2) )
ROM_RELOAD(0xf4000,0x4000)
ROM_LOAD( "dec190rom1.bin", 0xf8000, 0x4000, CRC(5CE59632) )
ROM_RELOAD(0xfc000,0x4000)
ROM_REGION(0x1000, "chargen", 0)
ROM_LOAD( "chargen.bin", 0x0000, 0x1000, CRC(1685e452) SHA1(bc299ff1cb74afcededf1a7beb9001188fdcf02f))
ROM_END
/* Driver */
/* YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS */
COMP( 1982, rainbow, 0, 0, rainbow, rainbow, driver_device, 0, "Digital Equipment Corporation", "Rainbow 100B", GAME_NOT_WORKING | GAME_IMPERFECT_COLORS)
/* YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS */
COMP( 1983, rainbow , 0 , 0, rainbow, rainbow100b_in, driver_device, 0, "Digital Equipment Corporation", "Rainbow 100-B", GAME_NOT_WORKING | GAME_IMPERFECT_COLORS)
COMP( 1985, rainb190, rainbow, 0, rainbow, rainbow100b_in, driver_device, 0, "Digital Equipment Corporation", "Rainbow 190-B", GAME_NOT_WORKING | GAME_IMPERFECT_COLORS)

View File

@ -1,13 +1,30 @@
<mamelayout version="2">
<element name="led" defstate="0">
<disk state="0">
<element name="driveled" defstate="0">
<disk state="1">
<color red="0.75" green="0.0" blue="0.0" />
</disk>
<disk state="1">
<disk state="0">
<color red="0.20" green="0.0" blue="0.0" />
</disk>
</element>
<element name="sysled" defstate="0">
<disk state="0">
<color red="0.55" green="0.0" blue="0.0" />
</disk>
<disk state="1">
<color red="0.15" green="0.0" blue="0.0" />
</disk>
</element>
<element name="greenkbd" defstate="0">
<disk state="0">
<color red="0.0" green="0.75" blue="0.0" />
</disk>
<disk state="1">
<color red="0.0" green="0.20" blue="0.0" />
</disk>
</element>
<element name="DRIVE0">
<text string="A">
@ -20,42 +37,55 @@
</text>
</element>
<element name="l1">
<element name="DRIVE2">
<text string="C">
<color red="0.70" green="0.70" blue="0.70" />
</text>
</element>
<element name="DRIVE3">
<text string="D">
<color red="0.70" green="0.70" blue="0.70" />
</text>
</element>
<element name="l1sysled0">
<text string="1">
<color red="1.0" green="1.0" blue="1.0" />
<color red="0.70" green="0.70" blue="0.70" />
</text>
</element>
<element name="l2">
<text string="2">
<color red="1.0" green="1.0" blue="1.0" />
<color red="0.70" green="0.70" blue="0.70" />
</text>
</element>
<element name="l3">
<text string="3">
<color red="1.0" green="1.0" blue="1.0" />
<color red="0.70" green="0.70" blue="0.70" />
</text>
</element>
<element name="l4">
<text string="4">
<color red="1.0" green="1.0" blue="1.0" />
<color red="0.70" green="0.70" blue="0.70" />
</text>
</element>
<element name="l5">
<text string="5">
<color red="1.0" green="1.0" blue="1.0" />
<color red="0.70" green="0.70" blue="0.70" />
</text>
</element>
<element name="l6">
<text string="6">
<color red="1.0" green="1.0" blue="1.0" />
<color red="0.70" green="0.70" blue="0.70" />
</text>
</element>
<element name="l7">
<text string="7">
<color red="1.0" green="1.0" blue="1.0" />
<color red="0.70" green="0.70" blue="0.70" />
</text>
</element>
<element name="l8">
<element name="l8wait">
<text string="WAIT">
<color red="1.0" green="1.0" blue="1.0" />
</text>
@ -81,45 +111,51 @@
<bounds x="30" y="0" width="640" height="480" />
</screen>
<bezel name="led20" element="led">
<bezel name="driveled0" element="driveled">
<bounds x="15" y="3" width="10" height="10" />
</bezel>
<bezel name="led21" element="led">
<bezel name="driveled1" element="driveled">
<bounds x="15" y="18" width="10" height="10" />
</bezel>
<bezel name="driveled2" element="driveled">
<bounds x="15" y="33" width="10" height="10" />
</bezel>
<bezel name="driveled3" element="driveled">
<bounds x="15" y="46" width="10" height="10" />
</bezel>
<bezel name="led1" element="led">
<bounds x="15" y="43" width="10" height="10" />
<bezel name="led1" element="sysled">
<bounds x="15" y="76" width="10" height="10" />
</bezel>
<bezel name="led2" element="led">
<bounds x="15" y="63" width="10" height="10" />
<bezel name="led2" element="sysled">
<bounds x="15" y="96" width="10" height="10" />
</bezel>
<bezel name="led3" element="led">
<bounds x="15" y="83" width="10" height="10" />
<bezel name="led3" element="sysled">
<bounds x="15" y="116" width="10" height="10" />
</bezel>
<bezel name="led4" element="led">
<bounds x="15" y="103" width="10" height="10" />
<bezel name="led4" element="sysled">
<bounds x="15" y="136" width="10" height="10" />
</bezel>
<bezel name="led5" element="led">
<bounds x="15" y="123" width="10" height="10" />
<bezel name="led5" element="sysled">
<bounds x="15" y="156" width="10" height="10" />
</bezel>
<bezel name="led6" element="led">
<bounds x="15" y="143" width="10" height="10" />
<bezel name="led6" element="sysled">
<bounds x="15" y="176" width="10" height="10" />
</bezel>
<bezel name="led7" element="led">
<bounds x="15" y="163" width="10" height="10" />
<bezel name="led7" element="sysled">
<bounds x="15" y="196" width="10" height="10" />
</bezel>
<bezel name="led8" element="led">
<bounds x="15" y="193" width="10" height="10" />
<bezel name="led8" element="greenkbd">
<bounds x="15" y="226" width="10" height="10" />
</bezel>
<bezel name="led9" element="led">
<bounds x="15" y="213" width="10" height="10" />
<bezel name="led9" element="greenkbd">
<bounds x="15" y="246" width="10" height="10" />
</bezel>
<bezel name="led10" element="led">
<bounds x="15" y="232" width="10" height="10" />
<bezel name="led10" element="greenkbd">
<bounds x="15" y="265" width="10" height="10" />
</bezel>
<bezel name="led11" element="led">
<bounds x="15" y="252" width="10" height="10" />
<bezel name="led11" element="greenkbd">
<bounds x="15" y="285" width="10" height="10" />
</bezel>
<bezel name="label20" element="DRIVE0">
@ -128,38 +164,45 @@
<bezel name="label21" element="DRIVE1">
<bounds x="0" y="14" width="15" height="16" />
</bezel>
<bezel name="label1" element="l1">
<bounds x="0" y="40" width="15" height="16" />
<bezel name="label22" element="DRIVE2">
<bounds x="0" y="29" width="15" height="16" />
</bezel>
<bezel name="label23" element="DRIVE3">
<bounds x="0" y="43" width="15" height="16" />
</bezel>
<bezel name="label1" element="l1sysled0">
<bounds x="0" y="73" width="15" height="16" />
</bezel>
<bezel name="label2" element="l2">
<bounds x="0" y="60" width="15" height="16" />
<bounds x="0" y="93" width="15" height="16" />
</bezel>
<bezel name="label3" element="l3">
<bounds x="0" y="80" width="15" height="16" />
<bounds x="0" y="113" width="15" height="16" />
</bezel>
<bezel name="label4" element="l4">
<bounds x="0" y="100" width="15" height="16" />
<bounds x="0" y="133" width="15" height="16" />
</bezel>
<bezel name="label5" element="l5">
<bounds x="0" y="120" width="15" height="16" />
<bounds x="0" y="153" width="15" height="16" />
</bezel>
<bezel name="label6" element="l6">
<bounds x="0" y="140" width="15" height="16" />
<bounds x="0" y="173" width="15" height="16" />
</bezel>
<bezel name="label7" element="l7">
<bounds x="0" y="160" width="15" height="16" />
<bounds x="0" y="193" width="15" height="16" />
</bezel>
<bezel name="label8" element="l8">
<bounds x="0" y="189" width="15" height="16" />
<bezel name="label8" element="l8wait">
<bounds x="0" y="222" width="15" height="16" />
</bezel>
<bezel name="label9" element="l9">
<bounds x="0" y="209" width="15" height="16" />
<bounds x="0" y="242" width="15" height="16" />
</bezel>
<bezel name="label10" element="l10">
<bounds x="0" y="229" width="15" height="16" />
<bounds x="0" y="262" width="15" height="16" />
</bezel>
<bezel name="label11" element="l11">
<bounds x="0" y="249" width="15" height="16" />
<bounds x="0" y="282" width="15" height="16" />
</bezel>
</view>

View File

@ -5,8 +5,8 @@
This is the later "cost-reduced" 6805 version; there's also an 8048 version.
*/
/* LK201-AA keyboard matrix (8048 version)
Source: VCB02 Technical Reference.
/* LK201-AA keyboard matrix (8048 version with updates)
Source: VCB02 Technical Reference.
KBD controller scan matrix (PORT 1): 8 x BCD IN => 18 DECIMAL OUT
@ -20,33 +20,32 @@ ________|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0
..KBD17:|[R] |F19 |[R] |F20|PF4|N--- N,| Enter
........| | | | | | NOTE1)
........| |G22 | |G23|E23|D23|C23| A23
........| | | | | | <- - - - - - ? ?
--------|----|----|----|---|---|---|---|---
..KBD16:|F18 |PF3 |[R] |N9 |V |N6 |N3 |N
..KBD16:|F18 |PF3 |[R] |N9 |C:D|N6 |N3 |N.
........|G21 |E22 | |D22|B17|C22|B22|A22
--------|----|----|----|---|---|---|---|---
..KBD15:|F17 |PF2 |[R] |N8 |N5 |-> | N2|N0
..KBD15:|F17 |PF2 |[R] |N8 |N5 |C:R| N2|N0
........| | | | | | | |NOTE 2)
........|G20 |E21 | |D21|C21|B18|B21|
--------|----|----|----|---|---|---|---|---
KBD14:|PF1 |Next|Remove ^|N7 |N4 |N1 |N0
........| |Scrn| | || | | |
KBD14:|PF1 |Next|Rem-|C:U|N7 |N4 |N1 |N0
........| |Scrn|move|...| | | |
........|E20 |D18 |E18 |C17|D20|C20|B20|A20
--------|----|----|----|---|---|---|---|---
..KBD13:|Ins.|--- |D0 Prev| { |" |[R]|[R]
........|Here|- | Scrn. [ |' | |
........|E17 |E11 |G16 |D17 D11|C11| |
..KBD13:|Ins.|--- |'Do'|Prev { |" |[R]|[R]
........|Here|- | Scrn| [ |' | |
........|E17 |E11 |G16 |D17|D11|C11| |
--------|----|----|----|---|---|---|---|---
..KBD12:|Find|+ |Help|Se-| } Re- |<- |
........| |= | |lect ] turn| |
........|E16 |E12 |G15 |D16 D12|C13| |
..KBD12:|Find|+ |Help|Se-| } |Re-|C:L| |
........| |= | |lect ] |turn...| \
........|E16 |E12 |G15 |D16 D12|C13|B16|C12
--------|----|----|----|---|---|---|---|---
..KBD11:Addtnl <X||[R] |) |P NOTE|: |?
.......Options Del| |0 | | 3)|; |/
..KBD11:Addtnl <X||[R] |) |P NOTE|: | ?
.......Options Del| |0 | | 3)|; | /
........|G14 | E13|....|E10|D10|...|C10|B10
--------|----|----|----|---|---|---|---|---
..KBD10:|[R] |F12 |[R] |F13| ( |O |L |.
........|....|(BS)| |(LF) 9 | | |
..KBD10:|[R] |F12 |[R] |F13| ( |O |L | .
........|....|(BS)| |(LF) 9 | | | .
........|....|G12 |....|G13|E09|D09|C09|B09
--------|----|----|----|---|---|---|---|---
..KBD_9:|[R] |F11 |[R] |[R]|* |I |K | ,
@ -58,27 +57,27 @@ ________|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0
........| |G08 | |G09|E07|D07|C07|B07
--------|----|----|----|---|---|---|---|---
..KBD_7:|[R] Cancel[R] Resu ^ |Y |H |N
........| | | me |6 | | |
........|....|G07 |G06|E06|D06|C06|B06
........|....|....|.....me |6 | | |
........|....|G07 |....|G06|E06|D06|C06|B06
--------|----|----|----|---|---|---|---|---
..KBD_6:|[R] |[R] |[R] Inter % |T |G |B
........|....|....|....rupt| 5 | | |
........|....|....|....|G05|E05|D05|C05|B05
--------|----|----|----|---|---|---|---|---
..KBD_5: F4 Break [R]|$ |R |F |V |Space
........|.........|....|4 | | | |
........ G02 G03 |....|E04 D04 C04 B04 A01-A09
..KBD_5: F4 |Break [R]|$ |R |F |V |Space
........|....|....|....|4 | | | |
........ G02 |G03 |....|E04 D04 C04 B04 A01-A09
--------|----|----|----|---|---|---|---|---
..KBD_4: [R] |Prt.|[R] |Set|# |E |D |C
........|....|Scrn|....|-Up|3 | | |
........|....|G00 |....|G01 E03 D03 C03 B03
--------|----|----|----|---|---|---|---|---
..KBD_3: Hold|@ |[R] |Tab|W |S |X |>
........|Scrn|2 |....| | | | |<
..KBD_3: Hold| @ |[R] |Tab|W |S |X |>
........|Scrn| 2 |....| | | | |<
........|G99 |E02 |....|D00|D02|C02|B02|B00
--------|----|----|----|---|---|---|---|---
..KBD_2: [R] |[R] |[R] |~ |! |Q |A |Z
........|..............| |1
........|..............|...|1
........|..............|E00 E01 D01 C01 B01
--------|----|----|----|---|---|---|---|---
..KBD_1: Ctrl|Lock|Comp|[R]
@ -94,6 +93,11 @@ ________|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0
Normally only the N0 keyswitch is implemented as a double-sized key.
NOTE 3) Return key occupies 2 positions that are
decoded as the Return (C13) key.
C:D - Cursor down (B17)
C:U - Cursor up (C17)
C:R - Cursor right (B18)
C:L - Cursor left (B16)
*/
#include "emu.h"

View File

@ -11,6 +11,20 @@
#define LK201_TAG "lk201"
#define LK_CMD_LEDS_ON 0x13 /* light LEDs - 1st param: led bitmask */
#define LK_CMD_LEDS_OFF 0x11 /* turn off LEDs */
#define LK_CMD_DIS_KEYCLK 0x99 /* disable the keyclick */
#define LK_CMD_ENB_KEYCLK 0x1b /* enable the keyclick - 1st param: volume */
//#define LK_CMD_DIS_CTLCLK 0xb9 /* disable the Ctrl keyclick */
//#define LK_CMD_ENB_CTLCLK 0xbb /* enable the Ctrl keyclick */
#define LK_CMD_SOUND_CLK 0x9f /* emit a keyclick - 1st param: volume */
#define LK_CMD_DIS_BELL 0xa1 /* disable the bell */
#define LK_CMD_ENB_BELL 0x23 /* enable the bell - 1st param: volume */
#define LK_CMD_BELL 0xa7 /* emit a bell - 1st param: volume */
#define LK_CMD_POWER_UP 0xfd /* init power-up sequence */
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************

View File

@ -1433,6 +1433,7 @@ vk100 // 1980 Digital Equipment Corporation
dectalk // 1982 Digital Equipment Corporation
mc7105 // Elektronika MC7105
rainbow // DEC Rainbow 100B
rainb190 // DEC Rainbow 190
// Memotech
mtx512 // 1983 Memotech MTX 512

View File

@ -1,16 +1,16 @@
/**********************************************************************
/**********************************************************************
DEC VT Terminal video emulation
[ DC012 and DC011 emulation ]
01/05/2009 Initial implementation [Miodrag Milanovic]
--/--/2013 portions by Karl-Ludwig Deisenhofer.
xx/xx/2013 portions by Karl-Ludwig Deisenhofer.
DEC VIDEO : STATE AS OF NOVEMBER 2013
-------------------------------------
- NOT WORKING : scrolling requires implementation of 'scrolling region'. Multiple regions could be present.
Split & a full screen modes exist. Scroll should be synced with beam or DMA.
See 4.7.4 and up in VT manual.
- NOT FULLY WORKING : scrolling requires implementation of 'scrolling region'. Multiple regions could be present.
Split & full screen modes exist. Scroll should be synced with beam or DMA.
See 4.7.4 and up in VT manual.
- TESTS REQUIRED : do line and character attributes (plus combinations) match real hardware?
@ -103,7 +103,6 @@ void vt100_video_device::device_start()
// LBA7 is scan line frequency update
machine().scheduler().timer_pulse(attotime::from_nsec(31778), timer_expired_delegate(FUNC(vt100_video_device::lba7_change),this));
save_item(NAME(m_lba7));
save_item(NAME(m_scroll_latch));
save_item(NAME(m_blink_flip_flop));
@ -146,10 +145,11 @@ void vt100_video_device::device_reset()
// 4 color (= monochrome intensities) palette, 24 and 48 line modes.
void rainbow_video_device::device_reset()
{
DEC_MHFU = true; // SET ON COLD BOOT
MHFU_FLAG = false;
MHFU_counter = 0; // **** MHFU: OFF ON COLD BOOT ! ****
palette_set_color_rgb(machine(), 0, 0x00, 0x00, 0x00); // black
// (rest of the palette is set in the main program)
palette_set_color_rgb(machine(), 0, 0x00, 0x00, 0x00); // black
m_height = 24; // <---- DEC-100
m_height_MAX = 48;
@ -201,14 +201,21 @@ READ8_MEMBER( vt100_video_device::lba7_r )
// Also used by Rainbow-100 ************
WRITE8_MEMBER( vt100_video_device::dc012_w )
{
if (data == 0)
{
if (DEC_MHFU == true)
DEC_MHFU = false; // MHFU is disabled by writing 00 to port 010C.
} else
{
if (DEC_MHFU == false)
DEC_MHFU = true; // TODO: MHFU ENABLE should also reset the MHFU timer.
// TODO: writes to 10C/0C should be treated differently (emulation disables the watchdog too often).
if (data == 0) // MHFU is disabled by writing 00 to port 010C.
{
//if (MHFU_FLAG == true)
// printf("MHFU *** DISABLED *** \n");
MHFU_FLAG = false;
MHFU_counter = 0;
}
else
{ // RESET
//if (MHFU_FLAG == false)
// printf("MHFU ___ENABLED___ \n");
MHFU_FLAG = true;
MHFU_counter = 0;
}
if (!(data & 0x08))
@ -223,7 +230,7 @@ WRITE8_MEMBER( vt100_video_device::dc012_w )
// and unlinked down at the bottom.
// Note that the scroll latch value will be used during the next frame rather than the current frame.
// All line linking/unlinking should be done during the vertical blanking interval (< 550ms).
// All line linking/unlinking is done during the vertical blanking interval (< 550ms).
// More on scrolling regions: Rainbow 100 B technical documentation (QV069-GZ) April 1985 page 22
// Also see VT100 Technical Manual: 4.7.4 Address Shuffling to 4.7.9 Split Screen Smooth Scrolling.
@ -249,6 +256,7 @@ WRITE8_MEMBER( vt100_video_device::dc012_w )
case 0x09:
// clear vertical frequency interrupt;
m_clear_video_interrupt(0, 0);
break;
case 0x0a:
// set reverse field on
@ -571,7 +579,7 @@ void rainbow_video_device::display_char(bitmap_ind16 &bitmap, UINT8 code, int x,
// modify line since that is how it is stored in rom
if (j == 0) j = 15; else j = j - 1;
line = m_gfx[code * 16 + j];
line = m_gfx[ (code << 4) + j]; // code * 16
// UNDERLINED CHARACTERS (CASE 5 - different in 1 line):
back_intensity = back_default_intensity; // 0, 1, 2
@ -606,13 +614,13 @@ void rainbow_video_device::display_char(bitmap_ind16 &bitmap, UINT8 code, int x,
// Double, 'double_height + double_width', then normal.
if (double_width)
{
bitmap.pix16( y_preset, d_x_preset + b * 2 + 1) = bit;
bitmap.pix16( y_preset, d_x_preset + b * 2) = bit;
bitmap.pix16( y_preset, d_x_preset + (b << 1) + 1) = bit;
bitmap.pix16( y_preset, d_x_preset + (b << 1) ) = bit;
if (double_height)
{
bitmap.pix16( 1 + y_preset, d_x_preset + b * 2 + 1) = bit;
bitmap.pix16( 1 + y_preset, d_x_preset + b * 2) = bit;
bitmap.pix16( 1 + y_preset, d_x_preset + (b << 1) + 1) = bit;
bitmap.pix16( 1 + y_preset, d_x_preset + (b << 1) ) = bit;
}
}
else
@ -683,7 +691,7 @@ void rainbow_video_device::video_update(bitmap_ind16 &bitmap, const rectangle &c
}
// LINE ATTRIBUTE - valid for all chars on next line ** DO NOT SHUFFLE **
attr_addr = ( 0x1000 | ((addr + xpos + 1) & 0x0fff) );
attr_addr = 0x1000 | ( (addr + xpos + 1) & 0x0fff );
// MOVE TO NEW DATA
temp = m_in_ram_func(addr + xpos + 2) * 256 + m_in_ram_func(addr + xpos + 1);
@ -747,15 +755,15 @@ void rainbow_video_device::palette_select ( int choice )
break;
case 0x02:
palette_set_color_rgb(machine(), 1, 0 , 200 -50, 0); // GREEN (dim)
palette_set_color_rgb(machine(), 2, 0 , 200, 0); // GREEN (NORMAL)
palette_set_color_rgb(machine(), 3, 0, 200 +50, 0); // GREEN (brighter)
palette_set_color_rgb(machine(), 1, 0 , 205 -50, 100 - 50); // GREEN (dim)
palette_set_color_rgb(machine(), 2, 0 , 205, 100 ); // GREEN (NORMAL)
palette_set_color_rgb(machine(), 3, 0, 205 +50, 100 + 50); // GREEN (brighter)
break;
case 0x03:
palette_set_color_rgb(machine(), 1, 213 - 47, 146 - 47, 82 - 47); // AMBER (dim)
palette_set_color_rgb(machine(), 2, 213, 146, 82); // AMBER (normal - not exact)
palette_set_color_rgb(machine(), 3, 255, 193, 129); // AMBER (brighter)
palette_set_color_rgb(machine(), 1, 213 - 47, 146 - 47, 82 - 47); // AMBER (dim)
palette_set_color_rgb(machine(), 2, 213, 146, 82 ); // AMBER (NORMAL)
palette_set_color_rgb(machine(), 3, 255, 193, 129 ); // AMBER (brighter)
break;
}
}
@ -764,13 +772,38 @@ void rainbow_video_device::palette_select ( int choice )
void rainbow_video_device::video_blanking(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
// 'In reverse screen mode, termination forces the beam to the screen background intensity'
// Background intensity means 'dim' (1) according to one source. Most certainly not pitch black.
// Background intensity means 'dim' (1) according to one source.
bitmap.fill( ((m_reverse_field ^ m_basic_attribute) ? 1 : 0) , cliprect);
}
int rainbow_video_device::dc012_MHFU()
int rainbow_video_device::MHFU(int ASK)
{
return DEC_MHFU;
switch (ASK)
{
case 1: // "true": RETURN BOOLEAN (MHFU disabled or enabled?)
return MHFU_FLAG;
case -1: // -1: increment, return counter value (=> Rainbow.c)
if (MHFU_FLAG == true)
MHFU_counter++;
return MHFU_counter;
case -100: // -100 : RESET and ENABLE MHFU counter
//printf("-100 MHFU * reset and ENABLE * \n");
MHFU_counter = 0;
//if (MHFU_FLAG == false)
// printf("-100 MHFU ___ENABLED___\n");
MHFU_FLAG = true;
return -100;
default:
assert(1);
return -255;
} // switch
}
TIMER_CALLBACK_MEMBER( vt100_video_device::lba7_change )

View File

@ -40,7 +40,6 @@ public:
DECLARE_WRITE8_MEMBER(brightness_w);
virtual void video_update(bitmap_ind16 &bitmap, const rectangle &cliprect);
protected:
// device-level overrides
virtual void device_config_complete();
@ -58,7 +57,10 @@ protected:
UINT8 *m_gfx; /* content of char rom */
int m_lba7;
bool DEC_MHFU;
bool MHFU_FLAG;
int MHFU_counter;
// dc012 attributes
UINT8 m_scroll_latch;
@ -84,7 +86,7 @@ public:
virtual void video_update(bitmap_ind16 &bitmap, const rectangle &cliprect);
virtual void video_blanking(bitmap_ind16 &bitmap, const rectangle &cliprect);
int dc012_MHFU();
int MHFU(int);
void palette_select(int choice);
protected:
virtual void display_char(bitmap_ind16 &bitmap, UINT8 code, int x, int y, UINT8 scroll_region, UINT8 display_type);