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

{
User font library for text mode.
}


{$IFDEF DPMI}
{$X+,S-}
{$ELSE}
{$X+,F+,O+}
{$ENDIF}
unit BBFont;

interface

const
  FontHeight = 16;   { 14 for EGA mode }

type
  PCharShape = ^TCharShape;
  TCharShape = array[0..FontHeight-1] of byte;

var
  points : word;


procedure ReplaceChar(c : char; NewChar : PCharShape);


implementation


{*******************************************************************}
{ Wen 03-mrt-1993 - wvl                                             }
{                                                                   }
{ Get font block index of current (resident) and alternate          }
{ character set. Up to two fonts can be active at the same time     }
{                                                                   }
{*******************************************************************}

Type
  FontBlock    = 0..7;


Procedure GetFontBlock(Var primary, secondary : FontBlock); Assembler;

ASM
  { Get character map select register:
    (VGA sequencer port 3C4h/3C5h index 3)

    7  6  5  4  3  2  1  0
          3  3  3  3  3  3
          3  3  3  3  @DDADD   Primary font   (lower 2 bits)
          3  3  @DDADDDDDDDD   Secondary font (lower 2 bits)
          3  @DDDDDDDDDDDDDD   Primary font   (high bit)
          @DDDDDDDDDDDDDDDDD   Secondary font (high bit)     }

        MOV     AL, 3
        MOV     DX, 3C4h
        OUT     DX, AL
        INC     DX
        IN      AL, DX
        MOV     BL, AL
        PUSH    AX

  { Get secondary font number: add up bits 5, 3 and 2 }

        SHR     AL, 1
        SHR     AL, 1
        AND     AL, 3
        TEST    BL, 00100000b
        JZ      @1
        ADD     AL, 4
@1:     LES     DI, secondary
        STOSB

  { Get primary font number: add up bits 4, 1 and 0 }

        POP     AX
        AND     AL, 3
        TEST    BL, 00010000b
        JZ      @2
        ADD     AL, 4
@2:     LES     DI, primary
        STOSB
end;  { GetFontBlock }



function postinc(var w : word) : word;  assembler;
asm
  les  di,w
  mov  ax,word ptr es:[di]
  inc  word ptr es:[di]
end;
{* pascal code
begin
  postinc := w;
  inc(w);
end;
*}


procedure ReplaceChar(c : char; NewChar : PCharShape);
var
  i : integer;
  off : word;
  CharPos : word;
  primfont, secfont : FontBlock;
  base : word;
begin

{* program the VGA controller *}
  asm
    pushf               { Disable interrupts }
    cli
    mov  dx, 03c4h      { Sequencer port address }
    mov  ax, 0704h      { Sequential addressing }
    out  dx, ax
    mov  dx, 03ceh      { Graphics Controller port address }
    mov  ax, 0204h      { Select map 2 for CPU reads }
    out  dx, ax
    mov  ax, 0005h      { Disable odd-even addressing }
    out  dx, ax
    mov  ax, 0406h      { Map starts at A000:0000 (64K mode) }
    out  dx, ax
    mov  dx, 03c4h      { Sequencer port address }
    mov  ax, 0402h      { CPU writes only to map 2 }
    out  dx, ax
  end;

{ first get the current font *}
  GetFontBlock(primfont, secfont);
  base := 8192*primfont;

  off := 16 - points;

  CharPos := Ord(c) * 32;

  for i := 0 to points-1 do  begin
    mem[SegA000:base+postinc(CharPos)] := NewChar^[postinc(off)];
  end;

{ Ok, put the Sequencer and Graphics Controller back to normal }

  asm

  { Program the Sequencer }
    pushf               { Disable interrupts }
    cli
    mov dx, 3c4h        { Sequencer port address }
    mov ax, 0302h       { CPU writes to maps 0 and 1 }
    out dx, ax
    mov ax, 0304h       { Odd-even addressing }
    out dx, ax

  { Program the Graphics Controller }
    mov dx, 3ceh        { Graphics Controller port address }
    mov ax, 0004h       { Select map 0 for CPU reads }
    out dx, ax
    mov ax, 1005h       { Enable odd-even addressing }
    out dx, ax;
    mov ax,Seg0040
    mov es,ax
    mov ax, 0e06h       { Map starts at B800:0000 }
    mov bl, 7
    cmp es:[49h], bl    { Get current video mode }
    jne @@notmono
    mov ax, 0806h       { Map starts at B000:0000 }
@@notmono:
    out dx, ax;
    popf;
  end;
end;


begin
  if (Mem[Seg0040:$0084] = 0)
   then  points := 8
   else  begin
     if Mem[Seg0040:$0084] in [42,49]
      then  points := 13
      else  points := Mem[Seg0040:$0085];
   end;
end.  { of unit BBFont }



program Test;

uses BBFont,...;

procedure TestFont;
const
  NewA:TCharShape = (
    $FF,  {11111111}
    $00,  {00000000}
    $FF,  {11111111}
    $00,  {00000000}
    $00,  {00000000}
    $00,  {00000000}
    $00,  {00000000}
    $00,  {00000000}
    $00,  {00000000}
    $00,  {00000000}
    $00,  {00000000}
    $00,  {00000000}
    $00,  {00000000}
    $00,  {00000000}
    $00,  {00000000}
    $00   {00000000}
  );
begin
  ReplaceChar('A', @NewA);
end;


begin
  TestFont;
end.



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