Thursday, April 30, 2020

PMG32BIT.P

[Table of Contents]
PMG32BIT.ATR Disk Image



This is an example program from page 322 of the classic book, Your Atari Computer, on how to use all four of Atari's player missile graphics players as one 32-bit object. I ported the code to Kyan Pascal. The original program just moved the object from left to right. I added vertical movement as well.

Its interesting to note that both the original edition of the book and the updated XL Series edition have a bug in the BASIC program. It is missing one datum in line 45. To fix the BASIC program, just add a 0 to the end of the line.

For vertical movement, the first and last byte of each player's image bitmap needs to be a zero so as to "clean up" the trailing byte when the players are moved through memory. As such, each player's bitmap was increased by two bytes, and a zero was added at the start and at the end.

What's on the Disk?


The disk image includes the various Atari DOS 2.5 files, Kyan Pascal Include files, Kyan Pascal Run-time library, and ...

  •   P.OUT - Pascal intermediate file
  •   PMG32BIT - Executable file 
  •   PMG32BIT.P - Pascal Source
  •   PMG32BIT.BAS - Original BASIC program
  •   PMLIB.I - Kyan Pascal Include file
  •   PMSETUP.I- Kyan Pascal Include file
  •   PMTYPES.I - Kyan Pascal Include file

Source Code


(* PMG32BIT.P *)
(* Kyan Pascal 2.x/Atari 8-bit *)

(* Port of a BASIC Language PMG Example       *)
(* from the book 'Your Atari Computer'        *)
(* Uses four players to make one large object *)

(* Set up some assembly langauge equates *)
#i pmsetup.i

program pmg32bit(input,output);

type

(* Creates an array type for  pmg bit maps *)
#i pmtypes.i

var
   p0, p1, p2, p3 : pmarray;
   d, p, t, w     : Integer;

(* Imports a bunch of pmg routines *)
#i pmlib.i

