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
If all you get is ] cursors printed and no syntax errors, then something might be working. List it:
Disk image: futile-AppleII-dsk.zip, containing:
$ ac.sh -l futile.dsk DISK VOLUME #254 T 002 FUT A 002 FUTILE DOS 3.3 format; 134,144 bytes free; 9,216 bytes used.
If you try to run the (unmodified) BASIC code for Oregon Trail (1975) on PDP-8 BASIC, you get this:
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:
1 3.6 2 3.60 3 3.600 4 3.6000 5 3.60000 6 3.600000 7 3.6000000 8 3.60000000 9 3.600000000 10 3.6000000000 11 3.60000000000 12 3.600000000000 13 3.6000000000000 14 3.60000000000000 15 3.600000000000000 16 3.6000000000000001 17 3.60000000000000009 18 3.600000000000000089
Oddly enough, good old Locomotive BASIC on the Amstrad CPC does it more correctly somehow:
cbmbasic is pretty cool. It’s a portable C rendition of the Commodore 64’s ROM BASIC interpreter. While not the spiffiest version of the language, it does allow some very old code to run — such as the games from David H. Ahl’s book BASIC Computer Games.
Here are all the programs automatically converted to cbmbasic’s tokenized format: cbmbasic-Ahl-BASIC_Games. They seem to run, but some might fail. Notes on sources of the text files and conversion methods are in the archive. Have fun!
That picture might not look much, but it’s doing something rather wonderful. It’s a tiny ESP8266 BASIC script running on a super-cheap ESP8266 wifi module. The code draws a clock that’s synced to an NTP server. ESP8266 BASIC graphic commands are built from SVG, so anything you can draw on the screen can also be saved as a vector graphic:
The runtime includes a simple textarea editor that saves code to the board’s flash:
Among other features, ESP8266 BASIC has a simple but useful variable display:
I’d picked up a (possible knock-off of a) WeMos D1 ESP8266 board in Arduino form factor a few months ago. The Arduino.cc Software now supports ESP8266 directly, so it’s much easier to program. Flashing the BASIC code to the board was very simple, as I’d noticed that the Arduino IDE printed all of its commands to the console. All I needed to do was download an ESP8266 BASIC Binary, and then run a modified Arduino upload line from the terminal:
~/.arduino15/packages/esp8266/tools/esptool/0.4.9/esptool -vv -cd nodemcu -cb 921600 -cp /dev/ttyUSB2 -ca 0x00000 -cf ESP8266Basic.cpp.bin
ESP8266 BASIC starts in wireless access point mode, so you’ll have to connect to the network it provides initially. Under Settings you can enter your normal network details, and it will join your wifi network on next reboot. I just hope it doesn’t wander around my network looking for things to steal …
FreeBASIC is a pretty nifty cross-platform BASIC compiler. It uses a Microsoft-like syntax, has an active user and developer base, and is quite fast. Building the latest version on a Raspberry Pi is a bit of a challenge, though.
Part of the problem is that FreeBASIC is mostly written in FreeBASIC, so you need a working compiler to bootstrap the latest version.
Update: you’re probably best just downloading the binary install packages from the FreeBASIC site. I’m having difficulty getting recent (late 2016) source packages to build for reasons that would take too long for most people to care about.
The following steps worked for me:
- Install some necessary packages:
sudo apt-get install build-essential libncurses5-dev libffi-dev libgl1-mesa-dev libx11-dev libxext-dev libxrender-dev libxrandr-dev libxpm-dev ncurses-doc libxcb-doc libxext-doc libgpm-dev git libcunit1 libcunit1-dev libcunit1-doc
(You don’t really have to include the cunit packages; they’re only needed if you run tests before installation.)
- Download a nightly binary from Sebastian’s server: http://users.freebasic-portal.de/stw/builds/linux-armv6-rpi/ and install it:
unzip fbc_linux_armv6_rpi_version.zip cd fbc_linux_armv6_rpi/ chmod +x install.sh sudo ./install.sh -i
Don’t delete the installation folder just yet.
- Grab the latest version of the source from github:
cd git clone https://github.com/freebasic/fbc.git
Change directory to the new FreeBASIC source folder (cd fbc), and type make. (or, on a Raspberry Pi 2 or 3, make -j4 to use all the cores …). After a while (in my tests, about 52 minutes on a 512 MB Raspberry Pi, or around 6½ minutes [!] on a Raspberry Pi 2), it should finish. If there’s a bin/fbc file, the compilation worked!
- Before you install the new compiler, uninstall the old one: change directory to the fbc_linux_armv6_rpi folder, and type:
sudo ./install.sh -u
- Once that’s done, go back to the new fbc folder, and type:
sudo make install
And you’re done! You can delete the fbc_linux_armv6_rpi folder now. If you don’t mind it taking up space, keep the fbc folder to allow you a quick rebuild of the latest version of the compiler with:
cd fbc git pull make sudo make install
Note that this will build a native armv7l compiler on a Raspberry Pi 2, and an armv6l one on a Raspberry Pi. This means you can’t run binaries you built on a Raspberry Pi 2 on a Raspberry Pi (you’ll get an Illegal Instruction error), but you should be able to run ones built on a Raspberry Pi on a Raspberry Pi 2. Binary compatibility is overrated, anyway …
Update: Markus Hoffmann uploaded a new version of X11Basic-1.20.tar.gz to SourceForge that addresses most of these problems. I’ve edited the article to remove the obsolete bits.
More than 20 years ago, I really liked GFA-Basic. It ran blindingly fast on the Atari ST, and when it didn’t crash on the Amiga, it ran blindingly fast there too. I even wrote a review of it for comp.sys.amiga.programmer, which you can read to this day in all its textual glory. One of the e-mail addresses in that article still works, too.
I still sometimes think in BASIC, and there is much wringing of hands (not by me, really) that there isn’t a good interpreter for Raspbian on the Raspberry Pi. So when I found X11-Basic — a cross-platform GFA-Basic-like system — I had to take a look.
While I have managed to get X11-Basic demos to run, I have to say it’s not running super well. I’ll show you how to install X11-Basic 1.20 and get it (mostly) running, but it’s a bit rough on the ARM. Incidentally, these instructions also work on Ubuntu 12.mumble LTS on x86.
First, you need to install some (okay, a lot of) packages:
sudo apt-get install libreadline-dev tcsh libncurses5-dev xutils-dev libc6-dev libsdl1.2-dev libtool
Now download and extract the package:
tar xvzf X11Basic-1.20.tar.gz cd X11Basic-1.20
For X11Basic-1.20, you have to issue an extra command before the standard ‘
./configure ; make ; make install‘ sequence:
sudo mkdir -p /usr/local/share/man/man1 ./configure make sudo make install
This is enough to make a working
xbasic interpreter. I made some screenshots of some of the graphics demos —
As you can see, there’s some screen corruption, but most demos just worked. Incidentally, the Mandelbrot one took almost 1¼ hours to run. Took me right back, that did (or it would have, if I hadn’t been outside bombing about in the slush on my bicycle while it churned away).
In order to see just how fast the interpreter is, I ran the formerly fearsome Personal Computer World Benchmark #8 under X11-Basic. PCW#8 used to bring 8-bit home computers to their knees, typically taking more than a minute to run. Here’s the code, indented a bit and with a timing wrapper added:
LET start=TIMER LET K=0 L30: LET K=K+1 LET A=K^2 LET B=LN(K) LET C=SIN(K) IF K<1000 GOTO L30 ENDIF PRINT TIMER-start QUIT
(yeah, GFA-style BASIC isn’t too pretty …)
It takes about ¼s to run. The old BBC B was supposed to take about 50s. By comparison, X11-Basic on a manky old dual-core Atom took 0.04s.
The native compiler xbc seems to work. To make a standalone binary of the above code, you do:
xbc -o PCWBenchmark PCWBenchmark.xbas
The compiled binary runs roughly twice as fast as the interpreted code. Not blazing fast, but a useful increase.
Unfortunately, the bytecode compiler
xbbc doesn’t actually do anything on the Raspberry Pi yet. So here I leave it up to you to play with X11-Basic, and see what it can and can’t do.
Sorry, folks at 10 PRINT, I think the Amstrad CPC’s version simply pwns the C64:
About 25 years ago, I was a smallish computer nerd obsessed with programming his Amstrad CPC464. I had got a BCPL rom-based compiler for cheap and was looking for things to do with it. “Why not write a game?” I asked myself.
There were two minor hurdles. I had no imagination, and I certainly wasn’t focused enough to write anything big. Fortunately, it was still the 80s, so we knew how to rip stuff off without being called out for it. I merrily copied a game my friend Alan Cook had written for the Dragon 32, and called it 2D Star Dodge.
2D Star Dodge was the perfect rip off. Not merely had I ripped off the idea from Alan, but he had ripped off the idea in turn from a BBC Basic one-liner game called (as verified by Graeme Smith) “One Line”. The name 2D Star Dodge was an, um, homage to Realtime Games’ 3D Starstrike, which itself was “strongly influenced” by the Star Wars arcade game. Originality? Pfft.
So I wrote the game. Well, okay, I wrote a mockup in Locomotive BASIC, which ran a bit slowly, but gave me something to work from. Here it is, if you want to play it in you (Java-enabled) browser: 2D Star Dodge – BASIC. I then meticulously translated it into BCPL, and ended up with something that looked liked this:
Once I’d finished the BCPL version, I had bought the MAXAM assembler ROM, and got learning the Z80 opcodes. Soon, a third port was complete, now needing hardcoded delays to be playable as it would kill you off in about one screen refresh without them.
So, now I had three versions of the same game. There was only a limited number of local folks I could give it to, so I decided to send all three versions to Amstrad Computer User magazine to print as a type-in. Thankfully, it arrived on the desk of the freshly minted (yet still beardy) assistant editor Jeff Walker, who had founded the jam econo CPC magazine/club WACCI. Jeff had the idea for me to turn the simple game into a comparison of programming in three languages.
Thanks to the CPCWiki forum, you can now read the articles I wrote in Amstrad Computer User in 1988 that went with the code. Writing style best described as “typing”:
- Amstrad Computer User 1988/09 – Star Dodger 1 – BASIC
- Amstrad Computer User 1988/10 – Star Dodger 2 – BCPL
- Amstrad Computer User 1988/11 – Star Dodger 3 – Assembler
- Download this disc image file: stardoj
- Unzip it
- Go to CPCBox
- “Choose configuration …” of Boot CPC464 (or 664, or 6128)
- Select your downloaded stardoj.dsk as Drive A:
- Annoyingly, it seems to be stuck with an AZERTY keymap, so to catalogue the disc (
cat) you have to type
- To run the BASIC version, type
run"stardoj2(on my American keyboard, that becomes
run@stqrdoj2; quotes are Shift+2). Hitting Escape twice will quit back to the prompt.
- To run the BCPL version, type
run"2dstardo. The only way to quit is to reset the emulator.
The BASIC version is based on the published type-in. The BCPL version I found as a disk image (2dstardo.dsk) on a download site — it’s exactly as I submitted it to the magazine, dubious copyright message and all. I’m not sure how it got out there; I suspect either my network of, ahem, software protection experts I knew through Colin Harris of Nemesis, or it went via my CPC-owning French penpal (Hi Benoit Hébert, formerly of Le Havre).
I had to modify the BCPL binary to run on modern emulators, as the real Amstrad CPC did a thing with its keymapping that is really hard to get right on modern systems. Originally, the game used the Shift key, but I modified it to use Space, which is easier to emulate as it’s a printing character. Can I just say that I remembered how to read and modify Z80 binaries after a quarter century? Old school, literally. I used iDsk‘s disassembler/hex dumper and emacs’s hexl mode to do the deed.
I recently discovered that someone created a Flash game based on my type-in: Star Dodger. Mind = Blown.
Ganked from the CPC 6128 manual. You’re welcome …
Note that non-printing keys (like SHIFT) are really hard to emulate on modern machines. The CPC scanned them as if they were any printing key, but modern machines handle them like key modifiers.
10 ' ** Initialise ** 20 MODE 1 30 INK 0,0 40 BORDER 0 50 INK 1,26 60 INK 3,0 70 q=5 90 LOCATE 16,1 100 PRINT"Stardodger" 110 LOCATE 1,5 120 PRINT"Avoid the killer Asterisqs, and seek the" 130 LOCATE 9,6 140 PRINT"wondrous Nextscreen Gap." 150 LOCATE 12,13 160 PRINT"Use SHIFT to climb" 170 GOSUB 700 190 MODE 1 200 DRAWR 629,0 210 DRAWR 0,170 220 MOVER 0,60 230 DRAWR 0,169 240 DRAWR -629,0 250 DRAWR 0,-399 260 DRAWR 0,2 270 DRAWR 627,0 280 DRAWR 0,168 290 MOVER 0,60 300 DRAWR 0,167 310 DRAWR -625,0 320 DRAWR 0,-399 330 MOVE 636,0 340 DRAW 636,399,3 350 MOVE 638,0 360 DRAW 638,399 370 PLOT -1,-1,1 380 TAG 390 FOR s=1 TO q 400 MOVE 50+RND*561,20+RND*361 410 PRINT"*"; 420 NEXT 430 TAGOFF 440 MOVE 0,200 450 dy=4 470 DRAWR 4,dy 480 IF INKEY(21)<>-1 THEN dy=4 ELSE dy=-4 490 t=TESTR(2,dy/2) 500 IF t=1 GOTO 550 510 IF t=3 GOTO 620 520 MOVER -2,-dy/2 530 GOTO 470 550 MODE 1 560 PRINT TAB(16);"YOU GOOFED" 570 LOCATE 5,13 580 PRINT"Number of Screens completed = "+STR$((q/5)-1) 590 GOSUB 700 600 RUN 620 MODE 1 630 PRINT TAB(16);"WELL DONE" 640 LOCATE 10,13 650 PRINT"Stand by for Screen "+STR$((q/5)+1) 660 GOSUB 700 670 q=q+5 680 GOTO 190 700 LOCATE 8,25 710 PRINT"Press any key to continue" 720 WHILE INKEY$<>"" 730 WEND 740 WHILE INKEY$="" 750 WEND 760 RETURN