Chiel Landsheer
2007-01-20 20:33:00 UTC
Hi,
I have been using the unit Vesa.pas with Borland Pascal 7.0 since 1998
in order to get, in the graphical mode under MS-DOS, a higher resolution
than the standard 640 x 480. I have downloaded this unit from (then)
Inprise. It has always worked fine, upto 1024 x 768, on (then) modern
graphical cards (non-AGP), in (or one should say "from") DOS-boxes in
Windows 98SE.
Now I have a new computer with Windows XP SP2, and it doesn't work
anymore. The only thing the procedure Initialize does is switch to full
screen text-mode.
The old 640 x 480 mode still works OK.
The new graphical card is: RAGE 128 PRO Ultra GL AGP.
Has anyone a suggestion for a solution?
For those who might be interested: the source of the unit follows. It is
mainly assembler, though.
Chiel Landsheer
{***************************************************}
{******************** VESA UNIT *********************}
{***************************************************}
unit Vesa;
{
Add this unit to programs that want Vesa support
for high resolutions such as 800 X 600, 1024 X 768
and 1280 X 1024. If Vesa is not supported on a system
the code automatically defaults to an available driver
such as EGAVGA.
To Initialize the graphics system, just call
Initialize with the path to VESA.BGI as the sole
parameter. Pass an empty string if the driver
is in the current subdirectory.
The code will automatically detect if you are
running in protected mode or real mode.
Examples:
Initialize('c:\bp\bin');
Initialize('');
}
Interface
uses
Graph {$IfDef DPMI}, WinApi {$EndIf};
const
VESA16Modes: array[0..2] of Word =
($0102, $0104, $0106);
type
VgaInfoBlock = record
VESASignature: array[0..3] of Byte;
VESAVersion: Word;
OEMStringPtr: Pointer;
Capabilities: array[0..3] of Byte;
VideoModePtr: Pointer;
end;
var
MaxColor,
MaxX, MaxY: Integer;
procedure Initialize(PathToDriver: String);
implementation
var
VESA16 : Integer; { Driver number of 16 color driver }
function GetHighestCap(Table: Pointer; Modes: Word; Size:Integer): Integer;
near; assembler;
asm
XOR AX,AX
LES DI, Table
@1:
MOV SI, Modes
ADD SI, Size
ADD SI, Size
SUB SI, 2
MOV BX, ES:[DI]
CMP BX, 0FFFFH
JE @4
INC DI
INC DI
MOV CX,Size
@2:
CMP BX,[SI]
JZ @3
DEC SI
DEC SI
LOOP @2
@3:
CMP AX,CX
JA @1
MOV AX,CX
JMP @1
@4:
DEC AX
end;
{$IFDEF DPMI}
type
TRealRegs = record
RealEDI: Longint;
RealESI: Longint;
RealEBP: Longint;
Reserved: Longint;
RealEBX: Longint;
RealEDX: Longint;
RealECX: Longint;
RealEAX: Longint;
RealFlags: Word;
RealES: Word;
RealDS: Word;
RealFS: Word;
RealGS: Word;
RealIP: Word;
RealCS: Word;
RealSP: Word;
RealSS: Word;
end;
function DetectVesa16: Integer; far; assembler;
var
Segment, Selector, VesaCap: Word;
asm
{$IFOPT G+}
PUSH 0000H
PUSH 0100H
{$ELSE}
XOR AX,AX
PUSH AX
INC AH
PUSH AX
{$ENDIF}
CALL GlobalDosAlloc
MOV Segment,DX
MOV Selector,AX
MOV DI,OFFSET RealModeRegs
MOV WORD PTR [DI].TRealRegs.RealSP, 0
MOV WORD PTR [DI].TRealRegs.RealSS, 0
MOV WORD PTR [DI].TRealRegs.RealEAX, 4F00H
MOV WORD PTR [DI].TRealRegs.RealES, DX
MOV WORD PTR [DI].TRealRegs.RealEDI, 0
MOV AX,DS
MOV ES,AX
MOV AX,0300H
MOV BX,0010H
XOR CX,CX
INT 31H
MOV DI,OFFSET RealModeRegs
MOV AX,grError
PUSH AX
CMP WORD PTR [DI].TRealRegs.RealEAX,004FH
JNZ @Exit
POP AX
MOV ES,Selector
XOR DI,DI
CMP ES:[DI].VgaInfoBlock.VESASignature.Word[0], 'EV'
JNZ @Exit
CMP ES:[DI].VgaInfoBlock.VESASignature.Word[2], 'AS'
JNZ @Exit
MOV AX,0000
MOV CX,1
INT 31H
MOV VesaCap,AX
MOV DX,ES:[DI].VgaInfoBlock.VideoModePtr.Word[2]
MOV CX,4
XOR AX,AX
@Convert:
SHL DX,1
RCL AX,1
LOOP @Convert
ADD DX,ES:[DI].VgaInfoBlock.VideoModePtr.Word[0]
ADC AX,0
MOV CX,AX
MOV BX,VesaCap
MOV AX,0007H
INT 31H
INC AX
XOR CX,CX
MOV DX,0FFFFH
INT 31H
MOV ES,BX
PUSH ES
PUSH DI
{$IFOPT G+}
PUSH OFFSET Vesa16Modes
PUSH 0003H
{$ELSE}
MOV SI, OFFSET Vesa16Modes
PUSH SI
MOV AX, 5
PUSH AX
{$ENDIF}
CALL GetHighestCap
PUSH AX
MOV BX,VesaCap
MOV AX,0001H
INT 31H
@Exit:
PUSH Selector
CALL GlobalDosFree
POP AX
end;
{$ELSE}
function DetectVesa16: Integer; far; assembler;
var
VesaInfo: array[0..255] of Byte;
asm
MOV AX,SS
MOV ES,AX
LEA DI,VesaInfo
MOV AX,4F00H
INT 10H
CMP AX,004FH
MOV AX,grError
JNZ @Exit
CMP ES:[DI].VgaInfoBlock.VESASignature.Word[0], 'EV'
JNZ @Exit
CMP ES:[DI].VgaInfoBlock.VESASignature.Word[2], 'AS'
JNZ @Exit
LES DI,ES:[DI].VgaInfoBlock.VideoModePtr
PUSH ES
PUSH DI
MOV AX, OFFSET Vesa16Modes
PUSH AX
MOV AX,3
PUSH AX
CALL GetHighestCap
@Exit:
end;
{$ENDIF}
procedure Initialize(PathToDriver: String);
var
MaxColor,
ErrorCode,
GraphMode,
GraphDriver: Integer;
begin
VESA16 := InstallUserDriver('VESA16', @DetectVESA16);
GraphDriver := Detect;
InitGraph(GraphDriver, GraphMode, PathToDriver);
ErrorCode := GraphResult;
if ErrorCode <> grOK then begin
WriteLn('Graphics error: ', GraphErrorMsg(ErrorCode));
ReadLn;
Halt;
end;
MaxX := GetMaxX;
MaxY := GetMaxY;
MaxColor := GetMaxColor;
end;
end.
I have been using the unit Vesa.pas with Borland Pascal 7.0 since 1998
in order to get, in the graphical mode under MS-DOS, a higher resolution
than the standard 640 x 480. I have downloaded this unit from (then)
Inprise. It has always worked fine, upto 1024 x 768, on (then) modern
graphical cards (non-AGP), in (or one should say "from") DOS-boxes in
Windows 98SE.
Now I have a new computer with Windows XP SP2, and it doesn't work
anymore. The only thing the procedure Initialize does is switch to full
screen text-mode.
The old 640 x 480 mode still works OK.
The new graphical card is: RAGE 128 PRO Ultra GL AGP.
Has anyone a suggestion for a solution?
For those who might be interested: the source of the unit follows. It is
mainly assembler, though.
Chiel Landsheer
{***************************************************}
{******************** VESA UNIT *********************}
{***************************************************}
unit Vesa;
{
Add this unit to programs that want Vesa support
for high resolutions such as 800 X 600, 1024 X 768
and 1280 X 1024. If Vesa is not supported on a system
the code automatically defaults to an available driver
such as EGAVGA.
To Initialize the graphics system, just call
Initialize with the path to VESA.BGI as the sole
parameter. Pass an empty string if the driver
is in the current subdirectory.
The code will automatically detect if you are
running in protected mode or real mode.
Examples:
Initialize('c:\bp\bin');
Initialize('');
}
Interface
uses
Graph {$IfDef DPMI}, WinApi {$EndIf};
const
VESA16Modes: array[0..2] of Word =
($0102, $0104, $0106);
type
VgaInfoBlock = record
VESASignature: array[0..3] of Byte;
VESAVersion: Word;
OEMStringPtr: Pointer;
Capabilities: array[0..3] of Byte;
VideoModePtr: Pointer;
end;
var
MaxColor,
MaxX, MaxY: Integer;
procedure Initialize(PathToDriver: String);
implementation
var
VESA16 : Integer; { Driver number of 16 color driver }
function GetHighestCap(Table: Pointer; Modes: Word; Size:Integer): Integer;
near; assembler;
asm
XOR AX,AX
LES DI, Table
@1:
MOV SI, Modes
ADD SI, Size
ADD SI, Size
SUB SI, 2
MOV BX, ES:[DI]
CMP BX, 0FFFFH
JE @4
INC DI
INC DI
MOV CX,Size
@2:
CMP BX,[SI]
JZ @3
DEC SI
DEC SI
LOOP @2
@3:
CMP AX,CX
JA @1
MOV AX,CX
JMP @1
@4:
DEC AX
end;
{$IFDEF DPMI}
type
TRealRegs = record
RealEDI: Longint;
RealESI: Longint;
RealEBP: Longint;
Reserved: Longint;
RealEBX: Longint;
RealEDX: Longint;
RealECX: Longint;
RealEAX: Longint;
RealFlags: Word;
RealES: Word;
RealDS: Word;
RealFS: Word;
RealGS: Word;
RealIP: Word;
RealCS: Word;
RealSP: Word;
RealSS: Word;
end;
function DetectVesa16: Integer; far; assembler;
var
Segment, Selector, VesaCap: Word;
asm
{$IFOPT G+}
PUSH 0000H
PUSH 0100H
{$ELSE}
XOR AX,AX
PUSH AX
INC AH
PUSH AX
{$ENDIF}
CALL GlobalDosAlloc
MOV Segment,DX
MOV Selector,AX
MOV DI,OFFSET RealModeRegs
MOV WORD PTR [DI].TRealRegs.RealSP, 0
MOV WORD PTR [DI].TRealRegs.RealSS, 0
MOV WORD PTR [DI].TRealRegs.RealEAX, 4F00H
MOV WORD PTR [DI].TRealRegs.RealES, DX
MOV WORD PTR [DI].TRealRegs.RealEDI, 0
MOV AX,DS
MOV ES,AX
MOV AX,0300H
MOV BX,0010H
XOR CX,CX
INT 31H
MOV DI,OFFSET RealModeRegs
MOV AX,grError
PUSH AX
CMP WORD PTR [DI].TRealRegs.RealEAX,004FH
JNZ @Exit
POP AX
MOV ES,Selector
XOR DI,DI
CMP ES:[DI].VgaInfoBlock.VESASignature.Word[0], 'EV'
JNZ @Exit
CMP ES:[DI].VgaInfoBlock.VESASignature.Word[2], 'AS'
JNZ @Exit
MOV AX,0000
MOV CX,1
INT 31H
MOV VesaCap,AX
MOV DX,ES:[DI].VgaInfoBlock.VideoModePtr.Word[2]
MOV CX,4
XOR AX,AX
@Convert:
SHL DX,1
RCL AX,1
LOOP @Convert
ADD DX,ES:[DI].VgaInfoBlock.VideoModePtr.Word[0]
ADC AX,0
MOV CX,AX
MOV BX,VesaCap
MOV AX,0007H
INT 31H
INC AX
XOR CX,CX
MOV DX,0FFFFH
INT 31H
MOV ES,BX
PUSH ES
PUSH DI
{$IFOPT G+}
PUSH OFFSET Vesa16Modes
PUSH 0003H
{$ELSE}
MOV SI, OFFSET Vesa16Modes
PUSH SI
MOV AX, 5
PUSH AX
{$ENDIF}
CALL GetHighestCap
PUSH AX
MOV BX,VesaCap
MOV AX,0001H
INT 31H
@Exit:
PUSH Selector
CALL GlobalDosFree
POP AX
end;
{$ELSE}
function DetectVesa16: Integer; far; assembler;
var
VesaInfo: array[0..255] of Byte;
asm
MOV AX,SS
MOV ES,AX
LEA DI,VesaInfo
MOV AX,4F00H
INT 10H
CMP AX,004FH
MOV AX,grError
JNZ @Exit
CMP ES:[DI].VgaInfoBlock.VESASignature.Word[0], 'EV'
JNZ @Exit
CMP ES:[DI].VgaInfoBlock.VESASignature.Word[2], 'AS'
JNZ @Exit
LES DI,ES:[DI].VgaInfoBlock.VideoModePtr
PUSH ES
PUSH DI
MOV AX, OFFSET Vesa16Modes
PUSH AX
MOV AX,3
PUSH AX
CALL GetHighestCap
@Exit:
end;
{$ENDIF}
procedure Initialize(PathToDriver: String);
var
MaxColor,
ErrorCode,
GraphMode,
GraphDriver: Integer;
begin
VESA16 := InstallUserDriver('VESA16', @DetectVESA16);
GraphDriver := Detect;
InitGraph(GraphDriver, GraphMode, PathToDriver);
ErrorCode := GraphResult;
if ErrorCode <> grOK then begin
WriteLn('Graphics error: ', GraphErrorMsg(ErrorCode));
ReadLn;
Halt;
end;
MaxX := GetMaxX;
MaxY := GetMaxY;
MaxColor := GetMaxColor;
end;
end.