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:
parent
5c0b03c10c
commit
4aa821d0e6
5 changed files with 91 additions and 34 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue