[Back to EGAVGA SWAG index] [Back to Main SWAG index] [Original]
{
Here's some VESA routines. The drawing stuff is quite limited right now
(to pixels and horizontal lines in 256-color linear modes only) but it
detects/sets/describes most everything else. Also no save/restore video
state yet. It uses direct VESA function calls instead of interrupts, and
tries to optimize where it puts the window based on what the routines
will be used for . . .
}
{VESA1.PAS}
{by Sean Palmer}
{with help from Ferraro and Olaf Bartlett}
type
pModeList = ^tModeList;
tModeList = Array [0..255] of word; {list of modes terminated by -1}
{VESA modes are >=100h}
modeAttrBits = (modeAvail,
modeExtendInfo,
modeBIOSsupport,
modeColor,
modeGraphics,
modeBit5,
modeBit6,
modeBit7,
modeBit8);
winAttrBits = (winSupported,
winReadable,
winWriteable);
tMemModel = (modelText,
modelCGA,
modelHerc,
model4Plane,
modelPacked,
modelModeX,
modelRGB);
var
VESAinfo : record
signature : array [1..4] of char;
version : word;
str : pChar;
caps : longint;
modeList : pModeList;
pad : array [18..255] of byte;
end;
modeInfo : record
attr : set of modeAttrBits;
winAAttr,
winBAttr : set of winAttrBits;
winGranularity : word; {in K}
winSize : word; {in K}
winASeg,
winBSeg : word; {segment to access window with}
winFunct : procedure;
scanBytes : word; {bytes per scan line}
extendedInfo : record
xRes, yRes : word; {pixels}
xCharSize,
yCharSize : byte;
planes : byte;
bitsPixel : byte;
banks : byte;
memModel : tMemModel;
bankSize : byte; {in K}
end;
pad : array [29..255] of byte;
end;
xSize,
ySize,
xBytes : word;
bits : byte;
model : tMemModel;
window : byte;
winSeg : word;
granShifts : byte;
winLo,
winHi,
winBytes,
granMask : longint;
funct : procedure;
m, i : word;
function getVESAInfo : boolean; assembler;
asm
mov ax,4F00h
push ds
pop es
mov di,offset VESAinfo
int 10h
sub ax,004Fh {make sure we got 004Fh back}
cmp ax,1
sbb al,al
cmp word ptr es:[di],'V'or('E'shl 8) {signature should be 'VESA'}
jne @@ERR
cmp word ptr es:[di+2],'S'or('A'shl 8)
je @@X
@@ERR:
mov al,0
@@X:
end;
function getModeInfo(mode:word):boolean;assembler;asm
mov ax,4F01h
mov cx,mode
push ds
pop es
mov di,offset modeInfo
int 10h
sub ax,004Fh {make sure it's 004Fh}
cmp ax,1
sbb al,al
end;
{if the VESA driver supports info on the regular VGA modes, add them to list}
procedure includeStandardVGAModes;var p:^word;begin
p:=pointer(VESAInfo.modeList);
while p^<>$FFFF do inc(p);
if getModeInfo($10) then begin p^:=$10; inc(p);end;
if getModeInfo($12) then begin p^:=$12; inc(p);end;
if getModeInfo($13) then begin p^:=$13; inc(p);end;
p^:=$FFFF;
end;
function setMode(mode:word):boolean;var i:word;begin
if getModeInfo(mode) then begin
with modeInfo do begin
if winSupported in winAAttr then begin window:=0; winSeg:=winASeg;end
else if winSupported in winBAttr then begin window:=1; winSeg:=winBSeg;end
else exit; {you call this a VESA mode?}
with extendedInfo do begin
xSize:=xRes; ySize:=yRes; xBytes:=scanBytes; bits:=bitsPixel;
model:=memModel;
end;
winBytes:=longint(winSize)*1024; {wraps to 0 if 64k}
winLo:=0; winHi:=winBytes;
i:=winGranularity;
granShifts:=10; {for 1K}
while not odd(i) do begin
i:=i shr 1;
inc(granShifts);
end;
if i<>1 then begin setMode:=false;exit;end; {granularity not power of 2}
granMask:=(longint(1)shl granShifts)-1;
funct:=winFunct;
end;
asm
mov ax,4F02h
mov bx,mode
int 10h
sub ax,004Fh
cmp ax,1
sbb al,al
mov @RESULT,al
end;
end;
end;
function getMode:word;assembler;asm {return -1 if error}
mov ax,4F03h
int 10h
cmp ax,004Fh
je @@OK
mov ax,-1
jmp @@X
@@OK: mov ax,bx
@@X:
end;
procedure plot(x, y : word; c : byte);
var
bank : word;
offs : longint;
begin
offs := longint(y) * xBytes + x;
if (offs < winLo) or (offs >= winHi) then
begin
winLo := (offs - (winBytes shr 1)) and not granMask;
winHi := winLo + winBytes;
bank := winLo shr granShifts;
asm
mov bl, window
mov dx, bank
call [funct]
end;
end;
mem[winSeg : word(offs) - word(winLo)] := c;
end;
procedure hLin(x,x2,y:word;c:byte);
var bank,w:word; offs:longint;
begin
w:=x2-x;
offs:=longint(y)*xBytes+x;
if (offs<winLo)or(offs+w>=winHi) then begin
winLo:=offs and not granMask;
winHi:=winLo+winBytes;
bank:=winLo shr granShifts;
asm
mov bl,window
mov dx,bank
call [funct]
end;
end;
fillChar(mem[winSeg:word(offs)-word(winLo)],w,c);
end;
function scrn(x,y:word):byte;
var bank:word; offs:longint;
begin
offs:=longint(y)*xBytes+x;
if (offs<winLo)or(offs>=winHi) then begin
winLo:=(offs-(winBytes shr 1))and not granMask;
winHi:=winLo+winBytes;
bank:=winLo shr granShifts;
asm
mov bl,window
mov dx,bank
call [funct]
end;
end;
scrn:=mem[winSeg:word(offs)-word(winLo)];
end;
{will find a color graphics mode that matches parms}
{if parm is 0, finds best mode for that parm}
function findMode(x,y:word;model:tMemModel;nBits,nPlanes,nBanks:byte):word;
var p:^word; m:word; gx,gy,gb,lp,lb:word;
begin
gx:=0;gy:=0;gb:=0;lp:=255;lb:=255;
p:=pointer(VESAInfo.modeList);
m:=$FFFF;
while p^<>$FFFF do begin
if getModeInfo(p^) then
with modeInfo do
if attr+[modeAvail,modeExtendInfo,modeColor,modeGraphics]=attr then
with extendedInfo do
if ((xRes=x)or((x=0)and(gx<=xRes)))
and((yRes=y)or((y=0)and(gy<=yRes)))
and(memModel=model)
and((bitsPixel=nBits)or((nBits=0)and(gb<=bitsPixel)))
and((planes=nPlanes)or((nPlanes=0)and(lp>=planes)))
and((banks=nBanks)or((nBanks=0)and(lb>=banks)))
then begin
gx:=xRes;gy:=yRes;gb:=bitsPixel;lp:=planes;lb:=banks;
m:=p^;
end;
inc(p);
end;
if m<>$FFFF then getModeInfo(m);
findMode:=m; {0FFFFh if not found. Try a standard mode number then.}
end;
procedure displayVESAInfo;
type
string2=string[2];
string4=string[4];
string8=string[8];
const
modelStr : array[tMemModel]of pChar=
('Text','CGA','Hercules','EGA','Linear','mode X','RGB');
var
p:^word;
function hexB(n:byte):string2; assembler;asm
les di,@RESULT; {adr of function result}
cld; mov al,2; stosb; {set len}
mov al,n; mov ah,al; {save it}
shr al,1; shr al,1; shr al,1; shr al,1; {high nibble}
add al,$90; daa; adc al,$40; daa; {convert hex nibble to ASCII}
stosb;
mov al,ah; and al,$F; {low nibble}
add al,$90; daa; adc al,$40; daa;
stosb;
end;
function hexW(n:word):string4;
begin
hexW:=hexB(hi(n))+hexB(lo(n));
end;
function hexL(n:longint):string8;
begin
hexL:=hexW(n shr 16)+hexW(n);
end;
begin
if getVESAInfo then
with VESAinfo do begin
includeStandardVGAModes;
writeln(signature,' Version ',hexB(hi(version)),'.',hexB(version));
writeln(str);
writeln('Capabilities: $',hexL(caps));
p:=pointer(modeList);
while p^<>$FFFF do begin
write('Mode $',hexW(p^),' = ');
if getModeInfo(p^) then
with modeInfo do begin
if not(modeAvail in attr) then write('Unavailable-');
if modeColor in attr then write('Color ') else write('Mono ');
if modeGraphics in attr then write('Graphics') else write('Text');
if modeBIOSSupport in attr then write('-BIOSsupport');
writeln;
if modeExtendInfo in attr then
with extendedInfo do begin
write(' ',xRes,'x',yRes,', ',bitsPixel,' bits, ',modelStr[memModel],
', ',scanBytes,' bytes per row');
if not (modeGraphics in attr) then
write(^M^J' Character size ',xCharSize,'x',yCharSize);
if planes>1 then write(', ',planes,' planes');
if banks>1 then write(', ',banks,' banks of ',bankSize,'K');
writeln;
end
else write(' No extended info available');
if winSupported in winAAttr then begin
write(' Window A: ');
if winReadable in winAAttr then write('R');
if winWriteable in winAAttr then write('W');
writeln(' at segment $',hexW(winASeg),', ',winSize,'K, granular by '
,winGranularity,'K, function at $',hexL(longint(@winFunct)));
end;
if winSupported in winBAttr then begin
write(' Window B: ');
if winReadable in winBAttr then write('R');
if winWriteable in winBAttr then write('W');
writeln(' at segment $',hexW(winBSeg),', ',winSize,'K, granular by '
,winGranularity,'K, function at $',hexL(longint(@winFunct)));
end;
end
else writeln('ERROR');
inc(p);
end;
end
else writeln('No VESA driver found');
end;
begin
writeln;
displayVESAInfo;
readln;
m := findMode(0, 0, modelPacked, 8, 1, 1);
getModeInfo(m);
if m <> $FFFF then
with modeInfo.extendedInfo do
writeln('Found ', xRes, 'x', yRes, 'x',
longint(1) shl bitsPixel, ' mode ', m)
else
exit;
setMode(m);
for i := 1 to 10000 do
plot(random(xSize), random(ySize), random(256));
readln;
for i := 1 to 200 do
hlin(random(xSize shr 1), random(xSize shr 1) + xSize shr 1,
random(ySize), random(256));
readln;
asm
mov ax, 3h
int 10h
end;
end.
[Back to EGAVGA SWAG index] [Back to Main SWAG index] [Original]