diff --git a/include/vga.h b/include/vga.h index 5fde426f..2674aeee 100644 --- a/include/vga.h +++ b/include/vga.h @@ -196,6 +196,8 @@ typedef struct { Bit8u gfx_control; Bit8u palette_mask; Bit8u border_color; + bool is_32k_mode; + bool pcjr_flipflop; } VGA_TANDY; typedef struct { diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 1569b2bc..fb54ce9c 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -502,7 +502,8 @@ void VGA_SetupDrawing(Bitu val) { case M_TANDY2: aspect_ratio=1.2; doubleheight=true; - doublewidth=(vga.tandy.mode_control & 0x10)==0; + if (machine==MCH_TANDY) doublewidth=(vga.tandy.mode_control & 0x10)==0; + else doublewidth=(vga.tandy.gfx_control & 0x8)==0x00; vga.draw.blocks=width * (doublewidth ? 4:8); width=vga.draw.blocks*2; VGA_DrawLine=VGA_Draw_1BPP_Line; @@ -510,7 +511,8 @@ void VGA_SetupDrawing(Bitu val) { case M_TANDY4: aspect_ratio=1.2; doubleheight=true; - doublewidth=(vga.tandy.mode_control & 0x10)==0; + if (machine==MCH_TANDY) doublewidth=(vga.tandy.mode_control & 0x10)==0; + else doublewidth=(vga.tandy.gfx_control & 0x8)==0x00; vga.draw.blocks=width * (doublewidth ? 4:8); width=vga.draw.blocks*2; VGA_DrawLine=VGA_Draw_2BPP_Line; @@ -518,7 +520,8 @@ void VGA_SetupDrawing(Bitu val) { case M_TANDY16: aspect_ratio=1.2; doubleheight=true; - doublewidth=(vga.tandy.mode_control & 0x10)==0; + if (machine==MCH_TANDY) doublewidth=(vga.tandy.mode_control & 0x10)==0; + else doublewidth=(vga.tandy.gfx_control & 0x8)==0x00; vga.draw.blocks=width * (doublewidth ? 2:4); width=vga.draw.blocks*2; VGA_DrawLine=VGA_Draw_4BPP_Line; diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index 88cbc4b2..93d6d5d9 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_memory.cpp @@ -428,7 +428,7 @@ public: phys_page-=0xb8; return &vga.mem.linear[(vga.tandy.mem_bank << 14)+(phys_page * 4096)]; } else { - phys_page-=0x80; + if (machine==MCH_TANDY) phys_page-=0x80; return &vga.mem.linear[phys_page * 4096]; } } @@ -457,10 +457,14 @@ void VGA_SetupHandlers(void) { range_handler=&vgaph.hmap; if (vga.herc.mode_control&0x80) goto range_b800; else goto range_b000; - case TANDY_ARCH_CASE: + case MCH_TANDY: range_handler=&vgaph.htandy; MEM_SetPageHandler(0x80,32,range_handler); goto range_b800; + case MCH_PCJR: + range_handler=&vgaph.htandy; + MEM_SetPageHandler(vga.tandy.mem_bank<<2,vga.tandy.is_32k_mode ? 0x08 : 0x04,range_handler); + goto range_b800; } switch (vga.mode) { case M_ERROR: diff --git a/src/hardware/vga_misc.cpp b/src/hardware/vga_misc.cpp index 1f96bcda..c63c53b2 100644 --- a/src/hardware/vga_misc.cpp +++ b/src/hardware/vga_misc.cpp @@ -30,6 +30,7 @@ Bitu read_p3d5_vga(Bitu port,Bitu iolen); static Bitu read_p3da(Bitu port,Bitu iolen) { vga.internal.attrindex=false; + vga.tandy.pcjr_flipflop=false; if (vga.config.retrace) { switch (machine) { case MCH_HERC: diff --git a/src/hardware/vga_other.cpp b/src/hardware/vga_other.cpp index 13e7f854..3453c73b 100644 --- a/src/hardware/vga_other.cpp +++ b/src/hardware/vga_other.cpp @@ -199,9 +199,6 @@ static void write_color_select(Bit8u val) { /* Check for BW Mode */ if (vga.tandy.mode_control & 0x4) { VGA_SetCGA4Table(val & 0xf,3+base,4+base,7+base); - /* old code: - if (val & 0x20) VGA_SetCGA4Table(val & 0xf,3+base,4+base,7+base); - else VGA_SetCGA4Table(val & 0xf,2+base,4+base,6+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); @@ -242,14 +239,39 @@ static void TANDY_FindMode(void) { } } +static void PCJr_FindMode(void) { + if (vga.tandy.mode_control & 0x2) { + if (vga.tandy.mode_control & 0x10) { + /* bit4 of mode control 1 signals 16 colour graphics mode */ + VGA_SetMode(M_TANDY16); + } else if (vga.tandy.gfx_control & 0x08) { + /* bit3 of mode control 2 signals 2 colour graphics mode */ + VGA_SetMode(M_TANDY2); + } else { + /* otherwise some 4-colour graphics mode */ + VGA_SetMode(M_TANDY4); + } + write_color_select(vga.tandy.color_select); + } else { + VGA_SetMode(M_TANDY_TEXT); + } +} + static void write_tandy_reg(Bit8u val) { switch (vga.tandy.reg_index) { + case 0x0: + if (machine==MCH_PCJR) { + vga.tandy.mode_control=val; + VGA_SetBlinking(val & 0x20); + PCJr_FindMode(); + } else LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index); case 0x2: /* Border color */ vga.tandy.border_color=val; break; case 0x3: /* More control */ vga.tandy.gfx_control=val; - TANDY_FindMode(); + if (machine==MCH_TANDY) TANDY_FindMode(); + else PCJr_FindMode(); break; /* palette colors */ case 0x10: case 0x11: case 0x12: case 0x13: @@ -311,6 +333,25 @@ 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(val); + break; + case 0x3da: + if (vga.tandy.pcjr_flipflop) write_tandy_reg(val); + else vga.tandy.reg_index=val; + vga.tandy.pcjr_flipflop=!vga.tandy.pcjr_flipflop; + break; + case 0x3df: + vga.tandy.is_32k_mode=(val & 0x80)==0x80; + vga.tandy.disp_bank=val & (vga.tandy.is_32k_mode ? 0x6 : 0x7); + vga.tandy.mem_bank=(val >> 3) & (vga.tandy.is_32k_mode ? 0x6 : 0x7); + VGA_SetupHandlers(); + break; + } +} + static void write_hercules(Bitu port,Bitu val,Bitu iolen) { switch (port) { case 0x3b8: @@ -362,13 +403,20 @@ void VGA_SetupOther(void) { IO_RegisterWriteHandler(0x3b8,write_hercules,IO_MB); IO_RegisterWriteHandler(0x3bf,write_hercules,IO_MB); } - if (IS_TANDY_ARCH) { + if (machine==MCH_TANDY) { IO_RegisterWriteHandler(0x3d8,write_tandy,IO_MB); IO_RegisterWriteHandler(0x3d9,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) { + vga.tandy.mem_bank=7;vga.tandy.disp_bank=7; + vga.tandy.is_32k_mode=false;vga.tandy.pcjr_flipflop=false; + IO_RegisterWriteHandler(0x3d9,write_pcjr,IO_MB); + IO_RegisterWriteHandler(0x3da,write_pcjr,IO_MB); + IO_RegisterWriteHandler(0x3df,write_pcjr,IO_MB); + } if (machine==MCH_CGA || machine==MCH_HERC || IS_TANDY_ARCH) { Bitu base=machine==MCH_HERC ? 0x3b4 : 0x3d4; IO_RegisterWriteHandler(base,write_crtc_index_other,IO_MB); diff --git a/src/ints/int10.cpp b/src/ints/int10.cpp index 27dcc17a..22ede176 100644 --- a/src/ints/int10.cpp +++ b/src/ints/int10.cpp @@ -85,6 +85,11 @@ static Bitu INT10_Handler(void) { crtcpu=(crtcpu & 0xc0) | (reg_bh & 7) | ((reg_bl & 7) << 3); break; } + if (machine==MCH_PCJR) { + /* always return graphics mapping, even for invalid values of AL */ + reg_bh=crtcpu & 7; + reg_bl=(crtcpu >> 3) & 0x7; + } IO_WriteB(0x3df,crtcpu); real_writeb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE,crtcpu); } @@ -114,7 +119,10 @@ static Bitu INT10_Handler(void) { INT10_SetColorSelect(reg_bl); break; default: - if(machine == MCH_CGA) INT10_SetColorSelect(reg_bl); + if ((machine==MCH_CGA) || (machine==MCH_PCJR)) { + /* those BIOSes check for !=0 */ + INT10_SetColorSelect(reg_bl); + } break; } break; diff --git a/src/ints/int10_modes.cpp b/src/ints/int10_modes.cpp index a64c2537..2996f014 100644 --- a/src/ints/int10_modes.cpp +++ b/src/ints/int10_modes.cpp @@ -300,9 +300,11 @@ bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) { break; case M_CGA2: scanline=2; + break; case M_CGA4: if (CurMode->mode!=0xa) scanline=2; else scanline=4; + break; case M_TANDY16: if (CurMode->mode!=0x9) scanline=2; else scanline=4; @@ -319,6 +321,11 @@ bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) { 0x2a,0x2e,0x1e,0x29, //4-7 0x2a,0x2b,0x3b //8-a }; + Bit8u mode_control_list_pcjr[0xa+1]={ + 0x0c,0x08,0x0d,0x09, //0-3 + 0x0a,0x0e,0x0e,0x09, //4-7 + 0x1a,0x1b,0x0b //8-a + }; Bit8u mode_control,color_select; switch (machine) { case MCH_HERC: @@ -336,10 +343,10 @@ bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) { real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control); real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select); break; - case TANDY_ARCH_CASE: + case MCH_TANDY: /* Init some registers */ IO_WriteB(0x3da,0x1);IO_WriteB(0x3de,0xf); //Palette mask always 0xf - IO_WriteB(0x3da,0x2);IO_WriteB(0x3de,0x0); //block border + IO_WriteB(0x3da,0x2);IO_WriteB(0x3de,0x0); //black border IO_WriteB(0x3da,0x3); //Tandy color overrides? switch (CurMode->mode) { case 0x8: @@ -362,6 +369,32 @@ bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) { real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control); real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select); break; + case MCH_PCJR: + /* Init some registers */ + IO_ReadB(0x3da); + IO_WriteB(0x3da,0x1);IO_WriteB(0x3da,0xf); //Palette mask always 0xf + IO_WriteB(0x3da,0x2);IO_WriteB(0x3da,0x0); //black border + IO_WriteB(0x3da,0x3); + if (CurMode->mode<=0x04) IO_WriteB(0x3da,0x02); + else if (CurMode->mode==0x06) IO_WriteB(0x3da,0x08); + else IO_WriteB(0x3da,0x00); + + /* set CRT/Processor page register */ + if (CurMode->mode<0x04) crtpage=0x3f; + else if (CurMode->mode>=0x09) crtpage=0xf6; + else crtpage=0x7f; + IO_WriteB(0x3df,crtpage); + real_writeb(BIOSMEM_SEG,BIOSMEM_CRTCPU_PAGE,crtpage); + + mode_control=mode_control_list_pcjr[CurMode->mode]; + IO_WriteB(0x3da,0x0);IO_WriteB(0x3da,mode_control); + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control); + + 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); + break; } FinishSetMode(clearmem); return true;