|
Update: Commodore BASIC as a Scripting Language for UNIX and Windows – now Open Source |
Recently, we reconstructed a perfect copy of Apple I BASIC, the first piece of software Apple ever sold – in 1976. Now it is time to make something useful out of it. Wouldn’t it be nice if you could use Apple I BASIC to replace, say, Perl? Wouldn’t it be nice if you could do this:
$ cat reverse.bas #!/usr/bin/apple1basic 10 DIM A$(100) 20 INPUT A$ 30 FOR I = LEN(A$) TO 1 STEP -1 40 PRINT A$(I,I); 50 NEXT I 60 PRINT 70 END $ chmod a+x reverse.bas $ echo MICHAEL STEIL | ./reverse.bas LIETS LEAHCIM $
Here is Apple I BASIC as a scripting language for Mac OS X Intel:
Just yet another Apple I emulator for Mac? No, it is not. There are some very important differences:
- The “apple1basic” executable is a statically recompiled version of the original binary. All code is running natively.
- “apple1basic” plugs right into UNIX stdin and stdout.
- You can pass “apple1basic” the filename of a BASIC program to run.
- You can run BASIC programs like shell scripts.
Let’s play with it for a bit. First, copy “apple1basic” to /usr/bin:
$ sudo cp apple1basic /usr/bin
Let’s try direct mode first:
$ apple1basic >PRINT"HELLO WORLD!" HELLO WORLD! >
Now let’s write a small program:
$ apple1basic
>10 FOR I = 1 TO 10
>20 TAB I: PRINT "HELLO WORLD!"
>30 NEXT I
>40 END
>RUN
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
>
We can tell apple1basic to run a BASIC program from a file, too:
$ cat hello.bas
10 FOR I = 1 TO 10
20 TAB I: PRINT "HELLO WORLD!"
30 NEXT I
40 END
$ apple1basic hello.bas
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
$
apple1basic can be interactive:
$ cat name.bas 10 DIM N$(20) 20 PRINT "WHAT IS YOUR NAME"; 30 INPUT N$ 40 PRINT "HELLO, "; N$; "!" 50 END $ apple1basic name.bas WHAT IS YOUR NAME?MICHAEL HELLO, MICHAEL! $
apple1basic supports redirection of stdin and stdout. Note that if stdin is a pipe, “INPUT” doesn’t print the “?”:
$ cat reverse.bas 10 DIM A$(100) 20 INPUT A$ 30 FOR I = LEN(A$) TO 1 STEP -1 40 PRINT A$(I,I); 50 NEXT I 60 PRINT 70 END $ echo MICHAEL STEIL | apple1basic reverse.bas LIETS LEAHCIM $
Which brings us back to our first example: You can even use apple1basic as a UNIX script interpreter by adding the hashbang as the first line:
$ cat reverse.bas #!/usr/bin/apple1basic 10 DIM A$(100) 20 INPUT A$ 30 FOR I = LEN(A$) TO 1 STEP -1 40 PRINT A$(I,I); 50 NEXT I 60 END $ chmod a+x reverse.bas $ echo MICHAEL STEIL | ./reverse.bas LIETS LEAHCIM $
Some more programs
These games, written for the Apple I in the 1970s, have been taken from this and other sites and converted from tokenized hexcode into ASCII.
- 21.bas: Blackjack
- aceyducey.bas: Card Game
- bowl.bas: Bowling Game
- buzzword.bas: Buzzword Generator
- crap.bas: Crap Game
- slots.bas: Slot Machine
- startrek.bas: Star Trek
You can also download hanoi-apple1.bas, a fixed version of Amit Singh’s BASIC program from his Hanoimania project.
How it is done
My static recompiler takes the Apple I BASIC binary as an input and produces a native executable. This file does not contain the original 6502 code and runs 100% natively. On a 2 GHz machine, it runs about 2000 times faster than a 1 MHz Apple I, so it can run one 6502 clock cycle per native cycle. (In the best case, an interpreter can only get up to 1/10 of an emulated cycle per native cycle.)
Accesses to the Apple I terminal (keyboard and screen) are handled by functions that implement a few hacks. Depending on the program counter and the stack, I can discard some output (like terminal echo, 80 column forced line wrap) and redirect files and stdin to keyboard input, depending on context. For example, if there is a filename on the command line, keyboard emulation passes these characters into BASIC, and adds the “RUN” command. All following input will be read from stdin, and as soon as the code to print the “>” prompt is detected, the output handler quits the application.
Commodore BASIC / Microsoft BASIC 6502
I have done the same thing to the 9 KB Microsoft BASIC for 6502 taken from the Commodore 64 ROM.
$ cbmbasic
**** COMMODORE 64 BASIC V2 ****
64K RAM SYSTEM 38911 BASIC BYTES FREE
READY.
_
It has many of the same features as Apple I BASIC: It discards the banner and the “READY.” prompt output when runnig in non-interactive mode, accepts a BASIC file as a parameter, and can be used as a script interpreter.
But… why??
I love the idea of reusing old code. Emulation is nice, but it rarely integrates well into modern systems. Most code out there has either a very lightweight (or well-understood) interface to the hardware (like the Apple I) or the opertaing system (like Commodore BASIC, as well as all programs from the GUI era), so hooking it up with modern operting system services can work out very nicely.
Also, emulation of vintage systems rarely cares too much about performance any more, since it is usually fast enough, i.e. as fast as or faster than the original system. But computers have always been slow, and running very old code can have the advantage of working with really fast software.
And yes, I think there is a lot of useful vintage code out there.
When I tried copying this to my /usr/local/bin & running it I got the following error message:
-bash: /usr/local/bin/apple1basic: cannot execute binary file
I am running Mac OS X 10.4.11. Does this program only work on 10.5?
@Evan: The binaries posted are Intel-only for now, sorry. If you ask nicely, I’ll target PowerPC, too. :-)
Nice one! Will try out the binary.
Thanks for the link to this thesis, very interesting.
[...] on pagetable.com, they managed to pull the original Apple I Basic off of its uber-old school cassette tape, and re-compile a working version of the code. And… [...]
Very cool! I’d love to have it under Linux. Is it opensourced or do you have any plan on porting it to Linux? Indeed, very well done!
Asking nicely for PPC binaries… please?
hah what a brilliant idea, just makes me wish I could actually understand basic to be able to make something cool with it
With a MacBook with 10.4, both BASIC binaries give me “Bus error” when I try them. Any ideas?
Nice thesis – please add me to the list of people asking nicely for source code.
Remember, this whole thing (Apple) started by taking advantage of Woz’ willingness to share.
It’s only fair to make your ‘Apple I BASIC interpreter’ available in source, so those of us who
run Linux or PowerPC processors can benefit.
Other folks wrote “open letters” to people who shared their BASIC interpreters.
- Ralph
The random number generator isn’t seeded differently per run, so you always get the same values. How did it work on the original hardware?
] cat random.bas
#!/usr/bin/env apple1basic
10 FOR I=1 TO 100
20 PRINT RND(100);” “;
30 NEXT I
40 PRINT
50 END
]
] ./random.bas
56 72 81 92 2 80 60 31 56 80 68 7 43 20 48 4 49 94 60 54 20 2 79 4 35 22 26 16 36 32 41 82 1 36 30 11 8 59 85 24 34 29 28 24 21 1 39 30 56 28 48 42 97 65 75 15 73 76 41 12 52 12 69 43 91 99 40 67 59 94 69 57 9 34 92 56 61 84 34 77 35 6 14 7 68 83 44 26 2 28 81 13 72 75 7 36 30 59 47 50
]
] ./random.bas
56 72 81 92 2 80 60 31 56 80 68 7 43 20 48 4 49 94 60 54 20 2 79 4 35 22 26 16 36 32 41 82 1 36 30 11 8 59 85 24 34 29 28 24 21 1 39 30 56 28 48 42 97 65 75 15 73 76 41 12 52 12 69 43 91 99 40 67 59 94 69 57 9 34 92 56 61 84 34 77 35 6 14 7 68 83 44 26 2 28 81 13 72 75 7 36 30 59 47 50
Awesome idea. Too bad I’m also getting the “Bus error” mentioned above on my 10.4.11 Mac Mini.
Hello ! I love Basic, I used ZX Spectrum, Commodore 64, PC XT, 286,386,486,P1,PII,PIII and P4 lots of Basics, GWBasic,QBasic, Visual Basic 1,4,6 and .NET and now Real Basic on My Power Mac G4@1.5 Ghz.
I need to use this script basic for PPC (becouse I love my Mac)and I want to make some script for it !! please ! if you will make some ppc versions please send me an E-mail.
This brings back some old and SCARY memories of programming PDP 11/45’s back in the 1970’s.
i want a gw basic application (downloadable, free) for my mac os x
+1 for a PPC port … please!
BTW, my Dad has a very old gwbasic script that he wants me to update. Will this apple1basic run a gwbasic script? Or am I comparing apples to oranges?
:-)
sjs
[...] all of Microsoft BASIC only depends on the CPU, makes no other assumptions on the hardware it runs on (be it Commodore, Apple, Atari, …), [...]
I love it. Are you generating assembly or using some intermediate representation like C? How portable would the resulting code be? Since you’re using POSIX IO, could you easily emit code for other IA32 (or amd64) POSIX systems or even portably for all POSIX systems? I’d love to run these, but am not a Mac user.
The ‘apple1basic’ program works fine, everything works as it should, as a script, and non-interactively. But, for some reason, the cbmbasic program only works interactively. When I try to run it as part of a script, it simply does nothing.
I’d love to have the source for this.
Then again, cbm basic for the C=64 is well documented. It seems like it should not be too hard for a good ‘c’ programmer to just write an implementation that would be portable.
I’m also asking nicely for PPC binaries. Please?
[...] A while back, I released Apple I BASIC and Commodore BASIC as a scripting language for Mac OS X 10.5 on Intel. It did not work on any other OS or on a different CPU type. [...]
Wow! This is an awesome idea. Commore 64 was my first computer and I loved it. I used to write quite a few simple programs on it. Let’s PEEK, POKE, and SYS
gettin’ bus error when I try to run as well. on an intel (macbook).
Nifty, but I’m running PPC, not Intel at home. :(
[...] Apple I BASIC as a native script interpreter on Mac OS X — http://www.pagetable.com/?p=35 [...]
Ok, how about a version of TI Extended Basic?
Please?
*THAT* was a powerful Basic!
Is there any chance of the Apple BASIC being ported to windows, like cbmbasic was? It rocks!