1
0
Fork 0

New Video bios code:

Support for VESA 1.2
Support for text mode font changes
Support for setting CGA colors
Support for setting text mode cursor shape
Support for 16 color palette group changes
Some initial tandy mode support
Some fixes with graphics mode text output
Some cleanups


Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1060
This commit is contained in:
Sjoerd van der Berg 2003-06-15 19:37:57 +00:00
parent 1b4b7cb77b
commit 155cbb9f36
8 changed files with 921 additions and 586 deletions

View file

@ -27,31 +27,42 @@
#include "int10.h"
#include "../hardware/vga.h" /* Maybe move this thing */
#define TEXT_SEG 0xb800
Int10Data int10;
static Bitu call_10;
static bool warned_ff=false;
static bool warned_int10_0b=false;
Int10Data int10;
static Bitu INT10_Handler(void) {
#if 0
switch (reg_ah) {
case 0x02:
case 0x03:
case 0x09:
case 0xc:
case 0xd:
case 0x0e:
case 0x10:
case 0x4f:
break;
default:
LOG(LOG_INT10,LOG_NORMAL)("Function AX:%04X , BX %04X",reg_ax,reg_bx);
break;
}
#endif
switch (reg_ah) {
case 0x00: /* Set VideoMode */
INT10_SetVideoMode(reg_al);
break;
case 0x01: /* Set TextMode Cursor Shape */
vga.internal.cursor=reg_cx; // maybe write some memory somewhere
LOG(LOG_INT10,LOG_NORMAL)("INT10:01:Set textmode cursor shape partially supported: %X",reg_cx);
INT10_SetCursorShape(reg_ch,reg_cl);
break;
case 0x02: /* Set Cursor Pos */
//TODO Check some shit but not really usefull
INT10_SetCursorPos(reg_dh,reg_dl,reg_bh);
break;
case 0x03: /* get Cursor Pos and Cursor Shape*/
//TODO the Cursor Shape Stuff
reg_ah=0;
reg_dl=CURSOR_POS_COL(reg_bh);
reg_dh=CURSOR_POS_ROW(reg_bh);
reg_cx=real_readw(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE);
break;
case 0x04: /* read light pen pos YEAH RIGHT */
/* Light pen is not supported */
@ -62,15 +73,12 @@ static Bitu INT10_Handler(void) {
else INT10_SetActivePage(reg_al);
break;
case 0x06: /* Scroll Up */
//TODO Graphics mode scroll
INT10_ScrollWindow(reg_ch,reg_cl,reg_dh,reg_dl,-reg_al,reg_bh,0xFF);
break;
case 0x07:
/* Scroll Down */
case 0x07: /* Scroll Down */
INT10_ScrollWindow(reg_ch,reg_cl,reg_dh,reg_dl,reg_al,reg_bh,0xFF);
break;
case 0x08: /* Read character & attribute at cursor */
//TODO Check for GRAPH and then just return
INT10_ReadCharAttr(&reg_ax,reg_bh);
break;
case 0x09: /* Write Character & Attribute at cursor CX times */
@ -80,10 +88,14 @@ static Bitu INT10_Handler(void) {
INT10_WriteChar(reg_al,reg_bl,reg_bh,reg_cx,false);
break;
case 0x0B: /* Set Background/Border Colour & Set Palette*/
if(!warned_int10_0b) {
LOG(LOG_INT10,LOG_ERROR)("Function 0B Unsupported: Set Background/border colour & Set Pallete");
warned_int10_0b=true;
}
switch (reg_bh) {
case 0x00: //Background/Border color
INT10_SetBackgroundBorder(reg_bl);
break;
case 0x01: //Set color Select
INT10_SetColorSelect(reg_bl);
break;
}
break;
case 0x0C: /* Write Graphics Pixel */
INT10_PutPixel(reg_cx,reg_dx,reg_bh,reg_al);
@ -128,18 +140,68 @@ static Bitu INT10_Handler(void) {
case 0x12: /* SET BLOCK OF DAC REGISTERS */
INT10_SetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx);
break;
case 0x13: /* SELECT VIDEO DAC COLOR PAGE */
INT10_SelectDACPage(reg_bl,reg_bh);
break;
case 0x15: /* GET INDIVIDUAL DAC REGISTER */
INT10_GetSingleDacRegister(reg_bl,&reg_dh,&reg_ch,&reg_cl);
break;
case 0x17: /* GET BLOCK OF DAC REGISTER */
INT10_GetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx);
break;
case 0x18: /* undocumented - SET PEL MASK */
INT10_SetPelMask(reg_bl);
break;
case 0x19: /* undocumented - GET PEL MASK */
INT10_GetPelMask(reg_bl);
break;
default:
LOG(LOG_INT10,LOG_ERROR)("Function 10:Unhandled EGA/VGA Palette Function %2X",reg_al);
}
break;
case 0x11: /* Character generator functions */
switch (reg_al) {
/* Textmode calls */
case 0x00: /* Load user font */
case 0x10:
INT10_LoadFont(SegPhys(es)+reg_bp,reg_al==0x10,reg_cx,reg_dx,reg_bl,reg_bh);
break;
case 0x01: /* Load 8x14 font */
case 0x11:
INT10_LoadFont(Real2Phys(int10.rom.font_14),true,256,0,0,14);
break;
case 0x02: /* Load 8x8 font */
case 0x12:
INT10_LoadFont(Real2Phys(int10.rom.font_8_first),true,256,0,0,8);
break;
/* Graphics mode calls */
case 0x20: /* Set User 8x8 Graphics characters */
RealSetVec(0x1f,RealMake(SegValue(es),reg_bp));
break;
case 0x21: /* Set user graphics characters */
RealSetVec(0x43,RealMake(SegValue(es),reg_bp));
real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,reg_cx);
goto graphics_chars;
case 0x22: /* Rom 8x14 set */
RealSetVec(0x43,int10.rom.font_14);
real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,14);
goto graphics_chars;
// case 0x23: /* Rom 8x8 double dot set */
//TODO
case 0x24: /* Rom 8x16 set */
RealSetVec(0x43,int10.rom.font_16);
real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,16);
goto graphics_chars;
graphics_chars:
switch (reg_bl) {
case 0x00:real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,reg_dl-1);break;
case 0x01:real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,13);break;
case 0x03:real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,42);break;
case 0x02:
default:real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,24);break;
}
break;
/* General */
case 0x30:/* Get Font Information */
switch (reg_bh) {
case 0x00: /* interupt 0x1f vector */
@ -159,23 +221,23 @@ static Bitu INT10_Handler(void) {
}
break;
case 0x02: /* font 8x14 */
SegSet16(es,RealSeg(int10_romarea.font_14));
reg_bp=RealOff(int10_romarea.font_14);
SegSet16(es,RealSeg(int10.rom.font_14));
reg_bp=RealOff(int10.rom.font_14);
reg_cx=14;
break;
case 0x03: /* font 8x8 first 128 */
SegSet16(es,RealSeg(int10_romarea.font_8_first));
reg_bp=RealOff(int10_romarea.font_8_first);
SegSet16(es,RealSeg(int10.rom.font_8_first));
reg_bp=RealOff(int10.rom.font_8_first);
reg_cx=8;
break;
case 0x04: /* font 8x8 second 128 */
SegSet16(es,RealSeg(int10_romarea.font_8_second));
reg_bp=RealOff(int10_romarea.font_8_second);
SegSet16(es,RealSeg(int10.rom.font_8_second));
reg_bp=RealOff(int10.rom.font_8_second);
reg_cx=8;
break;
case 0x06: /* font 8x16 */
SegSet16(es,RealSeg(int10_romarea.font_16));
reg_bp=RealOff(int10_romarea.font_16);
SegSet16(es,RealSeg(int10.rom.font_16));
reg_bp=RealOff(int10.rom.font_16);
reg_cx=16;
break;
default:
@ -197,8 +259,16 @@ static Bitu INT10_Handler(void) {
reg_cx=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES) & 0x0F;
break;
}
case 0x36: /* VGA Refresh control */
/*
Call disables/enables the vga from outputting video,
don't support it, but fake a success return
*/
reg_al=0x12;
break;
default:
LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl);
reg_al=0x12; //Always fake a success call
}
break;
case 0x13: /* Write String */
@ -223,7 +293,76 @@ static Bitu INT10_Handler(void) {
reg_al=0x1B;
break;
default:
LOG(LOG_INT10,LOG_ERROR)("Function 1B:Unhandled call BX %2X",reg_bx);
LOG(LOG_INT10,LOG_ERROR)("1B:Unhandled call BX %2X",reg_bx);
}
break;
case 0x4f: /* VESA Calls */
switch (reg_al) {
case 0x00: /* Get SVGA Information */
reg_al=0x4f;
reg_ah=VESA_GetSVGAInformation(SegValue(es),reg_di);
break;
case 0x01: /* Get SVGA Mode Information */
reg_al=0x4f;
reg_ah=VESA_GetSVGAModeInformation(reg_cx,SegValue(es),reg_di);
break;
case 0x02: /* Set videomode */
reg_al=0x4f;
reg_ah=VESA_SetSVGAMode(reg_bx);
break;
case 0x03: /* Get videomode */
reg_al=0x4f;
reg_ah=VESA_GetSVGAMode(reg_bx);
break;
case 0x05:
if (reg_bh==0) { /* Set CPU Window */
reg_ah=VESA_SetCPUWindow(reg_bl,reg_dx);
reg_al=0x4f;
} else if (reg_bh == 1) { /* Get CPU Window */
reg_ah=VESA_GetCPUWindow(reg_bl,reg_dx);
reg_al=0x4f;
} else {
LOG(LOG_INT10,LOG_ERROR)("Unhandled VESA Function %X Subfunction %X",reg_al,reg_bh);
reg_ah=0x01;
}
break;
case 0x07:
switch (reg_bl) {
case 0x80: /* Set Display Start during retrace ?? */
case 0x00: /* Set display Start */
reg_al=0x4f;
reg_ah=VESA_SetDisplayStart(reg_cx,reg_dx);
break;
case 0x01:
reg_al=0x4f;
reg_bh=0x00; //Weird?
reg_ah=VESA_GetDisplayStart(reg_cx,reg_dx);
break;
default:
LOG(LOG_INT10,LOG_ERROR)("Unhandled VESA Function %X Subfunction %X",reg_al,reg_bl);
reg_ah=0x1;
}
break;
case 0x09:
switch (reg_bl) {
case 0x80: /* Set Palette during retrace */
//TODO
case 0x00: /* Set Palette */
reg_ah=VESA_SetPalette(SegPhys(es)+reg_di,reg_dx,reg_cx);
reg_al=0x4f;
break;
case 0x01: /* Get Palette */
reg_ah=VESA_GetPalette(SegPhys(es)+reg_di,reg_dx,reg_cx);
reg_al=0x4f;
break;
default:
LOG(LOG_INT10,LOG_ERROR)("Unhandled VESA Function %X Subfunction %X",reg_al,reg_bl);
reg_ah=0x01;
}
break;
default:
LOG(LOG_INT10,LOG_ERROR)("Unhandled VESA Function %X",reg_al);
reg_al=0x0;
}
break;
case 0xff:
@ -251,8 +390,6 @@ static void INT10_Seg40Init(void) {
real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,0x51);
// Set the default MSR
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x09);
INT10_SetVideoMode(3);
}
@ -275,6 +412,8 @@ void INT10_Init(Section* sec) {
//Init the 0x40 segment and init the datastructures in the the video rom area
INT10_SetupRomMemory();
INT10_Seg40Init();
INT10_SetupVESA();
INT10_SetVideoMode(3);
};

