home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / TUT1-9.ZIP / TUTPROG9.PAS < prev    next >
Pascal/Delphi Source File  |  1994-02-26  |  18KB  |  550 lines

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