home *** CD-ROM | disk | FTP | other *** search
/ CD-X 1 / cdx_01.iso / demodisc / tyrant / vector / vector.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-08-14  |  17.7 KB  |  553 lines

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