mirror of
https://github.com/holub/mame
synced 2025-06-02 02:49:44 +03:00
[Rainbow-100]: correct palette problems and silence log output (#4373)
* Correct palette problems and silence log output Monitor autodetection avoids false colors [on a real machine, this would require rewiring]. Corrected palette problems (non-working flag). Also, video levels from DEC's documentation turned out too dark. Converted printf to logerror. * Old_palette removed * More fixes that slipped through (NW) * Update rainbow.cpp * Update rainbow.cpp
This commit is contained in:
parent
29ff589d21
commit
2d9895e7bd
@ -4,8 +4,8 @@
|
||||
DEC Rainbow 100
|
||||
|
||||
Driver-in-progress by R. Belmont and Miodrag Milanovic.
|
||||
Keyboard & GDC fixes by Cracyc (June - Nov. 2016), Baud rate generator by Shattered (July 2016)
|
||||
Portions (2013 - 2016) by Karl-Ludwig Deisenhofer (Floppy, ClikClok RTC, NVRAM, DIPs, hard disk, Color Graphics).
|
||||
Portions (2013 - 2018) by Karl-Ludwig Deisenhofer (Floppy, ClikClok RTC, NVRAM, DIPs, hard disk, Color Graphics).
|
||||
Baud rate generator by AJR (2018) and Shattered (2016), keyboard & GDC fixes by Cracyc (June - Nov. 2016).
|
||||
|
||||
To unlock floppy drives A-D compile with WORKAROUND_RAINBOW_B (prevents a side effect of ERROR 13).
|
||||
|
||||
@ -24,7 +24,7 @@ PLEASE USE THE RIGHT SLOT - AND ALWAYS SAVE YOUR DATA BEFORE MOUNTING FOREIGN DI
|
||||
You * should * also reassign SETUP (away from F3, where it sits on a LK201).
|
||||
DATA LOSS POSSIBLE: when in partial emulation mode, F3 performs a hard reset!
|
||||
|
||||
STATE AS OF JANUARY 2017
|
||||
STATE AS OF DECEMBER 2018
|
||||
------------------------
|
||||
Driver is based entirely on the DEC-100 'B' variant (DEC-190 and DEC-100 A models are treated as clones).
|
||||
While this is OK for the compatible -190, it doesn't do justice to ancient '100 A' hardware.
|
||||
@ -103,17 +103,15 @@ COLOR EMULATION (NEC 7220 + extra hardware)
|
||||
Palette takes 2 byte per palette entry. CLUT ("color map") is 32 byte long.
|
||||
------------------------------------------------------------------------------------------------
|
||||
|
||||
THE DEC 'R-M-B' COLOR CABLE VS. THE UNOFFICIAL 'R-G-B' MODE (A BIT OF HISTORY)
|
||||
The standard DEC "color cable" connected the green gun of a VR241 to the mono output of the Rainbow
|
||||
(DIP setting COLOR_MONITOR).
|
||||
|
||||
An unofficial DIY cable enabled R-G-B graphics + seperate text (emulated by DIP setting DUAL MONITOR).
|
||||
As DEC decided not to endorse R-G-B, many commercial programs show incorrect colors.
|
||||
A patch from one of the archives corrects the GWBASIC palette problem when using 2 monitors [Bavarese].
|
||||
DEC 'R-M-B' COLOR CABLE VS. THE UNOFFICIAL 'R-G-B' MODE (a bit of history)
|
||||
(1) the standard DEC "color cable" connected the green gun of a VR241 to the mono output of the Rainbow
|
||||
(2) an unofficial DIY cable enabled R-G-B graphics + seperate text
|
||||
|
||||
EMULATION SPECIFIC
|
||||
DUAL MONITOR enables both screens, even if onboard graphics has been accidently shut off
|
||||
(helps debugging semi broken programs, for example Doodle).
|
||||
(1) COLOR_MONITOR reflects DEC's recommendation (R-M-B with VR241 above)
|
||||
(2) DUAL MONITOR enables both screens, even if onboard graphics has been accidently shut off
|
||||
(also helps debugging semi broken programs, for example Doodle).
|
||||
(3) AUTODETECT (DIP setting) snoops the color palette and chooses the correct 'wiring'
|
||||
|
||||
SCREEN 1 vs. SCREEN 2 IN EMULATION
|
||||
All GDC 7220 output is displayed on the right. Be it color or monochrome, Option Graphics output is on screen 2.
|
||||
@ -145,16 +143,6 @@ UNKNOWN IMPLEMENTATION DETAILS:
|
||||
To obtain pixel exact graphics use 'Graphics Only' in Video Options and cmd.line switches -nowindow -aspect1 auto -nokeepaspect
|
||||
(Over-Under or Side-by-Side modes always distorted on my 1600 x 900 laptop)
|
||||
|
||||
Programs with initialization / redraw / reentrance problems (invocation order after reset matters in emulation):
|
||||
|
||||
- Canon (high resolution + vectors), Solitaire (SOLIT.EXE) and GDEMO (from GRPHCS.ARC, interactive graphics interpreter '85),
|
||||
plus 'Monitor Aligment' (from the GDC test disk). Sloppy programming or a bug related to a) to e)...?
|
||||
|
||||
Quote from Haze: "if you have 2 screens running at different refresh rates one of them won't update properly
|
||||
(the partial update system gets very confused because it expects both the screens to end at the same time
|
||||
and if that isn't the case large parts of one screen end up not updating at all)
|
||||
|
||||
The following games work well: Tetris, Pacman, MasterMind (MMIND), (G)otelo (needs GSX), Scram (uses scroll extensively).
|
||||
|
||||
CURRENTY UNEMULATED
|
||||
-------------------
|
||||
@ -469,11 +457,6 @@ W17 pulls J1 serial port pin 1 to GND when set (chassis to logical GND).
|
||||
#define COMPLEMENT_MODE 16
|
||||
#define OVERLAY_MODE 32
|
||||
|
||||
// MONITOR CONFIGURATION (DIP SWITCH!):
|
||||
#define MONO_MONITOR 0x01
|
||||
#define COLOR_MONITOR 0x02
|
||||
#define DUAL_MONITOR 0x03
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
#define LK201_TAG "lk201"
|
||||
#define FD1793_TAG "fd1793x"
|
||||
@ -481,6 +464,12 @@ W17 pulls J1 serial port pin 1 to GND when set (chassis to logical GND).
|
||||
#define INVALID_DRIVE 255
|
||||
#define MAX_FLOPPIES 4
|
||||
|
||||
// Monitor configurations -> see DIP switches. New: auto-detect color palette (last option).
|
||||
static constexpr int MONO_MONITOR = 0x01; // Tetris-M and Pacman-M need this setting (no auto-detection)
|
||||
static constexpr int COLOR_MONITOR = 0x02; // DEC recommendation. GWBASIC and most old libraries. Superseded by later development
|
||||
static constexpr int DUAL_MONITOR = 0x03; // Debugging, AutoCad, 'newer' freeware. Green is missing with unpatched software (for technical reasons)
|
||||
static constexpr int AUTODETECT_MONITOR = 0x04; // Snoop palette, then choose best output.
|
||||
|
||||
class rainbow_state : public driver_device
|
||||
{
|
||||
public:
|
||||
@ -718,11 +707,12 @@ private:
|
||||
uint8_t m_vpat, m_patmult, m_patcnt, m_patidx;
|
||||
|
||||
uint16_t m_GDC_WRITE_MASK;
|
||||
bool m_color_map_changed;
|
||||
bool m_ONBOARD_GRAPHICS_SELECTED; // (internal switch, on board video to mono out)
|
||||
|
||||
bool m_ONBOARD_GRAPHICS_SELECTED; // (internal switch, on board video to mono out)
|
||||
bool m_SCREEN_BLANK;
|
||||
|
||||
uint8_t m_monitor_suggested;
|
||||
|
||||
int INT88, INTZ80;
|
||||
|
||||
bool m_zflip; // Z80 alternate memory map with A15 inverted
|
||||
@ -773,7 +763,6 @@ private:
|
||||
|
||||
// FULL RANGE video levels for 100-B model, taken from page 46 of PDF
|
||||
const uint8_t video_levels[16] = { 255, 217, 201,186, 171, 156, 140, 125, 110, 97, 79, 66, 54, 31, 18, 0 };
|
||||
uint8_t m_PORT50;
|
||||
|
||||
const int comm_rates[16] = { 50,75,110,134,150,200,300,600,1200,1800,2000,2400,3600,4800,9600,19200 };
|
||||
};
|
||||
@ -795,10 +784,9 @@ if(m_patidx == 0) m_patidx = 7;
|
||||
// GDC RESET MACRO - used in "machine_reset" & GDC_EXTRA_REGISTER_w !
|
||||
#define OPTION_GRFX_RESET \
|
||||
lower_8088_irq(IRQ_GRF_INTR_L); \
|
||||
m_PORT50 = 0; \
|
||||
m_monitor_suggested = m_inp13->read(); \
|
||||
m_GDC_INDIRECT_REGISTER = 0; \
|
||||
m_GDC_color_map_index = 0; \
|
||||
m_color_map_changed = true; \
|
||||
for(int i=0; i <256; i++) { m_GDC_SCROLL_BUFFER[i] = i; }; \
|
||||
m_GDC_scroll_index = 0; \
|
||||
m_GDC_write_buffer_index = 0; \
|
||||
@ -807,7 +795,7 @@ m_GDC_ALU_PS_REGISTER = 0x0F; \
|
||||
m_GDC_FG_BG = 0xF0; \
|
||||
m_GDC_MODE_REGISTER &= GDC_MODE_VECTOR | GDC_MODE_HIGHRES | GDC_MODE_ENABLE_WRITES | GDC_MODE_READONLY_SCROLL_MAP;\
|
||||
m_GDC_MODE_REGISTER |= GDC_MODE_ENABLE_VIDEO; \
|
||||
printf("\n** OPTION GRFX. RESET **\n");
|
||||
logerror("\n** OPTION GRFX. RESET **\n");
|
||||
|
||||
UPD7220_DISPLAY_PIXELS_MEMBER( rainbow_state::hgdc_display_pixels )
|
||||
{
|
||||
@ -817,7 +805,7 @@ UPD7220_DISPLAY_PIXELS_MEMBER( rainbow_state::hgdc_display_pixels )
|
||||
uint16_t plane0, plane1, plane2, plane3;
|
||||
uint8_t pen;
|
||||
|
||||
if(m_ONBOARD_GRAPHICS_SELECTED && (m_inp13->read() != DUAL_MONITOR) )
|
||||
if(m_ONBOARD_GRAPHICS_SELECTED && (m_inp13->read() != DUAL_MONITOR) )
|
||||
{
|
||||
for(xi=0;xi<16;xi++) // blank screen when VT102 output active (..)
|
||||
{
|
||||
@ -846,7 +834,7 @@ UPD7220_DISPLAY_PIXELS_MEMBER( rainbow_state::hgdc_display_pixels )
|
||||
plane3 = m_video_ram[((address & 0x3fff) + 0x30000) >> 1];
|
||||
}
|
||||
|
||||
bool mono = (m_inp13->read() == MONO_MONITOR) ? true : false; // 1 = MONO, 2 = COLOR, 3 = DUAL MONITOR
|
||||
bool mono = (m_monitor_suggested == MONO_MONITOR) ? true : false; // 1 = MONO, 2 = COLOR, 3 = DUAL MONITOR; 4 = AUTO
|
||||
|
||||
for(xi=0;xi<16;xi++)
|
||||
{
|
||||
@ -986,9 +974,8 @@ void rainbow_state::rainbow8088_io(address_map &map)
|
||||
// * Color graphics option (NEC upd7220 GDC plus external hw.). See Programmer's Reference AA-AE36A-TV.
|
||||
// Either 384 x 240 x 16 or 800 x 240 x 4 colors (out of 4096). 8 x 64 K video RAM.
|
||||
// (Write Buffer, Pattern Register/Multiplier, ALU/PS, Color Map, readback and offset/scroll hardware):
|
||||
map(0x50, 0x55).rw(FUNC(rainbow_state::GDC_EXTRA_REGISTER_r), FUNC(rainbow_state::GDC_EXTRA_REGISTER_w));
|
||||
map(0x56, 0x57).rw(m_hgdc, FUNC(upd7220_device::read), FUNC(upd7220_device::write)); // 56 param, 57 command
|
||||
|
||||
map(0x50, 0x57).rw(FUNC(rainbow_state::GDC_EXTRA_REGISTER_r), FUNC(rainbow_state::GDC_EXTRA_REGISTER_w));
|
||||
|
||||
// ===========================================================
|
||||
// 0x60 -> 0x6f ***** EXTENDED COMM. OPTION / Option Select 2.
|
||||
// ===========================================================
|
||||
@ -1140,7 +1127,8 @@ static INPUT_PORTS_START(rainbow100b_in)
|
||||
PORT_DIPSETTING(0x01, DEF_STR(On))
|
||||
|
||||
PORT_START("MONITOR CONFIGURATION") // GDC
|
||||
PORT_DIPNAME(0x03, 0x03, "MONITOR CONFIGURATION")
|
||||
PORT_DIPNAME(0x0F, 0x04, "MONITOR CONFIGURATION")
|
||||
PORT_DIPSETTING(0x04, "AUTODETECT")
|
||||
PORT_DIPSETTING(0x01, "MONO ONLY / 4 to 16 monochrome shades (single VR-201)")
|
||||
PORT_DIPSETTING(0x02, "COLOR ONLY (single VR-241 with BCC-17 cable)")
|
||||
PORT_DIPSETTING(0x03, "DUAL MONITOR (SCREEN 1: TEXT; SCREEN 2: R-G-B)")
|
||||
@ -1201,7 +1189,7 @@ void rainbow_state::machine_reset()
|
||||
|
||||
if(END_OF_RAM > unmap_start)
|
||||
{
|
||||
printf("\nUnmapping from %x to %x",unmap_start, END_OF_RAM);
|
||||
logerror("\nUnmapping from %x to %x",unmap_start, END_OF_RAM);
|
||||
program.unmap_readwrite(unmap_start, END_OF_RAM);
|
||||
}
|
||||
|
||||
@ -1258,12 +1246,10 @@ void rainbow_state::machine_reset()
|
||||
|
||||
// *********** NEC 7220 DISPLAY CONTROLLER [ OPTIONAL ]
|
||||
OPTION_GRFX_RESET
|
||||
|
||||
OPTION_RESET_PATTERNS
|
||||
|
||||
for(int i=0; i <32; i++) { m_GDC_COLOR_MAP[i] = 0x00; };
|
||||
m_GDC_color_map_index = 0;
|
||||
m_color_map_changed = true;
|
||||
// *********** Z80
|
||||
|
||||
m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
|
||||
@ -1344,13 +1330,20 @@ void rainbow_state::device_timer(emu_timer &timer, device_timer_id tid, int para
|
||||
|
||||
uint32_t rainbow_state::screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
static int old_palette, old_monitor;
|
||||
static int old_monitor;
|
||||
|
||||
int monitor_selected = m_inp13->read();
|
||||
if(monitor_selected != old_monitor)
|
||||
if((m_monitor_suggested < 1) || (m_monitor_suggested > 3))
|
||||
m_monitor_suggested = COLOR_MONITOR;
|
||||
|
||||
if(m_monitor_suggested != old_monitor)
|
||||
{
|
||||
old_monitor = monitor_selected;
|
||||
m_color_map_changed = true;
|
||||
old_monitor = m_monitor_suggested;
|
||||
if(m_monitor_suggested == 1)
|
||||
popmessage("MONOCHROME MONITOR");
|
||||
if(m_monitor_suggested == 2)
|
||||
popmessage("COLOR MONITOR");
|
||||
if(m_monitor_suggested == 3)
|
||||
popmessage("DUAL MONITOR");
|
||||
}
|
||||
|
||||
int palette_selected;
|
||||
@ -1359,16 +1352,11 @@ uint32_t rainbow_state::screen_update_rainbow(screen_device &screen, bitmap_ind1
|
||||
else
|
||||
palette_selected = m_inp9->read();
|
||||
|
||||
if(palette_selected != old_palette)
|
||||
{
|
||||
old_palette = palette_selected;
|
||||
m_color_map_changed = true;
|
||||
}
|
||||
|
||||
m_crtc->palette_select(palette_selected);
|
||||
m_crtc->video_update(bitmap, cliprect);
|
||||
|
||||
if( m_SCREEN_BLANK ||
|
||||
( (!m_ONBOARD_GRAPHICS_SELECTED) && (monitor_selected != DUAL_MONITOR) ) // blank screen 1, except when in DUAL_MONITOR mode
|
||||
( (!m_ONBOARD_GRAPHICS_SELECTED) && (m_inp13->read() != DUAL_MONITOR) ) // dual monitor: never blank all
|
||||
)
|
||||
m_crtc->video_blanking(bitmap, cliprect);
|
||||
else
|
||||
@ -2370,7 +2358,7 @@ READ8_MEMBER(rainbow_state::z80_generalstat_r)
|
||||
if ( fdc_ready && ((fdc_status & 0x40) == 0) && m_POWER_GOOD )
|
||||
fdc_write_gate = 1; // "valid only when drive is selected" !
|
||||
}
|
||||
|
||||
//logerror(" RDY:%x WG:%d ",fdc_ready,fdc_write_gate);
|
||||
int data = (
|
||||
((fdc_step) ? 0x00 : 0x80) |
|
||||
((fdc_write_gate) ? 0x00 : 0x40) |
|
||||
@ -2572,17 +2560,16 @@ WRITE_LINE_MEMBER(rainbow_state::GDC_vblank_irq)
|
||||
else
|
||||
lower_8088_irq(IRQ_GRF_INTR_L);
|
||||
|
||||
uint8_t red, green, blue, mono;
|
||||
int xi;
|
||||
uint8_t xi, red, green, blue, mono;
|
||||
|
||||
if(m_color_map_changed)
|
||||
m_monitor_suggested = m_inp13->read();
|
||||
if((m_monitor_suggested < 1) || (m_monitor_suggested > 3))
|
||||
m_monitor_suggested = COLOR_MONITOR;
|
||||
|
||||
int mono_sum = 0;
|
||||
int green_sum = 0;
|
||||
for(xi=0;xi<16;xi++) // DELAYED LOAD OF PALETTE ...
|
||||
{
|
||||
m_color_map_changed = false;
|
||||
|
||||
int mono_sum = 0;
|
||||
int green_sum = 0;
|
||||
for(xi=0;xi<16;xi++) // DELAYED LOAD OF PALETTE ...
|
||||
{
|
||||
uint8_t colordata1 = m_GDC_COLOR_MAP[xi];
|
||||
uint8_t colordata2 = m_GDC_COLOR_MAP[xi + 16]; // Does it matter if the palette is incomplete...?
|
||||
|
||||
@ -2602,62 +2589,62 @@ WRITE_LINE_MEMBER(rainbow_state::GDC_vblank_irq)
|
||||
green =(colordata1 & 0x0F);
|
||||
green_sum += green;
|
||||
|
||||
switch( m_inp13->read())
|
||||
switch( m_monitor_suggested )
|
||||
{
|
||||
case MONO_MONITOR:
|
||||
{
|
||||
switch( m_inp9->read() ) // - monochrome monitor (phosphor) type (1,2,3)
|
||||
switch( m_inp9->read() ) // - monochrome monitor (phosphor) type (1,2,3)
|
||||
{
|
||||
case 1: // BLACK & WHITE
|
||||
mono = uint8_t( ( 205.0f / 80.0f) * ( video_levels[ mono ] / 3.19f) );
|
||||
m_palette2->set_pen_color(xi + 16, rgb_t( mono, mono, mono) );
|
||||
m_palette2->set_pen_color(xi + 16, pal4bit(mono), pal4bit(mono), pal4bit(mono) );
|
||||
break;
|
||||
|
||||
case 2: // SHADES OF GREEN
|
||||
red = uint8_t( ( 35.0f / 80.0f) * ( video_levels[ mono ] / 3.19f) ); // 80 % = NORMAL *
|
||||
green = uint8_t( (145.0f / 80.0f) * ( video_levels[ mono ] / 3.19f) );
|
||||
blue = uint8_t( ( 75.0f / 80.0f) * ( video_levels[ mono ] / 3.19f) );
|
||||
m_palette2->set_pen_color(xi + 16, rgb_t( red, green, blue) );
|
||||
case 2: // GREEN SHADES. Hand picked value from vtvideo coarsly transformed into a RGB value:
|
||||
red = uint8_t( ( 35.0f / 100.0f) * ( video_levels[ mono ] / 2.55f) );
|
||||
green = uint8_t( (145.0f / 100.0f) * ( video_levels[ mono ] / 2.55f) );
|
||||
blue = uint8_t( ( 75.0f / 100.0f) * ( video_levels[ mono ] / 2.55f) );
|
||||
m_palette2->set_pen_color(xi + 16, rgb_t( red, green, blue) );
|
||||
break;
|
||||
|
||||
case 3: // AMBER. Assumption: "normal" value at 80 % is 213, 146, 82 (decimal)
|
||||
red = uint8_t( (213.0f / 80.0f) * ( video_levels[ mono ] / 3.19f) ); // 80 % = NORMAL * is 3.19f (100 % would be 2.55f)
|
||||
green = uint8_t( (146.0f / 80.0f) * ( video_levels[ mono ] / 3.19f) );
|
||||
blue = uint8_t( ( 82.0f / 80.0f) * ( video_levels[ mono ] / 3.19f) );
|
||||
m_palette2->set_pen_color(xi + 16, rgb_t( red, green, blue) );
|
||||
red = uint8_t( (213.0f / 100.0f) * ( video_levels[ mono ] / 2.55f) );
|
||||
green = uint8_t( (146.0f / 100.0f) * ( video_levels[ mono ] / 2.55f) );
|
||||
blue = uint8_t( ( 82.0f / 100.0f) * ( video_levels[ mono ] / 2.55f) );
|
||||
m_palette2->set_pen_color(xi + 16, rgb_t( red, green, blue) );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case COLOR_MONITOR:
|
||||
|
||||
if(!(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_VIDEO))
|
||||
red = blue = 0; // Page 21 of PDF AA-AE36A (PDF) explains why
|
||||
red = uint8_t( red * 17 * ( (255-video_levels[ red ] ) / 255.0f) );
|
||||
green = uint8_t( mono * 17 * ( (255-video_levels[ mono ]) / 255.0f) ); // BCC-17 cable (red, mono -> green, blue)
|
||||
blue = uint8_t( blue * 17 * ( (255-video_levels[ blue ] ) / 255.0f) );
|
||||
m_palette2->set_pen_color(xi, rgb_t( red, green, blue) );
|
||||
red = blue = 0; // Page 21 of AA-AE36A (PDF) explains why
|
||||
|
||||
m_palette2->set_pen_color(xi, pal4bit( red ) , pal4bit( mono ) , pal4bit( blue ) );
|
||||
break;
|
||||
|
||||
case DUAL_MONITOR:
|
||||
red = uint8_t( red * 17 * ( (255-video_levels[ red ] ) / 255.0f) );
|
||||
green = uint8_t( green * 17 * ( (255-video_levels[ green ]) / 255.0f) ); // true R-G-B (homebrew cable only)
|
||||
blue = uint8_t( blue * 17 * ( (255-video_levels[ blue ] ) / 255.0f) );
|
||||
m_palette2->set_pen_color(xi, rgb_t( red, green, blue) );
|
||||
m_palette2->set_pen_color(xi, pal4bit( red ), pal4bit( green ), pal4bit( blue ) );
|
||||
break;
|
||||
}
|
||||
|
||||
} // palette (loop)
|
||||
} // palette (loop)
|
||||
|
||||
if(mono_sum == 0)
|
||||
if ( m_inp13->read() == COLOR_MONITOR)
|
||||
printf(" [HINT: COLOR MONITOR (DIP SWITCH) WRONG! NO MONO PALETTE] ");
|
||||
if( (green_sum >0) && (green_sum == mono_sum) ) // (R-G-B + M) palette (split cable). Examples: PACMAN, AutoCad
|
||||
{
|
||||
if(m_monitor_suggested == MONO_MONITOR)
|
||||
logerror("\n[HINT: COLOR PALETTE DETECTED - SUITABLE FOR DUAL MONITOR] ");
|
||||
if(m_inp13->read() == AUTODETECT_MONITOR)
|
||||
m_monitor_suggested = DUAL_MONITOR;
|
||||
}
|
||||
|
||||
if(green_sum == 0)
|
||||
if ( m_inp13->read() == DUAL_MONITOR)
|
||||
printf(" [HINT: DUAL MONITOR (DIP SWITCH) WRONG! NO GREEN PALETTE] ");
|
||||
} // color map changed?
|
||||
if((green_sum == 0) && (mono_sum > 0)) // No green = original DEC spec. Example: NLANDER. All older libaries use R-M-B.
|
||||
{
|
||||
if(m_inp13->read() == AUTODETECT_MONITOR)
|
||||
m_monitor_suggested = COLOR_MONITOR;
|
||||
if (m_monitor_suggested == DUAL_MONITOR)
|
||||
logerror("\n[HINT: SINGLE COLOR MONITOR ONLY! GREEN MISSING => NO SPLIT CABLE]");
|
||||
}
|
||||
|
||||
} // 7220 vblank IRQ
|
||||
|
||||
@ -2694,7 +2681,7 @@ READ8_MEMBER(rainbow_state::diagnostic_r) // 8088 (port 0A READ). Fig.4-29 + tab
|
||||
|
||||
WRITE8_MEMBER(rainbow_state::diagnostic_w) // 8088 (port 0A WRITTEN). Fig.4-28 + table 4-15
|
||||
{
|
||||
// printf("%02x to diag port (PC=%x)\n", data, m_i8088->pc());
|
||||
// logerror("%02x to diag port (PC=%x)\n", data, m_i8088->pc());
|
||||
|
||||
// ZRESET from 8088 to Z80 - - HIGH at powerup!
|
||||
if (!(data & 1))
|
||||
@ -2738,12 +2725,12 @@ WRITE8_MEMBER(rainbow_state::diagnostic_w) // 8088 (port 0A WRITTEN). Fig.4-28 +
|
||||
{ printf("\nALARM: GRAPHICS OPTION * SWITCHED OFF * VIA DIP. TEXT OUTPUT STILL ENABLED!\n");
|
||||
m_ONBOARD_GRAPHICS_SELECTED = true;
|
||||
}
|
||||
printf("DATA: %x (PC=%x)\n", data, m_i8088->pc());
|
||||
logerror("DATA: %x (PC=%x)\n", data, m_i8088->pc());
|
||||
}
|
||||
|
||||
// BIT 3: PARITY (1 enables parity test on memory board. Usually 64K per bank). -> ext_ram_w.
|
||||
if(data & 0x08)
|
||||
printf("\n*** PARITY TEST [on RAM EXTENSION] - (bit 3 - diagnostic_w) ");
|
||||
logerror("\n*** PARITY TEST [on RAM EXTENSION] - (bit 3 - diagnostic_w) ");
|
||||
|
||||
// MISSING BITS (* not vital for normal operation, see diag.disk) -
|
||||
// * BIT 4: DIAG LOOPBACK (0 at power-up; 1 directs RX50 and DC12 output to printer port)
|
||||
@ -2769,7 +2756,7 @@ WRITE8_MEMBER(rainbow_state::diagnostic_w) // 8088 (port 0A WRITTEN). Fig.4-28 +
|
||||
*/
|
||||
if (data & 16)
|
||||
{
|
||||
printf("\nWARNING: UNEMULATED DIAG LOOPBACK (directs RX50 and DC12 output to printer port) **** ");
|
||||
logerror("\nWARNING: UNEMULATED DIAG LOOPBACK (directs RX50 and DC12 output to printer port) **** ");
|
||||
}
|
||||
|
||||
address_space &io = m_i8088->space(AS_IO);
|
||||
@ -2782,7 +2769,7 @@ WRITE8_MEMBER(rainbow_state::diagnostic_w) // 8088 (port 0A WRITTEN). Fig.4-28 +
|
||||
PRT RCV DATA.......KBD TXD...........PRT RDATA
|
||||
KBD RCV DATA.......PRT TXD...........KBD RXD
|
||||
*/
|
||||
printf("\nWARNING: UNEMULATED PORT LOOPBACK (COMM, PRINTER, KEYBOARD ports) **** ");
|
||||
logerror("\nWARNING: UNEMULATED PORT LOOPBACK (COMM, PRINTER, KEYBOARD ports) **** ");
|
||||
|
||||
io.unmap_readwrite(0x40, 0x43); // unmap MPSC handlers to prevent CPU crashes ("INTERRUPTS OFF")
|
||||
}
|
||||
@ -2791,7 +2778,7 @@ WRITE8_MEMBER(rainbow_state::diagnostic_w) // 8088 (port 0A WRITTEN). Fig.4-28 +
|
||||
if ( !(data & 32) && (m_diagnostic & 32) )
|
||||
{
|
||||
io.install_readwrite_handler(0x40, 0x43, READ8_DEVICE_DELEGATE(m_mpsc, upd7201_new_device,cd_ba_r), WRITE8_DEVICE_DELEGATE(m_mpsc, upd7201_new_device, cd_ba_w) );
|
||||
printf("\n **** COMM HANDLER INSTALLED **** ");
|
||||
logerror("\n **** COMM HANDLER INSTALLED **** ");
|
||||
//popmessage("Autoboot from drive %c", m_p_nvram[0xab] ? (64 + m_p_nvram[0xab]) : 0x3F );
|
||||
}
|
||||
|
||||
@ -2870,11 +2857,11 @@ READ16_MEMBER(rainbow_state::vram_r)
|
||||
int readback_plane = 0;
|
||||
|
||||
if( !(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_WRITES) ) // 0x10 // READBACK OPERATION - if ENABLE_WRITES NOT SET
|
||||
readback_plane = (m_GDC_MODE_REGISTER & GDC_MODE_READBACK_PLANE_MASK) >> 2; // READBACK PLANE 00..02, mask in bits 2+3
|
||||
readback_plane = (m_GDC_MODE_REGISTER & GDC_MODE_READBACK_PLANE_MASK) >> 2; // READBACK PLANE 00..02, mask in bits 2+3
|
||||
|
||||
return m_video_ram[ (offset & 0x7fff) + (0x8000 * readback_plane)];
|
||||
}
|
||||
return 0xffff;
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
// NOTE: Rainbow has separate registers for fore and background.
|
||||
@ -2891,7 +2878,7 @@ WRITE16_MEMBER(rainbow_state::vram_w)
|
||||
if(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR) // VT240 : if(SELECT_VECTOR_PATTERN_REGISTER)
|
||||
{
|
||||
chr = bitswap<8>(m_vpat, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx);
|
||||
chr |= (chr << 8);
|
||||
chr |= (chr << 8);
|
||||
if(m_patcnt-- == 0)
|
||||
{
|
||||
m_patcnt = m_patmult;
|
||||
@ -2918,15 +2905,15 @@ WRITE16_MEMBER(rainbow_state::vram_w)
|
||||
|
||||
for(int i = 0; i <= 3; i++)
|
||||
{
|
||||
if( BIT(ps,i ) )
|
||||
if( BIT(ps,i ) ) // 1 means don't touch (bits already inverted)
|
||||
{
|
||||
uint16_t mem = m_video_ram[(offset & 0xffff) + (0x8000 * i)]; // VT240
|
||||
uint16_t mem = m_video_ram[(offset & 0xffff) + (0x8000 * i)];
|
||||
|
||||
uint16_t out = 0; // VT240 : uint8_t
|
||||
for(int j = 0; j <= 15; j++) // REPLACE MODE : one replaced by FG, zero by BG ( 16 instead of 8 bit on VT240 )
|
||||
out |= BIT(chr, j) ? ((fore & 1) << j) : ((back & 1) << j);
|
||||
|
||||
switch (m_GDC_ALU_PS_REGISTER & ALU_PS_MODE_MASK)
|
||||
switch ((m_GDC_ALU_PS_REGISTER) & ALU_PS_MODE_MASK)
|
||||
{
|
||||
case OVERLAY_MODE: // (OR)
|
||||
out |= mem;
|
||||
@ -2941,9 +2928,9 @@ WRITE16_MEMBER(rainbow_state::vram_w)
|
||||
}
|
||||
|
||||
if(!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR)) // 0 : Text Mode and Write Mask Batch
|
||||
out = (out & ~m_GDC_WRITE_MASK) | (mem & m_GDC_WRITE_MASK); // // M_MASK (1st use)
|
||||
out = (out & ~m_GDC_WRITE_MASK) | (mem & m_GDC_WRITE_MASK);
|
||||
else
|
||||
out = (out & ~data) | (mem & data); // vector mode
|
||||
out = (out & ~data) | (mem & data);
|
||||
|
||||
if(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_WRITES) // 0x10
|
||||
m_video_ram[(offset & 0xffff) + (0x8000 * i)] = out;
|
||||
@ -2954,37 +2941,45 @@ WRITE16_MEMBER(rainbow_state::vram_w)
|
||||
|
||||
} // plane select (LOOP)
|
||||
return;
|
||||
}
|
||||
} // if enable_writes
|
||||
}
|
||||
|
||||
// (READ)
|
||||
// Read scroll buffer (see GDC Diagnostic Disk, SCROLL BUFFER test)
|
||||
READ8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_r)
|
||||
{
|
||||
uint8_t out = 0;
|
||||
uint8_t data = 0;
|
||||
switch(offset)
|
||||
{
|
||||
case 0:
|
||||
out = m_PORT50;
|
||||
data = m_GDC_MODE_REGISTER; // ?
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_SCROLL_MAP ) // 0x80
|
||||
{
|
||||
// Documentation says it is always incremented (read and write):
|
||||
out = m_GDC_SCROLL_BUFFER[m_GDC_scroll_index++]; // // * READ * SCROLL_MAP ( 256 x 8 )
|
||||
data = m_GDC_SCROLL_BUFFER[m_GDC_scroll_index++]; // // * READ * SCROLL_MAP ( 256 x 8 )
|
||||
m_GDC_scroll_index &= 0xFF; // 0...255 (CPU accesses 256 bytes)
|
||||
break;
|
||||
}
|
||||
else
|
||||
printf("\n * UNEXPECTED CASE: READ REGISTER 50..55 with INDIRECT_REGISTER $%02x and OFFSET $%02x *", m_GDC_INDIRECT_REGISTER, offset);
|
||||
logerror("\n * UNEXPECTED CASE: READ REGISTER 50..55 with INDIRECT_REGISTER $%02x and OFFSET $%02x *", m_GDC_INDIRECT_REGISTER, offset);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
data = m_hgdc->read(space, offset & 0x00);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
data = m_hgdc->read(space, offset & 0x01);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("\n * UNHANDLED CASE: READ REGISTER 50..55 with INDIRECT_REGISTER $%02x and OFFSET $%02x *", m_GDC_INDIRECT_REGISTER, offset);
|
||||
logerror("\n * UNHANDLED CASE: READ REGISTER 50..55 with INDIRECT_REGISTER $%02x and OFFSET $%02x *", m_GDC_INDIRECT_REGISTER, offset);
|
||||
break;
|
||||
} // switch
|
||||
return out;
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
|
||||
@ -2997,7 +2992,7 @@ WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
|
||||
if(last_message != 1)
|
||||
{
|
||||
popmessage("\nCOLOR GRAPHICS ADAPTER INVOKED. PLEASE TURN ON THE APPROPRIATE DIP SWITCH, THEN REBOOT.\n");
|
||||
printf("OFFSET: %x (PC=%x)\n", 0x50 +offset , m_i8088->pc());
|
||||
logerror("OFFSET: %x (PC=%x)\n", 0x50 +offset , m_i8088->pc());
|
||||
last_message = 1;
|
||||
}
|
||||
return;
|
||||
@ -3017,7 +3012,7 @@ WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // 51h - DATA loaded into register previously written to 53h.
|
||||
case 1: // 51h = DATA loaded into (a register previously addressed by a write to 53h)
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_WRITE_BUFFER) // 0x01
|
||||
{
|
||||
m_GDC_write_buffer_index = 0; // (writing to 51h CLEARS the index counter)
|
||||
@ -3030,7 +3025,6 @@ WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
|
||||
if(m_GDC_color_map_index == 32)
|
||||
{
|
||||
m_GDC_color_map_index = 0; // 0...31 (CPU accesses 32 bytes
|
||||
m_color_map_changed = true;
|
||||
|
||||
printf("\n * COLOR MAP FULLY LOADED *");
|
||||
for(int zi =0; zi <16; zi++)
|
||||
@ -3063,81 +3057,88 @@ WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
|
||||
|
||||
// -----------------PATTERN + MULTIPLIER USED IN VECTOR MODE ONLY!
|
||||
// SEE PAGE 37 OF AA-AE36A (PDF).
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_PATTERN_MULTIPLIER)
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_PATTERN_MULTIPLIER) // 0x02
|
||||
{
|
||||
// On a Rainbow, 12 indicates a multiplier of 16-12 = 4 (example)
|
||||
m_patmult = 16 - (data & 15); // 4 bit register // VT240: "patmult_w"
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_PATTERN)
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_PATTERN) // 0x04
|
||||
{
|
||||
// NOTE : Pattern Multiplier MUST BE LOADED before (!)
|
||||
m_vpat = data;
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_FG_BG) // 2 x 4
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_FG_BG) // 0x08
|
||||
{
|
||||
m_GDC_FG_BG = data; // Neither bitswap nor negated (and also not both)...
|
||||
break; // Next: prepare FG / BG and PLANE in ALU - PLANE_SELECT register.
|
||||
break; // Next: prepare FG / BG (4 bits each) + plane in ALU - PLANE_SELECT register.
|
||||
}
|
||||
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_ALU_PS)
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_ALU_PS) // 0x10
|
||||
{
|
||||
m_GDC_ALU_PS_REGISTER = ~data; // Negated...
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_MODE_REGISTER)
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_MODE_REGISTER) // 0x40
|
||||
{
|
||||
m_GDC_MODE_REGISTER = data; // Neither bitswap nor negated (and also not both)...
|
||||
|
||||
if(last_message != 2)
|
||||
if(data & GDC_MODE_HIGHRES) // 0x01
|
||||
{
|
||||
if(last_message != 2)
|
||||
{
|
||||
last_message = 2;
|
||||
printf(" * HIGH RESOLUTION * ");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
last_message = 2;
|
||||
|
||||
if(data & GDC_MODE_HIGHRES)
|
||||
printf(" * HIGH RESOLUTION * ");
|
||||
else
|
||||
printf(" MEDIUM RESOLUTION ");
|
||||
if(last_message != 3)
|
||||
{
|
||||
last_message = 3;
|
||||
printf(" MEDIUM RESOLUTION ");
|
||||
}
|
||||
}
|
||||
|
||||
if(last_mode != (data & GDC_MODE_VECTOR))
|
||||
if(last_mode != (data & GDC_MODE_VECTOR)) // 0x02
|
||||
{
|
||||
last_mode = data & GDC_MODE_VECTOR;
|
||||
if(data & GDC_MODE_VECTOR)
|
||||
printf(" VECTOR MODE ");
|
||||
logerror(" VECTOR MODE ");
|
||||
else
|
||||
printf(" WORD MODE ");
|
||||
logerror(" WORD MODE ");
|
||||
}
|
||||
|
||||
if(last_readback != (data & GDC_MODE_ENABLE_WRITES))
|
||||
if(last_readback != (data & GDC_MODE_ENABLE_WRITES)) // 0x10
|
||||
{
|
||||
last_readback = data & GDC_MODE_ENABLE_WRITES;
|
||||
if(data & GDC_MODE_ENABLE_WRITES) // 0x10
|
||||
printf(" READBACK: OFF - ENABLE_WRITES ");
|
||||
logerror(" READBACK: OFF - ENABLE_WRITES ");
|
||||
else // READBACK PLANE 00..02 - mask in bits 2+3:
|
||||
printf(" READBACK MODE; plane = %02x ", m_GDC_MODE_REGISTER & GDC_MODE_READBACK_PLANE_MASK); // unsure if PLANE is set... already?!
|
||||
logerror(" READBACK MODE; plane = %02x ", m_GDC_MODE_REGISTER & GDC_MODE_READBACK_PLANE_MASK); // unsure if PLANE is set... already?!
|
||||
}
|
||||
|
||||
if(last_scroll_index != m_GDC_scroll_index)
|
||||
{
|
||||
last_scroll_index = m_GDC_scroll_index;
|
||||
if(data & GDC_MODE_READONLY_SCROLL_MAP) // 0x20
|
||||
{ //printf(" SCROLL MAP READ_ONLY. Index : %02x ", m_GDC_scroll_index);
|
||||
} else
|
||||
{ printf(" SCROLL MAP IS WRITABLE. Index : %02x ", m_GDC_scroll_index);
|
||||
}
|
||||
logerror(" SCROLL MAP READ_ONLY. Index : %02x ", m_GDC_scroll_index);
|
||||
else
|
||||
logerror(" SCROLL MAP IS WRITABLE. Index : %02x ", m_GDC_scroll_index);
|
||||
}
|
||||
|
||||
if(!(data & GDC_MODE_ENABLE_VSYNC_IRQ)) // 0x40
|
||||
lower_8088_irq(IRQ_GRF_INTR_L); // also clears the interrupt
|
||||
|
||||
// case 0x80 : If this bit is a 1 red and blue outputs are enabled. If this bit is a 0 red and blue outputs are disabled (page 20 of AA-AE36A)
|
||||
break;
|
||||
} // GDC_SELECT_MODE_REGISTER
|
||||
|
||||
printf("\n* UNIMPLEMENTED CASE. MODE = %02x / m_GDC_INDIRECT_REGISTER = %02x\n",m_GDC_MODE_REGISTER, m_GDC_INDIRECT_REGISTER);
|
||||
logerror("\n* UNIMPLEMENTED CASE. MODE = %02x / m_GDC_INDIRECT_REGISTER = %02x\n",m_GDC_MODE_REGISTER, m_GDC_INDIRECT_REGISTER);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
@ -3161,12 +3162,15 @@ WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
|
||||
m_GDC_color_map_index = 0; // (also clears the index counter)
|
||||
// NEXT: 32 BYTE COLOR MAP, LOADED TO $51
|
||||
|
||||
//if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_MODE_REGISTER) // 0x40
|
||||
// logerror(" *** SELECT MODE REGISTER");
|
||||
|
||||
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_SCROLL_MAP ) // 0x80
|
||||
{
|
||||
if(last_scroll_index != m_GDC_scroll_index)
|
||||
{
|
||||
last_scroll_index = m_GDC_scroll_index;
|
||||
printf(" *** SCROLL INDEX COUNTER RESET, old value = %d", m_GDC_scroll_index);
|
||||
logerror(" *** SCROLL INDEX COUNTER RESET, old value = %d", m_GDC_scroll_index);
|
||||
}
|
||||
m_GDC_scroll_index = 0; // (also clears the index counter)
|
||||
} // NEXT: LOAD 256 BYTE SCROLL MAP INTO $51
|
||||
@ -3181,6 +3185,11 @@ WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
|
||||
case 5: // 55h Write Mask HIGH
|
||||
m_GDC_WRITE_MASK = ( m_GDC_WRITE_MASK & 0xFF00 ) | bitswap<8>(data, 0, 1, 2, 3, 4, 5, 6, 7);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case 7:
|
||||
m_hgdc->write(space, offset & 0x01, data);
|
||||
break;
|
||||
} // switch
|
||||
|
||||
}
|
||||
@ -3336,7 +3345,7 @@ MACHINE_CONFIG_START(rainbow_state::rainbow)
|
||||
m_kbd8251->dtr_handler().set(FUNC(rainbow_state::irq_hi_w));
|
||||
m_kbd8251->rxrdy_handler().set(FUNC(rainbow_state::kbd_rxready_w));
|
||||
m_kbd8251->txrdy_handler().set(FUNC(rainbow_state::kbd_txready_w));
|
||||
|
||||
|
||||
LK201(config, m_lk201, 0);
|
||||
m_lk201->tx_handler().set(m_kbd8251, FUNC(i8251_device::write_rxd));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user