Add first C64 BASIC program collection

This commit is contained in:
Christian Johannesen 2026-10-07 20:03:59 +02:00
commit f5c2c05b40
21 changed files with 282 additions and 0 deletions

48
README.md Normal file
View file

@ -0,0 +1,48 @@
# C64 BASIC Collection
Ten small, polished programs for the Commodore 64, written entirely in stock
Commodore BASIC V2. The collection mixes arcade action, puzzles, simulations,
creative tools, sound, and visual effects. No cartridge, BASIC extension, or
machine-language payload is required.
## Programs
| Program | Type | Controls | Description |
| --- | --- | --- | --- |
| [Meteor Dodge](meteor-dodge/meteor-dodge.bas) | Arcade | `A`, `D`, `Q` | Dodge falling meteors and build your score. |
| [Code Breaker](code-breaker/code-breaker.bas) | Logic | Digits, `Q` | Deduce a four-digit secret in ten guesses. |
| [Submarine Hunt](submarine-hunt/submarine-hunt.bas) | Strategy | Coordinates, `Q` | Find three hidden submarines with limited sonar shots. |
| [Lunar Lander](lunar-lander/lunar-lander.bas) | Simulation | `0`-`9`, `Q` | Choose engine burns and touch down gently. |
| [Memory Matrix](memory-matrix/memory-matrix.bas) | Memory | `1`-`4`, `Q` | Repeat a growing sequence of flashing quadrants. |
| [Robot Maze](robot-maze/robot-maze.bas) | Puzzle | `W`, `A`, `S`, `D`, `Q` | Navigate a freshly generated maze to its exit. |
| [Music Box](music-box/music-box.bas) | Music | `A`-`K`, `1`-`3`, `Q` | Play the SID chip as a small computer keyboard. |
| [Pixel Painter](pixel-painter/pixel-painter.bas) | Creative | Cursor keys, Space, `C`, `Q` | Draw character-cell pictures on the screen. |
| [Stock Trader](stock-trader/stock-trader.bas) | Simulation | `B`, `S`, `W`, `Q` | Trade a volatile stock over twenty market days. |
| [Starfield](starfield/starfield.bas) | Demo | `1`-`3`, `Q` | Watch and control a layered animated starfield. |
## Running the programs
Each directory contains an editable, line-numbered `.bas` listing and a matching
tokenized `.prg` file. The PRGs use the normal C64 BASIC load address, `$0801`.
On a Commodore 64, transfer a PRG to disk or another supported medium, then use:
```text
LOAD"METEOR-DODGE.PRG",8
RUN
```
Substitute the filename and device number as needed. In VICE or another C64
emulator, drag a PRG into the emulator window or use its autostart command.
## Source format
The `.bas` files are plain ASCII for comfortable reading and editing on a modern
computer. They use uppercase BASIC V2 keywords and avoid embedded control-code
glyphs. Their corresponding `.prg` files contain the tokenized PETSCII program
that the C64 loads directly.
All programs are self-contained and designed for an ordinary PAL or NTSC
Commodore 64. Randomized programs seed BASIC's random-number generator from the
machine clock, so every session is different.

View file

@ -0,0 +1,23 @@
10 PRINT CHR$(147):PRINT " CODE BREAKER":PRINT
20 PRINT "GUESS THE FOUR DIFFERENT DIGITS.":PRINT "RIGHT PLACE = HIT, WRONG PLACE = NEAR":PRINT
30 PRINT "PRESS ANY KEY":GET A$:IF A$="" THEN 30
35 R=RND(-TI)
40 DIM C(4),G(4),U(9):FOR I=1 TO 4
50 C(I)=INT(RND(1)*10):IF U(C(I)) THEN 50
60 U(C(I))=1:NEXT:PRINT CHR$(147)
70 FOR T=1 TO 10:PRINT "GUESS";T;"OF 10 (OR Q)";:INPUT G$
80 IF G$="Q" THEN 190
90 IF LEN(G$)<>4 THEN PRINT "ENTER FOUR DIGITS.":GOTO 70
100 FOR I=1 TO 4:G(I)=ASC(MID$(G$,I,1))-48:IF G(I)<0 OR G(I)>9 THEN PRINT "DIGITS ONLY.":GOTO 70
110 NEXT:H=0:N=0
120 FOR I=1 TO 4:IF G(I)=C(I) THEN H=H+1
130 FOR J=1 TO 4:IF I<>J AND G(I)=C(J) THEN N=N+1
140 NEXT J,I:PRINT H;"HIT ";N;"NEAR":PRINT
150 IF H=4 THEN PRINT "CODE BROKEN IN";T;"GUESSES!":GOTO 180
160 NEXT
170 PRINT "THE CODE WAS";:FOR I=1 TO 4:PRINT C(I);:NEXT:PRINT
180 PRINT:PRINT "R=REPLAY Q=QUIT"
190 GET A$:IF A$="R" THEN RUN
200 IF A$<>"Q" THEN 190
210 PRINT CHR$(147):END