View file

@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "../hardware/vga.h"
#define BIOSMEM_SEG 0x40
#define BIOSMEM_INITIAL_MODE 0x10
@ -83,99 +85,64 @@
#define VGAMEM_CTEXT 0xB800
#define VGAMEM_MTEXT 0xB000
/*
*
* Tables of default values for each mode
*
*/
#define MODE_MAX 0x13
#define TEXT 0x00
#define GRAPH 0x01
#define CTEXT 0x00
#define MTEXT 0x01
#define CGA 0x02
#define PLANAR1 0x03
#define PLANAR2 0x04
#define PLANAR4 0x05
#define LINEAR8 0x06
#define CGA2 0x07
// for Tandy
#define TANDY16 0x0A
#define LINEAR15 0x10
#define LINEAR16 0x11
#define LINEAR24 0x12
#define LINEAR32 0x13
#define SCREEN_SIZE(x,y) (((x*y*2)|0x00ff)+1)
#define SCREEN_MEM_START(x,y,p) ((((x*y*2)|0x00ff)+1)*p)
#define SCREEN_IO_START(x,y,p) ((((x*y)|0x00ff)+1)*p)
#define BIOS_NCOLS Bit16u ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
#define BIOS_NROWS Bit16u nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
extern Bit8u int10_font_08[256 * 8];
extern Bit8u int10_font_14[256 * 14];
extern Bit8u int10_font_16[256 * 16];
struct VideoModeBlock {
Bitu mode;
VGAModes type;
Bitu swidth, sheight;
Bitu twidth, theight;
Bitu cwidth, cheight;
Bitu ptotal,pstart,plength;
typedef struct
{Bit8u svgamode;
Bit16u vesamode;
Bit8u type; /* TEXT, GRAPH */
Bit8u memmodel; /* CTEXT,MTEXT,CGA,PL1,PL2,PL4,P8,P15,P16,P24,P32 */
Bit8u nbpages;
Bit8u pixbits;
Bit16u swidth, sheight;
Bit16u twidth, theight;
Bit16u cwidth, cheight;
Bit16u sstart;
Bit16u slength;
Bit8u miscreg;
Bit8u pelmask;
Bit8u crtcmodel;
Bit8u actlmodel;
Bit8u grdcmodel;
Bit8u sequmodel;
Bit8u dacmodel; /* 0 1 2 3 */
} VGAMODES;
extern VGAMODES vga_modes[MODE_MAX+1];
Bitu htotal,vtotal;
Bitu hdispend,vdispend;
Bitu special;
};
extern VideoModeBlock ModeList[];
extern VideoModeBlock * CurMode;
typedef struct {
RealPt font_8_first;
RealPt font_8_second;
RealPt font_14;
RealPt font_16;
RealPt static_state;
} VGAROMAREA;
extern VGAROMAREA int10_romarea;
struct {
RealPt font_8_first;
RealPt font_8_second;
RealPt font_14;
RealPt font_16;
RealPt static_state;
RealPt oemstring;
RealPt vesa_modes;
Bitu used;
} rom;
} Int10Data;
#define BIOS_NCOLS Bit16u ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
#define BIOS_NROWS Bit16u nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
extern Int10Data int10;
inline Bit8u CURSOR_POS_COL(Bit8u page) {
INLINE Bit8u CURSOR_POS_COL(Bit8u page) {
return real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2);
}
inline Bit8u CURSOR_POS_ROW(Bit8u page) {
INLINE Bit8u CURSOR_POS_ROW(Bit8u page) {
return real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2+1);
}
void INT10_SetVideoMode(Bit8u mode);
bool INT10_SetVideoMode(Bitu mode);
void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page);
void INT10_SetActivePage(Bit8u page);
void INT10_GetFuncStateInformation(PhysPt save);
void INT10_SetCursorShape(Bit8u first,Bit8u last);
void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page);
void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page);
void INT10_ReadCharAttr(Bit16u * result,Bit8u page);
@ -185,9 +152,13 @@ void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,B
/* Graphics Stuff */
void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color);
void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color);
VGAMODES * GetCurrentMode(void);
/* Font Stuff */
void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu height);
/* Palette Group */
void INT10_SetBackgroundBorder(Bit8u val);
void INT10_SetColorSelect(Bit8u val);
void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val);
void INT10_SetOverscanBorderColor(Bit8u val);
void INT10_SetAllPaletteRegisters(PhysPt data);
@ -199,17 +170,27 @@ void INT10_SetSingleDacRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue);
void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * blue);
void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysPt data);
void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data);
void INT10_SelectDACPage(Bit8u function,Bit8u mode);
void INT10_SetPelMask(Bit8u mask);
void INT10_GetPelMask(Bit8u & mask);
/* Mouse pointer */
void INT10_SetGfxControllerToDefault(void);
/* Vesa Group */
Bit8u VESA_GetSVGAInformation(Bit16u seg,Bit16u off);
Bit8u VESA_GetSVGAModeInformation(Bit16u mode,Bit16u seg,Bit16u off);
Bit8u VESA_SetSVGAMode(Bit16u mode);
Bit8u VESA_GetSVGAMode(Bit16u & mode);
Bit8u VESA_SetCPUWindow(Bit8u window,Bit16u address);
Bit8u VESA_GetCPUWindow(Bit8u window,Bit16u & address);
Bit8u VESA_ScanLineLength(Bit8u subcall,Bit16u & bytes,Bit16u & pixels,Bit16u & lines);
Bit8u VESA_SetDisplayStart(Bit16u x,Bit16u y);
Bit8u VESA_GetDisplayStart(Bit16u & x,Bit16u & y);
Bit8u VESA_SetPalette(PhysPt data,Bitu index,Bitu count);
Bit8u VESA_GetPalette(PhysPt data,Bitu index,Bitu count);
/* Sup Groups */
void INT10_SetupRomMemory(void);
void INT10_SetupVESA(void);
struct Int10Data {
Bit8u mode;
VGAMODES * entry;
};
extern Int10Data int10;

View file

