Showing posts with label Kyan Pascal. Show all posts
Showing posts with label Kyan Pascal. Show all posts

Friday, May 1, 2020

CUSTCHAR.P

[Table of Contents]
CUSTCHAR.ATR Disk Image

Kyan Pascal 2.x has a few include files to help you modify the Atari ATASCII character set. Custom character sets can be used for program icons, objects, maps, animations, etc.

Simple Atari BASIC magazine type-in games such as Concentration and Gold Rush! make good use of these custom character sets.

You can use a program such as InstEdit to designed a custom character set. You can use a program such as MapMaker to use a customer character set to design a map.

ATASCII stands for ATARI Standard Code for Information Interchange, or a combination of ATARI ASCII, is the variation on the more general ASCII characters set code.

For reference, here is the standard Atari ATASCII character set:


Characters from 128 to 255 are the inverse video (blue character on white background for example) of characters 0 to 127. Some of the characters don't actually print on the screen by default, but are "control characters". For example, character 125 will clear the screen instead of displaying.

Note that the Atari's standard character set is at address 57344. Kyan Pascal only supports up to a two-byte signed integers (-32,768 to 32,767), so you will need to use a Two’s Complement conversion to reach that address:

  1. Take the number: 57344
  2. Convert the Decimal to Binary: 1110000000000000
  3. Moving from RIGHT to LEFT, flip every bit AFTER the first 1: 0010000000000000
  4. Convert the Binary to Decimal: 8192
  5. Use the negated value: -8192

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 ...


Source Code


PROGRAM CUSTCHAR(INPUT,OUTPUT);
TYPE
#I IOTYPES.I

VAR
   FN    : PATHSTRING;
   ADDR1 : INTEGER;
   ADDR2 : INTEGER;
   I     : INTEGER;

#I LOADCSET.I
#I ACTCSET.I

BEGIN
   (* NORMAL SET AT 57344 *)
   (* OR -8192 IN 2'S COMPLEMENT *)
   ADDR1 := -8192; (* 57344 *)

   (* RANDOM ADDRESS SPACE *)
   ADDR2 := 4000; (* CUSTOM *)

   (* DISPLAY SOME CHARACTERS *)
   WRITELN;
   FOR I := 32 TO 90 DO
      WRITE(CHR(I));
   WRITELN;
   WRITELN;

   WRITE('ENTER FILENAME: ');
   READLN(FN);
   WRITELN;

   (* LOAD FULL SET FROM FILE *)
   LOAD_CHAR_SET(FN,ADDR2);

   (* ACTIVATE CUSTOM SET *)
   ACTIVATE_CHAR_SET(ADDR2);

   READLN;

   (* ACTIVATE NORMAL SET *)
   ACTIVATE_CHAR_SET(ADDR1);

END.


Sample Run




Here are a few more screenshots:


Pascal Program Compiled 


Prompting For Character Set Filename


Custom Character Set Activated


Back To The Standard Character Set

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



PLAYDEMO.P

[Table of Contents]

PLAYDEMO.P is a demo program from 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 PlayDemo from the menu.

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


Source Code


#i pmsetup.i
program pmdemo(input,output);
    type
#i pmtypes.i
    var
        b    :pmarray;
        j,dis:integer;
        a    :integer;
        x,y  :array[1..100] of integer;
        i,step,z:real;
#i pmlib.i
    begin
        writeln(chr(125));
        writeln('This is a demo of smooth movement');
        writeln('of players in both horizontal and');
        writeln('vertical directions.');
        writeln;
        writeln('one moment please...');
        (*The b array contains the*)
        (*shape data for the ship.*)
        b[1]:=chr(66);
        b[2]:=chr(129);
        b[3]:=chr(153);
        b[4]:=chr(255);
        b[5]:=chr(255);
        b[6]:=chr(153);
        b[7]:=chr(129);
        b[8]:=chr(66);
        (*Now make a circle divided*)
        (*into 100 parts.          *)
        i:=0;
        j:=1;
        step:=0.062831853;
        while j<51 do begin
            a:=trunc(50*cos(i));
            z:=70*sin(i);

            x[j]:=120+a;
            y[j]:=120-trunc(z);
            x[j+50]:=120-a;
            y[j+50]:=trunc(120+z+0.5);
            i:=i+step;
            j:=j+1;
        end;
        pmstartup;
        (*save VBI vector*)
        pminitialize(1);
        (*set up for hires player*)
        (*missle graphics. Then  *)
        (*clear out the buffer   *)
        clear_pm_buffer(1);
        pmcolor(0,125);
        pmcolor(1,155);
        pmcolor(2,155);
        pmcolor(3,165);
        (*Give the players the *)
        (*colors which we want.*)
        (*Then put the ship in *)
        (*each player at offset*)
        (*120.  The ship is 8  *)
        (*bytes in length.     *)
        putshape(0,120,8,b);
        putshape(1,120,8,b);
        putshape(2,120,8,b);
        putshape(3,120,8,b);
        j:=2;
        a:=0;
        horiz_player_pos(2,120);
        while j<101 do begin
          dis:=y[j-1]-y[j];
          horiz_player_pos(0,x[j]);
          horiz_player_pos(1,255-x[j]);
          horiz_player_pos(3,x[j]);
          roll_player_buffer(0,dis);
          wait;
          (*The wait command will    *)
          (*suspend execution until  *)
          (*the vertical blank.  This*)
          (*will result in the roll  *)
          (*instruction executing.   *)
          roll_player_buffer(2,dis);
          (*This roll command will be*)
          (*executed in the next VBI *)
          (*which will occur before  *)
          (*the next roll instruction*)
          (*since arithmetic is time *)
          (*consuming.               *)
          j:=j+1;
          if (a<5) and (j=101) then
              begin
              a:=a+1;
              j:=2;
          end;
          (*The if makes the ship    *)
          (*circle 4 times the stop. *)
        end;
        (*This next command turns off*)
        (*PM graphics and revectors  *)
        (*the VBI to it's default.   *)
        pminitialize(0);
end.

Sample Run