Atari Legacy·Reader Resources·Mad-Pascal·Chapter 2
Software · Course
A complete one-button game in a few dozen lines of Pascal: a saucer crosses the screen one character at a time, drops bombs on a randomly generated city, and dies if it hits a tower. Poke and Peek straight into screen memory, ATASCII to internal screen codes, and a frame-counter trick that makes the bomb fall twice as fast as the ship moves without a single extra variable.
Everything from the printed article, ready to compile. Checksums are printed so you can verify a file you got from somewhere else against ours.
Mad-Pascal compiles to MADS assembly, MADS assembles that to an Atari executable, and the emulator boots it. Three commands, no project file.
mp bomber.pasmads bomber.a65 -x -o:bomber.xexatari800 bomber.xexOn real hardware, copy bomber.xex to an SD cartridge or a disk image and load it the way you would any other executable. The game needs a joystick in port 1 — the fire button drops the bomb, and on Atari a pressed button reads as 0, not 1.
The same file you can download above — line numbers match the errata table below. Line numbers are not selected when you copy.
// ---------------------------------------------------------------------// bomber.pas — Mad-Pascal, Chapter 2 of the Atari Legacy course// Wojciech "Bocianu" Bociański, Atari Legacy Issue 02//// !! TRANSCRIBED FROM THE PRINTED LISTING — NOT YET CONFIRMED BY THE// !! AUTHOR. Do not publish this file until Bocianu has sent the// !! original and downloads.verified has been flipped to true in// !! repo-src/resources/mad-pascal-02.toml.// ---------------------------------------------------------------------program bomber;uses atari, joystick;const SCREEN_SIZE = 24*40;var shipPos, bombPos, screenEdge: word; ship: string[3] = ' <>'~; GameOver: boolean = false;procedure DrawShip;var i: byte;begin for i:=0 to 2 do Poke(shipPos+i, Ord(ship[i+1]));end;procedure MoveShip;begin Inc(shipPos); // Move Ship if shipPos = screenEdge then GameOver:=true; // Check if Ship left screen if Peek(shipPos+2) <> 0 then GameOver:=true; // Check if Ship hit a buildingend;procedure MoveBomb;begin Poke(bombPos, Ord(' '~)); Inc(bombPos, 40); Poke(bombPos, Ord('v'~));end;procedure DropBomb;begin bombPos := shipPos+3;end;procedure DrawBuildings;var col, row, height: byte;begin for col:=0 to 39 do begin height := 23-Random(12); for row:=24 downto height do Poke(savmsc+(row*40)+col, Ord('"'*~)); end;end;begin FillChar(pointer(savmsc), SCREEN_SIZE, ' '~); // Fill screen with spaces DrawBuildings; shipPos := savmsc; // Set ship position to start of screen screenEdge := savmsc + SCREEN_SIZE; // Get length of screen bombPos := screenEdge; // Bomb starts off screen repeat if rtclok3 and 3 = 0 then MoveShip; // Move Ship if bombPos < screenEdge then begin // Check if Bomb is on Screen if rtclok3 and 1 = 0 then MoveBomb; end else if strig0 = 0 then DropBomb; // Drop Bomb DrawShip; Pause; until GameOver;end.


Paper cannot be patched. This is where a wrong line in the printed listing gets fixed — the downloadable file above is always the corrected one.
No corrections to the printed article so far. Found one? Write to biuro@l-tek.pl and it will appear here.
The source code from this chapter is published here with the author's permission so that readers do not have to retype a printed listing. Copyright remains with Wojciech "Bocianu" Bociański.