1
0
Fork 0

Implement waiting for retrace in VBE functions. Remove range checks in protected mode functions, consistent with UniVBE and other VBE implementations. Fixes hang and graphics glitches in Jack Orlando.

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@4048
This commit is contained in:
ripsaw8080 2017-09-10 11:29:34 +00:00
parent 5c0b03c10c
commit 4aa821d0e6
5 changed files with 91 additions and 34 deletions

View file

@ -592,10 +592,10 @@ graphics_chars:
break;
case 0x07:
switch (reg_bl) {
case 0x80: /* Set Display Start during retrace ?? */
case 0x80: /* Set Display Start during retrace */
case 0x00: /* Set display Start */
reg_al=0x4f;
reg_ah=VESA_SetDisplayStart(reg_cx,reg_dx);
reg_ah=VESA_SetDisplayStart(reg_cx,reg_dx,reg_bl==0x80);
break;
case 0x01:
reg_al=0x4f;
@ -611,9 +611,8 @@ graphics_chars:
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_ah=VESA_SetPalette(SegPhys(es)+reg_di,reg_dx,reg_cx,reg_bl==0x80);
reg_al=0x4f;
break;
case 0x01: /* Get Palette */
@ -633,27 +632,27 @@ graphics_chars:
}
switch (reg_bl) {
case 0x00:
reg_edi=RealOff(int10.rom.pmode_interface);
SegSet16(es,RealSeg(int10.rom.pmode_interface));
reg_di=RealOff(int10.rom.pmode_interface);
reg_cx=int10.rom.pmode_interface_size;
reg_ax=0x004f;
break;
case 0x01: /* Get code for "set window" */
reg_edi=RealOff(int10.rom.pmode_interface)+int10.rom.pmode_interface_window;
SegSet16(es,RealSeg(int10.rom.pmode_interface));
reg_cx=0x10; //0x10 should be enough for the callbacks
reg_di=RealOff(int10.rom.pmode_interface)+int10.rom.pmode_interface_window;
reg_cx=int10.rom.pmode_interface_start-int10.rom.pmode_interface_window;
reg_ax=0x004f;
break;
case 0x02: /* Get code for "set display start" */
reg_edi=RealOff(int10.rom.pmode_interface)+int10.rom.pmode_interface_start;
SegSet16(es,RealSeg(int10.rom.pmode_interface));
reg_cx=0x10; //0x10 should be enough for the callbacks
reg_di=RealOff(int10.rom.pmode_interface)+int10.rom.pmode_interface_start;
reg_cx=int10.rom.pmode_interface_palette-int10.rom.pmode_interface_start;
reg_ax=0x004f;
break;
case 0x03: /* Get code for "set palette" */
reg_edi=RealOff(int10.rom.pmode_interface)+int10.rom.pmode_interface_palette;
SegSet16(es,RealSeg(int10.rom.pmode_interface));
reg_cx=0x10; //0x10 should be enough for the callbacks
reg_di=RealOff(int10.rom.pmode_interface)+int10.rom.pmode_interface_palette;
reg_cx=int10.rom.pmode_interface_size-int10.rom.pmode_interface_palette;
reg_ax=0x004f;
break;
default:

View file

@ -133,6 +133,8 @@ typedef struct {
RealPt video_dcc_table;
RealPt oemstring;
RealPt vesa_modes;
RealPt wait_retrace;
RealPt set_window;
RealPt pmode_interface;
Bit16u pmode_interface_size;
Bit16u pmode_interface_start;
@ -208,9 +210,9 @@ Bit8u VESA_GetSVGAMode(Bit16u & mode);
Bit8u VESA_SetCPUWindow(Bit8u window,Bit8u address);
Bit8u VESA_GetCPUWindow(Bit8u window,Bit16u & address);
Bit8u VESA_ScanLineLength(Bit8u subcall, Bit16u val, Bit16u & bytes,Bit16u & pixels,Bit16u & lines);
Bit8u VESA_SetDisplayStart(Bit16u x,Bit16u y);
Bit8u VESA_SetDisplayStart(Bit16u x,Bit16u y,bool wait);
Bit8u VESA_GetDisplayStart(Bit16u & x,Bit16u & y);
Bit8u VESA_SetPalette(PhysPt data,Bitu index,Bitu count);
Bit8u VESA_SetPalette(PhysPt data,Bitu index,Bitu count,bool wait);
Bit8u VESA_GetPalette(PhysPt data,Bitu index,Bitu count);
/* Sub Groups */

View file

@ -36,7 +36,7 @@
#define VESA_UNIMPLEMENTED 0xFF
static struct {
Bitu setwindow;
Bitu rmWindow;
Bitu pmStart;
Bitu pmWindow;
Bitu pmPalette;
@ -254,7 +254,7 @@ foundit:
var_write(&minfo.XResolution,mblock->swidth);
var_write(&minfo.YResolution,mblock->sheight);
}
var_write(&minfo.WinFuncPtr,CALLBACK_RealPointer(callback.setwindow));
var_write(&minfo.WinFuncPtr,int10.rom.set_window);
var_write(&minfo.NumberOfBanks,0x1);
var_write(&minfo.Reserved_page,0x1);
var_write(&minfo.XCharSize,mblock->cwidth);
@ -297,11 +297,15 @@ Bit8u VESA_GetCPUWindow(Bit8u window,Bit16u & address) {
}
Bit8u VESA_SetPalette(PhysPt data,Bitu index,Bitu count) {
Bit8u VESA_SetPalette(PhysPt data,Bitu index,Bitu count,bool wait) {
//Structure is (vesa 3.0 doc): blue,green,red,alignment
Bit8u r,g,b;
if (index>255) return VESA_FAIL;
if (index+count>256) return VESA_FAIL;
// Wait for retrace if requested
if (wait) CALLBACK_RunRealFar(RealSeg(int10.rom.wait_retrace),RealOff(int10.rom.wait_retrace));
IO_Write(0x3c8,(Bit8u)index);
while (count) {
b = mem_readb(data++);
@ -422,8 +426,7 @@ Bit8u VESA_ScanLineLength(Bit8u subcall,Bit16u val, Bit16u & bytes,Bit16u & pixe
return VESA_SUCCESS;
}
Bit8u VESA_SetDisplayStart(Bit16u x,Bit16u y) {
// TODO wait for retrace in case bl==0x80
Bit8u VESA_SetDisplayStart(Bit16u x,Bit16u y,bool wait) {
Bitu pixels_per_offset;
Bitu panning_factor = 1;
@ -467,6 +470,9 @@ Bit8u VESA_SetDisplayStart(Bit16u x,Bit16u y) {
IO_Write(0x3c0,0x13 | 0x20); // panning register, screen on
IO_Write(0x3c0,new_panning);
// Wait for retrace if requested
if (wait) CALLBACK_RunRealFar(RealSeg(int10.rom.wait_retrace),RealOff(int10.rom.wait_retrace));
return VESA_SUCCESS;
}
@ -514,25 +520,30 @@ static Bitu VESA_SetWindow(void) {
if (reg_bh) reg_ah=VESA_GetCPUWindow(reg_bl,reg_dx);
else reg_ah=VESA_SetCPUWindow(reg_bl,(Bit8u)reg_dx);
reg_al=0x4f;
return 0;
return CBRET_NONE;
}
static Bitu VESA_PMSetWindow(void) {
VESA_SetCPUWindow(0,(Bit8u)reg_dx);
return 0;
IO_Write(0x3d4,0x6a);
IO_Write(0x3d5,reg_dl);
return CBRET_NONE;
}
static Bitu VESA_PMSetPalette(void) {
VESA_SetPalette(SegPhys(es) + reg_edi, reg_dx, reg_cx );
return 0;
PhysPt data=SegPhys(es)+reg_edi;
Bit32u count=reg_cx;
IO_Write(0x3c8,reg_dl);
do {
IO_Write(0x3c9,mem_readb(data+2));
IO_Write(0x3c9,mem_readb(data+1));
IO_Write(0x3c9,mem_readb(data));
data+=4;
} while (--count);
return CBRET_NONE;
}
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;
return CBRET_NONE;
}
@ -569,10 +580,12 @@ void INT10_SetupVESA(void) {
case SVGA_S3Trio:
break;
}
callback.setwindow=CALLBACK_Allocate();
callback.pmPalette=CALLBACK_Allocate();
callback.pmStart=CALLBACK_Allocate();
CALLBACK_Setup(callback.setwindow,VESA_SetWindow,CB_RETF, "VESA Real Set Window");
/* Prepare the real mode interface */
int10.rom.wait_retrace=RealMake(0xc000,int10.rom.used);
int10.rom.used += (Bit16u)CALLBACK_Setup(0, NULL, CB_VESA_WAIT, PhysMake(0xc000,int10.rom.used), "");
callback.rmWindow=CALLBACK_Allocate();
int10.rom.set_window=RealMake(0xc000,int10.rom.used);
int10.rom.used += (Bit16u)CALLBACK_Setup(callback.rmWindow, VESA_SetWindow, CB_RETF, PhysMake(0xc000,int10.rom.used), "VESA Real Set Window");
/* Prepare the pmode interface */
int10.rom.pmode_interface=RealMake(0xc000,int10.rom.used);
int10.rom.used += 8; //Skip the byte later used for offsets
@ -585,11 +598,12 @@ void INT10_SetupVESA(void) {
int10.rom.pmode_interface_start = int10.rom.used - RealOff( int10.rom.pmode_interface );
phys_writew( Real2Phys(int10.rom.pmode_interface) + 2, int10.rom.pmode_interface_start);
callback.pmStart=CALLBACK_Allocate();
int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmStart, VESA_PMSetStart, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Start");
int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmStart, VESA_PMSetStart, CB_VESA_PM, PhysMake(0xc000,int10.rom.used), "VESA PM Set Start");
/* PM Set Palette call */
int10.rom.pmode_interface_palette = int10.rom.used - RealOff( int10.rom.pmode_interface );
phys_writew( Real2Phys(int10.rom.pmode_interface) + 4, int10.rom.pmode_interface_palette);
callback.pmPalette=CALLBACK_Allocate();
int10.rom.used += (Bit16u)CALLBACK_Setup(0, NULL, CB_VESA_PM, PhysMake(0xc000,int10.rom.used), "");
int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmPalette, VESA_PMSetPalette, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Palette");
/* Finalize the size and clear the required ports pointer */
phys_writew( Real2Phys(int10.rom.pmode_interface) + 6, 0);