VESA patch:
- implement text mode support, add modes 108h through 10Ch - adjust the S3 text modes to the values found on real hardware - added defines for VESA return values - rewrite get/set scanlength and set display start for completeness - catch a possible division by zero, part of SF patch 3154782, thanks Daniel Richard G. - align display page sizes to 64k for compatibility Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3684
This commit is contained in:
parent
d97aade01a
commit
5d865dafc8
2 changed files with 193 additions and 107 deletions
|
@ -54,8 +54,8 @@ VideoModeBlock ModeList_VGA[]={
|
|||
{ 0x012 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },
|
||||
{ 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,0 },
|
||||
|
||||
{ 0x054 ,M_TEXT ,1056,688, 132,43, 8, 16, 1 ,0xB8000 ,0x4000, 192, 800, 132,688, 0 },
|
||||
{ 0x055 ,M_TEXT ,1056,400, 132,25, 8, 16, 1 ,0xB8000 ,0x2000, 192, 449, 132,400, 0 },
|
||||
{ 0x054 ,M_TEXT ,1056,344, 132,43, 8, 8, 1 ,0xB8000 ,0x4000, 160, 449, 132,344, 0 },
|
||||
{ 0x055 ,M_TEXT ,1056,400, 132,25, 8, 16, 1 ,0xB8000 ,0x2000, 160, 449, 132,400, 0 },
|
||||
|
||||
/* Alias of mode 101 */
|
||||
{ 0x069 ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 },
|
||||
|
@ -72,6 +72,14 @@ VideoModeBlock ModeList_VGA[]={
|
|||
{ 0x106 ,M_LIN4 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0 },
|
||||
{ 0x107 ,M_LIN8 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0 },
|
||||
|
||||
/* VESA text modes */
|
||||
{ 0x108 ,M_TEXT ,640 ,480, 80,60, 8, 8 ,2 ,0xB8000 ,0x4000, 100 ,525 ,80 ,480 ,0 },
|
||||
{ 0x109 ,M_TEXT ,1056,400, 132,25, 8, 16, 1 ,0xB8000 ,0x2000, 160, 449, 132,400, 0 },
|
||||
{ 0x10A ,M_TEXT ,1056,688, 132,43, 8, 8, 1 ,0xB8000 ,0x4000, 160, 449, 132,344, 0 },
|
||||
{ 0x10B ,M_TEXT ,1056,400, 132,50, 8, 8, 1 ,0xB8000 ,0x4000, 160, 449, 132,400, 0 },
|
||||
{ 0x10C ,M_TEXT ,1056,480, 132,60, 8, 8, 2 ,0xB8000 ,0x4000, 160, 531, 132,480, 0 },
|
||||
|
||||
/* VESA higher color modes */
|
||||
{ 0x10D ,M_LIN15 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE },
|
||||
{ 0x10E ,M_LIN16 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE },
|
||||
{ 0x10F ,M_LIN32 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,50 ,449 ,40 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE },
|
||||
|
@ -81,10 +89,10 @@ VideoModeBlock ModeList_VGA[]={
|
|||
{ 0x113 ,M_LIN15 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 ,0 },
|
||||
{ 0x114 ,M_LIN16 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 ,0 },
|
||||
{ 0x115 ,M_LIN32 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 },
|
||||
|
||||
{ 0x116 ,M_LIN15 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,336 ,806 ,256,768 ,0 },
|
||||
{ 0x117 ,M_LIN16 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,336 ,806 ,256,768 ,0 },
|
||||
{ 0x118 ,M_LIN32 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 },
|
||||
|
||||
/* those should be interlaced but ok */
|
||||
//{ 0x119 ,M_LIN15 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,424 ,1066,320,1024,0 },
|
||||
//{ 0x11A ,M_LIN16 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,424 ,1066,320,1024,0 },
|
||||
|
|
|
@ -29,6 +29,13 @@
|
|||
#include "int10.h"
|
||||
#include "dos_inc.h"
|
||||
|
||||
#define VESA_SUCCESS 0x00
|
||||
#define VESA_FAIL 0x01
|
||||
#define VESA_HW_UNSUPPORTED 0x02
|
||||
#define VESA_MODE_UNSUPPORTED 0x03
|
||||
// internal definition to pass to the caller
|
||||
#define VESA_UNIMPLEMENTED 0xFF
|
||||
|
||||
static struct {
|
||||
Bitu setwindow;
|
||||
Bitu pmStart;
|
||||
|
@ -117,7 +124,7 @@ Bit8u VESA_GetSVGAInformation(Bit16u seg,Bit16u off) {
|
|||
mem_writed(buffer+0x0a,0x0); //Capabilities and flags
|
||||
mem_writed(buffer+0x0e,int10.rom.vesa_modes); //VESA Mode list
|
||||
mem_writew(buffer+0x12,(Bit16u)(vga.vmemsize/(64*1024))); // memory size in 64kb blocks
|
||||
return 0x00;
|
||||
return VESA_SUCCESS;
|
||||
}
|
||||
|
||||
Bit8u VESA_GetSVGAModeInformation(Bit16u mode,Bit16u seg,Bit16u off) {
|
||||
|
@ -136,14 +143,13 @@ Bit8u VESA_GetSVGAModeInformation(Bit16u mode,Bit16u seg,Bit16u off) {
|
|||
while (ModeList_VGA[i].mode!=0xffff) {
|
||||
if (mode==ModeList_VGA[i].mode) goto foundit; else i++;
|
||||
}
|
||||
return 0x01;
|
||||
return VESA_FAIL;
|
||||
foundit:
|
||||
if ((int10.vesa_oldvbe) && (ModeList_VGA[i].mode>=0x120)) return 0x01;
|
||||
VideoModeBlock * mblock=&ModeList_VGA[i];
|
||||
switch (mblock->type) {
|
||||
case M_LIN4:
|
||||
pageSize = mblock->sheight * mblock->swidth/2;
|
||||
pageSize = (pageSize | 15) & ~ 15;
|
||||
var_write(&minfo.BytesPerScanLine,mblock->swidth/8);
|
||||
var_write(&minfo.NumberOfPlanes,0x4);
|
||||
var_write(&minfo.BitsPerPixel,4);
|
||||
|
@ -152,7 +158,6 @@ foundit:
|
|||
break;
|
||||
case M_LIN8:
|
||||
pageSize = mblock->sheight * mblock->swidth;
|
||||
pageSize = (pageSize | 15) & ~ 15;
|
||||
var_write(&minfo.BytesPerScanLine,mblock->swidth);
|
||||
var_write(&minfo.NumberOfPlanes,0x1);
|
||||
var_write(&minfo.BitsPerPixel,8);
|
||||
|
@ -162,7 +167,6 @@ foundit:
|
|||
break;
|
||||
case M_LIN15:
|
||||
pageSize = mblock->sheight * mblock->swidth*2;
|
||||
pageSize = (pageSize | 15) & ~ 15;
|
||||
var_write(&minfo.BytesPerScanLine,mblock->swidth*2);
|
||||
var_write(&minfo.NumberOfPlanes,0x1);
|
||||
var_write(&minfo.BitsPerPixel,15);
|
||||
|
@ -180,7 +184,6 @@ foundit:
|
|||
break;
|
||||
case M_LIN16:
|
||||
pageSize = mblock->sheight * mblock->swidth*2;
|
||||
pageSize = (pageSize | 15) & ~ 15;
|
||||
var_write(&minfo.BytesPerScanLine,mblock->swidth*2);
|
||||
var_write(&minfo.NumberOfPlanes,0x1);
|
||||
var_write(&minfo.BitsPerPixel,16);
|
||||
|
@ -196,7 +199,6 @@ foundit:
|
|||
break;
|
||||
case M_LIN32:
|
||||
pageSize = mblock->sheight * mblock->swidth*4;
|
||||
pageSize = (pageSize | 15) & ~ 15;
|
||||
var_write(&minfo.BytesPerScanLine,mblock->swidth*4);
|
||||
var_write(&minfo.NumberOfPlanes,0x1);
|
||||
var_write(&minfo.BitsPerPixel,32);
|
||||
|
@ -212,36 +214,40 @@ foundit:
|
|||
modeAttributes = 0x1b; // Color, graphics
|
||||
if (!int10.vesa_nolfb) modeAttributes |= 0x80; // linear framebuffer
|
||||
break;
|
||||
/* case M_TEXT:
|
||||
pageSize = mblock->sheight/8 * mblock->swidth*2/8;
|
||||
pageSize = (pageSize | 15) & ~ 15;
|
||||
var_write(&minfo.BytesPerScanLine,mblock->swidth*2/8);
|
||||
case M_TEXT:
|
||||
pageSize = 0;
|
||||
var_write(&minfo.BytesPerScanLine, mblock->twidth * 2);
|
||||
var_write(&minfo.NumberOfPlanes,0x4);
|
||||
var_write(&minfo.BitsPerPixel,4);
|
||||
var_write(&minfo.MemoryModel,0); //Text
|
||||
var_write(&minfo.MemoryModel,0); // text
|
||||
modeAttributes = 0x0f; //Color, text, bios output
|
||||
break; */
|
||||
break;
|
||||
default:
|
||||
return 0x1;
|
||||
return VESA_FAIL;
|
||||
}
|
||||
var_write(&minfo.WinAAttributes,0x7); // Exists/readable/writable
|
||||
|
||||
if(pageSize > vga.vmemsize) {
|
||||
// Mode not supported by current hardware configuration
|
||||
var_write(&minfo.ModeAttributes, modeAttributes & ~0x1);
|
||||
var_write(&minfo.NumberOfImagePages,0);
|
||||
} else {
|
||||
var_write(&minfo.ModeAttributes, modeAttributes);
|
||||
Bitu pages = (vga.vmemsize / pageSize)-1;
|
||||
var_write(&minfo.NumberOfImagePages,pages);
|
||||
if (pageSize & 0xFFFF) {
|
||||
// It is documented that many applications assume 64k-aligned page sizes
|
||||
// VBETEST is one of them
|
||||
pageSize += 0x10000;
|
||||
pageSize &= ~0xFFFF;
|
||||
}
|
||||
Bitu pages = 0;
|
||||
if (pageSize > vga.vmemsize) {
|
||||
// mode not supported by current hardware configuration
|
||||
modeAttributes &= ~0x1;
|
||||
} else if (pageSize) {
|
||||
pages = (vga.vmemsize / pageSize)-1;
|
||||
}
|
||||
var_write(&minfo.NumberOfImagePages, pages);
|
||||
var_write(&minfo.ModeAttributes, modeAttributes);
|
||||
var_write(&minfo.WinAAttributes, 0x7); // Exists/readable/writable
|
||||
|
||||
if (mblock->type==M_TEXT) {
|
||||
var_write(&minfo.WinGranularity,32);
|
||||
var_write(&minfo.WinSize,32);
|
||||
var_write(&minfo.WinASegment,0xb800);
|
||||
var_write(&minfo.XResolution,mblock->swidth/8);
|
||||
var_write(&minfo.YResolution,mblock->sheight/8);
|
||||
var_write(&minfo.XResolution,mblock->twidth);
|
||||
var_write(&minfo.YResolution,mblock->theight);
|
||||
} else {
|
||||
var_write(&minfo.WinGranularity,64);
|
||||
var_write(&minfo.WinSize,64);
|
||||
|
@ -257,46 +263,46 @@ foundit:
|
|||
if (!int10.vesa_nolfb) var_write(&minfo.PhysBasePtr,S3_LFB_BASE);
|
||||
|
||||
MEM_BlockWrite(buf,&minfo,sizeof(MODE_INFO));
|
||||
return 0x00;
|
||||
return VESA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Bit8u VESA_SetSVGAMode(Bit16u mode) {
|
||||
if (INT10_SetVideoMode(mode)) {
|
||||
int10.vesa_setmode=mode&0x7fff;
|
||||
return 0x00;
|
||||
return VESA_SUCCESS;
|
||||
}
|
||||
return 0x01;
|
||||
return VESA_FAIL;
|
||||
}
|
||||
|
||||
Bit8u VESA_GetSVGAMode(Bit16u & mode) {
|
||||
if (int10.vesa_setmode!=0xffff) mode=int10.vesa_setmode;
|
||||
else mode=CurMode->mode;
|
||||
return 0x00;
|
||||
return VESA_SUCCESS;
|
||||
}
|
||||
|
||||
Bit8u VESA_SetCPUWindow(Bit8u window,Bit8u address) {
|
||||
if (window) return 0x1;
|
||||
if (window) return VESA_FAIL;
|
||||
if (((Bit32u)(address)*64*1024<vga.vmemsize)) {
|
||||
IO_Write(0x3d4,0x6a);
|
||||
IO_Write(0x3d5,(Bit8u)address);
|
||||
return 0x0;
|
||||
} else return 0x1;
|
||||
return VESA_SUCCESS;
|
||||
} else return VESA_FAIL;
|
||||
}
|
||||
|
||||
Bit8u VESA_GetCPUWindow(Bit8u window,Bit16u & address) {
|
||||
if (window) return 0x1;
|
||||
if (window) return VESA_FAIL;
|
||||
IO_Write(0x3d4,0x6a);
|
||||
address=IO_Read(0x3d5);
|
||||
return 0x0;
|
||||
return VESA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Bit8u VESA_SetPalette(PhysPt data,Bitu index,Bitu count) {
|
||||
//Structure is (vesa 3.0 doc): blue,green,red,alignment
|
||||
Bit8u r,g,b;
|
||||
if (index>255) return 0x1;
|
||||
if (index+count>256) return 0x1;
|
||||
if (index>255) return VESA_FAIL;
|
||||
if (index+count>256) return VESA_FAIL;
|
||||
IO_Write(0x3c8,(Bit8u)index);
|
||||
while (count) {
|
||||
b = mem_readb(data++);
|
||||
|
@ -308,14 +314,14 @@ Bit8u VESA_SetPalette(PhysPt data,Bitu index,Bitu count) {
|
|||
IO_Write(0x3c9,b);
|
||||
count--;
|
||||
}
|
||||
return 0x00;
|
||||
return VESA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Bit8u VESA_GetPalette(PhysPt data,Bitu index,Bitu count) {
|
||||
Bit8u r,g,b;
|
||||
if (index>255) return 0x1;
|
||||
if (index+count>256) return 0x1;
|
||||
if (index>255) return VESA_FAIL;
|
||||
if (index+count>256) return VESA_FAIL;
|
||||
IO_Write(0x3c7,(Bit8u)index);
|
||||
while (count) {
|
||||
r = IO_Read(0x3c9);
|
||||
|
@ -327,114 +333,182 @@ Bit8u VESA_GetPalette(PhysPt data,Bitu index,Bitu count) {
|
|||
data++;
|
||||
count--;
|
||||
}
|
||||
return 0x00;
|
||||
return VESA_SUCCESS;
|
||||
}
|
||||
|
||||
// maximum offset for the S3 Trio64 is 10 bits
|
||||
#define S3_MAX_OFFSET 0x3ff
|
||||
|
||||
Bit8u VESA_ScanLineLength(Bit8u subcall,Bit16u val, Bit16u & bytes,Bit16u & pixels,Bit16u & lines) {
|
||||
Bit8u bpp;
|
||||
// offset register: virtual scanline length
|
||||
Bitu pixels_per_offset;
|
||||
Bitu bytes_per_offset = 8;
|
||||
Bitu vmemsize = vga.vmemsize;
|
||||
Bitu new_offset = vga.config.scan_len;
|
||||
Bitu screen_height = CurMode->sheight;
|
||||
|
||||
switch (CurMode->type) {
|
||||
case M_TEXT:
|
||||
vmemsize = 0x8000; // we have only the 32kB window here
|
||||
screen_height = CurMode->theight;
|
||||
pixels_per_offset = 16; // two characters each 8 pixels wide
|
||||
bytes_per_offset = 4; // 2 characters + 2 attributes
|
||||
break;
|
||||
case M_LIN4:
|
||||
bpp = 1;
|
||||
pixels_per_offset = 16;
|
||||
break;
|
||||
case M_LIN8:
|
||||
bpp=1;
|
||||
pixels_per_offset = 8;
|
||||
break;
|
||||
case M_LIN15:
|
||||
case M_LIN16:
|
||||
bpp=2;
|
||||
pixels_per_offset = 4;
|
||||
break;
|
||||
case M_LIN32:
|
||||
bpp=4;
|
||||
pixels_per_offset = 2;
|
||||
break;
|
||||
default:
|
||||
return 0x1;
|
||||
return VESA_MODE_UNSUPPORTED;
|
||||
}
|
||||
switch (subcall) {
|
||||
case 0x00: /* Set in pixels */
|
||||
if(CurMode->type==M_LIN4) vga.config.scan_len=val/2;
|
||||
else vga.config.scan_len = (val * bpp);
|
||||
case 0x00: // set scan length in pixels
|
||||
new_offset = val / pixels_per_offset;
|
||||
if (val % pixels_per_offset) new_offset++;
|
||||
|
||||
if (new_offset > S3_MAX_OFFSET)
|
||||
return VESA_HW_UNSUPPORTED; // scanline too long
|
||||
vga.config.scan_len = new_offset;
|
||||
VGA_CheckScanLength();
|
||||
break;
|
||||
case 0x02: /* Set in bytes */
|
||||
if(CurMode->type==M_LIN4) vga.config.scan_len = val*4;
|
||||
else vga.config.scan_len = val;
|
||||
|
||||
case 0x01: // get current scanline length
|
||||
// implemented at the end of this function
|
||||
break;
|
||||
case 0x03: /* Get maximum */
|
||||
bytes=0x400*4;
|
||||
pixels=bytes/bpp;
|
||||
lines = (Bit16u)(vga.vmemsize / bytes);
|
||||
return 0x00;
|
||||
case 0x01: /* Get lengths */
|
||||
|
||||
case 0x02: // set scan length in bytes
|
||||
new_offset = val / bytes_per_offset;
|
||||
if (val % bytes_per_offset) new_offset++;
|
||||
|
||||
if (new_offset > S3_MAX_OFFSET)
|
||||
return VESA_HW_UNSUPPORTED; // scanline too long
|
||||
vga.config.scan_len = new_offset;
|
||||
VGA_CheckScanLength();
|
||||
break;
|
||||
|
||||
case 0x03: // get maximum scan line length
|
||||
// the smaller of either the hardware maximum scanline length or
|
||||
// the limit to get full y resolution of this mode
|
||||
new_offset = S3_MAX_OFFSET;
|
||||
if ((new_offset * bytes_per_offset * screen_height) > vmemsize)
|
||||
new_offset = vmemsize / (bytes_per_offset * screen_height);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0x1; //Illegal call
|
||||
return VESA_UNIMPLEMENTED;
|
||||
}
|
||||
if (subcall!=0x01) {
|
||||
/* Write the scan line to video card the simple way */
|
||||
if (vga.config.scan_len & 7)
|
||||
vga.config.scan_len += 8;
|
||||
vga.config.scan_len /= 8;
|
||||
}
|
||||
if(CurMode->type==M_LIN4) {
|
||||
pixels=(vga.config.scan_len*16)/bpp;
|
||||
bytes=vga.config.scan_len*2;
|
||||
lines = (Bit16u)(vga.vmemsize /( bytes*4));
|
||||
}
|
||||
else {
|
||||
pixels=(vga.config.scan_len*8)/bpp;
|
||||
bytes=vga.config.scan_len*8;
|
||||
lines = (Bit16u)(vga.vmemsize / bytes);
|
||||
}
|
||||
VGA_StartResize();
|
||||
return 0x0;
|
||||
|
||||
// set up the return values
|
||||
bytes = (Bit16u)(new_offset * bytes_per_offset);
|
||||
pixels = (Bit16u)(new_offset * pixels_per_offset);
|
||||
if (!bytes)
|
||||
// return failure on division by zero
|
||||
// some real VESA BIOS implementations may crash here
|
||||
return VESA_FAIL;
|
||||
|
||||
lines = (Bit16u)(vmemsize / bytes);
|
||||
|
||||
if (CurMode->type==M_TEXT)
|
||||
lines *= CurMode->cheight;
|
||||
|
||||
return VESA_SUCCESS;
|
||||
}
|
||||
|
||||
Bit8u VESA_SetDisplayStart(Bit16u x,Bit16u y) {
|
||||
//TODO Maybe do things differently with lowres double line modes?
|
||||
Bitu start;
|
||||
// TODO wait for retrace in case bl==0x80
|
||||
Bitu pixels_per_offset;
|
||||
Bitu panning_factor = 1;
|
||||
|
||||
switch (CurMode->type) {
|
||||
case M_TEXT:
|
||||
case M_LIN4:
|
||||
start=vga.config.scan_len*16*y+x;
|
||||
vga.config.display_start=start/8;
|
||||
IO_Read(0x3da);
|
||||
IO_Write(0x3c0,0x13+32);
|
||||
IO_Write(0x3c0,start % 8);
|
||||
pixels_per_offset = 16;
|
||||
break;
|
||||
case M_LIN8:
|
||||
start=vga.config.scan_len*8*y+x;
|
||||
vga.config.display_start=start/4;
|
||||
IO_Read(0x3da);
|
||||
IO_Write(0x3c0,0x13+32);
|
||||
IO_Write(0x3c0,(start % 4)*2);
|
||||
panning_factor = 2; // the panning register ignores bit0 in this mode
|
||||
pixels_per_offset = 8;
|
||||
break;
|
||||
case M_LIN16:
|
||||
case M_LIN15:
|
||||
start=vga.config.scan_len*8*y+x*2;
|
||||
vga.config.display_start=start/4;
|
||||
case M_LIN16:
|
||||
panning_factor = 2; // this may be DOSBox specific
|
||||
pixels_per_offset = 4;
|
||||
break;
|
||||
case M_LIN32:
|
||||
start=vga.config.scan_len*8*y+x*4;
|
||||
vga.config.display_start=start/4;
|
||||
pixels_per_offset = 2;
|
||||
break;
|
||||
default:
|
||||
return 0x1;
|
||||
return VESA_MODE_UNSUPPORTED;
|
||||
}
|
||||
return 0x00;
|
||||
// We would have to divide y by the character height for text modes and
|
||||
// write the remainder to the CRTC preset row scan register,
|
||||
// but VBE2 BIOSes that actually get that far also don't.
|
||||
// Only a VBE3 BIOS got it right.
|
||||
Bitu virtual_screen_width = vga.config.scan_len * pixels_per_offset;
|
||||
Bitu new_start_pixel = virtual_screen_width * y + x;
|
||||
Bitu new_crtc_start = new_start_pixel / (pixels_per_offset/2);
|
||||
Bitu new_panning = new_start_pixel % (pixels_per_offset/2);
|
||||
new_panning *= panning_factor;
|
||||
|
||||
vga.config.display_start = new_crtc_start;
|
||||
|
||||
// Setting the panning register is nice as it allows for super smooth
|
||||
// scrolling, but if we hit the retrace pulse there may be flicker as
|
||||
// panning and display start are latched at different times.
|
||||
|
||||
IO_Read(0x3da); // reset attribute flipflop
|
||||
IO_Write(0x3c0,0x13 | 0x20); // panning register, screen on
|
||||
IO_Write(0x3c0,new_panning);
|
||||
|
||||
return VESA_SUCCESS;
|
||||
}
|
||||
|
||||
Bit8u VESA_GetDisplayStart(Bit16u & x,Bit16u & y) {
|
||||
Bitu times=(vga.config.display_start*4)/(vga.config.scan_len*8);
|
||||
Bitu rem=(vga.config.display_start*4) % (vga.config.scan_len*8);
|
||||
Bitu pan=vga.config.pel_panning;
|
||||
Bitu pixels_per_offset;
|
||||
Bitu panning_factor = 1;
|
||||
|
||||
switch (CurMode->type) {
|
||||
case M_TEXT:
|
||||
pixels_per_offset = 16;
|
||||
break;
|
||||
case M_LIN4:
|
||||
pixels_per_offset = 16;
|
||||
break;
|
||||
case M_LIN8:
|
||||
y=(Bit16u)times;
|
||||
x=(Bit16u)(rem+pan);
|
||||
panning_factor = 2;
|
||||
pixels_per_offset = 8;
|
||||
break;
|
||||
case M_LIN15:
|
||||
case M_LIN16:
|
||||
panning_factor = 2;
|
||||
pixels_per_offset = 4;
|
||||
break;
|
||||
case M_LIN32:
|
||||
pixels_per_offset = 2;
|
||||
break;
|
||||
default:
|
||||
return 0x1;
|
||||
return VESA_MODE_UNSUPPORTED;
|
||||
}
|
||||
return 0x00;
|
||||
|
||||
IO_Read(0x3da); // reset attribute flipflop
|
||||
IO_Write(0x3c0,0x13 | 0x20); // panning register, screen on
|
||||
Bit8u panning = IO_Read(0x3c1);
|
||||
|
||||
Bitu virtual_screen_width = vga.config.scan_len * pixels_per_offset;
|
||||
Bitu start_pixel = vga.config.display_start * (pixels_per_offset/2)
|
||||
+ panning / panning_factor;
|
||||
|
||||
y = start_pixel / virtual_screen_width;
|
||||
x = start_pixel % virtual_screen_width;
|
||||
return VESA_SUCCESS;
|
||||
}
|
||||
|
||||
static Bitu VESA_SetWindow(void) {
|
||||
|
@ -453,6 +527,10 @@ static Bitu VESA_PMSetPalette(void) {
|
|||
return 0;
|
||||
}
|
||||
static Bitu VESA_PMSetStart(void) {
|
||||
// This function is from VBE2 and directly sets the VGA
|
||||
// display start address.
|
||||
|
||||
// TODO wait for retrace in case bl==0x80
|
||||
Bit32u start = (reg_dx << 16) | reg_cx;
|
||||
vga.config.display_start = start;
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue