[Back to EGAVGA SWAG index] [Back to Main SWAG index] [Original]
{
With all the tonnes of absolutely NO help that the Pascal conferences
provided me <in one day> I've managed to hack my VGA Font loading code
to work properly in p-mode.
It's quite a trick getting the DPMI servers to allocate memory under
the one meg mark, but it is possible if you write a couple of routines
like the ones below (or golly-gee, use those! :) ..
Oh yeah - one other tip. Those of you who use OpCrt, TpCrt, or maybe
even plain CRT. The ScreenHeight function will not return the correct
value after a font change (if the change is a new line mode) unless you
call ReInitCRT.
Here's the code:
}
Unit LF;
{$IFDEF Windows}
This will not work with Windows!
{$ENDIF}
{ Text-mode font routines }
{ (c)1994 Chris Lautenbach }
{ }
{ Date Revision Description }
{ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ }
{ Sep 07 94 1.0 Wrote real mode routines }
{ Sep 09 94 1.1 Added protected mode versions }
{ Notes: }
{ It is important to note, that under protected mode, the normal VGA BIOS }
{ extensions could not access the memory procured by GetMem(). This is why }
{ the SimulateRealModeInt() and XGlobalDosAlloc() routines were needed. }
{ XGlobalDosAlloc() allocates memory under the 1mb mark that the VGA BIOS is }
{ capable of accessing, and thereby allows font loads in p-mode. }
{ Any size/line font may be used. This is because I used subfunction $11 }
{ instead of $10. $11 will calculate the scanlines/etc required for the }
{ font you are loading by dividing the number of characters by the fonts }
{ total size (as does LoadFont(), so that we may properly allocate memory). }
{ I've tested 25, 33, 50, and 66 line mode fonts with it and they all work }
{ fine. Make sure the font you are loading is _pure_ binary, and does not }
{ contain header information for some sort of font editing/loading program. }
{ The calls to LoadFont() are identical in p-mode to real mode, so you won't }
{ need to do any code changes should you decide to switch between the modes }
{ later on. Nor is any special setup necessary. Just USE it, and load }
{ fonts, that's it! :) }
{ Restrictions: }
{ Don't you dare use this code for profit without proclaiming my name in a }
{ prominent place in your program! :) (Oh, and it don't work under Windoze }
{ but I'm sure you knew that...) }
INTERFACE
{$IFDEF DPMI}
Uses WinApi;
{$ENDIF}
function LoadFont(FileName : string) : boolean;
{ Loads a 255-character font from FileName to font 0 and sets it on }
procedure NormalFont;
{ Returns the system to the normal system 8x16 character font }
{ !! This routine works fine under p-mode without modifications since it }
{ does no memory allocation of any kind. }
IMPLEMENTATION
{$IFDEF DPMI}
Type LongRec = record
Selector, Segment : word;
end;
DoubleWord = record
Lo, Hi : word;
end;
QuadrupleByte = record
Lo, Hi, sLo, sHi : byte;
end;
TDPMIRegisters = record
EDI, ESI, EBP, Reserved, EBX, EDX, ECX, EAX : longint;
Flags, ES, DS, FS, GS, IP, CS, SP, SS : word;
end;
function XGlobalDosAlloc(Size : longint; var P : Pointer) : word;
{ Allocates memory in an area that DOS can access properly }
var Long : longint;
begin
Long := GlobalDosAlloc(Size);
P := Ptr(LongRec(Long).Selector, 0);
XGlobalDosAlloc := LongRec(Long).Segment;
end;
... Viper: The offline mail reader for the best of us.
___ Viper v2.0 [0004] * Multi-part message, 1 of 3 *
---
þ RoseMail 2.55á: NANet - Toronto Twilight (416)663-1103 - 7 Nodes
{SWAG=???.SWG,CHRIS LAUTENBACH,VGA Fonts, they work[2/3]}
function SimulateRealModeInt(IntNo : word;
var Regs : TDPMIRegisters) : word; assembler;
{ Simulates a real mode interrupt }
asm
PUSH BP { Save BP, just in case }
MOV BX,IntNo { Move the Interrupt number into BX }
XOR CX,CX { Clear CX }
LES DI,Regs { Load the registers into ES:DI }
MOV AX,$300 { Set function number to 300h }
INT $31 { Call Interrupt 31h - DPMI Services }
JC @Exit { Jump to exit on carry }
XOR AX,AX { Clear AX }
@Exit: { Exit label }
POP BP { Restore BP }
end;
function LoadFont(FileName : string) : boolean;
{ Loads a 255-character font from FileName to font 0 and sets it on }
var FontFile : file;
Font, Tmp : pointer;
S, O, FontSize, RMSeg, DPSel : word;
BPC : byte;
Regs : TDPMIRegisters;
begin
{$I-}
Assign(FontFile, FileName); { Open the file }
Reset(FontFile, 1); { Reset it }
{$I+}
If (IOResult <> 0) then { File opening was unsuccessful }
begin
LoadFont := FALSE; { Return FALSE }
Exit; { Return to caller }
end;
FontSize := FileSize(FontFile); { Get the font size }
FillChar(Regs, SizeOf(Regs), #0); { Clear the DPMI registers }
Regs.ES := XGlobalDosAlloc(FontSize, Font); { Allocate memory }
BlockRead(FontFile, Font^, FontSize); { Load the font }
BPC := FontSize DIV 256; { Calculate bytes per character }
Close(FontFile); { Close the font file }
DoubleWord(Regs.EBP).Hi := Regs.ES; { Load font address into ES:BP }
QuadrupleByte(Regs.EAX).Hi := $11; { Set function $11 }
QuadrupleByte(Regs.EAX).Lo := $10; { Set sub-function $10 }
QuadrupleByte(Regs.EBX).Hi := BPC; { Set # of bytes per character }
QuadrupleByte(Regs.EBX).Lo := $00; { Set font number to 0 }
DoubleWord(Regs.ECX).Lo := $FF; { # of chars to load = 256 }
DoubleWord(Regs.EDX).Lo := $0; { Set start char to 0 }
SimulateRealModeInt($10, Regs); { Call the interrupt }
GlobalDosFree(LongRec(Font).Selector); { Free up the memory }
LoadFont := TRUE; { Return TRUE - function successful! }
end;
{$ENDIF}
{$IFDEF MSDOS}
function LoadFont(FileName : string) : boolean;
{ Loads a 255-character font from FileName to font 0 and sets it on }
var FontFile : file;
Font, Tmp : pointer;
S, O, FontSize, RMSeg, DPSel : word;
BPC : byte;
begin
{$I-}
Assign(FontFile, FileName); { Open the file }
Reset(FontFile, 1); { Reset it }
{$I+}
If (IOResult <> 0) then { File opening was unsuccessful }
begin
LoadFont := FALSE; { Return FALSE }
Exit; { Return to caller }
end;
FontSize := FileSize(FontFile); { Get the font size }
GetMem(Font, FontSize); { Allocate memory for font }
BlockRead(FontFile, Font^, FontSize); { Load the font }
BPC := FontSize DIV 256; { Calculate bytes per character }
Close(FontFile); { Close the font file }
S := Seg(Font^); { Get segment of font }
O := Ofs(Font^); { Get offset of font }
asm
PUSH BP { Save BP }
MOV AL,$10 { Set sub-function $10 }
MOV AH,$11 { Set function $11 }
MOV BH,BPC { Set # of bytes per character }
MOV BL,$00 { Set font # to load }
MOV CX,$FF { Set # of chars to load }
MOV DX,$0 { Set start of load to character 0 }
MOV ES,S { Load segment of font to load }
MOV BP,O { Load offset of font to load }
INT $10 { Call BIOS Interrupt 10h }
POP BP { Restore BP }
end;
FreeMem(Font, FontSize); { Release allocated memory }
LoadFont := TRUE; { Return TRUE - function successful! }
end;
{$ENDIF}
procedure NormalFont; assembler;
{ Returns the system to the normal system 8x16 character font }
asm
MOV AL,$04 { Set sub-function 04h }
MOV AH,$11 { Set function 11h }
MOV BL,$00 { Select font 0 as the one to reset }
INT $10 { Call BIOS Interrupt 10h }
end;
begin
end.
[Back to EGAVGA SWAG index] [Back to Main SWAG index] [Original]