Yup, it’s another “let’s wire up a SYN6988 board” thing, this time for MMBasic running on the Armmite STM32F407 Module (aka ‘Armmite F4’). This board is also known as the BLACK_F407VE, which also makes a nice little MicroPython platform.
Uh, let’s not dwell too much on how the SYN6988 seems to parse 19:51 as “91 minutes to 20” …
Wiring
SYN6988
Armmite F4
RX
PA09 (COM1 TX)
TX
PA10 (COM1 RX)
RDY
PA08
your choice of 3.3 V and GND connections, of course
Yes, I know it says it’s an XFS5152, but I got a SYN6988 and it seems to be about as reliable a source as one can find. The board is marked YS-V6E-V1.03, and even mentions SYN6988 on the rear silkscreen:
Code
REM SYN6988 speech demo - MMBasic / Armmite F4
REM scruss, 2023-07
OPEN "COM1:9600" AS #5
REM READY line on PA8
SETPIN PA8, DIN, PULLUP
REM you can ignore font/text commands
CLS
FONT 1
TEXT 0,15,"[v1]Hello - this is a speech demo."
say("[v1]Hello - this is a speech demo.")
TEXT 0,30,"[x1]soundy[d]"
say("[x1]soundy[d]"): REM chimes
TEXT 0,45,"The time is "+LEFT$(TIME$,5)+"."
say("The time is "+LEFT$(TIME$,5)+".")
END
SUB say(a$)
LOCAL dl%,maxlof%
REM data length is text length + 2 (for the 1 and 0 bytes)
dl%=2+LEN(a$)
maxlof%=LOF(#5)
REM SYN6988 simple data packet
REM byte 1 : &HFD
REM byte 2 : data length (high byte)
REM byte 3 : data length (low byte)
REM byte 4 : &H01
REM byte 5 : &H00
REM bytes 6-: ASCII string data
PRINT #5, CHR$(&hFD)+CHR$(dl%\256)+CHR$(dl% MOD 256)+CHR$(1)+CHR$(0)+a$;
DO WHILE LOF(#5)<maxlof%
REM pause while sending text
PAUSE 5
LOOP
DO WHILE PIN(PA8)<>1
REM wait until RDY is high
PAUSE 5
LOOP
DO WHILE PIN(PA8)<>0
REM wait until SYN6988 signals READY
PAUSE 5
LOOP
END SUB
The biggest thing that tripped me up was that PicoMite BASIC starts arrays at 0. OPTION BASE 1 fixes that oversight. It would have been nice to have OpenProcessing’s HSV colour space, and an editor that could handle lines longer than 80 characters that didn’t threaten to bomb out if you hit the End key, but it’ll serve.
Source below:
' autumn in canada
' scruss, 2021-11
' a take on my https://openprocessing.org/sketch/995420 for picomite
OPTION base 1
RANDOMIZE TIMER
' *** initialize polar coords of leaf polygon and colour array
DIM leaf_rad(24), leaf_ang(24), px%(24), py%(24)
FOR i=1 TO 24
READ leaf_rad(i)
NEXT i
FOR i=1 TO 24
READ x
leaf_ang(i)=RAD(x)
NEXT i
DIM integer c%(8)
FOR i=1 TO 8
READ r%, g%, b%
c%(i)=RGB(r%,g%,b%)
NEXT i
' *** set up some limits
min_scale%=INT(MIN(MM.HRES, MM.VRES)/8)
max_scale%=INT(MIN(MM.HRES, MM.VRES)/6)
min_angle=-30
max_angle=30
min_x%=min_scale%
min_y%=min_x%
max_x%=MM.HRES - min_x%
max_y%=MM.VRES - min_y%
CLS
TEXT MM.HRES/2, INT(MM.VRES/3), "autumn in canada", "CM"
TEXT MM.HRES/2, INT(MM.VRES/2), "scruss, 2021-11", "CM"
TEXT MM.HRES/2, INT(2*MM.VRES/3), "just watch ...", "CM"
kt%=0
DO
cx% = min_x% + INT(RND * (max_x% - min_x%))
cy% = min_y% + INT(RND * (max_y% - min_y%))
angle = min_angle + RND * (max_angle - min_angle)
sc% = min_scale% + INT(RND * (max_scale% - min_scale%))
col% = 1 + INT(RND * 7)
leaf cx%, cy%, sc%, angle, c%(7), c%(col%)
kt% = kt% + 1
LOOP UNTIL kt% >= 1024
END
SUB leaf x%, y%, scale%, angle, outline%, fill%
FOR i=1 TO 24
px%(i) = INT(x% + scale% * leaf_rad(i) * COS(RAD(angle)+leaf_ang(i)))
py%(i) = INT(y% - scale% * leaf_rad(i) * SIN(RAD(angle)+leaf_ang(i)))
NEXT i
POLYGON 24, px%(), py%(), outline%, fill%
END SUB
' radii
DATA 0.536, 0.744, 0.608, 0.850, 0.719
DATA 0.836, 0.565, 0.589, 0.211, 0.660, 0.515
DATA 0.801, 0.515, 0.660, 0.211, 0.589, 0.565
DATA 0.836, 0.719, 0.850, 0.608, 0.744, 0.536, 1.000
' angles
DATA 270.000, 307.249, 312.110, 353.267, 356.540
DATA 16.530, 18.774, 33.215, 3.497, 60.659, 72.514
DATA 90.000, 107.486, 119.341, 176.503, 146.785, 161.226
DATA 163.470, 183.460, 186.733, 227.890, 232.751, 270.000, 270.000
' leaf colours
DATA 255,0,0, 255,36,0, 255,72,0, 255,109,0
DATA 255,145,0, 255,182,0, 255,218,0, 255,255,0
You could probably use AUTOSAVE and paste the text into the PicoMite REPL. I used an ILI9341 SPI TFT LCD Touch Panel with my Raspberry Pi Pico along with some rather messy breadboard wiring.
Fun fact: the maple leaf polygon points are derived from the official definition of the flag of Canada.
It’s very much a work in progress, but Geoff Graham and Peter Mather’s MMBasic runs nicely on the Raspberry Pi Pico. Development is mostly coordinated on TheBackShed.com forum.
It supports an impressive range of displays and peripherals. The project gives me a very distinct “This is how we do things” vibe, and it’s quite unlike any other Raspberry Pi Pico project.
To show you what MMBasic code looks like, here’s a little demo that uses one of those “Open Smart” LED traffic lights on physical pins 14-16 which cycles through the phases every few seconds:
' traffic light on gp10-12 (green, yellow, red), pins 14-16
' set up ports for output
FOR i=14 TO 16
SETPIN i, DOUT
PIN(i)=0
NEXT i
red=16
amber=15
green=14
DO
' green on for 5 seconds
PIN(red)=0
PIN(green)=1
PAUSE 5000
' amber on for 3 seconds
PIN(green)=0
PIN(amber)=1
PAUSE 3000
' red on for 5 seconds
PIN(amber)=0
PIN(red)=1
PAUSE 5000
LOOP
Paleotronic’s Tetris for Applesoft BASIC is a surprisingly decent version for something that’s written in an interpreted language. It’s not what anyone would call zippy, but it’s not so slow that you want to give up.
Paleotronic want you to type it in, but life’s too short for that. You can play it in your browser on the Internet Archive: Tetris for Applesoft BASIC by Mark Stock
Life’s also too short for correcting OCR errors in BASIC code. Tesseract is hilariously bad at recognizing source code, so I had to go through this several times. AppleCommander’s BASIC Tools was very handy for catching the last of the errors with its variable dump: caught the cases of the TO keyword converted to the variable T0 … and frankly, I am no fan of SmartQuotes when applied to source code, either.
Here’s the source, straight from the interpreter with all its weird spacing:
10 GOSUB 1000
100 W = W +1: IF W >LV THEN W = 0: GOSUB 350
110 K = PEEK(KB): IF K > = H THEN POKE KC,H:K = K -H: GOSUB 300
190 GOTO 100
200 PY = PY *A2: VLIN PY,PY +A1 AT PX: RETURN
225 PY = PY *A2: HLIN X1,X2 AT PY: HLIN X1,X2 AT PY +A1: RETURN
300 ON E(K) GOTO 30000,330,340,350,360,30100
310 RETURN
330 X = X -1: GOTO 400
340 X = X +1: GOTO 400
350 DN = 1:Y = Y +1: GOSUB 400:DN = 0: RETURN
360 S = S +1: IF S/4 = INT(S/4) THEN S = S -4
400 GOSUB 500
410 GOSUB 800: IF F = 0 THEN X = XX:Y = YY:S = SS: GOSUB 420: IF DN THEN GOSUB 900
420 COLOR= CF: FOR PP = 1 TO 4:PX = X +X(S,PP):PY = Y +Y(S,PP): GOSUB 200: NEXT PP:XX = X:YY = Y:SS = S:D = 0: RETURN
500 IF DD THEN RETURN
510 COLOR= CB: FOR PP = 1 TO 4:PX = XX +X(SS,PP):PY = YY +Y(SS,PP): GOSUB 200: NEXT PP:DD = 0: RETURN
800 F = 1: FOR PP = 1 TO 4:PY = Y +Y(SS,PP): ON ( FN PC(X +X(S,PP)) >0) GOTO 805: NEXT PP: RETURN
805 F = 0: RETURN
850 F = 1: RETURN
900 P = 10: GOSUB 30300
905 RN = 0:Y = YM
910 X = XL
920 PY = Y: IF FN PC(X) = CB THEN 950
930 X = X +1: IF X < = XR THEN 920
940 R(RN) = Y:RN = RN +1
950 Y = Y -1: IF Y > = 0 THEN 910
960 IF RN THEN GOSUB 30400
970 Y = 0
980 X = INT((XR -XL)/2) +XL
985 S = INT( RND(1) *NS):CF = C(S):S = S *4
990 GOSUB 800: IF F THEN RETURN
995 GOTO 31000
1000 DIM E(127),X(27,4),Y(27,4),R(40)
1010 TEXT : HOME : GR
1011 PRINT "WELCOME..."
1014 LM = 10
1015 XM = 10:YM = 15
1016 XL = INT((40 -XM)/2)
1017 XR = XL +XM -1
1021 A1 = 1
1022 A2 = 2
1030 DEF FN PC(X) = SCRN( X,PY *A2)
1040 CB = 0
1050 XX = 20:YY = 0:SS = 0
1100 KB = -16384
1110 KC = -16368
1120 H = 128
1129 REM KEYBOARD ACTIONS
1130 REM QUIT
1131 E( ASC("Q")) = 1
1132 E( ASC("Q") -64) = 1
1140 REM MOVE LEFT
1141 E(8) = 2
1142 E( ASC(",")) = 2
1150 REM MOVE RIGHT
1151 E(21) = 3
1152 E( ASC(".")) = 3
1160 REM MOVE DOWN
1161 E(32) = 4
1162 E( ASC("Z")) = 4
1170 REM ROTATE
1171 E( ASC("R")) = 5
1172 E(13) = 5
1173 E( ASC("A")) = 5
1179 REM PAUSE GAME
1180 E( ASC("P")) = 6
1181 E( ASC("P") -64) = 6
1185 GOSUB 2000
1186 GOSUB 1300
1190 PRINT "PRESS ANY KEY TO START..."
1191 PRINT
1192 PRINT "PRESS Q TO QUIT."
1193 GOTO 31020
1299 REM DRAW THE GAME
1300 COLOR= 4: FOR I = 0 TO 19:X1 = 0:X2 = 39:PY = I: GOSUB 225: NEXT
1320 COLOR= CB: FOR I = 0 TO YM:X1 = XL:X2 = XR:PY = I: GOSUB 225: NEXT
1350 RETURN
1400 DATA 1
1401 DATA 0,0,1,0,0,1,1,1
1402 DATA 0,0,1,0,0,1,1,1
1403 DATA 0,0,1,0,0,1,1,1
1404 DATA 0,0,1,0,0,1,1,1
1410 DATA 2
1411 DATA 0,1,1,1,2,1,3,1
1412 DATA 1,0,1,1,1,2,1,3
1413 DATA 0,1,1,1,2,1,3,1
1414 DATA 1,0,1,1,1,2,1,3
1420 DATA 12
1421 DATA 1,1,0,1,1,0,2,1
1422 DATA 1,1,0,1,1,0,1,2
1423 DATA 1,1,0,1,2,1,1,2
1424 DATA 1,1,1,0,2,1,1,2
1430 DATA 13
1431 DATA 1,1,0,1,2,1,0,2
1432 DATA 1,1,1,0,1,2,2,2
1433 DATA 1,1,0,1,2,1,2,0
1434 DATA 1,1,1,0,1,2,0,0
1440 DATA 9
1441 DATA 1,1,0,1,2,1,2,2
1442 DATA 1,1,1,0,1,2,2,0
1443 DATA 1,1,0,1,2,1,0,0
1444 DATA 1,1,1,0,1,2,0,2
1450 DATA 3
1451 DATA 1,1,1,0,0,0,2,1
1452 DATA 1,1,1,0,0,1,0,2
1453 DATA 1,1,1,0,0,0,2,1
1454 DATA 1,1,1,0,0,1,0,2
1460 DATA 6
1461 DATA 1,1,0,1,1,0,2,0
1462 DATA 1,1,0,1,0,0,1,2
1463 DATA 1,1,0,1,1,0,2,0
1464 DATA 1,1,0,1,0,0,1,2
1990 DATA -1
2000 X = 0:Y = 0
2010 NS = 0
2020 READ C: IF C < > -1 THEN C(NS) = C: FOR J = 0 TO 3: FOR I = 1 TO 4: READ X(NS *4 +J,I): READ Y(NS *4 +J,I): NEXT I: NEXT J:NS = NS +1: GOTO 2020
2030 RETURN
21210 P = 1: RETURN
30000 TEXT : HOME : END
30100 HOME
30110 PRINT "GAME PAUSED. PRESS P TO CONTINUE..."
30120 P = 1
30130 K = PEEK(KB): IF K > = H THEN POKE KC,H:K = K -H: GOSUB 30200
30140 IF P THEN 30130
30150 HOME
30160 PRINT "SCORE ";SC; TAB( 21);"LEVEL ";LM -LV +1
30170 RETURN
30200 ON E(K) GOTO 30000,30210,30210,30210,30210,30220
30210 RETURN
30220 P = 0
30230 RETURN
30300 SC = SC +P
30310 VTAB 21: HTAB 7
30320 PRINT SC;
30330 RETURN
30400 RN = RN -1
30410 FOR C = 0 TO 32
30415 COLOR= C
30420 FOR I = 0 TO RN:X1 = XL:X2 = XR:PY = R(I): GOSUB 225: NEXT I
30430 FOR I = 0 TO 2: NEXT I
30440 NEXT C
30450 FOR I = 0 TO RN
30460 Y = R(I) +I
30470 YP = Y -1: FOR X = XL TO XR:PY = YP: COLOR= FN PC(X):PX = X:PY = Y: GOSUB 200: NEXT X:Y = Y -1: IF Y >0 THEN 30470
30480 P = 100: GOSUB 30300
30490 NEXT I
30495 RETURN
31000 VTAB 22: PRINT
31010 PRINT " GAME OVER"
31020 P = 1
31030 K = PEEK(KB): IF K > = H THEN POKE KC,H:K = K -H: GOSUB 31200
31040 IF P THEN 31030
31050 D = 1
31060 SC = 0:LV = LM
31070 GOSUB 30150
31080 GOSUB 1300
31090 GOTO 905
31200 ON E(K) GOTO 30000
31210 P = 0: RETURN
32000 REM END OF LISTING
If only AppleSoft had a RENUM command, the code might not look so messy
Almost no-one will need this knowledge, but I might need to remember it. In order to add Mini PPISD support to a RomWBW 3.01-supported system, you need to create a file called something like Source/HBIOS/Config/ZETA2_ppisd.asm (for yes, I’m using a Zeta SBC V2) containing:
Running make from the top-level directory should create a ROM image called Binary/ZETA2_ppisd.rom for you to write to flash. Since my floppy drive isn’t feeling too happy, I had to resort to buying a TL866II Plus programmer to write the chip.
And it worked!
RomWBW HBIOS v3.0.1, 2021-03-12
ZETA V2 Z80 @ 8.000MHz
0 MEM W/S, 1 I/O W/S, INT MODE 2
512KB ROM, 512KB RAM
CTC: MODE=Z2 IO=0x20
UART0: IO=0x68 16550A MODE=38400,8,N,1
DSRTC: MODE=STD IO=0x70 Sun 2021-03-14 17:47:13 CHARGE=OFF
MD: UNITS=2 ROMDISK=384KB RAMDISK=384KB
FD: IO=0x30 UNITS=2
SD: MODE=PPI IO=0x60 DEVICES=1
SD0: SDSC NAME=SD BLOCKS=0x003C7800 SIZE=1935MB
Unit Device Type Capacity/Mode
---------- ---------- ---------------- --------------------
Char 0 UART0: RS-232 38400,8,N,1
Disk 0 MD1: RAM Disk 384KB,LBA
Disk 1 MD0: ROM Disk 384KB,LBA
Disk 2 FD0: Floppy Disk 3.5",DS/HD,CHS
Disk 3 FD1: Floppy Disk 3.5",DS/HD,CHS
Disk 4 SD0: SD Card 1935MB,LBA
ZETA V2 Boot Loader
ROM: (M)onitor (C)P/M (Z)-System (F)orth (B)ASIC (T)-BASIC (P)LAY (U)SER ROM
Disk: (0)MD1 (1)MD0 (2)FD0 (3)FD1 (4)SD0
Boot Selection?
I was pleasantly surprised how easy it is to use a TL866 programmer under Linux. minipro does all the work, though. To write and verify the whole 512K Flash ROM, it’s:
minipro -p SST39SF040 -w ZETA2_ppisd.rom
The programmer supports over 16000 devices, of which around 10000 are variants (form factor, programming voltage, speed, OTP, etc). It’ll also verify over 100 different 74-series logic chips. It’s not a super cheap device (mine was a little over $80, from Simcoe Diy) but it does a lot for that price.
Next stop: try rebuilding BBC BASIC with RomWBW’s timer support included ..
Since I already had a Commodore 64, and seemingly several million other people did too, it seemed like a fair choice to use as the reference system. But the details, so many details …
While the benchmark doesn’t scale well for BASIC running on modern computers — the comparisons between a simple 8-bit processor at a few MHz and a multi-core wildly complex modern CPU at many GHz just aren’t applicable — it turns out I may have one of the fastest 8-bit BASIC computers around in the matchbox-sized shape of the MinZ v1.1 (36.864 Z180, CP/M 2.2, BBC BASIC [Z80] v3):
Oooh blecch — did I really like this when I was a young ‘un? Following on from the same process as in The coolest font (when I was 15, that is) here’s the bitmap font from Level 9’s Snowball.
10 REM *** L9SFONT.BAS ***
15 REM bitmap font from Level 9's
20 REM Snowball text adventure
30 REM on the Amstrad CPC 464
40 REM (it was so cool at the time ...)
50 REM Dug up by scruss, 2020-01
60 REM ==============================
100 SYMBOL AFTER 32
110 MODE 1
120 GOSUB 1000
130 PRINT" *** It's the Level 9 font ***"
140 PRINT" *** from Snowball! ***"
150 PRINT" Dug up by scruss, 2020-01"
160 PRINT
170 PEN 2
180 PRINT"Lorem ipsum dolor sit amet, consectetur"
190 PRINT"adipiscing elit, sed do eiusmod tempor"
200 PRINT"incididunt ut labore et dolore magna"
210 PRINT"aliqua. Ut enim ad minim veniam, quis"
220 PRINT"nostrud exercitation ullamco laboris"
230 PRINT"nisi ut aliquip ex ea commodo consequat"
240 PRINT"arfle barfle gloop? | | |"
250 PRINT
260 PEN 1
270 FOR i%=32 TO 127
280 PRINT CHR$(i%); " ";
290 NEXT i%
300 PRINT
310 PRINT
990 END
1000 SYMBOL 33,&10,&28,&28,&28,&10,0,&38,0
1010 SYMBOL 34,&66,&66,&44,&88,0,0,0,0
1020 SYMBOL 35,0,&24,&7e,&24,&24,&7e,&24,0
1030 SYMBOL 36,&10,&7c,&40,&7c,&04,&7c,&10,0
1040 SYMBOL 37,&e4,&a4,&e8,&10,&2e,&4a,&4e,0
1050 SYMBOL 38,&70,&88,&88,&72,&84,&88,&76,0
1060 SYMBOL 39,&0c,&0c,&08,&10,0,0,0,0
1070 SYMBOL 40,&0c,&10,&30,&30,&20,&14,&0c,0
1080 SYMBOL 41,&30,&28,&04,&0c,&0c,&08,&30,0
1090 SYMBOL 42,&10,&54,&38,&fe,&38,&54,&10,0
1100 SYMBOL 43,0,&10,&10,&7c,&10,&10,0,0
1110 SYMBOL 44,0,0,0,0,&18,&18,&10,&20
1120 SYMBOL 45,0,0,0,&fc,0,0,0,0
1130 SYMBOL 46,0,0,0,0,&1c,&14,&1c,0
1140 SYMBOL 47,0,&06,&0e,&08,&10,&70,&60,0
1150 SYMBOL 48,&fc,&8c,&8c,&84,&c4,&c4,&fc,0
1160 SYMBOL 49,&30,&10,&10,&10,&18,&18,&38,0
1170 SYMBOL 50,&f8,&98,&08,&f8,&80,&c8,&f8,0
1180 SYMBOL 51,&7c,&64,&04,&3c,&34,&04,&7c,0
1190 SYMBOL 52,&c8,&88,&88,&f8,&08,&18,&18,0
1200 SYMBOL 53,&f8,&98,&80,&f0,&08,&c8,&f0,0
1210 SYMBOL 54,&78,&98,&80,&f8,&98,&c8,&f8,0
1220 SYMBOL 55,&fc,&c4,&04,&08,&08,&18,&18,0
1230 SYMBOL 56,&fc,&c4,&8c,&fc,&84,&9c,&fc,0
1240 SYMBOL 57,&fc,&e4,&84,&fc,&04,&0c,&0c,0
1250 SYMBOL 58,&38,&28,&38,0,&38,&28,&38,0
1260 SYMBOL 59,&18,&18,0,&18,&18,&10,&20,0
1270 SYMBOL 60,&04,&08,&10,&20,&10,&08,&04,0
1280 SYMBOL 61,0,0,&7e,0,&7e,0,0,0
1290 SYMBOL 62,&80,&40,&20,&10,&20,&40,&80,0
1300 SYMBOL 63,&7c,&04,&1c,&10,&10,0,&10,0
1310 SYMBOL 64,&3e,&22,&2e,&2a,&2e,&20,&3e,0
1320 SYMBOL 65,&fc,&c4,&8c,&fc,&84,&c4,&c4,0
1330 SYMBOL 66,&f8,&84,&e4,&f8,&84,&9c,&f8,0
1340 SYMBOL 67,&fc,&8c,&80,&80,&c0,&c4,&fc,0
1350 SYMBOL 68,&f8,&64,&64,&44,&4c,&4c,&f8,0
1360 SYMBOL 69,&fc,&8c,&c0,&f8,&c0,&8c,&fc,0
1370 SYMBOL 70,&fc,&9c,&80,&f8,&80,&c0,&c0,0
1380 SYMBOL 71,&fc,&9c,&80,&9c,&c4,&c4,&fc,0
1390 SYMBOL 72,&c4,&c4,&84,&fc,&84,&8c,&8c,0
1400 SYMBOL 73,&7c,&14,&10,&10,&10,&50,&7c,0
1410 SYMBOL 74,&7c,&54,&10,&18,&18,&90,&60,0
1420 SYMBOL 75,&c8,&90,&a0,&d0,&88,&8c,&8c,0
1430 SYMBOL 76,&c0,&c0,&c0,&80,&80,&98,&f8,0
1440 SYMBOL 77,&82,&ee,&92,&92,&ba,&82,&c6,0
1450 SYMBOL 78,&8c,&c4,&c4,&b4,&8c,&8c,&84,0
1460 SYMBOL 79,&fc,&c4,&c4,&84,&8c,&8c,&fc,0
1470 SYMBOL 80,&fc,&c4,&8c,&fc,&80,&c0,&c0,0
1480 SYMBOL 81,&fc,&c4,&c4,&84,&94,&88,&f4,0
1490 SYMBOL 82,&fc,&c4,&8c,&fc,&90,&c8,&cc,0
1500 SYMBOL 83,&fc,&84,&80,&78,&04,&84,&fc,0
1510 SYMBOL 84,&7c,&10,&10,&10,&30,&30,&30,0
1520 SYMBOL 85,&c4,&c4,&84,&8c,&8c,&8c,&fc,0
1530 SYMBOL 86,&c4,&84,&84,&48,&48,&30,&30,0
1540 SYMBOL 87,&84,&84,&84,&b4,&b4,&cc,&84,0
1550 SYMBOL 88,&cc,&cc,&48,&30,&48,&cc,&cc,0
1560 SYMBOL 89,&86,&86,&44,&28,&10,&18,&18,0
1570 SYMBOL 90,&fc,&84,&08,&30,&40,&84,&fc,0
1580 SYMBOL 91,&7c,&60,&60,&40,&40,&4c,&7c,0
1590 SYMBOL 92,0,&60,&30,&10,&08,&0c,&06,0
1600 SYMBOL 93,&3e,&32,&02,&02,&06,&06,&3e,0
1610 SYMBOL 94,&18,&24,&42,&42,0,0,0,0
1620 SYMBOL 95,0,0,0,0,0,0,&ee,&bb
1630 SYMBOL 96,&3c,&22,&78,&20,&78,&20,&7e,0
1640 SYMBOL 97,0,0,&f8,&98,&88,&cc,&fc,0
1650 SYMBOL 98,&80,&80,&f8,&98,&88,&c8,&f8,0
1660 SYMBOL 99,0,0,&f8,&88,&c0,&c8,&f8,0
1670 SYMBOL 100,&08,&08,&f8,&98,&88,&c8,&f8,0
1680 SYMBOL 101,0,0,&f8,&80,&e0,&80,&f8,0
1690 SYMBOL 102,0,&1c,&10,&38,&38,&10,&70,0
1700 SYMBOL 103,0,0,&f8,&98,&88,&f8,&08,&78
1710 SYMBOL 104,&c0,&c0,&80,&f8,&88,&cc,&cc,0
1720 SYMBOL 105,0,&60,0,&60,&60,&70,&70,0
1730 SYMBOL 106,&08,0,&18,&18,&08,&08,&68,&78
1740 SYMBOL 107,&c0,&c0,&cc,&d8,&f0,&d8,&cc,0
1750 SYMBOL 108,&30,&30,&30,&30,&30,&30,&30,0
1760 SYMBOL 109,0,0,&cc,&b4,&b4,&84,&84,0
1770 SYMBOL 110,0,0,&f8,&98,&88,&cc,&cc,0
1780 SYMBOL 111,0,0,&f8,&98,&88,&c8,&f8,0
1790 SYMBOL 112,0,0,&f8,&98,&88,&f8,&80,&80
1800 SYMBOL 113,0,0,&f8,&88,&c8,&f8,&0c,&0c
1810 SYMBOL 114,0,0,&f8,&98,&80,&c0,&c0,0
1820 SYMBOL 115,0,0,&f8,&80,&70,&08,&f8,0
1830 SYMBOL 116,&60,&60,&20,&78,&20,&28,&38,0
1840 SYMBOL 117,0,0,&c8,&c8,&98,&98,&f8,0
1850 SYMBOL 118,0,0,&cc,&cc,&88,&70,&20,0
1860 SYMBOL 119,0,0,&84,&84,&b4,&b4,&cc,0
1870 SYMBOL 120,0,0,&cc,&48,&30,&48,&cc,0
1880 SYMBOL 121,0,0,&88,&c8,&f8,&08,&08,&78
1890 SYMBOL 122,0,0,&f8,&90,&20,&48,&f8,0
1900 SYMBOL 123,&0c,&30,&10,&60,&10,&30,&0c,0
1910 SYMBOL 124,&df,&db,&db,&9f,&83,&9b,&fb,0
1920 SYMBOL 125,&30,&0c,&08,&06,&08,&0c,&30,0
1930 SYMBOL 126,&7c,&82,&ba,&a2,&ba,&82,&7c,0
1940 SYMBOL 127,&FF,&FF,&FF,&FF,&FF,&FF,&FF,&FF
1950 RETURN
Process was the same:
Load the disk image into an emulator
Load the game
Save the game as a v2 snapshot – these are uncompressed memory dumps
Though I didn’t really have the patience for text adventures, Level 9 used what I thought was the coolest font (circa 1985). After checking through them all on the Internet Archive Amstrad CPC software library, I couldn’t find a version that used this bitmap font. I eventually found it on nvg. After lots of messing about, I extracted it and present it here. I’m sure I’ll make a TTF of it soon enough.
Tastes change a bit, don’t they?
10 REM *** L9FONT.BAS ***
15 REM bitmap font from Level 9's
20 REM Colossal Cave adventure
30 REM on the Amstrad CPC 464
40 REM (it was so cool at the time…)
50 REM Dug up by scruss, 2019-12
60 REM ==============================
100 SYMBOL AFTER 32
110 MODE 1
120 GOSUB 1000
130 PRINT" *** It's the Level 9 font ***"
140 PRINT" *** from Colossal Cave! ***"
150 PRINT" Dug up by scruss, 2019-12"
160 PRINT
170 PEN 2
180 PRINT"Lorem ipsum dolor sit amet, consectetur"
190 PRINT"adipiscing elit, sed do eiusmod tempor"
200 PRINT"incididunt ut labore et dolore magna"
210 PRINT"aliqua. Ut enim ad minim veniam, quis"
220 PRINT"nostrud exercitation ullamco laboris"
230 PRINT"nisi ut aliquip ex ea commodo consequat"
240 PRINT"arfle barfle gloop? | | |"
250 PRINT
260 PEN 1
270 FOR i%=32 TO 127
280 PRINT CHR$(i%); " ";
290 NEXT i%
300 PRINT
310 PRINT
990 END
1000 SYMBOL 33,&18,&24,&24,&24,&18,&0,&18,&0
1010 SYMBOL 34,&66,&66,&44,&88,&0,&0,&0,&0
1020 SYMBOL 35,&0,&24,&7E,&24,&24,&7E,&24,&0
1030 SYMBOL 36,&12,&7C,&D0,&7C,&16,&FC,&10,&0
1040 SYMBOL 37,&E4,&A4,&E8,&10,&2E,&4A,&4E,&0
1050 SYMBOL 38,&70,&D8,&D8,&72,&D6,&CC,&76,&0
1060 SYMBOL 39,&30,&30,&20,&40,&0,&0,&0,&0
1070 SYMBOL 40,&1C,&38,&70,&70,&70,&38,&1C,&0
1080 SYMBOL 41,&70,&38,&1C,&1C,&1C,&38,&70,&0
1090 SYMBOL 42,&10,&54,&38,&FE,&38,&54,&10,&0
1100 SYMBOL 43,&0,&10,&10,&7C,&10,&10,&0,&0
1110 SYMBOL 44,&0,&0,&0,&0,&30,&30,&20,&40
1120 SYMBOL 45,&0,&0,&0,&F8,&0,&0,&0,&0
1130 SYMBOL 46,&0,&0,&0,&0,&0,&60,&60,&0
1140 SYMBOL 47,&0,&4,&8,&10,&20,&40,&0,&0
1150 SYMBOL 48,&7C,&C6,&CE,&D6,&E6,&C6,&7C,&0
1160 SYMBOL 49,&8,&18,&38,&18,&18,&18,&3C,&0
1170 SYMBOL 50,&3C,&66,&C,&18,&30,&62,&7E,&0
1180 SYMBOL 51,&7E,&4C,&18,&3C,&6,&66,&3C,&0
1190 SYMBOL 52,&4,&C,&1C,&2C,&7E,&C,&1E,&0
1200 SYMBOL 53,&3E,&66,&60,&7C,&6,&6,&7C,&0
1210 SYMBOL 54,&3C,&66,&60,&7C,&66,&66,&3C,&0
1220 SYMBOL 55,&7E,&46,&6,&C,&C,&18,&18,&0
1230 SYMBOL 56,&3C,&66,&34,&18,&2C,&66,&3C,&0
1240 SYMBOL 57,&3C,&66,&66,&3E,&6,&66,&3C,&0
1250 SYMBOL 58,&0,&30,&30,&0,&0,&30,&30,&0
1260 SYMBOL 59,&0,&30,&30,&0,&30,&30,&20,&40
1270 SYMBOL 60,&1C,&30,&60,&C0,&60,&30,&1C,&0
1280 SYMBOL 61,&0,&0,&F8,&0,&F8,&0,&0,&0
1290 SYMBOL 62,&E0,&30,&18,&C,&18,&30,&E0,&0
1300 SYMBOL 63,&7C,&64,&C,&18,&10,&0,&10,&0
1310 SYMBOL 64,&7C,&C6,&DE,&D2,&DE,&C0,&7E,&0
1320 SYMBOL 65,&18,&6C,&C6,&C6,&FE,&66,&F6,&0
1330 SYMBOL 66,&FC,&C6,&C6,&FC,&C6,&C6,&FC,&0
1340 SYMBOL 67,&3C,&66,&C0,&C0,&C0,&66,&3C,&0
1350 SYMBOL 68,&D8,&EC,&C6,&C6,&C6,&EC,&D8,&0
1360 SYMBOL 69,&FE,&62,&60,&78,&60,&62,&FE,&0
1370 SYMBOL 70,&FE,&62,&60,&78,&60,&60,&E0,&0
1380 SYMBOL 71,&3C,&66,&C0,&CE,&C6,&66,&3C,&0
1390 SYMBOL 72,&C6,&C6,&C6,&FE,&C6,&C6,&C6,&0
1400 SYMBOL 73,&7E,&18,&18,&18,&18,&18,&7E,&0
1410 SYMBOL 74,&FE,&8C,&C,&C,&C,&CC,&78,&0
1420 SYMBOL 75,&E6,&CC,&D8,&F0,&D8,&CC,&C6,&0
1430 SYMBOL 76,&E0,&C0,&C0,&C0,&C0,&C2,&FE,&0
1440 SYMBOL 77,&C6,&EE,&FE,&D6,&C6,&C6,&CC,&0
1450 SYMBOL 78,&CE,&E6,&F6,&DE,&CE,&C6,&C6,&0
1460 SYMBOL 79,&38,&6C,&C6,&C6,&C6,&6C,&38,&0
1470 SYMBOL 80,&DC,&E6,&C6,&C6,&FC,&C0,&C0,&0
1480 SYMBOL 81,&38,&6C,&C6,&C6,&CA,&64,&3A,&0
1490 SYMBOL 82,&DC,&E6,&C6,&C6,&FC,&CC,&C6,&0
1500 SYMBOL 83,&7C,&C6,&C0,&7C,&6,&C6,&7C,&0
1510 SYMBOL 84,&FE,&B2,&30,&30,&30,&30,&30,&0
1520 SYMBOL 85,&E6,&66,&C6,&C6,&C6,&C6,&7C,&0
1530 SYMBOL 86,&E6,&66,&C6,&C6,&CC,&78,&30,&0
1540 SYMBOL 87,&EC,&66,&C6,&C6,&D6,&D6,&6C,&0
1550 SYMBOL 88,&EE,&C6,&6C,&38,&6C,&C6,&EE,&0
1560 SYMBOL 89,&EE,&C6,&2C,&18,&18,&18,&18,&0
1570 SYMBOL 90,&FE,&8C,&18,&30,&60,&C2,&FE,&0
1580 SYMBOL 91,&7C,&64,&60,&60,&60,&60,&7C,&0
1590 SYMBOL 92,&0,&60,&30,&10,&8,&C,&6,&0
1600 SYMBOL 93,&3E,&6,&6,&6,&6,&26,&3E,&0
1610 SYMBOL 94,&18,&24,&42,&42,&0,&0,&0,&0
1620 SYMBOL 95,&0,&0,&0,&0,&0,&0,&EE,&BB
1630 SYMBOL 96,&3C,&22,&78,&20,&78,&20,&7E,&0
1640 SYMBOL 97,&0,&0,&74,&DC,&C4,&CC,&74,&0
1650 SYMBOL 98,&C0,&C0,&DC,&E6,&C6,&E6,&DC,&0
1660 SYMBOL 99,&0,&0,&78,&CC,&C0,&CC,&78,&0
1670 SYMBOL 100,&0,&70,&18,&7C,&CC,&CC,&78,&0
1680 SYMBOL 101,&0,&0,&78,&CC,&FC,&C0,&7C,&0
1690 SYMBOL 102,&68,&74,&60,&F8,&60,&60,&60,&C0
1700 SYMBOL 103,&0,&0,&78,&CC,&C0,&CC,&7C,&C
1710 SYMBOL 104,&C0,&C0,&D8,&EC,&CC,&D8,&DC,&0
1720 SYMBOL 105,&C,&0,&38,&18,&18,&18,&38,&0
1730 SYMBOL 106,&6,&0,&1C,&C,&C,&C,&4C,&38
1740 SYMBOL 107,&C0,&C0,&CC,&D8,&F0,&D8,&CE,&0
1750 SYMBOL 108,&30,&30,&30,&30,&30,&36,&3E,&0
1760 SYMBOL 109,&0,&0,&AC,&D6,&D6,&C6,&CC,&0
1770 SYMBOL 110,&0,&0,&BC,&C6,&C6,&CC,&DE,&0
1780 SYMBOL 111,&0,&0,&7C,&C6,&C6,&C6,&7C,&0
1790 SYMBOL 112,&0,&0,&DC,&E6,&C6,&E6,&DC,&C0
1800 SYMBOL 113,&0,&0,&76,&CE,&C6,&CE,&76,&6
1810 SYMBOL 114,&0,&0,&DC,&E6,&C6,&FC,&C6,&0
1820 SYMBOL 115,&0,&0,&3C,&60,&3C,&8E,&7C,&0
1830 SYMBOL 116,&18,&30,&FC,&30,&30,&32,&1C,&0
1840 SYMBOL 117,&0,&0,&E6,&66,&C6,&C6,&7A,&0
1850 SYMBOL 118,&0,&0,&EC,&66,&C6,&EC,&38,&0
1860 SYMBOL 119,&0,&0,&EC,&C6,&D2,&7C,&28,&0
1870 SYMBOL 120,&0,&0,&EE,&6C,&38,&6C,&EE,&0
1880 SYMBOL 121,&0,&0,&EC,&C6,&6C,&18,&30,&E0
1890 SYMBOL 122,&0,&0,&FE,&9C,&30,&62,&FE,&0
1900 SYMBOL 123,&C,&30,&30,&60,&30,&30,&C,&0
1910 SYMBOL 124,&CF,&DB,&DB,&CF,&C3,&DB,&FB,&0
1920 SYMBOL 125,&60,&18,&18,&C,&18,&18,&60,&0
1930 SYMBOL 126,&7C,&C6,&BA,&A2,&BA,&C6,&7C,&0
1940 SYMBOL 127,&FF,&FF,&FF,&FF,&FF,&FF,&FF,&FF
1950 RETURN
Back in 1973, the future definitely wasn’t equally distributed. While in Scotland we had power cuts, the looming three-day week and Miners’ Strike I, in California, the People’s Computer Company (PCC) was giving distributed computer access, teaching programming and publishing computer magazines. I don’t think we got that kind of access until (coincidentally) Miners’ Strike II a little over 10 years later.
But the People’s Computer Company magazine archive is a sunny thing, overfilled with joyful amateur enthusiasm and thousands of lines of code fit to make Edsger Dijkstra explode. Of course it was written for the local few who had access to mainframes and terminals, but it hardly seems to come from the same world as the dark evenings in Scotland spent cursing the smug neighbours’ house with all the lights on, their diesel generator putt-putting into the night.
Lots of these games from the PCC era are forgettable now. The raw challenge of guessing a number on a text screen has paled somewhat in the face of 4K photo-realistic rendering. One game I found is still a little challenging, at least until you work out the trick of it: Taxman (or as the authors tried to rename it later, Factor Monster). Here’s a tiny sample game transcript:
Hi, I'm the taxman
Do you want the regulations?
(1=Yes, 0=No)? 0
How many numbers do you want
in the list? 6
The list is: 1 2 3 4 5 6
You take? 5
Your total is 5
I get 1
My total is 1
New list: 2 3 4 6
You take? 6
Your total is 11
I get 2 3
My total is 6
New list: 4
I get 4
because no factors of any number
are left.
My total is 10
You 11 Taxman 10
You win !!!
Again (1=yes, 0=no)?
Seems I sneaked a lucky win there, but it’s harder than it looks. The rules are simple:
Start with a list of consecutive numbers
You choose a number, but it has to have some factors in the list
The taxman (or the factor monster, a concept I much prefer as it doesn’t reinforce the Helmsley Doctrine) takes all the remaining factors of your number from the list
You get to choose a number from the list, which is now missing your previous choice and all of its factors, and repeat
Once the list has no multiples of any other number, the taxman/FM takes the rest
The winner is whoever has the largest sum.
For such a simple game (or perhaps, such a simple me) the computer wins surprisingly often. Since I find it fun to play, I thought I’d share the 1973 love as much as possible by porting to all of the BASIC dialects that I knew.
Plain text BASIC – taxman.bas – runs under interpreters such as bas. Almost verbatim from the 1973 publication. May not allow you to play again on some interpreters; you might want to try my slightly rearranged 40 column version that should run on systems that don’t allow a variable to be dimensioned twice.
Amstrad CPC Locomotive BASIC – taxman.dsk – or as I call it, BASIC. 40 columns yellow on blue is how BASIC should look.
BBC BASIC – taxman.ssd – for all the boopBeep fans out there. You can actually play this one in your browser, too. Yes, the number formatting is weird, but BBC BASIC was always its own master.
Commodore 64 – taxman.prg – very very upper case for this dinosaur of a BASIC.
Apple II AppleSoft BASIC – TAXMAN.DSK – lots of fiddling with import tools and dialect weirdness because Apple.
ZX Spectrum (Sinclair BASIC) – taxman.tap – 32 columns plus a very special dialect (no END, GOTO and GOSUB are GO TO and GO SUB) meant this took a while, but it was quite rewarding to get going.
Sinclair ZX81 (16 K) – taxman.p – this one was a fight. The ZX81 didn’t scroll automatically, so you have to invoke SCROLL before every newline-generating PRINT or else your program will stop. For some reason this version gets unbearably slow near the end of long games, but it does complete.
BBC BASIC bot [beta2] on Twitter is lovely. You tweet a BBC BASIC program to it and it replies with an animation rendering of what your program would look like on a BBC Micro.
which readers might recognize as 10 PRINT, the endless random maze one-liner for the C64. This program even inspired its own book – also called 10 PRINT CHR$(205.5+RND(1)); : GOTO 10 – about simple generative art.
BeebEm? Lawks, that’s a bit old (2006). All the cool (*cough*) kids are running b-em – https://github.com/stardot/b-em – these days. It’s lovingly maintain by Stardot forum members. It’s a little crashy on some Linux platforms, but seems stable on the Raspberry Pi and Raspbian. You may need to install the liballegro5-dev and zlib1g-dev packages to get it to compile.
If you want a native version of BBC BASIC, Richard Russell’s version is pretty neat: http://www.bbcbasic.co.uk/bbcsdl/ . You’ll most likely need to change line 280 to use some variant of the WAIT command to make it playable.
Another native interpreter is Brandy. There’s an ancient one in the repos, but I’m completely taken with the Matrix Brandy fork: https://github.com/stardot/MatrixBrandy . It may need a few packages installed to get it to build (libsdl1.2-dev might be a good first try), but it’s really fast. For cross-platform happiness, change line 280 to WAIT 10. If you stick to using a FOR loop, you might have to have it as high as 2,000,000 on a fast computer!
Around 1988–1991 there was a weekly computer magazine in the UK called New Computer Express. This period coincided roughly with the time I was a freelance writer in the same field.
For childish reasons now lost to time, a group of us freelancers had a major hate-on for NCE’s advice columnist. Writing under the name Uncle TechTip, this columnist seemed to answer most questions with something like “Hmm, I don’t know anything about _____. Maybe a reader can help?†Almost without fail, he’d have readers write in answers for next week’s issue.
Not realizing that Uncle TT’s economy of response was a sly precursor to crowdsourcing websites, the neophyte journo brigade were incensed by his lack of knowledge. One of us wrote an Uncle TechTip Simulator in BASIC, which I recreate from memory for your enjoyment:
10 CLS
15 PRINT " *** Uncle TechTip Simulator ***"
20 PRINT
25 INPUT "What is your question for Uncle TechTip";a$
30 PRINT
35 PRINT "Uncle TechTip's Answer: "
40 PRINT
45 PRINT "Hmm, I don't know anything about"
50 PRINT " ";a$;" ..."
55 PRINT "Maybe a reader can help?"
Thanks to users sbadger and lurkio on the stardot forum, I’ve been reunited the original BBC BASIC one-liner that begat 2d Star Dodge/Stardodger: Asterisk Tracker!
It was published in the December 1984 edition of BEEBUG Magazine (vol. 3, issue 7; page 9) and is credited to N. Silver.
It makes extensive use of BBC BASIC’s abbreviations, and the writeup even warns
… Here the programs are extensively abbreviated so that the line will fit into Basic’s keyboard buffer. Because of this, you cannot edit a LISTed version, and so, to allow for errors, it is best to spool out a copy of the text to tape/disc initially. This can be achieved as follows:
*SPOOL PROGRAM type in program *SPOOL
The program unwinds to something much more understandable:
10 L=0 20 REPEAT 30 L=L+3 40 MODE 4 50 DRAW 1279,0 60 DRAW 1279,452 70 MOVE 1279,572 80 DRAW 1279,1023 90 DRAW 0,1023 100 FOR I=1 TO L 110 VDU 31,RND(32)+5,RND(31),42,30 120 NEXT 130 PRINT (L-3)/3 140 X=0 150 Y=512 160 REPEAT 170 PLOT 69,X,Y 180 X=X+4 190 Y=Y-(INKEY(-74)+.5)*8 200 UNTIL POINT(X,Y)=1 OR X=1280 210 UNTIL X<1280 220 VDU 7 230 REPEAT UNTIL INKEY(-99) 240 RUN
The instructions are typical of the day:
The first game (called “Asterisk Tracker”) is a very simple game in which you have to guide a “snake” across the screen, whilst avoiding the stars. As the game progresses, more and more stars will be displayed, and the ease of the game rapidly disappears. The Return key guides the “snake” upwards, but it moves down if Return is not pressed. Aim your “snake” for the gap in the wall, and don’t touch any objects as this causes instant death from space acid poisoning!
Um, yeah, N. Silver, whatevs …
It’s pretty amazing that three type-ins could fit on a page: especially when you consider that the BEEBUG magazine was A5!
Because I care (and don’t if you don’t), here’s the Locomotive BASIC source, lovingly typed into the Caprice32 emulator then extracted as text using iDsk:
10 ' British Council Tile / Bus Fabric Sim
20 ' by Rob Manuel 2018
30 '
40 ' z/x - change char up/down (ascii)
50 ' space - random palette
60 ' c - show ascii val, inks & pause
70 ' v - random character (128+ ascii)
80 ' b - random char and cols
90 ' n - fill with same line & pause
100 'i - input ascii value
110 '
120 ON BREAK GOSUB 260:MODE 1:LOCATE 1,26
130 DEF FNs=INT(RND*255)
140 SYMBOL 255,FNs,FNs,FNs,FNs,FNs,FNs,FNs,FNs
150 DEF FNp=INT(RND*4)
160 DEF FNi=INT(RND*26)
170 GOSUB 470
180 GOSUB 270
190 o$="":i$=INKEY$
200 IF i$<>"" THEN GOSUB 380
210 FOR i=1 TO 40
220 w$=CHR$(14)+CHR$(FNp)+CHR$(15)+CHR$(FNp)
230 w$=w$+CHR$(c):o$=o$+w$:NEXT i
240 store$=o$
250 PRINT o$;:GOTO 190
260 CALL &BC02:PAPER 0:PEN 1:END
270 aa=FNi:bb=FNi:cc=FNi:dd=FNi
280 INK 0,aa:INK 1,bb:INK 2,cc:INK 3,dd
290 BORDER aa
300 GOSUB 320:RETURN
310 IF c>255 THEN c=32:IF c<32 THEN c=255
320 LOCATE 1,1:PAPER 0:PEN 1
330 PRINT "C:"c;
340 PRINT CHR$(c);
350 PRINT " ";
360 PRINT "I:"aa;bb;cc;dd;
370 LOCATE 1,26:RETURN
380 IF i$=" " THEN GOSUB 270:RETURN
390 IF i$="z" THEN c=c-1:GOSUB 310:RETURN
400 IF i$="x" THEN c=c+1:GOSUB 310:RETURN
410 IF i$="c" THEN GOSUB 310:CALL &BB18:RETURN
420 IF i$="i" THEN LOCATE 1,1:INPUT "ASCII?",c:GOSUB 310:RETURN
430 IF i$="v" THEN GOSUB 470:GOSUB 310:RETURN
440 IF i$="b" THEN GOSUB 270:GOSUB 470:GOSUB 310:RETURN
450 IF i$="n" THEN FOR i=1 TO 25:PRINT store$;:NEXT:CALL &BB18:RETURN
460 RETURN
470 c=INT(RND*128)+127:RETURN
As if it weren’t nerdy enough, the 6502 40th Anniversary Computer Badge runs Lee Davison’s EhBASIC. There are 1024 whole bytes free for your programs, so it’s not exactly spacious. It’s got useful floating point support, though:
Yup, that’s the second most boring BASIC example program, after the quadratic root finder.
100 REM HERON ROOTS
110 EP=0.0001
120 INPUT "X";X
130 N=1:RN=X/2
140 PRINT"COUNT","ROOT","DELTA":PRINT"======","======","======"
150 DE=ABS(RN*RN-X)
160 PRINT N,RN,DE
170 RN=(RN+X/RN)/2
180 N=N+1
190 IF DE>EP THEN GOTO 150
Update: Josh got my badge working again (it wasn’t, for $reasons …) and I re-ran this code. If you try the code for X=100000 and larger, it won’t converge. You might want to add:
185 IF N>25 THEN PRINT "EPSILON TOO LARGE, EXITING":END
so that the loop will exit after 25 times. Alternatively, make the value of EP depend upon the size of X. Aren’t numerical analysis and floating point foibles fun?
Just what no-one has needed since about 1979 or so …
BASIC on the Apple II has no easy way to import text as a program. When you LOAD a file, it must be in Apple’s tokenized format. While Apple DOS has the EXEC facility to run script files as if they were typed from the keyboard, it’s very picky about the file format:
There must be a carriage return character (CR, ASCII 13) before the first line
All line numbers must have an extra space before and after them
All tokens must be in upper case
All tokens (keywords and functions) must have a space after them.
The right way to do this conversion would be to write a tokenizer that spits out the correct binary file. But you can (kinda) fudge it with this shell command, operating from BASIC source PROG.BAS:
sed 's/^[0-9][0-9]*/& /;s/^/ /;1s/^/\n/;s/$/ /;s/[:()]/ & /g;' PROG.BAS | tr '\n' '\r' | ac.sh -p EG.dsk PROG T
ac.sh is the command line version of AppleCommander, and the file EG.dsk referred to above is an Apple DOS 3.3 image created with
ac.sh -dos140 EG.dsk
It still needs work, as there are functions that will mess this up, and Applesoft’s parser makes a mess of code like IF A THEN …, turning it into IF AT HEN ….
So if I wanted to import the following futile program:
10 REM A FUTILE PROGRAM BY SCRUSS
20 HOME
30 FOR X=1 TO 20
40 PRINT SPC(X);"FUTILE"
50 NEXT X
Run through the script (but before EOL conversion) it would look like this:
10 REM A FUTILE PROGRAM BY SCRUSS
20 HOME
30 FOR X=1 TO 20
40 PRINT SPC ( X ) ;"FUTILE"
50 NEXT X
Make a disk and put the modified program text on it:
ac.sh -dos140 futile.dsk
sed 's/^[0-9][0-9]*/& /;s/^/ /;1s/^/\n/;s/$/ /;s/[:()]/ & /g;' futile.bas | tr '\n' '\r' | ac.sh -p futile.dsk FUT T
Load the disk into your Apple II, clear out the init program, and import the code with EXEC FUT:
If all you get is ] cursors printed and no syntax errors, then something might be working. List it:
DI 30
XC 45
XC 205
…
IF 700
NM 730
… (many, many more lines …)
I thought at first it was a stack trace, but nope — it’s error messages! You need to dig through your trusty language manual, and on page 132 it has a table to explain:
DI ERROR IN DIM STATEMENT
IF ERROR IN IF STATEMENT
NM MISSING LINE NUMBER
XC CHARS AFTER END OF LINE
(and yes, they’re in all-caps. Mixed case? Mixed feelings!)
So whenever Python throws a tantrum (or as it calls it, an exception) and wails at length about its problems, remember PDP-8 BASIC: Two letters + a line number. That’s all.
Microsoft used to supply two versions of its BASIC for Macintosh. One used decimal mathematics for precise tallying of small amounts. The other used the more familiar floating point mathematics, rounding errors and all. I don’t know what floating point library Microsoft used for sure — perhaps Motorola’s 32-bit Fast Floating Point system — but it introduces rounding errors pretty quickly. Modern routines don’t start displaying oddly until after 15 decimal places.
Consider this simple program:
10 LET x=36/10
20 LET a$="## #.#"
30 FOR n%=1 TO 18
40 PRINT USING a$; n%; x
50 LET a$=a$+"#"
60 NEXT n%
70 END
Along with the number of decimal places, it should print 3.6, 3.60, 3.600, 3.6000, … with an increasing line of zeroes after the 3.6. Bas makes a valiant but typical attempt: