- implement Tandy special 4-color palette handling
- remove 3d8/3d9 from PCJr mode (PCJr didn't have it) - update INT10 palette functions accordingly - add a level of indirection to Tandy and PCjr palette deconding to fix video recording with on-screen palette changes - enable line-by-line emulation for Tandy too - machine-specific implementation of the color when display is disabled (vgaonly too) - enable the light pen stub on all machines that it is documented for - mask off a bank-selection bit that is not used under a specific circumstance Fixes Alley Cat palette on PCJr, Gauntlet, Ghostbusters, Pirates! on Tandy, Video recording on Tandy/PCJr where the palette is changed on-screen Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3647
This commit is contained in:
parent
959ea1527f
commit
c2622359f9
5 changed files with 327 additions and 130 deletions
|
@ -118,30 +118,30 @@ static Bit8u * VGA_Draw_CGA16_Line(Bitu vidstart, Bitu line) {
|
|||
|
||||
static Bit8u * VGA_Draw_4BPP_Line(Bitu vidstart, Bitu line) {
|
||||
const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift);
|
||||
Bit32u * draw=(Bit32u *)TempLine;
|
||||
for (Bitu x=0;x<vga.draw.blocks;x++) {
|
||||
Bitu val1 = base[vidstart & vga.tandy.addr_mask];
|
||||
++vidstart;
|
||||
Bitu val2 = base[vidstart & vga.tandy.addr_mask];
|
||||
++vidstart;
|
||||
*draw++=(val1 & 0x0f) << 8 |
|
||||
(val1 & 0xf0) >> 4 |
|
||||
(val2 & 0x0f) << 24 |
|
||||
(val2 & 0xf0) << 12;
|
||||
Bit8u* draw=TempLine;
|
||||
Bitu end = vga.draw.blocks*2;
|
||||
while(end) {
|
||||
Bit8u byte = base[vidstart & vga.tandy.addr_mask];
|
||||
*draw++=vga.attr.palette[byte >> 4];
|
||||
*draw++=vga.attr.palette[byte & 0x0f];
|
||||
vidstart++;
|
||||
end--;
|
||||
}
|
||||
return TempLine;
|
||||
}
|
||||
|
||||
static Bit8u * VGA_Draw_4BPP_Line_Double(Bitu vidstart, Bitu line) {
|
||||
const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift);
|
||||
Bit32u * draw=(Bit32u *)TempLine;
|
||||
for (Bitu x=0;x<vga.draw.blocks;x++) {
|
||||
Bitu val = base[vidstart & vga.tandy.addr_mask];
|
||||
++vidstart;
|
||||
*draw++=(val & 0xf0) >> 4 |
|
||||
(val & 0xf0) << 4 |
|
||||
(val & 0x0f) << 16 |
|
||||
(val & 0x0f) << 24;
|
||||
Bit8u* draw=TempLine;
|
||||
Bitu end = vga.draw.blocks;
|
||||
while(end) {
|
||||
Bit8u byte = base[vidstart & vga.tandy.addr_mask];
|
||||
Bit8u data = vga.attr.palette[byte >> 4];
|
||||
*draw++ = data; *draw++ = data;
|
||||
data = vga.attr.palette[byte & 0x0f];
|
||||
*draw++ = data; *draw++ = data;
|
||||
vidstart++;
|
||||
end--;
|
||||
}
|
||||
return TempLine;
|
||||
}
|
||||
|
@ -589,10 +589,60 @@ static void VGA_ProcessSplit() {
|
|||
vga.draw.address_line=0;
|
||||
}
|
||||
|
||||
static Bit8u bg_color_index = 0; // screen-off black index
|
||||
static void VGA_DrawSingleLine(Bitu /*blah*/) {
|
||||
if (GCC_UNLIKELY(vga.attr.disabled)) {
|
||||
// draw blanked line (DoWhackaDo, Alien Carnage, TV sports Football)
|
||||
memset(TempLine, 0, sizeof(TempLine));
|
||||
switch(machine) {
|
||||
case MCH_PCJR:
|
||||
// Displays the border color when screen is disabled
|
||||
bg_color_index = vga.tandy.border_color;
|
||||
break;
|
||||
case MCH_TANDY:
|
||||
// Either the PCJr way or the CGA way
|
||||
if (vga.tandy.gfx_control& 0x4) {
|
||||
bg_color_index = vga.tandy.border_color;
|
||||
} else if (vga.mode==M_TANDY4)
|
||||
bg_color_index = vga.attr.palette[0];
|
||||
else bg_color_index = 0;
|
||||
break;
|
||||
case MCH_CGA:
|
||||
// the background color
|
||||
bg_color_index = vga.attr.overscan_color;
|
||||
break;
|
||||
case MCH_EGA:
|
||||
case MCH_VGA:
|
||||
// DoWhackaDo, Alien Carnage, TV sports Football
|
||||
// when disabled by attribute index bit 5:
|
||||
// ET3000, ET4000, Paradise display the border color
|
||||
// S3 displays the content of the currently selected attribute register
|
||||
// when disabled by sequencer the screen is black "257th color"
|
||||
|
||||
// the DAC table may not match the bits of the overscan register
|
||||
// so use black for this case too...
|
||||
//if (vga.attr.disabled& 2) {
|
||||
if (vga.dac.xlat16[bg_color_index] != 0) {
|
||||
for(Bitu i = 0; i < 256; i++)
|
||||
if (vga.dac.xlat16[i] == 0) {
|
||||
bg_color_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//} else
|
||||
// bg_color_index = vga.attr.overscan_color;
|
||||
break;
|
||||
default:
|
||||
bg_color_index = 0;
|
||||
break;
|
||||
}
|
||||
if (vga.draw.bpp==8) {
|
||||
memset(TempLine, bg_color_index, sizeof(TempLine));
|
||||
} else if (vga.draw.bpp==16) {
|
||||
Bit16u* wptr = (Bit16u*) TempLine;
|
||||
Bit16u value = vga.dac.xlat16[bg_color_index];
|
||||
for (Bitu i = 0; i < sizeof(TempLine)/2; i++) {
|
||||
wptr[i] = value;
|
||||
}
|
||||
}
|
||||
RENDER_DrawLine(TempLine);
|
||||
} else {
|
||||
Bit8u * data=VGA_DrawLine( vga.draw.address, vga.draw.address_line );
|
||||
|
@ -966,6 +1016,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
|
|||
switch (machine) {
|
||||
case MCH_CGA:
|
||||
case MCH_PCJR:
|
||||
case MCH_TANDY:
|
||||
vga.draw.mode = LINE;
|
||||
break;
|
||||
case MCH_EGA:
|
||||
|
|
|
@ -153,6 +153,27 @@ static Bitu read_crtc_data_other(Bitu /*port*/,Bitu /*iolen*/) {
|
|||
return (Bitu)(~0);
|
||||
}
|
||||
|
||||
static void write_lightpen(Bitu port,Bitu val,Bitu) {
|
||||
switch (port) {
|
||||
case 0x3db: // Clear lightpen latch
|
||||
vga.other.lightpen_triggered = false;
|
||||
break;
|
||||
case 0x3dc: // Preset lightpen latch
|
||||
if (!vga.other.lightpen_triggered) {
|
||||
vga.other.lightpen_triggered = true; // TODO: this shows at port 3ba/3da bit 1
|
||||
|
||||
double timeInFrame = PIC_FullIndex()-vga.draw.delay.framestart;
|
||||
double timeInLine = fmod(timeInFrame,vga.draw.delay.htotal);
|
||||
Bitu current_scanline = (Bitu)(timeInFrame / vga.draw.delay.htotal);
|
||||
|
||||
vga.other.lightpen = (Bit16u)((vga.draw.address_add/2) * (current_scanline/2));
|
||||
vga.other.lightpen += (Bit16u)((timeInLine / vga.draw.delay.hdend) *
|
||||
((float)(vga.draw.address_add/2)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static double hue_offset = 0.0;
|
||||
static Bit8u cga16_val = 0;
|
||||
static void update_cga16_color(void);
|
||||
|
@ -235,56 +256,139 @@ static void DecreaseHue(bool pressed) {
|
|||
LOG_MSG("Hue at %f",hue_offset);
|
||||
}
|
||||
|
||||
static void write_color_select(Bit8u val) {
|
||||
static void write_cga_color_select(Bitu val) {
|
||||
vga.tandy.color_select=val;
|
||||
switch (vga.mode) {
|
||||
switch(vga.mode) {
|
||||
case M_TANDY4: {
|
||||
Bit8u base = (val & 0x10) ? 0x08 : 0;
|
||||
Bit8u bg = val & 0xf;
|
||||
if (vga.tandy.mode_control & 0x4) // cyan red white
|
||||
VGA_SetCGA4Table(bg, 3+base, 4+base, 7+base);
|
||||
else if (val & 0x20) // cyan magenta white
|
||||
VGA_SetCGA4Table(bg, 3+base, 5+base, 7+base);
|
||||
else // green red brown
|
||||
VGA_SetCGA4Table(bg, 2+base, 4+base, 6+base);
|
||||
vga.tandy.border_color = bg;
|
||||
vga.attr.overscan_color = bg;
|
||||
break;
|
||||
}
|
||||
case M_TANDY2:
|
||||
VGA_SetCGA2Table(0,val & 0xf);
|
||||
break;
|
||||
case M_TANDY4:
|
||||
{
|
||||
if ((machine==MCH_TANDY && (vga.tandy.gfx_control & 0x8)) ||
|
||||
(machine==MCH_PCJR && (vga.tandy.mode_control==0x0b))) {
|
||||
VGA_SetCGA4Table(0,1,2,3);
|
||||
return;
|
||||
}
|
||||
Bit8u base=(val & 0x10) ? 0x08 : 0;
|
||||
/* Check for BW Mode */
|
||||
if (vga.tandy.mode_control & 0x4) {
|
||||
VGA_SetCGA4Table(val & 0xf,3+base,4+base,7+base);
|
||||
} else {
|
||||
if (val & 0x20) VGA_SetCGA4Table(val & 0xf,3+base,5+base,7+base);
|
||||
else VGA_SetCGA4Table(val & 0xf,2+base,4+base,6+base);
|
||||
}
|
||||
}
|
||||
vga.attr.overscan_color = 0;
|
||||
break;
|
||||
case M_CGA16:
|
||||
cga16_color_select(val);
|
||||
break;
|
||||
case M_TEXT:
|
||||
case M_TANDY16:
|
||||
vga.tandy.border_color = val & 0xf;
|
||||
vga.attr.overscan_color = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void TANDY_FindMode(void) {
|
||||
if (vga.tandy.mode_control & 0x2) {
|
||||
if (vga.tandy.gfx_control & 0x10)
|
||||
VGA_SetMode(M_TANDY16);
|
||||
else if (vga.tandy.gfx_control & 0x08)
|
||||
VGA_SetMode(M_TANDY4);
|
||||
else if (vga.tandy.mode_control & 0x10)
|
||||
VGA_SetMode(M_TANDY2);
|
||||
else
|
||||
VGA_SetMode(M_TANDY4);
|
||||
write_color_select(vga.tandy.color_select);
|
||||
static void write_cga(Bitu port,Bitu val,Bitu /*iolen*/) {
|
||||
switch (port) {
|
||||
case 0x3d8:
|
||||
vga.tandy.mode_control=(Bit8u)val;
|
||||
vga.attr.disabled = (val&0x8)? 0: 1;
|
||||
if (vga.tandy.mode_control & 0x2) { // graphics mode
|
||||
if (vga.tandy.mode_control & 0x10) {// highres mode
|
||||
if (!(val & 0x4)) { // burst on
|
||||
VGA_SetMode(M_CGA16); // composite ntsc 160x200 16 color mode
|
||||
} else {
|
||||
VGA_SetMode(M_TANDY2);
|
||||
}
|
||||
} else VGA_SetMode(M_TANDY4); // lowres mode
|
||||
|
||||
write_cga_color_select(vga.tandy.color_select);
|
||||
} else {
|
||||
VGA_SetMode(M_TANDY_TEXT);
|
||||
}
|
||||
VGA_SetBlinking(val & 0x20);
|
||||
break;
|
||||
case 0x3d9: // color select
|
||||
write_cga_color_select(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void tandy_update_palette() {
|
||||
// TODO mask off bits if needed
|
||||
if (machine == MCH_TANDY) {
|
||||
switch (vga.mode) {
|
||||
case M_TANDY2:
|
||||
VGA_SetCGA2Table(vga.attr.palette[0],
|
||||
//vga.attr.palette[vga.tandy.color_select&0xf]);
|
||||
vga.attr.palette[0xf]);
|
||||
//VGA_SetCGA2Table(vga.attr.palette[0xf],vga.attr.palette[0]);
|
||||
break;
|
||||
case M_TANDY4:
|
||||
if (vga.tandy.gfx_control & 0x8) {
|
||||
// 4-color high resolution - might be an idea to introduce M_TANDY4H
|
||||
VGA_SetCGA4Table( // function sets both medium and highres 4color tables
|
||||
vga.attr.palette[0], vga.attr.palette[1],
|
||||
vga.attr.palette[2], vga.attr.palette[3]);
|
||||
} else {
|
||||
Bit8u color_set = 0;
|
||||
Bit8u r_mask = 0xf;
|
||||
if (vga.tandy.color_select & 0x10) color_set |= 8; // intensity
|
||||
if (vga.tandy.color_select & 0x20) color_set |= 1; // Cyan Mag. White
|
||||
if (vga.tandy.mode_control & 0x04) { // Cyan Red White
|
||||
color_set |= 1;
|
||||
r_mask &= ~1;
|
||||
}
|
||||
VGA_SetCGA4Table(
|
||||
vga.attr.palette[0],
|
||||
vga.attr.palette[(2|color_set)& vga.tandy.palette_mask],
|
||||
vga.attr.palette[(4|(color_set& r_mask))& vga.tandy.palette_mask],
|
||||
vga.attr.palette[(6|color_set)& vga.tandy.palette_mask]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
VGA_SetMode(M_TANDY_TEXT);
|
||||
// PCJr
|
||||
switch (vga.mode) {
|
||||
case M_TANDY2:
|
||||
VGA_SetCGA2Table(vga.attr.palette[0],vga.attr.palette[1]);
|
||||
break;
|
||||
case M_TANDY4:
|
||||
VGA_SetCGA4Table(
|
||||
vga.attr.palette[0], vga.attr.palette[1],
|
||||
vga.attr.palette[2], vga.attr.palette[3]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VGA_SetModeNow(VGAModes mode);
|
||||
|
||||
static void TANDY_FindMode(void) {
|
||||
if (vga.tandy.mode_control & 0x2) {
|
||||
if (vga.tandy.gfx_control & 0x10) {
|
||||
if (vga.mode==M_TANDY4) {
|
||||
VGA_SetModeNow(M_TANDY16);
|
||||
} else VGA_SetMode(M_TANDY16);
|
||||
}
|
||||
else if (vga.tandy.gfx_control & 0x08) {
|
||||
VGA_SetMode(M_TANDY4);
|
||||
}
|
||||
else if (vga.tandy.mode_control & 0x10)
|
||||
VGA_SetMode(M_TANDY2);
|
||||
else {
|
||||
if (vga.mode==M_TANDY16) {
|
||||
VGA_SetModeNow(M_TANDY4);
|
||||
} else VGA_SetMode(M_TANDY4);
|
||||
}
|
||||
tandy_update_palette();
|
||||
} else {
|
||||
VGA_SetMode(M_TANDY_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
static void PCJr_FindMode(void) {
|
||||
if (vga.tandy.mode_control & 0x2) {
|
||||
if (vga.tandy.mode_control & 0x10) {
|
||||
|
@ -299,7 +403,6 @@ static void PCJr_FindMode(void) {
|
|||
if (vga.mode==M_TANDY16) VGA_SetModeNow(M_TANDY4);
|
||||
else VGA_SetMode(M_TANDY4);
|
||||
}
|
||||
write_color_select(vga.tandy.color_select);
|
||||
} else {
|
||||
VGA_SetMode(M_TANDY_TEXT);
|
||||
}
|
||||
|
@ -327,11 +430,16 @@ static void write_tandy_reg(Bit8u val) {
|
|||
vga.tandy.mode_control=val;
|
||||
VGA_SetBlinking(val & 0x20);
|
||||
PCJr_FindMode();
|
||||
vga.attr.disabled = (val&0x8)? 0: 1;
|
||||
if (val&0x8) vga.attr.disabled &= ~1;
|
||||
else vga.attr.disabled |= 1;
|
||||
} else {
|
||||
LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index);
|
||||
}
|
||||
break;
|
||||
case 0x1: /* Palette mask */
|
||||
vga.tandy.palette_mask = val;
|
||||
tandy_update_palette();
|
||||
break;
|
||||
case 0x2: /* Border color */
|
||||
vga.tandy.border_color=val;
|
||||
break;
|
||||
|
@ -348,45 +456,12 @@ static void write_tandy_reg(Bit8u val) {
|
|||
TandyCheckLineMask();
|
||||
VGA_SetupHandlers();
|
||||
break;
|
||||
case 0x8: /* Monitor mode seletion */
|
||||
//Bit 1 select mode e, for 640x200x16, some double clocking thing?
|
||||
//Bit 4 select 350 line mode for hercules emulation
|
||||
LOG(LOG_VGAMISC,LOG_NORMAL)("Write %2X to tandy monitor mode",val );
|
||||
break;
|
||||
/* palette colors */
|
||||
case 0x10: case 0x11: case 0x12: case 0x13:
|
||||
case 0x14: case 0x15: case 0x16: case 0x17:
|
||||
case 0x18: case 0x19: case 0x1a: case 0x1b:
|
||||
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
|
||||
VGA_ATTR_SetPalette(vga.tandy.reg_index-0x10,val & 0xf);
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index);
|
||||
}
|
||||
}
|
||||
|
||||
static void write_cga(Bitu port,Bitu val,Bitu /*iolen*/) {
|
||||
switch (port) {
|
||||
case 0x3d8:
|
||||
vga.tandy.mode_control=(Bit8u)val;
|
||||
vga.attr.disabled = (val&0x8)? 0: 1;
|
||||
if (vga.tandy.mode_control & 0x2) {
|
||||
if (vga.tandy.mode_control & 0x10) {
|
||||
if (!(val & 0x4) && machine==MCH_CGA) {
|
||||
VGA_SetMode(M_CGA16); //Video burst 16 160x200 color mode
|
||||
} else {
|
||||
VGA_SetMode(M_TANDY2);
|
||||
}
|
||||
} else VGA_SetMode(M_TANDY4);
|
||||
write_color_select(vga.tandy.color_select);
|
||||
} else {
|
||||
VGA_SetMode(M_TANDY_TEXT);
|
||||
}
|
||||
VGA_SetBlinking(val & 0x20);
|
||||
break;
|
||||
case 0x3d9:
|
||||
write_color_select((Bit8u)val);
|
||||
break;
|
||||
default:
|
||||
if ((vga.tandy.reg_index & 0xf0) == 0x10) { // color palette
|
||||
vga.attr.palette[vga.tandy.reg_index-0x10] = val&0xf;
|
||||
tandy_update_palette();
|
||||
} else
|
||||
LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -394,40 +469,32 @@ static void write_tandy(Bitu port,Bitu val,Bitu /*iolen*/) {
|
|||
switch (port) {
|
||||
case 0x3d8:
|
||||
vga.tandy.mode_control=(Bit8u)val;
|
||||
if (val&0x8) vga.attr.disabled &= ~1;
|
||||
else vga.attr.disabled |= 1;
|
||||
TandyCheckLineMask();
|
||||
VGA_SetBlinking(val & 0x20);
|
||||
TANDY_FindMode();
|
||||
break;
|
||||
case 0x3d9:
|
||||
write_color_select((Bit8u)val);
|
||||
vga.tandy.color_select=val;
|
||||
if (vga.mode==M_TANDY2) vga.attr.palette[0xf] = vga.tandy.color_select&0xf;
|
||||
else vga.attr.palette[0] = vga.tandy.color_select&0xf; // Pirates!
|
||||
tandy_update_palette();
|
||||
break;
|
||||
case 0x3da:
|
||||
vga.tandy.reg_index=(Bit8u)val;
|
||||
break;
|
||||
case 0x3db: // Clear lightpen latch
|
||||
vga.other.lightpen_triggered = false;
|
||||
break;
|
||||
case 0x3dc: // Preset lightpen latch
|
||||
if (!vga.other.lightpen_triggered) {
|
||||
vga.other.lightpen_triggered = true; // TODO: this shows at port 3ba/3da bit 1
|
||||
|
||||
double timeInFrame = PIC_FullIndex()-vga.draw.delay.framestart;
|
||||
double timeInLine = fmod(timeInFrame,vga.draw.delay.htotal);
|
||||
Bitu current_scanline = (Bitu)(timeInFrame / vga.draw.delay.htotal);
|
||||
|
||||
vga.other.lightpen = (Bit16u)((vga.draw.address_add/2) * (current_scanline/2));
|
||||
vga.other.lightpen += (Bit16u)((timeInLine / vga.draw.delay.hdend) *
|
||||
((float)(vga.draw.address_add/2)));
|
||||
}
|
||||
//if (val&0x10) vga.attr.disabled |= 2;
|
||||
//else vga.attr.disabled &= ~2;
|
||||
break;
|
||||
// case 0x3dd: //Extended ram page address register:
|
||||
break;
|
||||
// break;
|
||||
case 0x3de:
|
||||
write_tandy_reg((Bit8u)val);
|
||||
break;
|
||||
case 0x3df:
|
||||
vga.tandy.line_mask = (Bit8u)(val >> 6);
|
||||
vga.tandy.draw_bank = val & ((vga.tandy.line_mask&2) ? 0x6 : 0x7);
|
||||
if(vga.tandy.line_mask==3) vga.tandy.draw_bank &= ~1; // LSB unused in 32k modes
|
||||
vga.tandy.mem_bank = (val >> 3) & ((vga.tandy.line_mask&2) ? 0x6 : 0x7);
|
||||
TandyCheckLineMask();
|
||||
VGA_SetupHandlers();
|
||||
|
@ -437,12 +504,14 @@ static void write_tandy(Bitu port,Bitu val,Bitu /*iolen*/) {
|
|||
|
||||
static void write_pcjr(Bitu port,Bitu val,Bitu /*iolen*/) {
|
||||
switch (port) {
|
||||
case 0x3d9:
|
||||
write_color_select((Bit8u)val);
|
||||
break;
|
||||
case 0x3da:
|
||||
if (vga.tandy.pcjr_flipflop) write_tandy_reg((Bit8u)val);
|
||||
else vga.tandy.reg_index=(Bit8u)val;
|
||||
else {
|
||||
vga.tandy.reg_index=(Bit8u)val;
|
||||
if (vga.tandy.reg_index & 0x10)
|
||||
vga.attr.disabled |= 2;
|
||||
else vga.attr.disabled &= ~2;
|
||||
}
|
||||
vga.tandy.pcjr_flipflop=!vga.tandy.pcjr_flipflop;
|
||||
break;
|
||||
case 0x3df:
|
||||
|
@ -577,6 +646,10 @@ void VGA_SetupOther(void) {
|
|||
for (i=0;i<256;i++) memcpy(&vga.draw.font[i*32],&int10_font_08[i*8],8);
|
||||
vga.draw.font_tables[0]=vga.draw.font_tables[1]=vga.draw.font;
|
||||
}
|
||||
if (machine==MCH_CGA || IS_TANDY_ARCH || machine==MCH_HERC) {
|
||||
IO_RegisterWriteHandler(0x3db,write_lightpen,IO_MB);
|
||||
IO_RegisterWriteHandler(0x3dc,write_lightpen,IO_MB);
|
||||
}
|
||||
if (machine==MCH_HERC) {
|
||||
extern Bit8u int10_font_14[256 * 14];
|
||||
for (i=0;i<256;i++) memcpy(&vga.draw.font[i*32],&int10_font_14[i*14],14);
|
||||
|
@ -586,8 +659,6 @@ void VGA_SetupOther(void) {
|
|||
if (machine==MCH_CGA) {
|
||||
IO_RegisterWriteHandler(0x3d8,write_cga,IO_MB);
|
||||
IO_RegisterWriteHandler(0x3d9,write_cga,IO_MB);
|
||||
IO_RegisterWriteHandler(0x3db,write_tandy,IO_MB);
|
||||
IO_RegisterWriteHandler(0x3dc,write_tandy,IO_MB);
|
||||
MAPPER_AddHandler(IncreaseHue,MK_f11,MMOD2,"inchue","Inc Hue");
|
||||
MAPPER_AddHandler(DecreaseHue,MK_f11,0,"dechue","Dec Hue");
|
||||
}
|
||||
|
@ -595,14 +666,13 @@ void VGA_SetupOther(void) {
|
|||
write_tandy( 0x3df, 0x0, 0 );
|
||||
IO_RegisterWriteHandler(0x3d8,write_tandy,IO_MB);
|
||||
IO_RegisterWriteHandler(0x3d9,write_tandy,IO_MB);
|
||||
IO_RegisterWriteHandler(0x3da,write_tandy,IO_MB);
|
||||
IO_RegisterWriteHandler(0x3de,write_tandy,IO_MB);
|
||||
IO_RegisterWriteHandler(0x3df,write_tandy,IO_MB);
|
||||
IO_RegisterWriteHandler(0x3da,write_tandy,IO_MB);
|
||||
}
|
||||
if (machine==MCH_PCJR) {
|
||||
//write_pcjr will setup base address
|
||||
write_pcjr( 0x3df, 0x7 | (0x7 << 3), 0 );
|
||||
IO_RegisterWriteHandler(0x3d9,write_pcjr,IO_MB);
|
||||
IO_RegisterWriteHandler(0x3da,write_pcjr,IO_MB);
|
||||
IO_RegisterWriteHandler(0x3df,write_pcjr,IO_MB);
|
||||
}
|
||||
|
|
|
@ -140,7 +140,8 @@ static Bitu INT10_Handler(void) {
|
|||
reg_ah=(Bit8u)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
|
||||
break;
|
||||
case 0x10: /* Palette functions */
|
||||
if ((machine==MCH_CGA) || ((!IS_VGA_ARCH) && (reg_al>0x03))) break;
|
||||
if (!IS_EGAVGA_ARCH && (reg_al>0x02)) break;
|
||||
else if (!IS_VGA_ARCH && (reg_al>0x03)) break;
|
||||
switch (reg_al) {
|
||||
case 0x00: /* SET SINGLE PALETTE REGISTER */
|
||||
INT10_SetSinglePaletteRegister(reg_bl,reg_bh);
|
||||
|
|
|
@ -246,6 +246,7 @@ VideoModeBlock ModeList_OTHER[]={
|
|||
{ 0x008 ,M_TANDY16,160 ,200 ,20 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,56 ,127 ,40 ,100 ,0 },
|
||||
{ 0x009 ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,113 ,63 ,80 ,50 ,0 },
|
||||
{ 0x00A ,M_CGA4 ,640 ,200 ,80 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,113 ,63 ,80 ,50 ,0 },
|
||||
//{ 0x00E ,M_TANDY16,640 ,200 ,80 ,25 ,8 ,8 ,8 ,0xA0000 ,0x10000 ,113 ,256 ,80 ,200 ,0 },
|
||||
{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 },
|
||||
};
|
||||
|
||||
|
@ -547,6 +548,11 @@ bool INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem) {
|
|||
default:
|
||||
IO_WriteB(0x3de,0x0);break;
|
||||
}
|
||||
// write palette
|
||||
for(Bitu i = 0; i < 16; i++) {
|
||||
IO_WriteB(0x3da,i+0x10);
|
||||
IO_WriteB(0x3de,i);
|
||||
}
|
||||
//Clear extended mapping
|
||||
IO_WriteB(0x3da,0x5);
|
||||
IO_WriteB(0x3de,0x0);
|
||||
|
@ -587,8 +593,9 @@ bool INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem) {
|
|||
|
||||
if (CurMode->mode == 0x6 || CurMode->mode==0xa) color_select=0x3f;
|
||||
else color_select=0x30;
|
||||
IO_WriteB(0x3d9,color_select);
|
||||
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
|
||||
INT10_SetColorSelect(1);
|
||||
INT10_SetBackgroundBorder(0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,9 +35,44 @@ static INLINE void WriteTandyACTL(Bit8u creg,Bit8u val) {
|
|||
|
||||
void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val) {
|
||||
switch (machine) {
|
||||
case TANDY_ARCH_CASE:
|
||||
case MCH_PCJR:
|
||||
reg&=0xf;
|
||||
IO_Read(VGAREG_TDY_RESET);
|
||||
WriteTandyACTL(reg+0x10,val);
|
||||
IO_Write(0x3da,0x0); // palette back on
|
||||
break;
|
||||
case MCH_TANDY:
|
||||
// TODO waits for vertical retrace
|
||||
switch(vga.mode) {
|
||||
case M_TANDY2:
|
||||
if (reg >= 0x10) break;
|
||||
else if (reg==1) reg = 0x1f;
|
||||
else reg |= 0x10;
|
||||
WriteTandyACTL(reg+0x10,val);
|
||||
break;
|
||||
case M_TANDY4: {
|
||||
if (CurMode->mode!=0x0a) {
|
||||
// Palette values are kept constand by the BIOS.
|
||||
// The four colors are mapped to special palette values by hardware.
|
||||
// 3D8/3D9 registers influence this mapping. We need to figure out
|
||||
// which entry is used for the requested color.
|
||||
if (reg > 3) break;
|
||||
if (reg != 0) { // 0 is assumed to be at 0
|
||||
Bit8u color_select=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL);
|
||||
reg = reg*2+8; // Green Red Brown
|
||||
if (color_select& 0x20) reg++; // Cyan Magenta White
|
||||
}
|
||||
WriteTandyACTL(reg+0x10,val);
|
||||
}
|
||||
// 4-color high resolution mode 0x0a isn't handled specially
|
||||
else WriteTandyACTL(reg+0x10,val);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WriteTandyACTL(reg+0x10,val);
|
||||
break;
|
||||
}
|
||||
IO_Write(0x3da,0x0); // palette back on
|
||||
break;
|
||||
case EGAVGA_ARCH_CASE:
|
||||
if (!IS_VGA_ARCH) reg&=0x1f;
|
||||
|
@ -266,14 +301,24 @@ void INT10_SetPelMask(Bit8u mask) {
|
|||
|
||||
void INT10_GetPelMask(Bit8u & mask) {
|
||||
mask=IO_Read(VGAREG_PEL_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
void INT10_SetBackgroundBorder(Bit8u val) {
|
||||
Bit8u temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL);
|
||||
temp=(temp & 0xe0) | (val & 0x1f);
|
||||
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,temp);
|
||||
if (machine == MCH_CGA || IS_TANDY_ARCH)
|
||||
IO_Write(0x3d9,temp);
|
||||
Bit8u color_select=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL);
|
||||
color_select=(color_select & 0xe0) | (val & 0x1f);
|
||||
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
|
||||
|
||||
if (machine == MCH_CGA || machine == MCH_TANDY)
|
||||
IO_Write(0x3d9,color_select);
|
||||
else if (machine == MCH_PCJR) {
|
||||
IO_Read(VGAREG_TDY_RESET); // reset the flipflop
|
||||
if (vga.mode!=M_TANDY_TEXT) {
|
||||
IO_Write(VGAREG_TDY_ADDRESS, 0x10);
|
||||
IO_Write(VGAREG_PCJR_DATA, color_select&0xf);
|
||||
}
|
||||
IO_Write(VGAREG_TDY_ADDRESS, 0x2); // border color
|
||||
IO_Write(VGAREG_PCJR_DATA, color_select&0xf);
|
||||
}
|
||||
else if (IS_EGAVGA_ARCH) {
|
||||
val = ((val << 1) & 0x10) | (val & 0x7);
|
||||
/* Aways set the overscan color */
|
||||
|
@ -282,7 +327,7 @@ void INT10_SetBackgroundBorder(Bit8u val) {
|
|||
if (CurMode->mode <= 3)
|
||||
return;
|
||||
INT10_SetSinglePaletteRegister( 0, val );
|
||||
val = (temp & 0x10) | 2 | ((temp & 0x20) >> 5);
|
||||
val = (color_select & 0x10) | 2 | ((color_select & 0x20) >> 5);
|
||||
INT10_SetSinglePaletteRegister( 1, val );
|
||||
val+=2;
|
||||
INT10_SetSinglePaletteRegister( 2, val );
|
||||
|
@ -295,8 +340,31 @@ void INT10_SetColorSelect(Bit8u val) {
|
|||
Bit8u temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL);
|
||||
temp=(temp & 0xdf) | ((val & 1) ? 0x20 : 0x0);
|
||||
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,temp);
|
||||
if (machine == MCH_CGA || IS_TANDY_ARCH)
|
||||
if (machine == MCH_CGA || machine==MCH_TANDY)
|
||||
IO_Write(0x3d9,temp);
|
||||
else if (machine == MCH_PCJR) {
|
||||
switch(vga.mode) {
|
||||
case M_TANDY2:
|
||||
IO_Write(VGAREG_TDY_ADDRESS, 0x11);
|
||||
IO_Write(VGAREG_PCJR_DATA, val&1? 0xf:0);
|
||||
break;
|
||||
case M_TANDY4:
|
||||
for(Bit8u i = 0x11; i < 0x14; i++) {
|
||||
const Bit8u t4_table[] = {0,2,4,6, 0,3,5,0xf};
|
||||
IO_Write(VGAREG_TDY_ADDRESS, i);
|
||||
IO_Write(VGAREG_PCJR_DATA, t4_table[(i-0x10)+(val&1? 4:0)]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// 16-color modes: always write the same palette
|
||||
for(Bit8u i = 0x11; i < 0x20; i++) {
|
||||
IO_Write(VGAREG_TDY_ADDRESS, i);
|
||||
IO_Write(VGAREG_PCJR_DATA, i-0x10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
IO_Write(VGAREG_TDY_ADDRESS, 0); // enable palette
|
||||
}
|
||||
else if (IS_EGAVGA_ARCH) {
|
||||
if (CurMode->mode <= 3) //Maybe even skip the total function!
|
||||
return;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue