home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / TUT09NEW.ZIP / TUT9.PAS < prev    next >
Pascal/Delphi Source File  |  1995-01-21  |  19KB  |  567 lines

  1. (*****************************************************************************)
  2. (*                                                                           *)
  3. (* TUT9.PAS - VGA Trainer Program 9 (in Pascal)                              *)
  4. (*                                                                           *)
  5. (* "The VGA Trainer Program" is written by Denthor of Asphyxia.  However it  *)
  6. (* was limited to Pascal only in its first run.  All I have done is taken    *)
  7. (* his original release, translated it to C++, and touched up a few things.  *)
  8. (* I take absolutely no credit for the concepts presented in this code.      *)
  9. (*        -Christopher G. Mann (Snowman)                                     *)
  10. (*                                                                           *)
  11. (* Program Notes : This program presents polygons.                           *)
  12. (*                                                                           *)
  13. (* Author        : Grant Smith (Denthor)  - denthor@beastie.cs.und.ac.za     *)
  14. (*                                                                           *)
  15. (*****************************************************************************)
  16.  
  17. {$X+}
  18. USES Crt;
  19.  
  20. CONST VGA = $A000;
  21.       maxpolys = 5;
  22.       A : Array [1..maxpolys,1..4,1..3] of integer =
  23.         (
  24.          ((-10,10,0),(-2,-10,0),(0,-10,0),(-5,10,0)),
  25.          ((10,10,0),(2,-10,0),(0,-10,0),(5,10,0)),
  26.          ((-2,-10,0),(2,-10,0),(2,-5,0),(-2,-5,0)),
  27.          ((-6,0,0),(6,0,0),(7,5,0),(-7,5,0)),
  28.          ((0,0,0),(0,0,0),(0,0,0),(0,0,0))
  29.         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
  30.             { (X2,Y2,Z2) ... for the 4 points of a poly }
  31.      S : Array [1..maxpolys,1..4,1..3] of integer =
  32.         (
  33.          ((-10,-10,0),(10,-10,0),(10,-7,0),(-10,-7,0)),
  34.          ((-10,10,0),(10,10,0),(10,7,0),(-10,7,0)),
  35.          ((-10,1,0),(10,1,0),(10,-2,0),(-10,-2,0)),
  36.          ((-10,-8,0),(-7,-8,0),(-7,0,0),(-10,0,0)),
  37.          ((10,8,0),(7,8,0),(7,0,0),(10,0,0))
  38.         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
  39.             { (X2,Y2,Z2) ... for the 4 points of a poly }
  40.      P : Array [1..maxpolys,1..4,1..3] of integer =
  41.         (
  42.          ((-10,-10,0),(-7,-10,0),(-7,10,0),(-10,10,0)),
  43.          ((10,-10,0),(7,-10,0),(7,0,0),(10,0,0)),
  44.          ((-9,-10,0),(9,-10,0),(9,-7,0),(-9,-7,0)),
  45.          ((-9,-1,0),(9,-1,0),(9,2,0),(-9,2,0)),
  46.          ((0,0,0),(0,0,0),(0,0,0),(0,0,0))
  47.         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
  48.             { (X2,Y2,Z2) ... for the 4 points of a poly }
  49.      H : Array [1..maxpolys,1..4,1..3] of integer =
  50.         (
  51.          ((-10,-10,0),(-7,-10,0),(-7,10,0),(-10,10,0)),
  52.          ((10,-10,0),(7,-10,0),(7,10,0),(10,10,0)),
  53.          ((-9,-1,0),(9,-1,0),(9,2,0),(-9,2,0)),
  54.          ((0,0,0),(0,0,0),(0,0,0),(0,0,0)),
  55.          ((0,0,0),(0,0,0),(0,0,0),(0,0,0))
  56.         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
  57.             { (X2,Y2,Z2) ... for the 4 points of a poly }
  58.      Y : Array [1..maxpolys,1..4,1..3] of integer =
  59.         (
  60.          ((-7,-10,0),(0,-3,0),(0,0,0),(-10,-7,0)),
  61.          ((7,-10,0),(0,-3,0),(0,0,0),(10,-7,0)),
  62.          ((-2,-3,0),(2,-3,0),(2,10,0),(-2,10,0)),
  63.          ((0,0,0),(0,0,0),(0,0,0),(0,0,0)),
  64.          ((0,0,0),(0,0,0),(0,0,0),(0,0,0))
  65.         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
  66.             { (X2,Y2,Z2) ... for the 4 points of a poly }
  67.      X : Array [1..maxpolys,1..4,1..3] of integer =
  68.         (
  69.          ((-7,-10,0),(10,7,0),(7,10,0),(-10,-7,0)),
  70.          ((7,-10,0),(-10,7,0),(-7,10,0),(10,-7,0)),
  71.          ((0,0,0),(0,0,0),(0,0,0),(0,0,0)),
  72.          ((0,0,0),(0,0,0),(0,0,0),(0,0,0)),
  73.          ((0,0,0),(0,0,0),(0,0,0),(0,0,0))
  74.         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
  75.             { (X2,Y2,Z2) ... for the 4 points of a poly }
  76.      I : Array [1..maxpolys,1..4,1..3] of integer =
  77.         (
  78.          ((-10,-10,0),(10,-10,0),(10,-7,0),(-10,-7,0)),
  79.          ((-10,10,0),(10,10,0),(10,7,0),(-10,7,0)),
  80.          ((-2,-9,0),(2,-9,0),(2,9,0),(-2,9,0)),
  81.          ((0,0,0),(0,0,0),(0,0,0),(0,0,0)),
  82.          ((0,0,0),(0,0,0),(0,0,0),(0,0,0))
  83.         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
  84.             { (X2,Y2,Z2) ... for the 4 points of a poly }
  85.  
  86.  
  87. Type Point = Record
  88.                x,y,z:real;                { The data on every point we rotate}
  89.              END;
  90.      Virtual = Array [1..64000] of byte;  { The size of our Virtual Screen }
  91.      VirtPtr = ^Virtual;                  { Pointer to the virtual screen }
  92.  
  93.  
  94. VAR Lines : Array [1..maxpolys,1..4] of Point;  { The base object rotated }
  95.     Translated : Array [1..maxpolys,1..4] of Point; { The rotated object }
  96.     Xoff,Yoff,Zoff:Integer;               { Used for movement of the object }
  97.     lookup : Array [0..360,1..2] of real; { Our sin and cos lookup table }
  98.     Virscr : VirtPtr;                     { Our first Virtual screen }
  99.     Vaddr  : word;                        { The segment of our virtual screen}
  100.  
  101.  
  102. {──────────────────────────────────────────────────────────────────────────}
  103. Procedure SetMCGA;  { This procedure gets you into 320x200x256 mode. }
  104. BEGIN
  105.   asm
  106.      mov        ax,0013h
  107.      int        10h
  108.   end;
  109. END;
  110.  
  111.  
  112. {──────────────────────────────────────────────────────────────────────────}
  113. Procedure SetText;  { This procedure returns you to text mode.  }
  114. BEGIN
  115.   asm
  116.      mov        ax,0003h
  117.      int        10h
  118.   end;
  119. END;
  120.  
  121. {──────────────────────────────────────────────────────────────────────────}
  122. Procedure Cls (Where:word;Col : Byte);
  123.    { This clears the screen to the specified color }
  124. BEGIN
  125.      asm
  126.         push    es
  127.         mov     cx, 32000;
  128.         mov     es,[where]
  129.         xor     di,di
  130.         mov     al,[col]
  131.         mov     ah,al
  132.         rep     stosw
  133.         pop     es
  134.      End;
  135. END;
  136.  
  137. {──────────────────────────────────────────────────────────────────────────}
  138. Procedure SetUpVirtual;
  139.    { This sets up the memory needed for the virtual screen }
  140. BEGIN
  141.   GetMem (VirScr,64000);
  142.   vaddr := seg (virscr^);
  143. END;
  144.  
  145.  
  146. {──────────────────────────────────────────────────────────────────────────}
  147. Procedure ShutDown;
  148.    { This frees the memory used by the virtual screen }
  149. BEGIN
  150.   FreeMem (VirScr,64000);
  151. END;
  152.  
  153.  
  154. {──────────────────────────────────────────────────────────────────────────}
  155. procedure flip(source,dest:Word);
  156.   { This copies the entire screen at "source" to destination }
  157. begin
  158.   asm
  159.     push    ds
  160.     mov     ax, [Dest]
  161.     mov     es, ax
  162.     mov     ax, [Source]
  163.     mov     ds, ax
  164.     xor     si, si
  165.     xor     di, di
  166.     mov     cx, 32000
  167.     rep     movsw
  168.     pop     ds
  169.   end;
  170. end;
  171.  
  172.  
  173. {──────────────────────────────────────────────────────────────────────────}
  174. Procedure Pal(Col,R,G,B : Byte);
  175.   { This sets the Red, Green and Blue values of a certain color }
  176. Begin
  177.    asm
  178.       mov    dx,3c8h
  179.       mov    al,[col]
  180.       out    dx,al
  181.       inc    dx
  182.       mov    al,[r]
  183.       out    dx,al
  184.       mov    al,[g]
  185.       out    dx,al
  186.       mov    al,[b]
  187.       out    dx,al
  188.    end;
  189. End;
  190.  
  191.  
  192. {──────────────────────────────────────────────────────────────────────────}
  193. Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;
  194.   { This draws a horizontal line from x1 to x2 on line y in color col }
  195. asm
  196.   mov   ax,where
  197.   mov   es,ax
  198.   mov   ax,y
  199.   mov   di,ax
  200.   shl   ax,8
  201.   shl   di,6
  202.   add   di,ax
  203.   add   di,x1
  204.  
  205.   mov   al,col
  206.   mov   ah,al
  207.   mov   cx,x2
  208.   sub   cx,x1
  209.   shr   cx,1
  210.   jnc   @start
  211.   stosb
  212. @Start :
  213.   rep   stosw
  214. end;
  215.  
  216.  
  217. {──────────────────────────────────────────────────────────────────────────}
  218. Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
  219.   { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
  220.     in color col }
  221. var
  222.   x:integer;
  223.   mny,mxy:integer;
  224.   mnx,mxx,yc:integer;
  225.   mul1,div1,
  226.   mul2,div2,
  227.   mul3,div3,
  228.   mul4,div4:integer;
  229.  
  230. begin
  231.   mny:=y1; mxy:=y1;
  232.   if y2<mny then mny:=y2;
  233.   if y2>mxy then mxy:=y2;
  234.   if y3<mny then mny:=y3;
  235.   if y3>mxy then mxy:=y3;    { Choose the min y mny and max y mxy }
  236.   if y4<mny then mny:=y4;
  237.   if y4>mxy then mxy:=y4;
  238.  
  239.   if mny<0 then mny:=0;
  240.   if mxy>199 then mxy:=199;
  241.   if mny>199 then exit;
  242.   if mxy<0 then exit;        { Verticle range checking }
  243.  
  244.   mul1:=x1-x4; div1:=y1-y4;
  245.   mul2:=x2-x1; div2:=y2-y1;
  246.   mul3:=x3-x2; div3:=y3-y2;
  247.   mul4:=x4-x3; div4:=y4-y3;  { Constansts needed for intersection calc }
  248.  
  249.   for yc:=mny to mxy do
  250.     begin
  251.       mnx:=320;
  252.       mxx:=-1;
  253.       if (y4>=yc) or (y1>=yc) then
  254.         if (y4<=yc) or (y1<=yc) then   { Check that yc is between y1 and y4 }
  255.           if not(y4=y1) then
  256.             begin
  257.               x:=(yc-y4)*mul1 div div1+x4; { Point of intersection on x axis }
  258.               if x<mnx then
  259.                 mnx:=x;
  260.               if x>mxx then
  261.                 mxx:=x;       { Set point as start or end of horiz line }
  262.             end;
  263.       if (y1>=yc) or (y2>=yc) then
  264.         if (y1<=yc) or (y2<=yc) then   { Check that yc is between y1 and y2 }
  265.           if not(y1=y2) then
  266.             begin
  267.               x:=(yc-y1)*mul2 div div2+x1; { Point of intersection on x axis }
  268.               if x<mnx then
  269.                 mnx:=x;
  270.               if x>mxx then
  271.                 mxx:=x;       { Set point as start or end of horiz line }
  272.             end;
  273.       if (y2>=yc) or (y3>=yc) then
  274.         if (y2<=yc) or (y3<=yc) then   { Check that yc is between y2 and y3 }
  275.           if not(y2=y3) then
  276.             begin
  277.               x:=(yc-y2)*mul3 div div3+x2; { Point of intersection on x axis }
  278.               if x<mnx then
  279.                 mnx:=x;
  280.               if x>mxx then
  281.                 mxx:=x;       { Set point as start or end of horiz line }
  282.             end;
  283.       if (y3>=yc) or (y4>=yc) then
  284.         if (y3<=yc) or (y4<=yc) then   { Check that yc is between y3 and y4 }
  285.           if not(y3=y4) then
  286.             begin
  287.               x:=(yc-y3)*mul4 div div4+x3; { Point of intersection on x axis }
  288.               if x<mnx then
  289.                 mnx:=x;
  290.               if x>mxx then
  291.                 mxx:=x;       { Set point as start or end of horiz line }
  292.             end;
  293.       if mnx<0 then
  294.         mnx:=0;
  295.       if mxx>319 then
  296.         mxx:=319;          { Range checking on horizontal line }
  297.       if mnx<=mxx then
  298.         hline (mnx,mxx,yc,color,where);   { Draw the horizontal line }
  299.     end;
  300.   end;
  301.  
  302.  
  303.  
  304. {──────────────────────────────────────────────────────────────────────────}
  305. Function rad (theta : real) : real;
  306.   {  This calculates the degrees of an angle }
  307. BEGIN
  308.   rad := theta * pi / 180
  309. END;
  310.  
  311.  
  312. {──────────────────────────────────────────────────────────────────────────}
  313. Procedure SetUpPoints;
  314.   { This creates the lookup table }
  315. VAR loop1,loop2:integer;
  316. BEGIN
  317.   For loop1:=0 to 360 do BEGIN
  318.     lookup [loop1,1]:=sin (rad (loop1));
  319.     lookup [loop1,2]:=cos (rad (loop1));
  320.   END;
  321. END;
  322.  
  323.  
  324. {──────────────────────────────────────────────────────────────────────────}
  325. Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
  326.   { This puts a pixel on the screen by writing directly to memory. }
  327. BEGIN
  328.   Asm
  329.     mov     ax,[where]
  330.     mov     es,ax
  331.     mov     bx,[X]
  332.     mov     dx,[Y]
  333.     mov     di,bx
  334.     mov     bx, dx                  {; bx = dx}
  335.     shl     dx, 8
  336.     shl     bx, 6
  337.     add     dx, bx                  {; dx = dx + bx (ie y*320)}
  338.     add     di, dx                  {; finalise location}
  339.     mov     al, [Col]
  340.     stosb
  341.   End;
  342. END;
  343.  
  344.  
  345.  
  346. {──────────────────────────────────────────────────────────────────────────}
  347. Procedure RotatePoints (X,Y,Z:Integer);
  348.   { This rotates object lines by X,Y and Z; then places the result in
  349.     TRANSLATED }
  350. VAR loop1,loop2:integer;
  351.     temp:point;
  352. BEGIN
  353.   For loop1:=1 to maxpolys do BEGIN
  354.     For loop2:=1 to 4 do BEGIN
  355.       temp.x:=lines[loop1,loop2].x;
  356.       temp.y:=lookup[x,2]*lines[loop1,loop2].y - lookup[x,1]*lines[loop1,loop2].z;
  357.       temp.z:=lookup[x,1]*lines[loop1,loop2].y + lookup[x,2]*lines[loop1,loop2].z;
  358.  
  359.       translated[loop1,loop2]:=temp;
  360.  
  361.       If y>0 then BEGIN
  362.         temp.x:=lookup[y,2]*translated[loop1,loop2].x - lookup[y,1]*translated[loop1,loop2].y;
  363.         temp.y:=lookup[y,1]*translated[loop1,loop2].x + lookup[y,2]*translated[loop1,loop2].y;
  364.         temp.z:=translated[loop1,loop2].z;
  365.         translated[loop1,loop2]:=temp;
  366.       END;
  367.  
  368.       If z>0 then BEGIN
  369.         temp.x:=lookup[z,2]*translated[loop1,loop2].x + lookup[z,1]*translated[loop1,loop2].z;
  370.         temp.y:=translated[loop1,loop2].y;
  371.         temp.z:=-lookup[z,1]*translated[loop1,loop2].x + lookup[z,2]*translated[loop1,loop2].z;
  372.         translated[loop1,loop2]:=temp;
  373.       END;
  374.     END;
  375.   END;
  376. END;
  377.  
  378.  
  379.  
  380. {──────────────────────────────────────────────────────────────────────────}
  381. Procedure DrawPoints;
  382.   { This draws the translated object to the virtual screen }
  383. VAR loop1:Integer;
  384.     nx,ny,nx2,ny2,nx3,ny3,nx4,ny4:integer;
  385.     temp:integer;
  386. BEGIN
  387.   For loop1:=1 to maxpolys do BEGIN
  388.     If (translated[loop1,1].z+zoff<0) and (translated[loop1,2].z+zoff<0) and
  389.        (translated[loop1,3].z+zoff<0) and (translated[loop1,4].z+zoff<0) then BEGIN
  390.       temp:=round (translated[loop1,1].z+zoff);
  391.       nx :=round (256*translated[loop1,1].X) div temp+xoff;
  392.       ny :=round (256*translated[loop1,1].Y) div temp+yoff;
  393.       temp:=round (translated[loop1,2].z+zoff);
  394.       nx2:=round (256*translated[loop1,2].X) div temp+xoff;
  395.       ny2:=round (256*translated[loop1,2].Y) div temp+yoff;
  396.       temp:=round (translated[loop1,3].z+zoff);
  397.       nx3:=round (256*translated[loop1,3].X) div temp+xoff;
  398.       ny3:=round (256*translated[loop1,3].Y) div temp+yoff;
  399.       temp:=round (translated[loop1,4].z+zoff);
  400.       nx4:=round (256*translated[loop1,4].X) div temp+xoff;
  401.       ny4:=round (256*translated[loop1,4].Y) div temp+yoff;
  402.       drawpoly (nx,ny,nx2,ny2,nx3,ny3,nx4,ny4,13,vaddr);
  403.     END;
  404.   END;
  405. END;
  406.  
  407.  
  408.  
  409. {──────────────────────────────────────────────────────────────────────────}
  410. Procedure MoveAround;
  411.   { This is the main display procedure. Firstly it brings the object towards
  412.     the viewer by increasing the Zoff, then passes control to the user }
  413. VAR deg,loop1,loop2:integer;
  414.     ch:char;
  415.  
  416.   Procedure Whizz (sub:boolean);
  417.   VAR loop1:integer;
  418.   BEGIN
  419.     For loop1:=-64 to -5 do BEGIN
  420.       zoff:=loop1*8;
  421.       if sub then xoff:=xoff-7 else xoff:=xoff+7;
  422.       RotatePoints (deg,deg,deg);
  423.       DrawPoints;
  424.       flip (vaddr,vga);
  425.       Cls (vaddr,0);
  426.       deg:=(deg+5) mod 360;
  427.     END;
  428.   END;
  429.  
  430. BEGIN
  431.   deg:=0;
  432.   ch:=#0;
  433.   Yoff:=100;
  434.   Xoff:=350;
  435.   Cls (vaddr,0);
  436.   For loop1:=1 to maxpolys do
  437.     For loop2:=1 to 4 do BEGIN
  438.       Lines [loop1,loop2].x:=a [loop1,loop2,1];
  439.       Lines [loop1,loop2].y:=a [loop1,loop2,2];
  440.       Lines [loop1,loop2].z:=a [loop1,loop2,3];
  441.     END;
  442.   Whizz (TRUE);
  443.  
  444.   For loop1:=1 to maxpolys do
  445.     For loop2:=1 to 4 do BEGIN
  446.       Lines [loop1,loop2].x:=s [loop1,loop2,1];
  447.       Lines [loop1,loop2].y:=s [loop1,loop2,2];
  448.       Lines [loop1,loop2].z:=s [loop1,loop2,3];
  449.     END;
  450.   Whizz (FALSE);
  451.  
  452.   For loop1:=1 to maxpolys do
  453.     For loop2:=1 to 4 do BEGIN
  454.       Lines [loop1,loop2].x:=p [loop1,loop2,1];
  455.       Lines [loop1,loop2].y:=p [loop1,loop2,2];
  456.       Lines [loop1,loop2].z:=p [loop1,loop2,3];
  457.     END;
  458.   Whizz (TRUE);
  459.  
  460.   For loop1:=1 to maxpolys do
  461.     For loop2:=1 to 4 do BEGIN
  462.       Lines [loop1,loop2].x:=h [loop1,loop2,1];
  463.       Lines [loop1,loop2].y:=h [loop1,loop2,2];
  464.       Lines [loop1,loop2].z:=h [loop1,loop2,3];
  465.     END;
  466.   Whizz (FALSE);
  467.  
  468.   For loop1:=1 to maxpolys do
  469.     For loop2:=1 to 4 do BEGIN
  470.       Lines [loop1,loop2].x:=y [loop1,loop2,1];
  471.       Lines [loop1,loop2].y:=y [loop1,loop2,2];
  472.       Lines [loop1,loop2].z:=y [loop1,loop2,3];
  473.     END;
  474.   Whizz (TRUE);
  475.  
  476.   For loop1:=1 to maxpolys do
  477.     For loop2:=1 to 4 do BEGIN
  478.       Lines [loop1,loop2].x:=x [loop1,loop2,1];
  479.       Lines [loop1,loop2].y:=x [loop1,loop2,2];
  480.       Lines [loop1,loop2].z:=x [loop1,loop2,3];
  481.     END;
  482.   Whizz (FALSE);
  483.  
  484.   For loop1:=1 to maxpolys do
  485.     For loop2:=1 to 4 do BEGIN
  486.       Lines [loop1,loop2].x:=i [loop1,loop2,1];
  487.       Lines [loop1,loop2].y:=i [loop1,loop2,2];
  488.       Lines [loop1,loop2].z:=i [loop1,loop2,3];
  489.     END;
  490.   Whizz (TRUE);
  491.  
  492.   For loop1:=1 to maxpolys do
  493.     For loop2:=1 to 4 do BEGIN
  494.       Lines [loop1,loop2].x:=a [loop1,loop2,1];
  495.       Lines [loop1,loop2].y:=a [loop1,loop2,2];
  496.       Lines [loop1,loop2].z:=a [loop1,loop2,3];
  497.     END;
  498.   Whizz (FALSE);
  499.  
  500.   cls (vaddr,0);
  501.   cls (vga,0);
  502.   Xoff := 160;
  503.  
  504.   Repeat
  505.     if keypressed then BEGIN
  506.       ch:=upcase (Readkey);
  507.       Case ch of 'A' : zoff:=zoff+5;
  508.                  'Z' : zoff:=zoff-5;
  509.                  ',' : xoff:=xoff-5;
  510.                  '.' : xoff:=xoff+5;
  511.                  'S' : yoff:=yoff-5;
  512.                  'X' : yoff:=yoff+5;
  513.       END;
  514.     END;
  515.     DrawPoints;
  516.     flip (vaddr,vga);
  517.     cls (vaddr,0);
  518.     RotatePoints (deg,deg,deg);
  519.     deg:=(deg+5) mod 360;
  520.   Until ch=#27;
  521. END;
  522.  
  523.  
  524. BEGIN
  525.   SetUpVirtual;
  526.   clrscr;
  527.   Writeln ('Hello there! Varsity has begun once again, so it is once again');
  528.   Writeln ('back to the grindstone ;-) ... anyway, this tutorial is, by');
  529.   Writeln ('popular demand, on poly-filling, in relation to 3-D solids.');
  530.   Writeln;
  531.   Writeln ('In this program, the letters of ASPHYXIA will fly past you. As you');
  532.   Writeln ('will see, they are solid, not wireframe. After the last letter has');
  533.   Writeln ('flown by, a large A will be left in the middle of the screen.');
  534.   Writeln;
  535.   Writeln ('You will be able to move it around the screen, and you will notice');
  536.   Writeln ('that it may have bits only half on the screen, i.e. clipping is');
  537.   Writeln ('perfomed. To control it use the following : "A" and "Z" control the Z');
  538.   Writeln ('movement, "," and "." control the X movement, and "S" and "X"');
  539.   Writeln ('control the Y movement. I have not included rotation control, but');
  540.   Writeln ('it should be easy enough to put in yourself ... if you have any');
  541.   Writeln ('hassles, leave me mail.');
  542.   Writeln;
  543.   Writeln ('I hope this is what you wanted...leave me mail for new ideas.');
  544.   writeln;
  545.   writeln;
  546.   Write ('  Hit any key to contine ...');
  547.   Readkey;
  548.   SetMCGA;
  549.   SetUpPoints;
  550.   MoveAround;
  551.   SetText;
  552.   ShutDown;
  553.   Writeln ('All done. This concludes the ninth sample program in the ASPHYXIA');
  554.   Writeln ('Training series. You may reach DENTHOR under the names of GRANT');
  555.   Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid');
  556.   Writeln ('Connectix BBS user, and occasionally read RSAProg.');
  557.   Writeln ('The numbers are available in the main text. You may also write to me at:');
  558.   Writeln ('             Grant Smith');
  559.   Writeln ('             P.O. Box 270');
  560.   Writeln ('             Kloof');
  561.   Writeln ('             3640');
  562.   Writeln ('I hope to hear from you soon!');
  563.   Writeln; Writeln;
  564.   Write   ('Hit any key to exit ...');
  565.   Readkey;
  566. END.
  567.