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

(*
  Written by Yuval Melamed <melamed@star.net.il>, 25-Oct-1997.

  This is a very fast implementation of digit plotting on mode 13h.
  Infact, I could have made the array to include not only digits, but
  the whole ASCII table. The reason I didn't do that, is none but lack
  of time. I just showed you the basics, now go on and develope !

  One of the great things in this implementation, is the ability to use
  different colors, unlike standard bitmaps used in most games and stuff.

  As I always like to do, I have optimized this to work with 386+
  proccessors. I cannot believe someone still has his XT, right? :)
*)

var
  X, Y : Word;
  Color,
  Time : Byte;
  Count : Longint;

const
  (* The bitmap of the digits, $FF represent pixel: *)
  DigitMap : array[0..9, 1..5] of Longint =
    (($FFFFFF00, $FF00FF00, $FF00FF00, $FF00FF00, $FFFFFF00),  {0}
     ($FF000000, $FF000000, $FF000000, $FF000000, $FF000000),  {1}
     ($FFFFFF00, $FF000000, $FFFFFF00, $0000FF00, $FFFFFF00),  {2}
     ($FFFFFF00, $FF000000, $FFFFFF00, $FF000000, $FFFFFF00),  {3}
     ($FF00FF00, $FF00FF00, $FFFFFF00, $FF000000, $FF000000),  {4}
     ($FFFFFF00, $0000FF00, $FFFFFF00, $FF000000, $FFFFFF00),  {5}
     ($FFFFFF00, $0000FF00, $FFFFFF00, $FF00FF00, $FFFFFF00),  {6}
     ($FFFFFF00, $FF000000, $FF000000, $FF000000, $FF000000),  {7}
     ($FFFFFF00, $FF00FF00, $FFFFFF00, $FF00FF00, $FFFFFF00),  {8}
     ($FFFFFF00, $FF00FF00, $FFFFFF00, $FF000000, $FFFFFF00)); {9}

(* 386-optimized procedure to draw a digit on global X,Y, using the
   global Color. The only parameter to this procedure is the digit
   itself, in order to avoid confusions.                            *)
procedure PutDigit(Digit : Byte); assembler;
asm
  mov ax,0A000h {the video segment}
  mov es,ax

  mov ax,Y  {get Y}
  mov di,ax {copy Y}
  shl ax,6  {Y * 64}
  shl di,8  {Y * 256}
  add di,ax {Y * 64 + Y * 256 = Y * 320}
  add di,X  {Y * 320 + X = offset of (X,Y) in video segment}

  lea bx,DigitMap {get offset of digit's bitmap}
  mov al,20       {20 = SizeOf(Longint) * 5 = bytes in digit}
  mul Digit       {calculate offset of the digit's pixels}
  add bx,ax       {add offset to BX}

  mov cl,Color
  mov ch,cl
  db 66h; shl cx,16
  mov cl,Color
  mov ch,cl         {all bytes of ECX now contain the color value}

  db 66h; mov ax,cx          (* mov eax,ecx                              *)
  db 66h; and ax,[bx]        (* and eax,[bx]         {mask digit's line} *)
  dw 6626h; mov [di],ax      (* mov es:[di],eax      {draw digit's line} *)
  db 66h; mov ax,cx          (* mov eax,ecx                              *)
  db 66h; and ax,[bx+4]      (* and eax,[bx+4]                           *)
  dw 6626h; mov [di+320],ax  (* mov es:[di+320],eax  {draw 2nd line}     *)
  db 66h; mov ax,cx          (* mov eax,ecx                              *)
  db 66h; and ax,[bx+8]      (* and eax,[bx+8]                           *)
  dw 6626h; mov [di+640],ax  (* mov es:[di+640],eax  {draw 3rd line}     *)
  db 66h; mov ax,cx          (* mov eax,ecx                              *)
  db 66h; and ax,[bx+12]     (* and eax,[bx+12]                          *)
  dw 6626h; mov [di+960],ax  (* mov es:[di+960],eax  {draw 4th line}     *)
  db 66h; mov ax,cx          (* mov eax,ecx                              *)
  db 66h; and ax,[bx+16]     (* and eax,[bx+16]                          *)
  dw 6626h; mov [di+1280],ax (* mov es:[di+1280],eax {draw 5th line}     *)
end;

begin
  MemW[$0040:$001A] := MemW[$0040:$001C];
  asm
    mov ax,13h
    int 10h
  end;
  Randomize;
  X := 0;
  Y := 0;
  Color := 0;
  Count := 0;
  Time := Mem[$0040:$006C];
  while Mem[$0040:$006C] = Time do;
  Time := Mem[$0040:$006C];
  while Mem[$0040:$006C] = Time do begin
    PutDigit(Random(10));
    Inc(Count);
  end;
  Count := Trunc(Count * 18.217);
  Color := 15;
  X := (Trunc(Ln(Count) / Ln(10)) + 1) * 4;
  repeat
    PutDigit(Count mod 10);
    Count := Count div 10;
    Dec(X, 4);
  until Count = 0;
  Writeln;
  Writeln(' Random digits per second');
  Writeln(' (inside loop)');
  while MemW[$0040:$001A] = MemW[$0040:$001C] do;
  asm
    mov ax,3h
    int 10h
  end;
end.

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