[Back to EGAVGA SWAG index] [Back to Main SWAG index] [Original]

    {
    I managed to write a unit called Fonts that will allow you to customise your
    EGA/VGA character sets and fonts like it is done in the Norton Utilities, save
    and restore them easily. There are given some different sizes for fonts:

    8x8        (VGA mode 80x50 or EGA mode 80x43)
    8x14       (EGA mode 80x25)
    8x16       (VGA mode 80x25)
    and
    9x16 (not currently supported)

    Each character represents the matrix with length of 8, 14, or 16 bytes. Here is
    the table for 8x8, 8x14 and 8x16 fonts, respectively:

    8x8 font        8x14 font       8x16 font

    00000000        00000000        00000000
    00000000        00000000        00000000
    00000000        00000000        00000000
    00000000        00000000        00000000
    00000000        00000000        00000000
    00000000        00000000        00000000
    00000000        00000000        00000000
    00000000        00000000        00000000
                    00000000        00000000
                    00000000        00000000
                    00000000        00000000
                    00000000        00000000
                    00000000        00000000
                    00000000        00000000
                                    00000000
                                    00000000

    So for 8x8 font there is array[0..255,1..8] of Byte, for 8x14 -
    array[0..255,1..14] of Byte, and for 8x16 - array[0..255,1..16] of Byte.

    How to reprogram a ASCII character so it will look 'as you would like it to
    be'?

    Single scan line of each character of any font type consists of 8 bits (1
    byte) each. Each font (as said earlier) has 8, 14, or 16 scan lines and will
    occupy whether 256*8=2048, 256*14=3584, or 256*16=4096 bytes (since there are
    0..255=256 bytes in the ASCII table).

    To define your own 'A' letter, for example, in font 8x8 you would need:

    1. To define first your own 8x8 matrix for 'A' character like shown below:

    00011111   hex 1F
    00110011   hex 33
    01100011   hex 63
    11000011   hex C3
    11000011   hex C3
    11111111   hex FF
    11000011   hex C3
    11000011   hex C3

    2. To replace active matrix of character 'A' with the new one using the Fonts
    unit do the following:

    Define a new 'A' character matrix for 8x8. NewA contains the buffer to load
    matrix from

    const
      NewA : array[1..8] of Byte = ($1F, $33, $63, $C3, $C3, $FF, $C3, $C3);

    Begin
      LoadCharset(NewA, Ord('A'), 1, 8)
    End.

    }

    Unit Fonts;
    { Copyright (c) 1994 by Andrew Eigus  Fidonet: 2:5100/33 }
    { Public Domain, ready for SWAG }

    (*
      This unit provides EGA/VGA font management routines and enables you
      to save/restore characters or charsets and also makes it easy for you
      to set your own (custom) characters or charsets in EGA/VGA modes

      8x8 font:  for EGA 80x43 or VGA 80x50 modes,
      8x14 font: for EGA 80x25 mode,
      8x16 font: for VGA 80x25 mode
    *)

    interface

    type
      { 8x8 font table type }
      P8x8Charset = ^T8x8Charset;
      T8x8Charset = array[0..255, 1..8] of Byte;

      { 8x14 font table type }
      P8x14Charset = ^T8x14Charset;
      T8x14Charset = array[0..255,1..14] of Byte;

      { 8x16 font table type }
      P8x16Charset = ^T8x16Charset;
      T8x16Charset = array[0..255, 1..16] of Byte;

    const
      { ROM table pointer request codes to use with #SaveROMFont#: }

      reqInt1F = 0; { return current Int 1Fh graphics font address }
      reqInt44 = 1; { return current Int 44h graphics font address }
      req8x14  = 2; { return ROM 8x14 font table address }
      req8x8   = 3; { return ROM 8x8 double dot font table address }
      req8x8t  = 4; { return ROM 8x8 double dot address (top) }
      req9x14  = 5; { return ROM 9x14 alternate table address }
      req8x16  = 6; { return ROM 8x16 font table address }

    function EGAInstalled : boolean;
    { Determines whether EGA/VGA is installed or not. If EGA/VGA is installed,
      True is returned and you may freely use all of those routines in this
      unit.

      See also #GetScanLines# }

    function GetScanLines : byte;
    { Performs auto detection of scan lines per one character in active video
      mode.

      for 80x43 EGA or 80x50 VGA mode - 8,
      for 80x25 EGA mode - 14,
      and
      for 80x25 VGA mode - 16 }

    procedure SaveCharset(var Buffer; StartChar, Count, ScanLines : word);
    { Saves Count characters from video memory into Buffer starting with
      StartChar ASCII code and using the ScanLines number for each character
      matrix. To determine number of scan lines in active video font,
      use function #GetScanLines#. (see #SaveFont# procedure) }

    procedure LoadCharset(var Buffer; StartChar, Count, ScanLines : word);
    { Loads Count characters from Buffer into video memory starting with
      StartChar ASCII code and using the ScanLines for each character matrix.
      To determine number of scan lines in active video font,
      use function #GetScanLines#. (see #LoadFont# procedure) }

    procedure LoadROMCharset(var Buffer; StartChar, Count, ScanLines : word);
    { Loads Count characters from ROM charset into video memory starting with
      StartChar ASCII code and using the ScanLines for each character matrix.
      To determine number a number of scan lines in active video font,
      use function #GetScanLines#. }

    procedure SaveROMFont(var Font; Code : byte);
    { Saves ROM font table into Buffer for the specified table pointer
      request code. See ROM table pointer request codes for more information. }

    procedure SaveFont(var Font; ScanLines : byte);
    { Saves the whole active video font into Buffer and uses the value of
      ScanLines to calculate the font size. }

    procedure LoadFont(var Font; ScanLines : byte);
    { Loads the whole into video memory and uses the value of
      ScanLines to calculate the font size. }

    implementation

    Procedure OpenRegs; near; assembler;
    { This is used internally and required by the unit }
    Asm
      cli
      mov dx,03C4h
      mov ax,0402h
      out dx,ax
      mov ax,0704h
      out dx,ax
      mov dl,0CEh { port 03CEh }
      mov ax,0204h
      out dx,ax
      mov ax,0005h
      out dx,ax
      mov ax,0406h
      out dx,ax
    End; { OpenRegs }

    Procedure CloseRegs; near; assembler;
    { This is used internally and required by the unit. }
    Asm
      mov dx,03C4h
      mov ax,0302h
      out dx,ax
      mov ax,0304h
      out dx,ax
      mov dl,0CEh { port 03CEh }
      mov ax,0004h
      out dx,ax
      mov ax,1005h
      out dx,ax
      mov es,Seg0040
      mov ax,0E06h
      cmp byte ptr es:[0049h],07h
      jne @color
      mov ax,0A06h
    @color:
      out dx,ax
      sti
    End; { CloseRegs }

    Function EGAInstalled; assembler;
    Asm
      mov ax,1200h
      mov bx,0010h
      xor cx,cx
      int 10h
      xor al,al { mov al,False }
      or  cx,0  { still cx the same? yes, there's no EGA }
      jz  @noega
      inc al { al gets True }
    @noega:
    End; { EGAInstalled }

    Function GetScanLines; assembler;
    Asm
      mov es,Seg0040
      mov al,byte ptr es:[0085h]
    End; { GetScanLines }

    Procedure SaveCharset; assembler;
    Asm
      call OpenRegs
      push ds
      mov ax,SegA000
      mov ds,ax
      mov ax,StartChar
      mov bx,32
      mul bx
      mov si,ax
      les di,Buffer
      cld
      mov ax,Count
      mul bx
      mov dx,ScanLines
    @@1:
      mov cx,dx
      rep movsb
      mov cx,bx
      sub cx,dx
      add si,cx
      sub ax,bx
      cmp ax,0
      jnz @@1
      pop ds
      call CloseRegs
    End; { SaveCharset }

    Procedure LoadCharset; assembler;
    Asm
      call OpenRegs
      push ds
      mov es,SegA000
      mov ax,StartChar
      mov bx,32
      mul bx
      mov di,ax
      mov ax,Count
      mul bx
      mov dx,ScanLines
      lds si,Buffer
      cld
    @@1:
      mov cx,dx
      rep movsb
      mov cx,bx
      sub cx,dx
      add di,cx
      sub ax,bx
      cmp ax,0
      jnz @@1
      pop ds
      call CloseRegs
    End; { LoadCharset }

    Procedure SaveROMFont; assembler;
    Asm
      mov ax,1130h
      mov bh,Code
      les bp,Font
      int 10h
    End; { SaveROMFont }

    Procedure LoadROMCharset; assembler;
    Asm
      mov ah,11h
      xor al,al
      mov cx,Count
      mov dx,StartChar
      xor bl,bl
      mov bh,byte ptr ScanLines
      les bp,Buffer
      int 10h
    End; { LoadROMCharset }

    Procedure SaveFont;
    Begin
      SaveCharset(Font, 0, 256, ScanLines)
    End; { SaveFont }

    Procedure LoadFont;
    Begin
      LoadCharset(Font, 0, 256, ScanLines)
    End; { LoadFont }

    End.

[Back to EGAVGA SWAG index] [Back to Main SWAG index] [Original]