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

@ -30,7 +30,7 @@ extern CallBack_Handler CallBack_Handlers[];
enum { CB_RETN,CB_RETF,CB_RETF8,CB_IRET,CB_IRETD,CB_IRET_STI,CB_IRET_EOI_PIC1,
CB_IRQ0,CB_IRQ1,CB_IRQ9,CB_IRQ12,CB_IRQ12_RET,CB_IRQ6_PCJR,CB_MOUSE,
CB_INT29,CB_INT16,CB_HOOKABLE,CB_TDE_IRET,CB_IPXESR,CB_IPXESR_RET,
CB_INT21,CB_INT13 };
CB_INT21,CB_INT13,CB_VESA_WAIT,CB_VESA_PM };
#define CB_MAX 128
#define CB_SIZE 32

View file

@ -458,6 +458,48 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_
phys_writew(physAddress+0x02,(Bit16u)0x0ECD); // int 0e
phys_writeb(physAddress+0x04,(Bit8u)0xCF); //An IRET Instruction
return (use_cb?9:5);
case CB_VESA_WAIT:
if (use_cb) E_Exit("VESA wait must not implement a callback handler!");
phys_writeb(physAddress+0x00,(Bit8u)0xFB); // sti
phys_writeb(physAddress+0x01,(Bit8u)0x50); // push ax
phys_writeb(physAddress+0x02,(Bit8u)0x52); // push dx
phys_writeb(physAddress+0x03,(Bit8u)0xBA); // mov dx,
phys_writew(physAddress+0x04,(Bit16u)0x03DA); // 0x3da
phys_writeb(physAddress+0x06,(Bit8u)0xEC); // in al,dx
phys_writew(physAddress+0x07,(Bit16u)0x08A8); // test al,8
phys_writew(physAddress+0x09,(Bit16u)0xFB75); // jne $-5
phys_writeb(physAddress+0x0B,(Bit8u)0xEC); // in al,dx
phys_writew(physAddress+0x0C,(Bit16u)0x08A8); // test al,8
phys_writew(physAddress+0x0E,(Bit16u)0xFB74); // je $-5
phys_writeb(physAddress+0x10,(Bit8u)0x5A); // pop dx
phys_writeb(physAddress+0x11,(Bit8u)0x58); // pop ax
phys_writeb(physAddress+0x12,(Bit8u)0xCB); //A RETF Instruction
return 19;
case CB_VESA_PM:
if (use_cb) {
phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word
physAddress+=4;
}
phys_writew(physAddress+0x00,(Bit16u)0xC3F6); // test bl,
phys_writeb(physAddress+0x02,(Bit8u)0x80); // 0x80
phys_writew(physAddress+0x03,(Bit16u)0x1674); // je $+22
phys_writew(physAddress+0x05,(Bit16u)0x5066); // push ax
phys_writew(physAddress+0x07,(Bit16u)0x5266); // push dx
phys_writew(physAddress+0x09,(Bit16u)0xBA66); // mov dx,
phys_writew(physAddress+0x0B,(Bit16u)0x03DA); // 0x3da
phys_writeb(physAddress+0x0D,(Bit8u)0xEC); // in al,dx
phys_writew(physAddress+0x0E,(Bit16u)0x08A8); // test al,8
phys_writew(physAddress+0x10,(Bit16u)0xFB75); // jne $-5
phys_writeb(physAddress+0x12,(Bit8u)0xEC); // in al,dx
phys_writew(physAddress+0x13,(Bit16u)0x08A8); // test al,8
phys_writew(physAddress+0x15,(Bit16u)0xFB74); // je $-5
phys_writew(physAddress+0x17,(Bit16u)0x5A66); // pop dx
phys_writew(physAddress+0x19,(Bit16u)0x5866); // pop ax
if (use_cb)
phys_writeb(physAddress+0x1B,(Bit8u)0xC3); //A RETN Instruction
return (use_cb?32:27);
default:
E_Exit("CALLBACK:Setup:Illegal type %d",type);
}

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);