P R I N T R O M - F O N T M A C H I N E
Fonts in a Can by Larry Stone
You know how it goes - in the process of creating a nifty program,
you get side tracked on an even more nifty subprogram. Eventually,
this nifty subprogram turns into an extrodinary piece of work. Such
is the story behind PrintROMtable - a routine to produce a library of
graphics fonts without a font library!
The original PrintROMtable was developed for FUSION (published in
The QBNews vol 2, issue ?). Based upon code published by PC Magazine,
PrintROMtable was limited in it's scope. Because my time, like most
of us, is limited, I made an early release of the code on the Quik_BAS
internation echo, and asked others to join in it's development. The
responce was outstanding. Rob Smetana immediately jumped into it with
code to create italics. Francois Roy supplied code to elongate char-
acters for a bold appearance. Bill Beasley supplied code to create
tall characters, inspiring Mike Kelly to offer code that creates fonts
that are 8, 14, 16, 28, or 32 pixel points in height. Both Rob and
Mike supplied code to allow CGA systems access to the extended ASCII
set (characters 128 through 255). Of course, my contribution continued
with left-handed italics, underlined characters, inverse and backward
characters, strike through, stencil characters, double wide and even
condensed characters, and, not least of all, intergrating the various
code supplied by the other, aforementioned contributors, into the one
highly useful and variable module. You know how it goes - while in the
process of creating a nifty program, it goes on and on and on...
Before we get much further, you should know that PrintROM is run
from a test program called, ROMtest.bas, and, although ROMtest traps
and sets the screen to your highest resolution, the pixel positioning
is coded for SCREEN 12. This means that if your computer monitor can't
handle this resolution then you will see only some of the nifty things
displayed or, in some cases, some of the diplay will be outside of the
monitor's graphic boundaries (you can always tweek the xAxis and yAxis
locations coded in the ROMtest program to place any string into your
system's view area).
So, what's so special about PrintROMtable? Plenty! It is a huge
library of fonts without needing external libraries! The external libs
supplied provide extended ASCII set 128 through 255. These are not
necessary to the program unless your system is CGA and passes a string
containing a high ASCII character to PrintROMtable. Even if your pro-
gram runs on EGA or VGA, you may wish to include one or more of these
font files for the special characters they provide, such as the copy-
right and registered trade mark symbols (more on this subject later!)
PrintROMtable compiles to around a 13K object file - as small or smal-
ler than most "standard" font libraries! As small as this is, you are
provided fonts ranging from 8 to 64 pixels tall in condensed, normal,
bold, or double wide sizes; characters can be underlined, shadowed,
italic (slanted left or right), inverted, backwards, stenciled, or
contain a strike through mark. Furthermore, you can print from left
to right, right to left, top-down, bottom-up, or even at an angle!
PrintROMtable has limitations. CGA systems can only use characters
8 pixels tall - this can be expanded to 16 by setting PR.Tall = True.
EGA systems cannot access sizes 16, 32. However, EGA can have size 8
expanded to 16 by setting PR.Tall = True. If you try to have an EGA
system use font size 16 or 32, PrintROMtable will reset the size to 14
or 28, respectively. This means that using PR.Height = 32 and PR.Tall
equals True on EGA systems will produce a font 56 pixels high, not 64
as intended. Only VGA has the entire range of 8, 14, 16, 28, 32, 56
and 64 height characters.
The heart of PrintROMtable is it's code to access the where-abouts
of the ROM BIOS segment containing the character shape table.
Once PrintROMtable has the pointer into the ROM segment that con-
taining the character shape tables, it loops through the passed-in
string, once for each character in the string. If a background color
is called for, it uses LINE with a box and fill (BF) argument to paint
a background color. If a background color is not requested then the
background color is transparent. The code then loops 4, 8, 14, 16, 28
32, 56, or 64 times for each scan line of the character (depending on
such factors as PR.Height, PR.Condesned, and PR.Tall).
The 1st item of business is to determine what value, based upon the
font size, need to be loaded into the BX register so that a subsequent
call to BIOS interrupt 10h, function 1130h can point us to the correct
memory address containing our scan lines:
SELECT CASE PR.Height
CASE 8 ' 8x8 font
reg.bx = &H300
CASE 14, 28 ' 8x14 font or 8x14 font double high
reg.bx = &H200
CASE 16, 32 ' 8x16 font or 8x16 font double high
reg.bx = &H600
CLS : PRINT "Invalid Character Size": END
Having determined the BX value, PrintROMtable then sets AX = &H1130
before it calls BIOS Video Service, &H10:
reg.ax = &H1130
InterruptX &H10, reg, reg
ofst& = reg.bp
sgmt& = reg.es
For those with inquiring minds, function AX = 1130h is called with AX
and BX set as follows:
AX = 1130h
BX = pointer specifier
&H0 INT 1Fh pointer
&H100 INT 44h pointer
&H200 ROM 8 by 14 character font pointer
&H300 ROM 8 by 8 double dot font pointer
&H400 ROM 8 by 8 DD font (top half)
&H500 ROM alpha alternate (9 by 14) pointer
&H600 ROM alpha alternate (9 by 16) pointer
On return, the ROM BIOS function supplies:
ES:BP = specified pointer
CX = bytes/character
DL = character rows on screen
Even though PrintROMtable has the appropriate segment and offset to
the character shape table, they may not be correct! The above call to
the BIOS is only good for EGA, MCGA, or VGA systems. If PR.ScreenMode
is less than 7 or, if you tell PrintROMtable to force the CGA address
then PrintROMtable sets the character shape table's segment to &HFFA6.
IF PR.ForceAddress OR PR.ScreenMode < 7 THEN sgmt& = &HFFA6
Segment &HFFA6 contains the character table but, unlike our INT 10h
table pointer, this table only goes to the first 127 ASCII characters.
This means that if PR.ScreenMode is 1, 2, or 3 (same as SCREEN 1, 2,
or 3) or, if you instruct PrintROMtable to force the address then, you
cannot access the upper ASCII set without defining a disk font file.
Since the objective of all of the contributors to this program was
to create a self-contained, linkable module, we wanted to avoid asking
users to have to have, or load, a 3rd-party file just to access the
upper ASCII character set. Several people answered our call for ideas.
Mike Kelly was 1st to supply code to accomplish this aim. Although
his code was self-contained, it required 4k of memory to use the data.
Cornel Huth described an approach similar to the one eventually taken
with PrintROMtable: to use Int 1Fh to point to an array containing the
high characters. Similar approaches were suggested by Bill Beeler and
Dave Cleary. The final approach developed was by Rob Smetana and is
similar in operation to the DOS program, Graftabl. Unlike Graftabl,
Rob's approach does not require a TSR and it uses a meager 1024 bytes
of memory. It does, however, use small, 1024 byte external files.
External fonts are loaded by the routine with one GET statement:
j% = FREEFILE 'Get a handle
OPEN FontFile$ FOR BINARY AS #j% 'Open with this handle
font$ = SPACE$(1024) 'Our fonts need just 1024 bytes (128 * 8).
GET #1, , font$: CLOSE #j% 'Close file with handle j%
PrintROMtable is supplied with four disk font files that access the
characters used in international, U.S., Portuguese, and French-Canada
ASCII sets. There can be additional 1024 font files added to the list
by altering the appropriate area of the PrintROMtable routine. To add
a new font file, search PrintROMtable for:
'**** You could create your own 1024 byte
The code is self-expanatory and you should not have any trouble adding
to the list.
If your program is to access one or more of these font files, you
might want to establish a default file to use (if you don't designate
a default file then the routine sets the default to number 1 -- inter-
national). To set a default font file, before you make any calls to
PrintROMtable, LET PR.DefaultFile = ? Where ? is the number of the
file to use (presently, 1 through 4).
Whether a default font file is established or not, you can, at any
time, instruct the routine to load any of the font files. First, you
should reset the current font file:
PR.ReadHiAscFile = -1
CALL PrintROMtable(a$, PR)
Then, to set the new file, simply:
PR.ReadHiAscFile = 2 (or 3, or 4, etc.)
The next call to PrintROMtable will then read and use the new fonts.
If your font files are not located in the default path, before you
you make your first call to PRINTROMtable, you need to inform it where
to look. This, too, is a simple instruction:
LSET PR.DiskFontLoc = "C:\OFF\IN\URANUS"
Many QB programmers set their SCREEN mode by using literals, ie.,
they use code similar to, SCREEN 9. PrintROMtable needs to know what
screen you are using. To inform it which screen mode is in use, do
PR.ScreenMode = 12
Putting it all together, your program should look something like:
REM $INCLUDE: 'printrom.bi'
LSET PR.DiskFontLoc = "D:\SNAZZY\FONT\AREA\"
PR.DefaultFile = 1
PR.ScreenMode = 9
PR.Height = 8: PR.xAxis = 20: PR.yAxis = 30
PR.StepX = 9: PR.CharClr = 15: PR.Shadow = -1
PrintROMtable "Hello there, my name is", PR
PR.Tall = -1: PR.xAxis = 20: PR.yAxis = 48
PrintROMtable "John Doe", PR
When working from within the QB environment, you need to load QB
by typing, "QB /Lqb". The sample program that demonstrates how to use
PrintROMtable is named, "ROMTEST.BAS". It is in the file, PRINTROM.ZIP
along with PRINTROM.BI, and ROMTEST.MAK. Run QB with the "/Lqb" switch
then open the file RomTest.Bas. That's all you have to do.
One final note. PrintROMtable can do a great deal of fancy work to
your strings. The fancier your output, the more time required to per-
form the work. One saving grace is that all of the fancy manipulation
performed by PrintROMtable is considerably faster once compiled as an
EXE file. However, compiled or not, expect certain processes, such as
PR.Elongate = 2 (double wide) to be slower than the simpler processes
like 8 pixel high, normal character writes.
Larry Stone is President of LSRGroup and is involved in writing
instructional and large data base application systems for business and
institutional clients. He is also the author of SERVICES, a shareware
application program rated a trophy by "Public Brand Software". He can
be reached at LSRGroup, 2945 "A" Street, North Bend, OR 97459, or in
care of this newsletter.