program mirror_text;
{$G+,X+}
{
MIRROR2.PAS -- Demonstration of 512-character set application.
Written by Scott F. Earnest -- Donated to Public Domain
current e-mail address: sinykal@cyberspace.org
Thanks to Osmo Ronkanen (ronkanen@cc.helsinki.fi) for pointing out why I
couldn't get the 9x16 supplemental font set to work correctly.
This is a demonstration of one application of the 512-character font. It
loads a copy of the VGA 9x16 font into memory, modifies it and uses it to
display a 512-character set on screen.
Notes:
- 512-character fonts are also possible in EGA, but this code is set to
support VGA only.
- Originally it was my understanding that when using 512 characters, blink
or bright backgrounds were disabled. Now that I've played with this, I
see this isn't true; character set is chosen with bit 3, not bit 7.
Blinking is still possible. Though I haven't tested it, bright backrounds
will very likely not work, since color plane 3 must be disabled.
- This is written for TP7 and modified to compile under TP6. Earlier
versions may need extensive modifications in order to get this to
compile.
- Corrected in this version: This now correctly loads the entire 9x16
character set, so the mirrored font is now identical to original font
(except, of course, for the fact that it's been rotated around).
- This is very simple and could use lots of improvements, but I've tested
it and it DOES work on VGA. There's plenty of room for improvement, and
I think I've commented it well enough.
Please pass this around. It would also be a VERY useful addition to SWAG.
Use this freely, but if you use this or modify it, please give me due
credit, thanks!
}
{$IFNDEF VER60}
{$IFNDEF VER70}
STOP: This requires TP 6.0 or TP/BP 7.0x to compile!
{$ENDIF}
{$ENDIF}
uses
crt;
{$IFDEF VER60}
const
SegB800 = $b800;
{$ENDIF}
const
CHARSIZE = 4096; {Size of memory needed to store 9x16 font set}
type
{structures for storing/accessing a font in memory}
Tcharmap = array[0..CHARSIZE-1] of byte;
Pcharmap = ^Tcharmap;
Pbyte = ^byte;
procedure reverse_set (var m : Tcharmap);
{
This function takes a character set and rotates in 180 degrees. The
result is a cool upside-down character set.
}
var
ch : array [0..15] of byte;
b, c : byte;
function reverse_byte (b : byte) : byte; assembler;
asm
{setup:}
mov cx,0008h {iterate shift 8 times}
mov ah,[b] {number to be reversed}
xor al,al {clear AL to receive shifted value}
@1:
rcr ah,1 {shift lowest bit of AH into CF}
rcl al,1 {shift CF into lowest bit of AL}
loop @1
end;
procedure byteswap (var a, b : byte);
var
c : byte;
begin
c := a;
a := b;
b := c;
end;
begin
for c := 0 to 255 do
begin
move (m[c*16],ch,16); {get character into temporary array}
for b := 0 to 7 do
begin
{flip the character in array ch[]}
byteswap (ch[b],ch[15-b]);
ch[b] := reverse_byte (ch[b]);
ch[15-b] := reverse_byte(ch[15-b]);
end;
move (ch,m[c*16],16); {write modified char map back to font map}
end;
end;
function getcharsetptr (setnum : byte) : pointer; assembler;
{
This function uses the video BIOS to return the address of one of the
character sets in memory. Those sets are:
0 -- int 1fh, user 8x8 upper 128 characters
1 -- int 43h, user 8x8 lower/8x14
2 -- ROM 8x14
3 -- ROM 8x8 lower
4 -- ROM 8x8 upper
5 -- ROM 9x14 supplement
6 -- ROM 8x16
7 -- ROM 9x16 supplement
Other information is returned in CX and DL, however these are ingored by
this function.
}
asm
push bp
mov bh,[setnum]
mov ax,1130h
int 10h
mov dx,es
mov ax,bp
pop bp
end;
procedure Get9x16font (const base : PCharMap);
{
Loads supplemental font over allocated 8x16 font. My own implementation,
but based on code written by Osmo Ronkanen (ronkanen@cc.helsinki.fi). This
procedure was rewritten to eliminate some unneeded structures and reduce
memory requirements.
}
var
s, w : Pbyte;
c : byte;
begin
s := getcharsetptr (7);
while s^<>0 do
begin
w := Pbyte(base);
inc (w,s^*16);
inc (s);
move (s^,w^,16);
inc (s,16);
end;
end;
procedure installVGAfont (p : Pcharmap; block : byte); assembler;
{
Install a user font. 'p' is the pointer to the character map in memory,
and block is the font number to write. For VGA, valid values are 0-7.
Note: This procedure is hard-coded to write a 16-scanline-per-pixel
character set.
}
asm
push bp
mov ax,1110h
mov bl,[block]
mov bh,10h
les bp,[p]
mov cx,0100h
mov dx,0000h
int 10h
pop bp
end;
procedure set512characters; assembler;
{
This sets video to use two chained character sets. In this case, sets 0
and 1 are set to be used. This can be rewritten to accept two values,
which represent which 2 of the 8 sets to use.
}
asm
{step 1: disable color plane 3 -- keeps set B from always being bright}
mov ax,1000h
mov bl,12h
mov bh,07h
int 10h
{step 2: enable set A and B -- A=0 (the normal set) B=1 (modified set)}
mov ax,1103h
mov bl,00000100b
int 10h
end;
procedure reset256characters; assembler;
{
This performs the opposite of above to return to a single 256 character set.
}
asm
mov ax,1000h
mov bl,12h
mov bh,0fh
int 10h
mov ax,1103h
mov bl,00h
int 10h
end;
procedure waitkey;
begin
while keypressed do readkey;
repeat until keypressed;
while keypressed do readkey;
end;
procedure writechar (x, y : byte; ch : char; attr : byte);
{
This just writes a single character to video memory in a specific attribute.
}
var
m : word;
begin
m := (pred(y)*80+pred(x))*2;
mem[SegB800:m] := ord(ch);
mem[SegB800:succ(m)] := attr;
end;
var
mirrorfont : Pcharmap;
fp : pointer;
xp, yp : byte;
begin
{allocate memory for modified set}
new (mirrorfont);
{load font into memory}
fp := getcharsetptr (6);
move (fp^,mirrorfont^,CHARSIZE);
Get9x16font (mirrorfont);
{modify the character maps}
reverse_set (mirrorfont^);
{draw up a demonstration on the screen}
textattr := $17;
clrscr;
textattr := $1f;
gotoxy (26,4);
writeln ('!ereht olleH -- tset a si sihT');
textattr := $17;
gotoxy (26,5);
writeln ('This is a test -- Hello there!');
for yp := 0 to 7 do
for xp := 0 to 31 do
begin
writechar (6+xp,10+yp,chr(yp*32+xp),$17);
writechar (75-xp,17-yp,chr(yp*32+xp),$1f);
end;
gotoxy (1,22);
writeln ('This is before . . .');
{wait for a keypress}
waitkey;
{install the font}
installVGAfont (mirrorfont,1);
set512characters;
{now update the banner message and wait once more}
gotoxy (1,22);
textattr := $1f;
writeln ('!retfa si siht dna . . .');
waitkey;
{reset fonts and wait once more}
reset256characters;
gotoxy (1,22);
textattr := $17;
writeln ('And now back to normal! ');
waitkey;
{clean up memory and reset the video system}
dispose (mirrorfont);
asm mov ax,0003h; int 10h; end;
end.
--
Scott F. Earnest | We now return you to our regularly scheduled |
sinykal@cyberspace.org | chaos and mayhem. . . . |
               (
geocities.com/~franzglaser)