(* Main Program *)
begin

   write(chr(125)); (* Clear screen *)

   writeln('This is a sample program of using');
   writeln('Atari''s Player Missile Graphics');
   writeln;
   writeln('It uses four players as one object');

   (* Player 0 bit map *)
   P0[1]:=CHR(0);
   p0[2]:=chr(0);
   p0[3]:=chr(0);
   p0[4]:=chr(0);
   p0[5]:=chr(0);
   p0[6]:=chr(3);
   p0[7]:=chr(15);
   p0[8]:=chr(119);
   p0[9]:=chr(254);
   p0[10]:=chr(255);
   p0[11]:=chr(63);
   p0[12]:=chr(31);
   p0[13]:=chr(7);
   p0[14]:=chr(4);
   p0[15]:=chr(14);
   p0[16]:=chr(14);
   p0[17]:=chr(0);

   (* Player 1 bit map *)
   P1[1]:=chr(0); 
   p1[2]:=chr(1);
   p1[3]:=chr(2);
   p1[4]:=chr(2);
   p1[5]:=chr(31);
   p1[6]:=chr(240);
   p1[7]:=chr(255);
   p1[8]:=chr(255);
   p1[9]:=chr(255);
   p1[10]:=chr(239);
   p1[11]:=chr(254);
   p1[12]:=chr(255);
   p1[13]:=chr(255);
   p1[14]:=chr(240);
   p1[15]:=chr(15);
   p1[16]:=chr(0);
   p1[17]:=chr(0);

   (* Player 2 bit map *)
   p2[1]:=chr(0);
   p2[2]:=chr(128);
   p2[3]:=chr(64);
   p2[4]:=chr(64);
   p2[5]:=chr(248);
   p2[6]:=chr(15);
   p2[7]:=chr(255);
   p2[8]:=chr(255);
   p2[9]:=chr(255);
   p2[10]:=chr(247);
   p2[11]:=chr(127);
   p2[12]:=chr(255);
   p2[13]:=chr(255);
   p2[14]:=chr(15);
   p2[15]:=chr(240);
   p2[16]:=chr(0);
   p2[17]:=chr(0);

   (* Player 3 bit map *)
   p3[1]:=chr(0);
   p3[2]:=chr(0);
   p3[3]:=chr(0);
   p3[4]:=chr(0);
   p3[5]:=chr(0);
   p3[6]:=chr(192);
   p3[7]:=chr(240);
   p3[8]:=chr(236);
   p3[9]:=chr(127);
   p3[10]:=chr(255);
   p3[11]:=chr(252);
   p3[12]:=chr(248);
   p3[13]:=chr(224);
   p3[14]:=chr(32);
   p3[15]:=chr(112);
   p3[16]:=chr(0);
   p3[17]:=chr(0);

   pmstartup;

   (* Turn on pmg *)
   pminitialize(1);

   (* Clear shape buffer *)
   clear_pm_buffer(1);

   for p:=0 to 3 do
   begin
      (* Set player width *)
      player_width(p,0);
      (* Set player color *)
      pmcolor(p,188);
   end;

   (* Plr#,Offset,Shape Size,Array *)
   (* Offset is the vertical pos *)
   putshape(0,140,17,p0);
   putshape(1,140,17,p1);
   putshape(2,140,17,p2);
   putshape(3,140,17,p3);

(* Move players across screen *)
for t:=0 to 1 do
begin  
 for d:=0 to 228 do
 begin
  for p:=0 to 3 do
  begin
   (* 8 for single width *)
   (* 16 for double width *)
   horiz_player_pos(p,d+(8*p));
   for w:=1 to 200 do; (* slow down *)
  end;
 end;
end;

(* Clear the PMG ribbon *)
clear_pm_buffer(1);

(* Move players to middle of screen *)
for p:= 0 to 3 do
   horiz_player_pos(p,100+(8*p));

(* Move players vertically *)
for t:=0 to 1 do 
begin
   for d:=240 downto 0 do
   begin
      putshape(0,d,17,p0);
      putshape(1,d,17,p1);
      putshape(2,d,17,p2);
      putshape(3,d,17,p3);
      for w:=1 to 400 do; (* slow down *)
   end;
end;  

   (* Turn off pmg *)
   pminitialize(0);

end.

Sample Run



Wednesday, April 29, 2020

ARTILLER.P

[Table of Contents]
ARTILLERY.ATR Disk Image




ARTILLER.P is from page 115 of the book Apple Pascal Games by Douglas Hergert and Joseph T. Kalash, published by Sybex.

It is a simple combat game where you attempt to knock out the enemy's base.

It could be a much better game if

  • the computer shot back
  • a graphical display was implemented

It has been slightly modified to work with Kyan Pascal and fit on the Atari 8-bit display.

Source Code


(*
 * Artillery
 * Fire a shell at an enemy outpost
 *
 * From the book 'Apple Pascal Games'
 * by Douglas Hergert and Joseph T. Kalash
 *
 * ARTILLER.P
 * Kyan Pascal 2.x / Atari 8-bit
 *)

Program ARTILLERY(Input,Output);
Const
   NUMSHELLS =     10;    (* Allowed 10 shells per target *)
   MINDIST   =    100;    (* Minimum distance for a target *)
   MAXDIST   =   1000;    (* Maximum distance for a target *)

   VELOCITY  =  200.0;    (* Initial velocity of 200 ft/sec *)
   GRAVITY   =   32.2;    (* Gravity of 32.2 ft/sec^2 *)
   PI        = 3.1415;
Var
   ANGLE  : REAL;         (* Angle to shoot at *)
   ENEMY  : INTEGER;      (* How far away the enemy is *)
   KILLED : INTEGER;      (* How many we have hit *)
   SHOTS  : 0..NUMSHELLS; (* Number of shells left *)
   CH     : CHAR;         (* Used to answer questions *)
   HIT    : BOOLEAN;      (* Whether the enemy has been hit *)

#i RANDOMS.I

   (*
    * DIST
    * Returns how far the shell went
    *)
   Function DIST : INTEGER;

      (*
       * TIMEINAIR
       * Figures out how long the shell
       * stays in the air
       *)
      Function TIMEINAIR:REAL;
      Begin
         TIMEINAIR := (2*VELOCITY * SIN(ANGLE)) / GRAVITY
      End; (* TIMEINAIR *)

   Begin
      DIST := ROUND((VELOCITY * COS(ANGLE)) * TIMEINAIR)
   End; (* DIST *)

   (*
    * FIRE
    * The user fires at the enemy
    *)
   Procedure FIRE;
   Begin
      Seed(Random_Byte,Random_Byte,Random_Byte,Random_Byte);
   (* ENEMY := MINDIST + RANDOM MOD MAXDIST; *)
      ENEMY := RANDOM(MINDIST,MAXDIST);

      Writeln('The enemy is ',ENEMY:3,' feet away!!!');
      SHOTS := NUMSHELLS;

      Repeat
         Write('What angle? ');
         Readln(ANGLE);
         ANGLE := (ANGLE * PI)/180.0; (* Convert from degrees to radians *)
         HIT := ABS(ENEMY-DIST) <= 1;
         If HIT Then
         Begin
            KILLED := KILLED + 1;
            Writeln('You hit him!!!');
            Writeln('It took you ',(NUMSHELLS-SHOTS),' shots');
            If KILLED = 1 Then
               Writeln('You have killed one enemy')
            Else
            Begin
               Writeln('You have now destroyed ',KILLED,' enemies of');
               Writeln('democracy');
            End;
         End
         Else
         Begin
            SHOTS := SHOTS - 1;
            If DIST > ENEMY Then
               Write('You over shot by ')
            Else
               Write('You under shot by ');
            Writeln(ABS(ENEMY - DIST))
         End
      UNTIL (SHOTS = 0) OR HIT;

      If SHOTS = 0 THEN
         Writeln('You have run out of ammo')
      End; (* Fire *)

Begin
   Write(Chr(125));
   Writeln('Welcome to Artillery');
   Writeln;
   Writeln('You are in the middle of a war');
   Writeln('(Depressing, no?) and are being charged');
   Writeln('by thousands of enemies.');
   Writeln('You job is to destroy their outpost.');
   Writeln('You have at your disposal, ');
   Writeln('a cannon, which you can shoot at any');
   Writeln('angle. As this is war, supplies are');
   Writeln('short, so you only have ',NUMSHELLS,' per target');
   Writeln;

   KILLED := 0;
   Repeat
      Writeln('********************');
      FIRE;
      Write('I see another one, care to shoot again? ');
      Readln(CH);
      While NOT (CH in ['Y','N']) Do
      Begin
         Writeln('Please answer YES or NO');
         Write('Want to try again? ');
         Readln(CH);
      End
   Until CH <> 'Y';

   Writeln;
   Writeln('You killed ', KILLED, ' of the enemy');
End. (* ARTILLERY 7/7/81 D.H. *)

Sample Run



Tuesday, April 28, 2020

GUESSIT.P

[Table of Contents]
GUESSIT.ATR Disk Image



GUESSIT.P is from the book Apple Pascal Games by Douglas Hergert and Joseph T. Kalash, published by Sybex.

It is a simple, guess the random number between 1 and 100 game.

It has been slightly modified to work with Kyan Pascal on the Atari 8-bit.

Source Code


(*
 * Guess It
 * A Computer Guessing Game
 *
 * From the book 'Apple Pascal Games'
 * by Douglas Hergert and Joseph T. Kalash
 *
 * GUESSIT.P
 * Kyan Pascal 2.x / Atari 8-bit
 *
 *)

program guessit(Input,Output);

const
  MAXTRYS = 6;  (* User allowed 6 tries to guess number *)
  MAXNUM = 100; (* Maximum number *)
  MINNUM = 1;   (* Minimum number *)

var
  CH : char;               (* Used to answer questions *)
  GUESS : INTEGER;         (* Human's guess *)
  NUMBER : MINNUM..MAXNUM; (* The number itself *)
  NUMTRY : 0..MAXTRYS;     (* Number of times human has guessed *)

#i randoms.i

(*
 * Instructions
 * Prints out the instructions
 *)
 procedure Instructions;
 begin
   writeln('This is Guess It');
   writeln;
   writeln('I will choose a number between 1 and');
   writeln('100. You will try to guess that number.');
   writeln('If you guess wrong, I will tell you if');
   writeln('you guessed too high, or too low.');
   writeln;
   writeln('Enjoy');
   writeln;
 end; (* Instructions *)

(*
 * GETNUM
 * Get a guess from the human,
 * with error checking (mostly removed)
 *)
procedure Getnum;
begin
   write('Your guess? ');

   readln(GUESS);
   if GUESS > MAXNUM then
   begin
      writeln('Illegal number');
      Getnum;
  end
  else
  begin
     if GUESS > NUMBER then
        writeln('Too high')
     else
        if GUESS < NUMBER then
           writeln('Too low')
        else
           writeln('Correct!!!!!')
  end;
end; (* Getnum *)

Procedure Randomize;
begin
   (* Seed pseudo-random number generator *)  

   Seed(Random_Byte,Random_Byte,Random_Byte,Random_Byte);

end;

(*
Main
 *)
begin
   write(chr(125)); (* Clear screen *)

   Instructions;

   Randomize;

   CH := ' ';
   while (CH <> 'N') do
   begin
     GUESS := 0;
     NUMTRY := 0;
     NUMBER := Random(MINNUM, MAXNUM); (* Get Number *)
     
     while ( NUMTRY < MAXTRYS ) and ( GUESS <> NUMBER ) do
     begin
       Getnum;
       NUMTRY := NUMTRY + 1;
     end;
     writeln;
     if GUESS <> NUMBER then
       writeln('The number was ', NUMBER);
     writeln;
     WRITE('Want to try again (''N'' to exit)? ');
     readln(ch); 
     end
end.

Sample Run




Sunday, April 26, 2020

LINES.PA

[Table of Contents]
LINES.ATR Disk Image



The LINES.PA program was extracted from a German language Kyan Pascal Tutorial disk.

I made the following modifications:

  • Moved all the required files to a single DOS 2.5 disk image
  • Modified LINES.PA to look for include files in the root directory
  • Remove special ATASCII characters from the program listing so it could be listed here
  • Translated the German text to English text
  • Commented out the CHAIN command near the end of the program
  • Compiled with “pc lines.pa -o lines -p"

Source Code


#i graphics.h

program Lines;

#i inline.h

const maxLines     =20;
      maxLines_1   =19;
      maxDrawLines =500;
      maxX         =319;
      maxY         =191;

type  LineDescr  = array [0..3] of integer;

var   Ball,
      Vel,
      max          : LineDescr;
      Lines        : array [0..maxLines] of LineDescr;
      index, t,
      i, new, old  : integer;

#i rnd.f
#i consol.f

#i plot.p
#i drawto.p
#i setcolor.p
#i graphics.p
#i textmode.p

begin
  setcolor(2,0,0);
  setcolor(1,0,7);
  setcolor(4,0,7);
  write(chr(125));
  write('Kyan Pascal Graphics Demo QX-Lines      ');
  write('    (c) 1985, 1986 by TDI Software Inc.');
  writeln('              (c) 1988 by Martin Krischik');
  writeln('This Demo is written in Kyan Pascal');
  writeln;
  writeln;
  writeln('The QX-Lines are drawn with the DRAWTO');
  writeln('command. Quicker execution can be');
  writeln('attained by writing your own Fast Line');
  writeln('routines in Assembly Language, but then');
  writeln('the program will no longer be easily');
  writeln('portable to other computer systems.');
  writeln;
  writeln('Press START to Begin and End.');
  repeat until consol<>7;
  graphics(8+16);
  setcolor(2,0,0);
  setcolor(1,0,7);
  setcolor(4,0,7);
  max[0]:=maxX;
  max[1]:=maxY;
  max[2]:=maxX;
  max[3]:=maxY;
  for i := 0 to 3 do
    begin
      Vel[i] :=rnd(16)-8;
      Ball[i]:=rnd(max[i]-100)+50;
    end;
  new   := 0;
  old   := 0;
  index :=0;
  repeat
    for i := 0 to 3 do
      begin 
        t:=Ball[i]+Vel[i];
        if t>=max[i] then
          begin
            t     :=max[i]*2 - Vel[i] - Ball[i];
            Vel[i]:=-Vel[i];
          end;
        if t<0 then
          begin
            t:=-t;
            Vel[i]:=-Vel[i];
          end;
        Ball[i]:=t;
      end; 
    if (index>=maxLines) then
      begin
        plot  (lines[old,0], lines[old,1],0);
        drawto(lines[old,2], lines[old,3],0);
        old:=(old+1) mod maxLines;
      end;
    Lines[new MOD maxLines]:=Ball;
    new:=(new+1) mod maxLines;
    Plot  (ball[0], ball[1],1);
    drawto(ball[2], ball[3],1);
    index:=index+1;
  until (consol<>7) or (index=MaxDrawLines);
  repeat until consol<>7;
  textmode;
  setcolor(2,0,0);
  setcolor(1,0,7);
  setcolor(4,0,7);
(*  chain('grdemo'); *)
end.



Sample Run



THREEDIM.P

[Table of Contents]



THREEDIM.P is a sample program on the Kyan Pascal 2.x Advanced Graphics Toolkit disk. The program generates the outline of a F-14 Tomcat figher jet and rotates around 3D space.

It can be run by booting the Kyan Pascal 2.x Advanced Graphics Toolkit and choosing THREEDIM from the menu.

The FIGHTER file must be on the disk to run it as well.

To compile this example program, the following include files need to be available to the compiler:


Source Code


#A
_ORIGIN EQU $4000
#
program threedimdemo(input,output);
    const
        max = 6;
#i      graph3.con
    var
        x,y,z,t,step:real;
        e,d         :real;
        i,j,color   :integer;
        points,lines:integer;
        rep         :char;
        a,b,c:array[1..44] of real;
        lf,lt:array[1..58] of integer;
        f    :text;
#i      graph3.gbl
#i      hires.i
#i      plotter.i
#i      graph3.i
    begin
    writeln(chr(125));
    writeln('This program rotates an object through');
    writeln('110 degrees in seven views.  While also');
    writeln('zooming and changing elevation of the');
    writeln('object.');
    writeln;
    writeln('Press [RETURN] to start the demo');
    readln;
    writeln;
    writeln('Output to plotter?(Y/N)');
    readln(rep);
#A
    LDA #$40
    STA $6A
#
    graphics(8+16);
    if (rep='y') or (rep='Y') then
        plotter:=true
    else
        plotter:=false;
    if plotter then begin
       set_plotter_port(40,440,0,290);
       set_plotter_window(-5,5,-5,0);
       init_plotter;
       advance;
       frame;
       plotter_color(2);
    end;
    reset(f,'fighter');
    read(f,points);
    for i:= 1 to points do
        read(f,a[i]);
    for i:= 1 to points do
        read(f,b[i]);
    for i:= 1 to points do
        read(f,c[i]);
    read(f,lines);
    for i:= 1 to lines do begin
        read(f,lf[i]);
        read(f,lt[i]);
    end;
    SetWindow(-30,30,-20,20);
    color:=1;
    for i:=3 to 9 do begin
        d:=sin(1.6*i/5);
        e:=cos(1.6*i/5);
        setviewreferencepoint(0,0,0);
        setviewplanenormal(d,e,1-i/10);
        setviewdistance(40-6*i);
        setviewup(0,0,1);
        setprojection(perspective,60*d,60*e,60-6*i);
        makeviewplanexfm;
        clearscreen;
        for j:=1 to lines do begin
            display(move_abs,a[lf[j]],
                             b[lf[j]],
                             c[lf[j]]);
            display(draw_abs,a[lt[j]],
                             b[lt[j]],
                             c[lt[j]]);
        end;
    end;
#A
   LDA #$C0
   STA $6A 
#
graphics(0)
end.

Sample Run



TEST3D.P

[Table of Contents]

TEST3D.P is a sample program on the Kyan Pascal 2.x Advanced Graphics Toolkit disk.

It can be run by booting the Kyan Pascal 2.x Advanced Graphics Toolkit and choosing Test3D from the menu.

To compile this example program, the following include files need to be available to the compiler:

  • graph3.con
  • graph3.gbl
  • HiRes.i
  • plotter.i
  • graph3.i

Source Code


#A
_ORIGIN EQU $4000
#
program threedimdemo(input,output);
    const
        max = 6;
#i d1:graph3.con
    var
        x,y,z,t,step:real;
        i,color     :integer;
        rep         :char;
#i d1:graph3.gbl
#i d1:HiRes.i
#i d1:plotter.i
#i d1:graph3.i
    begin
    writeln(chr(125));
    writeln('This program demos a simultaneous zoom');
    writeln('and roll of an object.');
    writeln;
    writeln('Press [RETURN] to start the demo');
    readln;
    writeln;
    writeln('Output to plotter?(Y/N)');
    readln(rep);
#A
    LDA #$40
    STA $6A
#
    graphics(8+16);
    if (rep='y') or (rep='Y') then
        plotter:=true
    else
        plotter:=false;
    if plotter then begin
       set_plotter_port(40,440,0,290);
       set_plotter_window(-5,5,-5,0);
       init_plotter;
       advance;
       frame;
       plotter_color(2);
    end;
    for i:= 1 to 10 do begin
        color:=1;
        setviewreferencepoint(i/12,i/12,-i/6);
        setviewplanenormal(0,0,-1);
        setviewdistance(2);
        setviewup(i/10-0.1,1,0);
        setprojection(perspective,i/12,i/12,3-i/6);
        makeviewplanexfm;
        clearscreen;
        SetWindow(-5,5,-5,5);
        display(move_abs,0,0,0);
        display(draw_abs,0,0,1);
        display(draw_abs,0,1,1);
        display(draw_abs,1,1,1);
        display(draw_abs,1,0,1);
        display(draw_abs,1,0,0);
        display(draw_abs,1,1,0);
        display(draw_abs,0,1,0);
        display(draw_abs,0,0,0);
        display(move_abs,1,1,1);
        display(draw_abs,1,1,0);
        display(move_abs,0,1,1);
        display(draw_abs,0,1,0);
        display(move_abs,1,0.4,0.4);
        display(draw_rel,0,0,0.2);
        display(draw_rel,0,0.2,0);
        display(draw_rel,0,0,-0.2);
        display(draw_rel,0,-0.2,0);
   end;
#A
   LDA #$C0
   STA $6A
#
   GRAPHICS(0);
end.


Sample Run