Page | Page | ||
2 | Breakout | 30 | HexPawn |
5 | 3D Maze | 33 | Drive |
9 | Letters | 35 | Biorythm |
11 | Matches | 36 | Sums Tester |
12 | Russian Roulette | 38 | Scramble |
13 | Compart | 40 | Designs |
14 | Talkback | 41 | Hunt the Wampus |
16 | MoonLander | 44 | Simon |
17 | Bouncing Ball | 45 | Screens |
18 | Patchwork | 48 | Hangman |
19 | Bugrace | 50 | Programming Tips |
20 | Space Battle | 57 | Other BASICs |
22 | Hammurabi | 67 | Tape Recording |
24 | Higher/Lower | 70 |
The 6522 Versatile Interface Adapter chip |
25 | Buzz-Word | 74 |
The 8255 Programmable Peripheral Interface Chip |
26 | Othello | 75 | Block 0 RAM |
28 | Number Guessing A | 77 | ROM Routines |
29 | Number Guessing B | 79 | VDU codes |
The programs and other information given in this book have been thoroughly checked and are believed to be accurate, but should you find any error then please let us have full details so that it may be corrected to help other readers. © 1981 TIMEDATA Ltd. 57 Swallowdale,Basildon,Essex |
|||
Edition |
1 ; Feb 1981 2 ; June 1981 3 ; October 1981 |
Text; 2K
VDU ½K
Integer
A noisy and fast moving version of the popular computer game, Breakout starts with a wall 5 bricks thick across the top of the screen and a small star passing from side to side across the bottom of the screen.
Pressing either of the SHIFT keys will make the star shoot up diagonally towards the wall. If it hits a brick then that brick will either fall out of the wall, or - if it is held up by another brick - will turn grey and fall as soon as it is no longer supported.
Points are scored by sending the star off the top of the screen through a gap in the wall. An arrow then appears at the point of exit and your score is increased by one. But be careful; if you accidentally hit an arrow it will fall and you lose that point !
You have a limited time in which to score as many points as possible. A count-down display of the time remaining is shown at the top left of the screen. When the game has finished, a new one may be started by pressing any key.
1 REM- BREAKOUT 2 REM- WRITTEM 22-10-80 3 REM- BY D.DINI 4 GOSUBy 5 CLEAR0;Y=#B001;F=0;A=4000 6 D=256*5 10 S=#8020;E=#80BF 15 V=1;G=0;Q=1 20 FORT=S TO E;?T=#7F;NEXTT 25 W=0;J=#81C0 27 P.$30,A,F
30 FORX=G TO(31-G) STEPQ 32 M=X?J;N=X+J 34 IFJ<S;GOTOe 36 IFM=#1E;F=F-1 37 IFM<>#40;O=X;X=(31-G);GOTOx 40 ?N=#2A;IFW=0;WAIT;WAIT 50 IFW=-32;B=60;GOS.s 55 ?N=#40 56 IF?YP<>0;V=1 57 IFV=0;GOTOa 60 IF?YP=0;W=-32 61 IF?Y&1=0;W=-32 70aJ=J+W 80 A=A-1;IFA=0;GOTOf 210 N.;X=X-Q 215 G=X;Q=(G+1)/(-G+1) 220 IF?#B001P=0;V=0 230 G.25 490eZ=X 500 X=31-G;NEXT 510 F=F+1 515 Z=Z-Q;J=J-W 520 Z?J=#1E 525 FORI=1TO4;B=40;D=256*#22;GOS.s;N.;D=256*5 530 GOTO25 1000fP.$30''''''''''''" ***GAME OVER***" 1005 P.$30,A,F 1006 D=#22*256;B=100;FORI=1TO12;GOS.s;N. 1007 X=31-G;N. 1010 LINK#FFE3;RUN 2000xIFO?(J-W)<>#40;O?J=#FF;B=20;GOS.s;G.210 2002 IFO?J=#1E;D=256*#22;B=#C0;F.I=1TO4;GOS.s;N.;D=256*5 2005 B=20 2010 O?J=#40;J=J-W 2020 IFJ>#8200;LINKNN1;G.u 2030 O?J=#FF 2035 B=B+5;GOS.s 2040 GOTO2010 2050uJ=J+W 2060 IFO?J=#40;G.u 2070 IFO?J=#FF;G.x 2080 G.210 5000yDIML(2),NN(10),WW(5) 5005 DIMP(-1) 5010 C=#B002 5015 P.$21 5020[ 5025 \ RANDOM NOISE GENERATOR(SEE MANUAL) 5030:NN1LDY@#B0
5040:NN0 5050 LDAL;AND@#F7;STAC;LDAL 5060 AND@#48;ADC@#38 5070 ASLA;ASLA 5080 ROLL+2;ROLL+1;ROLL 5085 LDA@#C0;DEX;BNEP-1 5090 DEY;BNENN0;RTS 5100 \ TONE GENERATOR (SEE "HARPSICHORD" PROGRAM IN MANUAL) 5110:WW0STA#80;LDA@0 5120:WW2LDX#80 5130:WW1DEX;NOP;NOP;BNEWW1 5140 EOR@4;STA#B002 5150 DEY;BNEWW2;RTS 5160] 5170 P.$6 6000 RET. 7000sC=A;R=Y;A=B;Y=D/A 7010 LINKWW0;A=C;Y=R;RET.
The program uses two machine language routines (lines 5020 to 5160) to generate various sound effects.
The program draws on the screen by storing appropriate values (e.g. #2A for a *) in the VDU screen memory locations 8000-81FF. Thus line 20 draws the initial 5 rows of bricks, line 40 plots a *, and line 55 deletes the old *.
The main program loop is from lines 30 to 210, which moves the star across the screen; line 32 branching to e if you have scored a point, line 36 reducing your score if you have hit an arrow. If you hit anything, line 37 branches to the routine at line 2000. Lines 40-55 shift the image of the star - using subroutine s to provide sound effects if it is moving upwards. Lines 56-60 set W to -32 when the SHIFT key has been pressed.
Lines 490-530 increment your score, PLOT an arrow in the place where you broke through the wall, using the subroutine s to generate the winning sound.
Line 2000 is reached if the star hits anything, and returns to the main loop at line 210 if a solid brick is below the one hit. Line 2002 is executed if you have hit an arrow. Lines 2005-2040 make the falling brick images and sounds. Lines 2050-2070 repeat the process if any grey blocks are left unsupported.
Line 1010 is reached at the end of the program; it waits for any key to be pressed, then starts a new game.
Text; 5K
VDU; 1K
Integer
This program generates a random maze of specified dimensions, then plots it in 3D as though you were actually inside it. You then have to find your way out by moving forward (key F), or by turning right (R) or left (L). Pressing key H (for HELP!!!) will give you your co-ordinates and the direction in which you are pointing.
The exit is represented by two vertical poles;
EXIT
The maximum size of maze allowed is 19 x 18.
1 P.$12'''"LABYRINTH:"''"MAZES IN 3D..."''' 3 REM-BY D.DINI 6/10/80 5P.$21 10 DIMVV1 15 P=#2800 20[ 30:VV0 JSR#FFE3;STA#80;RTS;] 40 P.$6 100 P."MAZE SIZE"' 110 INPUT"WIDTH"I,"HEIGHT"H 120 DIMA(I*H-1),B(I*H-1) 130 FORX=0TO(I*H-1);A?X=9;NEXT 135 CLEAR0 140 Y=ABSRND%H;L=0;X=-1;M=Y;D=1;E=D 145 MOVE(X*2+2),(Y*2) 150 R=0;IF ABSRND%2;GOTOa 160 D=ABSRND%4 165aV=0;W=0 170 GOTO(180+D) 180 W=1;G.b 181 V=1;G.b 182 W=-1;G.b 183 V=-1 190bIFX+V>I-1 ORX+V<0ORY+W>H-1 ORY+W<0;R=R+1;GOTOt 200 IFA?((X+V)*H+Y+W)<>9;R=R+1;GOTOt 210 X=X+V;Y=Y+W 220 A?(X*H+Y)=D;GOSUBu 225 DRAW(X*2+2),(Y*2) 230 GOTO150
240tIFR>3;GOTOe 250 IFR>2;P=D;GOTOc 260 IFR>1;K=D;P=9;GOTOc 270 J=D;K=9;P=9 280cDO D=ABSRND%4 290 UNTIL D<>J AND D<>K AND D<>P 300 GOTOa 400eD=A?(X*H+Y);D=D+4;A?(X*H+Y)=D 405 GOSUB3000 410 D=D-4 420 V=0;W=0 430 GOTO(440+D) 440 W=-1;G.h 441 V=-1;G.h 442 W=1;G.h 443 V=1 450hX=X+V;Y=Y+W;IFX=L;IFY=M;GOTOx 455 PLOT14,(X*2+2),(Y*2);WAIT;WAIT;WAIT 456 PLOT14,(X*2+2),(Y*2) 460 IFA?((X+1)*H+Y)=9;IFX+1<I;D=1;GOTOj 470 IFA?((X-1)*H+Y)=9;IFX-1>-1;D=3;GOTOj 480 IFA?(X*H+Y+1)=9;IFY+1<H;D=0;GOTOj 490 IFA?(X*H+Y-1)=9;IFY-1>-1;D=2;GOTOj 500 D=A?(X*H+Y);GOTO 420 510jMOVE(X*2+2),(Y*2) 520 F=B?(X*H+Y) 530 IFD=0;F=F&#E;G.i 540 IFD=1;F=F&#D;G.i 550 IFD=2;F=F&#B;G.i 560 IFD=3;F=F 570iB?(X*H+Y)=F 580 E=D;GOTOa 600xX=I-1 610 FORY=0TO H-1 620 IF A?(X*H+Y)>3;GOTOq 630 NEXTY 640 Y=ABSRND%H 645qMOVE(X*2+2),(Y*2) 650 DRAW((X+1)*2+2),(Y*2) 660 N=X;O=Y 670 B?(N*H+O)=B?(N*H+O)&#D 690 P.$30"MAZE COMPLETE"' 700 P."PRESS ANY KEY TO ENTER MAZE";LINK#FFE3 705 B?(L*H+M)=B?(L*H+M)|8 720 Q=1;Y=M;X=L 726 CLEAR1;G=0 730 S=0;GOSUB4050 770 MOVE34,0;DRAW34,63;MOVE94,0;DRAW94,63 810 IFF&1<>0;MOVE34,0;DRAW94,0;MOVE34,63; DRAW94,63;G=1;GOTOz
815 REM--DEPTH 2 820 MOVE46,12;DRAW46,51;MOVE82,12;DRAW82,51 830 GOSUBl 835 IFS=1;G.z 840 IFF&8<>0;MOVE46,12;DRAW34,0;MOVE46,51;DRAW34,63;GOTO860 850 MOVE46,12;DRAW34,12;MOVE46,51;DRAW34,51 860 IFF&2<>0;MOVE82,12;DRAW94,0;MOVE82,51;DRAW94,63;GOTO880 870 MOVE82,12;DRAW94,12;MOVE82,51;DRAW94,51 880 IFF&1<>0;MOVE46,12;DRAW82,12;MOVE46,51;DRAW82,51;GOTOz 890 REM-DEPTH3 900 MOVE54,20;DRAW54,43;MOVE74,20;DRAW74,43 910 GOSUBl 915 IFS=1;GOTOz 920 IFF&8<>0;MOVE54,20;DRAW46,12;MOVE54,43;DRAW46,51;GOTO940 930 MOVE54,43;DRAW46,43;MOVE54,20;DRAW46,20 940 IFF&2<>0;MOVE74,20;DRAW82,12;MOVE74,43;DRAW82,51;GOTO960 950 MOVE74,20;DRAW82,20;MOVE74,43;DRAW82,43 960 IFF&1<>0;MOVE54,20;DRAW74,20;MOVE54,43;DRAW74,43;GOTOz 970 REM-DEPTH4 980 MOVE58,24;DRAW58,39;MOVE70,24;DRAW70,39 990 GOSUBl 995 IFS=1;GOTOz 1000 IFF&8<>0;MOVE58,24;DRAW54,20;MOVE58,39;DRAW54,43;GOTO1020 1010 MOVE58,39;DRAW54,39;MOVE58,24;DRAW54,24 1020 IFF&2<>0;MOVE70,24;DRAW74,20;MOVE70,39;DRAW74,43;GOTO1040 1030 MOVE70,39;DRAW74,39;MOVE70,24;DRAW74,24 1040 IFF&1<>0;MOVE58,24;DRAW70,24;MOVE58,39;DRAW70,39;GOTOz 1050 MOVE61,27;DRAW61,36;MOVE67,27;DRAW67,36 1060 GOSUBl 1065 IFS=1;G.z 1070 IFF&8<>0;MOVE61,27;DRAW58,24;MOVE61,36;DRAW58,39;GOTO1090 1080 MOVE61,27;DRAW58,27;MOVE61,36;DRAW58,36 1090 IFF&2<>0;MOVE67,27;DRAW70,24;MOVE67,36;DRAW70,39;GOTO1110 1100 MOVE67,27;DRAW70,27;MOVE67,36;DRAW70,36 1110 IFF&1<>0;MOVE61,36;DRAW67,36;MOVE61,27;DRAW67,27 1120zLINKVV0;Z=?#80 1122 IFZ<>CH"H";GOTO1130 1123 P.$12"YOU ARE AT "X","Y 1124 P.'"FACING " 1125 IFQ=0;P."DUE NORTH"' 1126 IFQ=1;P."DUE EAST"' 1127 IFQ=2;P."DUE SOUTH"' 1128 IFQ=3;P."DUE WEST"' 1129 P."PRESS ANY KEY TO CONTINUE";LINK#FFE3;GOTOp 1130 IFZ<>CH"R";G.1140 1135 Q=Q+1;IFQ=4;Q=0 1136 G.p 1140 IFZ<>CH"L";GOTO1150 1145 Q=Q-1;IFQ=-1;Q=3 1146 G.p 1150 IFZ=CH"F"ANDG=0;GOTOf
1155 P.$7;GOTOz 1160fGOTO(1170+Q) 1170 Y=Y+1;GOTOp 1171 X=X+1;GOTOp 1172 Y=Y-1;GOTOp 1173 X=X-1 1175pL=X;M=Y;IFL>N;IFO=M;P.$12"WELL DONE!"';RUN 1190 CLEAR1;G=0;GOTO730 2000uIFD/2*2=D;B?(X*H+Y)=#A;GOTO2020 2010 B?(X*H+Y)=#5 2020 IFD=E;RET. 2030 IFE=0IFD=1;F=9;GOTOw 2040 IFE=3IFD=2;F=9;GOTOw 2050 IFE=0IFD=3;F=3;GOTOw 2060 IFE=1IFD=2;F=3;GOTOw 2070 IFE=2IFD=3;F=6;GOTOw 2080 IFE=1IFD=0;F=6;GOTOw 2090 IFE=3IFD=0;F=#C;GOTOw 2100 IFE=2IFD=1;F=#C;GOTOw 2110wB?((X-V)*H+Y-W)=F;E=D;RET. 2999 REM-BLOCK OFF DEAD END 3000 F=B?(X*H+Y) 3010 IFD=4;F=F|1;GOTOs 3020 IFD=5;F=F|2;GOTOs 3030 IFD=6;F=F|4;GOTOs 3040 F=F|8 3060sB?(X*H+Y)=F;RET. 4000lV=0;W=0;S=0 4010 GOTO(4020+Q) 4020 W=1;GOTOk 4021 V=1;GOTOk 4022 W=-1;GOTOk 4023 V=-1;GOTOk 4040kL=L+V;M=M+W 4045 IFL=N+1ANDM=0;F=10;S=1;RET. 4050 F=B?(L*H+M) 4055 U=Q;T=F 4060mC=F 4070 IFU=0;R. 4080 F=F/2;IFC&1<>0;F=F+8 4100 U=U-1;GOTOm
Text; 2K
VDU; ½K
Integer
This program plots a number of letters on the screen. You then have to erase them all by moving the cursor over each letter in turn. If you hit the edge of the screen or donut erase the letters in alphabetic order then the game finishes and you lose.
Once the game has started the cursor is continually moving. To change it's direction press one of the keys 4,5,6 or 7; which make it, go down, ups left or right respectively.
As it moves, the cursor leaves a trail that can cause great confusion if you have to retrace your steps, as you are then unable to see exactly where you are.
The difficulty of the game can be varied by specifying a different number of letters (1 to 26) to be erased, or by varying the speed of movement to 10) in response to questions asked when the game is started. You are also asked for a 'course number'. This is used to seed the random number generator used to position the letters, so that you may run exactly the same game again by specifying the same course number.
When the game has finished - either because you have made a mistake or because, you have successfully erased all of the letters, then another game is automatically started.
1 REM-LETTERS BY D.DINI WRITTEN 1/8/80 9 P.$21;@=0 10 DIM VV(2);P=#2802 15 FOR Q=1 TO 2 19 REM-ASSEMBLE ROUTINE TO READ KEYS 4-7 20[ 30:VV0 LDX@6 40:VV1 STX#B000;LDA#B001;AND@4 50 BEQ VV2 60 INX;CPX@10;BNE VV1 70:VV2 STX#80;RTS 75] 80 NEXT Q 90 P.$6 100 INPUT"NO OF LETTERS"L 105 IF L>26;GOTO 100 110 INPUT"SPEED"S 114 REM-SEED RANDOM NUMBER GENERATOR 115 ?12=0;INPUT"COURSE"C;!8=C
120 CLEAR 0;MOVE 0,0;U=1 130 DRAW 63,0;DRAW 63,47;DRAW 0,47;DRAW 0,0 134 REM-PLOT LETTERS ON SCREEN 135 FOR A=1 TO L 140 X=ABSRND%30+1;Y=ABSRND%14+1;P=#8000+32*Y+X ;IF?P<>64;GOTO140 150 ?P=A;NEXT A 160 X=2;Y=45;R=1 165 REM-WAIT TILL KEY PRESSED 170 GOSUB k;IF O=10 THEN GOTO 170 180mPLOT 13,X,Y;GOSUB k;U=U+1;GOTO (K-6+181) 181 X=X+1;GOTO z 182 X=X-1;GOTO z 183 Y=Y+1;GOTO z 184 Y=Y-1 185z ?#B000=0 186 IF R>L THEN GOTO s 189 REM-CHECK IF BORDER HIT 190 IF X<1 OR X>62 OR Y<1 OR Y>46 THEN GOTO e 195 REM-CHECK IF LETTER HIT 200 V=X/2;W=15-Y/3;P=#8000+32*W+V 205 REM-CHECK IF RIGHT LETTER 210 IF ?P>26 THEN GOTO m 220 IF ?P=R R=R+1;?P=64;GOTO m 230 GOTO e 240sP.$30"WELL DONE,TOOK "U" MOVES"';RUN 250e?P=42;P.$30$7"SHAME!"';RUN 489 REM-GET KEY & WAIT 490kFORT=10TO S STEP-1 500 LINK VV0;O=?#80;IF O<10 K=O 510 WAIT;NEXT;RETURN
By leaving out the REM lines and abbreviating the other lines, 'letters' can be made to fit into 1K text RAM space.
A machine language routine (lines 20-75) is used to scan the keyboard by directly manipulating the 8255 I/O chip ports. Line 9 prevents the assembly listing from appearing on the screen when the program is executed. Line 90 subsequently re- enables the display.
Since the random number seed occupies 5 bytes of RAM, (locations 8 to 12), while an integer variable takes only 4 bytes, pre-setting the seed to the 'course' number (C; line 115) involves setting RAM location 12 to zero as well as storing the value of C in the other four bytes.
Text; 1K
VDU ½K
Integer
Matches is a simplified form of NIM. Starting with a row of from 21 to 32 matches, the player and the computer take turns to remove 1, 2 or 3 matches. The player left with the last match loses.
10 REM MATCHES 20 @=0 100 M=ABSRND%12+21;GOSUB 900 110 PRINT"WE TAKE TURNS TO REMOVE"' 120 PRINT"1,2 OR 3 MATCHES."'' 130 PRINT"THE ONE LEFT WITH THE LAST"' 140 PRINT"MATCH LOSES."'' 300 PRINT M" MATCHES, YOUR TURN"' 310 IF M=1 GOTO 510 320 INPUT"HOW MANY WILL YOU TAKE "T 330 IF T=M GOTO 500 340 IF T>3 OR T<1 OR T>M GOTO 320 400 M=M-T;IF M=1 GOTO 600 410 R=M%4;C=(R+3)%4 420 IF R=1 C=1+ABSRND%3 430 M=M-C;IF M=0 GOTO 600 440 GOSUB 900 450 PRINT"YOU TOOK ",T' 460 PRINT"SO I TOOK ",C'' 470 GOTO 300 500 PRINT $12 510 PRINT"I WON !!!";END 600 PRINT $12,"*** YOU WON ***" 610 FOR I=1 TO 10;PRINT $7;NEXT;END 900 PRINT $12;CLEAR 0;FOR K=1 TO M 910 MOVE (2*K),0;DRAW (2*K),10 920 NEXT;RETURN
Line 100 establishes the starting number of matches and displays them by calling subroutine 900. Lines 110 to 140 then present the instructions above the displayed row of matches.
Lines 300-340 get the player's choice and check that it is valid, lines 400-470 then calculate the computer's move. If neither side has won then the current state of the game is displayed and the next move played.
Text; 1K
VDU; ½K
Integer
Russian Roulette is a game for two or more players who take turns to place a loaded revolver to their heads and pull the trigger. Five of the revolver's chambers are empty, the sixth contains a live round. The game is over when a player refuses to take his turn, or when the revolver fires.
In response to the question 'DO YOU WANT TO PULL THE TRIGGER', enter either Y or N, then press the Return key.
1 REM RUSSIAN ROULETTE 10 DIM A(64) 20 X=#B002;PRINT $12 110 PRINT"YOU HAVE A REVOLVER"' 120 PRINT"WITH 5 EMPTY CHAMBERS"' 130 PRINT"AND ONE LOADED ONE."'' 140 PRINT"IT IS POINTED AT YOUR HEAD !"'' 200 INPUT"DO YOU WANT TO PULL THE TRIGGER"$A 210 PRINT $12 220 IF CH$A=CH"N" THEN GOTO 500 230 FOR I=1 TO 30;WAIT;NEXT 240 IF ABSRND%6=5 THEN GOTO 400 300 ?X=?X:4;?X=?X:4 310 PRINT"LUCKY !"''''''';GOTO 200 400 CLEAR 0;MOVE 18,30 410 PLOT 5,16,30;PLOT 5,16,6 420 PLOT 5,56,6;PLOT 5,56,12 430 PLOT 5,50,12;PLOT 5,50,6 440 MOVE 40,24;PLOT 5,40,6 450 PLOT 13,53,13 460 PRINT''"!!! YOU ARE DEAD !!!" 470 END 500 PRINT"*** CHICKEN ***" 510 FOR I=1 TO 20;?X=?X:4;WAIT;NEXT;END
The two PRINT $12 statements (lines 20 & 210) clear the VDU screen and position the cursor at the top left corner.
Line 230 gives a half-second pause to heighten the tension. Line 300 generates a 'click' sound; line 510 makes a suitable 'raspberry' noise.
Lines 400-450 may be improved by artistically minded programmers.
Text; 1K
VDU; 1K
Integer
This program draws a sequence of five abstract pictures in either black and white, or black, grey and white.
1 REM COMPART BY D. DINI AUG.'80 5 DIM A(7);!A=#10204080;A!4=#1020408 10 P.$12 20 P." computer art"'' 25 IN."DO YOU WANT SINGLE(1) OR DOUBLE(2) SHADE DRAWINGS"I 30 P."PRESS ANY KEY TO START" 35 LINK #FFE3 37 FOR D=1 TO 5 40 CLEAR 1;IF I=2 THEN ?#B000=#10 44 MOVE 1,1;X=126;Y=62 45 DRAW 1,Y;DRAW X,Y;DRAW X,1;DRAW 1,1 50 P=ABSRND%123+2;Q=ABSRND%59+2 60 GOSUBd 70 FOR Z=1 TO 10000;NEXT Z 80 NEXT D 90 RUN 1000dX=RND%2;Y=RND%2 1010 V=X+P;W=Y+Q;GOSUBt 1020 IFC GOTOn 1030 T=0 1040 P=P+X;Q=Q+Y 1050 PLOT 13,P,Q 1060 GOTO 1010 1070nT=T+1 1080 IF T<100 GOTOd 1090 RETURN 2000tB=V/8+(63-W)*16+#8000 2010 C=(?B&(A?(V&7))<>0);RETURN
If double shade drawings are selected, then I=2 and line 40 sets the VDU controller to mode 1a.
Line 70 gives a short pause at the end of each drawing for you to admire it before the computer begins its next opus.
Text; 2K
VDU; 2-6K
Integer
While this program does not answer Man's dream of a talking computer, it does allow you to record a few seconds of speech in ATOM's memory, then play it back on demand.
The speech is converted to digital form then stored in the VDU RAM area (above the text screen area), each 1K byte giving one second of recording time. In any digital speech recording system a compromise must be made between quality of reproduction and the amount of storage needed - in this case the choice has been to extend the recording time as much as possible and accept a pretty dreadful quality for the reproduced signal) although a noticeable improvement can be made by careful choice of the recording-level and by turning any amplifier 'treble' control to minimum.
Recording is done from a microphone connected via a suitable amplifier to ATOM's 'CASS IN' port. The level needed by ATOM is about the same as when loading programs from tape, so the cassette recorder amplifier will probably be suitable. Playback is through ATOM's built-in loudspeaker.
When the program is run, it asks if you want to Record or Play-back If you choose to record then the screen will be covered by 'snow' for a few seconds while the program initialises the VDU RAM area. You are then asked to press any key to start the recording process. While recording, the screen will again be sprinkled with white lines as the data is stored.
10 REM TALKBACK 20 DIM YY(6),ZZ(7),A(10) 30 P.$12;P=P&#FF00+#100 100 P.$21;GOSUBa;GOSUBa;P.$6$12 110 DO INPUT"RECORD (R) OR PLAYBACK (P) "$A 120 UNTIL ?A=CH"P" OR ?A=CH"R" 130 IF ?A=CH"P" LINK ZZ0;GOTO 100 200 P.'"ONE MOMENT PLEASE"' 210 C=#1010101 220 FOR X=#8200 TO #97FF STEP 4 230 !X=C;NEXT X 240 P.$12"PRESS ANY KEY TO START RECORDING" 250 LINK #FFE3;LINK YY0 270 P.$12"** END **"''$7;GOTO 100
1000a REM RECORD ROUTINE 1005 DIM P(-1) 1010[ 1020:YY0 LDX @0;LDY @#82 1030:YY1 LDA @10 1040:YY2 SEC;NOP;SBC @1;BNE YY2 1050 LDA #B002;ROL A;ROL A;ROL A 1060:YY3 ROL #8200,X;BCC YY5 1070 INX;BNE YY6 1080 INY;STY YY3+2;CPY @#98 1090:YY4 BNE YY1;RTS 1100:YY5 LDA @#FF;NOP 1110:YY6 NOP;NOP;BNE YY4 1120] 1500 REM PLAYBACK ROUTINE 1510[ 1520:ZZ0 LDX @0;LDY @#82 1530:ZZ1 LDA @8;STA ZZ7 1540:ZZ2 LDA #8200,X 1550:ZZ3 ASL A;PHA;PHP;LDA @10 1560:ZZ4 SEC;SBC @1;BNE ZZ4;NOP 1570 PLP;LDA @4;ADC @0;STA #B003 1580 PLA;DEC ZZ7;BNE ZZ6;INX;BNE ZZ5 1590 INY;STY ZZ2+2;CPY @#98;BNE ZZ1;RTS 1600:ZZ5 PHA;PLA;NOP;JMP ZZ1 1610:ZZ6 ASL #FF00,X;ASL #FF00,X;ASL #FF00,X;JMP ZZ3 1620:ZZ7 NOP 1630];RETURN
As given, the program expects the full 6K bytes of VDU RAM. If less RAM is available, the CPY @#98 instructions in lines 1080 and 1590 should be changed to;
CPY @#94 for 5K bytes VDU RAM #90 4 " " #8C 3 " " #88 2 " "
The main work is done by the two machine language routines at lines 1000-1120 and 1500-1630. When recording, the voltage on the CASS IN port is examined every 125 µS, and one bit of the memory is set to either '1' or '0' depending on whether the signal was positive or negative. When playing back, a single bit is taken from the memory every 125 µS and the state of the loudspeaker drive line set high or low accordingly. A large part of the machine language routines (notably lines 1040, 1100, 1110, 1560, 1600 & 1610) consists of 'time wasting' instructions inserted so that the over-all loop time is always 125 uS.
Note that lines 210-230 preset the RAM before recording so that each byte has bits 1-7 =0 and bit 0 = 1.
Text; 2K
VDU; 1K
Integer
You are piloting a rocket landing on the Moon; the **!!**!!** computer has failed again (and the engine sounds rough). At the start of the simulation you are 450 metres up, travelling horizontally at 300 metres per second, and starting to fall from orbit. You should aim to land within the Lunar Landing Area (the small white rectangle on the Moon's surface) with a vertical velocity of less than 50 m/s and a horizontal velocity of less than 20.
Your controls are the keys F, R and U, which apply forward, reverse or upward thrust respectively but only one at a time. Instrument readings of height, velocities and fuel remaining are given on the right of the screen. Happy landings.
10 REM MOONLANDER 20 DIM P(-1);P.$21 30[;JSR #FE71;STY #80;RTS;];P.$6 100 J=#1B8020;K=#1B8080;L=#1B80E0 110 M=#1B8140;N=#B002;O=#DE 120 D=0;A=45000;V=0;H=300;F=1250 130 T=1000;Y=A/T+2;X=D/T 140 CLEAR 0;@=5;MOVE 0,0;DRAW 63,0;MOVE 0,1 150 DRAW 63,1;MOVE 31,2;DRAW 33,2 160 !O=#1D8000;P."ALT" 170 !O=#1D8060;P."H-V" 180 !O=#1D80C0;P."V-V" 190 !O=#1C8120;P."FUEL" 200a FOR U=1 TO 5;IF A<1 A=0;G.c 210 WAIT;PLOT15,X,Y;X=D/T;Y=A/T+2 220 WAIT;PLOT13,X,Y;?N=#D3 230 LINK TOP;R=?#80;IF F=1 F=0;G.b 240 IF R=53 V=V-5;F=F-5;?N=#D7 250 IF R=50 H=H-3;F=F-3;?N=#D7 260 IF R=38 H=H+3;F=F-3;?N=#D7 270b A=A-V;D=D+H;V=V+2;N. 280c !O=J;P.A/100;!O=K;P.H;!O=L;P.V;!O=M;P.F 290 IF A>0 G.a
300 IF ABSV<50 IF ABSH<20 G.d 310 FOR I=1 TO 4;MOVE(X-6),4 320 PLOT5,X,0;?N=?N:4;PLOT1,6,4;?N=?N:4;WAIT 330 PLOT7,X,0;?N=?N:4;PLOT3,(-6),4;?N=?N:4 340 NEXT;MOVE X,0;PLOT 3,0,3 350 !O=#8080;P."ANOTHER CRATER " 360 IF ABSV<100 G.e 370 !O=#80C0;P."WHERE WAS THE PILOT ?";G.e 400d !O=#8080;S=ABS(H*V) 410 IF S<300 P."SMOOTH - -" 420 IF S>299 P."BUMPY ! ! " 430 !O=#80C0;@=0;X=ABS(X-32) 440 IF X>1 P."BUT "X" KM FROM BASE" 450 IF X>5 P." walk" 460 IF X>1 OR S>200 G.e 470 P."HELLO BUCK ROGERS " 499e ?#E1=#80;GOTO 514
A small machine language routine (line 30) is used to scan the keyboard and put the number of any key pressed into RAM location 80. Lines 100-190 set up the constants J-O which are used for speed in the main program loop, the starting values and position, and prepare the screen. Note lines 160-190 (and 280) which move the print cursor by storing a four-byte word in locations #DE-E1.
The main body of the program is lines 200 to 290 which continually plot the latest position of your craft (lines 210, 220), scan the keyboard and adjust the velocities and fuel level accordingly (lines 230-260) and update your position (line 270). Every five iterations, line 280 updates the instrument readings.
When you have touched ground, lines 300-370 draw an explosion and make suitable comments if you landed too fast. If you have survived, lines 400-499 pass comment on your prowess as a pilot.
Text; ½K
VDU.; ½K
Integer
A simple demonstration of a moving display) this program shows a ball bouncing endlessly between the walls of an enclosure. Use ESC to stop the program.
1 REM BOUNCING BALL 10 CLEAR 0;X=1;Y=24;H=-1;V=1 20 MOVE 0,0 30 PLOT 1,63,0;PLOT 1,0,47 40 PLOT 1,-63,0;PLOT 1,0,-47 50aWAIT;IF X=1 OR X=62 WAIT;H=-H 60 WAIT;IF Y=1 OR Y=46 WAIT;V=-V 70 WAIT;PLOT 15,X,Y 80 WAIT;X=X+H;Y=Y+V 90 WAIT;PLOT 13,X,Y;GOTO a
Line 10 sets up the 48 x 64 graphics mode and the starting position (X,Y) and velocity (H,V) of the ball. Lines 25-40 then DRAW the four walls.
The main body of the program is the loop covering lines 50-90. Lines 50 and 60 reverse the direction of travel if the ball touches one of the walls; line 70 deletes the old image of the ball from the screen, and lines 80 and 90 calculate the new position and plot it.
Text; ½K
VDU; ½K
Integer
Patchwork displays a very long sequence of 'kaleidoscope' patterns. Other sequences may be obtained by changing line 140.
10 REM PATCHWORK 100 CLEAR 0 110 FOR A=1 TO 100 120 FOR B=1 TO 31 130 FOR C=0 TO 31 140 E=(C*5/(B+A+1)+B)%2*2+13 145 D=B+C 146 F=B*23/31;G=D*23/31;H=63-D;I=63-B;J=47-F;K=47-G 150 WAIT;PLOT E,D,F 160 PLOT E,H,F 170 WAIT;PLOT E,D,J 180 PLOT E,H,J 190 WAIT;PLOT E,B,G 200 PLOT E,I,G 210 WAIT;PLOT E,B,K 220 PLOT E,I,K 230 NEXT;NEXT;NEXT;END
Text; 1K
VDU; 1K
Integer
Another simple moving display program, Bug race shows two specks skittering down a racetrack. The program stops when one bug reaches the end of the course - then after a short pause it runs another race.
1 CLEAR 0 3 INPUT"HIT RETURN TO START BUGRACE"$TOP 5 CLEAR 1;A=0;B=15;C=0;D=47 10 DO WAIT 20 PLOT 15,A,B;PLOT 15,C,D 30 A=A+ABSRND%2;B=B+RND%3 40 C=C+ABSRND%2;D=D+RND%3 50 IF B<1 B=1 55 IF B>30 B=30 60 IF D<33 D=33 65 IF D>62 D=62 70 WAIT 80 PLOT 13,A,B;PLOT 13,C,D 90 UNTIL (A=127) OR (C=127) 100 FOR X=1 TO 100;WAIT;NEXT X 110 GOTO 1
Line 5 sets up the 64 x 128 graphics mode and the starting points (A,B for the first bug, C,D for the second).
The main body of the program is the loop through lines 10-90. Line 20 erases the previous images; line 80 plots the new positions of the racers. The WAIT statements in lines 10 and 70 ensure that the VDU RAM is only accessed during the display blanking periods (and also slow the competitors down to a decent pace). Lines 30,40 calculate the new positions, and lines 50-65 make sure that the racers do not stray out of their lanes.
Text; 2K
VDU; 1K
Integer
You are engaged in a fast moving battle against alien spaceships that must be zapped before they can destroy you and go on to conquer Cambridge. Before the fight started, you had a chance to choose the number of enemy ships and the general level of skill needed to survive. Now' the battle is under way, the screen shows you the relative position of the nearest alien. To kill him you just have to steer your ship until his image comes within the inner aiming rectangle on your screen, then press the firing key. But be quick about it - he is liable to shoot back. New recruits to the Atomic Space Service are advised to gain experience in fights at skill level 1 before tackling trickier opponents.
1 REM SPACE BATTLE - BY T. MABBS 10 P.$12"*** SPACE BATTLE ***"'' 15 P."KEY 'B' TO GO RIGHT"' 20 P." 'C' LEFT"' 25 P." 'D' DOWN"' 30 P." 'E' UP"' 35 P." 'F' TO FIRE"'' 50 INPUT"NUMBER OF ALIEN SHIPS (1-20)"A;IF A<1 OR A>20 GOTO 50 60 INPUT"LEVEL OF SKILL (1-6)"L;IF L<1 OR L>6 GOTO 60 70 O=56+L;P=72-L;Q=24+L;R=40-L;U=1;V=1;S=0 80 P."PRESS ANY KEY TO START";LINK #FFE3 100 GOSUB d 200e PLOT 14,X,Y;F=X;G=Y;GOSUB b 210 IF ABSRND%100<L GOSUB 500 220 IF ?#80=0 GOSUB 300 230 IF ?#81=0 Y=Y-3 250 IF ?#82=0 Y=Y+3 260 IF ?#83=0 X=X+3 270 IF ?#84=0 X=X-3 280 X=(X+U)&127;Y=(Y+V)&63 290 PLOT 14,F,G;GOTO e 300 S=S+1;FOR C=1 TO 6;?#B002=?#B002:4;NEXT 320 MOVE 32,0;PLOT 6,64,32;PLOT 6,96,0 330 MOVE 32,0;PLOT 6,64,32;PLOT 6,96,0 340 IF X>O IF X<P IF Y>Q IF Y<R GOTO 400 350 RETURN 400 MOVE (X-3),(Y-3);PLOT 5,(X+3),(Y+3) 410 MOVE (X+3),(Y-3);PLOT 5,(X-3),(Y+3) 420 FOR C=1 TO 90;?#B002=?#B002&RND:4;NEXT 430 A=A-1;IF A=0 GOTO 1000
440 GOSUB d;PLOT 14,X,Y;RETURN 500 MOVE X,Y;C=64+RND%8;D=32+RND%5;PLOT 6,C,D 510 Z=#B002;FOR K=1 TO 8;?Z=?Z:4;N. 520 MOVE X,Y;PLOT 6,C,D 530 U=-U;IF RND%2=0 V=-V 540 IF C<>64 OR D<>32 RETURN 560 @=0;P.$12"BAD LUCK!"'"YOU WERE HIT BY ENEMY FIRE"' 570 P."AND YOUR SHIELDS FAILED."'"YOU USED "S" SHOTS"' 580 P."BUT "A" ALIEN REMAINED"';GOTO 1100 800dX=ABSRND%128;Y=ABSRND%64;F=X;G=Y 810aCLEAR 1;MOVE 64,0;DRAW 64,Q;MOVE 64,R;DRAW 64,64 820 MOVE 0,32;DRAW O,32;MOVE P,32;DRAW 128,32 830 MOVE O,Q;DRAW O,R;DRAW P,R;DRAW P,Q;DRAW O,Q 840 MOVE 32,16;DRAW 32,48;DRAW96,48;DRAW 96,16;DRAW 32,16;R. 900bFOR B=1 TO 5;?#B000=?#B000&#F0+B 910 B?#7F=?#B001&8;NEXT;RETURN 1000 P.$12"WELL DONE!!"'"YOU DESTOYED THE ENEMY"' 1010 @=0;P."WITH "S" SHOT";IF S>1 P."S" 1100 P.'';INPUT"AGAIN "$TOP;IF ?TOP=CH"Y" RUN 1110 END
Lines 10-80 display the instructions at the start of the game, get the number of aliens (A) and skill level (L), then calculate the size of the aiming window (O, P, Q, R). U and V are the horizontal and vertical velocities of the alien ship, S is the number of shots fired.
The main body of the program is the loop through lines 200-280, which plots the latest position of the alien ship (line 200), then scans the keyboard (subroutine b) and acts accordingly.
Line 2l0 sometimes calls the subroutine at line 500 to give the enemy a chance to fire at you or change direction.
Lines 300-350 are the 'your shot' subroutine; line 300 makes a suitable noise, line 320 draws the shot lines and line 330 erases them. If the alien ship was within the aiming rectangle the program jumps to line 400 to draw a brief explosion with sound effects provided by line 420. If you have destroyed all of the enemy ships the program then goes to line 1000, otherwise line 440 draws a new screen with the next alien.
Lines 500-580 are executed when the alien fires at you. Lines 500 and 520 show the enemy fire and make a suitably frightening noise, line 530 changes his direction of travel. If you have suffered a direct hit (C=64, D=32) then the game ends via lines 560 to 580.
Lines 900-910 scan the keys B-F by direct manipulation of the I/O ports at B000 and B001, and put a '1' in one or the RAM locations 80-84 if the corresponding key was pressed.
Text; 2K
VDU; ½K
Integer
Hammurabi was possibly the first 'world simulation' computer game to be written. You play the part of Hammurabi; King of ancient Sumaria. Each year your faithful servant - Atom - tells you how big your kingdom is, how many subjects you have, and how much grain is left from the harvest and from previous years. You then have to decide whether to trade land for grain with neighbouring kingdoms, how much to allocate as food for the coming year, and how much grain is to be used as seed.
Your subjects will die of starvation if you don't allocate enough food for the coming year (about 15 bushels each), but if you give them too much the surplus is wasted. Each year's harvest depends on the amount of seed used, but planting more than two bushels per acre is wasteful as is allocating more than 25 bushels of seed to each of your subjects. The harvest is also subject to a large random factor (the weather). Rats can devastate your grain stores, and your kingdom is subject to plagues about every seventh year.
10 REM HAMMURABI 20 H=100;S=3000;A=1000;Y=0;@=0;P.$12 100 P.'"O HAMMURABI, KING OF SUMARIA,"' 120 P."YOUR SUBJECTS NOW NUMBER "H","' 130 P."YOUR KINGDOM COVERS "A" ACRES,"' 140 P."YOU HAVE "S" BUSHELS OF GRAIN."'' 200 L=20+RND%5;P."LAND IS "L" BUSHELS PER ACRE,"'
210 INPUT"HOW MANY ACRES DO YOU BUY "E;IF E*L>S GOSUB a;G.210 220 IF E>0 GOTO 260 230 GOSUB a 240 INPUT"HOW MANY ACRES DO YOU SELL"E;E=-E 250 IF (-E)>A GOSUB a;GOTO 240 260 A=A+E;S=S-L*E 270 INPUT"HOW MANY BUSHELS FOR FOOD "F;IF F>S GOSUB a;GOTO 270 280 S=S-F 290 INPUT"HOW MANY BUSHELS FOR SEED "P;IF P>S GOSUBa;GOTO290 300 S=S-P;IF P>2*A P=2*A 310 IF P>25*H P=25*H 320 R=ABSRND%(1+S/2);C=P/4+ABSRND%(1+P*4);S=S+C-R;D=H-F/15 330 D=H-F/15;IF D<1 D=0 340 H=H-D;N=H/20+ABSRND%(1+H/20);H=H+N 350 Z=0;IF RND%4=3 Z=H/3+RND%(1+H/4) 360 H=H-Z;Y=Y+1 400 P.$12;FOR I=1 TO 50;WAIT;NEXT I 410 P."O KING,I BEG TO REPORT THAT"' 420 P."IN YEAR "Y" OF YOUR REIGN"' 430 P."YOU HARVESTED "C" BUSHELS"' 440 IF R>0 P."BUT RATS ATE "R" BUSHELS"' 450 P.D" PEOPLE STARVED, "N" WERE BORN"' 480 IF Z>0 P.Z" DIED OF PLAGUE"' 490 IF H>0 GOTO 100 500 P.''"AS YOU HAVE NO SUBJECTS LEFT,"' 510 P."THIS IS THE END OF YOUR REIGN"'';END 1000aP.$11$13" "$13$11;R.
Line 20 sets up the initial values of H (population), S (grain in store), A (acres of land) and Y (year).
The main body of the program is lines 100 to 490, which are executed once for each year of your reign. Lines 100-140 report on the extent of your kingdom, lines 200-290 then ask for your decisions about the amounts of grain to be used for food and seed, each answer being quietly checked for validity and diplomatically ignored if you ask for the impossible (subroutine a being used to delete an erroneous entry from the screen and re-position the cursor; note that there should be exactly 32 spaces, between the quotation marks in line 1000). Lines 300-360 calculate the results for the year, in terms of R (bushels of grain eaten by rats), 0 (deaths from starvation), Z (deaths from plague) and N (births). If you have any subjects left after another year of misrule, the program then loops back to line 100.
Text; 1K
VDU; ½K
Integer
Higher/Lower is played by one person against the computer. For each play the computer picks two numbers between 1 and 99, displays the first, then asks the player to bet on whether the second number is higher or lower than the first. Starting with a stake of £100, a really successful player can break the bank by amassing £10,000 or more. The game will also end if the player has no money left.
10 REM HIGHER/LOWER 20 @=0;P=100 100 M=1+ABSRND%99;N=ABSRND%100;IF N=M GOTO 100 110 P.$12"I HAVE CHOSEN TWO NUMBERS (0-99)"' 120 P."THE FIRST IS "M''"IS THE SECOND NUMBER"' 130 INPUT"HIGHER (H) OR LOWER (L) "$TOP 140 IF CH$TOP<>CH"H" AND CH$TOP<>CH"L" GOTO 130 150 P."YOU HAVE GOT "P" POUNDS,"' 160 INPUT"HOW MUCH DO YOU BET "B;IF B>P OR B<0 GOTO 160 200 P=P+B 210 IF CH$TOP=CH"H" AND N<M P=P-2*B 220 IF CH$TOP=CH"L" AND N>M P=P-2*B 230 P.'"IT WAS "N'"YOU NOW HAVE "P" POUNDS"'' 240 IF P=0 P."*SORRY & GODBYE*"';END 250 IF P>9999 P."CONGRATULATIONS - YOU'VE BROKEN THE BANK"';END 300 INPUT"ANOTHER BET (Y/N) "$TOP;IF CH$TOP=CH"Y" GOTO 100 310 END
Text; 1K
VDU; ½K
Integer
An aid for the busy executive, Buzz-Word generates impressive sounding phrases for use in reports to higher management.
10 PRINT$12"*** BUZZ-WORDS ***"'' 20 DIM A(10);N=5;D=#D 100 X=?18*256 110 PRINT'"YOUR PHRASE IS;"'' 120 Y=CH"a";GOSUB 500 130 Y=CH"b";GOSUB 500 140 Y=CH"c";GOSUB 500 150 PRINT''"ANOTHER " 160 INPUT $A 170 IF ?A=CH"Y" GOTO 100 180 END 500 DO DO X=X+1;U.?X=D;U.X?3=Y 510 X=X+3;Y=CH"*" 520 FOR P=1 TO 1+ABSRND%N 530 DO X=X+1;IF ?X=D X=X+3 540 UNTIL ?X=Y 550 NEXT P 600 DO X=X+1;PRINT $?X 610 UNTIL X?1=Y OR X?1=D 620 PRINT" ";RETURN 1000a*GLOBAL*PARALLEL*FEASIBLE 1010 *LATERAL*STRUCTURED 1100b*TOP-DOWN*INTEGRATED 1110 *SILICON*PRAGMATIC*MODULAR 1200c*CONCEPT*SCENARIO 1210 *PROJECTION*EVENT*PHASE
3 lists, each containing 5 words, are stored at the end of the program listing. Each list starts with a label (a, b or c), each word or phrase starts with a *. The program displays one word or phrase - chosen at random - from each list.
Text; 3K
VDU; ½K
Integer
Othello is played between the computer (C) and its human opponent (H) on an 8 x 8 board. At the start of the game, each player has two pieces in the centre of the board.
H and C take turns to place a new piece in one of the vacant squares so as to 'capture' one or more opponent's pieces. Pieces are captured if they lie on a horizontal, vertical or diagonal line terminated at one end by the piece just placed, and at the other end by an existing piece belonging to the player making the move. Pieces captured change type to that of the player capturing them.
Each move must capture at least one piece, or else the player forfeits that move. The game ends when all 64 squares have been filled or when neither player can move. The winner is then the player with the most pieces.
The program displays the current scores and the state of the board after each move. The human player should enter his move as the row (1-8) and column (A-H) of the selected square (e.g. 8A), or he may forfeit his move by just pressing the Return key. The program will not accept invalid moves.
The algorithm used to calculate the computer's move is a fairly simple one, which allows the human player a reasonable chance of winning.
10 REM OTHELLO 100 M=1;H=8;C=3;DIM A(99),NN(7),B(9) 110 NN(0)=11;NN(1)=10;NN(2)=9;NN(3)=1 120 NN(4)=-1;NN(5)=-9;NN(6)=-10;NN(7)=-11 130 P.$12;?#E1=0;P." A B C D E F G H"'
140 @=7;FOR I=1 TO 8;P.I" * * * * * * * *"';NEXT 150 FOR I=0 TO 99;A?I=0;NEXT 160 T=C;P=44;GOSUB a;P=55;GOSUB a 170 T=H;P=45;GOSUB a;P=54;GOSUB a 200 REM YOUR MOVE 210 GOSUB b;IF ($B="" AND M=0) OR Y+Z=64 GOTO 900 230 INPUT"YOUR TURN (E.G. 3D) "$B;IF $B="" GOTO 300 240 IF ?B<CH"1" OR ?B>CH"8" OR B?1<CH"A" OR B?1>CH"H" GOTO 260 250 P=(?B-CH"0")*10+B?1-CH"A"+1;T=H;F=0;GOSUB c;IF S>0 GOTO 270 260 P.$11;GOSUB g;GOTO 230 270 F=1;GOSUB c 300 REM COMPUTER'S MOVE 310 GOSUB b;IF ($B="" AND M=0) OR Y+Z=64 GOTO 900 320 M=0;D=0;F=0;T=C;P."LET ME THINK ...." 330 FOR U=1 TO 8;FOR V=1 TO 8;P=U+10*V;GOSUB c;IF S=0 GOTO 365 340 IF U=1 OR V=8 S=S*2 345 IF V=1 OR V=8 S=S*2 350 IF U=2 OR U=7 OR V=2 OR V=7 S=S/2 355 IF S=D D=D-ABSRND%2 360 IF S>D D=S;M=P 365 NEXT V;NEXT U 370 GOSUB g;IF M>0 F=1;P=M;GOSUB c 380 IF M=0 P."I CNA'T MOVE";FOR I=1 TO 25;WAIT;NEXT 390 GOTO 200 900 REM WRAP IT UP 910 IF Y>Z P."YOU WON - CONGRATULATIONS"' 920 IF Y=Z P."** A DRAW **"' 930 IF Y<Z P."I WON - OF COURSE"' 940 ?#E1=#80;END 1000a REM PLACE PIECE 1010 X=2*(P%10)+32*(P/10);X?#8006=128+X?#8006 1020 FOR I=1 TO 30;WAIT;NEXT 1030 A?P=T;X?#8006=T;RETURN 2000b REM ADD SCORES 2010 Y=0;Z=0 2020 FOR I=11 TO 88 2030 IF A?I=H Y=Y+1 2040 IF A?I=C Z=Z+1 2050 NEXT 2060 P.$30;FOR I=1 TO 10;P.$10;NEXT 2070 FOR I=1 TO 3;GOSUB g;P.$10;NEXT 2080 FOR I=1 TO 3;P.$11;NEXT 2090 @=0;P."YOU HAVE "Y", I HAVE "Z'';RETURN 3000c REM EXAMINE POSITION & MOVE IF F=1 3010 R=P;S=0;IF A?P<>0 RETURN 3015 IF F=1 GOSUB a 3020 FOR J=0 TO 7;Q=R;P=R;K=0
3030d Q=Q+NN(J);IF A?Q=0 GOTO f 3040 IF A?Q=T GOTO e 3050 K=K+1;GOTO d 3060e S=S+K;IF F=0 OR K<1 GOTO f 3070 FOR L=1 TO K;P=P+NN(J);GOSUB a;NEXT 3080f NEXT J;RETURN 4000g REM CLEAR LINE 4010 P.$13" "$11;RETURN
There should be exactly 32 spaces between the quotation marks in line 4010.
By cutting out the REM statements and abbreviating wherever possible, Othello can be made to run in 2K of text RAM.
The 10 x 10 byte array A(99) is used to hold the current state of the board; each byte being either 0 (free square), H or C. A 10 x 10 array is used because by considering it to represent the 8 x 8 board plus an empty surrounding border no special treatment is needed for squares on the edge of the playing board when looking for possible moves. The variable P is used to represent the position being examined, and the array NN holds the 8 possible movements from P.
Lines 100-170 set the starting values and DRAW the board at the start of play.
Lines 200-270 get your move, check that it is valid, then update the displayed board image and the array A().
The computer calculates its best move in lines 300-390 by examining every possible position, then choosing that with the highest score S. Line 355 introduces a random element if two positions have equal scores. The algorithm used does not do any form of 'look-ahead' but just sums the number of enemy pieces that could be captured, then increases the score if the square being examined is on the edge of the board, or decreases the score if it is just one row or column away from the edge.
Text; ½K
VDU; ½K
Integer
In this simple game, the computer picks a random number from 1 to 9, the player then has 5 chances to guess it. Unless the player has considerable ESP talent, he should only be able to win about half of the games played.
10 REM NUMBER GUESSING A 20 N=1+ABS(RND%9);@=0 30 PRINT $12,"I AM THINKING OF"' 40 PRINT "A NUMBER FROM 1 TO 9"' 50 PRINT"YOU HAVE 5 GUESSES"'' 100 FOR G=1 TO 5;INPUT X 110 IF X=N THEN GOTO 200 120 PRINT $11,X," IS WRONG"' 130 NEXT G 140 PRINT'"IT WAS "N';END 200 PRINT $7;WAIT;PRINT $7 210 PRINT'"*** CORRECT ***"';END
Text; ½K
VDU; ½K
Integer
This number guessing game gives the player 7 chances to guess a number from 1 to 99, but tells the player whether each guess was too high or too-low - which is enough information to allow the correct number to be deduced in every game.
10 REM NUMBER GUESSING B 20 N=1+ABS(RND%99);@=0 30 PRINT $12,"I AM THINKING OF "' 40 PRINT "A NUMBER FROM 1 TO 99"' 50 PRINT "YOU HAVE 7 GUESSES."'' 100 FOR G=1 TO 7 110 INPUT X;IF X=N THEN GOTO 200 120 IF X<N THEN PRINT $11,X," IS TOO SMALL"' 130 IF X>N THEN PRINT $11,X," IS TOO BIG"' 140 NEXT G 150 PRINT'"IT WAS ",N';END 200 PRINT $7;WAIT;PRINT $7 210 PRINT'"*** CORRECT ***"';END
Line 20 chooses the number (N) and sets the print field width to zero for a neater display.
The PRINT $11 statements in lines 120 and 130 move the cursor back one line so that the comment 'IS TOO SMALL' or 'IS TOO BIG' appears on the same line as the entered value.
Line 200 generates the sound of success.
Text; 3K
VDU; 1/2K
Integer
Hexpawn is a simple game played between the computer (C) and its human opponent (H) on a 3 x 3 board. It is interesting to the computer programmer as it has the right level of complexity to useful for experiments in computer 'learning' techniques. In the program given here, the computer remembers each board position (or pattern) that it encounters, and over the course of many games it learns the best move to make from each position. Given enough practice it can become very good.
As the player will soon notice, the program does not attempt to work out the best move to make from any new position, but just selects the first legal move that it can find. However, if that move results in the computer losing, then it will not play the move again if confronted by the same position in another game.
At the start of each game each player has three pieces; the computer's being along the top row of the board, the human player's being along the bottom row. The pieces are similar to chess pawns and may be moved straightforward to an empty square, or may be moved diagonally forward to take an opponent's piece. A player loses when he cannot move any of his pieces. The program assumes that its opponent knows how to play properly, and the computer will surrender if it finds itself in a position that it has learnt will always lead to defeat.
At the end of each game the computer will ask if you want to another. Note that if the program is actually stopped at any time by ESC, BREAK or by refusing the invitation to play another game, then re-starting it by typing RUN will make the computer forget all it has learned. Type GOTO 100 to avoid this.
10 REM HEXPAWN 20 DIM A(8),S(200),I(10);C=1;H=2 30 FOR L=0 TO 200;S?L=0;NEXT L 100 FOR R=1 TO 54321;P.$12;?#E1=0 110 A?0=C;A?1=0;A?2=H;A?3=C;A?4=0;A?5=H;A?6=C;A?7=0;A?8=H 120 P." C C C 1 4 7"'' 130 P." * * * 2 5 8"'' 140 P." H H H 3 6 9"''''
200 REM YOUR MOVE 210 T=H;FOR M=10 TO 87 220 IF M%10<9 GOSUB b;IF E=0 GOTO 240 230 NEXT M;GOTO 800 240 GOSUB a;INPUT"YOUR MOVE (FROM TO) "$I 250 IF ?I<CH"1" OR ?I>CH"9" GOTO 240 260 IF I?1<CH"1" OR I?1>CH"9" GOTO 240 270 M=(?I-CH"1")*10+I?1-CH"1" 280 GOSUB b;IF E>0 GOTO 240 290 GOSUB c 300 REM COMPUTERS MOVE; FIRST LOOK THROUGH S() 310 GOSUB a;T=C;U=0;P."MY MOVE ..."' 320 X=A?0+4*(A?1)+16*(A?2)+64 330 Y=A?3+4*(A?4)+16*(A?5)+64 340 Z=A?6+4*(A?7)+16*(A?8)+64 350 V=S 355e IF ?V>128 GOTO f 360 IF ?V=0 GOTO 400 370 IF ?V=X IF V?1=Y IF V?2=Z GOTO 500 380 IF ?V=Z IF V?1=Y IF V?2=X U=1;GOTO 500 385 V=V+2 390f IF V<S+200 V=V+1;GOTO e 395 P.'''"S() TOO SMALL";END 400 REM ADD NEW ENTRY TO S() 410 ?V=X;V?1=Y;V?2=Z;W=V+3;?W=0 420 FOR M=1 TO 78;IF M%10<9 GOSUB b 430 IF E=0 W?0=M+128;W?1=0;W=W+1 440 NEXT M 500 REM SELECT MOVE IF POSSIBLE 510 V=V+3;IF ?V<128 GOTO 700 520 M=?V-128; IF U=0 GOTO 600 530 IF M/10<3 M=M+60 540 IF M/10>5 M=M-60 550 IF M%10<3 M=M+6 560 IF M%10>5 M=M-6 600 REM DO COMPUTER'S MOVE 610 GOSUB c;L=V;GOTO 200 700 REM DELETE LOSING MOVE & QUIT 710 FOR V=L TO S+199;?V=V?1;NEXT V 720 P.'"OK - YOU WIN"'';GOTO 900 800 P."YOU CAN'T MOVE - I WIN"'' 900 INPUT"ANOTHER GAME "$I;IF ?I=CH"N" THEN ?#E1=#80;END 910 NEXT R 1000a REM CLEAR LINE 1010 P.$11" "$11;RETURN 2000 REM CHECK MOVE, E=0 IF OK 2010b E=1;F=M/10;G=M%10;IF A?F<>T OR A?G=T RETURN 2020 IF A?G>0 GOTO g
2030 IF G=F-2*T+3 IF G/3=F/3 E=0 2040 RETURN 2050g IF G-F=4*T-6 IF G/3<>F/3 E=0;RETURN 2060 IF G-F=12-8*T IF F<>2 IF F<>6 E=0 2070 RETURN 3000 REM MOVE PIECE 3010c P=M/10;GOSUB d;?P=#2A 3020 P=M%10;GOSUB d;?P=5*T-2 3030 A?(M/10)=0;A?(M%10)=T;RETURN 3100d P=#8008+P/3*2+P%3*64 3110 ?P=?P+#80 3120 FOR K=1 TO 30;WAIT;NEXT K;RETURN
There should be exactly 32 spaces between the quotation marks in line 1010.
The current state of the board is held in the 9 byte vector A(), each byte being 0 (empty square), 1 (computer's piece) or 2 (human player's piece).
The 201-byte vector S() is used to hold previously encountered board positions and the possible moves which did not lead to disaster. Each board position is represented by three bytes, which give the states of the three columns of the board, each coded to have a value of 64 to 127 (as X, Y & Z in lines 320-340). These are followed by single byte representations of the possible moves (if any) from that position coded as values from 128 to 255 (see lines 430 & 520). The end of the list is signalled by a zero byte. When the computer finds itself in a losing position, it removes the move that lead to defeat from the list (line 710).
The learning process is simplified by allowing the computer to recognise 'reflections' of board positions - thus when searching the list to see if it has played from that position before line 380 sets U=1 if it finds the mirror image position, and lines 520 to 560 subsequently invert the move selected.
When a new position is encountered, it is added to the list by line 410, then the program examines all possible from that position and adds legal ones to the list (lines 420-440).
Text; 1K
VDU; ½K
Integer
Drive is a game in which you have to steer a rapidly moving object through a course that is gradually filled with white and grey squares. The grey squares represent the enemy targets; if you hit one it is destroyed and you gain a point. The white squares, however, are dangerous if you hit one it will explode, killing you and scattering potentially lethal debris. You can survive 3 'deaths' before the game ends - and gain an extra 'life' for every 10 grey blocks hit.
The REPT and SHIFT keys are used for steering, moving you up and down the screen respectively. When the game ends (because you have run out of 'lives') press the space bar to play another. While the game is in progress three numbers across the top of the screen show (from left to right) your current score of grey blocks zapped, the number of lives you have left, and the best score to date in previous games.
1 REM- DRIVE 18-11-80 2 REM- BY D. DINI 4 G=0 5 A=0;N=#8000;Z=32;M=3 10 CLEAR 0
15 DIM H(5);!H=#4081020;H!4=#102 20 MOVE 0,2;DRAW 64,2;MOVE 0,42;DRAW 64,42 25 PRINT $30,A,M,G 30 Y=24;O=0;U=24 40 FOR X=0 TO 63 50 GOSUB p 60 IF Q=0 THEN GOTO c 70 IF ?P=#FF THEN ?P=#40;A=A+1;IF A%10=0 THEN M=M+1 72 IF ?P=#40 THEN GOTO c 75 GOTO e 80cIF RND%5<>0 THEN GOTO j 82 L=ABSRND%13+2 85 S=N+L*Z+ABSRND%22+8 88 IF (15-L)=Y/3 THEN GOTO j 90 ?S=#FF;IF ABSRND%2=0 THEN ?S=#7F 100jPLOT 15,O,U;PLOT 13,X,Y;O=X;U=Y 102 IF ?#B001P=0THEN Y=Y-1 104 IF ?#B002(=0 THEN Y=Y+1 110 NEXT 120 PLOT 15,O,U 130 PRINT $30,A,M,G 999 GOTO 30 1000pP=X/2+(47-Y)/3*Z+N 1010 Q=(?P&(H?(X&1+(47-Y)%3*2))<>0) 1020 RETURN 2000eMOVE X,Y;PLOT 0,-3,0;PLOT 2,6,0;PLOT 0,-3,3;PLOT 2,0,-6 2010 PLOT 0,3,0;PLOT 2,-6,6;PLOT 0,6,0;PLOT 2,-6,-6 2011 M=M-1;IF M<>0 THEN X=64;N.;G.25 2015 IF A>G THEN G=A 2020 PRINT $30,A,M,G 2040 LINK #FFE3 2045 X=64;NEXT 2050 GOTO 5
Abbreviations have been used wherever possible to fit the program into 1K text RAM.
Line 20 draws the top and bottom boundaries of the course.
The main body of the program is within the loop between lines 30 and 999. An inner loop (lines 40-110) moves the object across the screen, using subroutine p to check for collision with a white square, and line 70 to see if you have destroyed a grey one. The program branches to see if you are killed; to PLOT the debris from the explosion and to see if you have any lives left. If you are still alive, line 100 plots your new position, and lines 102,104 test the state of the SHIFT and REPT keys.
Text; 2K
VDU; ½K
Integer
This program plots graphs of your physical (P), emotional (E) and intellectual (I) cycles for a four-week period.
As well as showing the ups and downs of your biological cycles, the graphs also warn of those critical days when a cycle is crossing through the centre line. For a finale, the program calculates how many days you have lived.
100 P.$12"* ATOMIC BIORYTHM CALCULATER *" 110 P.''"ENTER YOUR DATE OF BIRTH"'' 120 E=0;GOSUB 500;E=-E 130 P.'"NOW ENTER TODAY'S DATE"'' 150 GOSUB 500;E=E-14 200 P.$12;FOR I=1 TO 6;P.';NEXT;P." " 210 FOR I=1 TO 4;P."!......";NEXT;P."!"' 220 FOR I=1 TO 7;P.';NEXT 230 P." PREV 2 WKS TODAY NEXT 2 WKS"' 250 FOR I=0 TO 12;X=32*I+#800F;?X=#21;NEXT 300 P=#10;C=23;GOSUB 600 310 P=#5;C=28;GOSUB 600 320 P=#9;C=33;GOSUB 600 400 @=0;P." YOU ARE "E+14" DAYS OLD" 410 END 500 REM GET # OF DAYS 510 INPUT"YEAR "Y,"MONTH (1-12) "M,"DAY (1-31) "D 515 E=E+D 520 IF M>1 E=E+31;IF M>2 E=E+28 525 IF M>3 E=E+31;IF M>4 E=E+30 530 IF M>5 E=E+31;IF M>6 E=E+30 535 IF M>7 E=E+31;IF M>8 E=E+31 540 IF M>9 E=E+30;IF M>10 E=E+31 545 IF M>11 E=E+30 550 IF M>2 IF Y%4=0 IF Y%100<>0 E=E+1 560 Y=Y-1800 570 FOR I=0 TO Y-1;E=E+365 580 IF I%4=0 IF I%100<>0 E=E+1 590 NEXT;RETURN 600 REM PLOT A CURVE 610 FOR I=0 TO 28 620 X=%(6.5*SIN(2*PI*(E+I)/C)) 630 X=#80C1-32*X+I;?X=P 640 NEXT;RETURN
The program is based on the assumption that your cycles follow sine-wave patterns with periods of 23, 28 and 33 days, starting from your date of birth.
Text; 2K
VDU; ½K
Integer
And now to prove that the computer has an educational value. Sums Tester provides an exercise in simple mental arithmetic by posing 10 questions to be answered in 60 seconds. The questions involve simple addition and subtraction of numbers from 1 to 99 (no negative answers), and multiplication and division using factors up to 12, and are chosen at random by the program.
If you don't finish within the time allowed, the test ends; in any case your score and the total time taken to answer are shown at the end of the test.
10 REM SUMS TESTER 100 DIM B(8),I(-1);S=0;T=60 110 GOSUB a;!#80=-(T*60) 120 $B="GOTO 700";?16=B;?17=B/256 130 P.$12"YOU HAVE 10 QUESTIONS"' 140 @=0;P."TO ANSWER IN "T" SECONDS"'' 200 FOR Q=1 TO 10;P."QUESTION "Q" IS ;"'' 300 GOSUB (1000+ABSRND%4*100) 400 INPUT $I;IF $I="" P.$7;GOTO 400 410 Z=0 420 FOR P=0 TO LEN(I)-1 430 IF I?P<CH"0" OR I?P>CH"9" P.$7;GOTO 400 440 Z=I?P-CH"0"+10*Z 450 NEXT P 500 IF Z=R P.'"THAT'S RIGHT !";S=S+1;GOTO 520 510 P.'"SORRY, BUT IT WOULD BE "R 520 FOR A=1 TO 60;WAIT;NEXT 530 P.$12;@=0 540 NEXT Q
600 P."YOUR SCORE WAS"'S" OUT OF 10"'' 610 E=T+(!#80)/60;P."IN "E" SECONDS"'' 620 IF S>8 P."CONGRATULATIONS ARE DUE"' 630 IF S*T/E>10 P."WELL DONE"' 640 ?#20A=?#A0;?#20B=?#A1;END 700 P.&7$12;@=0;P."* NO MORE TIME *"' 710 !#80=0;GOTO 600 1000 X=2+ABSRND%98;Y=2+ABSRND%98 1010 R=X+Y;P."WHAT IS "X" + "Y" ";RETURN 1100 X=2+ABSRND%98;Y=2+ABSRND%98 1110 IF Y+2>X GOTO 1100 1120 R=X-Y;P."WHAT IS "X" - "Y" ";RETURN 1200 X=2+ABSRND%11;X=2+ABSRND%11 1210 R=X*Y;P."WHAT IS "X" TIMES "Y" ";RETURN 1300 X=2+ABSRND%11;R=2+ABSRND%11 1310 Y=X*R;P."WHAT IS "Y" DEVIDED BY "X" ";RETURN 9000a P.$21;P=#84 9010[ PHP;CLD;STX #E4;STY #E5 9020 BIT #B002;BVC #94;JSR #21C;BCC #8A 9030 JSR #FB8A;JSR #21C;BCS #97;JMP #FEA7;] 9040 P=#21C 9050[ JSR #FE66;INC #80;BNE #228 9060 INC #81;BNE #228;BRK;JMP #FE71;] 9070 ?#A0=?#20A;?#A1=?#20B 9080 11/05/2019?#20A=#84;?#20B=0;P.$6;RETURN
The program loops between lines 200 and 540 ten times; each time line 300 decides whether the question is to involve addition, subtraction, multiplication or division, and calls one of the subroutines starting at lines 1000, 1100, 1200 and 1300.
Lines 9000-9080 are two machine language routines similar, to those in the 'Keyboard Timeout' program given elsewhere in this book, which increment a counter (locations #80,#81) every 1/60th of a second while the program is waiting for an answer. The counter is preset to (-T) seconds at the start of the program by line 110. If the counter times out (by reaching zero), the machine-language routine executes a BRK instruction which - because of line 120 - makes the program jump immediately to line 700.
Lines 400-450 get the answer to each question as a string and convert that to a number if possible. If the input cannot be a number then the program goes back to line 400 to ask again. This approach is used in preference to a simple 'INPUT Z' because it prevents the program crashing if the user gives a non-numeric response (such as just pressing the Return key), and it also stops him cheating by for example answering "WHAT IS 63+38" by "63+38".
Text; 2K
VDU; ½K
Integer
Scramble is a computer version of the old sliding letter square puzzle, in which you have to re-arrange 24 letters in a 5 x5 board by moving one letter at a time into the empty square.
When the program is run, it first shows you the board with the letters in order. It then scrambles them according to the degree of difficulty you have chosen for the game. You then have to restore the board to its original ordered form in less than 100,000 moves.
10 REM SCRAMBLE 100 REM SET UP BOARD 110 DIM DD(3),A(-1) 120 DD(0)=-32;DD(1)=-1;DD(2)=1;DD(3)=32 130 P.$12;X=#800D 140 FOR I=1 TO 24;?X=I;X=X+1 150 IF I%5=0 X=X+27 160 NEXT;?X=#20 200 REM INSTRUCTIONS 210 FOR I=1 TO 6;P.$10;NEXT 220 P."THIS PATTERN WILL BE SCRAMBLED."' 230 P."YOU HAVE TO PUT IT BACK IN ORDER" 240 P."BY MOVING ONE LETTER AT A TIME"' 250 P."INTO A BLANK SQUARE."' 260 P."YOU CAN ONLY MOVE A LETTER WHICH" 270 P."IS VERTICALLY OR HORIZONTALLY"' 280 P."NEXT TO THE BLANK SQUARE."'' 300 REM SCRAMBLE BOARD 310 INPUT"DIFFICULTY (1-9) "D 320 GOSUB a;P=0 330 FOR R=1 TO D*5 340 DO J=X+DD(ABSRND%4) 350 UNTIL ?J<25 AND J<>P 360 WAIT;?X=?J;?J=#20;P=X;X=J 370 NEXT R
400 REM GET MOVE 410 FOR M=1 TO 9999 420 DO P.$11"WHICH LETTER WILL YOU MOVE "$8$8 430 INPUT $A;B=?A-#40;P=0 440 FOR I=0 TO 3;IF X?DD(I)=B P=X+DD(I) 450 NEXT 460 UNTIL P>0 AND B>0 AND B<26 470 ?P=?P+#80 475 FOR I=1 TO 30;WAIT;NEXT 480 ?P=#20;?X=B+#80 485 FOR I=1 TO 30;WAIT;NEXT 490 ?X=B;X=P 500 REM GAME OVER ? 510 B=#800C 520 FOR I=1 TO 24;IF B?I<>I GOTO 600 530 IF I%5=0 B=B+27 540 NEXT I 550 GOSUB a;@=0 560 P."AT LAST; YOU MADE IT"' 570 P."IN "M" MOVES"' 580 END 600 NEXT M 900a REM CLEAR BOTTOM OF SCREEN 905 P.$30;B=#20202020 920 FOR I=#80A0 TO #81FC STEP 4;!I=B;NEXT 930 FOR I=1 TO 7;P.$10;NEXT;RETURN
The letters are stored directly in the appropriate VDU RAM locations, lines 130-160 set up the initial (ordered) board with the letters A-X and a blank position.
Lines 300-370 then 'scramble' the board by making 5xD moves (D being the degree of difficulty chosen for the game); the array DD(3) being used to hold the four possible movements from any position J. Line 350 checks that the computer does not attempt to move outside of the playing area, and that it does not attempt to move the same piece two times running when scrambling the board.
Lines 420-460 get your move and check that it is legal. Lines 470-490 then make your move on the screen, highlighting the positions you are moving between, then lines 500-540 see if you have put the board back into its correct order. If not, the program branches to line 600 and so back for your next move.
Lines 900-930 form a subroutine which is used to clear the bottom part of the screen and re-position the text cursor ready for the next move.
Text; 1k
VDU; 6K
Integer
Three short programs that use the highest resolution graphics mode to generate attractive moiré patterns each program can produce a number of different designs, a fresh one being drawn each time a key is pressed.
10 REM DESIGN #1 100 CLEAR 4;Z=6;S=2+ABSRND%4 110 A=127+RND%100;B=95+RND%75 120 FOR X=1 TO 255 STEP S 130 PLOT 4,X,0;PLOT Z,A,B;PLOT Z,(255-X),191 140 NEXT 150 FOR Y=1 TO 191 STEP S 160 PLOT 4,255,Y;PLOT Z,A,B;PLOT Z,0,(191-Y) 170 NEXT 180 LINK #FFE3;RUN
10 REM DESIGN #2 100 CLEAR 4;Z=6;S=1+ABSRND%4 110 FOR Y=0 TO 191 STEP S;MOVE 0,Y 120 PLOT Z,127,0;PLOT Z,255,Y;NEXT 125 S=1+ABSRND%4 130 S=1+ABSRND%4 140 FOR X=0 TO 127 STEP S;MOVE X,191 150 PLOT Z,127,0;PLOT Z,(255-X),191;NEXT 160 LINK #FFE3;RUN
10 REM DESIGN #3 100 CLEAR4;Z=6;S=1+ABSRND%15 110 FOR Y=0 TO 191 STEP S 120 MOVE 0,0;PLOT Z,255,Y 130 MOVE 255,0;PLOT Z,0,Y;NEXT 140 S=2+ABSRND%15 150 FOR X=0 TO ABSRND%5*32+127 STEP S 160 MOVE 0,0;PLOT Z,(255-X),191 170 MOVE 255,0;PLOT Z,X,191;NEXT 180 LINK #FFE3;RUN
Text; 4K
VDU ½K
Integer
This is a game for the brave and adventurous. You are hunting the dread Wampus, in the pitch-black depths of his cave kingdom, armed only with a bow and five arrows. Super strong bats also inhabit the caves, and though they will not harm you directly, they may make you lose the trail by carrying you off to another cave - and that might be the one with the bottomless pit! Good hunting, and don't run out of arrows.
1 REM WAMPUS. BY T.MABBS 5 P.$15 10 P.$12"hunt the wampus"''"YOU ARE IN A NETWORK OF 20 CAVES"' 20 P."THE WAMPUS IS IN ONE CAVE, YOU"' 30 P."HAVE 5 ARROWS TO SHOOT AT HIM,"' 35 P."YOU MAY THROUGH 1 OR 2"'"CAVES PER SHOT."'' 40 P."ALSO IN THE CAVES ARE A COLONY"' 45 P."OF SUPERBATS, AND A BOTTOMLESS PIT!!"'' 50 P."any key to continue";LINK #FFE3;P.$12 55 P."IF THE SUPERBATS GET YOU, THEY"' 60 P."TAKE YOU TO ANOTHER CAVE."'' 65 P."IF YOU FALL INTO A PIT, YOU LOSE"'' 70 P."IF YOU MEET THE WAMPUS, HE MAY"' 72 P."MOVE TO THE NEXT CAVE, OR HE"'"MAY EAT YOU."'' 75 P."any key to continue";LINK #FFE3;P.$12 77 P."""I SMELL THE WAMPUS"" MEANS THE"' 78 P."WAMPUS IS IN THE NEXT CAVE."'' 79 P."""I FEEL A DRAFT"" MEANS A"'"BOTTOMLESS PIT."'' 80 P."""I HEAR WINGFLAPS"" MEANS"'"SUPERBATS."'' 85 P."GOOD LUCK!!!!"''"press any key to start";LINK #FFE3 90 DIM AA(6),BB(20),Q(5);D=5 100 X=ABSRND%19+1;Y=ABSRND%19+1;Z=ABSRND%19+1;P.$12;@=0;F=5 105 IF X=Y OR X=Z X=ABSRND%19+1;G.105 106 IF Y=Z Y=ABSRND%19+1;G.106 110 W=ABSRND%19+1 120 FOR T=1 TO 32;P."-";N.;P."YOU ARE IN CAVE "W' 125 GOS.130;G.230
130 S=W-1;IF S=0 S=20 140 U=W+1;IF U=21 U=1 150 V=W+10;IF V>20 V=V-20 225 R. 230 P."YOU CAN MOVE INTO CAVES"'S", "U", OR "V' 231 P."SHOOT(1) OR MOVE(2)"' 235 ?#B000=2;IF ?#B001=#FD THEN T=1;G.250 240 ?#B000=1;IF ?#B001=#FD THEN T=2;G.250 245 G.235 250 IF T=1 P."shoot"';G.600 260 P."move"' 270 IN."MOVE TO"T;IF T<>S IF T<>U IF T<>V G.270 280 W=T;GOS.130 290 IF X=S OR X=U OR X=V P."I SMELL A WAMPUS!!"' 300 IF Y=S OR Y=U OR Y=V P."I HEAR WINGFLAPS!!"' 310 IF Z=S OR Z=U OR Z=V P."I FEEL A DRAFT!!"' 320 IF Z=W P.$12"AAAAHHHHHHHH!!"';FOR T=1 TO 100;WAIT;N.;G.5000 330 IF Y=W G.340 335 G.400 340 T=ABSRND%5+15;P.$12;?#E1=0;?#8000=#20 345 FOR P=1 TO T 350 L=ABSRND%#1FF+#8000;?#DE=L;?#DF=(L/255) 351 BB(P)=L;N=0 352 FOR M=1 TO 8;IF ?(BB(P)+M)<>#20 M=8;N.;N.;N=1;G.354 353 N. 354 P."FLAP!!";WAIT;WAIT;WAIT;WAIT;WAIT;WAIT;WAIT 355 IF N=1 G.360 356 N. 360 F.T=1 TO 100;WAIT;N.;P.$12;F.T=1 TO 6;P.$10;N.;W=ABSRND%8+1 370 ?#E1=#80;P." SUPERBATSNATCHED!!"';G.110 400 IF X<>W G.120 410 P."YOU HAVE DISTURBED THE WAMPUS!!"';T=ABSRND%10 420 IF T=1 OR T=4 X=S;IF X=Y OR X=Z X=X+1;G.500 430 IF T=2 OR T=5 X=U;IF X=Y OR X=Z X=X+1;G.500 440 IF T=3 OR T=6 X=V;IF X=Y OR X=Z X=X+1;G.500 445 IF T<>5 G.120 450 P.$12"THE WAMPUS HAS EATEN YOU!!";FOR T=1 TO 100;WAIT;N. 460 G.5000 500 G.120 600 IN."THROUGH HOW MANY CAVES"C;IFC<1ORC>2P."MUSCLES"';G.600 601 E=W 602 F.T=1 TO C;P."SHOOTING THROUGH CAVE"'S", "U" OR "V 603 IN.G;AA(T)=G 605 IFAA(T)<>U IFAA(T)<>V IFAA(T)<>S P."I'M NOT BIONIC!"';G.603
607 W=G;GOS.130 618 N. 619 W=E 620 FOR T=1 TO C;G=AA(T) 630 IF X=G THEN T=11;N.;G.700 640 IF W=G THEN T=11;N.;G.800 650 P."********BOIIIING!!*****"';N.;D=D-1;IF D=0 G.900 660 G.120 700 P.$12"YOU GOT THE WAMPUS,"' 710 P."BUT THE WAMPUS'LL GETCHA NEXT"'"TIME!!!!!!!!"';G.5030 800 P.$12"UUNNNNNGGGHH!!!!"'"YOU SHOT YOURSELF!!";F.T=1 TO 100 810 WAIT;N.;G.5000 900 P.$12"YOU EXHAUSTED YOUR SUPPLIES"'"OF ARROWS!!!!"' 910 FOR T=1 TO 100;WAIT;N.;G.5000 5000 P.$12"YOU LOST!"';IN."AGAIN(YES OR NO)"$Q 5010 IF $Q="NO" OR $Q="N" E. 5020 IF $Q="YES" OR $Q="Y" G.5040 5030 IN."AGAIN(YES OR NO)"$Q;G.5010 5040 IN."SAME SETUP(YES OR NO)"$Q 5045 IF $Q="YES" OR $Q="Y" P.$12;G.110 5050 IF $Q="NO" OR $Q="N" G.100 5060 G.5040
The body of the program is the loop from lines 120 to 400. Lines 120-230 show which cave you are in (W), and which you can move to (S,U,V). Lines 231,245 directly examine the keyboard keys 1 and 2 to see if you want to shoot or move to another cave. If you decide to move, lines 260-270 find out which cave you want to move to and check that this is possible.
Having moved you, the program then uses lines 290-310 to warn you of any dangers lurking in adjacent caves (X is the cave occupied by the Wampus, Y that infested by superbats, and Z is that without a floor). If you had entered the cave of the bottomless pit, line 320 drops you in it. Lines 340-370 activate the bats when you intrude upon them. If the Wampus is next door, lines 410-450 decide whether he will eat you or merely move away.
When you decide to shoot, lines 600-618 find out which caves you will shoot through - and note them in AA(). Lines 619-910 then tell you what - if any - effect your shot has had.
Text; 1k
VDU; ½K
Integer
The Simon of legend said "Do what I do". In this musically accompanied game, ATOM says "Remember the sequence of letters I flash onto the screen, then press the same sequence of keys". If you do well, ATOM will gradually increase the number of letters displayed each time, but if you consistently fail to remember, then ATOM will give up in disgust.
10 REM SIMON 100 DIM S(10),R(-1) 110 N=5;B=0;P=#81;;P.$21 120[;LDA #B002;LDY @#FF;LDX #80;DEX;BNE P-1 130 EOR @4;STA #B002;DEY;BNE P-11;RTS 140];P.$6 200 DO;P.$12;@=0;?#E1=0 210 P."THIS TIME, SIMON GIVES YOU "N 215 P.'"LETTERS TO REMEMBER ;"'' 220 FOR L=0 TO N-1;T=65+ABSRND%26 230 S?L=T;?#806C=T-64;?#80=160-L*8;LINK#81 240 FOR I=1 TO 30;WAIT;N.;?#806C=#40 250 FOR I=1 TO 30;WAIT;N.;N.L;S?N=13 300 IN.'"THEY WERE ; "$R;IF $R=$S G.340 310 P."NO - THEY WERE ; " 320 FOR L=0 TO N-1;P.$S?L;?#80=?#80+8 330 LINK#81;WAIT;N.;B=B-1;G.350 340 P."CORRECT !"';LINK#81;WAIT;LINK#81;B=B+1 350 IF B=2;N=N+1;B=0 360 IF B=-2;N=N-1;B=0 370 IF N=2 P.''"ABYSMAL !!!"';G.500 380 INPUT''"ANOTHER "$R;IF ?R=CH"N" G.500 390 UNTIL N=10 400 P."WELL DONE, I GIVE UP"' 500 ?#E1=#80;END
A small machine language routine (lines 120-140) is used to provide the musical accompaniment by generating a short note of a pitch determined by the value put into the RAM location 80.
The main body of the program is the loop through lines 200 to 390, an inner loop (lines 220-250) chooses and displays the sequence of N letters, saving them as the string $S. If the player answers incorrectly, lines 320-330 show him what he should have entered.
Text; 2K
VDU; 2-6K
Integer
This program is useful as a lecture aid, as an advertising gimmick, or as an auto-banner for Computer Lib demonstrations, as it allows you to create a number of text 'screens' in RAM, to edit them as required, and to play them through at any rate. It will also save the screens to a tape file, and subsequently load them back into RAM.
The number of screens that can be used is limited by the amount of VDU RAM available; the minimum useable amount of 2K bytes gives 3 screens - while an ATOM fitted with the full 6K bytes of VDU RAM can handle 11 screens.
When the program is first run the screens are cleared, then a 'menu' is presented. You may then enter;
10 REM SCREENS 50 DIMG8,Z-1;GOS.9000 100 S=-1;X=#8000;C=#20202020;W=0 110 DOX?512=#AA;X?513=#55 120 F.I=0TO511STEP4;X!I=C;N. 130 X=X+512;S=S+1 140 U.?X<>#AAORX?1<>#55 200 P.$12;@=2;P."ENTER ;"'' 210 P."1-"S" TO EDIT SCREENS"' 220 P." P TO PLAY SCREENS"' 230 P." S TO SAVE ON TAPE'"'
240 P." L TO LOAD FROM TAPE"' 250 P." E TO END"'' 260 IN.$Z 265 IF$Z="P"G.2000 270 IF$Z="S"G.3000 275 IF$Z="L"G.4000 280 IF$Z="E"E. 285 GOS.6000 288 IFT>0AND T<(S+1)G.1000 290 P.$11;G.260 1000 D=512*T;W=1 1010 F.I=#8000TO#81FFSTEP4;!I=I!D;N. 1020 !#DE=#80008000;?#8000=(?#8000+#80)&#FF 1030aLI.#FFE6;G.a 2000 IN."SCREENS 1-"$Z;GOS.6000 2010 IFT<1ORT>S P.$11$11;G.2000 2020 E=T 2030 IN."TIME FOR EACH (SECONDS) "$Z 2040 GOS.6000 2050 K=T 2060 IN."NUMBER OF CYCLES "$Z 2070 GOS.6000 2100 F.L=1TO T 2110 F.F=1TO E;D=512*F 2120 F.I=#8000TO#81FFSTEP4;!I=I!D;N. 2130 F.H=0TO60*K;WAIT;N. 2140 N.F 2150 N.L;G.200 3000 IN.'"SCREENS 1-"$Z;GOS.6000 3010 IFT<1ORT>S P.$11$11;G.3000 3020 IN."FILENAME "$Z 3030 T=#8200+512*T;X=#A0 3040 !X=Z;X!2=#8200;X!6=#8200 3050 X?8=T;X?9=T/256 3060 LI.#FFDD;G.200 4000 IN."FILENAME "$Z 4010 T=#8200+512*T;X=#A0;!X=Z;X!2=#8200 4020 LI.#FFE0;G.200 6000 T=0;J=0 6010bIFZ?J<CH"0"ORZ?J>CH"9"R. 6020 T=10*T+Z?J-CH"0";J=J+1;G.b 8000 D=?#DE+?#DF*256+?#E0;?D=(?D+#80)&#FF 8020 D=512*T 8030 F.I=#8000TO#81FFSTEP4;I!D=!I;N. 8040 W=0;G.200
9000 P=#80;P.$21 9010[;LDA@0;STA#B000;JSR#FE94 9020 PHA;LDA@#A;STA#B000;PLA 9030 CMP@#1B;BEQP+3;RTS;BRK 9040] 9050 P.$6;?#20A=#80;?#20B=0 9060 $G="GOTO8000";?16=G&#FF;?17=G&#FFFF/256 9070 R.
When the program is started it calls the subroutine at line 9000 which modifies ATOM's normal keyboard read and BRK routines so that pressing the ESC key does not stop the program, but makes it jump to line 8000 instead
The screens are stored in the VDU RAM space above 81FF, this area being otherwise unused when the VDU is in text mode. Lines 100-140 fill this area with the VDU 'space' code and also count the number (S) of 512 byte blocks available for use as screens.
Lines 200-295 present the menu - and refuse to accept anything except a valid response from the user. If a screen number is entered the program jumps to line 1000 with T equal to the number of the selected screen. This screen is then copied into the visible area of the VDU RAM space (8000 - 81FF) by lines 1000, 1010 and the cursor positioned at the top left corner by line
1020. Line 1030 allows you to type onto the screen by repeatedly calling the (now modified) Operating System OSECHO routine.
Lines 2000-2150 are executed if you have chosen to Play through the screens; line 2120 being used to bring the appropriate screen into the viewing area.
Lines 3000-3060 save selected screens as a file on tape by using the Operating System OSSAVE routine - after getting the new file's name and setting up the appropriate data for the OSSAVE routine (lines 3020-3050). Lines 4000-4020 similarly use the OSLOAD routine to load a tape rile of screens into RAM.
Lines 6000-6020 are a subroutine which is used to convert an input string $Z to a number Z; if $Z cannot be interpreted as a number then the subroutine returns T as 0.
When the ESC key is pressed the program jumps to lines 8000-8030 which remove the cursor (line 8000), then if the program had been in Edit mode, the screen is saved in the appropriate area of RAM before branching back to line 200 to display the menu.
Text; 2K
VDU; ½K
Integer
This is a computerised version of the word guessing game; Hangman. The computer picks a word, shows you how many letters it has, and then you try to guess the letters one at a time. If the letter you choose is in the word, the computer shows you where, but it you are wrong then the computer starts to hang you. For each mistake, the computer fills in part of a drawing of you dangling from a gallows. The ninth mistake is fatal.
1 REM HANGMAN 10 DIM W(20),R(1);N=10 20 CLEAR 0;GOTO 100 50a*CAMBRIDGE*ATOM*FIEND*SLAYS 51 *FOREIGN*MICRO*DURING*PIZZA 52 *EATING*COMPETITION 100 X=?18*256;D=#D;Y=CH"a" 110 DO DO X=X+1;UNTIL ?X=D;UNTIL X?3=Y 120 X=X+3;Y=CH"*" 130 FOR P=1 TO ABSRND%N 140 DO X=X+1;IF ?X=D X=X+3 150 UNTIL ?X=Y;X=X+1 160 NEXT P;Z=0 170 DO W?Z=X?Z;Z=Z+1 180 UNTIL X?Z=D OR X?Z=Y OR X?Z=CH" " 190 W?Z=D 200 FOR X=1 TO LEN(W);X?#80F0=#2E;NEXT 210 MOVE 0,9;DRAW 24,9 220 E=0 300 DO !#DE=#81C0 310 P."LETTER "$8$8$8;INPUT $R 320 UNTIL ?R>CH"@" AND ?R<CH"[" 400 X=1 410 IF X?#80F0=#2E IF ?R=W?(X-1) GOTO 600 420 IF X<LEN(W) X=X+1;GOTO 410 430 GOSUB (1000+100*E);E=E+1 440 IF E<10 GOTO 300 500 !#DE=#8111;P.$W 510 !#DE=#81C0;P."<** YOU ARE dead !!! **" 520 ?#E1=#80;END 530 END 600 X?#80F0=?R-#40;C=0 610 FOR X=1 TO LEN(W) 620 IF X?#80F0=#2E C=1 630 NEXT X;IF C=1 GOTO 300
700 CLEAR 0;MOVE 16,40 710 GOSUB 1400;GOSUB 1500;GOSUB 1600 720 GOSUB 1700;GOSUB 1800 730 MOVE 16,32;DRAW 24,40 740 MOVE 0,8;DRAW 63,8 750 !#DE=#80F1;P.$W 760 !#DE=#81C0;P."<** A REPRIEVE !! ** " 770 ?#E1=#80;END 1000 MOVE 0,6;DRAW 0,47;RETURN 1100 MOVE 0,38;DRAW 9,47;RETURN 1200 MOVE 0,47;DRAW 16,47;RETURN 1300 DRAW 16,40;RETURN 1400 DRAW 14,40;DRAW 14,36;DRAW 18,36 1410 DRAW 18,40;DRAW 16,40;RETURN 1500 MOVE 16,36;DRAW 16,24;RETURN 1600 DRAW 8,10;RETURN 1700 MOVE 16,24;DRAW 24,10;RETURN 1800 MOVE 16,32;DRAW 8,40;RETURN 1900 MOVE 3,9;PLOT 7,24,9 1910 MOVE 8,10;PLOT 6,16,24;PLOT 6,24,10 1920 MOVE 14,8;DRAW 16,24;MOVE 18,8;DRAW 16,24 1930 MOVE 8,40;PLOT 6,16,32;DRAW 13,22 1940 MOVE 16,32;DRAW 19,22;RETURN
The list of words used is stored in lines 50-52, and may be changed as long as each word is preceded by a *, and N (line 10) is made equal to the number of words in the list.
When the program is run, lines 100-120 look through the text area for the * immediately following the label a. Lines 130-160 then search for the start of a randomly chosen word, and lines 170-190 copy it as a string into the byte vector W. Lines 200-220 put a line of dots onto the screen, corresponding to the number of letters in the word, and draw the stage of the gallows.
The body of the program is the loop through lines 300-440, which gets the letter you have chosen, then sees if it is in the word (lines 400-420). If it isn't, then lines 430,440 draw the next stage of your execution and - if you are still alive - go back to line 300 for your next guess. After the ninth mistake, lines 500-530 declare you dead. Note line 300, which sets the text cursor position to the start of the 14th line and turns the cursor off.
If you have guessed a letter correctly, lines 600-630 display it and see if you have completed the word. If so, your reprieve is granted via lines 700-770, if not then back to line 300.
Lines 1000-1940 are a series of subroutines used to draw various parts.
In some circumstances you may wish to allow people to run your program, but not to list it - to hide your programming technique or to protect a password or other sensitive data within the program. Unfortunately a determined programmer can break any software safeguards if he has total control of the machine - as with ATOM - but it is possible to make it difficult enough to discourage the merely curious, or those with little time to spare.
The basic technique is to insert those ASCII codes that turn off the printer and VDU into REM statements so that they have no effect when the program is run, but prevent the later lines from being shown when the LIST command is given. Thus, if you have a completed, tested program ready for added protection type;
1 REM CTRL-L CTRL-U CTRL-C RETURN
(do it carefully, the screen will not show anything after the REM statement).
Then press BREAK, and enter OLD to restore the VDU to normal use. You should now be able to run the program as before, but not list it out on the VDU or printer.
Although it is easy enough to call a machine language routine from a BASIC program by using the LINK command, there are occasions when it would be useful if a short BASIC routine could be called from a machine language program - for example to generate a random number with BASIC's RND function. It can be done if the RAM locations 5 & 6 are loaded with the address of the start of the BASIC routine (low byte in 5, high byte in 6), then a JSR #C2F2 is executed. At the end of the BASIC routine, a suitable LINK instruction will return control to the remainder of the machine language routine.
If a BASIC program is saved on tape by using the COS command
*SAVE "FILENAME" START END CE86
Where START is the text space start address (2900 or 8200), and END is the (hex) address of the end of the program (obtained by typing P.&TOP), then you will subsequently be able to LOAD the program, and RUN it as normally, but the command
*RUN "FILENAME"
will fetch the program from tape, and run it automatically as soon as it has loaded.
It is possible for a BASIC program to load and run another program from tape - the original program being deleted from RAM in the process - if the second program is saved as an 'autostart' program.
Thus, in the example given below, two programs are entered and saved on tape, the second in autostart mode, then the first one is loaded and run. Program 1 then automatically loads and runs the second program.
10 REM PROG 1 20 PRINT "THIS IS PROGRAM 1"' 30 *RUN "PROG 2" > >P.&TOP 293F> >*SAVE "PROG 1" 2900 293F CE86 RECORD TAPE > >NEW >10 REM PROG 2 >20 PRINT "THIS IS PROGRAM 2"' >30 END > >P.&TOP 2935> >*SAVE "PROG 2" 2900 2935 CE86 RECORD TAPE >*RUN "PROG 1" PLAY TAPE THIS IS PROGRAM 1 PLAY TAPE THIS IS PROGRAM 2 >
Repeatedly branching out of a FOR ... NEXT loop (or a DO ... UNTIL loop) can cause a program to 'crash', giving error code 18 or 111. For example, the two programs given below should both print out indefinitely, but they both crash after 11 *'s.
10 REM 20 X=1 30 DO 40 X=X+1 50 IF X=5 GOTO 70 60 UNTIL X=0 70 PRINT '*' 80 GOTO 10 RUN ERROR 18 LINE 30 |
10 REM START 20 FOR I-1 TO 10 30 IF I=5 GOTO 50 40 NEXT I 50 PRINT '*' 60 GOTO 10 >RUN *********** ERROR 111 LINE 20 |
The reason is that on entering a FOR ... NEXT loop (or a DO UNTIL loop), ATOM BASIC puts details of the loop onto a stack, and pulls them from the stack when it finally exits via the NEXT or UNTIL statement. However, jumping out of the middle of the loop leaves the data still on the stack, which can eventually fill up and cause the program to crash.
In the case of the DO … UNTIL loop, there is no way around the problem, so programs should avoid having to branch out of DO UNTIL loops. FOR … NEXT loops, however, will not cause a crash if an outer FOR ... NEXT loop (which is not jumped out of) can be included so that the NEXT of the outer loop is reached before the stack has filled. Thus in the example given below, the addition of the loop involving lines 10 and 60 prevents the overall program from crashing. The reason for this recovery is that the data relating to the outer loop is put onto the stack first, so on encountering the outer NEXT statement in line 60, ATOM BASIC cleans-up the stack, removing the irrelevant data left from the inner loop. For a practical example, see the program "SCRAMBLE", where lines 410,600 prevent the inner loop between lines 520 and 540 from crashing the program after several moves.
10 FOR K=1 TO 30 20 FOR 1=1 TO 10 30 IF 1=5 GOTO 50 40 NEXT I 50 PRINT '*' 60 NEXT K 70 END >RUN ******************************>
In some cases it would be convenient if the program could read a single keystroke, without the user having to press the Return key. The following example program does this by using a machine language routine to wait for a keystroke then place the appropriate ASCII code in location 80 before returning to the BASIC program which then displays the ASCII code.
1 REM KEYPRESS DEMO 10 DIM P(-1) 20[JSR #FFE6;STA #80;RTS;] 100 PRINT"PRESS A KEY; "' 110 LINK TOP 120 PRINT" CODE = "?#80 130 GOTO 100
As it stands, the routine will display the character corresponding to the key pressed. To prevent this 'echo' change line 20 to;
20[JSR #FFE3;STA #80;RTS;]
Atomic Theory and Practice suggests that to prevent operation of the ESC key from halting a program, you use ?#B000=10. This is because, when the program is running, the low four bits of the 8255 port B000 are normally set to 0 to allow the BASIC interpreter to examine the state of the ESC key by simply looking at bit 5 of B001; setting B000 to 10 means that B001 bit 5 no longer is connected to any of the keys.
Unfortunately, if the program requires an INPUT from the user, then each time a character is read from the keyboard, the keyboard scan routine resets the low four bits of B000 to zero. To overcome this, and so provide a more foolproof method of disabling the ESC Key, we should also modify the OSRDCH routine so that B000 is set to 10 after each character has been read. This can be done by placing a routine such as that listed below at the start of the program;
10 P=#80;P.$21 20[LDA @0; STA#B000;JSR #FE94 30 CMP @#1B;BNE P+4;LDA @#20 40 PHA;LDA @10;STA #B000;PLA;RTS;] 50 P.$6;?#20A=#80;?#20B=0;?#B000=10
Lines 20-40 are a machine language routine which is substituted for OSRDCH by changing the vector at 20A & 20B. Line 20 reads a character from the keyboard, using the (undocumented) COS routine at FE94, line 30 then checks to see if it is ESC, and if
so changes the code to that for 'space', line 40 resets B000 to 10. As well as changing the vector, line 50 also sets B000 to 10 before anything else happens. Note that certain control codes (e.g. that generated by PRINT $6) or a CLEAR will reset the low four bits of B000 to zero.
If you have to store a lot of alphanumeric data in RAM or on tape, and if you can do without the inverse (lower case) characters and the control codes, then it is possible to increase the number of characters that can be stored in a given area by converting each ASCII character to a 6-bit code, then packing 4 characters into 3 bytes.
The demonstration program below use lines 100-180 to pack the 16-character string $A into the 12 byte vector P(), then lines 400-480 reverse the process to restore the original form of $A.
10 REM PACKING DEMO 20 DIM A(16),P(11) 30 $A="ABCDEF0123156789" 100 Y=A 110 FOR X=P TO (P+11) STEP 3 120 Z=0 130 FOR Q=0 TO 3;Z=Z*#40+Y?Q-#20 140 NEXT Q 150 FOR Q=0 TO 2;X?Q=Z%256;Z=Z/256 160 NEXT Q 170 Y=Y+4 180 NEXT X 200 @=0;P.$12$A''"PACKS TO (HEX)"' 210 FOR X=P TO P+11;P.&?X" ";NEXT X 300 $A = " ";REM DESTROY THE EVIDENCE 400 Y=A 410 FOR X=P TO (P+11) STEP 5 420 Z=0 430 FOR Q=2 TO 0 STEP -1;Z=Z*256+X?Q 410 NEXT P 450 FOR Q=3 TO 0 STEP 1;Y?Q=Z%#40+#20;Z=Z/#40 460 NEXT Q 470 Y=Y+4 480 NEXT X 500 P.''"AND UNPACKS TO; "'' 510 END
If a control code such as CR is essential, then it could be substituted for one of the less-used alphanumerics such as ASCII codes 5B-5F.
A similar technique can he used to pack two BCD digits into a single byte for data storage applications.
In some applications (as for example the "Sums Tester" program given elsewhere in this book), the computer should be able to keep track of how long it has waited for a response from the keyboard, and take alternative action if it has waited too long.
This can be done by modifying ATOM's normal keyboard input routine so that a counter is incremented at regular intervals when it is waiting for a key to be pressed, and abandoning the wait via a BRK instruction when the counter has reached a pre-determined number.
An example of such a routine is given below.
10 REM KB TIMEOUT EXAMPLE 100 P=#B4 102[\ NEW KEYIN ROUTINE 104 PHP 106 CLD 108 STX #E4 110 STY #E5 112 BIT #B002 114 BVC #94 REPT? 116 JSR #210 SCAN KB 118 BCC #8A BR IF KEYPRESS 120 JSR #FB8A CHECK SHFT,CTRL 122 JSR #21C WAIT FOR 124 BCS #97 KEYPRESS 126 JMP #FEA7 TO OP SYSTEM 129] 130 P=#21C 132[\ SCAN & COUNT SUBROUTINE 134 JSR #FE66 WAIT FOR FLYBACK 136 INC #80 INCREMENT 138 BNE #228 140 INC #81 142 BNE #228 TIMER 144 BRK 146 JMP #FE71 SCAN KB & RTS 148] 200 REM LINK IN NEW ROUTINE 210 ?#20A=#84;?#20B=0 300 REM TEST ROUTINE 310 !#80=-600 320 INPUT STOP 330 PRINT !#80 340 GOTO 310
Lines 100-128 assemble to give a machine language routine in the free RAM locations 80-9E, which is used to replace the first part of ATOM's normal input routine. It waits until all keys except
perhaps the SHIFT, CTRL or REPT keys) have been released (lines 114,118), then waits for a new key to be pressed (lines 122,124) before jumping to the second part of ATOM's normal keyboard input routine at FEA7. While waiting, it uses a subroutine (lines 132, 146) which assembles into the free RAM locations 21C-22A to increment the contents of locations 80,81 and scan the keyboard every 1/60 second. Locations 80,81 are to be preset to a negative number at the start of a program, and the routine times out by executing the BRK instruction when the count reaches zero. Note that locations 82 & 83 are left free so that the counter can be preset with a normal ATOM BASIC 4-byte word. The longest timeout that can be obtained is 18 minutes, obtained by pre-setting the count to -65535.
As an example of using the timeout facility, lines 300-340 are a simple loop which first presets the count to -600 (10 seconds), then waits for an input. If the Return key is pressed to signal the end of the input before the 10 seconds has elapsed, the program will display the remaining count then loop back for another input. If the time limit is exceeded, the program simply crashes;- in practice it would be better to add a BRK error handler as described in sections 18.8 and 23.10 of 'Atomic Theory and Practice', or as in the 'Sums Tester' program in this book.
It should be noted that the ATOM Operating System routines used by this program are not documented by Acorn, and so may not be valid if they introduce an updated ROM.
102 0084 \ NEW KEYIN ROUTINE 104 0084 08 PHP 106 0085 D8 CLD 108 0086 86 E4 STX #E4 110 0088 84 E5 STY #E5 112 008A 2C 02 B0 BIT #B002 114 008D 50 05 BVC #94 REPT? 116 008F 20 1C 02 JSR #21C SCAN KB 118 0092 90 F6 BCC #8A BR IF KEYPRESS 120 0094 20 8A FB JSR #FB8A CHECK SHIFT,CTRL 122 0097 20 10 02 JSR #21C WAIT FOR 124 009A B0 FB BCS #97 KEYPRESS 126 009C 4C A7 FE JMP #FEA7 TO OP SYSTEM 132 021C \ SCAN & COUNT SUBROUTINE 134 021C 20 66 FE JSR #FE66 WAIT FOR FLYBACK 136 021F E6 80 INC #80 INCREMENT 138 0221 D0 05 BNE #228 140 0223 E6 81 INC #81 142 0225 D0 01 BNE #228 TIMER 144 0227 00 BRK 146 0228 4C 71 FE JMP #FE71 SCAN KB & RTS
A wealth of programs written in BASIC can be found in other books and computing magazines, but there are many versions of BASIC, and it is unlikely that a program written to run on another computer will work on the ATOM without some changes. The extent and nature of the alterations needed will depend on the structure of the program, and how it handles data, as well as the particular dialect of BASIC used, so you should understand how the original program works before attempting to convert it to ATOM BASIC, and be prepared to alter the program and data structures if necessary.
The following paragraphs list the differences between ATOM BASIC and the major dialects found on other machines.
Some BASICs don't allow more than one statement on a line, thus
10 LET B=B+C 15 PRINT B
could be written for the ATOM as;
10 LET B=B+C;PRINT B
but take care that the 'deleted' line (line 15 in this example) is not the target of a GOTO or GOSUB.
More importantly, those versions of BASIC which do allow multiple statements on a line usually use ':' or '\' to separate the statements, rather than the ';' used by the ATOM. Thus;
10 A=2:B=3
would become;
10 A=2;B=3
Note that most other BASICs use the semi-colon in a PRINT statement to indicate that the items on either side of it are to be printed without intervening spaces, thus;
10 PRINT "ABCD";"EFGH"
will usually give a print-out of;
ABCDEFGH
whereas ATOM BASIC would misinterpret this line as two statements;
10 PRINT "ABCD" and "EFGH"
See the notes on PRINT statements for ways of replacing the ';' in these circumstances.
Many BASICs allow floating point decimal numbers (generally called 'real' numbers) such as 9.73 or -27.456. If your ATOM is not fitted with the Floating-Point extension ROM, then depending on the program it may be possible to 'scale' the values - by multiplying by say 10 or 1000 for the calculations so that a reasonable accuracy is obtained. The large range of values allowed by ATOM (approximately -2000 million to +2000 million) make this task relatively straightforward.
BASICs that allow real numbers usually do all operations in floating point mode, and only give integer results when specifically instructed to do so by a function such as INT (X); which gives the integer value of the real variable or expression X (e.g. INT (6.67) gives 6). This is different to the approach used by ATOM BASIC, which has separate commands for integer and floating point working (when the Floating Point ROM is fitted) e.g. PRINT and FPRINT, IF and FIF, and must be watched carefully when translating.
Some floating point BASICs allow the use of integer variables by giving them special names in much the same way as ATOM BASIC has different types of names for integer and real variables. Unfortunately, this can cause some confusion as opposite conventions are used, thus typically;
A is a floating point variable equivalent to ATOM's %A
%A or A% is an integer variable equivalent to ATOM's A
Many versions of BASIC allow you to use variable names longer than one character, such as A1, A2% or COUNTUP.
Single letter names will have to be allocated for ATOM.
In most versions of BASIC, an array variable is distinguished from an ordinary variable only by the presence of the parentheses () after the name. For example A(7) is element 7 of the array A() and may be an integer or a floating point number depending on the type of BASIC, space for the array being reserved by a previous statement such as DIM A(99). ATOM BASIC, of course, uses the double letter form AA() for an integer array element, and %M() for a floating point array element - with space reserved by a DIM AA(99) or FDIM %AA(99).
Note that the expression DIM A(n) is used by ATOM BASIC to reserve space for n+1 bytes, which may then be used to hold a string variable or for byte or word vectors, and is therefore not equivalent to DIM A(n) In other BASICs (which don't allow for byte or word
vectors). Also, note that in most BASICs the array variable A() and the ordinary variable A have no relation and may be used independently within a program. This differs from ATOM BASIC which uses the variable A to hold the RAM address of the first byte in the vector defined by a DIM A() statement.
As byte and word vectors are a unique ATOM BASIC feature, it may be worthwhile seeing if a program being translated can be simplified by their use.
Many versions of BASIC allow multi-dimensional arrays, such as DIM A(4,4,4) , which declares a three dimensioned array having a total of 125 (5x5x5) elements. Page 50 of 'Atomic Theory and Practice' shows how to convert multi-dimensional arrays so that the ATOM can handle them.
Note that in some BASICs the first element of an array has the subscript (1), rather than (0).
String variables are represented in most versions of BASIC by a variable name followed by the '$' sign, thus A$ is a string variable. Usually A and A$ are unrelated.
In ATOM BASIC, however, strings are handled as byte vectors, by using a DIM statement to set up a variable (say A) to point to the first RAM location where the string is to be stored. The string is then accessed by putting the string operator '$' in front of the variable name. Thus '$A' refers to a string starting at RAM location A.
Many versions of BASIC allow string variables of less than a certain length (for example 10 characters) to be used without having to specifically reserve space with a DIM statement. This is not allowed in ATOM BASIC.
When the length of a string has to be declared to reserve memory space, the various versions of BASIC differ in the details of how this is done, but the most common scheme is to use a statement of the form DIM A$(20) or DIM A$[20] to reserve space for a 20-character string. The latter form is most used by BASICs which allow arrays of strings; such that DIM A$(10)[20] declares a 10 (or 11) element string array, each string being up to 20 characters. Pages 62,63 of 'Atomic Theory and Practice' show how string arrays can be handled by the ATOM.
Some BASICs do not allow a computed GOTO or GOSUB such as GOTO (A+100). It may therefore be possible to simplify a program
by taking advantage of this ATOM BASIC facility.
Remember also that the use of a label associated with a line number is another ATOM BASIC feature that can be useful to speed up the execution of GOTO and GOSUB statements.
Sometimes found in other BASICs, these statements make the program GOTO (or GOSUB) one of a number of lines depending on the value of a variable. For example;
10 ON I GOTO 100,105,50
will jump to line 100 if I=1, 105 if I=2, or 50 if I=3.
Depending on the particular application, ON..GOTO or ON..GOSUB may be replaced by a 'computed' GOTO or GOSUB, or by a combination of IF- - GOTO lines.
Most other versions of BASIC require that the 'THEN' is always included; a few memory bytes can usually be saved by leaving it out when translating to ATOM BASIC.
Some BASICs don't allow anything except a GOTO after the THEN. Programs written in these dialects may sometimes be simplified by taking advantage of ATOM's ability to have any statement or statements after a THEN. Thus;
10 IF X>0 THEN GOTO 40 20 PRINT "TOO LOW" 30 END 40 ...
could be re-written as;
10 IF X<11 PRINT "TOO LOW"; END 40 ...
Note that BASICs differ in their interpretation of a value as being 'true' or 'false'. Thus;
10 IF A THEN PRINT "TRUE"
will print TRUE in ATOM BASIC if A is non-zero, whereas other versions of BASIC may use - for example - negative values to represent the Boolean value 'false' and zero or positive values for 'true'.
ATOM BASIC's FOR ... NEXT loop function is similar to other BASICs, so usually no alteration will be needed when translating except - perhaps - to note that in some circumstances it may be better to take advantage of ATOM's DO . .UNTIL loop control function.
Be careful, however, if the program jumps out of a FOR . . NEXT loop. Some BASICs are able to do this repeatedly without harm, but as discussed in the section 'Programming Tips', ATOM BASIC may object.
Some forms of BASIC don't allow a 'prompt' string to be included in the INPUT statement, so programs written in these dialects may be simplified slightly for use on the ATOM. For example;
10 PRINT "MONTH " 20 INPUT M
could be translated to;
10 INPUT "MONTH "M
Print statements will often have to be amended to make best use of the ATOM's screen format. It should also be noted that in most versions of BASIC, items in a PRINT list must be separated by a comma (,) or a semicolon (;). The comma causes the next expression to be printed out in the next tabulation field - as in ATOM BASIC -the semicolon causes the next expression to be printed immediately following the previous one without any intervening spaces, and is equivalent to an ATOM BASIC PRINT statement with just a space between expressions. For example;
10 PRINT A,B;C;D
translates to the ATOM BASIC
10 PRINT A,B C D
Most versions of BASIC output a carriage return/line feed automatically at the end of a PRINT list, unless the last character in the list is a semicolon, and if an additional line feed is needed it has to be generated by another PRINT statement. ATOM
BASIC on the other hand, only outputs carriage return/line feed when specifically instructed by an apostrophe (') in the PRINT list. Thus;
10 PRINT "ABC"; 20 PRINT "DEF" 30 PRINT "l23" 40 PRINT 50 PRINT "456"
will cause most BASICs to print out
ABCDEF 123 456
and is equivalent to the ATOM's
10 PRINT "ABC" "DEF" '"123"' '"456"'
In most BASIC dialects, TAB(X) is used in a PRINT statement to cause the next character to be printed at position number X in the line. Thus PRINT TAB(25);"A" will print the letter A in the 25th column.
ATOM BASIC does not have the TAB() function, but does have a function COUNT which gives the number of characters already printed on that line, thus the example given above could be re-written as; DO PRINT " ";UNTIL COUNT=24; PRINT "A".
Programs written in other BASICs sometimes use the TAB function to simple graphs; in these cases it may be possible to produce the same result by use of ATOM's PLOT or DRAW statements.
PEEK and POKE statements are used in some BASICs to look at, and change, the values of specific memory locations. Equivalents of these are given in page 15 of 'Atomic Theory and Practice'.
USR(X) is a function which calls a machine language routine starting at memory location X - and sometimes it returns a value in a way that depends on the version of BASIC being used. As ATOM BASIC allows you to insert a section of machine code within a BASIC program, to pass values freely between the BASIC and machine code routines, and to run the machine code routine by using the LINK statement, it allows you to do all that USR() can, and more.
In any case, the effect of PEEK, POKE and USR(X) depends entirely an the particular computer being used, therefore to convert a program containing any of these to run on the ATOM, you must find out exactly what the command was intended to do, then write ATOM code to perform a similar function.
DATA and READ statements are often used to handle a list of fixed numeric or string values. Thus if the lines;
100 DATA 7,2,5 110 DATA 12,13
appear in a program, then
200 FOR I=1 TO 5 210 READ A(I) 220 NEXT I
will load the values 7,2,5,12,13 into the array variables A(1) to A(5); each READ statement executed taking the next value from the list. RESTORE sets the list 'pointer' back to the first item in the first DATA statement in the program.
Pages 63,64 of 'Atomic Theory and Practice' show how to perform similar functions in ATOM BASIC, and see the program "Buzz-Word" in this bock for an example with strings.
A statement of the form
10 DEF FNA(X) = X+X*X
is acceptable to most BASICs, and defines a function FNA(X) which returns the value of X+X*X and can be called up with different parameters during the program, e.g.
20 LET A=3*FNA(2)
would give A the value 18.
Usually up to 26 functions; FNA() to FNZ(), are allowed.
ATOM BASIC does not allow functions to be defined in this way, so the expression would have to be written out in full each time it is used, thus the above example would require line 20 to be;
20 A=3*(2+2*2)
The following functions are not available in the Integer form of ATOM BASIC, and if they occur in a program you wish to translate then some other way of calculating the required value must be found;
ATN(X) ; Arctangent of X COS(X) ; Cosine of X EXP(X) ; e raised to the Xth power LOG(X) ; Logarithm of X to the base e SGN(X) ; Returns -1,0 or +1 depending on whether X is negative, zero or positive. SIN(X) ; Sine of X SQR(X) ; Square root of X TAN(X) ; Tangent of X
Trigonometric functions are usually expressed in radians. The Floating Point extension to ATOM BASIC uses the symbol ^ to mean 'raise to the power of' (e.g. 3^2 = 9). Some BASICs use the symbols up-arrow or ** instead.
In most Integer BASICs, the expression RND(X) returns a random positive integer between 0 and X, and is equivalent to ATOM BASIC's ABSRND%(X+1).
In most Floating Point BASICs, RND(X) returns a random decimal fraction between 0 and 1, regardless of the value of X.
Most BASICs will let you join two strings to form a third ('concatenation' is the official word for this operation), thus;
10 LET AS = "ABC" 20 LET S$ = "DEF" 30 LET C$ = A$ & B$
gives C$ the value "ABCDEF". "+" or "!" symbols may sometimes be used instead of "&". ATOM's equivalent for this example is;
10 $A = "ABC" 20 $B = "DEF" 30 $C = $A; $C+LEN(A)=$B
These functions occur in many versions of BASIC. They operate on a string (e.g. X$) to return a string which is a part of X$.
LEFT$(X$,Y) gives the first Y characters in X$. The statement;
10 LET X$ = LEFT$(X$,3)
translates to;
10 $X+3
and the ATOM BASIC equivalent of
10 LET A$ = LEFT$(X$,J)
is;
10 $A = $X ; $A+J = ""
RIGHT$(X$,Y) gives the last Y characters from X$ and is equivalent to ATOM BASIC's $X+Y
MID$(X$,Y,Z) gives 7 characters from X$, starting at the Yth character, thus;
10 LET B$ = "ABCDEF" 20 LET A$ = MID$(B$,3,2)
will give A$ the value "CD". To perform a similar function in ATOM BASIC, a routine such as that given below is required;
10 $B = "ABCDEF" 20 $A = $B+3; $A+2 = ""
Page 61 of 'Atomic Theory and Practice' gives further explanation of these techniques.
ASC(X$) gives the decimal value of the ASCII code for the first character in the string X$, the ATOM BASIC's equivalent is the function CH. Thus
10 LET B = ASC(C$)
translates to;
10 B = CH$C
CHR$(X) returns a string of one character corresponding to the
ASCII code X. Thus;
10 LET B$ = CHR$(65)
gives B$ the value "A". To perform this function on the Atom, we first put the value of X in the first byte of the memory space reserved for the target string, then put the value 13 ('Return') in the second byte. Thus the example given above becomes;
10 B?0 = 65; B?1 = 13
Alternatively, if the CHR$() function is being used in a PRINT statement (usually to output a special control code or a graphics character), the $ operator may be used. Thus;
10 PRINT CHR$(12)
could be translated to run on the Atom as;
10 PRINT $12
as long as the value following the $ is between 0 and 255.
VAL(X$)gives the numeric value of the string (of digits) X$. Thus;
10 LET A = VAL("12.34")
gives A the value 12.34
The function is available in the floating Point extension to Atom BASIC, but not in the integer form, where a special routine would have to be written to convert the string to it's equivalent numeric form, for example;
10 A = 0 20 FOR I = 1 TO LEN(X) 30 A = 10*A+X?I-CH"0" 40 NEXT I
In most versions of BASIC, the function STR$(X) gives a string of digits equal to the value X. Thus LET A$ = STR$(123) give A$ the value "123". The function is available in the Floating Point Extension to Atom BASIC, although in a slightly different form (see page 163 of 'Atomic Theory and Practice'), but not in integer BASIC.
To avoid future aggravation, it is worth investing in a few hours to find the best settings for your tape recorder controls, and possibly the brand of tape used, so you can be confident of being able to retrieve whatever valuable information you commit to tape.
The simplest test is that given in chapter 1 of 'Atomic Theory and Practice', and this should be used first. For a more stringent test, we need to record and retrieve data in blocks, as the Atom normally does. This can easily be done by saving the contents of the 4K BASIC ROM;
*SAVE "TEST TAPE" C000 D000
which gives a tape lasting about 4 minutes. A catalogue of the tape should then show 16 consecutive blocks, as below, if the Atom can successfully read the block headers.
TEST TAPE C000 C000 0000 FF TEST TAPE C100 C000 0001 FF TEST TAPE C200 C000 0002 FF TEST TAPE C300 C000 0003 FF TEST TAPE C400 C000 0004 FF TEST TAPE C500 C000 0005 FF TEST TAPE C600 C000 0006 FF TEST TAPE C700 C000 0007 FF TEST TAPE C800 C000 0008 FF TEST TAPE C900 C000 0009 FF TEST TAPE CA00 C000 000A FF TEST TAPE CB00 C000 000B FF TEST TAPE CC00 C000 000C FF TEST TAPE CD00 C000 000D FF TEST TAPE CE00 C000 000E FF TEST TAPE CF00 C000 000F FF
If all is well, we can then check the Atom can read all the tape, including the actual data, by;
*LOAD "TEST TAPE"
This makes the Atom try to read data from the tape and write it to the BASIC Read Only Memory, which is of course impossible, but the Atom will check that the data there matches the data it tried to write. If the data are read without error, the cursor will re-appear about four minutes later.
Problems and Cures
If you are unable to save and load programs successfully despite careful adjustment of your recorder's level and tone controls, then;
As supplied, the recorder interface of the Atom is optimised for use with the 'Aux' or 'Amp' recorder sockets which expect a signal level of around 300 to 500 mV at an impedance of 1 to 10k. If you are feeding into the 'Mic' socket, then the level expected is usually 5 mV, and the resulting overload can have some very odd effects, especially if the recorder has automatic level control.
In this case, the Atom's 'CAS OUT' level should be reduced drastically; either by increasing R29 to between 100k and 1M, or by adding an external voltage divider as Fig. 1. The latter is preferable as it avoids tampering with the Atom's PCB, and can easily be changed for different recorders by fitting miniature resistors in the recorder connectors.
If the recorder output level is not enough to drive the Atom's interface properly when reading tapes, then the gain of the input amplifier IC46 can be increased by increasing R34 to 100k or 200k. Alternatively, a 3k3 to 10k resistor can be added in parallel with R37.
Some cheap cassette recorders produce a lot of high-frequency noise on playback. This may not be noticed if the loudspeaker has a poor high-frequency response, but can upset the Atom. If you think this may be the problem, a simple low-pass filter (Fig. 2) may help.
The 6522 VIA chip can be added to the Atom to provide printer or other parallel I/O. It is a very clever chip which can handle many parallel or serial I/O functions. A full description would occupy many pages and be beyond the scope of this book, but the following paragraphs show the simpler functions satisfactory for most applications.
Within the VIA are two 8-bit bi-directional I/O ports connected to the I/O lines PA0-7 and PB0-7, two 16-bit counter/timers, an 8-bit serial shift register, and some control circuitry associated with the four lines CA1-2, CB1-2. It appears as 16 registers;
Base | Offset | Function |
---|---|---|
B800 | ||
+00 | Port B. Will float high when inputs. | |
+01 | Port A | |
+02 | Port B data direction | |
+03 | Port A data direction | |
+04 | Timer 1 low counter/latch | |
+05 | Timer 1 high counter | |
+06 | Timer 1 low latch | |
+07 | Timer 1 high latch | |
+08 | Timer 2 low counter/latch | |
+09 | Timer 2 high counter | |
+0A | Shift register | |
+0B | Auxiliary control | |
+0C | Peripheral control | |
+0D | Interrupt flags | |
+0E | Interrupt enables | |
+0F | Port A (like B801, but does not affect interrupt flag) |
Each bit of ports A and B can be made an input by writing '0' to the corresponding bit of the direction register ('1' = output). Once the bit direction has been programmed, the port registers (B800 and B801) may be read or written as any other memory location. reading output bits will just return the value last written to them. Writing to an input bit does nothing.
PA0-7 and PB0-7 presents one TTL load as an input, and can drive one TTL load as an output. PB0-7 outputs can source 3mA at 1V5 when high, useful for driving NPN transistors.
Bits 0 and 1 of B80B should normally be zero. Setting either to 1 invokes a complex latching arrangement for data input to ports A and B.
The 16-bit timer 1 counts down at 1MHz, and has two associated 8-bit latches. Writing to B804 latches the low count data byte. Reading B804 returns the low 8 bits of the counter. Reading B805 returns the high 8 bits of the counter. You can read and write the two latches at B806 and B807 without affecting the counter.
If bit 6 of the auxiliary control register (B80B) is '0', the counter will decrement continually at 1MHz, and set the interrupt flag the first time it reaches zero. This is the 'one-shot' timing mode. If B80B bit 6 is '1', the counter will decrement at 1MHz, but will reload from the two latches as well as setting the T1 interrupt flag. This is the 'free-running' mode, and PB7 toggles each time the counter reaches zero.
The 16-bit timer 2 is similar but there are some differences. Writing to B808 stores the data in an 8-bit latch, reading B808 returns the low byte of the counter. Writing to B809 directly loads the high byte of the counter then loads the low-byte of the counter with the data from the latch. Reading B809 returns the high 8 bits of the counter.
Timer 2 can be clocked from either of two sources; if bit 5 of B808 is '0', the counter decrements at 1MHz. If bit 5 is '1', the counter is decremented by each falling edge applied to PB6. In all cases the timer operates in the 'one-shot' mode; the counter is started by writing to B809, and on reaching zero the T2 interrupt flag becomes '1' and the counter continues to decrement.
The 8-bit shift register uses CB2 for serial input or output, and CB1 for clock pulse input or output. Its operation is controlled by B80B bits 2, 3 and 4.
000 | Shift register disabled |
001 | Shift in controlled by timer 2, clock pulses output on CB1 |
010 | Shift in at 1MHz, clock pulses output on CB1 |
011 | Shift in on falling edge clock pulses input on CB1 |
100 | Shift out repeatedly, controlled by timer 2 |
101 | Shift out 8 bits, controlled by timer 2 |
110 | Shift out at 1MHz, clock pulses output on CB1 |
111 | Shift out on falling edge clock pulses input on CB1 |
In the timer '2' modes, only the low byte of the timer is used. In all cases data are clocked on the rising edge of the internal or external clock pulse on CB1, and - except for the 'repetitive' mode - shifting (and clock pulses supplied to CB1) stops after 8 bits have been shifted in or out. The shift register interrupt flag then becomes '1'. This flag is made '0' by reading or writing of the shift register.
The function of the four control lines are (except when CB1 or CB2 are used by timer 2 or the shift register) determined by the Peripheral Control register at B80C. Most modes are intended for complex interrupt/handshake operations. CA2 and CB2 can be used as simple I/O lines via bits 0 and 5 respectively of B80C if all other bits of B80C are set to '1'.
The interrupt flag register (B80D) has 7 bits which are set to '1'' by particular events inside the VIA chip, and set to '0' by reading or writing particular registers.
Bit | Set to '1' by | Set to '0' by: |
0 | Transition on CA2 | Read/write B801 |
1 | Transition on CA1 | Read/write B801 |
2 | 8th shift in/out | Read/write shift reg. |
3 | Transition on CB2 | Read/write B800 |
4 | Transition on CB1 | Read/write B800 |
5 | Timer 2 = zero | Read B808, write B809 |
6 | Timer 1 = zero | Read B804, write B807 |
7 | Any other bit '1' |
The Interrupt enable register at B80E has 6 interrupt enable bits corresponding to the six bits in the Interrupt flag register. Most applications will not use interrupts, so 00 should be written to B80E. This will not affect the setting of bits in B80D, but will prevent them interrupting the processor.
The following paragraphs summarise the main features of the 8255, which should be enough for most applications. More complex applications require the full data sheet.
The 8255 has three 8-bit ports (A, B and C) which may be used in three modes. Modes 2 and 3 use certain port C lines for handshaking. Mode 0 is easy to use for most applications.
The 8255 appears as four registers
Address | Offset | Function |
---|---|---|
B000 | +00 | Port A |
+01 | Port B | |
+02 | Port C | |
+03 | Control |
In mode 0, ports A and B may be set up as 8
input lines or 8 output lines.
Port C is divided into upper and lower 4-bit sections, each of
which may be set up for input or output.
B003 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Bit function |
---|---|---|---|---|---|---|---|---|---|
0 | Port C lower = output | ||||||||
1 | Port C lower = input | ||||||||
0 | Port B = output | ||||||||
1 | Port B = input | ||||||||
0 | Mode 0 | ||||||||
1 | Mode 1 | ||||||||
0 | Port C upper = output | ||||||||
1 | Port C upper = input | ||||||||
0 | Port A = output | ||||||||
1 | Port A = input | ||||||||
0 | 0 | Mode 0: Basic input/output | |||||||
0 | 1 | Mode 1: Strobed Input/output | |||||||
1 | x | Mode 2: Bi-directional Bus | |||||||
0 | Mode select flag = inactive | ||||||||
1 | Mode select flag = active |
Thus to set port A for output, port B for input, port C lower for output and port C upper for input (the normal conditions in the Atom), we have to write 10001010 binary (8A hex) to B003. We can then read the data on port B at B001.
Port C lines can also be changed individually (if set for output) by writing to the control register a value equal to 2*BitNumber +Q where Q is the value of the output.
When set for output, the 24 I/O lines can each drive one TTL load, sinking 1.7 mA at 0.4V, sourcing 200mA at 2.4V. As inputs, they present a high impedance to the driving source, recognising voltages below 0.8V as '0' and voltages between 2.0V and 5V as '1'
Advanced programmers may find the following table useful as it shows the contents of important block zero RAM locations used by BASIC or the Cassette Operating System. Locations marked as miscellaneous working space tend to have multiple uses. For example, B0 to DB are used by COS for different purposes at different times, and 16 to 59 are usually but not always used as 4-byte integer arithmetic registers.
Note that many of these explanations are not formally supported by Acorn, so they may change in future ROMs. If this happens, we at Timedata would be interested to hear about it.
Address | |
00 | Error number |
01-02 | Current Line number (binary) |
03 | Pointer to character being investigated in statement being interpreted. |
04 | Temp. for X |
05-06 | Address of start of statement being interpreted |
07 | Print Column counter |
08-0C | Random number seed |
0D 0E | Top (binary) |
10 11 | Address of BASIC error handler, normally C9E7, |
12 | Text space pointer; normally 82 or 89 |
16-59 | Misc. BASIC working space |
5A 5B | X ordinate for point plot routine |
5C 5D | Y ordinate for point plot routine |
5E | Data for point plot routine. 1=set, 2=invert, else clear |
5F 60 | Point plot routine workspace |
61 6F | Misc. BASIC working space |
70 7F | FP. BASIC working space |
80 AF | Free |
B0 DB | Misc. COS working space |
DC | Tape read/write checksum |
DD | Fload flag; bit 7 = 1 to ignore block numbers |
DE DF | VDU RAM address of
start of line containing the cursor DE should be 00, 20, 40 ... E0, DF should be 80 or 81 |
E0 | Cursor position in VDU line; 00 to 3F (or is that 1F?) |
E1 | 0=cursor off, 1 = cursor on |
E2 E5 | Misc. Workspace |
E6 | Number of lines
remaining (1-16) if VDU in page mode, bit 7 = 1 if not in page mode. |
E7 | Bits 5,6,= 1 for shift lock, else 0 |
E8 E9 | Misc. Workspace |
EA | 'Nomon' if not zero |
EB FD | Misc. Workspace for COS |
FE | Character not sent to printer (normally 0A = Line Feed) |
100 13F | Input line buffer |
140 17F | String processing area |
180 1FF | Stack |
200 201 | Ptr. to NMI routine; not set by COS or BASIC |
202 203 | Ptr. to BRK routine; normally C9D8 |
204 205 | Ptr. to IRQ routine; normally A000 (Utility ROM) |
206 207 | Ptr. to Command Line Interpreter, normally F8EF |
208 209 | Ptr. to Write Char. routine, normally FE52 |
20A 20B | Ptr. to Read Char. routine, normally FE94 |
20C 20D | Ptr. to Load File routine, normally FE6E |
20E 20E | Ptr. to Save File routine, normally FAE5 |
210 211 | Ptr. to RDRVEC routine, normally |
212 213 | Ptr. to STRVEC routine, normally |
214 215 | Ptr. to GetTapeByte routine, normally |
216 217 | Ptr. to PutTapeByte routine, normally |
218 219 | Ptr. to PrintTapeMessage routine, normally |
21A 21B | Ptr. to Shut file routine, normally |
21C 23F | Free |
240 2EA | Misc. Workspace for BASIC |
2EB 320 | Pointers to arrays: 2EB,306 = AA; 2EC,307 = BB etc. |
321 | Integer Variable |
322 33C | Low byte of variables A-Z |
33E 357 | 2nd byte of variables A-Z |
359 371 | 3rd byte of variables A-Z |
373 38C | High byte of variables A-Z |
38D 3C0 | Labels; 38D, 38E is
RAM address of label a, 38F, 340 is RAM address of label b, etc. |
3C1 3FD | Misc. Workspace for BASIC |
3FE 3FF | Ptr. to point plot
routine F6E2 for mode 0, F73B for mode 1, F754 for mode 2, F76D for mode 3, F7AA for mode 4, |
The following addresses (except for C2F2, C8E6, FFFA, FFFC and FFFE) are the entry points for some useful routines in BASIC and COS. Note that most are not documented by Acorn, and so may change in future ROMs.
Address | |
C2F2 | Entry point for BASIC
interpreter; locations 5 and 6 should point to the start of the BASIC program |
C278 | File Shut - just RTS |
C589 | Print4-byte binary integer from #16,#25,#34, #43 (MSB) |
C8E6 | Auto start address for routine loaded from tape. |
C9D8 | BRK service routine;
retrieves PC from stack, stores it in 0, then goes to BASIC routine pointed to by 10,11 (normally C9E7) |
F6E2 | Plot mode 0 |
F73B | Plot mode 1 |
F754 | Plot mode 2 |
F76D | Plot mode 3 |
F7AA | Plot mode 4. See block zero RAM |
F7D1 | Output ASCII string
from the calling routine following 'JSR F7D1'. Returns calling routine at first byte with bit 7 = 1. Uses A,X,Y. |
F802 | Print A as two hex digits. A destroyed. |
F87E | Convert ASCII hex
char in A to binary. A destroyed. Returns C=1 if char was not ASCII '0' to '9' |
F89E | Converts ASCII hex
string at 0100,Y to 16 bit binary in 0,X and 1,X. Uses
2,X. Destroys A. Returns with Y pointing to first non-hex character, Z=1 if first character is not ASCII '0' to '9' |
F8EF | Interpret string starting at 0100 as an Operating System command. Uses all registers. Legal commands are: 'CAT', 'LOAD', 'SAVE', 'RUN', 'MON', 'NOMON', 'FLOAD' and 'DOS'. The latter causes a jump to E000 |
F96E | Load cassette file. Enter with X pointing to the first of five data bytes in zero page RAM; 0,X and 1,X pointing to the file name string, 2,X and 3,X pointing to the first byte to be loaded. 4,X bit 7 should be 0 to use the file's start address |
FAE5 | Save cassette file. Enter with X pointing to the first of 10 data bytes in zero page RAM; 0,X and 1,X pointing to the file name string, 2,X and 3,X pointing to the reload address 4,X and 5,X pointing to the execution address 6,X and 7,X pointing to the first byte to be saved 8,X and 9,X pointing to the last byte to be saved plus one |
FB83 | Wait X/60 seconds. Returns with X=0. Other registers preserved |
FBEE | Get byte from tape,
return with it in A. X and Y preserved Byte added to checksum at 00DC |
FC38 | Prints 'PLAY TAPE' if
flag C=1, or 'RECORD TAPE' if C=0. Then waits for a key press before returning. Returns with A=13, X and Y destroyed. |
FC40 | Prints 'REWIND TAPE',
then waits for a key press before returning with A=13. X and Y destroyed. |
FC7C | Put byte to tape. All registers preserved. Byte added to checksum at 00DC. |
FD1A | Bleep. All registers destroyed. |
FD44 | Invert character at
current cursor position. See page zero RAM locations DE to E0. A and Y destroyed. |
FE52 | Write ASCII character
in A to printer and VDU (if enabled). Control characters recognised and acted upon. All registers preserved. |
FE55 | As FE52 but does not write to printer. |
FE66 | Wait for start of VDU fly-back (blanking) period. All registers preserved. |
FE71 | Scan key (except for
CTRL, SHIFT, RPT and BRK). Returns with flag C-1 if no key pressed, else C=0 and Y = key number. All registers destroyed. |
FE94 | Wait for key press then return with its ASCII code in A. X and Y preserved. |
FEFB | Write ASCII character
in A to printer (if enabled). If A=02 (STX), enable printer. If A=03 (ETX), disable printer. All registers preserved. |
FFCB | OSSHUT; normally calls C278 (RTS) |
FFCE | OSFIND; normally calls FC38 |
FFD1 | OSBPUT; normally calls FC7C |
FFD4 | OSBGET; normally calls FBEE |
FFDD | OSSAVE; normally calls FAE5 |
FFE0 | OSLOAD; normally calls F96E |
FFE3 | OSRDCH; normally calls FE94 |
FFE6 | OSECHO; normally calls FE94 then FE52 |
FFE9 | OSASCI; normally calls FE52 |
FFED | OSCRLF; normally calls FE52 to print CR/LF |
FFF7 | OSCLI; normally calls F8EF |
FFFA | NMI vector; normally contains FFC7 |
FFFC | Reset vector; normally contains FF3F |
FFFE | IRQ/BRK vector; normally contains FFB2 |
Note: #C014 input routine in #100. Y register must be zero.
00 | @ | 01 | A | 02 | B | 03 | C | 04 | D | 05 | E | 06 | F | 07 | G |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
08 | H | 09 | I | 0A | J | 0B | K | 0C | L | 0D | M | 0E | N | 0F | O |
10 | P | 11 | Q | 12 | R | 13 | S | 14 | T | 15 | U | 16 | V | 17 | W |
18 | X | 19 | Y | 1A | Z | 1B | [ | 1C | \ | 1D | ] | 1E | ^ | 1F | ` |
20 | 21 | ! | 22 | " | 23 | # | 24 | $ | 25 | % | 26 | & | 27 | ' | |
28 | ( | 29 | ) | 2A | * | 2B | + | 2C | , | 2D | - | 2E | . | 2F | / |
30 | 0 | 31 | 1 | 32 | 2 | 33 | 3 | 34 | 4 | 35 | 5 | 36 | 6 | 37 | 7 |
38 | 8 | 39 | 9 | 3A | : | 3B | ; | 3C | < | 3D | = | 3E | > | 3F | ? |
40 | 41 | | 42 | | 43 | | 44 | | 45 | | 46 | | 47 | | |
48 | | 49 | | 4A | | 4B | | 4C | | 4D | | 4E | | 4F | |
50 | | 51 | | 52 | | 53 | | 54 | | 55 | | 56 | | 57 | |
58 | | 59 | | 5A | | 5B | | 5C | | 5D | | 5E | | 5F | |
60 | | 61 | | 62 | | 63 | | 64 | | 65 | | 66 | | 67 | |
68 | | 69 | | 6A | | 6B | | 6C | | 6D | | 6E | | 6F | |
70 | | 71 | | 72 | | 73 | | 74 | | 75 | | 76 | | 77 | |
78 | | 79 | | 7A | | 7B | | 7C | | 7D | | 7E | | 7F | |
80 | @ | 81 | A | 82 | B | 83 | C | 84 | D | 85 | E | 86 | F | 87 | G |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
88 | H | 89 | I | 8A | J | 8B | K | 8C | L | 8D | M | 8E | N | 8F | O |
90 | P | 91 | Q | 92 | R | 93 | S | 94 | T | 95 | U | 96 | V | 97 | W |
98 | X | 99 | Y | 9A | Z | 9B | [ | 9C | \ | 9D | ] | 9E | ^ | 9F | ` |
A0 | A1 | ! | A2 | " | A3 | # | A4 | $ | A5 | % | A6 | & | A7 | ' | |
A8 | ( | A9 | ) | AA | * | AB | + | AC | , | AD | - | AE | . | AF | / |
B0 | 0 | B1 | 1 | B2 | 2 | B3 | 3 | B4 | 4 | B5 | 5 | B6 | 6 | B7 | 7 |
B8 | 8 | B9 | 9 | BA | : | BB | ; | BC | < | BD | = | BE | > | BF | ? |
C0 | C1 | | C2 | | C3 | | C4 | | C5 | | C6 | | C7 | | |
C8 | | C9 | | CA | | CB | | CC | | CD | | CE | | CF | |
D0 | | D1 | | D2 | | D3 | | D4 | | D5 | | D6 | | D7 | |
D8 | | D9 | | DA | | DB | | DC | | DD | | DE | | DF | |
E0 | | E1 | | E2 | | E3 | | E4 | | E5 | | E6 | | E7 | |
E8 | | E9 | | EA | | EB | | EC | | ED | | EE | | EF | |
F0 | | F1 | | F2 | | F3 | | F4 | | F5 | | F6 | | F7 | |
F8 | | F9 | | FA | | FB | | FC | | FD | | FE | | FF | |
Original scans, OCR, quick proof reading and initial separate HTML pages by Keith Howell
Markup & layout tidying, additional content, images and thorough proof reading by Phil Mainwaring
All source code added from tested versions in AtomMMC library by Phil Mainwaring
AtomMMC versions entered and edited by David Banks and the other good peeps over at the StarDot forums