Binary file not shown.

View file

@ -0,0 +1,20 @@
10 PRINT CHR$(147):PRINT " LUNAR LANDER":PRINT
20 PRINT "EACH TURN CHOOSE BURN 0 TO 9.":PRINT "LAND AT SPEED 3 OR LESS.":PRINT:PRINT "PRESS ANY KEY"
30 GET A$:IF A$="" THEN 30
40 H=100:V=0:F=50:T=0
50 PRINT CHR$(147):PRINT "ALTITUDE";INT(H):PRINT "SPEED ";INT(V*10)/10:PRINT "FUEL ";F:PRINT
60 PRINT "BURN (0-9, OR -1 TO QUIT)";:INPUT B
70 IF B=-1 THEN 180
80 IF B<0 OR B>9 OR B>F THEN PRINT "INVALID BURN.":GOTO 60
90 F=F-B:V=V+2-B*.45:H=H-V:T=T+1
100 FOR I=1 TO 12:PRINT:PRINT TAB(19);"*":NEXT
110 IF H>0 THEN 50
120 PRINT CHR$(147):PRINT "TOUCHDOWN SPEED";INT(ABS(V)*10)/10:PRINT
130 IF ABS(V)<=3 THEN PRINT "PERFECT LANDING, COMMANDER!":GOTO 170
140 IF ABS(V)<=6 THEN PRINT "ROUGH LANDING. THE CREW IS SAFE.":GOTO 170
150 PRINT "CRASH! A NEW CRATER APPEARS."
170 PRINT:PRINT "R=REPLAY Q=QUIT"
180 GET A$:IF A$="R" THEN RUN
190 IF A$<>"Q" THEN 180
200 PRINT CHR$(147):END

Binary file not shown.

View file

@ -0,0 +1,25 @@
10 PRINT CHR$(147):PRINT " MEMORY MATRIX":PRINT
20 PRINT "WATCH THE NUMBERS, THEN REPEAT THEM.":PRINT "THE PATTERN GROWS EVERY ROUND."
25 PRINT:PRINT "PRESS ANY KEY"
30 GET A$:IF A$="" THEN 30
35 R=RND(-TI)
40 DIM S(30):L=1:FOR I=1 TO 30:S(I)=INT(RND(1)*4)+1:NEXT
50 PRINT CHR$(147):PRINT "ROUND";L:FOR I=1 TO L:GOSUB 130:NEXT
60 FOR D=1 TO 250:NEXT:PRINT CHR$(147)
70 FOR I=1 TO L:PRINT "STEP";I;" (1-4, Q QUITS)";
80 GET A$:IF A$="" THEN 80
90 IF A$="Q" THEN 180
100 IF VAL(A$)<>S(I) THEN PRINT:PRINT "WRONG! SCORE";L-1:GOTO 170
110 PRINT A$:NEXT:L=L+1:IF L<=30 THEN 50
120 PRINT "AMAZING! YOU COMPLETED ALL 30.":GOTO 170
130 PRINT CHR$(147):PRINT:PRINT:PRINT
140 IF S(I)=1 THEN PRINT " 1111":PRINT " 1111"
145 IF S(I)=2 THEN PRINT " 2222":PRINT " 2222"
150 IF S(I)=3 THEN PRINT:PRINT:PRINT " 3333":PRINT " 3333"
155 IF S(I)=4 THEN PRINT:PRINT:PRINT " 4444":PRINT " 4444"
160 FOR D=1 TO 220:NEXT:PRINT CHR$(147):FOR D=1 TO 60:NEXT:RETURN
170 PRINT:PRINT "R=REPLAY Q=QUIT"
180 GET A$:IF A$="R" THEN RUN
190 IF A$<>"Q" THEN 180
200 PRINT CHR$(147):END

Binary file not shown.

View file

