1
0
Fork 0

Added MC6845 display controller support for hercules,cga,tandy machine modes.

Added cga,tandy,text modes.
Added some new tandy modes.
Added better tandy register support.


Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1691
This commit is contained in:
Sjoerd van der Berg 2004-02-29 22:18:24 +00:00
parent 5ec076438e
commit f7c4b46991
19 changed files with 953 additions and 667 deletions

View file

@ -23,13 +23,13 @@
#include "dosbox.h"
enum VGAModes {
M_TEXT2,M_TEXT16,
M_HERC,
M_CGA2,M_CGA4,M_CGA16,
M_TANDY16,
M_EGA2,M_EGA4,M_EGA16,
M_TEXT,
M_HERC_GFX,M_HERC_TEXT,
M_CGA2,M_CGA4,
M_EGA16,
M_VGA,
M_LIN8,
M_CGA16,M_TANDY2,M_TANDY4,M_TANDY16,M_TANDY_TEXT,
M_ERROR,
};
@ -161,18 +161,28 @@ typedef struct {
} VGA_HERC;
typedef struct {
Bit8u mode_control;
Bit8u color_select;
} VGA_CGA;
Bit8u index;
Bit8u htotal;
Bit8u hdend;
Bit8u hsyncp;
Bit8u hsyncw;
Bit8u vtotal;
Bit8u vdend;
Bit8u vadjust;
Bit8u vsyncp;
Bit8u vsyncw;
Bit8u max_scanline;
} VGA_OTHER;
typedef struct {
Bit8u mode_control;
Bit8u color_select;
Bit8u mem_bank;
Bit8u disp_bank;
Bit8u reg_index;
Bit8u mode_control1;
Bit8u gfx_control;
Bit8u palette_mask;
Bit8u border_color;
Bit8u mode_control2;
} VGA_TANDY;
typedef struct {
@ -255,7 +265,6 @@ typedef struct {
Bit8u read_index;
Bitu first_changed;
RGBEntry rgb[0x100];
Bit8u attr[16];
} VGA_Dac;
union VGA_Latch {
@ -284,8 +293,8 @@ typedef struct {
VGA_Latch latch;
VGA_S3 s3;
VGA_HERC herc;
VGA_CGA cga;
VGA_TANDY tandy;
VGA_OTHER other;
VGA_Memory mem;
} VGA_Type;
@ -293,6 +302,7 @@ typedef struct {
/* Functions for different resolutions */
void VGA_SetMode(VGAModes mode);
void VGA_DetermineMode(void);
void VGA_SetupHandlers(void);
void VGA_StartResize(void);
void VGA_SetupDrawing(Bitu val);
@ -300,6 +310,7 @@ void VGA_CheckScanLength(void);
/* Some DAC/Attribute functions */
void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal);
void VGA_DAC_SetEntry(Bitu entry,Bit8u red,Bit8u green,Bit8u blue);
void VGA_ATTR_SetPalette(Bit8u index,Bit8u val);
/* The VGA Subfunction startups */
@ -310,6 +321,7 @@ void VGA_SetupCRTC(void);
void VGA_SetupMisc(void);
void VGA_SetupGFX(void);
void VGA_SetupSEQ(void);
void VGA_SetupOther(void);
/* Some Support Functions */
void VGA_SetClock(Bitu which,Bitu target);
@ -317,6 +329,8 @@ void VGA_DACSetEntirePalette(void);
void VGA_StartRetrace(void);
void VGA_StartUpdateLFB(void);
void VGA_SetBlinking(Bitu enabled);
void VGA_SetCGA2Table(Bit8u val0,Bit8u val1);
void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3);
extern VGA_Type vga;

View file

@ -6,7 +6,7 @@ noinst_LIBRARIES = libhardware.a
libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler.cpp joystick.cpp keyboard.cpp \
memory.cpp mixer.cpp pcspeaker.cpp pic.cpp sblaster.cpp tandy_sound.cpp timer.cpp \
vga.cpp vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_gfx.cpp \
vga.cpp vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_gfx.cpp vga_other.cpp \
vga_memory.cpp vga_misc.cpp vga_seq.cpp font-switch.h ega-switch.h cmos.cpp disney.cpp \
gus.cpp mpu401.cpp serialport.cpp softmodem.cpp ipx.cpp ipxserver.cpp

View file

@ -48,6 +48,20 @@ void VGA_SetMode(VGAModes mode) {
VGA_StartResize();
}
void VGA_DetermineMode(void) {
/* Test for graphics or alphanumeric mode */
if (vga.attr.mode_control & 1) {
if (!(vga.crtc.mode_control & 0x1)) {
if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4);
else VGA_SetMode(M_CGA2);
} else if (vga.attr.mode_control & 0x40) {
VGA_SetMode(M_VGA);
} else VGA_SetMode(M_EGA16);
} else {
VGA_SetMode(M_TEXT);
}
}
void VGA_StartResize(void) {
if (!vga.draw.resizing) {
vga.draw.resizing=true;
@ -88,34 +102,56 @@ void VGA_SetClock(Bitu which,Bitu target) {
VGA_StartResize();
}
void VGA_SetCGA2Table(Bit8u val0,Bit8u val1) {
Bit8u total[2]={ val0,val1};
for (Bitu i=0;i<16;i++) {
CGA_2_Table[i]=
#ifdef WORDS_BIGENDIAN
(total[(i >> 0) & 1] << 0 ) | (total[(i >> 1) & 1] << 8 ) |
(total[(i >> 2) & 1] << 16 ) | (total[(i >> 3) & 1] << 24 );
#else
(total[(i >> 3) & 1] << 0 ) | (total[(i >> 2) & 1] << 8 ) |
(total[(i >> 1) & 1] << 16 ) | (total[(i >> 0) & 1] << 24 );
#endif
}
}
void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3) {
Bit8u total[4]={ val0,val1,val2,val3};
for (Bitu i=0;i<256;i++) {
CGA_4_Table[i]=
#ifdef WORDS_BIGENDIAN
(total[(i >> 0) & 3] << 0 ) | (total[(i >> 2) & 3] << 8 ) |
(total[(i >> 4) & 3] << 16 ) | (total[(i >> 6) & 3] << 24 );
#else
(total[(i >> 6) & 3] << 0 ) | (total[(i >> 4) & 3] << 8 ) |
(total[(i >> 2) & 3] << 16 ) | (total[(i >> 0) & 3] << 24 );
#endif
}
}
void VGA_Init(Section* sec) {
vga.draw.resizing=false;
vga.mode=M_ERROR; //For first init
VGA_SetupMemory();
VGA_SetupMisc();
VGA_SetupDAC();
VGA_SetupGFX();
VGA_SetupSEQ();
VGA_SetupAttr();
VGA_SetupOther();
VGA_SetClock(0,CLK_25);
VGA_SetClock(1,CLK_28);
/* Generate tables */
VGA_SetCGA2Table(0,1);
VGA_SetCGA4Table(0,1,2,3);
Bitu i,j;
for (i=0;i<256;i++) {
ExpandTable[i]=i | (i << 8)| (i <<16) | (i << 24);
#ifdef WORDS_BIGENDIAN
CGA_4_Table[i]=((i>>0)&3) | (((i>>2)&3) << 8)| (((i>>4)&3) <<16) | (((i>>6)&3) << 24);
#else
CGA_4_Table[i]=((i>>6)&3) | (((i>>4)&3) << 8)| (((i>>2)&3) <<16) | (((i>>0)&3) << 24);
#endif
}
for (i=0;i<16;i++) {
TXT_FG_Table[i]=i | (i << 8)| (i <<16) | (i << 24);
TXT_BG_Table[i]=i | (i << 8)| (i <<16) | (i << 24);
#ifdef WORDS_BIGENDIAN
CGA_2_Table[i]=((i>>0)&1) | (((i>>1)&1) << 8)| (((i>>1)&1) <<16) | (((i>>3)&1) << 24);
FillTable[i]=
((i & 1) ? 0xff000000 : 0) |
((i & 2) ? 0x00ff0000 : 0) |
@ -127,7 +163,6 @@ void VGA_Init(Section* sec) {
((i & 4) ? 0x00ff0000 : 0) |
((i & 8) ? 0xff000000 : 0) ;
#else
CGA_2_Table[i]=((i>>3)&1) | (((i>>2)&1) << 8)| (((i>>1)&1) <<16) | (((i>>0)&1) << 24);
FillTable[i]=
((i & 1) ? 0x000000ff : 0) |
((i & 2) ? 0x0000ff00 : 0) |
@ -138,7 +173,6 @@ void VGA_Init(Section* sec) {
((i & 2) ? 0x00ff0000 : 0) |
((i & 4) ? 0x0000ff00 : 0) |
((i & 8) ? 0x000000ff : 0) ;
#endif
}
for (j=0;j<4;j++) {

View file

@ -23,7 +23,6 @@
#define attr(blah) vga.attr.blah
void VGA_ATTR_SetPalette(Bit8u index,Bit8u val) {
vga.attr.palette[index]=val;
if (vga.attr.mode_control & 0x80) val=(val&0xf) | (vga.attr.color_select << 4);
else val|=(vga.attr.color_select & 0xc) << 4;
VGA_DAC_CombineColor(index,val);
@ -69,16 +68,9 @@ void write_p3c0(Bit32u port,Bit8u val) {
Doesn't work if they program EGA16 themselves,
but haven't encountered that yet
*/
if (val&0x40) {
if (vga.mode<M_VGA) VGA_SetMode(M_VGA);
} else {
if (vga.mode==M_VGA) VGA_SetMode(M_EGA16);
}
attr(mode_control)=val;
//TODO Monochrome mode
VGA_DetermineMode();
//TODO 9 bit characters
//TODO line wrapping split screen shit see bit 5
//TODO index 14h weirdo dac switch bits
/*
0 Graphics mode if set, Alphanumeric mode else.
1 Monochrome mode if set, color mode else.
@ -116,8 +108,7 @@ void write_p3c0(Bit32u port,Bit8u val) {
case 0x13: /* Horizontal PEL Panning Register */
attr(horizontal_pel_panning)=val & 0xF;
switch (vga.mode) {
case M_TEXT2:
case M_TEXT16:
case M_TEXT:
if (val==0x7) vga.config.pel_panning=7;
if (val>0x7) vga.config.pel_panning=0;
else vga.config.pel_panning=val+1;
@ -196,8 +187,10 @@ Bit8u read_p3c1(Bit32u port) {
void VGA_SetupAttr(void) {
IO_RegisterWriteHandler(0x3c0,write_p3c0,"VGA Attribute controller");
IO_RegisterReadHandler(0x3c1,read_p3c1,"VGA Attribute Read");
if (machine==MCH_VGA) {
IO_RegisterWriteHandler(0x3c0,write_p3c0,"VGA Attribute controller");
IO_RegisterReadHandler(0x3c1,read_p3c1,"VGA Attribute Read");
}
}

View file

@ -22,19 +22,17 @@
#include "debug.h"
#include "cpu.h"
#define crtc(blah) vga.crtc.blah
void write_p3d4(Bit32u port,Bit8u val) {
void write_p3d4_vga(Bit32u port,Bit8u val) {
crtc(index)=val;
}
Bit8u read_p3d4(Bit32u port) {
Bit8u read_p3d4_vga(Bit32u port) {
return crtc(index);
}
void write_p3d5(Bit32u port,Bit8u val) {
void write_p3d5_vga(Bit32u port,Bit8u val) {
// if (crtc(index)>0x18) LOG_MSG("VGA CRCT write %X to reg %X",val,crtc(index));
switch(crtc(index)) {
case 0x00: /* Horizontal Total Register */
@ -256,6 +254,7 @@ void write_p3d5(Bit32u port,Bit8u val) {
break;
case 0x17: /* Mode Control Register */
crtc(mode_control)=val;
VGA_DetermineMode();
/*
0 If clear use CGA compatible memory addressing system
by substituting character row scan counter bit 0 for address bit 13,
@ -495,7 +494,7 @@ void write_p3d5(Bit32u port,Bit8u val) {
}
}
Bit8u read_p3d5(Bit32u port) {
Bit8u read_p3d5_vga(Bit32u port) {
// LOG_MSG("VGA CRCT read from reg %X",crtc(index));
switch(crtc(index)) {
case 0x00: /* Horizontal Total Register */

View file

@ -105,7 +105,7 @@ static void write_p3c9(Bit32u port,Bit8u val) {
default:
/* Check for attributes and DAC entry link */
for (Bitu i=0;i<16;i++) {
if (vga.dac.attr[i]==vga.dac.write_index) {
if (vga.attr.palette[i]==vga.dac.write_index) {
RENDER_SetPal(i,
vga.dac.rgb[vga.dac.write_index].red << 2,
vga.dac.rgb[vga.dac.write_index].green << 2,
@ -145,7 +145,7 @@ static Bit8u read_p3c9(Bit32u port) {
void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal) {
/* Check if this is a new color */
vga.dac.attr[attr]=pal;
vga.attr.palette[attr]=pal;
switch (vga.mode) {
case M_VGA:
case M_LIN8:
@ -159,6 +159,20 @@ void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal) {
}
}
void VGA_DAC_SetEntry(Bitu entry,Bit8u red,Bit8u green,Bit8u blue) {
vga.dac.rgb[entry].red=red;
vga.dac.rgb[entry].green=green;
vga.dac.rgb[entry].blue=blue;
switch (vga.mode) {
case M_VGA:
case M_LIN8:
return;
}
for (Bitu i=0;i<16;i++)
if (vga.attr.palette[i]==entry)
RENDER_SetPal(i,red << 2,green << 2,blue << 2);
}
void VGA_SetupDAC(void) {
vga.dac.first_changed=256;
vga.dac.bits=6;
@ -167,14 +181,16 @@ void VGA_SetupDAC(void) {
vga.dac.state=DAC_READ;
vga.dac.read_index=0;
vga.dac.write_index=0;
/* Setup the DAC IO port Handlers */
IO_RegisterWriteHandler(0x3c6,write_p3c6,"PEL Mask");
IO_RegisterReadHandler(0x3c6,read_p3c6,"PEL Mask");
IO_RegisterWriteHandler(0x3c7,write_p3c7,"PEL Read Mode");
IO_RegisterReadHandler(0x3c7,read_p3c7,"PEL Status Mode");
IO_RegisterWriteHandler(0x3c8,write_p3c8,"PEL Write Mode");
IO_RegisterWriteHandler(0x3c9,write_p3c9,"PEL Data");
IO_RegisterReadHandler(0x3c9,read_p3c9,"PEL Data");
if (machine==MCH_VGA) {
/* Setup the DAC IO port Handlers */
IO_RegisterWriteHandler(0x3c6,write_p3c6,"PEL Mask");
IO_RegisterReadHandler(0x3c6,read_p3c6,"PEL Mask");
IO_RegisterWriteHandler(0x3c7,write_p3c7,"PEL Read Mode");
IO_RegisterReadHandler(0x3c7,read_p3c7,"PEL Status Mode");
IO_RegisterWriteHandler(0x3c8,write_p3c8,"PEL Write Mode");
IO_RegisterWriteHandler(0x3c9,write_p3c9,"PEL Data");
IO_RegisterReadHandler(0x3c9,read_p3c9,"PEL Data");
}
};

View file

@ -30,18 +30,8 @@ typedef Bit8u * (* VGA_Line_Handler)(Bitu vidstart,Bitu panning,Bitu line);
static VGA_Line_Handler VGA_DrawLine;
static Bit8u * VGA_HERC_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) {
Bit8u * reader=&vga.mem.linear[vidstart+(line * 8 * 1024)];
Bit32u * draw=(Bit32u *)RENDER_TempLine;
for (Bitu x=vga.draw.blocks;x>0;x--) {
Bitu val=*reader++;
*draw++=CGA_2_Table[val >> 4];
*draw++=CGA_2_Table[val & 0xf];
}
return RENDER_TempLine;
}
static Bit8u * VGA_CGA2_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) {
static Bit8u * VGA_Draw_1BPP_Line(Bitu vidstart,Bitu panning,Bitu line) {
line*=8*1024;Bit32u * draw=(Bit32u *)RENDER_TempLine;
for (Bitu x=vga.draw.blocks;x>0;x--) {
Bitu val=vga.mem.linear[vidstart+line];vidstart=(vidstart+1)&0x1fff;
@ -51,7 +41,7 @@ static Bit8u * VGA_CGA2_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) {
return RENDER_TempLine;
}
static Bit8u * VGA_CGA4_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) {
static Bit8u * VGA_Draw_2BPP_Line(Bitu vidstart,Bitu panning,Bitu line) {
line*=8*1024;Bit32u * draw=(Bit32u *)RENDER_TempLine;
for (Bitu x=0;x<vga.draw.blocks;x++) {
Bitu val=vga.mem.linear[vidstart+line];vidstart=(vidstart+1)&0x1fff;
@ -60,23 +50,12 @@ static Bit8u * VGA_CGA4_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) {
return RENDER_TempLine;
}
static Bit8u convert16[16]={
0x0,0x2,0x1,0x3,0x5,0x7,0x4,0x9,
0x6,0xa,0x8,0xb,0xd,0xe,0xc,0xf
};
static Bit8u * VGA_CGA16_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) {
line*=8*1024;Bit32u * draw=(Bit32u *)RENDER_TempLine;
for (Bitu x=0;x<vga.draw.blocks;x++) {
Bitu val=vga.mem.linear[vidstart+line];vidstart=(vidstart+1)&0x1fff;
Bit32u full=convert16[val >> 4] | convert16[val & 0xf] << 16;
*draw++=full|=full<<8;
}
return RENDER_TempLine;
}
static Bit8u * VGA_TANDY16_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) {
static Bit8u * VGA_Draw_4BPP_Line(Bitu vidstart,Bitu panning,Bitu line) {
Bit8u * reader=&vga.mem.linear[(vga.tandy.disp_bank << 14) + vidstart + (line * 8 * 1024)];
Bit32u * draw=(Bit32u *)RENDER_TempLine;
for (Bitu x=0;x<vga.draw.blocks;x++) {
@ -89,10 +68,24 @@ static Bit8u * VGA_TANDY16_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) {
return RENDER_TempLine;
}
static Bit8u * VGA_EGA_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) {
static Bit8u * VGA_Draw_4BPP_Line_Double(Bitu vidstart,Bitu panning,Bitu line) {
Bit8u * reader=&vga.mem.linear[(vga.tandy.disp_bank << 14) + vidstart + (line * 8 * 1024)];
Bit32u * draw=(Bit32u *)RENDER_TempLine;
for (Bitu x=0;x<vga.draw.blocks;x++) {
Bitu val1=*reader++;Bitu val2=*reader++;
*draw++=(val1 & 0x0f) << 8 |
(val1 & 0xf0) >> 4 |
(val2 & 0x0f) << 24 |
(val2 & 0xf0) << 12;
}
return RENDER_TempLine;
}
static Bit8u * VGA_Draw_EGA_Line(Bitu vidstart,Bitu panning,Bitu line) {
return &vga.mem.linear[512*1024+vidstart*8+panning];
}
static Bit8u * VGA_VGA_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) {
static Bit8u * VGA_Draw_VGA_Line(Bitu vidstart,Bitu panning,Bitu line) {
return &vga.mem.linear[vidstart*4+panning];
}
@ -163,11 +156,11 @@ void VGA_SetBlinking(Bitu enabled) {
if (enabled) {
b=0;vga.draw.blinking=1; //used to -1 but blinking is unsigned
vga.attr.mode_control|=0x08;
vga.cga.mode_control&=~0x20;
vga.tandy.mode_control&=~0x20;
} else {
b=8;vga.draw.blinking=0;
vga.attr.mode_control&=~0x08;
vga.cga.mode_control|=0x20;
vga.tandy.mode_control|=0x20;
}
for (Bitu i=0;i<8;i++) TXT_BG_Table[i+8]=(b+i) | ((b+i) << 8)| ((b+i) <<16) | ((b+i) << 24);
}
@ -183,7 +176,7 @@ static void VGA_VerticalTimer(Bitu val) {
vga.draw.split_line=vga.draw.lines_total-(vga.config.line_compare/vga.draw.lines_scaled);
vga.draw.panning=vga.config.pel_panning;
switch (vga.mode) {
case M_TEXT2:case M_TEXT16:
case M_TEXT:
vga.draw.cursor.count++;
/* check for blinking and blinking change delay */
FontMask[1]=(vga.attr.mode_control & (vga.draw.cursor.count >> 1) & 0x8) ?
@ -206,57 +199,98 @@ void VGA_CheckScanLength(void) {
case M_LIN8:
vga.draw.address_add=vga.config.scan_len*2;
break;
case M_CGA2:case M_CGA4:case M_CGA16:
vga.draw.address_add=80;
break;
case M_TANDY16:
vga.draw.address_add=160;
break;
case M_TEXT16:
case M_TEXT2:
case M_TEXT:
vga.draw.address_add=vga.config.scan_len*4;
break;
case M_HERC:
case M_CGA2:
case M_CGA4:
vga.draw.address_add=80;
return;
case M_TANDY2:
vga.draw.address_add=vga.draw.blocks/4;
break;
case M_TANDY4:
vga.draw.address_add=vga.draw.blocks/2;
break;
case M_CGA16:
vga.draw.address_add=vga.draw.blocks/2;
return;
case M_TANDY16:
vga.draw.address_add=vga.draw.blocks;
break;
case M_TANDY_TEXT:
vga.draw.address_add=vga.draw.blocks*2;
break;
case M_HERC_TEXT:
vga.draw.address_add=vga.draw.blocks*2;
break;
case M_HERC_GFX:
vga.draw.address_add=vga.draw.blocks;
break;
}
}
void VGA_SetupDrawing(Bitu val) {
/* Calculate the FPS for this screen */
double fps;
Bitu vtotal=2 + vga.crtc.vertical_total |
((vga.crtc.overflow & 1) << 8) | ((vga.crtc.overflow & 0x20) << 4);
Bitu htotal=5 + vga.crtc.horizontal_total;
Bitu vdispend = 1 + (vga.crtc.vertical_display_end |
((vga.crtc.overflow & 2)<<7) | ((vga.crtc.overflow & 0x40) << 3) |
((vga.s3.ex_ver_overflow & 0x2) << 9));
Bitu hdispend = 1 + (vga.crtc.horizontal_display_end);
Bitu hbstart = vga.crtc.start_horizontal_blanking;
Bitu vbstart = vga.crtc.start_vertical_blanking | ((vga.crtc.overflow & 0x08) << 5) |
((vga.crtc.maximum_scan_line & 0x20) << 4) ;
Bitu hrstart = vga.crtc.start_horizontal_retrace;
Bitu vrstart = vga.crtc.vertical_retrace_start + ((vga.crtc.overflow & 0x04) << 6) |
((vga.crtc.overflow & 0x80) << 2);
if (hbstart<hdispend) hdispend=hbstart;
if (vbstart<vdispend) vdispend=vbstart;
Bitu clock=(vga.misc_output >> 2) & 3;
clock=1000*S3_CLOCK(vga.s3.clk[clock].m,vga.s3.clk[clock].n,vga.s3.clk[clock].r);
/* Check for 8 for 9 character clock mode */
if (vga.seq.clocking_mode & 1 ) clock/=8; else clock/=9;
/* Check for pixel doubling, master clock/2 */
if (vga.seq.clocking_mode & 0x8) {
htotal*=2;
if (vga.mode==M_ERROR) {
PIC_RemoveEvents(VGA_VerticalTimer);
PIC_RemoveEvents(VGA_VerticalDisplayEnd);
return;
}
/* Calculate the FPS for this screen */
double fps;Bitu clock;
Bitu htotal,hdispend,hbstart,hrstart;
Bitu vtotal,vdispend,vbstart,vrstart;
if (machine==MCH_VGA) {
vtotal=2 + vga.crtc.vertical_total |
((vga.crtc.overflow & 1) << 8) | ((vga.crtc.overflow & 0x20) << 4);
htotal=5 + vga.crtc.horizontal_total;
vdispend = 1 + (vga.crtc.vertical_display_end |
((vga.crtc.overflow & 2)<<7) | ((vga.crtc.overflow & 0x40) << 3) |
((vga.s3.ex_ver_overflow & 0x2) << 9));
hdispend = 1 + (vga.crtc.horizontal_display_end);
hbstart = vga.crtc.start_horizontal_blanking;
vbstart = vga.crtc.start_vertical_blanking | ((vga.crtc.overflow & 0x08) << 5) |
((vga.crtc.maximum_scan_line & 0x20) << 4) ;
hrstart = vga.crtc.start_horizontal_retrace;
vrstart = vga.crtc.vertical_retrace_start + ((vga.crtc.overflow & 0x04) << 6) |
((vga.crtc.overflow & 0x80) << 2);
if (hbstart<hdispend) hdispend=hbstart;
if (vbstart<vdispend) vdispend=vbstart;
clock=(vga.misc_output >> 2) & 3;
clock=1000*S3_CLOCK(vga.s3.clk[clock].m,vga.s3.clk[clock].n,vga.s3.clk[clock].r);
/* Check for 8 for 9 character clock mode */
if (vga.seq.clocking_mode & 1 ) clock/=8; else clock/=9;
/* Check for pixel doubling, master clock/2 */
if (vga.seq.clocking_mode & 0x8) {
htotal*=2;
}
vga.draw.font_height=(vga.crtc.maximum_scan_line&0xf)+1;
/* Check for dual transfer whatever thing,master clock/2 */
if (vga.s3.pll.cmd & 0x10) clock/=2;
} else {
vga.draw.font_height=vga.other.max_scanline+1;
htotal=vga.other.htotal;
hdispend=vga.other.hdend;
hrstart=vga.other.hsyncp;
vtotal=vga.draw.font_height*vga.other.vtotal+vga.other.vadjust;
vdispend=vga.draw.font_height*vga.other.vdend;
vrstart=vga.draw.font_height*vga.other.vsyncp;
switch (machine) {
case MCH_CGA:
case MCH_TANDY:
clock=((vga.tandy.mode_control & 1) ? 14318180 : (14318180/2))/8;
break;
case MCH_HERC:
if (vga.herc.mode_control & 0x2) clock=14318180/16;
else clock=14318180/8;
break;
}
}
/* Check for dual transfer whatever thing,master clock/2 */
if (vga.s3.pll.cmd & 0x10) clock/=2;
LOG(LOG_VGA,LOG_NORMAL)("H total %d, V Total %d",htotal,vtotal);
LOG(LOG_VGA,LOG_NORMAL)("H D End %d, V D End %d",hdispend,vdispend);
if (!htotal) return;
if (!vtotal) return;
fps=clock/(vtotal*htotal);
double linemicro=(1000000/fps);
vga.draw.parts_total=VGA_PARTS;
@ -279,86 +313,103 @@ void VGA_SetupDrawing(Bitu val) {
width=hdispend;
height=vdispend;
vga.draw.double_scan=false;
vga.draw.font_height=(vga.crtc.maximum_scan_line&0xf)+1;
switch (vga.mode) {
case M_VGA:
scalew=2;
scaleh*=vga.draw.font_height;
scalew=2;scaleh*=vga.draw.font_height;
if (vga.crtc.maximum_scan_line&0x80) scaleh*=2;
vga.draw.lines_scaled=scaleh;
height/=scaleh;
width<<=2;
vga.draw.address_line_total=1;
VGA_DrawLine=VGA_VGA_Draw_Line;
height/=scaleh;width<<=2;
VGA_DrawLine=VGA_Draw_VGA_Line;
break;
case M_LIN8:
width<<=3;
scaleh*=vga.draw.font_height;
vga.draw.lines_scaled=scaleh;
vga.draw.address_line_total=1;
VGA_DrawLine=VGA_VGA_Draw_Line;
width<<=3;
VGA_DrawLine=VGA_Draw_VGA_Line;
break;
case M_EGA16:
width<<=3;
scaleh*=vga.draw.font_height;
if (vga.crtc.maximum_scan_line&0x80) scaleh*=2;
vga.draw.lines_scaled=scaleh;
height/=scaleh;
if (vga.seq.clocking_mode & 0x8) scalew*=2;
width<<=3;height/=scaleh;
vga.draw.address_line_total=1;
VGA_DrawLine=VGA_EGA_Draw_Line;
VGA_DrawLine=VGA_Draw_EGA_Line;
break;
case M_CGA4:
case M_CGA16: //Let is use 320x200 res and double pixels myself
scaleh=2;scalew=2;
vga.draw.blocks=width;
width<<=2;
height/=2;
scaleh=2;scalew*=2;
vga.draw.blocks=width*2;
vga.draw.lines_scaled=1;
vga.draw.address_line_total=2;
VGA_DrawLine=(vga.mode == M_CGA4) ? VGA_CGA4_Draw_Line : VGA_CGA16_Draw_Line;
width<<=3;height/=2;
VGA_DrawLine=VGA_Draw_2BPP_Line;
break;
case M_CGA2:
scaleh=2;height/=2;
vga.draw.address_line_total=2;
scaleh=2;
vga.draw.blocks=width;
width<<=3;
vga.draw.lines_scaled=1;
vga.draw.address_line_total=2;
vga.draw.lines_scaled=1;
VGA_DrawLine=VGA_CGA2_Draw_Line;
width<<=4;height/=2;
VGA_DrawLine=VGA_Draw_1BPP_Line;
break;
case M_HERC:
vga.draw.address_line_total=4;
width*=9;
vga.draw.blocks=width/8;
vga.draw.lines_scaled=1;
height=348;
aspect_ratio=1.5;
VGA_DrawLine=VGA_HERC_Draw_Line;
break;
case M_TANDY16:
scaleh=2;scalew=2;
vga.draw.blocks=width*2;
vga.draw.address_line_total=4;
vga.draw.lines_scaled=1;
width<<=2;height/=2;
VGA_DrawLine=VGA_TANDY16_Draw_Line;
break;
case M_TEXT2:
case M_TEXT16:
case M_TEXT:
aspect_ratio=1.0;
if (vga.draw.font_height<4 && (machine<MCH_VGA || machine==MCH_AUTO)) {
vga.draw.font_height=4;
};
vga.draw.address_line_total=vga.draw.font_height;
vga.draw.blocks=width;
if (vga.seq.clocking_mode & 0x8) scalew*=2;
if (vga.crtc.maximum_scan_line&0x80) scaleh*=2;
vga.draw.lines_scaled=scaleh;
height/=scaleh;
vga.draw.lines_scaled=scaleh;
width<<=3; /* 8 bit wide text font */
if (width>640) width=640;
if (height>480) height=480;
VGA_DrawLine=VGA_TEXT_Draw_Line;
break;
case M_HERC_GFX:
aspect_ratio=1.5;
vga.draw.address_line_total=vga.draw.font_height;
vga.draw.blocks=width*2;
vga.draw.lines_scaled=1;
width*=16;
VGA_DrawLine=VGA_Draw_1BPP_Line;
break;
case M_TANDY2:
scaleh=2;aspect_ratio=1.2;
scalew=(vga.tandy.mode_control & 0x10) ? 1 : 2;
vga.draw.blocks=width*8/scalew;
vga.draw.address_line_total=vga.draw.font_height;
vga.draw.lines_scaled=1;
width=vga.draw.blocks*2;
VGA_DrawLine=VGA_Draw_1BPP_Line;
break;
case M_TANDY4:
scaleh=2;aspect_ratio=1.2;
scalew=(vga.tandy.mode_control & 0x10) ? 1 : 2;
vga.draw.blocks=width*8/scalew;
vga.draw.address_line_total=vga.draw.font_height;
vga.draw.lines_scaled=1;
width=vga.draw.blocks*2;
VGA_DrawLine=VGA_Draw_2BPP_Line;
break;
case M_TANDY16:
scaleh=2;aspect_ratio=1.2;
scalew=(vga.tandy.mode_control & 0x10) ? 1 : 2;
vga.draw.blocks=width*4/scalew;
vga.draw.address_line_total=vga.draw.font_height;
vga.draw.lines_scaled=1;
width=vga.draw.blocks*2;
VGA_DrawLine=VGA_Draw_4BPP_Line;
break;
case M_TANDY_TEXT:
scalew=(vga.tandy.mode_control & 0x1) ? 1 : 2;
case M_HERC_TEXT:
aspect_ratio=1;
scaleh=(vga.mode==M_HERC_TEXT) ? 1 : 2;
vga.draw.lines_scaled=1;
vga.draw.address_line_total=vga.draw.font_height;
vga.draw.blocks=width;
vga.draw.lines_scaled=1;
width<<=3;
VGA_DrawLine=VGA_TEXT_Draw_Line;
break;
default:

View file

@ -20,19 +20,18 @@
#include "inout.h"
#include "vga.h"
#define gfx(blah) vga.gfx.blah
static bool index9warned=false;
void write_p3ce(Bit32u port,Bit8u val) {
static void write_p3ce(Bit32u port,Bit8u val) {
gfx(index)=val & 0x0f;
}
Bit8u read_p3ce(Bit32u port) {
static Bit8u read_p3ce(Bit32u port) {
return gfx(index);
}
void write_p3cf(Bit32u port,Bit8u val) {
static void write_p3cf(Bit32u port,Bit8u val) {
switch (gfx(index)) {
case 0: /* Set/Reset Register */
gfx(set_reset)=val & 0x0f;
@ -92,8 +91,11 @@ void write_p3cf(Bit32u port,Bit8u val) {
vga.config.read_map_select=val & 0x03;
// LOG_DEBUG("Read Map %2X",val);
break;
case 5: /* Mode Register */ /* Important one very */
gfx(mode)=val;
case 5: /* Mode Register */
if ((gfx(mode) ^ val) & 0xf0) {
gfx(mode)=val;
VGA_DetermineMode();
} else gfx(mode)=val;
vga.config.write_mode=val & 3;
vga.config.read_mode=(val >> 3) & 1;
// LOG_DEBUG("Write Mode %d Read Mode %d val %d",vga.config.write_mode,vga.config.read_mode,val);
@ -134,7 +136,6 @@ void write_p3cf(Bit32u port,Bit8u val) {
4 Enables Odd/Even mode if set (See 3C4h index 4 bit 2).
5 Enables CGA style 4 color pixels using even/odd bit pairs if set.
6 Enables 256 color mode if set.
*/
break;
case 6: /* Miscellaneous Register */
@ -183,7 +184,7 @@ void write_p3cf(Bit32u port,Bit8u val) {
}
}
Bit8u read_p3cf(Bit32u port) {
static Bit8u read_p3cf(Bit32u port) {
switch (gfx(index)) {
case 0: /* Set/Reset Register */
return gfx(set_reset);
@ -212,10 +213,12 @@ Bit8u read_p3cf(Bit32u port) {
void VGA_SetupGFX(void) {
IO_RegisterWriteHandler(0x3ce,write_p3ce,"VGA Graphics Index");
IO_RegisterWriteHandler(0x3cf,write_p3cf,"VGA Graphics Data");
IO_RegisterReadHandler(0x3ce,read_p3ce,"Vga Graphics Index");
IO_RegisterReadHandler(0x3cf,read_p3cf,"Vga Graphics Data");
if (machine==MCH_VGA) {
IO_RegisterWriteHandler(0x3ce,write_p3ce,"VGA Graphics Index");
IO_RegisterWriteHandler(0x3cf,write_p3cf,"VGA Graphics Data");
IO_RegisterReadHandler(0x3ce,read_p3ce,"Vga Graphics Index");
IO_RegisterReadHandler(0x3cf,read_p3cf,"Vga Graphics Data");
}
}

View file

@ -247,11 +247,17 @@ public:
class VGA_TANDY_PageHandler : public PageHandler {
public:
VGA_TANDY_PageHandler() {
flags=PFLAG_READABLE|PFLAG_WRITEABLE|PFLAG_NOCODE;
flags=PFLAG_READABLE|PFLAG_WRITEABLE;
// |PFLAG_NOCODE;
}
HostPt GetHostPt(Bitu phys_page) {
phys_page-=vgapages.map_base;
return &vga.mem.linear[(vga.tandy.mem_bank << 14)+(phys_page * 4096)];
if (phys_page>=0xb8) {
phys_page-=0xb8;
return &vga.mem.linear[(vga.tandy.mem_bank << 14)+(phys_page * 4096)];
} else {
phys_page-=0x80;
return &vga.mem.linear[phys_page * 4096];
}
}
};
@ -268,7 +274,22 @@ static struct {
void VGA_SetupHandlers(void) {
PageHandler * range_handler;
switch (machine) {
case MCH_CGA:
range_handler=&vgaph.hmap;
goto range_b800;
case MCH_HERC:
range_handler=&vgaph.hmap;
if (vga.herc.mode_control&0x80) goto range_b800;
else goto range_b000;
case MCH_TANDY:
range_handler=&vgaph.htandy;
MEM_SetPageHandler(0x80,32,range_handler);
goto range_b800;
}
switch (vga.mode) {
case M_ERROR:
return;
case M_LIN8:
range_handler=&vgaph.hmap;
break;
@ -282,29 +303,15 @@ void VGA_SetupHandlers(void) {
case M_EGA16:
range_handler=&vgaph.h16;
break;
case M_TEXT2:
case M_TEXT16:
case M_TEXT:
/* Check if we're not in odd/even mode */
if (vga.gfx.miscellaneous & 0x2) {
range_handler=&vgaph.hmap;
} else {
range_handler=&vgaph.htext;
}
if (vga.gfx.miscellaneous & 0x2) range_handler=&vgaph.hmap;
else range_handler=&vgaph.htext;
break;
case M_TANDY16:
range_handler=&vgaph.htandy;
break;
case M_CGA16:
case M_CGA4:
case M_CGA2:
range_handler=&vgaph.hmap;
break;
case M_HERC:
range_handler=&vgaph.hmap;
if (vga.herc.mode_control&0x80) goto range_b800;
else goto range_b000;
default:
LOG_MSG("Unhandled vga mode %X",vga.mode);
}
switch ((vga.gfx.miscellaneous >> 2) & 3) {
case 0:

View file

@ -20,26 +20,25 @@
#include "inout.h"
#include "pic.h"
#include "vga.h"
#include "../ints/int10.h"
static Bit8u flip=0;
void write_p3d4(Bit32u port,Bit8u val);
Bit8u read_p3d4(Bit32u port);
void write_p3d5(Bit32u port,Bit8u val);
Bit8u read_p3d5(Bit32u port);
void write_p3d4_vga(Bit32u port,Bit8u val);
Bit8u read_p3d4_vga(Bit32u port);
void write_p3d5_vga(Bit32u port,Bit8u val);
Bit8u read_p3d5_vga(Bit32u port);
static void write_p3d9(Bit32u port,Bit8u val);
void write_p3d4_cga(Bit32u port,Bit8u val);
Bit8u read_p3d4_cga(Bit32u port);
void write_p3d5_cga(Bit32u port,Bit8u val);
Bit8u read_p3d5_cga(Bit32u port);
static Bit8u read_p3da(Bit32u port) {
vga.internal.attrindex=false;
if (vga.config.retrace) {
switch (vga.mode) {
case M_HERC:
switch (machine) {
case MCH_HERC:
return 0x81;
case M_TEXT2:
if (machine==MCH_HERC) return 0x81;
if (machine==MCH_AUTO) return 0x89;
default:
return 9;
}
@ -54,182 +53,14 @@ static Bit8u read_p3da(Bit32u port) {
*/
}
static void write_p3d8(Bit32u port,Bit8u val) {
/* Check if someone changes the blinking/hi intensity bit */
switch (machine) {
case MCH_AUTO:
VGA_SetBlinking((val & 0x20));
switch (vga.mode) {
case M_CGA2:
case M_CGA4:
case M_CGA16:
goto m_cga;
}
break;
case MCH_CGA:
VGA_SetBlinking((val & 0x20));
m_cga:
if (val & 0x2) {
if (val & 0x10) {
if (val & 0x8) {
VGA_SetMode(M_CGA16); //Video burst 16 160x200 color mode
} else {
VGA_SetMode(M_CGA2);
}
} else VGA_SetMode(M_CGA4);
write_p3d9(0x3d9,vga.cga.color_select); //Setup the correct palette
} else {
VGA_SetMode(M_TEXT16);
}
vga.cga.mode_control=val;
break;
default:
LOG(LOG_VGAMISC,LOG_NORMAL)("Write %2X to 3d8 in mode %d",val,vga.mode);
}
/*
3 Vertical Sync Select. If set Vertical Sync to the monitor is the
logical OR of the vertical sync and the vertical display enable.
*/
}
static void write_p3d9(Bit32u port,Bit8u val) {
Bitu i;
vga.cga.color_select=val;
switch (vga.mode) {
case M_CGA2:
/* changes attribute 1 */
VGA_ATTR_SetPalette(0,0);
VGA_ATTR_SetPalette(1,val & 0xf);
break;
case M_CGA4:
/* changes attribute 0 */
{
VGA_ATTR_SetPalette(0,(val & 0xf));
Bit8u pal_base=(val & 0x10) ? 0x08 : 0;
/* Check for BW Mode */
if (vga.cga.mode_control & 0x4) {
if (val & 0x20) {
VGA_ATTR_SetPalette(1,0x03+pal_base);
VGA_ATTR_SetPalette(2,0x04+pal_base);
VGA_ATTR_SetPalette(3,0x07+pal_base);
} else {
//TODO Maybe? will anyone ever use,
//will also need to setup a BW palette,but could put it behind normal cga...
VGA_ATTR_SetPalette(1,0x02+pal_base);
VGA_ATTR_SetPalette(2,0x04+pal_base);
VGA_ATTR_SetPalette(3,0x06+pal_base);
}
} else {
if (val & 0x20) {
VGA_ATTR_SetPalette(1,0x03+pal_base);
VGA_ATTR_SetPalette(2,0x05+pal_base);
VGA_ATTR_SetPalette(3,0x07+pal_base);
} else {
VGA_ATTR_SetPalette(1,0x02+pal_base);
VGA_ATTR_SetPalette(2,0x04+pal_base);
VGA_ATTR_SetPalette(3,0x06+pal_base);
}
}
}
break;
case M_CGA16:
for(i=0;i<0x10;i++) VGA_ATTR_SetPalette(i,i);
break;
case M_TEXT16:
/* Assume a normal text palette has been set */
// VGA_ATTR_SetPalette(0,(val & 0x8) ? ((val & 7)+32) : (val &7));
break;
default:
LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to %X in mode %d",val,port,vga.mode);
}
}
static void write_p3da(Bit32u port,Bit8u val) {
if (machine==MCH_TANDY) goto tandy_3da;
switch (vga.mode) {
case M_TANDY16:
tandy_3da:
vga.tandy.reg_index=val;
break;
default:
LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to %X in mode %d",val,port,vga.mode);
break;
}
}
static void write_p3de(Bit32u port,Bit8u val) {
if (machine==MCH_TANDY) goto tandy_3de;
switch (vga.mode) {
case M_TANDY16:
tandy_3de:
switch (vga.tandy.reg_index) {
case 0x2: /* Border color */
vga.tandy.border_color=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);
}
break;
default:
LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to %X in mode %d",val,port,vga.mode);
break;
}
}
static void write_p3df(Bit32u port,Bit8u val) {
if (machine==MCH_TANDY) goto tandy_3df;
switch (vga.mode) {
case M_TANDY16:
tandy_3df:
vga.tandy.disp_bank=val & ((val & 0x80) ? 0x6 : 0x7);
vga.tandy.mem_bank=(val >> 3) & ((val & 0x80) ? 0x6 : 0x7);
VGA_SetupHandlers();
break;
/*
0-2 Identifies the page of main memory being displayed in units of 16K.
0: 0K, 1: 16K...7: 112K. In 32K modes (bits 6-7 = 2) only 0,2,4 and
6 are valid, as the next page will also be used.
3-5 Identifies the page of main memory that can be read/written at B8000h
in units of 16K. 0: 0K, 1: 16K...7: 112K. In 32K modes (bits 6-7 = 2)
only 0,2,4 and 6 are valid, as the next page will also be used.
6-7 Display mode. 0: Text, 1: 16K graphics mode (4,5,6,8)
2: 32K graphics mode (9,Ah)
*/
default:
LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to %X in mode %d",val,port,vga.mode);
break;
}
}
static Bit8u read_p3d9(Bit32u port) {
switch (machine) {
case MCH_AUTO:
case MCH_CGA:
case MCH_TANDY:
return vga.cga.color_select;
default:
return 0xff;
};
}
static void write_p3c2(Bit32u port,Bit8u val) {
vga.misc_output=val;
if (val & 0x1) {
IO_RegisterWriteHandler(0x3d4,write_p3d4,"VGA:CRTC Index Select");
IO_RegisterReadHandler(0x3d4,read_p3d4,"VGA:CRTC Index Select");
IO_RegisterWriteHandler(0x3d5,write_p3d5,"VGA:CRTC Data Register");
IO_RegisterReadHandler(0x3d5,read_p3d5,"VGA:CRTC Data Register");
IO_RegisterWriteHandler(0x3d4,write_p3d4_vga,"VGA:CRTC Index Select");
IO_RegisterReadHandler(0x3d4,read_p3d4_vga,"VGA:CRTC Index Select");
IO_RegisterWriteHandler(0x3d5,write_p3d5_vga,"VGA:CRTC Data Register");
IO_RegisterReadHandler(0x3d5,read_p3d5_vga,"VGA:CRTC Data Register");
IO_RegisterReadHandler(0x3da,read_p3da,"VGA Input Status 1");
IO_FreeWriteHandler(0x3b4);
@ -238,10 +69,10 @@ static void write_p3c2(Bit32u port,Bit8u val) {
IO_FreeReadHandler(0x3b5);
IO_FreeReadHandler(0x3ba);
} else {
IO_RegisterWriteHandler(0x3b4,write_p3d4,"VGA:CRTC Index Select");
IO_RegisterReadHandler(0x3b4,read_p3d4,"VGA:CRTC Index Select");
IO_RegisterWriteHandler(0x3b5,write_p3d5,"VGA:CRTC Data Register");
IO_RegisterReadHandler(0x3b5,read_p3d5,"VGA:CRTC Data Register");
IO_RegisterWriteHandler(0x3b4,write_p3d4_vga,"VGA:CRTC Index Select");
IO_RegisterReadHandler(0x3b4,read_p3d4_vga,"VGA:CRTC Index Select");
IO_RegisterWriteHandler(0x3b5,write_p3d5_vga,"VGA:CRTC Data Register");
IO_RegisterReadHandler(0x3b5,read_p3d5_vga,"VGA:CRTC Data Register");
IO_RegisterReadHandler(0x3ba,read_p3da,"VGA Input Status 1");
IO_FreeWriteHandler(0x3d4);
@ -269,67 +100,16 @@ static Bit8u read_p3cc(Bit32u port) {
}
static void write_hercules(Bit32u port,Bit8u val) {
switch (port) {
case 0x3b8:
vga.herc.mode_control=(vga.herc.mode_control & ~0x7d) | (val&0x7d);
if ((vga.herc.enable_bits & 1) && ((vga.herc.mode_control ^ val)&0x2)) {
vga.herc.mode_control^=0x2;
if (vga.mode != M_HERC || vga.mode != M_TEXT2) {
VGA_ATTR_SetPalette(0,0x00);
VGA_ATTR_SetPalette(1,0x07);
/* Force 0x3b4/5 registers */
if (vga.misc_output & 1) write_p3c2(0,vga.misc_output & ~1);
}
if (val & 0x2) {
if (vga.mode != M_HERC) VGA_SetMode(M_HERC);
} else {
if (vga.mode != M_TEXT2) VGA_SetMode(M_TEXT2);
}
}
if ((vga.herc.enable_bits & 0x2) && ((vga.herc.mode_control ^ val)&0x80)) {
vga.herc.mode_control^=0x80;
VGA_SetupHandlers();
}
break;
case 0x3bf:
vga.herc.enable_bits=val;
break;
default:
LOG_MSG("write %x to Herc port %x",val,port);
}
}
static Bit8u read_hercules(Bit32u port) {
switch (port) {
case 0x3b8:
default:
LOG_MSG("read from Herc port %x",port);
}
return 0;
}
void VGA_SetupMisc(void) {
vga.herc.enable_bits=0;
IO_RegisterWriteHandler(0x3d8,write_p3d8,"VGA Feature Control Register");
IO_RegisterWriteHandler(0x3d9,write_p3d9,"CGA Color Select Register");
IO_RegisterReadHandler(0x3d9,read_p3d9,"CGA Color Select Register");
IO_RegisterWriteHandler(0x3c2,write_p3c2,"VGA Misc Output");
IO_RegisterReadHandler(0x3cc,read_p3cc,"VGA Misc Output");
if (machine==MCH_HERC || machine==MCH_AUTO) {
vga.herc.mode_control=0x8;
IO_RegisterWriteHandler(0x3b8,write_hercules,"Hercules");
IO_RegisterWriteHandler(0x3bf,write_hercules,"Hercules");
if (machine==MCH_VGA) {
IO_RegisterWriteHandler(0x3c2,write_p3c2,"VGA Misc Output");
IO_RegisterReadHandler(0x3cc,read_p3cc,"VGA Misc Output");
} else if (machine==MCH_CGA || machine==MCH_TANDY) {
IO_RegisterReadHandler(0x3da,read_p3da,"VGA Input Status 1");
} else if (machine==MCH_HERC) {
IO_RegisterReadHandler(0x3ba,read_p3da,"VGA Input Status 1");
}
IO_RegisterWriteHandler(0x3de,write_p3de,"PCJR Reg Write");
IO_RegisterWriteHandler(0x3df,write_p3df,"PCJR Bank Select");
IO_RegisterWriteHandler(0x3da,write_p3da,"PCJR Reg Select");
}

308
src/hardware/vga_other.cpp Normal file
View file

@ -0,0 +1,308 @@
/*
* Copyright (C) 2002-2004 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include "dosbox.h"
#include "inout.h"
#include "vga.h"
static void write_crtc_index_other(Bit32u port,Bit8u val) {
vga.other.index=val;
}
static Bit8u read_crtc_index_other(Bit32u port) {
return vga.other.index;
}
static void write_crtc_data_other(Bit32u port,Bit8u val) {
switch (vga.other.index) {
case 0x00: //Horizontal total
if (vga.other.htotal ^ val) VGA_StartResize();
vga.other.htotal=val;
break;
case 0x01: //Horizontal displayed chars
if (vga.other.hdend ^ val) VGA_StartResize();
vga.other.hdend=val;
break;
case 0x02: //Horizontal sync position
vga.other.hsyncp=val;
break;
case 0x03: //Horizontal sync width
vga.other.hsyncw=val;
break;
case 0x04: //Vertical total
if (vga.other.vtotal ^ val) VGA_StartResize();
vga.other.vtotal=val;
break;
case 0x05: //Vertical display adjust
if (vga.other.vadjust ^ val) VGA_StartResize();
vga.other.vadjust=val;
break;
case 0x06: //Vertical rows
if (vga.other.vdend ^ val) VGA_StartResize();
vga.other.vdend=val;
break;
case 0x07: //Vertical sync position
vga.other.vsyncp=val;
break;
case 0x09: //Max scanline
if (vga.other.max_scanline ^ val) VGA_StartResize();
vga.other.max_scanline=val;
break;
vga.config.display_start=(vga.config.display_start & 0xFF00FF)| (val << 8);
break;
case 0x0C: /* Start Address High Register */
vga.config.display_start=(vga.config.display_start & 0xFF00FF)| (val << 8);
break;
case 0x0D: /* Start Address Low Register */
vga.config.display_start=(vga.config.display_start & 0xFFFF00)| val;
break;
case 0x0E: /*Cursor Location High Register */
vga.config.cursor_start&=0xff00ff;
vga.config.cursor_start|=val << 8;
break;
case 0x0F: /* Cursor Location Low Register */
vga.config.cursor_start&=0xffff00;
vga.config.cursor_start|=val;
break;
default:
LOG_MSG("Write %X to illgal index %x",val,vga.other.index);
}
}
static Bit8u read_crtc_data_other(Bit32u port) {
switch (vga.other.index) {
case 0x00: //Horizontal total
return vga.other.htotal;
case 0x01: //Horizontal displayed chars
return vga.other.hdend;
case 0x02: //Horizontal sync position
return vga.other.hsyncp;
case 0x03: //Horizontal sync width
return vga.other.hsyncw;
case 0x04: //Vertical total
return vga.other.vtotal;
case 0x05: //Vertical display adjust
return vga.other.vadjust;
case 0x06: //Vertical rows
return vga.other.vdend;
case 0x07: //Vertical sync position
return vga.other.vsyncp;
case 0x09: //Max scanline
return vga.other.max_scanline;
case 0x0C: /* Start Address High Register */
return vga.config.display_start >> 8;
case 0x0D: /* Start Address Low Register */
return vga.config.display_start;
case 0x0E: /*Cursor Location High Register */
return vga.config.cursor_start>>8;
case 0x0F: /* Cursor Location Low Register */
return vga.config.cursor_start;
default:
LOG_MSG("Read from illgal index %x",vga.other.index);
}
}
static void write_color_select(Bit8u val) {
vga.tandy.color_select=val;
switch (vga.mode) {
case M_TANDY2:
VGA_SetCGA2Table(0,val & 0xf);
break;
case M_TANDY4:
{
if (machine == MCH_TANDY && (vga.tandy.gfx_control & 0x8)) {
VGA_SetCGA4Table(0,1,2,3);
return;
}
Bit8u base=(val & 0x10) ? 0x08 : 0;
/* Check for BW Mode */
if (vga.tandy.mode_control & 0x4) {
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);
}
}
break;
case M_CGA16:
case M_TEXT:
case M_TANDY16:
break;
}
}
static void write_mode_control(Bit8u val) {
/* Check if someone changes the blinking/hi intensity bit */
vga.tandy.mode_control=val;
VGA_SetBlinking((val & 0x20));
if (val & 0x2) {
if (val & 0x10) {
if (val & 0x8) {
VGA_SetMode(M_CGA16); //Video burst 16 160x200 color mode
} else {
VGA_SetMode(M_CGA2);
}
} else VGA_SetMode(M_CGA4);
write_color_select(vga.tandy.color_select); //Setup the correct palette
} else {
VGA_SetMode(M_TEXT);
}
}
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);
} else {
VGA_SetMode(M_TANDY_TEXT);
}
}
static void write_tandy_reg(Bit8u val) {
switch (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();
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(Bit32u port,Bit8u val) {
switch (port) {
case 0x3d8:
vga.tandy.mode_control=val;
if (vga.tandy.mode_control & 0x2) {
if (vga.tandy.mode_control & 0x10) {
VGA_SetMode(M_TANDY2);
} else VGA_SetMode(M_TANDY4);
write_color_select(vga.tandy.color_select);
} else {
VGA_SetMode(M_TANDY_TEXT);
}
break;
case 0x3d9:
write_color_select(val);
break;
}
}
static void write_tandy(Bit32u port,Bit8u val) {
switch (port) {
case 0x3d8:
vga.tandy.mode_control=val;
TANDY_FindMode();
break;
case 0x3d9:
write_color_select(val);
break;
case 0x3da:
vga.tandy.reg_index=val;
break;
case 0x3de:
write_tandy_reg(val);
break;
case 0x3df:
vga.tandy.disp_bank=val & ((val & 0x80) ? 0x6 : 0x7);
vga.tandy.mem_bank=(val >> 3) & ((val & 0x80) ? 0x6 : 0x7);
VGA_SetupHandlers();
break;
}
}
static void write_hercules(Bit32u port,Bit8u val) {
switch (port) {
case 0x3b8:
if (vga.herc.enable_bits & 1) {
vga.herc.mode_control&=~0x2;
vga.herc.mode_control|=(val&0x2);
if (val & 0x2) {
VGA_SetMode(M_HERC_GFX);
} else {
VGA_SetMode(M_HERC_TEXT);
}
}
if ((vga.herc.enable_bits & 0x2) && ((vga.herc.mode_control ^ val)&0x80)) {
vga.herc.mode_control^=0x80;
VGA_SetupHandlers();
}
break;
case 0x3bf:
vga.herc.enable_bits=val;
break;
}
}
static Bit8u read_hercules(Bit32u port) {
LOG_MSG("read from Herc port %x",port);
return 0;
}
void VGA_SetupOther(void) {
Bitu i;
if (machine==MCH_CGA || machine==MCH_TANDY) {
extern Bit8u int10_font_08[256 * 8];
for (i=0;i<256;i++) memcpy(&vga.draw.font[i*32],&int10_font_08[i*8],8);
}
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);
}
if (machine==MCH_CGA) {
IO_RegisterWriteBHandler(0x3d8,write_cga);
IO_RegisterWriteBHandler(0x3d9,write_cga);
}
if (machine==MCH_HERC) {
vga.herc.enable_bits=0;
vga.herc.mode_control=0x8;
IO_RegisterWriteBHandler(0x3b8,write_hercules);
IO_RegisterWriteBHandler(0x3bf,write_hercules);
}
if (machine==MCH_TANDY) {
IO_RegisterWriteBHandler(0x3d8,write_tandy);
IO_RegisterWriteBHandler(0x3d9,write_tandy);
IO_RegisterWriteBHandler(0x3de,write_tandy);
IO_RegisterWriteBHandler(0x3df,write_tandy);
IO_RegisterWriteBHandler(0x3da,write_tandy);
}
if (machine==MCH_CGA || machine==MCH_HERC || machine==MCH_TANDY) {
Bitu base=machine==MCH_HERC ? 0x3b4 : 0x3d4;
IO_RegisterWriteBHandler(base,write_crtc_index_other);
IO_RegisterWriteBHandler(base+1,write_crtc_data_other);
IO_RegisterReadBHandler(base,read_crtc_index_other);
IO_RegisterReadBHandler(base+1,read_crtc_data_other);
}
}

View file

@ -167,10 +167,11 @@ Bit8u read_p3c5(Bit32u port) {
void VGA_SetupSEQ(void) {
IO_RegisterWriteHandler(0x3c4,write_p3c4,"VGA:Sequencer Index");
IO_RegisterWriteHandler(0x3c5,write_p3c5,"VGA:Sequencer Data");
IO_RegisterReadHandler(0x3c4,read_p3c4,"VGA:Sequencer Index");
IO_RegisterReadHandler(0x3c5,read_p3c5,"VGA:Sequencer Data");
if (machine==MCH_VGA) {
IO_RegisterWriteHandler(0x3c4,write_p3c4,"VGA:Sequencer Index");
IO_RegisterWriteHandler(0x3c5,write_p3c5,"VGA:Sequencer Data");
IO_RegisterReadHandler(0x3c4,read_p3c4,"VGA:Sequencer Index");
IO_RegisterReadHandler(0x3c5,read_p3c5,"VGA:Sequencer Data");
}
}

View file

@ -445,7 +445,7 @@ static void SetupTandyBios(void) {
void INT10_Init(Section* sec) {
INT10_InitVGA();
if (machine==MCH_TANDY || machine==MCH_AUTO) SetupTandyBios();
if (machine==MCH_TANDY) SetupTandyBios();
/* Setup the INT 10 vector */
call_10=CALLBACK_Allocate();
CALLBACK_Setup(call_10,&INT10_Handler,CB_IRET);

View file

@ -104,11 +104,10 @@ struct VideoModeBlock {
Bitu htotal,vtotal;
Bitu hdispend,vdispend;
Bitu rate;
Bitu special;
};
extern VideoModeBlock ModeList[];
extern VideoModeBlock ModeList_VGA[];
extern VideoModeBlock * CurMode;
typedef struct {

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: int10_char.cpp,v 1.22 2004-01-28 18:04:18 harekiet Exp $ */
/* $Id: int10_char.cpp,v 1.23 2004-02-29 22:18:24 harekiet Exp $ */
/* Character displaying moving functions */
@ -174,7 +174,7 @@ static INLINE void TEXT_FillRow(Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,B
void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page) {
/* Do some range checking */
if (CurMode->type>M_TEXT16) page=0xff;
if (CurMode->type!=M_TEXT) page=0xff;
BIOS_NCOLS;BIOS_NROWS;
if(rul>rlr) return;
if(cul>clr) return;
@ -204,8 +204,7 @@ void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit
while (start!=end) {
start+=next;
switch (CurMode->type) {
case M_TEXT2:
case M_TEXT16:
case M_TEXT:
TEXT_CopyRow(cul,clr,start,start+nlines,base);break;
case M_CGA2:
CGA2_CopyRow(cul,clr,start,start+nlines,base);break;
@ -229,8 +228,7 @@ filling:
}
for (;nlines>0;nlines--) {
switch (CurMode->type) {
case M_TEXT2:
case M_TEXT16:
case M_TEXT:
TEXT_FillRow(cul,clr,start,base,attr);break;
case M_CGA2:
CGA2_FillRow(cul,clr,start,base,attr);break;
@ -363,8 +361,7 @@ static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool
Bitu x,y;
Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
switch (CurMode->type) {
case M_TEXT2:
case M_TEXT16:
case M_TEXT:
{
// Compute the address
Bit16u address=page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE);
@ -410,7 +407,7 @@ static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool
void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr) {
//TODO Check if this page thing is correct
if (CurMode->type>M_TEXT16) page=0xff;
if (CurMode->type!=M_TEXT) page=0xff;
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
Bit8u cur_row=CURSOR_POS_ROW(page);
Bit8u cur_col=CURSOR_POS_COL(page);
@ -474,12 +471,12 @@ void INT10_TeletypeOutputAttr(Bit8u chr,Bit8u attr,bool useattr) {
void INT10_TeletypeOutput(Bit8u chr,Bit8u attr) {
INT10_TeletypeOutputAttr(chr,attr,CurMode->type>M_TEXT16);
INT10_TeletypeOutputAttr(chr,attr,CurMode->type!=M_TEXT);
}
void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,Bit16u count,Bit8u page) {
//TODO Check if this page thing is correct
if (CurMode->type>M_TEXT16) page=0xff;
if (CurMode->type!=M_TEXT) page=0xff;
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
BIOS_NCOLS;BIOS_NROWS;

View file

@ -80,8 +80,10 @@ void INT10_SetupRomMemory(void) {
PhysPt rom_base=PhysMake(0xc000,0);
Bitu i;
int10.rom.used=3; // int10.rom.used=2; Size of ROM added
phys_writew(rom_base+0,0xaa55);
phys_writeb(rom_base+2,0x40); // Size of ROM: 64 512-blocks = 32KB
if (machine==MCH_VGA) {
phys_writew(rom_base+0,0xaa55);
phys_writeb(rom_base+2,0x40); // Size of ROM: 64 512-blocks = 32KB
}
int10.rom.font_8_first=RealMake(0xC000,int10.rom.used);
for (i=0;i<128*8;i++) {
phys_writeb(rom_base+int10.rom.used++,int10_font_08[i]);

View file

@ -91,10 +91,8 @@ void INT10_GetFuncStateInformation(PhysPt save) {
mem_writeb(save+0x25,real_readb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
Bit16u col_count=0;
switch (CurMode->type) {
case M_TEXT16:
case M_TEXT:
col_count=16;break;
case M_TEXT2:
col_count=2;break; // ??
case M_CGA2:
col_count=2;break;
case M_CGA4:

View file

@ -5,6 +5,7 @@
#include "inout.h"
#include "int10.h"
#include "mouse.h"
#include "vga.h"
#define _EGA_HALF_CLOCK 0x0001
#define _EGA_LINE_DOUBLE 0x0002
@ -13,41 +14,55 @@
#define GFX_REGS 0x09
#define ATT_REGS 0x15
VideoModeBlock ModeList[]={
/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde ,rate,special flags */
{ 0x000 ,M_TEXT16 ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,70 ,_EGA_HALF_CLOCK },
{ 0x001 ,M_TEXT16 ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,70 ,_EGA_HALF_CLOCK },
{ 0x002 ,M_TEXT16 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,70 ,0 },
{ 0x003 ,M_TEXT16 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,70 ,0 },
{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,60 ,0 },
{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,60 ,0},
{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,60 ,0 },
{ 0x007 ,M_TEXT2 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,70 ,0 },
/* 8,9,0xa are tandy modes */
{ 0x009 ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,100 ,449 ,80 ,400 ,60 ,0},
{ 0x00D ,M_EGA16 ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,70 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE },
{ 0x00E ,M_EGA16 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,70 ,_EGA_LINE_DOUBLE },
{ 0x00F ,M_EGA16 ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,400 ,70 ,0 },/*was EGA_2*/
{ 0x010 ,M_EGA16 ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,70 ,0 },
{ 0x011 ,M_EGA16 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,449 ,80 ,480 ,70 ,0 },/*was EGA_2 */
{ 0x012 ,M_EGA16 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,70 ,0 },
{ 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x0000 ,100 ,449 ,80 ,400 ,70 ,0 },
VideoModeBlock ModeList_VGA[]={
/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */
{ 0x000 ,M_TEXT ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
{ 0x001 ,M_TEXT ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
{ 0x002 ,M_TEXT ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
{ 0x003 ,M_TEXT ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
{ 0x007 ,M_TEXT ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
{ 0x100 ,M_LIN8 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,70 ,0 },
{ 0x101 ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,70 ,0 },
{ 0x103 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,70 ,0 },
{ 0x00D ,M_EGA16 ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE },
{ 0x00E ,M_EGA16 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE },
{ 0x00F ,M_EGA16 ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,400 ,0 },/*was EGA_2*/
{ 0x010 ,M_EGA16 ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },
{ 0x011 ,M_EGA16 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,449 ,80 ,480 ,0 },/*was EGA_2 */
{ 0x012 ,M_EGA16 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },
{ 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x0000 ,100 ,449 ,80 ,400 ,0 },
{ 0x100 ,M_LIN8 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0 },
{ 0x101 ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 },
{ 0x103 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,0 },
{ 0x150 ,M_LIN8 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,70 , 0},
{ 0x151 ,M_LIN8 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,70 , 0},
{ 0x152 ,M_LIN8 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,70 , 0 },
{ 0x153 ,M_LIN8 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,70 , 0 },
{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 ,0 },
{ 0x150 ,M_LIN8 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , 0},
{ 0x151 ,M_LIN8 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , 0},
{ 0x152 ,M_LIN8 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , 0 },
{ 0x153 ,M_LIN8 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , 0 },
{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 },
};
VideoModeBlock ModeList_OTHER[]={
/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde ,special flags */
{ 0x000 ,M_TEXT ,320 ,400 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x0800 ,56 ,31 ,40 ,25 ,0 },
{ 0x001 ,M_TEXT ,320 ,400 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x0800 ,56 ,31 ,40 ,25 ,0 },
{ 0x002 ,M_TEXT ,640 ,400 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x1000 ,113 ,31 ,80 ,25 ,0 },
{ 0x003 ,M_TEXT ,640 ,400 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x1000 ,113 ,31 ,80 ,25 ,0 },
{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,56 ,127 ,40 ,100 ,0 },
{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,56 ,127 ,40 ,100 ,0 },
{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,56 ,127 ,40 ,100 ,0 },
{ 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 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,113 ,63 ,80 ,50 ,0 },
{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 },
};
VideoModeBlock Hercules_Mode=
{ 0x007 ,M_TEXT ,640 ,400 ,80 ,25 ,8 ,14 ,4 ,0xB0000 ,0x1000 ,97 ,25 ,80 ,25 ,0 };
static Bit8u text_palette[64][3]=
{
{0x00,0x00,0x00},{0x00,0x00,0x2a},{0x00,0x2a,0x00},{0x00,0x2a,0x2a},{0x2a,0x00,0x00},{0x2a,0x00,0x2a},{0x2a,0x2a,0x00},{0x2a,0x2a,0x2a},
@ -72,18 +87,10 @@ static Bit8u ega_palette[64][3]=
{0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}
};
#if 0
static Bit8u cga_palette[64][3]= {
{0x00,0x00,0x00}, {0x00,0x00,0x1f}, {0x00,0x1f,0x00}, {0x00,0x1f,0x1f}, {0x1f,0x00,0x00}, {0x1f,0x00,0x1f}, {0x1f,0x1f,0x00}, {0x1f,0x1f,0x1f},
{0x0f,0x0f,0x0f}, {0x00,0x00,0x3f}, {0x00,0x3f,0x00}, {0x00,0x3f,0x3f}, {0x3f,0x00,0x00}, {0x3f,0x00,0x3f}, {0x3f,0x3f,0x00}, {0x3f,0x3f,0x3f},
};
#else
static Bit8u cga_palette[16][3]= {
{0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
{0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
};
#endif
static Bit8u vga_palette[256][3]=
{
@ -126,31 +133,205 @@ static Bit8u vga_palette[256][3]=
VideoModeBlock * CurMode;
bool INT10_SetVideoMode(Bitu mode) {
bool clearmem=true;
Bit8u modeset_ctl,video_ctl,vga_switches;
if (mode<256) {
if (mode & 128) {
clearmem=false;
mode-=128;
}
} else {
/* Check for special vesa mode bits */
mode&=0xfff;
}
LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode);
static bool SetCurMode(VideoModeBlock modeblock[],Bitu mode) {
Bitu i=0;
while (ModeList[i].mode!=0xffff) {
if (ModeList[i].mode==mode) goto foundmode;
while ( modeblock[i].mode!=0xffff) {
if ( modeblock[i].mode==mode) goto foundmode;
i++;
}
LOG(LOG_INT10,LOG_ERROR)("Trying to set illegal mode %X",mode);
return false;
foundmode:
CurMode=&ModeList[i];
CurMode=&modeblock[i];
return true;
}
static void FinishSetMode(bool clearmem) {
Bitu i;
/* Clear video memory if needs be */
if (clearmem) {
switch (CurMode->type) {
case M_CGA4:
case M_CGA2:
for (i=0;i<16*1024;i++) {
real_writew(0xb800,i*2,0x0000);
}
break;
case M_TEXT:
if (CurMode->mode==7) for (i=0;i<16*1024;i++) {
real_writew(0xb000,i*2,0x0120);
} else for (i=0;i<16*1024;i++) {
real_writew(0xb800,i*2,0x0720);
}
break;
case M_EGA16:
case M_VGA:
case M_LIN8:
/* Just clear the whole 2 mb of memory */
for (i=0;i<2*1024*1024/4;i++) {
mem_writed(S3_LFB_BASE+i*4,0);
}
}
}
/* Setup the BIOS */
if (CurMode->mode<128) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,CurMode->mode);
else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,CurMode->mode-0x98); //Looks like the s3 bios
real_writew(BIOSMEM_SEG,BIOSMEM_NB_COLS,CurMode->twidth);
real_writew(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,CurMode->plength);
real_writew(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,CurMode->mode==7 ? 0x3b4 : 0x3d4);
real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,CurMode->theight-1);
real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,CurMode->cheight);
real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem << 7)));
real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0x09);
real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
// FIXME We nearly have the good tables. to be reworked
real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
real_writew(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
real_writew(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
// Set cursor shape
if(CurMode->type==M_TEXT) {
INT10_SetCursorShape(0x06,07);
}
// Set cursor pos for page 0..7
for(i=0;i<8;i++) INT10_SetCursorPos(0,0,(Bit8u)i);
// Set active page 0
INT10_SetActivePage(0);
/* Set some interrupt vectors */
switch (CurMode->cheight) {
case 8:RealSetVec(0x43,int10.rom.font_8_first);break;
case 14:RealSetVec(0x43,int10.rom.font_14);break;
case 16:RealSetVec(0x43,int10.rom.font_16);break;
}
/* Tell mouse resolution change */
Mouse_NewVideoMode();
}
bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) {
Bitu i;
switch (machine) {
case MCH_CGA:
if (mode>6) return false;
case MCH_TANDY:
if (mode>0xa) return false;
if (!SetCurMode(ModeList_OTHER,mode)) {
LOG(LOG_INT10,LOG_ERROR)("Trying to set illegal mode %X",mode);
return false;
}
break;
case MCH_HERC:
if (mode!=7) return false;
CurMode=&Hercules_Mode;
break;
}
LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode);
/* Setup the VGA to the correct mode */
// VGA_SetMode(CurMode->type);
/* Setup the CRTC */
Bitu crtc_base=machine==MCH_HERC ? 0x3b4 : 0x3d4;
//Horizontal total
IO_WriteW(crtc_base,0x00 | (CurMode->htotal) << 8);
//Horizontal displayed
IO_WriteW(crtc_base,0x01 | (CurMode->hdispend) << 8);
//Horizontal sync position
IO_WriteW(crtc_base,0x02 | (CurMode->hdispend+1) << 8);
//Horizontal sync width, seems to be fixed to 0xa, for cga at least, hercules has 0xf
IO_WriteW(crtc_base,0x03 | (0xa) << 8);
////Vertical total
IO_WriteW(crtc_base,0x04 | (CurMode->vtotal) << 8);
//Vertical total adjust, 6 for cga,hercules,tandy
IO_WriteW(crtc_base,0x05 | (6) << 8);
//Vertical displayed
IO_WriteW(crtc_base,0x06 | (CurMode->vdispend) << 8);
//Vertical sync position
IO_WriteW(crtc_base,0x07 | (CurMode->vdispend+1) << 8);
//Maximum scanline
Bit8u scanline;
switch(CurMode->type) {
case M_TEXT:
if (machine==MCH_HERC) scanline=14;
else scanline=8;
break;
case M_CGA2:
scanline=2;
case M_CGA4:
if (CurMode->mode!=0xa) scanline=2;
else scanline=4;
case M_TANDY16:
if (CurMode->mode!=0x9) scanline=2;
else scanline=4;
break;
}
IO_WriteW(crtc_base,0x09 | (scanline-1) << 8);
//Setup the CGA palette using VGA DAC palette
for (i=0;i<16;i++) VGA_DAC_SetEntry(i,cga_palette[i][0],cga_palette[i][1],cga_palette[i][2]);
//Setup the tandy palette
for (i=0;i<16;i++) VGA_DAC_CombineColor(i,i);
//Setup the special registers for each machine type
Bit8u mode_control_list[0xa+1]={
0x2c,0x28,0x2d,0x29, //0-3
0x2a,0x2e,0x1e,0x29, //4-7
0x2a,0x2b,0x3b //8-a
};
Bit8u mode_control,color_select;
switch (machine) {
case MCH_HERC:
IO_WriteB(0x3bf,0x3); //Enable changing all bits
IO_WriteB(0x3b8,0x8); //TEXT mode and non-blinking characters
IO_WriteB(0x3bf,0x0); //Disable changing all bits
VGA_DAC_CombineColor(1,0xf);
break;
case MCH_CGA:
mode_control=mode_control_list[CurMode->mode];
if (CurMode->mode == 0x6) color_select=0x3f;
else color_select=0x30;
IO_WriteB(0x3d8,mode_control);
IO_WriteB(0x3d9,color_select);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
break;
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,0x3); //Tandy color overrides?
switch (CurMode->mode) {
case 0x8: case 0x9:
IO_WriteB(0x3de,0x14);break;
case 0xa:
IO_WriteB(0x3de,0x0c);break;
default:
IO_WriteB(0x3de,0x0);break;
}
mode_control=mode_control_list[CurMode->mode];
if (CurMode->mode == 0x6 || CurMode->mode==0xa) color_select=0x3f;
else color_select=0x30;
IO_WriteB(0x3d8,mode_control);
IO_WriteB(0x3d9,color_select);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
break;
}
FinishSetMode(clearmem);
return true;
}
bool INT10_SetVideoMode(Bitu mode) {
bool clearmem=true;Bitu i;
if ((mode<256) && (mode & 128)) {
clearmem=false;
mode-=128;
}
LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode);
if (machine!=MCH_VGA) return INT10_SetVideoMode_OTHER(mode,clearmem);
Bit8u modeset_ctl,video_ctl,vga_switches;
if (!SetCurMode(ModeList_VGA,mode)){
LOG(LOG_INT10,LOG_ERROR)("Trying to set illegal mode %X",mode);
return false;
}
/* First read mode setup settings from bios area */
video_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
@ -158,15 +339,12 @@ foundmode:
modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
/* Setup the VGA to the correct mode */
VGA_SetMode(CurMode->type);
// VGA_SetMode(CurMode->type);
Bit16u crtc_base;
bool mono_mode=CurMode->type == M_TEXT2;
if (mono_mode) {
crtc_base=0x3b4;
} else {
crtc_base=0x3d4;
}
bool mono_mode=(CurMode->type == M_TEXT && machine==MCH_HERC);
if (mono_mode) crtc_base=0x3b4;
else crtc_base=0x3d4;
/* Setup MISC Output Register */
Bit8u misc_output=0x2 | (mono_mode ? 0x0 : 0x1);
IO_Write(0x3c2,misc_output); //Setup for 3b4 or 3d4
@ -178,8 +356,7 @@ foundmode:
(CurMode->special & _EGA_HALF_CLOCK) ? 0x08 : 0x00;
seq_data[4]|=0x02; //More than 64kb
switch (CurMode->type) {
case M_TEXT2:
case M_TEXT16:
case M_TEXT:
seq_data[2]|=0x3; //Enable plane 0 and 1
seq_data[4]|=0x05; //Alpanumeric and odd/even enabled
break;
@ -223,28 +400,17 @@ foundmode:
blank_end = (CurMode->htotal-2) & 0x7f;
}
IO_Write(crtc_base,0x03);IO_Write(crtc_base+1,0x80|(blank_end & 0x1f));
// hor_overflow|=(blank_end & 0x40) >> 3;
/* Start Horizontal Retrace */
Bitu ret_start;
if (CurMode->special & _EGA_HALF_CLOCK) {
ret_start = (CurMode->hdispend+2);
} else {
ret_start = (CurMode->hdispend+4);
}
if (CurMode->special & _EGA_HALF_CLOCK) ret_start = (CurMode->hdispend+2);
else ret_start = (CurMode->hdispend+4);
IO_Write(crtc_base,0x04);IO_Write(crtc_base+1,ret_start);
hor_overflow|=(ret_start & 0x100) >> 4;
/* End Horizontal Retrace */
Bitu ret_end;
if (CurMode->special & _EGA_HALF_CLOCK) {
ret_end = (CurMode->htotal-2) & 0x3f;
} else {
ret_end = (CurMode->htotal-4) & 0x3f;
}
if (CurMode->special & _EGA_HALF_CLOCK) ret_end = (CurMode->htotal-2) & 0x3f;
else ret_end = (CurMode->htotal-4) & 0x3f;
IO_Write(crtc_base,0x05);IO_Write(crtc_base+1,(ret_end & 0x1f) | (blank_end & 0x20) << 2);
// hor_overflow|=(ret_end & 0x20);
//TODO Be sure about these ending values in extended overflow of s3
/* Vertical Total */
IO_Write(crtc_base,0x06);IO_Write(crtc_base+1,(CurMode->vtotal-2));
overflow|=((CurMode->vtotal-2) & 0x100) >> 8;
@ -286,8 +452,7 @@ foundmode:
/* Maximum scanline / Underline Location */
if (CurMode->special & _EGA_LINE_DOUBLE) max_scanline|=0x80;
switch (CurMode->type) {
case M_TEXT2:
case M_TEXT16:
case M_TEXT:
max_scanline|=CurMode->cheight-1;
underline=0x1f;
break;
@ -297,7 +462,6 @@ foundmode:
break;
case M_LIN8:
underline=0x60; //Seems to enable the every 4th clock on my s3
// if (CurMode->special & _VGA_LINE_DOUBLE) max_scanline|=1;
break;
}
IO_Write(crtc_base,0x09);IO_Write(crtc_base+1,max_scanline);
@ -328,8 +492,7 @@ foundmode:
case M_EGA16:
mode_control=0xe3;
break;
case M_TEXT2:
case M_TEXT16:
case M_TEXT:
case M_VGA:
mode_control=0xa3;
break;
@ -342,16 +505,9 @@ foundmode:
IO_Write(crtc_base,0x11);
IO_Write(crtc_base+1,IO_Read(crtc_base+1)|0x80);
/* Setup the correct clock */
switch (CurMode->type) {
case M_VGA:
case M_TEXT2:
case M_TEXT16:
case M_EGA16:
//Stick to 25mhz clock for now
break;
default:
if (CurMode->mode>=0x100) {
misc_output|=0xef; //Select clock 3
Bitu clock=CurMode->vtotal*8*CurMode->htotal*CurMode->rate;
Bitu clock=CurMode->vtotal*8*CurMode->htotal*70;
VGA_SetClock(3,clock/1000);
}
/* Write Misc Output */
@ -363,13 +519,9 @@ foundmode:
gfx_data[0x7]=0xf; /* Color don't care */
gfx_data[0x8]=0xff; /* BitMask */
switch (CurMode->type) {
case M_TEXT2:
case M_TEXT:
gfx_data[0x5]|=0x10; //Odd-Even Mode
gfx_data[0x6]|=0x0a; //alphanumeric mode at 0xb000=0x7fff
break;
case M_TEXT16:
gfx_data[0x5]|=0x10; //Odd-Even Mode
gfx_data[0x6]|=0x0e; //alphanumeric mode at 0xb800=0xbfff
gfx_data[0x6]|=mono_mode ? 0x0a : 0x0e; //Either b800 or b000
break;
case M_LIN8:
case M_VGA:
@ -393,7 +545,7 @@ foundmode:
Bit8u att_data[ATT_REGS];
memset(att_data,0,ATT_REGS);
att_data[0x12]=0xf; //Always have all color planes enabled
/* Porgram Attribute Controller */
/* Program Attribute Controller */
switch (CurMode->type) {
case M_EGA16:
if (CurMode->mode>0xe) goto att_text16;
@ -401,15 +553,13 @@ foundmode:
att_data[i]=i;
att_data[i+8]=i+0x10;
}
att_data[0x10]=0x01; //Color Graphics
break;
case M_TANDY16:
att_data[0x10]=0x01; //Color Graphics
for (i=0;i<16;i++) {
att_data[i]=i;
}
for (i=0;i<16;i++) att_data[i]=i;
break;
case M_TEXT2:
case M_TEXT16:
case M_TEXT:
att_data[0x13]=0x08; //Pel panning on 8, although we don't have 9 dot text mode
att_data[0x10]=0x0C; //Color Text with blinking
att_text16:
@ -419,30 +569,31 @@ att_text16:
}
break;
case M_CGA2:
IO_Write(0x3d9,0x7); //Setup using CGA color select register
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x7);
goto skipatt;
att_data[0x10]=0x01; //Color Graphics
att_data[0]=0x0;
att_data[1]=0xf;
att_data[0x12]=0x1; //Only enable 1 plane
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x3f);
break;
case M_CGA4:
//Set Bit 2 in black/white mode 0x5
IO_Write(0x3d8,0xa+(CurMode->mode==0x5) ? 0x4 : 0);
IO_Write(0x3d9,0x30); //Setup using CGA color select register
att_data[0x10]=0x01; //Color Graphics
att_data[0]=0x0;
att_data[1]=0x3;
att_data[2]=0x5;
att_data[3]=0x7;
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30);
goto skipatt;
break;
case M_VGA:
case M_LIN8:
for (i=0;i<16;i++) {
att_data[i]=i;
}
for (i=0;i<16;i++) att_data[i]=i;
att_data[0x10]=0x41; //Color Graphics 8-bit
break;
}
IO_Read(mono_mode ? 0x3ba : 0x3da);
for (i=0;i<ATT_REGS;i++) {
IO_Write(0x3c0,i);
IO_Write(0x3c0,att_data[i]);
}
skipatt:
/* Setup the DAC */
IO_Write(0x3c8,0);
switch (CurMode->type) {
@ -463,8 +614,7 @@ skipatt:
IO_Write(0x3c9,cga_palette[i][2]);
}
break;
case M_TEXT2:
case M_TEXT16:
case M_TEXT:
dac_text16:
for (i=0;i<64;i++) {
IO_Write(0x3c9,text_palette[i][0]);
@ -486,22 +636,16 @@ dac_text16:
switch (CurMode->type) {
case M_CGA2:
feature=(feature&~0x30)|0x20;
IO_Write(0x3d8,0x12); //Setup using CGA color select register
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x12);
break;
case M_CGA4:
feature=(feature&~0x30)|0x20;
IO_Write(0x3d8,0x2); //Setup using CGA color select register
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2);
break;
case M_TANDY16:
feature=(feature&~0x30)|0x20;
IO_Write(0x3df,0x80); //Enter 32k mode and banks on 0
break;
case M_TEXT2:
feature=(feature&~0x30)|0x30;
break;
case M_TEXT16:
case M_TEXT:
feature=(feature&~0x30)|0x20;
break;
case M_EGA16:
@ -527,70 +671,10 @@ dac_text16:
IO_Write(crtc_base,0x39);IO_Write(crtc_base+1,0xa5); //Register lock 2
/* Load text mode font */
if (CurMode->type<=M_TEXT16) {
if (CurMode->type==M_TEXT) {
INT10_LoadFont(Real2Phys(int10.rom.font_16),true,256,0,0,16);
}
/* Clear video memory if needs be */
if (clearmem) {
switch (CurMode->type) {
case M_CGA4:
case M_CGA2:
for (i=0;i<16*1024;i++) {
real_writew(0xb800,i*2,0x0000);
}
break;
case M_TEXT2:
for (i=0;i<16*1024;i++) {
real_writew(0xb000,i*2,0x0120);
}
break;
case M_TEXT16:
for (i=0;i<16*1024;i++) {
real_writew(0xb800,i*2,0x0720);
}
break;
case M_EGA16:
case M_VGA:
case M_LIN8:
/* Just clear the whole 2 mb of memory */
for (i=0;i<2*1024*1024/4;i++) {
mem_writed(S3_LFB_BASE+i*4,0);
}
}
}
/* Setup the BIOS */
if (mode<128) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode-0x98); //Looks like the s3 bios
real_writew(BIOSMEM_SEG,BIOSMEM_NB_COLS,CurMode->twidth);
real_writew(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,CurMode->plength);
real_writew(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_base);
real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,CurMode->theight-1);
real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,CurMode->cheight);
real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem << 7)));
real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0x09);
real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
// FIXME We nearly have the good tables. to be reworked
real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
real_writew(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
real_writew(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
// Set cursor shape
if(CurMode->type<=M_TEXT16) {
INT10_SetCursorShape(0x06,07);
}
// Set cursor pos for page 0..7
for(i=0;i<8;i++) INT10_SetCursorPos(0,0,(Bit8u)i);
// Set active page 0
INT10_SetActivePage(0);
/* Set some interrupt vectors */
switch (CurMode->cheight) {
case 8:RealSetVec(0x43,int10.rom.font_8_first);break;
case 14:RealSetVec(0x43,int10.rom.font_14);break;
case 16:RealSetVec(0x43,int10.rom.font_16);break;
}
/* Tell mouse resolution change */
Mouse_NewVideoMode();
FinishSetMode(clearmem);
return true;
}

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: int10_vesa.cpp,v 1.7 2004-01-11 09:27:52 harekiet Exp $ */
/* $Id: int10_vesa.cpp,v 1.8 2004-02-29 22:18:24 harekiet Exp $ */
#include <string.h>
#include <stddef.h>
@ -125,12 +125,12 @@ Bit8u VESA_GetSVGAModeInformation(Bit16u mode,Bit16u seg,Bit16u off) {
Bitu i=0;
if (mode<0x100) return 0x01;
while (ModeList[i].mode!=0xffff) {
if (mode==ModeList[i].mode) goto foundit; else i++;
while (ModeList_VGA[i].mode!=0xffff) {
if (mode==ModeList_VGA[i].mode) goto foundit; else i++;
}
return 0x01;
foundit:
VideoModeBlock * mblock=&ModeList[i];
VideoModeBlock * mblock=&ModeList_VGA[i];
switch (mblock->type) {
case M_LIN8: //Linear 8-bit
WLE(minfo.ModeAttributes,0x9b);
@ -310,9 +310,9 @@ void INT10_SetupVESA(void) {
i=0;
int10.rom.vesa_modes=RealMake(0xc000,int10.rom.used);
//TODO Maybe add normal vga modes too, but only seems to complicate things
while (ModeList[i].mode!=0xffff) {
if (ModeList[i].mode>=0x100){
phys_writew(PhysMake(0xc000,int10.rom.used),ModeList[i].mode);
while (ModeList_VGA[i].mode!=0xffff) {
if (ModeList_VGA[i].mode>=0x100){
phys_writew(PhysMake(0xc000,int10.rom.used),ModeList_VGA[i].mode);
int10.rom.used+=2;
}
i++;