@ -24,28 +24,28 @@
#include "inout.h"
#include "int10.h"
static INLINE void CGA_CopyRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) {
PhysPt dest=base+((curmode->twidth*rnew)*(curmode->cheight/2)+cleft)*2;
PhysPt src=base+((curmode->twidth*rold)*(curmode->cheight/2)+cleft)*2;
Bitu copy=(cright-cleft)*2;Bitu nextline=curmode->twidth*2;
for (Bits i=0;i<curmode->cheight/2;i++) {
static INLINE void CGA_CopyRow(Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) {
PhysPt dest=base+((CurMode->twidth*rnew)*(CurMode->cheight/2)+cleft)*2;
PhysPt src=base+((CurMode->twidth*rold)*(CurMode->cheight/2)+cleft)*2;
Bitu copy=(cright-cleft)*2;Bitu nextline=CurMode->twidth*2;
for (Bitu i=0;i<CurMode->cheight/2;i++) {
MEM_BlockCopy(dest,src,copy);
MEM_BlockCopy(dest+8*1024,src+8*1024,copy);
dest+=nextline;src+=nextline;
}
}
static INLINE void PLANAR4_CopyRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) {
static INLINE void EGA16_CopyRow(Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) {
PhysPt src,dest;Bitu copy;
dest=base+(curmode->twidth*rnew)*curmode->cheight+cleft;
src=base+(curmode->twidth*rold)*curmode->cheight+cleft;
Bitu nextline=curmode->twidth;
dest=base+(CurMode->twidth*rnew)*CurMode->cheight+cleft;
src=base+(CurMode->twidth*rold)*CurMode->cheight+cleft;
Bitu nextline=CurMode->twidth;
/* Setup registers correctly */
IO_Write(0x3ce,5);IO_Write(0x3cf,1); /* Memory transfer mode */
IO_Write(0x3c4,2);IO_Write(0x3c5,0xf); /* Enable all Write planes */
/* Do some copying */
Bitu rowsize=(cright-cleft);
copy=curmode->cheight;
copy=CurMode->cheight;
for (;copy>0;copy--) {
for (Bitu x=0;x<rowsize;x++) mem_writeb(dest+x,mem_readb(src+x));
dest+=nextline;src+=nextline;
@ -55,17 +55,17 @@ static INLINE void PLANAR4_CopyRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,B
}
static INLINE void TEXT_CopyRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) {
static INLINE void TEXT_CopyRow(Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) {
PhysPt src,dest;
src=base+(rold*curmode->twidth+cleft)*2;
dest=base+(rnew*curmode->twidth+cleft)*2;
src=base+(rold*CurMode->twidth+cleft)*2;
dest=base+(rnew*CurMode->twidth+cleft)*2;
MEM_BlockCopy(dest,src,(cright-cleft)*2);
}
static INLINE void CGA_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) {
PhysPt dest=base+((curmode->twidth*row)*(curmode->cheight/2)+cleft)*2;
Bitu copy=(cright-cleft)*2;Bitu nextline=curmode->twidth*2;
for (Bits i=0;i<curmode->cheight/2;i++) {
static INLINE void CGA_FillRow(Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) {
PhysPt dest=base+((CurMode->twidth*row)*(CurMode->cheight/2)+cleft)*2;
Bitu copy=(cright-cleft)*2;Bitu nextline=CurMode->twidth*2;
for (Bitu i=0;i<CurMode->cheight/2;i++) {
for (Bitu x=0;x<copy;x++) {
mem_writeb(dest+x,attr);
mem_writeb(dest+8*1024+x,attr);
@ -74,17 +74,16 @@ static INLINE void CGA_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u
}
}
static INLINE void PLANAR4_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) {
static INLINE void EGA16_FillRow(Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) {
/* Set Bitmask / Color / Full Set Reset */
IO_Write(0x3ce,0x8);IO_Write(0x3cf,0xff);
IO_Write(0x3ce,0x0);IO_Write(0x3cf,attr);
IO_Write(0x3ce,0x1);IO_Write(0x3cf,0xf);
/* Write some bytes */
PhysPt dest;
dest=base+(curmode->twidth*row)*curmode->cheight+cleft;
Bitu nextline=curmode->twidth;
Bitu copy=curmode->cheight; Bitu rowsize=(cright-cleft);
dest=base+(CurMode->twidth*row)*CurMode->cheight+cleft;
Bitu nextline=CurMode->twidth;
Bitu copy=CurMode->cheight; Bitu rowsize=(cright-cleft);
for (;copy>0;copy--) {
for (Bitu x=0;x<rowsize;x++) mem_writeb(dest+x,0xff);
dest+=nextline;
@ -93,10 +92,10 @@ static INLINE void PLANAR4_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,B
}
static INLINE void TEXT_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) {
static INLINE void TEXT_FillRow(Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) {
/* Do some filing */
PhysPt dest;
dest=base+(row*curmode->twidth+cleft)*2;
dest=base+(row*CurMode->twidth+cleft)*2;
Bit16u fill=(attr<<8)+' ';
for (Bit8u x=0;x<(cright-cleft);x++) {
mem_writew(dest,fill);
@ -107,8 +106,7 @@ static INLINE void TEXT_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8
void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page) {
/* Do some range checking */
VGAMODES * curmode=GetCurrentMode();
if (curmode->type==GRAPH) page=0xff;
if (CurMode->type!=M_TEXT16) page=0xff;
BIOS_NCOLS;BIOS_NROWS;
if(rul>rlr) return;
if(cul>clr) return;
@ -118,9 +116,9 @@ void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit
/* Get the correct page */
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
PhysPt base=PhysMake(curmode->sstart,curmode->slength*page);
PhysPt base=CurMode->pstart+CurMode->plength*page;
/* See how much lines need to be copies */
/* See how much lines need to be copied */
Bit8u start,end;Bits next;
/* Copy some lines */
if (nlines>0) {
@ -137,15 +135,16 @@ void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit
}
while (start!=end) {
start+=next;
switch (curmode->memmodel) {
case MTEXT:
case CTEXT:
TEXT_CopyRow(curmode,cul,clr,start,start+nlines,base);break;
case CGA2:
case CGA:
CGA_CopyRow(curmode,cul,clr,start,start+nlines,base);break;
case PLANAR4:
PLANAR4_CopyRow(curmode,cul,clr,start,start+nlines,base);break;
switch (CurMode->type) {
case M_TEXT16:
TEXT_CopyRow(cul,clr,start,start+nlines,base);break;
case M_CGA2:
case M_CGA4:
CGA_CopyRow(cul,clr,start,start+nlines,base);break;
case M_EGA16:
EGA16_CopyRow(cul,clr,start,start+nlines,base);break;
default:
LOG(LOG_INT10,LOG_ERROR)("Unhandled mode %d for scroll",CurMode->type);
}
}
/* Fill some lines */
@ -157,14 +156,16 @@ filling:
start=rlr-nlines+1;
}
for (;nlines>0;nlines--) {
switch (curmode->memmodel) {
case MTEXT:
case CTEXT:
TEXT_FillRow(curmode,cul,clr,start,base,attr);break;
case CGA:
CGA_FillRow(curmode,cul,clr,start,base,attr);break;
case PLANAR4:
PLANAR4_FillRow(curmode,cul,clr,start,base,attr);break;
switch (CurMode->type) {
case M_TEXT16:
TEXT_FillRow(cul,clr,start,base,attr);break;
case M_CGA2:
case M_CGA4:
CGA_FillRow(cul,clr,start,base,attr);break;
case M_EGA16:
EGA16_FillRow(cul,clr,start,base,attr);break;
default:
LOG(LOG_INT10,LOG_ERROR)("Unhandled mode %d for scroll",CurMode->type);
}
start++;
}
@ -175,14 +176,11 @@ void INT10_SetActivePage(Bit8u page) {
Bit16u mem_address;
Bit8u cur_col=0 ,cur_row=0 ;
VGAMODES * curmode=GetCurrentMode();
if (curmode==0) return;
if (page>7) return;
mem_address=page*curmode->slength;
mem_address=page*CurMode->plength;
/* Write the new page start */
real_writew(BIOSMEM_SEG,BIOSMEM_CURRENT_START,mem_address);
if (curmode->svgamode<8) mem_address>>=1;
if (CurMode->mode<8) mem_address>>=1;
/* Write the new start address in vgahardware */
IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0c);
@ -197,6 +195,53 @@ void INT10_SetActivePage(Bit8u page) {
INT10_SetCursorPos(cur_row,cur_col,page);
}
void INT10_SetCursorShape(Bit8u first,Bit8u last) {
real_writew(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,last|(first<<8));
/* Skip CGA cursor emulation if EGA/VGA system is active */
if (!(real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL) & 0x8)) {
/* Check for CGA type 01, invisible */
if ((first & 0x60) == 0x20) {
first=0x1e;
last=0x00;
goto dowrite;
}
/* Check if we need to convert CGA Bios cursor values */
if (!(real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL) & 0x1)) {
if (CurMode->mode>0x3) goto dowrite; //Only mode 0-3 are text modes on cga
if ((first & 0xe0) || (last & 0xe0)) goto dowrite;
Bit8u cheight=real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)-1;
/* Creative routine i based of the original ibmvga bios */
if (last<first) {
if (!last) goto dowrite;
first=last;
last=cheight;
/* Test if this might be a cga style cursor set, if not don't do anything */
} else if (((first | last)>=cheight) || !(last==(cheight-1)) || !(first==cheight) ) {
if (last<=3) goto dowrite;
if (first+2<last) {
if (first>2) {
first=(cheight+1)/2;
last=cheight;
} else {
last=cheight;
}
} else {
first=(first-last)+cheight;
last=cheight;
if (cheight>0xc) {
first--;
last--;
}
}
}
}
}
dowrite:
IO_Write(0x3d4,0xa);IO_Write(0x3d5,first);
IO_Write(0x3d4,0xb);IO_Write(0x3d5,last);
}
void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page) {
Bit16u address;
@ -217,12 +262,11 @@ void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page) {
IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(address&0xff00)>>8);
IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0f);
IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,address&0x00ff);
}
}
}
void INT10_ReadCharAttr(Bit16u * result,Bit8u page) {
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
BIOS_NCOLS;BIOS_NROWS;
Bit8u cur_row=CURSOR_POS_ROW(page);
@ -233,66 +277,55 @@ void INT10_ReadCharAttr(Bit16u * result,Bit8u page) {
}
INLINE static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool useattr) {
VGAMODES * curmode=GetCurrentMode();
switch (curmode->type) {
case TEXT:
static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool useattr) {
Bit8u * fontdata;
Bitu x,y;
switch (CurMode->type) {
case M_TEXT16:
{
// Compute the address
Bit16u address=SCREEN_MEM_START(curmode->twidth,curmode->theight,page)+(col+row*curmode->twidth)*2;
Bit16u address=SCREEN_MEM_START(CurMode->twidth,CurMode->theight,page)+(col+row*CurMode->twidth)*2;
// Write the char
Bit16u segment = curmode->sstart;
real_writeb(segment,address,chr);
PhysPt where = CurMode->pstart+address;
mem_writeb(where,chr);
if (useattr) {
real_writeb(segment,address+1,attr);
mem_writeb(where+1,attr);
}
}
return;
case M_CGA4:
case M_CGA2:
if (chr<128) fontdata=Real2Host(RealGetVec(0x43))+chr*8;
else {
chr-=128;
fontdata=Real2Host(RealGetVec(0x1F))+(chr)*8;
}
break;
case GRAPH:
{
/* Amount of lines */
Bit8u * fontdata;
Bit16u x,y;
switch (curmode->cheight) {
case 8:
// fontdata=&int10_font_08[chr*8];
if (chr<128) fontdata=Real2Host(RealGetVec(0x43))+chr*8;
else fontdata=Real2Host(RealGetVec(0x1F))+(chr-128)*8;
break;
case 14:
fontdata=&int10_font_14[chr*14];
break;
case 16:
fontdata=&int10_font_16[chr*16];
break;
default:
LOG(LOG_INT10,LOG_ERROR)("Teletype Illegal Font Height");
return;
}
x=8*col;
y=curmode->cheight*row;
//TODO Check for out of bounds
for (Bit8u h=0;h<curmode->cheight;h++) {
Bit8u bitsel=128;
Bit8u bitline=*fontdata++;
Bit16u tx=x;
while (bitsel) {
if (bitline&bitsel) INT10_PutPixel(tx,y,page,attr);
else INT10_PutPixel(tx,y,page,attr & 0x80);
tx++;
bitsel>>=1;
}
y++;
}
}
default:
fontdata=Real2Host(RealGetVec(0x43))+chr*real_readw(0x40,BIOSMEM_CHAR_HEIGHT);
break;
}
x=8*col;
y=CurMode->cheight*row;
//TODO Check for out of bounds
for (Bit8u h=0;h<CurMode->cheight;h++) {
Bit8u bitsel=128;
Bit8u bitline=*fontdata++;
Bit16u tx=x;
while (bitsel) {
if (bitline&bitsel) INT10_PutPixel(tx,y,page,attr);
else INT10_PutPixel(tx,y,page,attr & 0x80);
tx++;
bitsel>>=1;
}
y++;
}
}
void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr) {
VGAMODES * curmode=GetCurrentMode();
if (curmode->type==GRAPH) page=0xff;
//TODO Check if this page thing is correct
if (CurMode->type!=M_TEXT16) 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);
@ -310,8 +343,8 @@ void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr)
void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page) {
VGAMODES * curmode=GetCurrentMode();
if (curmode->type==GRAPH) page=0xff;
//TODO Check if this page thing is correct
if (CurMode->type!=M_TEXT16) page=0xff;
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
BIOS_NCOLS;BIOS_NROWS;
Bit8u cur_row=CURSOR_POS_ROW(page);
@ -357,8 +390,8 @@ void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page) {
}
void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,Bit16u count,Bit8u page) {
VGAMODES * curmode=GetCurrentMode();
if (curmode->type==GRAPH) page=0xff;
//TODO Check if this page thing is correct
if (CurMode->type!=M_TEXT16) page=0xff;
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
BIOS_NCOLS;BIOS_NROWS;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002 The DOSBox Team
* Copyright (C) 2002-2003 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
@ -22,7 +22,6 @@
#include "int10.h"
VGAROMAREA int10_romarea;
static Bit8u static_functionality[0x10]=
{
/* 0 */ 0xff, // All modes supported #1
@ -40,35 +39,67 @@ static Bit8u static_functionality[0x10]=
/* f */ 0x00 // reserved
};
static Bit16u map_offset[8]={
0x0000,0x4000,0x8000,0xc000,
0x2000,0x6000,0xa000,0xe000
};
void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu height) {
PhysPt where=PhysMake(0xa000,map_offset[map & 0x7]+offset*32);
IO_Write(0x3c4,0x2);IO_Write(0x3c5,0x4); //Enable plane 2
IO_Write(0x3ce,0x6);IO_Write(0x3cf,0x0); //Disable odd/even and a0000 adressing
for (Bitu i=0;i<count;i++) {
MEM_BlockCopy(where,font,height);
where+=32;
font+=height;
}
IO_Write(0x3c4,0x2);IO_Write(0x3c5,0xf); //Enable all planes
IO_Write(0x3ce,0x6);
IO_Write(0x3cf,0x0e); //odd/even and b8000 adressing
/* Reload tables and registers with new values based on this height */
if (reload) {
//Max scanline
IO_Write(0x3d4,0x9);
IO_Write(0x3d5,(IO_Read(0x3d5) & 0xe0)|(height-1));
//Vertical display end bios says, but should stay the same?
//Rows setting in bios segment
real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,(CurMode->sheight/height)-1);
real_writeb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,height);
//TODO Reprogram cursor size?
}
}
void INT10_SetupRomMemory(void) {
/* This should fill up certain structures inside the Video Bios Rom Area */
Bit32u i;
Bit16u segoff=0;
int10_romarea.font_8_first=RealMake(0xC000,segoff);
Bitu i;
int10.rom.used=2;
real_writew(0xc000,0,0xaa55);
int10.rom.font_8_first=RealMake(0xC000,int10.rom.used);
for (i=0;i<128*8;i++) {
real_writeb(0xC000,segoff++,int10_font_08[i]);
real_writeb(0xC000,int10.rom.used++,int10_font_08[i]);
}
int10_romarea.font_8_second=RealMake(0xC000,segoff);
int10.rom.font_8_second=RealMake(0xC000,int10.rom.used);
for (i=0;i<128*8;i++) {
real_writeb(0xC000,segoff++,int10_font_08[i+128*8]);
real_writeb(0xC000,int10.rom.used++,int10_font_08[i+128*8]);
}
int10_romarea.font_14=RealMake(0xC000,segoff);
int10.rom.font_14=RealMake(0xC000,int10.rom.used);
for (i=0;i<256*14;i++) {
real_writeb(0xC000,segoff++,int10_font_14[i]);
real_writeb(0xC000,int10.rom.used++,int10_font_14[i]);
}
int10_romarea.font_16=RealMake(0xC000,segoff);
int10.rom.font_16=RealMake(0xC000,int10.rom.used);
for (i=0;i<256*16;i++) {
real_writeb(0xC000,segoff++,int10_font_16[i]);
real_writeb(0xC000,int10.rom.used++,int10_font_16[i]);
}
int10_romarea.static_state=RealMake(0xC000,segoff);
int10.rom.static_state=RealMake(0xC000,int10.rom.used);
for (i=0;i<0x10;i++) {
real_writeb(0xC000,segoff++,static_functionality[i]);
real_writeb(0xC000,int10.rom.used++,static_functionality[i]);
}
MEM_BlockWrite(PhysMake(0xf000,0xfa6e),int10_font_08,128*8);
RealSetVec(0x1F,int10_romarea.font_8_second);
RealSetVec(0x1F,int10.rom.font_8_second);
};