@ -0,0 +1,25 @@
10 PRINT CHR$(147):POKE 53280,0:POKE 53281,0
20 PRINT " METEOR DODGE":PRINT:PRINT " A=LEFT D=RIGHT Q=QUIT"
25 PRINT:PRINT " PRESS ANY KEY"
30 GET A$:IF A$="" THEN 30
35 R=RND(-TI)
40 DIM X(5),Y(5):FOR I=1 TO 5:X(I)=INT(RND(1)*38)+1:Y(I)=-I*4:NEXT
50 P=20:S=0:L=3:PRINT CHR$(147)
60 GET A$:IF A$="A" AND P>1 THEN P=P-1
70 IF A$="D" AND P<38 THEN P=P+1
80 IF A$="Q" THEN 190
90 FOR I=1 TO 5:IF Y(I)>=0 THEN POKE 1024+Y(I)*40+X(I),32
100 Y(I)=Y(I)+1:IF Y(I)>22 THEN Y(I)=0:X(I)=INT(RND(1)*38)+1:S=S+1
110 IF Y(I)=22 AND ABS(X(I)-P)<2 THEN L=L-1:Y(I)=0:X(I)=INT(RND(1)*38)+1
120 IF Y(I)>=0 THEN POKE 1024+Y(I)*40+X(I),42:POKE 55296+Y(I)*40+X(I),8
125 NEXT
130 POKE 1024+22*40+P,1:POKE 55296+22*40+P,1
140 PRINT CHR$(19);" SCORE";S;" SHIELDS";L;" "
150 FOR D=1 TO 55:NEXT:POKE 1024+22*40+P,32
160 IF L>0 THEN 60
170 PRINT CHR$(147):PRINT "FINAL SCORE:";S:PRINT
180 PRINT "R=REPLAY Q=QUIT"
190 GET A$:IF A$="R" THEN RUN
200 IF A$<>"Q" THEN 190
210 POKE 53280,14:POKE 53281,6:PRINT CHR$(147):END

Binary file not shown.

23
music-box/music-box.bas Normal file
View file

@ -0,0 +1,23 @@
10 PRINT CHR$(147):PRINT " MUSIC BOX":PRINT
20 PRINT "PLAY NOTES WITH A S D F G H J K":PRINT "1=SQUARE 2=SAW 3=TRIANGLE Q=QUIT":PRINT
30 S=54272:FOR I=0 TO 24:POKE S+I,0:NEXT:POKE S+5,9:POKE S+6,240:POKE S+24,15
40 W=65:DIM F(8):F(1)=4291:F(2)=4817:F(3)=5407:F(4)=5730
45 F(5)=6434:F(6)=7217:F(7)=8103:F(8)=8581
50 GET A$:IF A$="" THEN 50
60 IF A$="Q" THEN 160
70 IF A$="1" THEN W=65:PRINT "SQUARE WAVE":GOTO 50
80 IF A$="2" THEN W=33:PRINT "SAW WAVE":GOTO 50
90 IF A$="3" THEN W=17:PRINT "TRIANGLE WAVE":GOTO 50
100 N=0:IF A$="A" THEN N=1
105 IF A$="S" THEN N=2
110 IF A$="D" THEN N=3
115 IF A$="F" THEN N=4
120 IF A$="G" THEN N=5
125 IF A$="H" THEN N=6
130 IF A$="J" THEN N=7
135 IF A$="K" THEN N=8
140 IF N=0 THEN 50
145 POKE S,F(N)-INT(F(N)/256)*256:POKE S+1,INT(F(N)/256):POKE S+4,W
150 FOR D=1 TO 80:NEXT:POKE S+4,W-1:GOTO 50
160 FOR I=0 TO 24:POKE S+I,0:NEXT:PRINT CHR$(147):END

BIN
music-box/music-box.prg Normal file

Binary file not shown.

View file

@ -0,0 +1,17 @@
10 PRINT CHR$(147):POKE 53280,11:POKE 53281,0
20 PRINT "PIXEL PAINTER - CURSORS MOVE, SPACE DRAWS":PRINT "C=CLEAR Q=QUIT":PRINT "PRESS ANY KEY"
30 GET A$:IF A$="" THEN 30
40 PRINT CHR$(147):X=20:Y=12:D=1
50 P=1024+Y*40+X:O=PEEK(P):POKE P,160:POKE 55296+Y*40+X,1
60 GET A$:IF A$="" THEN 60
70 POKE P,O:NX=X:NY=Y
80 IF ASC(A$)=145 AND Y>0 THEN NY=Y-1
90 IF ASC(A$)=17 AND Y<24 THEN NY=Y+1
100 IF ASC(A$)=157 AND X>0 THEN NX=X-1
110 IF ASC(A$)=29 AND X<39 THEN NX=X+1
120 IF A$=" " THEN POKE P,160:O=160:GOTO 150
130 IF A$="C" THEN PRINT CHR$(147):O=32:GOTO 50
140 IF A$="Q" THEN 180
150 X=NX:Y=NY:GOTO 50
180 POKE 53280,14:POKE 53281,6:PRINT CHR$(147):END

Binary file not shown.

33
robot-maze/robot-maze.bas Normal file
View file

@ -0,0 +1,33 @@
10 PRINT CHR$(147):PRINT " ROBOT MAZE":PRINT
20 PRINT "REACH E. MOVE WITH W A S D.":PRINT "THE MAZE CHANGES EVERY GAME."
25 PRINT:PRINT "PRESS ANY KEY"
30 GET A$:IF A$="" THEN 30
35 R=RND(-TI)
40 DIM M(19,19):FOR Y=1 TO 19:FOR X=1 TO 19:M(X,Y)=1:NEXT X,Y
50 X=2:Y=2:M(X,Y)=0:FOR I=1 TO 160:D=INT(RND(1)*4):NX=X:NY=Y
60 IF D=0 THEN NX=X+1
70 IF D=1 THEN NX=X-1
80 IF D=2 THEN NY=Y+1
90 IF D=3 THEN NY=Y-1
100 IF NX<2 OR NX>18 OR NY<2 OR NY>18 THEN 50
110 X=NX:Y=NY:M(X,Y)=0:NEXT:FOR I=2 TO 18:M(I,2)=0:M(18,I)=0:NEXT:X=2:Y=2
120 PRINT CHR$(147):FOR J=1 TO 19:FOR I=1 TO 19
130 IF I=X AND J=Y THEN PRINT "R";:GOTO 160
140 IF I=18 AND J=18 THEN PRINT "E";:GOTO 160
150 IF M(I,J) THEN PRINT "#";:GOTO 160
155 PRINT " ";
160 NEXT:PRINT:NEXT:PRINT "WASD MOVE, Q QUITS"
170 GET A$:IF A$="" THEN 170
180 NX=X:NY=Y:IF A$="W" THEN NY=Y-1
190 IF A$="S" THEN NY=Y+1
200 IF A$="A" THEN NX=X-1
210 IF A$="D" THEN NX=X+1
220 IF A$="Q" THEN 280
230 IF M(NX,NY)=0 THEN X=NX:Y=NY
240 IF X<>18 OR Y<>18 THEN 120
250 PRINT CHR$(147):PRINT "THE ROBOT FOUND THE EXIT!":PRINT
260 PRINT "R=REPLAY Q=QUIT"
280 GET A$:IF A$="R" THEN RUN
290 IF A$<>"Q" THEN 280
300 PRINT CHR$(147):END

BIN
robot-maze/robot-maze.prg Normal file

Binary file not shown.

16
starfield/starfield.bas Normal file
View file

@ -0,0 +1,16 @@
10 PRINT CHR$(147):POKE 53280,0:POKE 53281,0
20 PRINT " STARFIELD":PRINT:PRINT "1=SLOW 2=MEDIUM 3=FAST Q=QUIT"
25 PRINT:PRINT "PRESS ANY KEY"
30 GET A$:IF A$="" THEN 30
35 R=RND(-TI)
40 DIM X(30),Y(30),Z(30):FOR I=1 TO 30:X(I)=INT(RND(1)*40)
45 Y(I)=INT(RND(1)*24):Z(I)=INT(RND(1)*3)+1:NEXT:V=2:PRINT CHR$(147)
50 FOR I=1 TO 30:P=1024+Y(I)*40+X(I):POKE P,32
60 X(I)=X(I)+Z(I)*V:IF X(I)>39 THEN X(I)=0:Y(I)=INT(RND(1)*24):Z(I)=INT(RND(1)*3)+1
70 P=1024+Y(I)*40+X(I):POKE P,46:POKE 55296+Y(I)*40+X(I),Z(I)+10
80 NEXT
90 GET A$:IF A$="1" THEN V=1
100 IF A$="2" THEN V=2
110 IF A$="3" THEN V=3
120 IF A$<>"Q" THEN 50
130 POKE 53280,14:POKE 53281,6:PRINT CHR$(147):END

BIN
starfield/starfield.prg Normal file

Binary file not shown.

View file

@ -0,0 +1,25 @@
10 PRINT CHR$(147):PRINT " STOCK TRADER":PRINT
20 PRINT "MAKE THE MOST MONEY IN 20 DAYS.":PRINT "B=BUY S=SELL W=WAIT Q=QUIT"
25 PRINT:PRINT "PRESS ANY KEY"
30 GET A$:IF A$="" THEN 30
35 R=RND(-TI)
40 C=1000:N=0:P=50:FOR D=1 TO 20
50 P=P+INT(RND(1)*21)-10:IF P<5 THEN P=5
60 PRINT CHR$(147):PRINT "DAY";D;"OF 20":PRINT "PRICE $";P:PRINT "CASH $";C
65 PRINT "SHARES ";N:PRINT "VALUE $";C+N*P
70 PRINT:PRINT "B, S, W, OR Q?"
80 GET A$:IF A$="" THEN 80
90 IF A$="Q" THEN 180
100 IF A$="W" THEN 150
110 IF A$="B" THEN PRINT "HOW MANY";:INPUT Q:IF Q>=0 AND Q*P<=C THEN C=C-Q*P:N=N+Q:GOTO 150
120 IF A$="S" THEN PRINT "HOW MANY";:INPUT Q:IF Q>=0 AND Q<=N THEN C=C+Q*P:N=N-Q:GOTO 150
130 PRINT "TRADE NOT POSSIBLE.":FOR T=1 TO 500:NEXT:GOTO 70
150 NEXT:C=C+N*P:N=0:PRINT CHR$(147):PRINT "MARKET CLOSED.":PRINT "FINAL WEALTH $";C
160 IF C>=1500 THEN PRINT "WALL STREET LEGEND!"
165 IF C>=1000 AND C<1500 THEN PRINT "A SOLID PROFIT."
170 IF C<1000 THEN PRINT "BETTER LUCK NEXT MARKET."
175 PRINT:PRINT "R=REPLAY Q=QUIT"
180 GET A$:IF A$="R" THEN RUN
190 IF A$<>"Q" THEN 180
200 PRINT CHR$(147):END

Binary file not shown.

View file

@ -0,0 +1,27 @@
10 PRINT CHR$(147):PRINT " SUBMARINE HUNT":PRINT
20 PRINT "THREE SUBS HIDE IN AN 8 BY 8 SEA.":PRINT "ENTER ROW,COLUMN. YOU HAVE 15 SHOTS.":PRINT
25 R=RND(-TI)
30 DIM S(8,8),F(8,8):FOR I=1 TO 3
40 R=INT(RND(1)*8)+1:C=INT(RND(1)*8)+1:IF S(R,C) THEN 40
50 S(R,C)=1:NEXT:H=0
60 FOR T=1 TO 15:GOSUB 150:PRINT "SHOT";T;" ROW,COLUMN (0,0 QUITS)";:INPUT R,C
70 IF R=0 AND C=0 THEN 210
80 IF R<1 OR R>8 OR C<1 OR C>8 THEN PRINT "OUTSIDE THE SEA.":GOTO 60
90 IF F(R,C) THEN PRINT "ALREADY CHECKED.":GOTO 60
100 F(R,C)=1:IF S(R,C) THEN H=H+1:PRINT "DIRECT HIT!":GOTO 120
110 PRINT "MISS. SONAR RANGE";:GOSUB 190:PRINT D
120 IF H=3 THEN PRINT "ALL SUBMARINES FOUND!":GOTO 200
130 NEXT:PRINT "OUT OF SHOTS. THE FLEET ESCAPED."
140 GOTO 200
150 PRINT CHR$(147):PRINT " 1 2 3 4 5 6 7 8":FOR Y=1 TO 8:PRINT Y;" ";
160 FOR X=1 TO 8:IF F(Y,X)=0 THEN PRINT ". ";
170 IF F(Y,X)=1 AND S(Y,X)=0 THEN PRINT "O ";
180 IF F(Y,X)=1 AND S(Y,X)=1 THEN PRINT "X ";
185 NEXT:PRINT:NEXT:PRINT "SUBS";H;"/3":RETURN
190 D=9:FOR Y=1 TO 8:FOR X=1 TO 8:IF S(Y,X)=1 AND F(Y,X)=0 THEN Q=ABS(Y-R)+ABS(X-C):IF Q<D THEN D=Q
195 NEXT X,Y:RETURN
200 PRINT:PRINT "R=REPLAY Q=QUIT"
210 GET A$:IF A$="R" THEN RUN
220 IF A$<>"Q" THEN 210
230 PRINT CHR$(147):END

Binary file not shown.