Enhance DEC Rainbow 100 Option Graphics

Colors in highres mode and video levels
This commit is contained in:
Bavarese 2016-10-28 18:30:12 +02:00 committed by GitHub
parent ba2cf306fe
commit 9d137d160e

View File

@ -7,8 +7,8 @@
//-------------------- Differences to VT240: --------------------------------------------------- //-------------------- Differences to VT240: ---------------------------------------------------
// - Registers of graphics option not directly mapped (indirect access via mode register) // - Registers of graphics option not directly mapped (indirect access via mode register)
// - write mask is 16 bits wide (not only 8) // - write mask is 16 bits wide (not only 8)
// - scroll register is 8 bits wide - not 16. Probably also different semantics (see UNTESTED *) // - scroll register is 8 bits wide - not 16.
// - There appears to be NO "DMA scroll mode" and no "line erase mode" (so code sections were deleted). Really? // - no "DMA SCROLL", "LINE ERASE MODE", no ZOOM hardware (factor must always be 1)
// Two modes: highres and medres mode (different bank length..?) // Two modes: highres and medres mode (different bank length..?)
// - MEDRES: palette of 16 colors out of 4096. 384 x 240 // - MEDRES: palette of 16 colors out of 4096. 384 x 240
@ -25,8 +25,6 @@ THE DEC 'R-M-B' COLOR CABLE VS. THE UNOFFICIAL 'R-G-B' MODE (A BIT OF HISTORY)
// A patch from one of the archives corrects the GWBASIC palette problem when using 2 monitors [Bavarese]. // A patch from one of the archives corrects the GWBASIC palette problem when using 2 monitors [Bavarese].
EMULATION SPECIFIC EMULATION SPECIFIC
// If a program disables text output (via port $0A), a log message is given.
// DUAL MONITOR enables both screens, even if onboard graphics has been accidently shut off // DUAL MONITOR enables both screens, even if onboard graphics has been accidently shut off
// (helps debugging semi broken programs, for example Doodle). // (helps debugging semi broken programs, for example Doodle).
@ -37,13 +35,16 @@ SCREEN 1 vs. SCREEN 2 IN EMULATION
BUGS BUGS
- MEDRES LOOKS CORRECT - MEDRES LOOKS CORRECT
- HIRES-MODE UNTESTED. - HIRES-MODE SEMI BROKEN (colors OK, else untested).
- VECTOR MODE SEEMS TO DISPLAY NOTHING AT ALL (16 bit access botched?) Examples: MMIND (MasterMind, after BMP logo), SOLIT (Solitair). - GDC diagnostic disk bails out on 10 of 13 low level tests. Separate SCROLL CHECK crashes CPU. Readback from GDC fails?
- GDC diagnostic disk bails out on 11 of 13 low level tests. SCROLL CHECK crashes CPU. - VECTOR MODE SEEMS TO DISPLAY NOTHING AT ALL (16 bit access botched here in driver?)
Interaction of Upd7220 and Rainbow.cpp:
- FIG directions / params appear to be odd (lines go 45 degrees up or down instead of straight dir.),
- RDAT with MOD 2 is unimplemented. WDAT appears to set "m_bitmap_mod" wrongly ("2" means all pixels will be reset)...
Some examples to try: MMIND (MasterMind, after BMP logo), SOLIT (Solitaire), CANON (all freeware games).
UNIMPLEMENTED: UNIMPLEMENTED:
// - Video levels for color modes. // - Rainbow 100 A palette quirks (2 bit palette... applies to certain modes only)
// - Rainbow 100 A palette quirks (2 bit palette... in MEDRES only...?)
UNKNOWN IMPLEMENTATION DETAILS: UNKNOWN IMPLEMENTATION DETAILS:
// a. READBACK (hard copy programs like JOBSDUMP definitely use it. See also GDC diagnostics). VRAM_R ? // a. READBACK (hard copy programs like JOBSDUMP definitely use it. See also GDC diagnostics). VRAM_R ?
@ -72,7 +73,7 @@ DEC Rainbow 100
Driver-in-progress by R. Belmont and Miodrag Milanovic. Driver-in-progress by R. Belmont and Miodrag Milanovic.
Keyboard fix by Cracyc (June 2016), Baud rate generator by Shattered (July 2016) Keyboard fix by Cracyc (June 2016), Baud rate generator by Shattered (July 2016)
Portions (2013 - 2016) by Karl-Ludwig Deisenhofer (Floppy, ClikClok RTC, NVRAM, DIPs, hard disk). Portions (2013 - 2016) by Karl-Ludwig Deisenhofer (Floppy, ClikClok RTC, NVRAM, DIPs, hard disk, Color Graphics).
To unlock floppy drives A-D compile with WORKAROUND_RAINBOW_B (prevents a side effect of ERROR 13). To unlock floppy drives A-D compile with WORKAROUND_RAINBOW_B (prevents a side effect of ERROR 13).
@ -91,8 +92,8 @@ 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). 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! DATA LOSS POSSIBLE: when in partial emulation mode, F3 performs a hard reset!
STATE AS OF JULY 2016 STATE AS OF OCTOBER 2016
--------------------- ------------------------
Driver is based entirely on the DEC-100 'B' variant (DEC-190 and DEC-100 A models are treated as clones). 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. While this is OK for the compatible -190, it doesn't do justice to ancient '100 A' hardware.
The public domain file RBCONVERT.ZIP documents how model 'A' differs from version B. The public domain file RBCONVERT.ZIP documents how model 'A' differs from version B.
@ -538,6 +539,7 @@ public:
DECLARE_WRITE_LINE_MEMBER( com8116_a_ft_w ); DECLARE_WRITE_LINE_MEMBER( com8116_a_ft_w );
DECLARE_WRITE8_MEMBER(GDC_EXTRA_REGISTER_w); DECLARE_WRITE8_MEMBER(GDC_EXTRA_REGISTER_w);
DECLARE_READ8_MEMBER(GDC_EXTRA_REGISTER_r);
uint32_t screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_rainbow(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(vblank_irq); INTERRUPT_GEN_MEMBER(vblank_irq);
@ -680,6 +682,13 @@ private:
emu_timer *cmd_timer; emu_timer *cmd_timer;
const int vectors[9] = { 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x02 }; const int vectors[9] = { 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x02 };
// VIDEO LEVELS: 0 is 100 % output; F is 0 % output. Range of 0...255.
// LIMITED RANGE levels for 100-A model (valid only for all mono + green out on COLOR MONITOR):
//const uint8_t A_MONO_GREEN_video_levels[16] = { 255 , 185, 166, 21, 255 , 185, 166, 21, 255 , 185, 166, 21, 255 , 185, 166, 21};
// 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 };
}; };
@ -689,17 +698,17 @@ m_GDC_INDIRECT_REGISTER = 0; \
m_GDC_MODE_REGISTER = 0; \ m_GDC_MODE_REGISTER = 0; \
m_GDC_WRITE_MASK = 0; \ m_GDC_WRITE_MASK = 0; \
m_GDC_write_buffer_index = 0; \ m_GDC_write_buffer_index = 0; \
m_GDC_scroll_index = 0; \
m_GDC_color_map_index = 0; \ m_GDC_color_map_index = 0; \
m_GDC_ALU_PS_REGISTER = 0; \ m_GDC_ALU_PS_REGISTER = 0; \
m_vpat = 0; \ m_vpat = 0; \
m_patmult = 0; \ m_patmult = 1; \
m_patcnt = 0; \ m_patcnt = 0; \
m_patidx = 7; \ m_patidx = 7; \
m_GDC_FG_BG = 0; \ m_GDC_FG_BG = 0; \
m_color_map_changed = true; \ m_color_map_changed = true; \
for(int i=0; i <256; i++) { m_GDC_SCROLL_BUFFER[i] = m_GDC_SCROLL_BUFFER_PRELOAD[i] = i; };\ for(int i=0; i <256; i++) { m_GDC_SCROLL_BUFFER[i] = m_GDC_SCROLL_BUFFER_PRELOAD[i] = i; };\
m_scroll_buffer_changed = true; \ m_GDC_scroll_index = 255; \
m_scroll_buffer_changed = true; \
printf("\n** NEC 7220 GDC RESET **\n"); printf("\n** NEC 7220 GDC RESET **\n");
UPD7220_DISPLAY_PIXELS_MEMBER( rainbow_state::hgdc_display_pixels ) UPD7220_DISPLAY_PIXELS_MEMBER( rainbow_state::hgdc_display_pixels )
@ -723,28 +732,22 @@ UPD7220_DISPLAY_PIXELS_MEMBER( rainbow_state::hgdc_display_pixels )
return; // no output from graphics option return; // no output from graphics option
// ********************* GET BITMAP DATA FOR 4 PLANES *************************************** // ********************* GET BITMAP DATA FOR 4 PLANES ***************************************
// _READ_ BIT MAP from 2 or 4 planes (plane 0 is least, plane 3 most significant). See page 42 / 43 // _READ_ BIT MAP from 2 or 4 planes (plane 0 is least, plane 3 most significant). See page 42 / 43
if(m_GDC_MODE_REGISTER & GDC_MODE_HIGHRES) if(m_GDC_MODE_REGISTER & GDC_MODE_HIGHRES)
{ {
// HIGH RES (2 planes, 2 color bits, 4 color map entries / 4 MONOCHROME SHADES) plane0 = m_video_ram[((address & 0x7fff) + 0x00000) >> 1];
// MANUAL: (GDC "sees" 2 planes X 16 bits X 16K words)! plane1 = m_video_ram[((address & 0x7fff) + 0x10000) >> 1];
plane2 = plane3 = 0;
// !!! m_video_ram is defined as uint16_t !!!
plane0 = m_video_ram[ ((address & 0x7fff) + 0x00000) >> 1 ]; // Video Ram is defined as LITTLE_ENDIAN, 16 (?):
plane1 = m_video_ram[ ((address & 0x7fff) + 0x20000) >> 1 ]; // 8 x 32 K is 0x40000, see page 16
plane2 = 0;
plane3 = 0;
} }
else else
{ {
// MED.RESOLUTION (4 planes, 4 color bits, 16 color map entries / 16 (4) MONOCHROME SHADES) // MED.RESOLUTION (4 planes, 4 color bits, 16 color map entries / 16 (4) MONOCHROME SHADES)
// MANUAL SAYS: (GDC "sees" 4 planes X 16 bits X 8K words)! // MANUAL SAYS: (GDC "sees" 4 planes X 16 bits X 8K words)!
plane0 = m_video_ram[((address & 0x3fff) + 0x00000) >> 1]; plane0 = m_video_ram[((address & 0x3fff) + 0x00000) >> 1];
plane1 = m_video_ram[((address & 0x3fff) + 0x10000) >> 1]; // 8 x 16 K is 0x20000, see page 16 // OLD: 0x10000 plane1 = m_video_ram[((address & 0x3fff) + 0x10000) >> 1];
plane2 = m_video_ram[((address & 0x3fff) + 0x20000) >> 1]; // OLD: 0x20000 plane2 = m_video_ram[((address & 0x3fff) + 0x20000) >> 1];
plane3 = m_video_ram[((address & 0x3fff) + 0x30000) >> 1]; // OLD: 0x30000 plane3 = m_video_ram[((address & 0x3fff) + 0x30000) >> 1];
} }
// ********************* GET BITMAP DATA per PLANE ***************************************
bool mono = (m_inp13->read() == MONO_MONITOR) ? true : false; // 1 = MONO, 2 = COLOR, 3 = DUAL MONITOR bool mono = (m_inp13->read() == MONO_MONITOR) ? true : false; // 1 = MONO, 2 = COLOR, 3 = DUAL MONITOR
@ -770,7 +773,6 @@ FLOPPY_FORMATS_END
static SLOT_INTERFACE_START(rainbow_floppies) static SLOT_INTERFACE_START(rainbow_floppies)
SLOT_INTERFACE("525qd0", FLOPPY_525_QD) // QD means 80 tracks with DD data rate (single or double sided). SLOT_INTERFACE("525qd0", FLOPPY_525_QD) // QD means 80 tracks with DD data rate (single or double sided).
SLOT_INTERFACE("525qd1", FLOPPY_525_QD) SLOT_INTERFACE("525qd1", FLOPPY_525_QD)
//SLOT_INTERFACE("525sd", FLOPPY_525_SD) // mimic a 5.25 DEC Robin (40 track SINGLE SIDED drive). BIOS DETECTED?
SLOT_INTERFACE("525dd", FLOPPY_525_DD) // mimic a 5.25" PC (40 track) drive. Requires IDrive5.SYS. SLOT_INTERFACE("525dd", FLOPPY_525_DD) // mimic a 5.25" PC (40 track) drive. Requires IDrive5.SYS.
SLOT_INTERFACE("35dd", FLOPPY_35_DD) // mimic 3.5" PC drive (720K, double density). Use Impdrv3.SYS. SLOT_INTERFACE("35dd", FLOPPY_35_DD) // mimic 3.5" PC drive (720K, double density). Use Impdrv3.SYS.
SLOT_INTERFACE_END SLOT_INTERFACE_END
@ -877,6 +879,7 @@ AM_RANGE(0x11, 0x11) AM_DEVREADWRITE("kbdser", i8251_device, status_r, control_w
// EXTRA HARDWARE (Write Buffer, Pattern Register/Multiplier, ALU/PS, Color Map, readback and offset/scroll hardware): // EXTRA HARDWARE (Write Buffer, Pattern Register/Multiplier, ALU/PS, Color Map, readback and offset/scroll hardware):
AM_RANGE(0x50, 0x55) AM_WRITE(GDC_EXTRA_REGISTER_w) AM_RANGE(0x50, 0x55) AM_WRITE(GDC_EXTRA_REGISTER_w)
AM_RANGE(0x50, 0x55) AM_READ(GDC_EXTRA_REGISTER_r)
// 56h Data written is loaded into the GDC's FIFO and flagged as a parameter. // 56h Data written is loaded into the GDC's FIFO and flagged as a parameter.
// 57h Data written is loaded into the GDC's FIFO and flagged as a command. // 57h Data written is loaded into the GDC's FIFO and flagged as a command.
@ -1031,8 +1034,8 @@ PORT_DIPSETTING(0x01, DEF_STR(On))
PORT_START("MONITOR CONFIGURATION") // GDC-NEW PORT_START("MONITOR CONFIGURATION") // GDC-NEW
PORT_DIPNAME(0x03, 0x03, "MONITOR CONFIGURATION") PORT_DIPNAME(0x03, 0x03, "MONITOR CONFIGURATION")
PORT_DIPSETTING(0x01, "MONO ONLY (SCREEN 2: 16 monochrome shades)") PORT_DIPSETTING(0x01, "MONO ONLY / 4 to 16 monochrome shades (single VR-201)")
PORT_DIPSETTING(0x02, "COLOR ONLY (SCREEN 2: R-G-B; mono -> green)") 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)") PORT_DIPSETTING(0x03, "DUAL MONITOR (SCREEN 1: TEXT; SCREEN 2: R-G-B)")
INPUT_PORTS_END INPUT_PORTS_END
@ -1203,28 +1206,29 @@ uint32_t rainbow_state::screen_update_rainbow(screen_device &screen, bitmap_ind1
} }
#endif #endif
int monitor_selected = m_inp13->read(); int monitor_selected = m_inp13->read();
if(monitor_selected != old_monitor) if(monitor_selected != old_monitor)
{ {
old_monitor = monitor_selected; old_monitor = monitor_selected;
m_color_map_changed = true; m_color_map_changed = true;
} }
int palette_selected = m_inp9->read(); int palette_selected;
if(palette_selected != old_palette) if( m_ONBOARD_GRAPHICS_SELECTED && (monitor_selected == COLOR_MONITOR) )
{ palette_selected = 2; // Color monitor; green text
else
palette_selected = m_inp9->read();
if(palette_selected != old_palette)
{
old_palette = palette_selected; old_palette = palette_selected;
m_color_map_changed = true; m_color_map_changed = true;
} }
m_crtc->palette_select(palette_selected); m_crtc->palette_select(palette_selected);
// GDC-NEW if( m_SCREEN_BLANK ||
// NEC 7220 output (MONO or COLOR) can only be shown on the RIGHT hand side, ( (!m_ONBOARD_GRAPHICS_SELECTED) && (monitor_selected != DUAL_MONITOR) ) // blank screen 1, except when in DUAL_MONITOR mode
// so disable TEXT out if 'dual monitor' is unselected.
// BLANK SCREEN : ONLY IF 1) graphics option output selected AND 2) no multi monitor setup selected
if( m_SCREEN_BLANK ||
( (!m_ONBOARD_GRAPHICS_SELECTED) && (monitor_selected != 3))
) )
m_crtc->video_blanking(bitmap, cliprect); m_crtc->video_blanking(bitmap, cliprect);
else else
@ -2344,88 +2348,103 @@ IRQ_CALLBACK_MEMBER(rainbow_state::irq_callback)
// VERIFY: SCROLL_MAP & COLOR_MAP are updated at the next VSYNC (not immediately)... Are there more registers? // VERIFY: SCROLL_MAP & COLOR_MAP are updated at the next VSYNC (not immediately)... Are there more registers?
WRITE_LINE_MEMBER(rainbow_state::GDC_vblank_irq) WRITE_LINE_MEMBER(rainbow_state::GDC_vblank_irq)
{ {
// VERIFICATION NEEDED: IRQ raised before or after new palette loaded...?
if(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_VSYNC_IRQ) // 0x40
raise_8088_irq(IRQ_GRF_INTR_L);
uint8_t red, green, blue, mono; uint8_t red, green, blue, mono;
int xi; int xi;
// VIDEO LEVELS: 0 is 100 % output; F is 0 % output
// Levels for 100-B model, taken from page 46 of PDF, multiplied by 2.55 to obtain a range of 0...255
const uint8_t v_levels[16] = { 255, 217, 201,186, 171, 156, 140, 125, 110, 97, 79, 66, 54, 31, 18, 0 };
if(m_scroll_buffer_changed) if(m_scroll_buffer_changed)
{ {
m_scroll_buffer_changed = false; m_scroll_buffer_changed = false;
for(xi = 0; xi < 256; xi++) // LOAD REAL SCROLL BUFFER FROM PRELOAD BUFFER: for(xi = 0; xi < m_GDC_scroll_index; xi++) // LOAD REAL SCROLL BUFFER FROM PRELOAD (up to scroll_index...?)
m_GDC_SCROLL_BUFFER[xi] = m_GDC_SCROLL_BUFFER_PRELOAD[xi]; m_GDC_SCROLL_BUFFER[xi] = m_GDC_SCROLL_BUFFER_PRELOAD[xi];
} }
if(m_color_map_changed) if(m_color_map_changed)
{ {
m_color_map_changed = false; m_color_map_changed = false;
for(xi=0;xi<16;xi++) // DELAYED LOAD OF PALETTE ... 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 colordata1 = m_GDC_COLOR_MAP[xi];
uint8_t colordata2 = m_GDC_COLOR_MAP[xi + 16]; // Does it matter if the palette is incomplete...? uint8_t colordata2 = m_GDC_COLOR_MAP[xi + 16]; // Does it matter if the palette is incomplete...?
// Color map: 32 x 8
// 2nd 16 Byte 1st 16 Bytes (colordata1)
// ----------- ------------
// 7..4 3..0 7..4 3..0
// Mono Blue Red Green
// NOTE: 2nd 16 BYTES ARE MONO PALETTE, 1st 16 ARE COLOR PALETTE * HERE * (on the VT240 driver, it is the other way round)
// Color map: 32 x 8
// 2nd 16 Byte 1st 16 Bytes (colordata1)
// ----------- ------------
// 7..4 3..0 7..4 3..0
// Mono Blue Red Green
mono = (colordata2 & 0xF0) >> 4; // FIXME: limit palette in appropriate modes on 100-A mono = (colordata2 & 0xF0) >> 4; // FIXME: limit palette in appropriate modes on 100-A
mono_sum += mono;
blue = (colordata2 & 0x0F); blue = (colordata2 & 0x0F);
red = (colordata1 & 0xF0) >> 4; red = (colordata1 & 0xF0) >> 4;
green =(colordata1 & 0x0F); green =(colordata1 & 0x0F);
// NOTE: SECOND 16 BYTES ARE MONO PALETTE, _FIRST_ 16 ARE COLOR PALETTE * HERE * (on the VT240 driver, it is the other way round) green_sum += green;
switch( m_inp13->read()) switch( m_inp13->read())
{ {
case MONO_MONITOR: // FIXME: bad colors! 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 case 1: // BLACK & WHITE
m_palette2->set_pen_color(xi + 16, pal4bit(mono), pal4bit(mono), pal4bit(mono) ); mono = uint8_t( ( 205.0f / 80.0f) * ( video_levels[ mono ] / 3.19f) );
m_palette2->set_pen_color(xi + 16, rgb_t( mono, mono, mono) );
break; break;
case 2: // SHADES OF GREEN case 2: // SHADES OF GREEN
// For now, a hand picked value from VTVIDEO * is coarsly transformed into a RGB value. red = uint8_t( ( 35.0f / 80.0f) * ( video_levels[ mono ] / 3.19f) ); // 80 % = NORMAL *
red = uint8_t( ( 35.0f / 80.0f) * ( v_levels[ mono ] / 3.19f) ); // 80 % = NORMAL * green = uint8_t( (145.0f / 80.0f) * ( video_levels[ mono ] / 3.19f) );
green = uint8_t( (145.0f / 80.0f) * ( v_levels[ mono ] / 3.19f) ); blue = uint8_t( ( 75.0f / 80.0f) * ( video_levels[ mono ] / 3.19f) );
blue = uint8_t( ( 75.0f / 80.0f) * ( v_levels[ mono ] / 3.19f) ); m_palette2->set_pen_color(xi + 16, rgb_t( red, green, blue) );
m_palette2->set_pen_color(xi + 16, rgb_t( red, green, blue) );
break; break;
case 3: // AMBER. Assumption: "normal" value at 80 % is 213, 146, 82 (decimal) case 3: // AMBER. Assumption: "normal" value at 80 % is 213, 146, 82 (decimal)
red = uint8_t( (213.0f / 80.0f) * ( v_levels[ mono ] / 3.19f) ); // 80 % = NORMAL * is 3.19f (100 % would be 2.55f) 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) * ( v_levels[ mono ] / 3.19f) ); green = uint8_t( (146.0f / 80.0f) * ( video_levels[ mono ] / 3.19f) );
blue = uint8_t( ( 82.0f / 80.0f) * ( v_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) ); m_palette2->set_pen_color(xi + 16, rgb_t( red, green, blue) );
break; break;
} }
// 255 durch 2.55 ist 100 255 durch x ist 80 break;
} }
case COLOR_MONITOR: // w.official COLOR CABLE (mono out wired to green gun)
m_palette2->set_pen_color(xi, pal4bit( red ) , pal4bit( mono ) , pal4bit( blue ) ); case COLOR_MONITOR:
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) );
break; break;
case DUAL_MONITOR: // Dual monitor configuration with homebrew cable (R G B, separate onboard circuit is mono) case DUAL_MONITOR:
m_palette2->set_pen_color(xi, pal4bit( red ), pal4bit( green ), pal4bit( blue ) ); 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) );
break; 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)
if ( m_inp13->read() == DUAL_MONITOR)
printf(" [HINT: DUAL MONITOR (DIP SWITCH) WRONG! NO GREEN PALETTE] ");
} // color map changed? } // color map changed?
} // 7220 vblank IRQ
// Raising it aftwards seems more reasonable.
// ....but there is a chance to introduce timing issues with the current code -
// IRQ raised before or after new palette loaded...?
if(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_VSYNC_IRQ) // 0x40
raise_8088_irq(IRQ_GRF_INTR_L);
}
INTERRUPT_GEN_MEMBER(rainbow_state::vblank_irq) INTERRUPT_GEN_MEMBER(rainbow_state::vblank_irq)
{ {
@ -2645,32 +2664,26 @@ WRITE_LINE_MEMBER(rainbow_state::irq_hi_w)
// ********************************* NEC UPD7220 *********************************************** // ********************************* NEC UPD7220 ***********************************************
// Readback mode: correct place? Not for vector mode (really)...? // Readback mode: correct place? Not for vector mode (really)...?
// NOTE: "More than one plane at a time can be enabled for a write operation; however, // NOTE: "More than one plane at a time can be enabled for a write operation; however,
// only one plane can be enabled for a read operation at anyone time." // only one plane can be enabled for a read operation at anyone time."
READ16_MEMBER(rainbow_state::vram_r) READ16_MEMBER(rainbow_state::vram_r)
{ {
if((!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR)) || space.debugger_access()) // (NOT VECTOR MODE) if((!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR)) || space.debugger_access()) // (NOT VECTOR MODE)
{ {
//offset = ((offset & 0x18000) >> 1) | (offset & 0x3fff); // VT 240 // SCROLL_MAP IN BITMAP MODE ONLY...?
if(m_GDC_MODE_REGISTER & GDC_MODE_HIGHRES)
//******************************************************************************************************************************* offset = ( m_GDC_SCROLL_BUFFER[ (offset & 0x3FC0) >> 6 ] << 6) | (offset & 0x3F);
// NEW SCROLL_MAP - "valid for reading, writing, and refreshing" else
// SEE PAGE 48 OF PDF FOR A DESCRIPTION OF THE SCROLL_MAP / SCROLL BUFFER: offset = ( m_GDC_SCROLL_BUFFER[ (offset & 0x1FC0) >> 6 ] << 6) | (offset & 0x3F);
offset = ( m_GDC_SCROLL_BUFFER[ ( (offset & 0x3FC0) >> 6 ) ] << 6) | (offset & 0x3F);
//*******************************************************************************************************************************
int readback_plane = 0; int readback_plane = 0;
// READBACK CODE DISABLED, FOR BETTER DEBUGGING (CANT SEE ANYTHING...): if( !(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_WRITES) ) // 0x10 // READBACK OPERATION - if ENABLE_WRITES NOT SET
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)];
// printf(" READBACK MODE * ON *; plane selected: %02x ", readback_plane); }
}
return m_video_ram[ (offset & 0xffff) + (0x8000 * readback_plane)];
//return m_video_ram[(offset & 0x7fff) + (0x8000 * readback_plane)]; // VT240
}
return 0; return 0;
} }
@ -2681,23 +2694,18 @@ READ16_MEMBER(rainbow_state::vram_r)
// Rainbow has separate registers for fore and background. // Rainbow has separate registers for fore and background.
WRITE16_MEMBER(rainbow_state::vram_w) WRITE16_MEMBER(rainbow_state::vram_w)
{ {
//uint8_t *video_ram8 = (uint8_t *)(&m_video_ram[0]); if(!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR))
if(!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR)) // NOT VECTOR MODE
{ {
// SCROLL_MAP IN BITMAP MODE ONLY...?
//******************************************************************************************************************************* if(m_GDC_MODE_REGISTER & GDC_MODE_HIGHRES)
// NEW SCROLL_MAP - "valid for reading, writing, and refreshing" offset = ( m_GDC_SCROLL_BUFFER[ (offset & 0x3FC0) >> 6 ] << 6) | (offset & 0x3F);
// SEE PAGE 48 OF PDF FOR A DESCRIPTION OF THE SCROLL_MAP / SCROLL BUFFER: else
offset = ( m_GDC_SCROLL_BUFFER[ ( (offset & 0x3FC0) >> 6 ) ] << 6) | (offset & 0x3F); offset = ( m_GDC_SCROLL_BUFFER[ (offset & 0x1FC0) >> 6 ] << 6) | (offset & 0x3F);
//*******************************************************************************************************************************
offset |= BIT(offset, 16); // leftover from VT240 (GDC has 18 bit, Duell schematics dont show if A16 und A17 are connected...)
} }
else else
{ {
if(data & 0xff00) if(data & 0xff00)
{ {
data >>= 8; data >>= 8;
offset += 1; offset += 1;
} }
@ -2773,21 +2781,35 @@ WRITE16_MEMBER(rainbow_state::vram_w)
back >>= 1; back >>= 1;
} // plane select (LOOP) } // plane select (LOOP)
return; // ?? return;
} }
if(!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR))
data = (chr & ~m_GDC_WRITE_MASK) | (m_video_ram[offset] & m_GDC_WRITE_MASK);
else
data = (chr & data) | (m_video_ram[offset] & ~data);
// < scroll thingy from VT240 omitted >
m_video_ram[offset] = data;
} }
// (READ)
// Read _preloaded_ scroll buffer (see GDC Diagnostic Disk, SCROLL BUFFER test)
READ8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_r)
{
uint8_t out = 0;
switch(offset)
{
case 1:
if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_SCROLL_MAP ) // 0x80
{
// Documentation says it is always incremented, no matter if read or write:
out = m_GDC_SCROLL_BUFFER_PRELOAD[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);
break;
default:
printf("\n * UNHANDLED CASE: READ REGISTER 50..55 with INDIRECT_REGISTER $%02x and OFFSET $%02x *", m_GDC_INDIRECT_REGISTER, offset);
break;
} // switch
return out;
}
WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w) WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
{ {
@ -3061,7 +3083,6 @@ MCFG_SCREEN_VISIBLE_AREA(0, 800-1, 0, 256-1) // should be 240
MCFG_FD1793_ADD(FD1793_TAG, XTAL_24_0734MHz / 24) // no separate 1 Mhz quartz MCFG_FD1793_ADD(FD1793_TAG, XTAL_24_0734MHz / 24) // no separate 1 Mhz quartz
MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":0", rainbow_floppies, "525qd0", rainbow_state::floppy_formats) MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":0", rainbow_floppies, "525qd0", rainbow_state::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":1", rainbow_floppies, "525qd1", rainbow_state::floppy_formats) MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":1", rainbow_floppies, "525qd1", rainbow_state::floppy_formats)
//MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":1", rainbow_floppies, "525sd", rainbow_state::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":2", rainbow_floppies, "525dd", rainbow_state::floppy_formats) MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":2", rainbow_floppies, "525dd", rainbow_state::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":3", rainbow_floppies, "35dd", rainbow_state::floppy_formats) MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":3", rainbow_floppies, "35dd", rainbow_state::floppy_formats)
MCFG_SOFTWARE_LIST_ADD("flop_list", "rainbow") MCFG_SOFTWARE_LIST_ADD("flop_list", "rainbow")