View file

@ -73,12 +73,12 @@ struct Dynamic_Functionality {
void INT10_GetFuncStateInformation(PhysPt save) {
/* set static state pointer */
mem_writed(save,int10_romarea.static_state);
mem_writed(save,int10.rom.static_state);
/* Copy BIOS Segment areas */
Bit16u i;
/* First area in Bios Seg */
for (i=0;i<30;i++) {
for (i=0;i<0x1e;i++) {
mem_writeb(save+0x4+i,real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE+i));
}
/* Second area */
@ -89,31 +89,27 @@ void INT10_GetFuncStateInformation(PhysPt save) {
for (i=0x25;i<0x40;i++) mem_writeb(save+i,0);
/* DCC Index */
mem_writeb(save+0x25,real_readb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
VGAMODES * curmode=GetCurrentMode();
if (!curmode) return;
Bit16u col_count=0;
switch (curmode->memmodel) {
case CTEXT:
col_count=2;break;
case MTEXT:
switch (CurMode->type) {
case M_TEXT16:
col_count=16;break;
case CGA:
col_count=4;break;
case PLANAR1:
case M_CGA2:
col_count=2;break;
case PLANAR2:
case M_CGA4:
col_count=4;break;
case PLANAR4:
case M_EGA16:
col_count=16;break;
case LINEAR8:
case M_VGA:
col_count=256;break;
default:
LOG(LOG_INT10,LOG_ERROR)("Get Func State illegal mode type %d",CurMode->type);
}
/* Colour count */
mem_writew(save+0x27,col_count);
/* Page count */
mem_writeb(save+0x29,curmode->nbpages);
mem_writeb(save+0x29,CurMode->ptotal);
/* scan lines */
switch (curmode->sheight) {
switch (CurMode->sheight) {
case 200:
mem_writeb(save+0x2a,0);break;
case 350:

View file

@ -1,20 +1,4 @@
/*
* Copyright (C) 2002-2003 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 "mem.h"
@ -22,113 +6,57 @@
#include "int10.h"
#include "mouse.h"
//TODO Maybe also add PCJR Video Modes could be nice :)
//TODO include some credits to bochs/plex86 bios i used for info/tables
#define _HALF_CLOCK 0x0001
#define _LINE_DOUBLE 0x0002
#define SEQ_REGS 0x05
#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 ,special flags */
{ 0x000 ,M_TEXT16 ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_HALF_CLOCK },
{ 0x001 ,M_TEXT16 ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_HALF_CLOCK },
{ 0x002 ,M_TEXT16 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
{ 0x003 ,M_TEXT16 ,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 ,_HALF_CLOCK |_LINE_DOUBLE },
{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_HALF_CLOCK |_LINE_DOUBLE },
{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,_LINE_DOUBLE },
{ 0x007 ,M_TEXT16 ,720 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
/* 8,9,0xa are tandy modes */
{ 0x009 ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_HALF_CLOCK |_LINE_DOUBLE },
VGAMODES vga_modes[MODE_MAX+1]=
{//mode vesa class model pg bits sw sh tw th cw ch sstart slength misc pelm crtc actl gdc sequ dac
{0x00, 0xFFFF, TEXT, CTEXT, 8, 4, 360, 400, 40, 25, 9, 16, 0xB800, 0x0800, 0x67, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02},
{0x01, 0xFFFF, TEXT, CTEXT, 8, 4, 360, 400, 40, 25, 9, 16, 0xB800, 0x0800, 0x67, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02},
{0x02, 0xFFFF, TEXT, CTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB800, 0x1000, 0x67, 0xFF, 0x01, 0x00, 0x00, 0x01, 0x02},
{0x03, 0xFFFF, TEXT, CTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB800, 0x1000, 0x67, 0xFF, 0x01, 0x00, 0x00, 0x01, 0x02},
{0x04, 0xFFFF, GRAPH, CGA, 4, 2, 320, 200, 40, 25, 8, 8, 0xB800, 0x0800, 0x63, 0xFF, 0x02, 0x01, 0x01, 0x02, 0x01},
{0x05, 0xFFFF, GRAPH, CGA, 1, 2, 320, 200, 40, 25, 8, 8, 0xB800, 0x0800, 0x63, 0xFF, 0x02, 0x01, 0x01, 0x02, 0x01},
{0x06, 0xFFFF, GRAPH, CGA2, 1, 1, 640, 200, 80, 25, 8, 8, 0xB800, 0x1000, 0x63, 0xFF, 0x03, 0x02, 0x02, 0x03, 0x01},
{0x07, 0xFFFF, TEXT, MTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB000, 0x1000, 0x66, 0xFF, 0x04, 0x03, 0x03, 0x01, 0x00},
{0x0D, 0xFFFF, GRAPH, PLANAR4, 8, 4, 320, 200, 40, 25, 8, 8, 0xA000, 0x2000, 0x63, 0xFF, 0x05, 0x04, 0x04, 0x04, 0x01},
{0x0E, 0xFFFF, GRAPH, PLANAR4, 4, 4, 640, 200, 80, 25, 8, 8, 0xA000, 0x4000, 0x63, 0xFF, 0x06, 0x04, 0x04, 0x05, 0x01},
{0x0F, 0xFFFF, GRAPH, PLANAR2, 2, 2, 640, 350, 80, 25, 8, 14, 0xA000, 0x8000, 0xa2, 0xFF, 0x07, 0x05, 0x04, 0x05, 0x00},
{0x10, 0xFFFF, GRAPH, PLANAR4, 2, 4, 640, 350, 80, 25, 8, 14, 0xA000, 0x8000, 0xa3, 0xFF, 0x07, 0x06, 0x04, 0x05, 0x02},
{0x11, 0xFFFF, GRAPH, PLANAR1, 1, 1, 640, 480, 80, 30, 8, 16, 0xA000, 0xA000, 0xe3, 0xFF, 0x08, 0x07, 0x04, 0x05, 0x02},
{0x12, 0xFFFF, GRAPH, PLANAR4, 1, 4, 640, 480, 80, 30, 8, 16, 0xA000, 0xA000, 0xe3, 0xFF, 0x08, 0x06, 0x04, 0x05, 0x02},
{0x13, 0xFFFF, GRAPH, LINEAR8, 1, 8, 320, 200, 40, 25, 8, 8, 0xA000, 0xFA00, 0x63, 0xFF, 0x09, 0x08, 0x05, 0x06, 0x03}
{ 0x00D ,M_EGA16 ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_HALF_CLOCK |_LINE_DOUBLE },
{ 0x00E ,M_EGA16 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_LINE_DOUBLE },
{ 0x00F ,M_EGA2 ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,400 ,0 },
{ 0x010 ,M_EGA16 ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },
{ 0x011 ,M_EGA2 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,449 ,80 ,480 ,0 },
{ 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 ,20 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0 },
{ 0x101 ,M_LIN8 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },
{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 },
};
/* CRTC */
#define CRTC_MAX_REG 0x18
#define CRTC_MAX_MODEL 0x09
static Bit8u crtc_regs[CRTC_MAX_MODEL+1][CRTC_MAX_REG+1]=
{/* Model 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 */
/* 00 */ {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,0xff},
/* 01 */ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff},
/* 02 */ {0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f,0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,0xff},
/* 03 */ {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2,0xff},
/* 04 */ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3,0xff},
/* 05 */ {0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3,0xff},
/* 06 */ {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3,0xff},
/* 07 */ {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x85,0x5d,0x28,0x0f,0x63,0xba,0xe3,0xff},
/* 08 */ {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0xea,0x8c,0xdf,0x28,0x00,0xe7,0x04,0xe3,0xff},
/* 09 */ {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3,0xff}
};
/* Attribute Controler 0x3c0 */
#define ACTL_MAX_REG 0x14
#define ACTL_MAX_MODEL 0x08
static Bit8u actl_regs[ACTL_MAX_MODEL+1][ACTL_MAX_REG+1]=
{/* Model 00 01 02 03 04 05 06 07 08 09 0A 0B OC OD OE OF 10 11 12 13 14 */
/* 00 */ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x0c,0x00,0x0f,0x08,0x00},
/* 01 */ {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x01,0x00,0x03,0x00,0x00},
/* 02 */ {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x01,0x00,0x01,0x00,0x00},
/* 03 */ {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x0e,0x00,0x0f,0x08,0x00},
/* 04 */ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x01,0x00,0x0f,0x00,0x00},
/* 05 */ {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x0b,0x00,0x05,0x00,0x00},
/* 06 */ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x01,0x00,0x0f,0x00,0x00},
/* 07 */ {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x01,0x00,0x01,0x00,0x00},
/* 08 */ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x41,0x00,0x0f,0x00,0x00}
};
/* Sequencer 0x3c4 */
#define SEQU_MAX_REG 0x04
#define SEQU_MAX_MODEL 0x06
static Bit8u sequ_regs[SEQU_MAX_MODEL+1][SEQU_MAX_REG+1]=
{/* Model 00 01 02 03 04 */
/* 00 */ {0x03,0x08,0x03,0x00,0x02},
/* 01 */ {0x03,0x00,0x03,0x00,0x02},
/* 02 */ {0x03,0x09,0x03,0x00,0x02},
/* 03 */ {0x03,0x01,0x01,0x00,0x06},
/* 04 */ {0x03,0x09,0x0f,0x00,0x06},
/* 05 */ {0x03,0x01,0x0f,0x00,0x06},
/* 06 */ {0x03,0x01,0x0f,0x00,0x0e}
};
/* Graphic ctl 0x3ce */
#define GRDC_MAX_REG 0x08
#define GRDC_MAX_MODEL 0x05
static Bit8u grdc_regs[GRDC_MAX_MODEL+1][GRDC_MAX_REG+1]=
{/* Model 00 01 02 03 04 05 06 07 08 */
/* 00 */ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x0f,0xff},
/* 01 */ {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x0f,0xff},
/* 02 */ {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x0f,0xff},
/* 03 */ {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x0f,0xff},
/* 04 */ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,0xff},
/* 05 */ {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,0xff}
};
/* Default Palette */
#define DAC_MAX_MODEL 3
static Bit8u dac_regs[DAC_MAX_MODEL+1]=
{0x3f,0x3f,0x3f,0xff};
/* Mono */
static Bit8u palette0[63+1][3]=
static Bit8u text_palette[64][3]=
{
{0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00},
{0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a},
{0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a},
{0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f},
{0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00},
{0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a},
{0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a}, {0x2a,0x2a,0x2a},
{0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}, {0x3f,0x3f,0x3f}
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a,
0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f, 0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f,
0x00,0x15,0x00, 0x00,0x15,0x2a, 0x00,0x3f,0x00, 0x00,0x3f,0x2a, 0x2a,0x15,0x00, 0x2a,0x15,0x2a, 0x2a,0x3f,0x00, 0x2a,0x3f,0x2a,
0x00,0x15,0x15, 0x00,0x15,0x3f, 0x00,0x3f,0x15, 0x00,0x3f,0x3f, 0x2a,0x15,0x15, 0x2a,0x15,0x3f, 0x2a,0x3f,0x15, 0x2a,0x3f,0x3f,
0x15,0x00,0x00, 0x15,0x00,0x2a, 0x15,0x2a,0x00, 0x15,0x2a,0x2a, 0x3f,0x00,0x00, 0x3f,0x00,0x2a, 0x3f,0x2a,0x00, 0x3f,0x2a,0x2a,
0x15,0x00,0x15, 0x15,0x00,0x3f, 0x15,0x2a,0x15, 0x15,0x2a,0x3f, 0x3f,0x00,0x15, 0x3f,0x00,0x3f, 0x3f,0x2a,0x15, 0x3f,0x2a,0x3f,
0x15,0x15,0x00, 0x15,0x15,0x2a, 0x15,0x3f,0x00, 0x15,0x3f,0x2a, 0x3f,0x15,0x00, 0x3f,0x15,0x2a, 0x3f,0x3f,0x00, 0x3f,0x3f,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
};
static Bit8u palette1[63+1][3]=
static Bit8u ega_palette[64][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},
{0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
@ -140,220 +68,415 @@ static Bit8u palette1[63+1][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}
};
static Bit8u palette2[63+1][3]=
static Bit8u vga_palette[256][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},
{0x00,0x00,0x15}, {0x00,0x00,0x3f}, {0x00,0x2a,0x15}, {0x00,0x2a,0x3f}, {0x2a,0x00,0x15}, {0x2a,0x00,0x3f}, {0x2a,0x2a,0x15}, {0x2a,0x2a,0x3f},
{0x00,0x15,0x00}, {0x00,0x15,0x2a}, {0x00,0x3f,0x00}, {0x00,0x3f,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x15,0x2a}, {0x2a,0x3f,0x00}, {0x2a,0x3f,0x2a},
{0x00,0x15,0x15}, {0x00,0x15,0x3f}, {0x00,0x3f,0x15}, {0x00,0x3f,0x3f}, {0x2a,0x15,0x15}, {0x2a,0x15,0x3f}, {0x2a,0x3f,0x15}, {0x2a,0x3f,0x3f},
{0x15,0x00,0x00}, {0x15,0x00,0x2a}, {0x15,0x2a,0x00}, {0x15,0x2a,0x2a}, {0x3f,0x00,0x00}, {0x3f,0x00,0x2a}, {0x3f,0x2a,0x00}, {0x3f,0x2a,0x2a},
{0x15,0x00,0x15}, {0x15,0x00,0x3f}, {0x15,0x2a,0x15}, {0x15,0x2a,0x3f}, {0x3f,0x00,0x15}, {0x3f,0x00,0x3f}, {0x3f,0x2a,0x15}, {0x3f,0x2a,0x3f},
{0x15,0x15,0x00}, {0x15,0x15,0x2a}, {0x15,0x3f,0x00}, {0x15,0x3f,0x2a}, {0x3f,0x15,0x00}, {0x3f,0x15,0x2a}, {0x3f,0x3f,0x00}, {0x3f,0x3f,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}
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,
0x00,0x00,0x00, 0x05,0x05,0x05, 0x08,0x08,0x08, 0x0b,0x0b,0x0b, 0x0e,0x0e,0x0e, 0x11,0x11,0x11, 0x14,0x14,0x14, 0x18,0x18,0x18,
0x1c,0x1c,0x1c, 0x20,0x20,0x20, 0x24,0x24,0x24, 0x28,0x28,0x28, 0x2d,0x2d,0x2d, 0x32,0x32,0x32, 0x38,0x38,0x38, 0x3f,0x3f,0x3f,
0x00,0x00,0x3f, 0x10,0x00,0x3f, 0x1f,0x00,0x3f, 0x2f,0x00,0x3f, 0x3f,0x00,0x3f, 0x3f,0x00,0x2f, 0x3f,0x00,0x1f, 0x3f,0x00,0x10,
0x3f,0x00,0x00, 0x3f,0x10,0x00, 0x3f,0x1f,0x00, 0x3f,0x2f,0x00, 0x3f,0x3f,0x00, 0x2f,0x3f,0x00, 0x1f,0x3f,0x00, 0x10,0x3f,0x00,
0x00,0x3f,0x00, 0x00,0x3f,0x10, 0x00,0x3f,0x1f, 0x00,0x3f,0x2f, 0x00,0x3f,0x3f, 0x00,0x2f,0x3f, 0x00,0x1f,0x3f, 0x00,0x10,0x3f,
0x1f,0x1f,0x3f, 0x27,0x1f,0x3f, 0x2f,0x1f,0x3f, 0x37,0x1f,0x3f, 0x3f,0x1f,0x3f, 0x3f,0x1f,0x37, 0x3f,0x1f,0x2f, 0x3f,0x1f,0x27,
0x3f,0x1f,0x1f, 0x3f,0x27,0x1f, 0x3f,0x2f,0x1f, 0x3f,0x37,0x1f, 0x3f,0x3f,0x1f, 0x37,0x3f,0x1f, 0x2f,0x3f,0x1f, 0x27,0x3f,0x1f,
0x1f,0x3f,0x1f, 0x1f,0x3f,0x27, 0x1f,0x3f,0x2f, 0x1f,0x3f,0x37, 0x1f,0x3f,0x3f, 0x1f,0x37,0x3f, 0x1f,0x2f,0x3f, 0x1f,0x27,0x3f,
0x2d,0x2d,0x3f, 0x31,0x2d,0x3f, 0x36,0x2d,0x3f, 0x3a,0x2d,0x3f, 0x3f,0x2d,0x3f, 0x3f,0x2d,0x3a, 0x3f,0x2d,0x36, 0x3f,0x2d,0x31,
0x3f,0x2d,0x2d, 0x3f,0x31,0x2d, 0x3f,0x36,0x2d, 0x3f,0x3a,0x2d, 0x3f,0x3f,0x2d, 0x3a,0x3f,0x2d, 0x36,0x3f,0x2d, 0x31,0x3f,0x2d,
0x2d,0x3f,0x2d, 0x2d,0x3f,0x31, 0x2d,0x3f,0x36, 0x2d,0x3f,0x3a, 0x2d,0x3f,0x3f, 0x2d,0x3a,0x3f, 0x2d,0x36,0x3f, 0x2d,0x31,0x3f,
0x00,0x00,0x1c, 0x07,0x00,0x1c, 0x0e,0x00,0x1c, 0x15,0x00,0x1c, 0x1c,0x00,0x1c, 0x1c,0x00,0x15, 0x1c,0x00,0x0e, 0x1c,0x00,0x07,
0x1c,0x00,0x00, 0x1c,0x07,0x00, 0x1c,0x0e,0x00, 0x1c,0x15,0x00, 0x1c,0x1c,0x00, 0x15,0x1c,0x00, 0x0e,0x1c,0x00, 0x07,0x1c,0x00,
0x00,0x1c,0x00, 0x00,0x1c,0x07, 0x00,0x1c,0x0e, 0x00,0x1c,0x15, 0x00,0x1c,0x1c, 0x00,0x15,0x1c, 0x00,0x0e,0x1c, 0x00,0x07,0x1c,
0x0e,0x0e,0x1c, 0x11,0x0e,0x1c, 0x15,0x0e,0x1c, 0x18,0x0e,0x1c, 0x1c,0x0e,0x1c, 0x1c,0x0e,0x18, 0x1c,0x0e,0x15, 0x1c,0x0e,0x11,
0x1c,0x0e,0x0e, 0x1c,0x11,0x0e, 0x1c,0x15,0x0e, 0x1c,0x18,0x0e, 0x1c,0x1c,0x0e, 0x18,0x1c,0x0e, 0x15,0x1c,0x0e, 0x11,0x1c,0x0e,
0x0e,0x1c,0x0e, 0x0e,0x1c,0x11, 0x0e,0x1c,0x15, 0x0e,0x1c,0x18, 0x0e,0x1c,0x1c, 0x0e,0x18,0x1c, 0x0e,0x15,0x1c, 0x0e,0x11,0x1c,
0x14,0x14,0x1c, 0x16,0x14,0x1c, 0x18,0x14,0x1c, 0x1a,0x14,0x1c, 0x1c,0x14,0x1c, 0x1c,0x14,0x1a, 0x1c,0x14,0x18, 0x1c,0x14,0x16,
0x1c,0x14,0x14, 0x1c,0x16,0x14, 0x1c,0x18,0x14, 0x1c,0x1a,0x14, 0x1c,0x1c,0x14, 0x1a,0x1c,0x14, 0x18,0x1c,0x14, 0x16,0x1c,0x14,
0x14,0x1c,0x14, 0x14,0x1c,0x16, 0x14,0x1c,0x18, 0x14,0x1c,0x1a, 0x14,0x1c,0x1c, 0x14,0x1a,0x1c, 0x14,0x18,0x1c, 0x14,0x16,0x1c,
0x00,0x00,0x10, 0x04,0x00,0x10, 0x08,0x00,0x10, 0x0c,0x00,0x10, 0x10,0x00,0x10, 0x10,0x00,0x0c, 0x10,0x00,0x08, 0x10,0x00,0x04,
0x10,0x00,0x00, 0x10,0x04,0x00, 0x10,0x08,0x00, 0x10,0x0c,0x00, 0x10,0x10,0x00, 0x0c,0x10,0x00, 0x08,0x10,0x00, 0x04,0x10,0x00,
0x00,0x10,0x00, 0x00,0x10,0x04, 0x00,0x10,0x08, 0x00,0x10,0x0c, 0x00,0x10,0x10, 0x00,0x0c,0x10, 0x00,0x08,0x10, 0x00,0x04,0x10,
0x08,0x08,0x10, 0x0a,0x08,0x10, 0x0c,0x08,0x10, 0x0e,0x08,0x10, 0x10,0x08,0x10, 0x10,0x08,0x0e, 0x10,0x08,0x0c, 0x10,0x08,0x0a,
0x10,0x08,0x08, 0x10,0x0a,0x08, 0x10,0x0c,0x08, 0x10,0x0e,0x08, 0x10,0x10,0x08, 0x0e,0x10,0x08, 0x0c,0x10,0x08, 0x0a,0x10,0x08,
0x08,0x10,0x08, 0x08,0x10,0x0a, 0x08,0x10,0x0c, 0x08,0x10,0x0e, 0x08,0x10,0x10, 0x08,0x0e,0x10, 0x08,0x0c,0x10, 0x08,0x0a,0x10,
0x0b,0x0b,0x10, 0x0c,0x0b,0x10, 0x0d,0x0b,0x10, 0x0f,0x0b,0x10, 0x10,0x0b,0x10, 0x10,0x0b,0x0f, 0x10,0x0b,0x0d, 0x10,0x0b,0x0c,
0x10,0x0b,0x0b, 0x10,0x0c,0x0b, 0x10,0x0d,0x0b, 0x10,0x0f,0x0b, 0x10,0x10,0x0b, 0x0f,0x10,0x0b, 0x0d,0x10,0x0b, 0x0c,0x10,0x0b,
0x0b,0x10,0x0b, 0x0b,0x10,0x0c, 0x0b,0x10,0x0d, 0x0b,0x10,0x0f, 0x0b,0x10,0x10, 0x0b,0x0f,0x10, 0x0b,0x0d,0x10, 0x0b,0x0c,0x10,
0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00
};
static Bit8u palette3[256][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},
{0x00,0x00,0x00}, {0x05,0x05,0x05}, {0x08,0x08,0x08}, {0x0b,0x0b,0x0b}, {0x0e,0x0e,0x0e}, {0x11,0x11,0x11}, {0x14,0x14,0x14}, {0x18,0x18,0x18},
{0x1c,0x1c,0x1c}, {0x20,0x20,0x20}, {0x24,0x24,0x24}, {0x28,0x28,0x28}, {0x2d,0x2d,0x2d}, {0x32,0x32,0x32}, {0x38,0x38,0x38}, {0x3f,0x3f,0x3f},
{0x00,0x00,0x3f}, {0x10,0x00,0x3f}, {0x1f,0x00,0x3f}, {0x2f,0x00,0x3f}, {0x3f,0x00,0x3f}, {0x3f,0x00,0x2f}, {0x3f,0x00,0x1f}, {0x3f,0x00,0x10},
{0x3f,0x00,0x00}, {0x3f,0x10,0x00}, {0x3f,0x1f,0x00}, {0x3f,0x2f,0x00}, {0x3f,0x3f,0x00}, {0x2f,0x3f,0x00}, {0x1f,0x3f,0x00}, {0x10,0x3f,0x00},
{0x00,0x3f,0x00}, {0x00,0x3f,0x10}, {0x00,0x3f,0x1f}, {0x00,0x3f,0x2f}, {0x00,0x3f,0x3f}, {0x00,0x2f,0x3f}, {0x00,0x1f,0x3f}, {0x00,0x10,0x3f},
{0x1f,0x1f,0x3f}, {0x27,0x1f,0x3f}, {0x2f,0x1f,0x3f}, {0x37,0x1f,0x3f}, {0x3f,0x1f,0x3f}, {0x3f,0x1f,0x37}, {0x3f,0x1f,0x2f}, {0x3f,0x1f,0x27},
VideoModeBlock * CurMode;
{0x3f,0x1f,0x1f}, {0x3f,0x27,0x1f}, {0x3f,0x2f,0x1f}, {0x3f,0x37,0x1f}, {0x3f,0x3f,0x1f}, {0x37,0x3f,0x1f}, {0x2f,0x3f,0x1f}, {0x27,0x3f,0x1f},
{0x1f,0x3f,0x1f}, {0x1f,0x3f,0x27}, {0x1f,0x3f,0x2f}, {0x1f,0x3f,0x37}, {0x1f,0x3f,0x3f}, {0x1f,0x37,0x3f}, {0x1f,0x2f,0x3f}, {0x1f,0x27,0x3f},
{0x2d,0x2d,0x3f}, {0x31,0x2d,0x3f}, {0x36,0x2d,0x3f}, {0x3a,0x2d,0x3f}, {0x3f,0x2d,0x3f}, {0x3f,0x2d,0x3a}, {0x3f,0x2d,0x36}, {0x3f,0x2d,0x31},
{0x3f,0x2d,0x2d}, {0x3f,0x31,0x2d}, {0x3f,0x36,0x2d}, {0x3f,0x3a,0x2d}, {0x3f,0x3f,0x2d}, {0x3a,0x3f,0x2d}, {0x36,0x3f,0x2d}, {0x31,0x3f,0x2d},
{0x2d,0x3f,0x2d}, {0x2d,0x3f,0x31}, {0x2d,0x3f,0x36}, {0x2d,0x3f,0x3a}, {0x2d,0x3f,0x3f}, {0x2d,0x3a,0x3f}, {0x2d,0x36,0x3f}, {0x2d,0x31,0x3f},
{0x00,0x00,0x1c}, {0x07,0x00,0x1c}, {0x0e,0x00,0x1c}, {0x15,0x00,0x1c}, {0x1c,0x00,0x1c}, {0x1c,0x00,0x15}, {0x1c,0x00,0x0e}, {0x1c,0x00,0x07},
{0x1c,0x00,0x00}, {0x1c,0x07,0x00}, {0x1c,0x0e,0x00}, {0x1c,0x15,0x00}, {0x1c,0x1c,0x00}, {0x15,0x1c,0x00}, {0x0e,0x1c,0x00}, {0x07,0x1c,0x00},
{0x00,0x1c,0x00}, {0x00,0x1c,0x07}, {0x00,0x1c,0x0e}, {0x00,0x1c,0x15}, {0x00,0x1c,0x1c}, {0x00,0x15,0x1c}, {0x00,0x0e,0x1c}, {0x00,0x07,0x1c},
{0x0e,0x0e,0x1c}, {0x11,0x0e,0x1c}, {0x15,0x0e,0x1c}, {0x18,0x0e,0x1c}, {0x1c,0x0e,0x1c}, {0x1c,0x0e,0x18}, {0x1c,0x0e,0x15}, {0x1c,0x0e,0x11},
{0x1c,0x0e,0x0e}, {0x1c,0x11,0x0e}, {0x1c,0x15,0x0e}, {0x1c,0x18,0x0e}, {0x1c,0x1c,0x0e}, {0x18,0x1c,0x0e}, {0x15,0x1c,0x0e}, {0x11,0x1c,0x0e},
{0x0e,0x1c,0x0e}, {0x0e,0x1c,0x11}, {0x0e,0x1c,0x15}, {0x0e,0x1c,0x18}, {0x0e,0x1c,0x1c}, {0x0e,0x18,0x1c}, {0x0e,0x15,0x1c}, {0x0e,0x11,0x1c},
{0x14,0x14,0x1c}, {0x16,0x14,0x1c}, {0x18,0x14,0x1c}, {0x1a,0x14,0x1c}, {0x1c,0x14,0x1c}, {0x1c,0x14,0x1a}, {0x1c,0x14,0x18}, {0x1c,0x14,0x16},
{0x1c,0x14,0x14}, {0x1c,0x16,0x14}, {0x1c,0x18,0x14}, {0x1c,0x1a,0x14}, {0x1c,0x1c,0x14}, {0x1a,0x1c,0x14}, {0x18,0x1c,0x14}, {0x16,0x1c,0x14},
{0x14,0x1c,0x14}, {0x14,0x1c,0x16}, {0x14,0x1c,0x18}, {0x14,0x1c,0x1a}, {0x14,0x1c,0x1c}, {0x14,0x1a,0x1c}, {0x14,0x18,0x1c}, {0x14,0x16,0x1c},
{0x00,0x00,0x10}, {0x04,0x00,0x10}, {0x08,0x00,0x10}, {0x0c,0x00,0x10}, {0x10,0x00,0x10}, {0x10,0x00,0x0c}, {0x10,0x00,0x08}, {0x10,0x00,0x04},
{0x10,0x00,0x00}, {0x10,0x04,0x00}, {0x10,0x08,0x00}, {0x10,0x0c,0x00}, {0x10,0x10,0x00}, {0x0c,0x10,0x00}, {0x08,0x10,0x00}, {0x04,0x10,0x00},
{0x00,0x10,0x00}, {0x00,0x10,0x04}, {0x00,0x10,0x08}, {0x00,0x10,0x0c}, {0x00,0x10,0x10}, {0x00,0x0c,0x10}, {0x00,0x08,0x10}, {0x00,0x04,0x10},
{0x08,0x08,0x10}, {0x0a,0x08,0x10}, {0x0c,0x08,0x10}, {0x0e,0x08,0x10}, {0x10,0x08,0x10}, {0x10,0x08,0x0e}, {0x10,0x08,0x0c}, {0x10,0x08,0x0a},
{0x10,0x08,0x08}, {0x10,0x0a,0x08}, {0x10,0x0c,0x08}, {0x10,0x0e,0x08}, {0x10,0x10,0x08}, {0x0e,0x10,0x08}, {0x0c,0x10,0x08}, {0x0a,0x10,0x08},
{0x08,0x10,0x08}, {0x08,0x10,0x0a}, {0x08,0x10,0x0c}, {0x08,0x10,0x0e}, {0x08,0x10,0x10}, {0x08,0x0e,0x10}, {0x08,0x0c,0x10}, {0x08,0x0a,0x10},
{0x0b,0x0b,0x10}, {0x0c,0x0b,0x10}, {0x0d,0x0b,0x10}, {0x0f,0x0b,0x10}, {0x10,0x0b,0x10}, {0x10,0x0b,0x0f}, {0x10,0x0b,0x0d}, {0x10,0x0b,0x0c},
{0x10,0x0b,0x0b}, {0x10,0x0c,0x0b}, {0x10,0x0d,0x0b}, {0x10,0x0f,0x0b}, {0x10,0x10,0x0b}, {0x0f,0x10,0x0b}, {0x0d,0x10,0x0b}, {0x0c,0x10,0x0b},
{0x0b,0x10,0x0b}, {0x0b,0x10,0x0c}, {0x0b,0x10,0x0d}, {0x0b,0x10,0x0f}, {0x0b,0x10,0x10}, {0x0b,0x0f,0x10}, {0x0b,0x0d,0x10}, {0x0b,0x0c,0x10},
{0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}, {0x00,0x00,0x00}
};
static Bit8u FindVideoMode(Bit8u mode) {
Bit8u line=0xff;
for(Bit8u i=0;i<=MODE_MAX;i++) {
if(vga_modes[i].svgamode==mode) {
line=i;
break;
}
}
return line;
}
VGAMODES * GetCurrentMode(void) {
Bit8u mode=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)&127;
if (mode==int10.mode) return int10.entry;
int10.mode=mode;
int10.entry=&vga_modes[FindVideoMode(mode)];
return int10.entry;
}
bool INT10_SetVideoMode(Bitu mode) {
void INT10_SetVideoMode(Bit8u mode) {
bool clearmem=(mode & 128)==0;
Bit8u *palette;
Bit16u i,twidth,theight,cheight;
bool clearmem=true;
Bit8u modeset_ctl,video_ctl,vga_switches;
Bit16u crtc_addr;
Bit8u line;
mode&=mode & 127;
line=FindVideoMode(mode);
if (line==0xff) {
LOG(LOG_INT10,LOG_ERROR)("INT10:Trying to set non supported video mode %X",mode);
return;
if (mode<256) {
if (mode & 128) {
clearmem=false;
mode-=128;
}
} else {
/* Check for special vesa mode bits */
mode&=0xfff;
}
twidth=vga_modes[line].twidth;
theight=vga_modes[line].theight;
cheight=vga_modes[line].cheight;
// Read the bios vga control
LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode);
Bitu i=0;
while (ModeList[i].mode!=0xffff) {
if (ModeList[i].mode==mode) goto foundmode;
i++;
}
LOG(LOG_INT10,LOG_ERROR)("Trying to set illegal mode %X",mode);
return false;
foundmode:
CurMode=&ModeList[i];
/* First read mode setup settings from bios area */
video_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
// Read the bios vga switches
vga_switches=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES);
// Read the bios mode set control
modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
/* Setup the VGA to the correct mode */
VGA_SetMode(CurMode->type);
/* Reset Attribute ctl into address mode just to be safe */
IO_Read(VGAREG_ACTL_RESET);
// Set the High Attribute Ctl
for(i=0x10;i<=ACTL_MAX_REG;i++) {
IO_Write(VGAREG_ACTL_ADDRESS,(Bit8u)i);
IO_Write(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
/* Setup MISC Output Register */
Bit8u misc_output=0x3; //Color and cpu memory access
/* Program Sequencer */
Bit8u seq_data[SEQ_REGS];
memset(seq_data,0,SEQ_REGS);
seq_data[1]|=1; //8 dot fonts by default
seq_data[1]|= //Check for half clock
(CurMode->special & _HALF_CLOCK) ? 0x08 : 0x00;
seq_data[4]|=0x02; //More than 64kb
switch (CurMode->type) {
case M_TEXT16:
seq_data[2]|=0x3; //Enable plane 0 and 1
seq_data[4]|=0x05; //Alpanumeric and odd/even enabled
break;
case M_EGA16:
seq_data[2]|=0xf; //Enable all planes for writing
break;
case M_LIN8: //Seems to have the same reg layout from testing
case M_VGA:
seq_data[2]|=0xf; //Enable all planes for writing
seq_data[4]|=0xc; //Graphics - odd/even - Chained
break;
}
// Set Sequencer Ctl
for(i=0;i<=SEQU_MAX_REG;i++) {
IO_Write(VGAREG_SEQU_ADDRESS,(Bit8u)i);
IO_Write(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
for (i=0;i<SEQ_REGS;i++) {
IO_Write(0x3c4,i);
IO_Write(0x3c5,seq_data[i]);
}
// Set Grafx Ctl
for(i=0;i<=GRDC_MAX_REG;i++) {
IO_Write(VGAREG_GRDC_ADDRESS,(Bit8u)i);
IO_Write(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
/* Program CRTC */
/* First disable write protection */
IO_Write(0x3d4,0x11);
IO_Write(0x3d5,IO_Read(0x3d5)&0x7f);
/* Clear all the regs */
for (i=0x0;i<=0x18;i++) {
IO_Write(0x3d4,i);IO_Write(0x3d5,0);
}
// Set CRTC address VGA or MDA
crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
// Set CRTC regs
for(i=0;i<=CRTC_MAX_REG;i++) {
IO_Write(crtc_addr,(Bit8u)i);
IO_Write(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
Bit8u overflow=0;Bit8u max_scanline=0;
Bit8u ver_overflow=0;Bit8u hor_overflow=0;
/* Horizontal Total */
IO_Write(0x3d4,0x00);IO_Write(0x3d5,CurMode->htotal-5);
hor_overflow|=((CurMode->htotal-5) & 0x100) >> 8;
/* Horizontal Display End */
IO_Write(0x3d4,0x01);IO_Write(0x3d5,CurMode->hdispend-1);
hor_overflow|=((CurMode->hdispend-1) & 0x100) >> 7;
/* Start horizontal Blanking */
IO_Write(0x3d4,0x02);IO_Write(0x3d5,CurMode->hdispend);
hor_overflow|=((CurMode->hdispend) & 0x100) >> 6;
/* End horizontal Blanking */
Bitu blank_end;
if (CurMode->special & _HALF_CLOCK) {
blank_end = (CurMode->htotal-1) & 0x7f;
} else {
blank_end = (CurMode->htotal-2) & 0x7f;
}
IO_Write(0x3d4,0x03);IO_Write(0x3d5,0x80|(blank_end & 0x1f));
// hor_overflow|=(blank_end & 0x40) >> 3;
// Set the misc register
IO_Write(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
// Enable video
IO_Write(VGAREG_ACTL_ADDRESS,0x20);
IO_Read(VGAREG_ACTL_RESET);
//Set the palette
if ((modeset_ctl&0x08)==0x8) LOG(LOG_INT10,LOG_NORMAL)("Mode set without palette");
if((modeset_ctl&0x08)==0) {
// Set the PEL mask
IO_Write(VGAREG_PEL_MASK,vga_modes[line].pelmask);
// Set the whole dac always, from 0
IO_Write(VGAREG_DAC_WRITE_ADDRESS,0x00);
// From which palette
switch(vga_modes[line].dacmodel) {
case 0:
palette=(Bit8u*)&palette0;
break;
case 1:
palette=(Bit8u*)&palette1;
break;
case 2:
palette=(Bit8u*)&palette2;
break;
case 3:
palette=(Bit8u*)&palette3;
break;
default:
palette=(Bit8u*)&palette0;/*for gcc*/
E_Exit("INT10: palette error in setvidmode");
break;
}
// Set the actual palette
for (i=0;i<256;i++) {
if (i<=dac_regs[vga_modes[line].dacmodel]) {
IO_Write(VGAREG_DAC_DATA,palette[(i*3)+0]);
IO_Write(VGAREG_DAC_DATA,palette[(i*3)+1]);
IO_Write(VGAREG_DAC_DATA,palette[(i*3)+2]);
} else {
IO_Write(VGAREG_DAC_DATA,0);
IO_Write(VGAREG_DAC_DATA,0);
IO_Write(VGAREG_DAC_DATA,0);
}
}
/* Start Horizontal Retrace */
Bitu ret_start;
if (CurMode->special & _HALF_CLOCK) {
ret_start = (CurMode->hdispend+2);
} else {
ret_start = (CurMode->hdispend+4);
}
IO_Read(VGAREG_ACTL_RESET);
// Set the Low Attribute Ctl
for(i=0;i<=0xf;i++) {
IO_Write(VGAREG_ACTL_ADDRESS,(Bit8u)i);
IO_Write(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
IO_Write(0x3d4,0x04);IO_Write(0x3d5,ret_start);
hor_overflow|=(ret_start & 0x100) >> 4;
/* End Horizontal Retrace */
Bitu ret_end;
if (CurMode->special & _HALF_CLOCK) {
ret_end = (CurMode->htotal-2) & 0x3f;
} else {
ret_end = (CurMode->htotal-4) & 0x3f;
}
IO_Write(0x3d4,0x05);IO_Write(0x3d5,(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(0x3d4,0x06);IO_Write(0x3d5,(CurMode->vtotal-2));
overflow|=((CurMode->vtotal-2) & 0x100) >> 8;
overflow|=((CurMode->vtotal-2) & 0x200) >> 4;
ver_overflow|=((CurMode->vtotal-2) & 0x400) >> 10;
/*
These aren't exactly accurate i think,
Should be more like a certain percentage based on vertical total
So you get same sized borders, but okay :)
*/
/* Vertical Retrace Start */
IO_Write(0x3d4,0x10);IO_Write(0x3d5,(CurMode->vdispend+12));
overflow|=((CurMode->vdispend+12) & 0x100) >> 6;
overflow|=((CurMode->vdispend+12) & 0x200) >> 2;
ver_overflow|=((CurMode->vdispend+12) & 0x400) >> 6;
/* Vertical Retrace End */
IO_Write(0x3d4,0x11);IO_Write(0x3d5,(CurMode->vdispend+14) & 0xF);
/* Vertical Display End */
IO_Write(0x3d4,0x12);IO_Write(0x3d5,(CurMode->vdispend-1));
overflow|=((CurMode->vdispend-1) & 0x100) >> 7;
overflow|=((CurMode->vdispend-1) & 0x200) >> 3;
ver_overflow|=((CurMode->vdispend-1) & 0x400) >> 9;
Bit32u tel;
if(clearmem) {
if(vga_modes[line].type==TEXT) {
PhysPt dest=PhysMake(vga_modes[line].sstart,0);
for (tel=0;tel<0x4000;tel++) {
mem_writew(dest,0x0720);
dest+=2;
/* Vertical Blank Start */
IO_Write(0x3d4,0x15);IO_Write(0x3d5,(CurMode->vdispend+8));
overflow|=((CurMode->vdispend+8) & 0x100) >> 5;
max_scanline|=((CurMode->vdispend+8) & 0x200) >> 3;
ver_overflow|=((CurMode->vdispend+8) & 0x400) >> 8;
/* Vertical Retrace End */
IO_Write(0x3d4,0x16);IO_Write(0x3d5,(CurMode->vtotal-8));
/* Line Compare */
Bitu line_compare=CurMode->vtotal+1; //Out of range
IO_Write(0x3d4,0x18);IO_Write(0x3d5,line_compare&0xff);
overflow|=(line_compare & 0x100) >> 4;
max_scanline|=(line_compare & 0x200) >> 3;
ver_overflow|=(line_compare & 0x400) >> 4;
Bit8u underline=0;
/* Maximum scanline / Underline Location */
if (CurMode->special & _LINE_DOUBLE) max_scanline|=0x80;
switch (CurMode->type) {
case M_TEXT16:
max_scanline|=CurMode->theight-1;
underline=0x1f;
break;
case M_VGA:
underline=0x40;
max_scanline|=1; //Vga doesn't use double line but this
break;
case M_LIN8:
underline=0x60; //Seems to enable the every 4th clock on my s3
break;
}
IO_Write(0x3d4,0x09);IO_Write(0x3d5,max_scanline);
IO_Write(0x3d4,0x14);IO_Write(0x3d5,underline);
/* OverFlow */
IO_Write(0x3d4,0x07);IO_Write(0x3d5,overflow);
/* Extended Horizontal Overflow */
IO_Write(0x3d4,0x5d);IO_Write(0x3d5,hor_overflow);
/* Extended Vertical Overflow */
IO_Write(0x3d4,0x5e);IO_Write(0x3d5,ver_overflow);
/* Offset Register */
IO_Write(0x3d4,0x13);
switch (CurMode->type) {
case M_LIN8:
IO_Write(0x3d5,CurMode->swidth/8);
break;
default:
IO_Write(0x3d5,CurMode->hdispend/2);
}
/* Mode Control */
Bit8u mode_control=0;
switch (CurMode->type) {
case M_CGA4:
case M_CGA2:
mode_control=0xa2;
break;
case M_EGA16:
mode_control=0xe3;
break;
case M_TEXT16:
case M_VGA:
mode_control=0xa3;
break;
case M_LIN8:
mode_control=0xab;
break;
}
IO_Write(0x3d4,0x17);IO_Write(0x3d5,mode_control);
/* Renable write protection */
IO_Write(0x3d4,0x11);
IO_Write(0x3d5,IO_Read(0x3d5)|0x80);
/* Setup the correct clock */
if (CurMode->mode<0x100) {
//Stick to 25mhz clock for now
} else {
misc_output|=0xef; //Select clock 3
Bitu clock=CurMode->vtotal*8*CurMode->htotal*70;
VGA_SetClock(3,clock/1000);
}
/* Write Misc Output */
IO_Write(0x3c2,misc_output);
/* Program Graphics controller */
Bit8u gfx_data[GFX_REGS];
memset(gfx_data,0,GFX_REGS);
gfx_data[0x7]=0xf; /* Color don't care */
gfx_data[0x8]=0xff; /* BitMask */
switch (CurMode->type) {
case M_TEXT16:
gfx_data[0x5]|=0x10; //Odd-Even Mode
gfx_data[0x6]|=0x0e; //alphanumeric mode at 0xb800=0xbffff
break;
case M_LIN8:
case M_VGA:
gfx_data[0x5]|=0x40; //256 color mode
gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff
break;
case M_EGA16:
gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff
break;
case M_CGA4:
gfx_data[0x5]|=0x20; //CGA mode
gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff
break;
}
for (i=0;i<GFX_REGS;i++) {
IO_Write(0x3ce,i);
IO_Write(0x3cf,gfx_data[i]);
}
Bit8u att_data[ATT_REGS];
memset(att_data,0,ATT_REGS);
att_data[0x12]=0xf; //Always have all color planes enabled
/* Porgram Attribute Controller */
switch (CurMode->type) {
case M_EGA16:
if (CurMode->mode>0xe) goto att_text16;
case M_TANDY16:
att_data[0x10]=0x01; //Color Graphics
for (i=0;i<8;i++) {
att_data[i]=i;
att_data[i+8]=i+0x10;
}
break;
case M_TEXT16:
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:
for (i=0;i<8;i++) {
att_data[i]=i;
att_data[i+8]=i+0x38;
}
break;
case M_CGA2:
case M_CGA4:
IO_Write(0x3d9,0x20); //Setup using CGA color select register
goto skipatt;
case M_VGA:
case M_LIN8:
for (i=0;i<16;i++) {
att_data[i]=i;
}
att_data[0x10]=0x41; //Color Graphics 8-bit
break;
}
IO_Read(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) {
case M_EGA16:
if (CurMode->mode>0xe) goto dac_text16;
case M_CGA2:
case M_CGA4:
case M_TANDY16:
for (i=0;i<64;i++) {
IO_Write(0x3c9,ega_palette[i][0]);
IO_Write(0x3c9,ega_palette[i][1]);
IO_Write(0x3c9,ega_palette[i][2]);
}
break;
case M_TEXT16:
dac_text16:
for (i=0;i<64;i++) {
IO_Write(0x3c9,text_palette[i][0]);
IO_Write(0x3c9,text_palette[i][1]);
IO_Write(0x3c9,text_palette[i][2]);
}
break;
case M_VGA:
case M_LIN8:
for (i=0;i<256;i++) {
IO_Write(0x3c9,vga_palette[i][0]);
IO_Write(0x3c9,vga_palette[i][1]);
IO_Write(0x3c9,vga_palette[i][2]);
}
break;
}
/* Setup registers for special video modes */
switch (CurMode->type) {
case M_TANDY16:
IO_Write(0x3df,0x80); //Enter 32k mode and banks on 0
break;
}
/* Setup some remaining S3 registers */
IO_Write(0x3d4,0x31);IO_Write(0x3d5,0x9); //Enable banked memory and 256k+ access
IO_Write(0x3d4,0x58);IO_Write(0x3d5,0x3); //Enable 8 mb of linear addressing
IO_Write(0x3d4,0x38);IO_Write(0x3d5,0x48); //Register lock 1
IO_Write(0x3d4,0x39);IO_Write(0x3d5,0xa5); //Register lock 2
/* Load text mode font */
if (CurMode->type==M_TEXT16) {
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);
}
} else {
PhysPt dest=PhysMake(0xb800,0);
for (tel=0;tel<0x4000;tel++) {
mem_writew(dest,0x0000);
dest+=2;
break;
case M_TEXT16:
for (i=0;i<16*1024;i++) {
real_writew(0xb800,i*2,0x0700);
}
dest=PhysMake(0xa000,0);
for (tel=0;tel<0x8000;tel++) {
mem_writew(dest,0x0000);
dest+=2;
break;
case M_EGA16:
case M_VGA:
for (i=0;i<64*1024;i++) {
real_writeb(0xa000,i,0x00);
}
// FIXME should handle gfx mode
break;
}
}
// Set the BIOS mem
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode|((!clearmem) << 7));
real_writew(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
real_writew(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
/* Setup the CRTC Address */
crtc_addr=0x3d4;
/* 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_addr);
real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
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);
@ -368,27 +491,23 @@ void INT10_SetVideoMode(Bit8u mode) {
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
// Set cursor shape
if(vga_modes[line].type==TEXT) {
//TODO cursor shape biosfn_set_cursor_shape(0x06,0x07);
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 */
RealSetVec(0x43,int10_romarea.font_8_first);
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_SetResolution(vga_modes[line].swidth,vga_modes[line].sheight);
};
Mouse_NewVideoMode();
return true;
}
void INT10_SetGfxControllerToDefault()
// reset gfx controller to default values
// needed for drawing mouse pointer
{
Bit8u line=FindVideoMode(real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)&127);
// Set Grafx Ctl
for(Bit8u i=0;i<=GRDC_MAX_REG;i++) {
IO_Write(VGAREG_GRDC_ADDRESS,(Bit8u)i);
IO_Write(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
}
};

View file

@ -29,6 +29,7 @@ void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val) {
IO_Write(VGAREG_ACTL_ADDRESS,reg);
IO_Write(VGAREG_ACTL_WRITE_DATA,val);
}
IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette
}
@ -36,6 +37,7 @@ void INT10_SetOverscanBorderColor(Bit8u val) {
IO_Read(VGAREG_ACTL_RESET);
IO_Write(VGAREG_ACTL_ADDRESS,0x11);
IO_Write(VGAREG_ACTL_WRITE_DATA,val);
IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette
}
void INT10_SetAllPaletteRegisters(PhysPt data) {
@ -49,6 +51,7 @@ void INT10_SetAllPaletteRegisters(PhysPt data) {
// Then the border
IO_Write(VGAREG_ACTL_ADDRESS,0x11);
IO_Write(VGAREG_ACTL_WRITE_DATA,mem_readb(data));
IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette
}
void INT10_ToggleBlinkingBit(Bit8u state) {
@ -64,19 +67,20 @@ void INT10_ToggleBlinkingBit(Bit8u state) {
IO_Read(VGAREG_ACTL_RESET);
IO_Write(VGAREG_ACTL_ADDRESS,0x10);
IO_Write(VGAREG_ACTL_WRITE_DATA,value);
IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette
}
void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val) {
if(reg<=ACTL_MAX_REG) {
IO_Read(VGAREG_ACTL_RESET);
IO_Write(VGAREG_ACTL_ADDRESS,reg);
IO_Write(VGAREG_ACTL_ADDRESS,reg+32);
*val=IO_Read(VGAREG_ACTL_READ_DATA);
}
}
void INT10_GetOverscanBorderColor(Bit8u * val) {
IO_Read(VGAREG_ACTL_RESET);
IO_Write(VGAREG_ACTL_ADDRESS,0x11);
IO_Write(VGAREG_ACTL_ADDRESS,0x11+32);
*val=IO_Read(VGAREG_ACTL_READ_DATA);
}
@ -89,7 +93,7 @@ void INT10_GetAllPaletteRegisters(PhysPt data) {
data++;
}
// Then the border
IO_Write(VGAREG_ACTL_ADDRESS,0x11);
IO_Write(VGAREG_ACTL_ADDRESS,0x11+32);
mem_writeb(data,IO_Read(VGAREG_ACTL_READ_DATA));
}
@ -123,4 +127,46 @@ void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data) {
mem_writeb(data++,IO_Read(VGAREG_DAC_DATA));
mem_writeb(data++,IO_Read(VGAREG_DAC_DATA));
}
};
}
void INT10_SelectDACPage(Bit8u function,Bit8u mode) {
IO_Read(VGAREG_ACTL_RESET);
IO_Write(VGAREG_ACTL_ADDRESS,0x10);
Bit8u old10=IO_Read(VGAREG_ACTL_READ_DATA);
if (!function) { //Select paging mode
if (mode) old10|=0x80;
else old10&=0x7f;
IO_Write(VGAREG_ACTL_ADDRESS,0x10);
IO_Write(VGAREG_ACTL_WRITE_DATA,old10);
} else { //Select page
if (!(old10 & 0x80)) mode<<=2;
mode&=0xf;
IO_Write(VGAREG_ACTL_ADDRESS,0x14);
IO_Write(VGAREG_ACTL_WRITE_DATA,mode);
}
IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette
}
void INT10_SetPelMask(Bit8u mask) {
IO_Write(VGAREG_PEL_MASK,mask);
}
void INT10_GetPelMask(Bit8u & mask) {
mask=IO_Read(VGAREG_PEL_MASK);
}
void INT10_SetBackgroundBorder(Bit8u val) {
//TODO Detect if we're CGA?
Bit8u old=IO_Read(0x3d9) & 0xf0;
old|=val & 0xf;
IO_Write(0x3d9,old);
}
void INT10_SetColorSelect(Bit8u val) {
//TODO Detect if we're CGA?
Bit8u old=IO_Read(0x3d9) & ~0x20;
old|=(val & 1) << 5;
IO_Write(0x3d9,old);
}

View file

@ -25,9 +25,8 @@ static Bit8u cga_masks[4]={~192,~48,~12,~3};
static Bit8u cga_masks2[8]={~128,~64,~32,~16,~8,~4,~2,~1};
void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
VGAMODES * curmode=GetCurrentMode();
switch (curmode->memmodel) {
case CGA:
switch (CurMode->type) {
case M_CGA4:
{
Bit16u off=(y>>1)*80+(x>>2);
if (y&1) off+=8*1024;
@ -41,7 +40,7 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
real_writeb(0xb800,off,old);
}
break;
case CGA2:
case M_CGA2:
{
Bit16u off=(y>>1)*80+(x>>3);
if (y&1) off+=8*1024;
@ -55,7 +54,7 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
real_writeb(0xb800,off,old);
}
break;
case PLANAR4:
case M_EGA16:
{
/* Set the correct bitmask for the pixel position */
IO_Write(0x3ce,0x8);Bit8u mask=128>>(x&7);IO_Write(0x3cf,mask);
@ -67,7 +66,7 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x18); }
//Perhaps also set mode 1
/* Calculate where the pixel is in video memory */
PhysPt off=0xa0000+curmode->slength*page+((y*curmode->swidth+x)>>3);
PhysPt off=0xa0000+CurMode->plength*page+((y*CurMode->swidth+x)>>3);
/* Bitmask and set/reset should do the rest */
mem_readb(off);
mem_writeb(off,0xff);
@ -78,23 +77,18 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x0); }
break;
}
case LINEAR8:
case M_VGA:
mem_writeb(Real2Phys(RealMake(0xa000,y*320+x)),color);
break;
case PLANAR1:
case PLANAR2:
case CTEXT:
case MTEXT:
default:
LOG(LOG_INT10,LOG_ERROR)("PutPixel Unhandled memory model %d",curmode->memmodel);
LOG(LOG_INT10,LOG_ERROR)("PutPixel unhandled mode type %d",CurMode->type);
break;
}
}
void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) {
VGAMODES * curmode=GetCurrentMode();
switch (curmode->memmodel) {
case CGA:
switch (CurMode->type) {
case M_CGA4:
{
Bit16u off=(y>>1)*80+(x>>2);
if (y&1) off+=8*1024;
@ -102,7 +96,7 @@ void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) {
*color=(val>>(((3-x&3))*2)) & 3 ;
}
break;
case CGA2:
case M_CGA2:
{
Bit16u off=(y>>1)*80+(x>>3);
if (y&1) off+=8*1024;
@ -110,10 +104,10 @@ void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) {
*color=(val>>(((7-x&7)))) & 1 ;
}
break;
case PLANAR4:
case M_EGA16:
{
/* Calculate where the pixel is in video memory */
PhysPt off=0xa0000+curmode->slength*page+((y*curmode->swidth+x)>>3);
PhysPt off=0xa0000+CurMode->plength*page+((y*CurMode->swidth+x)>>3);
Bitu shift=7-(x & 7);
/* Set the read map */
*color=0;
@ -127,15 +121,11 @@ void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) {
*color|=((mem_readb(off)>>shift) & 1) << 3;
break;
}
case LINEAR8:
case M_VGA:
*color=mem_readb(PhysMake(0xa000,320*y+x));
break;
case PLANAR1:
case PLANAR2:
case CTEXT:
case MTEXT:
default:
LOG(LOG_INT10,LOG_ERROR)("GetPixel Unhandled memory model %d",curmode->memmodel);
LOG(LOG_INT10,LOG_ERROR)("GetPixel unhandled mode type %d",CurMode->type);
break;
}
}