Forum
Pascalated ZX BASIC Demo #23 - Space Invader - Printable Version

+- Forum (https://www.boriel.com/forum)
+-- Forum: Compilers and Computer Languages (https://www.boriel.com/forum/forumdisplay.php?fid=12)
+--- Forum: ZX Basic Compiler (https://www.boriel.com/forum/forumdisplay.php?fid=11)
+---- Forum: Gallery (https://www.boriel.com/forum/forumdisplay.php?fid=18)
+---- Thread: Pascalated ZX BASIC Demo #23 - Space Invader (/showthread.php?tid=2471)



Pascalated ZX BASIC Demo #23 - Space Invader - zarsoft - 07-16-2023

To run online, click here: RUN ONLINE


Code:
' PROGRAM Space Invader
' (c) ZarSoft 2022 Pascalated BASIC
' (c) ZarSoft 2023 Pascalated Boriel ZX BASIC
' Written by Ze Oliveira
' Pascalated Sinclair BASIC (c) 1987 by ZarSoft
' Pascalated BASIC Converter (c) 2021 by Zarsoft
' Pascalated Boriel (c) 2023 by ZarSoft
' ZX BASIC Compiler (c) 2008 by Boriel

#include <input.bas>  ' number = VAL INPUT(12)
#include <screen.bas> ' SCREEN$ function
#include <attr.bas>   ' ATTR function

'--- Pascalated Boriel ---
#define PROGRAM   REM
#define BEGIN    REM
'#define CONST     CONST
#define VAR       DIM
#define INTEGER   LONG
#define REAL      FLOAT
#define CHAR      STRING ' UBYTE is type integer
'#define STRING    STRING
#define BOOLEAN   UBYTE
#define TYPE      AS
'#define WHILE    WHILE
#define REPEAT    DO
#define UNTIL     LOOP UNTIL
#define PROCEDURE  SUB
CONST   TRUE      TYPE BOOLEAN = 1
CONST   FALSE     TYPE BOOLEAN = 0

PROGRAM SpaceInvader

' CONSTant declarations
REM CONSTant declarations
CONST black = 0
CONST blue = 1
CONST red = 2
CONST magenta = 3
CONST green = 4
CONST cyan = 5
CONST yellow = 6
CONST white = 7
CONST ZXscreen = 22528
CONST GameScreen = ZXscreen+4+4*32

' VAR - Global variables
VAR INKoff TYPE INTEGER = blue
VAR INKon TYPE INTEGER= cyan
VAR LEDoff TYPE INTEGER = INKoff+64
VAR LEDon TYPE INTEGER = INKon+64
VAR VIDEO(8,6) TYPE INTEGER ' video memory
VAR ADDR(8,6) TYPE INTEGER ' video address
VAR score1 TYPE INTEGER
VAR score2 TYPE INTEGER
VAR score3 TYPE INTEGER
VAR PlayerLin TYPE INTEGER
VAR PlayerCol TYPE INTEGER
VAR MissileLin TYPE INTEGER
VAR MissileCol TYPE INTEGER
VAR BombLin TYPE INTEGER
VAR BombCol TYPE INTEGER
VAR MothershipLin TYPE INTEGER
VAR MothershipCol TYPE INTEGER
VAR MothershipInc TYPE INTEGER
VAR Enemies TYPE INTEGER
VAR ScrollState TYPE INTEGER
VAR ScrollLin TYPE INTEGER
VAR ScrollCol TYPE INTEGER
VAR GameOver TYPE BOOLEAN
' VAR Scroll TYPE INTEGER = VAL ("Scroll"+STR$ ScrollState)
VAR k$ TYPE CHAR
VAR Period TYPE INTEGER = 16

'--- KEYBOARD BUFFER ---

VAR BUFFER$ TYPE STRING = ""
VAR LASTKEY$ TYPE STRING = ""

PROCEDURE ScanKey
VAR key$ TYPE STRING = INKEY$ + "#"
IF key$(0) <> LASTKEY$ 
  LASTKEY$ = key(0)
  LET BUFFER$ = BUFFER$+key$(0)
ENDIF
END PROCEDURE

FUNCTION GetKey$ TYPE STRING
VAR result$ TYPE STRING
VAR l TYPE INTEGER
LET l = LEN BUFFER$
IF l = 0
  LET result$ = CHR 0
ELSEIF l = 1
  LET result$ = BUFFER$(0)
  BUFFER$ = ""
ELSE
  LET result$ = BUFFER$(0)
  BUFFER$ = BUFFER$( 1 TO )
ENDIF
RETURN result$
END FUNCTION

FUNCTION LastKey$ TYPE STRING
RETURN LASTKEY$
END FUNCTION

'------------------------

VAR Clock,Clock0 TYPE INTEGER

PROCEDURE WaitClock
VAR elapsed TYPE INTEGER
REPEAT
  ScanKey
  LET Clock = PEEK 23672
  LET elapsed = Clock-Clock0
  IF elapsed<0 THEN LET elapsed = elapsed+256
UNTIL elapsed >= Period
LET Clock0 = Clock0 + Period: IF Clock0 > 255 THEN LET Clock0 = Clock0 - 256
REM PRINT AT 0,0;INK 2;elapsed;"  ";
END PROCEDURE

'------------------------

PROCEDURE InitADDR
VAR l,c TYPE INTEGER
FOR l=1 TO 8
  FOR c=1 TO 6
    ADDR(l,c) = GameScreen+l*64+c*3
    ' POKE ADDR(l,c),18
  NEXT c
NEXT l
END PROCEDURE

PROCEDURE ShipOFF (l TYPE INTEGER,c TYPE INTEGER)
VAR addr TYPE INTEGER
VIDEO(l,c) = 0
addr = ADDR(l,c)
POKE addr,LEDoff: POKE addr+1,LEDoff: POKE addr+2,LEDoff
END PROCEDURE

PROCEDURE ShipON (l TYPE INTEGER,c TYPE INTEGER)
VAR addr TYPE INTEGER
IF VIDEO(l,c) = 0 THEN VIDEO(l,c) = 1 ' do not change shield value
addr = ADDR(l,c)
POKE addr,LEDon: POKE addr+1,LEDon: POKE addr+2,LEDon
END PROCEDURE

PROCEDURE FireOFF (l TYPE INTEGER,c TYPE INTEGER)
VAR addr TYPE INTEGER
addr = ADDR(l,c)
IF VIDEO(l,c) = 0 THEN POKE addr+1,LEDoff
END PROCEDURE

PROCEDURE FireON (l TYPE INTEGER,c TYPE INTEGER)
VAR addr TYPE INTEGER
addr = ADDR(l,c)
IF VIDEO(l,c) = 0 THEN POKE addr+1,LEDon
END PROCEDURE

'------------------------

'------------------------

PROCEDURE ChangeColors
VAR l,c TYPE INTEGER
VAR oldOFF,oldON TYPE INTEGER
oldOFF = LEDoff
oldON = LEDon
INKoff = (black+blue)-INKoff
INKon = (red+cyan)-INKon
LEDoff = INKoff+64
LEDon = INKon+64
' update colors on screen
FOR l=2 TO 4
  FOR c=7 TO 24
    IF ATTR(l,c) = oldOFF THEN PRINT AT l,c;OVER 1;BRIGHT 1;PAPER 8;INK LEDoff;" ";
    IF ATTR(l,c) = oldON THEN PRINT AT l,c;OVER 1;BRIGHT 1;PAPER 8;INK LEDon;" ";
  NEXT c
NEXT l
FOR l=6 TO 20 STEP 2
  FOR c=7 TO 24
    IF ATTR(l,c) = oldOFF THEN PRINT AT l,c;OVER 1;BRIGHT 1;PAPER 8;INK LEDoff;" ";
    IF ATTR(l,c) = oldON THEN PRINT AT l,c;OVER 1;BRIGHT 1;PAPER 8;INK LEDon;" ";
  NEXT c
NEXT l
END PROCEDURE

'------------------------

PROCEDURE ShowScore
IF score1 > 9 THEN LET score1 = score1-10: LET score2 = score2 + 1: IF score2 > 9 THEN LET score2 = score2-10: LET score3 = score3 + 1: IF score3 > 9 THEN LET score3 = score3-10
ShowDigit(1,score1)
ShowDigit(2,score2)
ShowDigit(3,score3)
END PROCEDURE

'------------------------

PROCEDURE NewWave
' Period for game speed
LET Period = Period-1: IF Period < 8 THEN LET Period = 8
' Enemies
LET VIDEO(2,1) = 1: LET VIDEO(2,2) = 1: LET VIDEO(2,3) = 1: LET VIDEO(2,4) = 1
LET VIDEO(3,1) = 1: LET VIDEO(3,2) = 1: LET VIDEO(3,3) = 1: LET VIDEO(3,4) = 1
LET Enemies = 8
' bombs and missiles
LET BombLin = 0
LET BombCol = 0
LET MissileLin = 0
LET MissileCol = 0
' Scroll
LET ScrollState = 1
LET ScrollLin = 6
LET ScrollCol = 6
' refresh screen
FOR l=1 TO 8
  FOR c=1 TO 6
    IF VIDEO(l,c) = 0
      ShipOFF(l,c)
    ELSE
      ShipON(l,c)
    ENDIF
  NEXT c
NEXT l
END PROCEDURE

'------------------------

PROCEDURE MoveLeft
VAR i TYPE INTEGER
IF PlayerCol > 1
  ShipOFF(PlayerLin,PlayerCol)
  LET PlayerCol = PlayerCol - 1
  ShipON(PlayerLin,PlayerCol)
  BEEP .01,5
ENDIF
END PROCEDURE

PROCEDURE MoveRight
VAR i TYPE INTEGER
IF PlayerCol < 6
  ShipOFF(PlayerLin,PlayerCol)
  LET PlayerCol = PlayerCol + 1
  ShipON(PlayerLin,PlayerCol)
  BEEP .01,5
ENDIF
END PROCEDURE

PROCEDURE MissileFire
IF MissileLin = 0
  IF VIDEO(7,PlayerCol) = 0  ' freeway
    LET MissileLin = 7
    LET MissileCol = PlayerCol
    FireON(MissileLin,MissileCol)
    BEEP .1,5
  ENDIF
ENDIF
END PROCEDURE

PROCEDURE MissileGo
FireOFF(MissileLin,MissileCol)
LET MissileLin = MissileLin-1
IF  MissileLin >= 1 ' free way
  IF VIDEO(MissileLin,MissileCol) = 0
    FireON(MissileLin,MissileCol)
  ELSE
    IF MissileLin = 1 ' hit on mothership
      ShipOFF(MissileLin,MissileCol): LET MothershipCol = 0
      LET score1 = score1 + 5: ShowScore
      LET MissileLin = 0
      BEEP .01,0: BEEP .01,10: BEEP .01,20: BEEP .01,30
    ELSE ' hit on ship
      ShipOFF(MissileLin,MissileCol)
      LET Enemies = Enemies - 1: LET score1 = score1 + 2: ShowScore
      LET MissileLin = 0
      BEEP .01,0: BEEP .01,10: BEEP .01,20: BEEP .01,30
      IF Enemies = 0 THEN NewWave: FOR n=0 TO 30: BEEP .01,n: NEXT n
    ENDIF 
  ENDIF
ENDIF
END PROCEDURE

PROCEDURE BombDrop
LET BombLin = 6
LET BombCol = 1+INT(RND*6)
WHILE VIDEO(BombLin,BombCol) = 0 AND BombLin >= 1
  LET BombLin = BombLin-1
END WHILE
IF BombLin = 1
  LET BombLin = BombLin+1
  FireON(BombLin,BombCol)
ENDIF
END PROCEDURE

PROCEDURE BombGo
FireOFF(BombLin,BombCol)
LET BombLin = BombLin+1
IF BombLin = 9
  REM ground zero
  LET BombLin = 0
ELSEIF VIDEO(BombLin,BombCol) = 0 ' free way
  FireON(BombLin,BombCol)
ELSEIF BombLin = 7 ' hit shield
  LET VIDEO(7,BombCol) = VIDEO(7,BombCol)-1: IF VIDEO(7,BombCol) = 0 THEN ShipOFF(7,BombCol): BEEP .2,30
  LET BombLin = 0
ELSEIF BombLin = 8 ' hit defender
  ShipOFF(PlayerLin,PlayerCol)
  LET BombLin = 0
  BEEP .2,5: BEEP .2,7: BEEP .2,0: BEEP .4,0
  LET GameOver = TRUE
ENDIF
END PROCEDURE

PROCEDURE MothershipStart
VAR i TYPE INTEGER
LET MothershipInc = -MothershipInc
LET MothershipCol = 1+5*(MothershipInc = -1)
ShipON(MothershipLin,MothershipCol)
END PROCEDURE

PROCEDURE MothershipGo
ShipOFF(MothershipLin,MothershipCol)
LET MothershipCol = MothershipCol + MothershipInc
IF MothershipCol < 1 OR MothershipCol > 6
  LET MothershipCol = 0
ELSE
  ShipON(MothershipLin,MothershipCol)
ENDIF
END PROCEDURE

' scroll right
PROCEDURE Scroll1
VAR l TYPE INTEGER
REM shift ship
FOR l = 6 TO 2  STEP -1
  IF VIDEO(l,ScrollCol-1) > 0 THEN ShipON(l,ScrollCol): ShipOFF(l,ScrollCol-1)
NEXT l 
LET ScrollCol = ScrollCol-1
IF ScrollCol = 1
  IF VIDEO(2,6) + VIDEO(3,6) + VIDEO(4,6) + VIDEO(5,6) + VIDEO(6,6) = 0
    REM continue scroll right
    LET ScrollState = 1
    LET ScrollCol = 6
  ELSE
    REM goto scroll down (at right corner)
    LET ScrollState = 2
    LET ScrollCol = 6
    IF VIDEO(6,1) + VIDEO(6,2) + VIDEO(6,3) + VIDEO(6,4) + VIDEO(6,5) + VIDEO(6,6) > 0 THEN BEEP .1,5: BEEP .1,7: BEEP .1,0: BEEP .1,0: LET GameOver = TRUE
  ENDIF
ENDIF
END PROCEDURE

' scroll down (at right corner)
PROCEDURE Scroll2
VAR l TYPE INTEGER
REM shift ship
FOR l = 6 TO 3 STEP -1
  IF VIDEO(l-1,ScrollCol) > 0 THEN ShipON(l,ScrollCol): ShipOFF(l-1,ScrollCol)
NEXT l 
LET ScrollCol = ScrollCol-1
IF ScrollCol = 1 ' goto scroll left
  LET ScrollState = 3
  LET ScrollCol = 1
ENDIF
END PROCEDURE

' scroll left
PROCEDURE Scroll3
VAR i TYPE INTEGER
REM shift ship
FOR i = 6 TO 2  STEP -1
  IF VIDEO(i,ScrollCol+1) > 0 THEN ShipON(i,ScrollCol): ShipOFF(i,ScrollCol+1)
NEXT i 
LET ScrollCol = ScrollCol+1
IF ScrollCol = 6
  IF VIDEO(2,1) + VIDEO(3,1) + VIDEO(4,1) + VIDEO(5,1) + VIDEO(6,1) = 0
    REM continue scroll left
    LET ScrollState = 3
    LET ScrollCol = 1
  ELSE
    REM goto scroll down (at right corner)
    LET ScrollState = 4
    LET ScrollCol = 1
    IF VIDEO(6,1) + VIDEO(6,2) + VIDEO(6,3) + VIDEO(6,4) + VIDEO(6,5) + VIDEO(6,6) > 0 THEN BEEP .1,5: BEEP .1,7: BEEP .1,0: BEEP .1,0: LET GameOver = TRUE
  ENDIF
ENDIF
END PROCEDURE

' scroll down (at left corner)
PROCEDURE Scroll4
VAR l TYPE INTEGER
REM shift ship
FOR l = 6 TO 3 STEP -1
  IF VIDEO(l-1,ScrollCol) > 0 THEN ShipON(l,ScrollCol): ShipOFF(l-1,ScrollCol)
NEXT l 
LET ScrollCol = ScrollCol+1
IF ScrollCol = 6 ' goto scroll right
  LET ScrollState = 1
  LET ScrollCol = 5
ENDIF
END PROCEDURE

PROCEDURE Scroll
IF ScrollState = 1
  Scroll1
ELSEIF ScrollState = 2
  Scroll2
ELSEIF ScrollState = 3
  Scroll3
ELSEIF ScrollState = 4
  Scroll4
ENDIF 
END PROCEDURE

PROCEDURE ShowDigit0 (col TYPE INTEGER)
PRINT AT 2,col;BRIGHT 1;INK INKon;"\..\..";
PRINT AT 3,col;BRIGHT 1;INK INKon;"\: \ :";
PRINT AT 4,col;BRIGHT 1;INK INKon;"\:.\.:";
END PROCEDURE

PROCEDURE ShowDigit1 (col TYPE INTEGER)
PRINT AT 2,col;BRIGHT 1;INK INKon;"\  \ .";
PRINT AT 3,col;BRIGHT 1;INK INKon;"\  \ :";
PRINT AT 4,col;BRIGHT 1;INK INKon;"\  \ :";
END PROCEDURE

PROCEDURE ShowDigit2 (col TYPE INTEGER)
PRINT AT 2,col;BRIGHT 1;INK INKon;"\..\..";
PRINT AT 3,col;BRIGHT 1;INK INKon;"\..\.:";
PRINT AT 4,col;BRIGHT 1;INK INKon;"\:.\..";
END PROCEDURE

PROCEDURE ShowDigit3 (col TYPE INTEGER)
PRINT AT 2,col;BRIGHT 1;INK INKon;"\..\..";
PRINT AT 3,col;BRIGHT 1;INK INKon;"\..\.:";
PRINT AT 4,col;BRIGHT 1;INK INKon;"\..\.:";
END PROCEDURE

PROCEDURE ShowDigit4 (col TYPE INTEGER)
PRINT AT 2,col;BRIGHT 1;INK INKon;"\. \ .";
PRINT AT 3,col;BRIGHT 1;INK INKon;"\:.\.:";
PRINT AT 4,col;BRIGHT 1;INK INKon;"\  \ :";
END PROCEDURE

PROCEDURE ShowDigit5 (col TYPE INTEGER)
PRINT AT 2,col;BRIGHT 1;INK INKon;"\..\..";
PRINT AT 3,col;BRIGHT 1;INK INKon;"\:.\..";
PRINT AT 4,col;BRIGHT 1;INK INKon;"\..\.:";
END PROCEDURE

PROCEDURE ShowDigit6 (col TYPE INTEGER)
PRINT AT 2,col;BRIGHT 1;INK INKon;"\..\..";
PRINT AT 3,col;BRIGHT 1;INK INKon;"\:.\..";
PRINT AT 4,col;BRIGHT 1;INK INKon;"\:.\.:";
END PROCEDURE

PROCEDURE ShowDigit7 (col TYPE INTEGER)
PRINT AT 2,col;BRIGHT 1;INK INKon;"\..\..";
PRINT AT 3,col;BRIGHT 1;INK INKon;"\  \ :";
PRINT AT 4,col;BRIGHT 1;INK INKon;"\  \ :";
END PROCEDURE

PROCEDURE ShowDigit8 (col TYPE INTEGER)
PRINT AT 2,col;BRIGHT 1;INK INKon;"\..\..";
PRINT AT 3,col;BRIGHT 1;INK INKon;"\:.\.:";
PRINT AT 4,col;BRIGHT 1;INK INKon;"\:.\.:";
END PROCEDURE

PROCEDURE ShowDigit9 (col TYPE INTEGER)
PRINT AT 2,col;BRIGHT 1;INK INKon;"\..\..";
PRINT AT 3,col;BRIGHT 1;INK INKon;"\:.\.:";
PRINT AT 4,col;BRIGHT 1;INK INKon;"\  \ :";
END PROCEDURE

PROCEDURE ShowDigit (ndigit TYPE INTEGER, value TYPE INTEGER)
VAR col TYPE INTEGER
LET col = 12+3*(3-ndigit)
IF value = 0
  ShowDigit0 (col)
ELSEIF value = 1
  ShowDigit1 (col)
ELSEIF value = 2
  ShowDigit2 (col)
ELSEIF value = 3
  ShowDigit3 (col)
ELSEIF value = 4
  ShowDigit4 (col)
ELSEIF value = 5
  ShowDigit5 (col)
ELSEIF value = 6
  ShowDigit6 (col)
ELSEIF value = 7
  ShowDigit7 (col)
ELSEIF value = 8
  ShowDigit8 (col)
ELSEIF value = 9
  ShowDigit9 (col)
ENDIF 
END PROCEDURE

PROCEDURE ClearScreen
FOR i=2 TO 20
  PRINT AT i,7;OVER 1;BRIGHT 1;INK LEDoff;"                  ";
NEXT i
END PROCEDURE

PROCEDURE Game
VAR active TYPE INTEGER
VAR k$ TYPE STRING
VAR elapsed TYPE INTEGER

REPEAT

  REM process1
  'WaitClock
  REPEAT
    ScanKey
    LET k$ = GetKey$
    IF k$ = "1" THEN MoveLeft
    IF k$ = "2" THEN MoveRight
    IF k$ = "0" THEN MissileFire
    LET Clock = PEEK 23672
    LET elapsed = Clock-Clock0
    IF elapsed<0 THEN LET elapsed = elapsed+256
  UNTIL elapsed >= Period
  LET Clock0 = Clock0 + Period: IF Clock0 > 255 THEN LET Clock0 = Clock0 - 256

  LET active = MothershipCol
  IF NOT active THEN MothershipStart
  IF active THEN MothershipGo
  LET active = BombLin
  'IF Enemies > 3 THEN IF active+RND < ((score3+1.5)*10+score2)/50 THEN BombDrop
  IF NOT active THEN BombDrop
  IF active THEN BombGo
  IF MissileLin THEN MissileGo

  REM process2
  'WaitClock
  REPEAT
    ScanKey
    LET k$ = GetKey$
    IF k$ = "1" THEN MoveLeft
    IF k$ = "2" THEN MoveRight
    IF k$ = "0" THEN MissileFire
    LET Clock = PEEK 23672
    LET elapsed = Clock-Clock0
    IF elapsed<0 THEN LET elapsed = elapsed+256
  UNTIL elapsed >= Period
  LET Clock0 = Clock0 + Period: IF Clock0 > 255 THEN LET Clock0 = Clock0 - 256

  LET active = MothershipCol
  IF NOT active THEN MothershipStart
  IF active THEN MothershipGo
  LET active = BombLin
  'IF Enemies > 3 THEN IF active+RND < ((score3+1.5)*10+score2)/50 THEN BombDrop
  IF NOT active THEN BombDrop
  IF active THEN BombGo
  IF MissileLin THEN MissileGo

  REM process3
  Scroll

UNTIL GameOver
END PROCEDURE

PROCEDURE WaitForPlayer
PRINT AT 23,6;PAPER blue;INK white;" [s]            [c]";
REPEAT
  PAUSE 0
  LET k$ = INKEY$
  IF k$ = "c" THEN ChangeColors
UNTIL k$ = "s"
BEEP .4,5
RANDOMIZE
LET Clock0 = PEEK 23672
PRINT AT 23,6;PAPER blue;INK white;" [1][2]         [0]";
END PROCEDURE

PROCEDURE InitGame
VAR l,c TYPE INTEGER
LET Period = 16+1
' score
LET score1 = 0
LET score2 = 0
LET score3 = 0
ShowScore
' clear screen
FOR l=1 TO 8
  FOR c=1 TO 6
    VIDEO(l,c) = 0
  NEXT c
NEXT l
' Mothership
LET MothershipLin = 1
LET MothershipCol = 0
LET MothershipInc = -1
' defense shield
LET VIDEO(7,2) = 10: LET VIDEO(7,5) = 10
' Player
LET PlayerLin = 8
LET PlayerCol = 1
LET VIDEO(PlayerLin,PlayerCol) = 1
' new wave
NewWave
' extra
LET GameOver = FALSE
END PROCEDURE

PROCEDURE InitScreen
BORDER 1: PAPER 1: INK 7: CLS
PRINT AT 0,8;INK 7;"* SPACE INVADER *";
PAPER 0
FOR i=1 TO 21
  PRINT AT i,6;INK 1;"                    ";
NEXT i
PRINT AT 1,6;INK 7;"\:'\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\':";
FOR i=2 TO 20
  PRINT AT i,6;INK 7;"\: ";
  PRINT AT i,25;INK 7;"\ :";
NEXT i
PRINT AT 21,6;INK 7;"\:.\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\.:";
REM PLOT 11*8,176-2*8: DRAW 10*8,0: DRAW 0,-4*8+4: DRAW -10*8,0: DRAW 0,4*8-4
PRINT AT 2,12;INK INKoff;"\..\.. \..\.. \..\..";
PRINT AT 3,12;INK INKoff;"\:.\.: \:.\.: \:.\.:";
PRINT AT 4,12;INK INKoff;"\:.\.: \:.\.: \:.\.:";
PRINT AT 6,7;BRIGHT 1;INK INKoff;"\A\B\C\A\B\C\A\B\C\A\B\C\A\B\C\A\B\C";
FOR i=1 TO 5
  PRINT AT 6+i*2,7;BRIGHT 1;INK INKoff;"\D\E\F\D\E\F\D\E\F\D\E\F\D\E\F\D\E\F";
NEXT i
REM PRINT AT 18,7;INK INKoff;"   \G\H\I      \G\H\I";
REM PRINT AT 19,7;INK INKoff;" \E  \E  \E  \E  \E  \E ";
PRINT AT 18,7;BRIGHT 1;INK INKoff;"\M\E\N\M\E\N\M\E\N\M\E\N\M\E\N\M\E\N";
PRINT AT 20,7;BRIGHT 1;INK INKoff;"\J\K\L\J\K\L\J\K\L\J\K\L\J\K\L\J\K\L";
REM PRINT AT 23,7;INK 7;"12     keys     90";
PRINT AT 23,6;PAPER blue;INK white;" [1][2]         [0]";
END PROCEDURE

PROCEDURE DefineChars
VAR i,n TYPE INTEGER
VAR b$ TYPE STRING
RESTORE ' DataChars
READ b$
REPEAT
  FOR i=0 TO 7
    READ n
    POKE USR b$+i,n
  NEXT i
  READ b$
UNTIL b$ = ""
END PROCEDURE

PROCEDURE DataChars
DATA "A"
DATA BIN 00000000
DATA BIN 00000011
DATA BIN 00000001
DATA BIN 00011111
DATA BIN 00111111
DATA BIN 01111111
DATA BIN 00111111
DATA BIN 00000111
DATA "B"
DATA BIN 00111100
DATA BIN 11111111
DATA BIN 01011010
DATA BIN 11111111
DATA BIN 11111111
DATA BIN 11111111
DATA BIN 11111111
DATA BIN 00111100
DATA "C"
DATA BIN 00000000
DATA BIN 11000000
DATA BIN 10000000
DATA BIN 11111000
DATA BIN 11111100
DATA BIN 11111110
DATA BIN 11111100
DATA BIN 11100000
DATA "D"
DATA BIN 00000010
DATA BIN 00000010
DATA BIN 00000110
DATA BIN 00001111
DATA BIN 00001111
DATA BIN 00011100
DATA BIN 00010000
DATA BIN 00010000
DATA "E"
DATA BIN 00011000
DATA BIN 00111100
DATA BIN 01111110
DATA BIN 11111111
DATA BIN 11111111
DATA BIN 01111110
DATA BIN 00111100
DATA BIN 00011000
DATA "F"
DATA BIN 01000000
DATA BIN 01000000
DATA BIN 01100000
DATA BIN 11110000
DATA BIN 11110000
DATA BIN 00110000
DATA BIN 00010000
DATA BIN 00001000
END PROCEDURE

PROCEDURE DataChars2
DATA "G"
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00000001
DATA BIN 00000111
DATA BIN 00011111
DATA BIN 01111111
DATA BIN 00000000
DATA BIN 00000000
DATA "H"
DATA BIN 00011000
DATA BIN 01111110
DATA BIN 11111111
DATA BIN 11111111
DATA BIN 11111111
DATA BIN 11111111
DATA BIN 00000000
DATA BIN 00000000
DATA "I"
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 10000000
DATA BIN 11100000
DATA BIN 11111000
DATA BIN 11111110
DATA BIN 00000000
DATA BIN 00000000
DATA "J"
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00011111
DATA BIN 00111111
DATA BIN 01111111
DATA BIN 00111111
DATA BIN 00011110
DATA "K"
DATA BIN 00011000
DATA BIN 01111110
DATA BIN 11111111
DATA BIN 11111111
DATA BIN 11111111
DATA BIN 11111111
DATA BIN 11111111
DATA BIN 00000000
DATA "L"
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 11110000
DATA BIN 11111100
DATA BIN 11111110
DATA BIN 11111100
DATA BIN 01111000
DATA "M"
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00001111
DATA BIN 00011111
DATA BIN 00111100
DATA BIN 01111000
DATA BIN 11110000
DATA "N"
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 00000000
DATA BIN 11110000
DATA BIN 11111000
DATA BIN 00111100
DATA BIN 00011110
DATA BIN 00001111
DATA ""
END PROCEDURE

PROCEDURE TellStory
BORDER 1: PAPER 1: INK 7: CLS
PRINT AT 5,0;"In 1980 was launched"
PRINT TAB 0;"the first handheld videogame:"
PRINT TAB 5;""
PRINT TAB 5;INK 6;"SPACE INVADER"
PRINT TAB 5;"  by Entex"
PRINT TAB 5;""
PRINT TAB 5;"Red leds screen"
PRINT TAB 5;"6 x 8 resolution"
PRINT TAB 5;"6 AA batteries"
PRINT TAB 5;""
PRINT TAB 0;"On youtube search:"
PRINT TAB 0;"  Entex Space Invader"
PAUSE 15*50
END PROCEDURE

PROCEDURE MainRoutine
TellStory
DefineChars
InitADDR
InitScreen
WaitForPlayer
InitGame
REPEAT
  Game
  WaitForPlayer
  ClearScreen
  InitGame
UNTIL FALSE
END PROCEDURE

PROGRAM SpaceInvader
FOR n=0 TO 30: BEEP .01,n: NEXT n
PRINT AT 23,0;"Pascalated Boriel ZX BASIC demo";
PAUSE 3*50
MainRoutine
PRINT AT 21,10;INK 2;"The End"
END PROGRAM