Outils pour utilisateurs

Outils du site


back2root:archives:denthor:part-07

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
back2root:archives:denthor:part-07 [2021/09/02 11:10] – [In Closing] fraterback2root:archives:denthor:part-07 [2021/09/05 14:00] (Version actuelle) – [In Closing] frater
Ligne 394: Ligne 394:
 </code> </code>
  
 +==== Code Source ====
  
 +=== PASCAL ===
  
 +<code pascal>
 +(*****************************************************************************)
 +(*                                                                           *)
 +(* TUT7.PAS - VGA Trainer Program 7 (in Pascal)                              *)
 +(*                                                                           *)
 +(* "The VGA Trainer Program" is written by Denthor of Asphyxia.  However it  *)
 +(* was limited to Pascal only in its first run.  All I have done is taken    *)
 +(* his original release, translated it to C++, and touched up a few things.  *)
 +(* I take absolutely no credit for the concepts presented in this code, and  *)
 +(* am NOT the person to ask for help if you are having trouble.  -Snowman    *)
 +(*                                                                           *)
 +(* Program Notes : This program demonstrates animation.  Several of the      *)
 +(*                 functions have been converted to assembler.  This         *)
 +(*                 tutorial is a whopper, so just take your time.            *)
 +(*                                                                           *)
 +(* Author        : Grant Smith (Denthor)  - denthor@beastie.cs.und.ac.za     *)
 +(*                                                                           *)
 +(*****************************************************************************)
  
 +{$X+}
 +USES crt;
  
 +CONST VGA = $a000;
  
 +Type Toastinfo = Record                 { This is format of of each of our }
 +                 x,y:integer;              { records for the flying toasters }
 +                 speed,frame:integer;
 +                 active:boolean;
 +               END;
  
 +     icon = Array [1..30*48] of byte;  { This is the size of our pictures }
  
 +     Virtual = Array [1..64000] of byte;  { The size of our Virtual Screen }
 +     VirtPtr = ^Virtual;                  { Pointer to the virtual screen }
  
 +CONST frame1 : icon = (
 +0,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,
 +7,7,7,7,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,
 +5,7,7,7,7,7,7,7,8,8,7,7,7,7,7,7,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,5,5,7,7,7,7,7,8,8,7,8,8,7,8,7,8,7,7,7,5,8,8,8,8,5,5,5,5,5,5,5,5,5,5,5,
 +5,0,0,0,0,0,0,0,0,0,0,0,5,7,7,7,7,7,7,8,7,7,7,8,7,7,7,7,7,7,0,0,0,0,0,0,8,5,5,5,
 +5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,5,7,7,8,8,7,7,8,7,7,8,7,7,7,7,7,0,0,0,0,0,
 +0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,5,7,8,8,8,7,7,8,7,7,8,7,7,7,
 +7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,5,7,8,8,8,7,7,
 +8,8,8,8,8,8,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
 +9,5,7,8,8,8,8,8,7,7,8,8,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
 +1,1,1,1,9,9,9,9,5,7,7,8,8,8,8,7,7,8,8,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
 +1,1,0,0,0,1,1,1,1,1,1,1,9,9,9,5,7,8,8,7,7,8,8,7,8,8,8,7,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,5,7,8,8,7,7,7,7,8,8,7,7,7,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,7,8,8,8,8,8,8,8,7,
 +7,7,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,7,
 +7,7,7,7,7,7,7,7,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,
 +1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
 +1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,
 +2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,
 +2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,
 +1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,
 +4,6,6,6,6,6,6,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,3,3,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,
 +9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
 +9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
 +1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 +);
 +      frame2 : icon = (
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
 +9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
 +1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,
 +1,1,0,0,0,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,
 +2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,5,
 +5,5,5,5,5,5,5,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,
 +1,1,1,2,2,2,2,2,5,5,5,5,5,5,5,5,5,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
 +1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,5,5,5,5,5,5,5,5,5,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,5,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,5,5,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,5,5,5,5,
 +5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,
 +2,2,2,2,2,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,1,1,1,1,1,0,0,0,1,1,1,
 +1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,7,1,4,
 +4,6,6,6,6,6,6,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,5,5,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,5,5,1,1,1,1,1,1,1,1,1,3,3,1,1,1,1,9,9,9,9,9,9,9,9,9,9,5,5,
 +5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
 +9,9,9,9,9,9,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
 +1,1,1,1,9,9,9,9,9,9,9,9,9,9,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,
 +1,7,7,1,7,1,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,5,5,1,7,7,7,1,1,5,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,1,1,5,5,5,5,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,
 +5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 +);
 +      frame3 : icon = (
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
 +9,9,9,9,9,9,9,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,7,7,1,1,1,1,1,1,1,1,1,1,1,
 +1,1,1,1,9,9,9,9,9,9,9,9,9,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,7,1,1,1,1,1,
 +1,1,0,0,0,1,1,1,1,1,1,1,9,9,9,9,9,9,9,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,
 +0,7,1,1,7,7,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,7,7,7,7,5,5,5,5,5,5,
 +5,0,0,0,0,0,0,0,7,1,7,7,7,1,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,5,5,1,1,1,7,7,
 +1,1,7,5,5,5,5,5,5,5,0,0,0,0,0,0,1,1,7,1,1,7,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,
 +2,1,7,7,7,1,7,7,7,7,7,5,5,5,5,5,5,5,5,0,0,0,0,0,1,7,7,7,7,1,1,1,1,1,0,0,0,1,1,1,
 +1,1,1,2,2,2,2,2,2,1,7,7,7,7,7,7,7,1,1,5,5,5,5,5,5,5,5,5,0,0,0,0,7,7,1,7,1,7,1,1,
 +1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1,1,1,2,2,5,5,5,5,5,5,5,5,5,5,5,0,0,0,
 +7,7,7,7,7,1,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,
 +5,5,5,5,5,0,0,0,7,7,0,0,7,7,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,
 +2,2,5,5,0,0,5,5,0,5,5,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,
 +2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,
 +1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,
 +4,6,6,6,6,6,6,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,3,3,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,
 +9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
 +9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
 +1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 +);
  
  
 +VAR Virscr : VirtPtr;                      { Our first Virtual screen }
 +    VirScr2 : VirtPtr;                     { Our second Virtual screen }
 +    Vaddr  : word;                      { The segment of our virtual screen}
 +    Vaddr2 : Word;                      { The segment of our 2nd virt. screen}
 +    ourpal : Array [0..255,1..3] of byte; { A virtual pallette }
 +    toaster : Array [1..10] of toastinfo; { The toaster info }
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure SetMCGA;  { This procedure gets you into 320x200x256 mode. }
 +BEGIN
 +  asm
 +     mov        ax,0013h
 +     int        10h
 +  end;
 +END;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure SetText;  { This procedure returns you to text mode.  }
 +BEGIN
 +  asm
 +     mov        ax,0003h
 +     int        10h
 +  end;
 +END;
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure Cls (Col : Byte; Where:word);
 +   { This clears the screen to the specified color }
 +BEGIN
 +     asm
 +        push    es
 +        mov     cx, 32000;
 +        mov     es,[where]
 +        xor     di,di
 +        mov     al,[col]
 +        mov     ah,al
 +        rep     stosw
 +        pop     es
 +     End;
 +END;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
 +  { This puts a pixel on the screen by writing directly to memory. }
 +BEGIN
 +  Asm
 +    push    ds
 +    push    es
 +    mov     ax,[where]
 +    mov     es,ax
 +    mov     bx,[X]
 +    mov     dx,[Y]
 +    push    bx                      {; and this again for later}
 +    mov     bx, dx                  {; bx = dx}
 +    mov     dh, dl                  {; dx = dx * 256}
 +    xor     dl, dl
 +    shl     bx, 1
 +    shl     bx, 1
 +    shl     bx, 1
 +    shl     bx, 1
 +    shl     bx, 1
 +    shl     bx, 1                   {; bx = bx * 64}
 +    add     dx, bx                  {; dx = dx + bx (ie y*320)}
 +    pop     bx                      {; get back our x}
 +    add     bx, dx                  {; finalise location}
 +    mov     di, bx
 +    {; es:di = where to go}
 +    xor     al,al
 +    mov     ah, [Col]
 +    mov     es:[di],ah
 +    pop     es
 +    pop     ds
 +  End;
 +END;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +procedure WaitRetrace; assembler;
 +  {  This waits for a vertical retrace to reduce snow on the screen }
 +label
 +  l1, l2;
 +asm
 +    mov dx,3DAh
 +l1:
 +    in al,dx
 +    and al,08h
 +    jnz l1
 +l2:
 +    in al,dx
 +    and al,08h
 +    jz  l2
 +end;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure Pal(Col,R,G,B : Byte);
 +  { This sets the Red, Green and Blue values of a certain color }
 +Begin
 +   asm
 +      mov    dx,3c8h
 +      mov    al,[col]
 +      out    dx,al
 +      inc    dx
 +      mov    al,[r]
 +      out    dx,al
 +      mov    al,[g]
 +      out    dx,al
 +      mov    al,[b]
 +      out    dx,al
 +   end;
 +End;
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure GetPal(Col : Byte; Var R,G,B : Byte);
 +  { This gets the Red, Green and Blue values of a certain color }
 +Var
 +   rr,gg,bb : Byte;
 +Begin
 +   asm
 +      mov    dx,3c7h
 +      mov    al,col
 +      out    dx,al
 +
 +      add    dx,2
 +
 +      in     al,dx
 +      mov    [rr],al
 +      in     al,dx
 +      mov    [gg],al
 +      in     al,dx
 +      mov    [bb],al
 +   end;
 +   r := rr;
 +   g := gg;
 +   b := bb;
 +end;
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure SetUpVirtual;
 +   { This sets up the memory needed for the virtual screen }
 +BEGIN
 +  GetMem (VirScr,64000);
 +  vaddr := seg (virscr^);
 +  GetMem (VirScr2,64000);
 +  vaddr2 := seg (virscr2^);
 +END;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure ShutDown;
 +   { This frees the memory used by the virtual screen }
 +BEGIN
 +  FreeMem (VirScr,64000);
 +  FreeMem (VirScr2,64000);
 +END;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +procedure flip(source,dest:Word);
 +  { This copies the entire screen at "source" to destination }
 +begin
 +  asm
 +    push    ds
 +    mov     ax, [Dest]
 +    mov     es, ax
 +    mov     ax, [Source]
 +    mov     ds, ax
 +    xor     si, si
 +    xor     di, di
 +    mov     cx, 32000
 +    rep     movsw
 +    pop     ds
 +  end;
 +end;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure putico(X,Y:Word;VAR sprt : icon;Where:Word); ASSEMBLER;
 +  { This puts an icon, EXCEPT it's color 0 (black) pixels, onto the screen
 +    "where", at position X,Y }
 +label
 +  _Redraw, _DrawLoop, _Exit, _LineLoop, _NextLine, _Store, _NoPaint;
 +
 +asm
 +    push  ds
 +    push  es
 +    lds   si,Sprt
 +    mov   ax,    { ax = x }
 +    mov   bx,    { bx = y }
 +_Redraw:
 +    push    ax
 +    mov     ax,[where]
 +    mov     es,ax
 +
 +    mov     ax, bx                  {; ax = bx  x = y}
 +    mov     bh, bl                  {; y = y * 256  bx = bx * 256}
 +    xor     bl, bl
 +    shl     ax, 1
 +    shl     ax, 1
 +    shl     ax, 1
 +    shl     ax, 1
 +    shl     ax, 1
 +    shl     ax, 1                   {; y = y * 64   ax = ax * 64}
 +    add     bx, ax                  {; y = (y*256) + (Y*64)  bx = bx + ax (ie y*320)}
 +
 +    pop     ax                      {; get back our x}
 +
 +
 +    add     ax, bx                  {; finalise location}
 +    mov     di, ax
 +
 +    mov   dl,30    { dl = height of sprite }
 +    xor   ch,ch
 +    mov   cl,48     { cx = width of sprite }
 +    cld
 +    push  ax
 +    mov   ax,cx
 +_DrawLoop:
 +    push  di            { store y adr. for later }
 +    mov   cx,ax          { store width }
 +_LineLoop:
 +    mov   bl,byte ptr [si]
 +    or    bl,bl
 +    jnz   _Store
 +_NoPaint:
 +    inc    si
 +    inc    di
 +    loop   _LineLoop
 +    jmp    _NextLine
 +_Store:
 +    movsb
 +    loop  _LineLoop
 +_NextLine:
 +    pop   di
 +    dec   dl
 +    jz    _Exit
 +    add   di,320        { di = next line of sprite }
 +    jmp   _DrawLoop
 +_Exit:
 +    pop   ax
 +    pop   es
 +    pop   ds
 +end;
 +
 +
 +
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure Funny_line(a,b,c,d:integer;where:word);
 +  { This procedure draws a line from a,b to c,d on screen "where". After
 +    each pixel it plots, it increments a color counter for the next pixel.
 +    you may easily alter this to be a normal line procedure, and it will
 +    be quite a bit faster than the origional one I gave you. This is
 +    because I replaced all the reals with integers. }
 +
 +  function sgn(a:real):integer;
 +  begin
 +       if a>0 then sgn:=+1;
 +       if a<0 then sgn:=-1;
 +       if a=0 then sgn:=0;
 +  end;
 +var i,s,d1x,d1y,d2x,d2y,u,v,m,n:integer;
 +    count:integer;
 +begin
 +     count:=50;
 +     u:= c - a;
 +     v:= d - b;
 +     d1x:= SGN(u);
 +     d1y:= SGN(v);
 +     d2x:= SGN(u);
 +     d2y:= 0;
 +     m:= ABS(u);
 +     n := ABS(v);
 +     IF NOT (M>N) then
 +     BEGIN
 +          d2x := 0 ;
 +          d2y := SGN(v);
 +          m := ABS(v);
 +          n := ABS(u);
 +     END;
 +     s := m shr 1;
 +     FOR i := 0 TO m DO
 +     BEGIN
 +          putpixel(a,b,count,where);
 +          inc (count);
 +          if count=101 then count:=50;
 +          s := s + n;
 +          IF not (s<m) THEN
 +          BEGIN
 +               s := s - m;
 +               a:= a + d1x;
 +               b := b + d1y;
 +          END
 +          ELSE
 +          BEGIN
 +               a := a + d2x;
 +               b := b + d2y;
 +          END;
 +     end;
 +END;
 +
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure SetUpScreen;
 +  { This procedure sets up the static background to be used in the program }
 +
 +CONST circ : Array [1..5,1..5] of byte =
 +        ((0,10,10,10,0),
 +         (10,13,12,11,10),
 +         (10,12,12,11,10),
 +         (10,11,11,11,10),
 +         (0,10,10,10,0));
 +
 +VAR x,y:integer;
 +    loop1,loop2,loop3:integer;
 +
 +BEGIN
 +  pal (1,22,22,22);
 +  pal (2,45,45,45);
 +  pal (3,59,59,59);
 +  pal (4,63,63,27);
 +  pal (5,39,63,3);
 +  pal (6,51,39,3);
 +  pal (7,3,27,3);
 +  pal (8,15,39,15);
 +  pal (9,35,35,35);
 +  pal (10, 0, 0,40);
 +  pal (11,10,10,50);
 +  pal (12,20,20,60);
 +  pal (13,30,30,63);
 +
 +  For loop1:=50 to 100 do
 +    pal (loop1,0,0,loop1-36);
 +
 +  For loop1:=0 to 255 do
 +     getpal (loop1,OurPal[loop1,1],OurPal[loop1,2],OurPal[loop1,3]);
 +
 +  For loop1:=0 to 319 do
 +    Funny_line (0,199,loop1,0,vaddr);
 +  For loop1:=0 to 199 do
 +    Funny_line (0,199,319,loop1,vaddr);
 +
 +  For loop1:=1 to 200 do BEGIN
 +    x:=random (315);
 +    y:=random (195);
 +    For loop2:=1 to 5 do
 +      For loop3:=1 to 5 do
 +        if circ [loop2,loop3]<>0 then
 +          putpixel (x+loop2,y+loop3,circ [loop2,loop3],vaddr);
 +  END;
 +  flip (vaddr,vga);  { Copy the entire screen at vaddr, our virtual screen }
 +                     { on which we have done all our graphics, onto the    }
 +                     { screen you see, VGA }
 +  flip (vaddr,vaddr2);
 +END;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure rotatepal;
 +  { This procedure rotates the colors between 50 and 100 }
 +VAR temp : Array [1..3] of byte;
 +    loop1:integer;
 +BEGIN
 +  Move(OurPal[100],Temp,3);
 +  Move(OurPal[50],OurPal[51],50*3);
 +  Move(Temp,OurPal[50],3);
 +  For loop1:=50 to 100 do
 +    pal (loop1,OurPal[loop1,1],OurPal[loop1,2],OurPal[loop1,3]);
 +END;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure ScreenTrans (x,y:word);
 +  { This is a small procedure to copy a 30x30 pixel block from coordinates
 +    x,y on the virtual screen to coordinates x,y on the true vga screen }
 +BEGIN
 +  asm
 +    push    ds
 +    push    es
 +    mov     ax,vaddr
 +    mov     es,ax
 +    mov     ax,vaddr2
 +    mov     ds,ax
 +    mov     bx,[X]
 +    mov     dx,[Y]
 +    push    bx                      {; and this again for later}
 +    mov     bx, dx                  {; bx = dx}
 +    mov     dh, dl                  {; dx = dx * 256}
 +    xor     dl, dl
 +    shl     bx, 1
 +    shl     bx, 1
 +    shl     bx, 1
 +    shl     bx, 1
 +    shl     bx, 1
 +    shl     bx, 1                   {; bx = bx * 64}
 +    add     dx, bx                  {; dx = dx + bx (ie y*320)}
 +    pop     bx                      {; get back our x}
 +    add     bx, dx                  {; finalise location}
 +    mov     di, bx                  {; es:di = where to go}
 +    mov     si, di
 +    mov     al,60
 +    mov     bx, 30         { Hight of block to copy }
 +@@1 :
 +    mov     cx, 24         { Width of block to copy divided by 2 }
 +    rep     movsw
 +    add     di,110h        { 320 - 48 = 272 .. or 110 in hex }
 +    add     si,110h
 +    dec     bx
 +    jnz     @@1
 +
 +    pop     es
 +    pop     ds
 +  end;
 +  { I wrote this procedure late last night, so it may not be in it's
 +    most optimised state. Sorry :-)}
 +END;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure NewToaster;
 +  { This adds a new toaster to the screen }
 +VAR loop1:integer;
 +BEGIN
 +  loop1:=0;
 +  repeat
 +    inc (loop1);
 +    if not (toaster[loop1].active) then BEGIN
 +      toaster[loop1].x:=random (200)+70;
 +      toaster[loop1].y:=0;
 +      toaster[loop1].active:=true;
 +      toaster[loop1].frame:=1;
 +      toaster[loop1].speed:=Random (3)+1;
 +      loop1:=10;
 +    END;
 +  until loop1=10;
 +END;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure Fly;
 +  { This is the procedure where we move and put the toasters }
 +VAR loop1,loop2:integer;
 +    ch:char;
 +BEGIN
 +  For loop1:=1 to 10 do
 +    toaster[loop1].active:=FALSE;
 +  ch:=#0;
 +  NewToaster;
 +  Repeat
 +    if keypressed then BEGIN
 +      ch:=readkey;
 +      if ch='+' then NewToaster;      { If '+' is pressed, add a toaster }
 +      if ch='-' then BEGIN            { if '-' is pressed, remove a toaster }
 +        loop1:=0;
 +        repeat
 +          inc (loop1);
 +          if toaster[loop1].active then BEGIN
 +            screentrans (toaster[loop1].x,toaster[loop1].y);
 +            toaster [loop1].active:=FALSE;
 +            loop1:=10;
 +          END;
 +        until loop1=10;
 +      END;
 +    END;
 +    for loop1:=1 to 10 do
 +      if toaster[loop1].active then BEGIN
 +        screentrans (toaster[loop1].x,toaster[loop1].y);
 +          { Restore the backgrond the toaster was over }
 +        dec (toaster[loop1].x,toaster[loop1].speed);
 +        inc (toaster[loop1].y,toaster[loop1].speed);
 +          { Move the toaster }
 +        if (toaster[loop1].x<1) or (toaster[loop1].y>170) then BEGIN
 +          toaster[loop1].active:=FALSE;
 +          NewToaster;
 +        END;
 +          { When toaster reaches the edge of the screen, render it inactive
 +            and bring a new one into existance. }
 +      END;
 +    for loop1:=1 to 10 do
 +      if toaster[loop1].active then BEGIN
 +        CASE toaster [loop1].frame of
 +             : putico (toaster[loop1].x,toaster[loop1].y,frame1,vaddr);
 +             : putico (toaster[loop1].x,toaster[loop1].y,frame2,vaddr);
 +           2,4 : putico (toaster[loop1].x,toaster[loop1].y,frame3,vaddr);
 +        END;
 +        toaster[loop1].frame:=toaster[loop1].frame+1;
 +        if toaster [loop1].frame=5 then toaster[loop1].frame:=1;
 +          { Draw all the toasters on the VGA screen }
 +      END;
 +    waitretrace;
 +    flip (vaddr,vga);
 +    rotatepal;
 +  Until ch=#27;
 +END;
 +
 +
 +BEGIN
 +  Randomize;       { Make sure that the RANDOM funcion really is random }
 +  SetupVirtual;    { Set up virtual page, VADDR }
 +  ClrScr;
 +  writeln ('Hello! This program will demonstrate the principals of animation.');
 +  writeln ('The program will firstly generate an arb background screen to a');
 +  writeln ('virtual page, then flip it to the VGA. A toaster will then start');
 +  writeln ('to move across the screen. Note that the background will be restored');
 +  writeln ('after the toaster has passed over it. You may add or remove toasters');
 +  writeln ('by hitting "+" or "-" respectively. Note that the more frames you');
 +  writeln ('use, usually the better the routine looks. Because of space');
 +  writeln ('restrictions, we only had room for three frames.');
 +  writeln;
 +  writeln ('The toasters were drawn by Fubar (Pieter Buys) in Autodesk Animator.');
 +  writeln ('I wrote a small little program to convert them into CONSTANTS. See');
 +  writeln ('the main text to find out how to load up AA CEL files directly.');
 +  writeln;
 +  writeln;
 +  Write ('  Hit any key to contine ...');
 +  Readkey;
 +  SetMCGA;
 +  SetupScreen;     { Draw the background screen to VADDR, then flip it to
 +                     the VGA screen }
 +  Fly;             { Make the toasters fly around the screen }
 +  SetText;
 +  ShutDown;        { Free the memory taken up by virtual page }
 +  Writeln ('All done. This concludes the seventh sample program in the ASPHYXIA');
 +  Writeln ('Training series. You may reach DENTHOR under the names of GRANT');
 +  Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid');
 +  Writeln ('Connectix BBS user, which is unfortunatly offline for the moment.');
 +  Writeln ('For discussion purposes, I am also the moderator of the Programming');
 +  Writeln ('newsgroup on the For Your Eyes Only BBS.');
 +  Writeln ('The numbers are available in the main text. You may also write to me at:');
 +  Writeln ('             Grant Smith');
 +  Writeln ('             P.O. Box 270');
 +  Writeln ('             Kloof');
 +  Writeln ('             3640');
 +  Writeln ('I hope to hear from you soon!');
 +  Writeln; Writeln;
 +  Write   ('Hit any key to exit ...');
 +  Readkey;
 +END.
 +</code>
 +
 +=== C ===
 +
 +<code c>
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// TUTPROG7.CPP - VGA Trainer Program 7 (in Turbo C++ 3.0)                 //
 +//                                                                         //
 +// "The VGA Trainer Program" is written by Denthor of Asphyxia. However it //
 +// was limited to only Pascal in its first run.  All I have done is taken  //
 +// his original release, translated it to C++ and touched up a few things. //
 +// I take absolutely no credit for the concepts presented in this code and //
 +// am NOT the person to ask for help if you are having trouble.            //
 +//                                                                         //
 +// Program Notes : This program demonstrates animation.  Several of the    //
 +//                 functions have been converted to assembler.  This       //
 +//                 tutorial is a whopper, so just take your time.          //
 +//                                                                         //
 +//                 If you are compiling this program from within the       //
 +//                 Turbo C++ environment, you must go under Options,       //
 +//                 Debugger, and change the "Program Heap Size" to a value //
 +//                 132 or greater.  If you are going to be fooling around  //
 +//                 with the code a bit, I suggest raising this to about    //
 +//                 150 just to be on the safe side.  You don't have to     //
 +//                 worry about this if you are compiling command line.     //
 +//                                                                         //
 +//                 Just for reference, this is what I use:                 //
 +//                                                                         //
 +//                    tcc tut7 -mc -a -G -2 -O                             //
 +//                                                                         //
 +//                 The Compact memory model (-mc) seems to provide the     //
 +//                 best results for this tutorial.  Remember, use this     //
 +//                 memory model when you have little code (less than 64k)  //
 +//                 and lots of data.                                       //
 +//                                                                         //
 +// Author        : Grant Smith (Denthor) - denthor@beastie.cs.und.ac.za    //
 +// Translator    : Christopher G. Mann   - r3cgm@dax.cc.uakron.edu         //
 +//                                                                         //
 +// Last Modified : January 6, 1995                                         //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +//               //
 +// INCLUDE FILES //
 +//               //
 +
 +  #include <alloc.h>
 +                           // farcalloc()
 +  #include <conio.h>
 +                           // clrscr(), getch(), kbhit()
 +  #include <dos.h>
 +                           // FP_SEG, geninterrupt()
 +  #include <iostream.h>
 +                           // cout, memmove()
 +  #include <stdlib.h>
 +                           // abs(), exit(), randomize(), random()
 +
 +//          //
 +// TYPEDEFS //
 +//          //
 +
 +  typedef unsigned char byte;
 +  typedef unsigned int  word;
 +
 +//              //
 +// TOASTER DATA //
 +//              //
 +
 +const byte FRAME1[] = {
 +0,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,
 +7,7,7,7,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,
 +5,7,7,7,7,7,7,7,8,8,7,7,7,7,7,7,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,5,5,7,7,7,7,7,8,8,7,8,8,7,8,7,8,7,7,7,5,8,8,8,8,5,5,5,5,5,5,5,5,5,5,5,
 +5,0,0,0,0,0,0,0,0,0,0,0,5,7,7,7,7,7,7,8,7,7,7,8,7,7,7,7,7,7,0,0,0,0,0,0,8,5,5,5,
 +5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,5,7,7,8,8,7,7,8,7,7,8,7,7,7,7,7,0,0,0,0,0,
 +0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,5,7,8,8,8,7,7,8,7,7,8,7,7,7,
 +7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,5,7,8,8,8,7,7,
 +8,8,8,8,8,8,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
 +9,5,7,8,8,8,8,8,7,7,8,8,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
 +1,1,1,1,9,9,9,9,5,7,7,8,8,8,8,7,7,8,8,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
 +1,1,0,0,0,1,1,1,1,1,1,1,9,9,9,5,7,8,8,7,7,8,8,7,8,8,8,7,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,5,7,8,8,7,7,7,7,8,8,7,7,7,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,7,8,8,8,8,8,8,8,7,
 +7,7,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,7,
 +7,7,7,7,7,7,7,7,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,
 +1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
 +1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,
 +2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,
 +2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,
 +1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,
 +4,6,6,6,6,6,6,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,3,3,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,
 +9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
 +9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
 +1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 +};
 +
 +const byte FRAME2[] = {
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
 +9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
 +1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,
 +1,1,0,0,0,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,
 +2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,5,
 +5,5,5,5,5,5,5,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,
 +1,1,1,2,2,2,2,2,5,5,5,5,5,5,5,5,5,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
 +1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,5,5,5,5,5,5,5,5,5,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,5,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,5,5,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,5,5,5,5,
 +5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,
 +2,2,2,2,2,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,1,1,1,1,1,0,0,0,1,1,1,
 +1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,7,1,4,
 +4,6,6,6,6,6,6,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,5,5,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,5,5,1,1,1,1,1,1,1,1,1,3,3,1,1,1,1,9,9,9,9,9,9,9,9,9,9,5,5,
 +5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
 +9,9,9,9,9,9,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
 +1,1,1,1,9,9,9,9,9,9,9,9,9,9,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,
 +1,7,7,1,7,1,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,5,5,1,7,7,7,1,1,5,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,1,1,5,5,5,5,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,
 +5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 +};
 +
 +const byte FRAME3[] = {
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
 +9,9,9,9,9,9,9,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,7,7,1,1,1,1,1,1,1,1,1,1,1,
 +1,1,1,1,9,9,9,9,9,9,9,9,9,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,7,1,1,1,1,1,
 +1,1,0,0,0,1,1,1,1,1,1,1,9,9,9,9,9,9,9,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,
 +0,7,1,1,7,7,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,7,7,7,7,5,5,5,5,5,5,
 +5,0,0,0,0,0,0,0,7,1,7,7,7,1,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,5,5,1,1,1,7,7,
 +1,1,7,5,5,5,5,5,5,5,0,0,0,0,0,0,1,1,7,1,1,7,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,
 +2,1,7,7,7,1,7,7,7,7,7,5,5,5,5,5,5,5,5,0,0,0,0,0,1,7,7,7,7,1,1,1,1,1,0,0,0,1,1,1,
 +1,1,1,2,2,2,2,2,2,1,7,7,7,7,7,7,7,1,1,5,5,5,5,5,5,5,5,5,0,0,0,0,7,7,1,7,1,7,1,1,
 +1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1,1,1,2,2,5,5,5,5,5,5,5,5,5,5,5,0,0,0,
 +7,7,7,7,7,1,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,
 +5,5,5,5,5,0,0,0,7,7,0,0,7,7,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,
 +2,2,5,5,0,0,5,5,0,5,5,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,
 +2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,
 +1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,
 +4,6,6,6,6,6,6,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,3,3,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,
 +9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
 +9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
 +1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 +};
 +
 +//           //
 +// CONSTANTS //
 +//           //
 +
 +  const VGA = 0xa000;         // The address of our VGA screen
 +  const ICON = 30*48;         // This is the size of our pictures
 +  const NUMTOASTERS = 10;     // The maximum number of toasters we have
 +  const NUMCIRCLES = 200;     // The number of little circles on the screen
 +  const TRUE = 1;
 +  const FALSE = 0;
 +
 +//                     //
 +// FUNCTION PROTOTYPES //
 +//                     //
 +
 +  // GENERAL VIDEO TOOLS
 +  void SetMCGA     ();
 +  void SetText     ();
 +  void Cls         (byte Col, word Where);
 +  void Putpixel    (word X, word Y, byte Col, word Where);
 +  void WaitRetrace ();
 +  void Pal         (byte Col, byte  R, byte  G, byte  B);
 +  void GetPal      (byte Col, byte &R, byte &G, byte &B);
 +
 +  // MID-LEVEL FUNCTIONS
 +  void SetUpVirtual();
 +  void ShutDown    ();
 +  void Flip        (word source, word dest);
 +  void Putico      (word X, word Y, const byte *sprt, word Where);
 +  void Funny_line  (int a, int b, int c, int d, word where);
 +   int sgn         (int a);
 +  void SetUpScreen ();
 +  void Rotatepal   ();
 +  void ScreenTrans (word x, word y);
 +  void NewToaster  ();
 +  void Fly         ();
 +
 +//            //
 +// STRUCTURES //
 +//        //
 +
 +  struct Toastinfo {
 +    int      x;
 +    int      y;
 +    word     speed;
 +    word     frame;
 +    byte     active;
 +  };
 +
 +//                              //
 +// GLOBAL VARIABLE DECLARATIONS //
 +//                              //
 +
 +  byte far *Virscr1=NULL, *Virscr2=NULL;  // Pointers to both virtual screens
 +  word Vaddr1, Vaddr2;                    // Segments of both virtual screens
 +  byte ourpal[256][3];                    // A virtual pallette
 +  Toastinfo toaster[NUMTOASTERS];         // The toaster info
 +
 +
 +///////////////////////////////////////////////////////////////////////////////
 +//                                                                           //
 +//                                MAIN FUNCTION                              //
 +//                                                                           //
 +///////////////////////////////////////////////////////////////////////////////
 +
 +void main() {
 +
 +  randomize();    // Make sure that the random() function really is random
 +  SetUpVirtual(); // Set up the virtual screens and get their segments
 +
 +  clrscr();
 +  cout
 +    << "Hello! This program will demonstrate the principals of animation.\n"
 +    << "The program will firstly generate an arb background screen to a\n"
 +    << "virtual page, then flip it to the VGA. A toaster will then start\n"
 +    << "to move across the screen. Note that the background will be restored\n"
 +    << "after the toaster has passed over it. You may add or remove toasters\n"
 +    << "by hitting ""+"" or ""-"" respectively. Note that the more frames you\n"
 +    << "use, usually the better the routine looks. Because of space\n"
 +    << "restrictions, we only had room for three frames.\n\n";
 +  cout
 +    << "The toasters were drawn by Fubar (Pieter Buys) in Autodesk Animator.\n"
 +    << "I wrote a small little program to convert them into CONSTANTS. See\n"
 +    << "the main text to find out how to load up AA CEL files directly.\n\n\n";
 +  cout << "Hit any key to continue...";
 +  getch();
 +
 +  SetMCGA();
 +  SetUpScreen();  // Draw background screen to Vaddr1, then flip to VGA
 +  Fly();          // Make the toasters fly around the screen.
 +  SetText();
 +  ShutDown();     // Free the memory taken up by virtual pages
 +
 +  cout
 +    << "All done. This concludes the seventh sample program in the ASPHYXIA\n"
 +    << "Training series. You may reach DENTHOR under the names of GRANT\n"
 +    << "SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid\n"
 +    << "Connectix BBS user, which is unfortunatly offline for the moment.\n"
 +    << "For discussion purposes, I am also the moderator of the Programming\n"
 +    << "newsgroup on the For Your Eyes Only BBS.\n"
 +    << "The numbers are available in the main text. You may also write to me at:\n"
 +    << "             Grant Smith\n"
 +    << "             P.O. Box 270\n"
 +    << "             Kloof\n"
 +    << "             3640\n"
 +    << "I hope to hear from you soon!\n\n\n";
 +  cout << "Hit any key to exit...";
 +  getch();
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// SetMCGA() - This function gets you into 320x200x256 mode.               //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void SetMCGA() {
 +  _AX = 0x0013;
 +  geninterrupt (0x10);
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// SetText() - This function gets you into text mode.                      //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void SetText() {
 +  _AX = 0x0003;
 +  geninterrupt (0x10);
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// Cls() - This clears the screen at location Where to color Col           //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void Cls(byte Col, word Where) {
 +  asm {
 +    push    es           // save ES
 +    mov     cx, 32000    // this is our loop counter.  we want to clear
 +                         //   64000 bytes of memory, so why do we use 32000?
 +                         //   1 word = 2 bytes, and we are moving a word at
 +                         //   a time
 +    mov     es, [Where]  // move address in Where to ES
 +    xor     di, di       // zero out DI
 +    mov     al, [Col]    // move color to AL
 +    mov     ah, al       // move color to AH (Remember, will be moving
 +                         //   a WORDS, so we need two copies
 +    rep     stosw        // copy AX to Where and drecrement CX by 1
 +                         //   until CX equals 0
 +    pop     es           // restore ES
 +  }
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// Putpixel() - This puts a pixel on the screen by writing directly to     //
 +//              memory.                                                    //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void Putpixel (word X, word Y, byte Col, word Where) {
 +  asm {
 +    push    ds           // save DS
 +    push    es           // save ES
 +    mov     ax, [Where]  // move segment of Where to AX
 +    mov     es, ax       // set ES to segment of Where
 +    mov     bx, [X]      // set BX to X
 +    mov     dx, [Y]      // set DX to Y
 +    push    bx           // save BX (our X value)
 +    mov     bx, dx       // now BX and DX are equal to Y
 +    mov     dh, dl       // copy DL to DH (multiply Y by 256)
 +    xor     dl, dl       // zero out DL
 +    shl     bx, 6        // shift BX left 6 places (multiply Y by 64).
 +    add     dx, bx       // add BX to DX (Y*64 + Y*256 = Y*320)
 +    pop     bx           // restore BX (X coordinate)
 +    add     bx, dx       // add BX to DX (Y*320 + X).  this gives you
 +                         //   the offset in memory you want
 +    mov     di, bx       // move the offset to DI
 +    xor     al, al       // zero out AL
 +    mov     ah, [Col]    // move value of Col into AH
 +    mov     es:[di], ah  // move Col to the offset in memory (DI)
 +    pop     es           // restore ES
 +    pop     ds           // restore DS
 +  }
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// WaitRetrace() - This waits until you are in a Verticle Retrace.         //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void WaitRetrace() {
 +
 +  asm mov dx,0x03DA
 +
 +  l1: asm {
 +    in      al,dx;
 +    and     al,0x08;
 +    jnz     l1;
 +  }
 +  l2: asm {
 +    in      al,dx;
 +    and     al,0x08;
 +    jz      l2;
 +  }
 +
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// Pal() - This sets the Red, Green, and Blue values of a certain color.   //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void Pal (byte Col, byte  R, byte  G, byte  B) {
 +  asm {
 +    mov     dx, 0x3C8    // load DX with 3C8 (write pallette function)
 +    mov     al, [Col]    // move color to AL
 +    out     dx, al       // write DX to the VGA (tell VGA that we want to
 +                         //   work with the color in AL
 +    inc     dx           // load DX with 3C9 (write RGB colors)
 +    mov     al, [R]      // move Red   to AL
 +    out     dx, al       // write DX to VGA (tell VGA that we want to use
 +                         //   the Red value in AL
 +    mov     al, [G]      // move Green to AL
 +    out     dx, al       // write DX to VGA
 +    mov     al, [B]      // move Blue  to AL
 +    out     dx, al       // write DX to VGA
 +  }
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// GetPal() - This reads the values of the Red, Green, and Blue values of  //
 +//            a certain color.  This function uses pass-by-reference.      //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void GetPal (byte Col, byte &R, byte &G, byte &B) {
 +
 +  byte rr,gg,bb;
 +
 +  asm {
 +    mov     dx, 0x03C7   // load DX with 3C7 (read pallette function)
 +    mov     al, [Col]    // move color to AL
 +    out     dx, al       // write DX to the VGA (tell VGA that we want to
 +                         //   work with the color in AL
 +    add     dx, 2        // load DX with 3C9 (read RGB colors)
 +    in      al, dx       // read Red   to AL
 +    mov     [rr],al      // copy AL to rr
 +    in      al, dx       // read Green to AL
 +    mov     [gg],al      // copy AL to gg
 +    in      al, dx       // read Blue  to AL
 +    mov     [bb],al      // copy AL to bb
 +  }
 +
 +  R = rr;
 +  G = gg;
 +  B = bb;
 +
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// SetUpVirtual() - This sets up the memory needed for the virtual screen. //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void SetUpVirtual() {
 +
 +  Virscr1 = (byte far *) farcalloc(64000,1);
 +  Virscr2 = (byte far *) farcalloc(64000,1);
 +
 +  // always check to see if enough memory was allocated
 +  if ((Virscr1 == NULL) || (Virscr2 == NULL)) {
 +    SetText();
 +    cout << "Insufficient memory for virtual screens, exiting...";
 +    free(Virscr1);  // on the off chance that it allocated 1 but not 2,
 +            // deallocate the first.
 +    exit(1);
 +  }
 +
 +  Vaddr1 = FP_SEG(Virscr1);
 +  Vaddr2 = FP_SEG(Virscr2);
 +
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// ShutDown() - This frees the memory used by the virtual screen.          //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void ShutDown() {
 +
 +//  free(Virscr1);
 +//  free(Virscr2);
 +
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// Flip() - This copies the entire screen at "source" to destination.      //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void Flip(word source, word dest) {
 +  asm {
 +    push    ds           // save DS
 +    mov     ax, [dest]   // copy segment of destination to AX
 +    mov     es, ax       // set ES to point to destination
 +    mov     ax, [source] // copy segment of source to AX
 +    mov     ds, ax       // set DS to point to source
 +    xor     si, si       // zero out SI
 +    xor     di, di       // zero out DI
 +    mov     cx, 32000    // set our counter to 32000
 +    rep     movsw        // move source to destination by words.  decrement
 +                         //   CX by 1 each time until CX is 0
 +    pop     ds           // restore DS
 +  }
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// Putico() - This puts an icon, EXCEPT it's color 0 (black) pixels, onto  //
 +//            the screen "where", at position X,Y                          //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void Putico(word X, word Y, const byte *sprt, word Where) {
 +  asm {
 +    push    ds           // save DS
 +    push    es           // save ES
 +    lds     si, [sprt]   // set SI to offset of sprite
 +    mov     ax, X        // set AX equal to X
 +    mov     bx, Y        // set BX equal to Y
 +  }
 +  _Redraw: asm {
 +    push    ax           // save AX (X coordinate)
 +    mov     ax, [Where]  // copy segment of Where to AX
 +    mov     es, ax       // set ES to segment of Where
 +    mov     ax, bx       // set AX to BX (X)
 +    mov     bh, bl       // copy BL to BH (multiply Y by 256)
 +    xor     bl, bl       // zero out BL
 +    shl     ax, 6        // multiply AX by 64 (Y * 64)
 +    add     bx, ax       // add AX to BX (Y*64 + Y*256 = Y*320)
 +    pop     ax           // restore BX (X coordinate)
 +    add     ax, bx       // add BX to AX (Y*320 + X).  this gives you
 +                         //   the offset in memory you want
 +    mov     di, ax       // move the offset to DI
 +    mov     dl, 30       // set DL to height of sprite
 +    xor     ch, ch       // zero out CH
 +    mov     cl, 48       // set CL to width of sprite
 +    cld                  // clear direction flag.  if you did not do this,
 +                         //   the loop would go backward instead of forward
 +    push    ax           // save AX (offset in memory where you draw)
 +    mov     ax, cx       // set AX to CX (width)
 +  }
 +  _DrawLoop: asm {
 +    push    di           // save DI (offset in memory where you draw)
 +    mov     cx, ax       // set CX to AX (width)
 +  }
 +  _LineLoop: asm {       // DRAW THE DATA
 +    mov     bl,byte ptr [si]
 +                         // load byte of data from sprite to BL
 +    or      bl, bl       // no effect, but triggers zero flag
 +    jnz     _Store       // if previous statement did not trigger zero flag
 +                         //   (BL was not color 0) then jump to _Store
 +                         //   (write it to the screen).  in the description
 +                         //   of this function, it said that we would not be
 +                         //   putting color 0 on the screen, so the next
 +  }                      //   section skips over the pixel if it was 0.
 +
 +  _NoPaint: asm {        // SKIP OVER COLOR 0
 +    inc     si           // increment SI (skip to next pixel)
 +    inc     di           // increment DI (skip to next pixel)
 +    loop    _LineLoop    // decrement CX and jump to _LineLoop if CX is
 +                         //   not 0 (end of line)
 +    jmp     _NextLine    // if CX is 0 (end of line) jump to _NextLine
 +  }
 +  _Store: asm {          // COPY THE DATA
 +    movsb                // move the byte that DS:SI is pointing to into
 +                         //   ES:DI and increment SI and DI.
 +    loop    _LineLoop    // decrement CX and jump to _LineLoop if CX is
 +  }                      //   not 0 (end of line)
 +
 +  _NextLine: asm {       // START A NEW LINE
 +    pop     di           // restore address of line just drawn
 +    dec     dl           // decrement DL (height)
 +    jz      _Exit        // when DL equals 0, you are done drawing the sprite
 +    add     di, 320      // if not end of sprite, add 320 to DI so that we
 +                         //   start drawing the sprite on the next line
 +    jmp     _DrawLoop    // go back to _DrawLoop and start drawing the next
 +  }                      //   line
 +
 +  _Exit: asm {           // WE ARE DONE DRAWING THE SPRITE
 +    pop     ax           // restore AX
 +    pop     es           // restore ES
 +    pop     ds           // restore DS
 +  }
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// sgn() - This function is used by Line() to determine the sign of a long //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +int sgn (int a) {
 +
 +  if (a > 0)  return +1;
 +  if (a < 0)  return -1;
 +  return 0;
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// Funny_line() - This function draws a line from a,b, to c,d on screen    //
 +//                "where" After it plots each pixel, it increments a     //
 +//                color counter for the next pixel.  You may easily alter  //
 +//                this to be a normal line function, and it will be quite  //
 +//                a bit faster than the original one I gave you.  This is  //
 +//                because I replaced all the floats with integers.         //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void Funny_line (int a, int b, int c, int d, word where) {
 +
 +int i,s,d1x,d1y,d2x,d2y,u,v,m,n,count;
 +
 +  count = 50;
 +  u = c - a;       // u = x2 - x1  (change in x)
 +  v = d - b;       // v = y2 - y1  (change in y)
 +
 +  d1x = sgn(u);    // d1x = sign of the change in x
 +  d1y = sgn(v);    // d1y = sign of the change in y
 +
 +  d2x = sgn(u);    // d2x = sign of the change in x
 +  d2y = 0;         // d2y = 0
 +  m = abs(u);      // m = positive change in x
 +  n = abs(v);      // n = positive change in y
 +
 +  if (m <= n) {
 +    d2x = 0;       // d2x = 0
 +    d2y = sgn(v);  // d2y = sign of the change in y
 +    m = abs(v);    // m = positive change in y
 +    n = abs(u);    // n = positive change in x
 +  }
 +  s = m / 2;       // s = half of the change in x/y
 +
 +  for (i=0;i<m+1;i++) {
 +    Putpixel(a,b,count,where);   // plot the original x1 and y1
 +    count++;                     // increment the color
 +    if (count > 100) count = 50; // if color is out of bounds, reset
 +    s += n;
 +    if (s >= m) {
 +      s -= m;
 +      a += d1x;
 +      b += d1y;
 +    }
 +    else {
 +      a += d2x;
 +      b += d2y;
 +    }
 +  }
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// SetUpScreen() - This procedure sets up the static background to be used //
 +//                 in the program.                                         //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void SetUpScreen() {
 +
 +  int x,y,loop1,loop2,loop3;
 +  const byte circ[5][5] = {{ 0,10,10,10, 0},
 +               {10,13,12,11,10},
 +               {10,12,12,11,10},
 +               {10,11,11,11,10},
 +               { 0,10,10,10, 0}};
 +
 +  // set the pallette for the toasters and some other things
 +  Pal (1 ,22,22,22);
 +  Pal (2 ,45,45,45);
 +  Pal (3 ,59,59,59);
 +  Pal (4 ,63,63,27);
 +  Pal (5 ,39,63, 3);
 +  Pal (6 ,51,39, 3);
 +  Pal (7 , 3,27, 3);
 +  Pal (8 ,15,39,15);
 +  Pal (9 ,35,35,35);
 +  Pal (10, 0, 0,40);
 +  Pal (11,10,10,50);
 +  Pal (12,20,20,60);
 +  Pal (13,30,30,63);
 +
 +  // set pallette colors 50-100 to blue values between 13 and 63
 +  for (loop1 = 50; loop1 < 101; loop1++)
 +    Pal (loop1,0,0,loop1-37);
 +
 +  // put a copy of the pallette into ourpal[]
 +  for (loop1 = 0; loop1 < 256; loop1++)
 +    GetPal (loop1,ourpal[loop1][0],ourpal[loop1][1],ourpal[loop1][2]);
 +
 +  // draw funny lines
 +  for (loop1 = 0; loop1 < 320; loop1++)
 +    Funny_line (0,199,loop1,0,Vaddr1);
 +  for (loop1 = 0; loop1 < 200; loop1++)
 +    Funny_line (0,199,319,loop1,Vaddr1);
 +
 +  // draw circles
 +  for (loop1 = 0; loop1 < 200; loop1++) {
 +    x = random (315);
 +    y = random (195);
 +    for (loop2 = 0; loop2 < 5; loop2++)
 +      for (loop3 = 0; loop3 < 5; loop3++)
 +      // don't plot a pixel if its color is 0
 +        if (circ[loop2][loop3] != 0)
 +          Putpixel(x+loop2,y+loop3,circ[loop2][loop3],Vaddr1);
 +  }
 +
 +  // Copy the entire screen at Vaddr1, our virtual screen on which we have
 +  // done all our graphics, onto the screen you see, VGA.
 +  Flip (Vaddr1,VGA);
 +  // also make a copy of the virtual screen to Vaddr2
 +  Flip (Vaddr1,Vaddr2);
 +
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// Rotatepal() - This function rotates the colors between 50 and 100.      //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void Rotatepal() {
 +
 +  byte temp[3];
 +  int loop1;
 +
 +  memmove(temp,ourpal[100],3);
 +  memmove(ourpal[51],ourpal[50],50*3);
 +  memmove(ourpal[50],temp,3);
 +  for (loop1 = 50; loop1 < 101; loop1++)
 +    Pal (loop1,ourpal[loop1][0],ourpal[loop1][1],ourpal[loop1][2]);
 +
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// ScreenTrans() - This is a small function to copy a 30x30 pixel block    //
 +//                 from coordinates x,y on the Vaddr1 to           //
 +//                 coordinates x,y on the true vga screen.                 //
 +//                                                                         //
 +// ERROR, from Vaddr1 to Vaddr2
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void ScreenTrans (word x, word y) {
 +  asm {
 +    push    ds           // save DS
 +    push    es           // save ES
 +    mov     ax,Vaddr1    // set AX to the segment of Virtual Screen 1
 +    mov     es,ax        // set ES to segment of Vaddr1
 +    mov     ax,Vaddr2    // set AX to the segment of Virtual Screen 2
 +    mov     ds,ax        // set DS to segment of Vaddr2
 +    mov     bx,[x]       // set BX to x
 +    mov     dx,[y]       // set DX to y
 +    push    bx           // save x coordinate
 +    mov     bx, dx       // copy y coordinate to BX
 +    mov     dh, dl       // multiply y*256
 +    xor     dl, dl       // zero out DL
 +    shl     bx, 6        // multiply y*64
 +    add     dx, bx       // add y*64 to y*256 to get y*320
 +    pop     bx           // restore x coordinate
 +    add     bx, dx       // finalize the location
 +    mov     di, bx       // set DI to offset of Virtual Screen 1
 +    mov     si, di       // set SI to offset of Virtual Screen 2
 +    mov     al,60        // I have no idea why this is here.
 +    mov     bx, 30       // set BX to height of block
 +  }
 +  _loop1: asm {
 +    mov     cx, 24       // set CX to width of block divided by 2
 +    rep     movsw        // copy the screens and decrement CX by 1 until
 +                         //   CX is 0
 +    add     di,0x110     // 320 - 48 = 272 .. or 110 in hex
 +    add     si,0x110
 +    dec     bx           // decrease number lines left to draw
 +    jnz     _loop1       // if not done go back to _loop1
 +    pop     es           // restore ES
 +    pop     ds           // restore DS
 +  }
 +
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// NewToaster() - This adds a new toaster to the screen.                   //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void NewToaster() {
 +
 +  int loop1 = 0;
 +
 +  do {
 +    if (toaster[loop1].active == FALSE) {
 +      toaster[loop1].x = random(200)+70;
 +      toaster[loop1].y = 0;
 +      toaster[loop1].active = TRUE;
 +      toaster[loop1].frame = 1;
 +      toaster[loop1].speed = random(3)+1;
 +      loop1 = 10;
 +    }
 +    loop1++;
 +  } while (loop1 < NUMTOASTERS);
 +
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// Fly() - This is the function where we move and put the toasters.        //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void Fly() {
 +
 +  int loop1,loop2;
 +  char ch;
 +
 +  for (loop1 = 0; loop1 < NUMTOASTERS; loop1++)
 +    toaster[loop1].active = FALSE;
 +
 +  ch = '0'; // assign a dummy value to ch
 +  NewToaster();
 +
 +  do {
 +    // if a key is pressed...
 +
 +    if (kbhit()) {
 +      ch = getch();
 +      // if '+' is pressed, add a toaster
 +      if (ch == '+') NewToaster();
 +      // if '-' is pressed, remove a toaster
 +      if (ch == '-') {
 +        loop1 = 0; // start with toaster 0
 +        do {
 +          // if the loop1 toaster is active
 +          if (toaster[loop1].active == TRUE) {
 +            // draw the toaster on the screen
 +            ScreenTrans(toaster[loop1].x,toaster[loop1].y);
 +            // then make it false
 +            toaster[loop1].active = FALSE;
 +            // break out of the loop
 +            loop1 = 10;
 +          }
 +          // check the next toaster
 +          loop1++;
 +        } while (loop1 < NUMTOASTERS);
 +      }
 +    }
 +
 +    // if no key was pressed...
 +
 +    for (loop1 = 0; loop1 < NUMTOASTERS; loop1++) {
 +      if (toaster[loop1].active == TRUE) {
 +        // Restore the background the toaster was over
 +        ScreenTrans(toaster[loop1].x,toaster[loop1].y);
 +        // Move the toaster
 +        toaster[loop1].x -= toaster[loop1].speed;
 +        toaster[loop1].y += toaster[loop1].speed;
 +        // When toaster reaches the edge of the screen, render it inactive
 +        // and bring a new one into existance.
 +        if ((toaster[loop1].x < 0) || (toaster[loop1].y > 170)) {
 +          toaster[loop1].active = FALSE;
 +          NewToaster();
 +        }
 +      }
 +    }
 +
 +    // Draw all of the toasters
 +    for (loop1 = 0; loop1 < NUMTOASTERS; loop1++) {
 +      // ... but only if they are active
 +      if (toaster[loop1].active == TRUE)
 +        switch (toaster[loop1].frame) {
 +        case 1: Putico(toaster[loop1].x,toaster[loop1].y,FRAME1,Vaddr1); break;
 +        case 2: Putico(toaster[loop1].x,toaster[loop1].y,FRAME3,Vaddr1); break;
 +        case 3: Putico(toaster[loop1].x,toaster[loop1].y,FRAME2,Vaddr1); break;
 +        case 4: Putico(toaster[loop1].x,toaster[loop1].y,FRAME3,Vaddr1); break;
 +        }
 +      // increment the current frame of the toaster
 +      toaster[loop1].frame += 1;
 +      // reset the frame if it gets to 5
 +      if (toaster[loop1].frame == 5) toaster[loop1].frame = 1;
 +    }
 +
 +    WaitRetrace();
 +    Flip(Vaddr1,VGA);
 +    Rotatepal();
 +
 +    // if the key pressed above was 0 (escape key) then read the escape code
 +    if (ch == 0) ch = getch();
 +
 +  } while (ch != 27); // if the escape code was 27 (escape key) then exit
 +
 +}
 +</code>
  
 <nspages back2root/archives/denthor -simpleList -title -h1 -exclude:start -textPages="Denthor VGA Trainer"> <nspages back2root/archives/denthor -simpleList -title -h1 -exclude:start -textPages="Denthor VGA Trainer">
  
back2root/archives/denthor/part-07.txt · Dernière modification : 2021/09/05 14:00 de frater