{"id":35,"date":"2008-07-18T22:33:24","date_gmt":"2008-07-19T06:33:24","guid":{"rendered":"http:\/\/www.pagetable.com\/?p=35"},"modified":"2008-07-18T22:33:24","modified_gmt":"2008-07-19T06:33:24","slug":"apple-i-basic-as-a-mac-os-x-scripting-language","status":"publish","type":"post","link":"https:\/\/www.pagetable.com\/?p=35","title":{"rendered":"Apple I BASIC as a Mac OS X Scripting Language"},"content":{"rendered":"<p><i>Update<\/i>: <a href=\"http:\/\/www.pagetable.com\/?p=48\">Commodore BASIC as a Scripting Language for UNIX and Windows &#8211; now Open Source<\/a><\/p>\n<p>Recently, we <a href=\"http:\/\/www.pagetable.com\/?p=32\">reconstructed a perfect copy of Apple I BASIC<\/a>, the first piece of software Apple ever sold &#8211; in 1976. Now it is time to make something useful out of it. Wouldn&#8217;t it be nice if you could use Apple I BASIC to replace, say, Perl? Wouldn&#8217;t it be nice if you could do this:<\/p>\n<pre>\n$ cat reverse.bas\n#!\/usr\/bin\/apple1basic\n10 DIM A$(100)\n20 INPUT A$\n30 FOR I = LEN(A$) TO 1 STEP -1\n40 PRINT A$(I,I);\n50 NEXT I\n60 PRINT\n70 END\n$ chmod a+x reverse.bas\n$ echo MICHAEL STEIL | .\/reverse.bas\nLIETS LEAHCIM\n$\n<\/pre>\n<p>Here is Apple I BASIC as a scripting language for Mac OS X Intel:<\/p>\n<p><a href=\"http:\/\/www.weihenstephan.org\/~michaste\/pagetable\/recompiler\/apple1basic_osx.zip\">apple1basic_osx.zip<\/a><\/p>\n<p>Just yet another Apple I emulator for Mac? No, it is not. There are some very important differences:<\/p>\n<ul>\n<li>The &#8220;apple1basic&#8221; executable is a statically recompiled version of the original binary. All code is running natively.<\/li>\n<li>&#8220;apple1basic&#8221; plugs right into UNIX stdin and stdout.<\/li>\n<li>You can pass &#8220;apple1basic&#8221; the filename of a BASIC program to run.<\/li>\n<li>You can run BASIC programs like shell scripts.<\/li>\n<\/ul>\n<p>Let&#8217;s play with it for a bit. First, copy &#8220;apple1basic&#8221; to \/usr\/bin:<\/p>\n<pre>\n$ sudo cp apple1basic \/usr\/bin\n<\/pre>\n<p>Let&#8217;s try direct mode first:<\/p>\n<pre>\n$ apple1basic\n>PRINT\"HELLO WORLD!\"\nHELLO WORLD!\n>\n<\/pre>\n<p>Now let&#8217;s write a small program:<\/p>\n<p><pre>$ apple1basic\n>10 FOR I = 1 TO 10\n>20 TAB I: PRINT \"HELLO WORLD!\"\n>30 NEXT I\n>40 END\n>RUN\nHELLO WORLD!\n HELLO WORLD!\n  HELLO WORLD!\n   HELLO WORLD!\n    HELLO WORLD!\n     HELLO WORLD!\n      HELLO WORLD!\n       HELLO WORLD!\n        HELLO WORLD!\n         HELLO WORLD!\n>\n<\/pre>\n<p>We can tell apple1basic to run a BASIC program from a file, too:<\/p>\n<pre>\n$ cat hello.bas\n10 FOR I = 1 TO 10\n20 TAB I: PRINT \"HELLO WORLD!\"\n30 NEXT I\n40 END\n$ apple1basic hello.bas\nHELLO WORLD!\n HELLO WORLD!\n  HELLO WORLD!\n   HELLO WORLD!\n    HELLO WORLD!\n     HELLO WORLD!\n      HELLO WORLD!\n       HELLO WORLD!\n        HELLO WORLD!\n         HELLO WORLD!\n$\n<\/pre>\n<p>apple1basic can be interactive:<\/p>\n<pre>\n$ cat name.bas\n10 DIM N$(20)\n20 PRINT \"WHAT IS YOUR NAME\";\n30 INPUT N$\n40 PRINT \"HELLO, \"; N$; \"!\"\n50 END\n$ apple1basic name.bas\nWHAT IS YOUR NAME?MICHAEL\nHELLO, MICHAEL!\n$\n<\/pre>\n<p>apple1basic supports redirection of stdin and stdout. Note that if stdin is a pipe, &#8220;INPUT&#8221; doesn&#8217;t print the &#8220;?&#8221;:<\/p>\n<pre>\n$ cat reverse.bas\n10 DIM A$(100)\n20 INPUT A$\n30 FOR I = LEN(A$) TO 1 STEP -1\n40 PRINT A$(I,I);\n50 NEXT I\n60 PRINT\n70 END\n$ echo MICHAEL STEIL | apple1basic reverse.bas\nLIETS LEAHCIM\n$\n<\/pre>\n<p>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:<\/p>\n<pre>\n$ cat reverse.bas\n<b>#!\/usr\/bin\/apple1basic<\/b>\n10 DIM A$(100)\n20 INPUT A$\n30 FOR I = LEN(A$) TO 1 STEP -1\n40 PRINT A$(I,I);\n50 NEXT I\n60 END\n$ chmod a+x reverse.bas\n$ echo MICHAEL STEIL | <b>.\/reverse.bas<\/b>\nLIETS LEAHCIM\n$\n<\/pre>\n<h3>Some more programs<\/h3>\n<p>These games, written for the Apple I in the 1970s, have been taken from <a href=\"http:\/\/www.brielcomputers.com\/replica1.html\">this<\/a> and other sites and converted from tokenized hexcode into ASCII.<\/p>\n<ul>\n<li><a href=\"http:\/\/www.weihenstephan.org\/~michaste\/pagetable\/recompiler\/21.bas\">21.bas<\/a>: Blackjack<\/li>\n<li><a href=\"http:\/\/www.weihenstephan.org\/~michaste\/pagetable\/recompiler\/aceyducey.bas\">aceyducey.bas<\/a>: Card Game<\/li>\n<li><a href=\"http:\/\/www.weihenstephan.org\/~michaste\/pagetable\/recompiler\/bowl.bas\">bowl.bas<\/a>: Bowling Game<\/li>\n<li><a href=\"http:\/\/www.weihenstephan.org\/~michaste\/pagetable\/recompiler\/buzzword.bas\">buzzword.bas<\/a>: Buzzword Generator<\/li>\n<li><a href=\"http:\/\/www.weihenstephan.org\/~michaste\/pagetable\/recompiler\/crap.bas\">crap.bas<\/a>: Crap Game<\/li>\n<li><a href=\"http:\/\/www.weihenstephan.org\/~michaste\/pagetable\/recompiler\/slots.bas\">slots.bas<\/a>: Slot Machine<\/li>\n<li><a href=\"http:\/\/www.weihenstephan.org\/~michaste\/pagetable\/recompiler\/startrek.bas\">startrek.bas<\/a>: Star Trek<\/li>\n<\/ul>\n<p>You can also download <a href=\"http:\/\/www.weihenstephan.org\/~michaste\/pagetable\/recompiler\/hanoi-apple1.bas\">hanoi-apple1.bas<\/a>, a fixed version of Amit Singh&#8217;s BASIC program from his <a href=\"http:\/\/www.kernelthread.com\/hanoi\/\">Hanoimania<\/a> project.<\/p>\n<h3>How it is done<\/h3>\n<p>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, <a href=\"http:\/\/softpear.sourceforge.net\/down\/steil-recompilation.pdf\">an interpreter can only get up to 1\/10 of an emulated cycle per native cycle<\/a>.)<\/p>\n<p>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 &#8220;RUN&#8221; command. All following input will be read from stdin, and as soon as the code to print the &#8220;>&#8221; prompt is detected, the output handler quits the application.<\/p>\n<h3>Commodore BASIC \/ Microsoft BASIC 6502<\/h3>\n<p>I have done the same thing to the 9 KB Microsoft BASIC for 6502 taken from the Commodore 64 ROM.<\/p>\n<p><a href=\"http:\/\/www.weihenstephan.org\/~michaste\/pagetable\/recompiler\/cbmbasic_osx.zip\">cbmbasic_osx.zip<\/a><\/p>\n<pre>\n$ cbmbasic\n\n    **** COMMODORE 64 BASIC V2 ****\n\n 64K RAM SYSTEM  38911 BASIC BYTES FREE\n\nREADY.\n_\n<\/pre>\n<p>It has many of the same features as Apple I BASIC: It discards the banner and the &#8220;READY.&#8221; prompt output when runnig in non-interactive mode, accepts a BASIC file as a parameter, and can be used as a script interpreter.<\/p>\n<h3>But&#8230; why??<\/h3>\n<p>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.<\/p>\n<p>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 adv\u0005antage of working with really fast software.<\/p>\n<p>And yes, I think there is a lot of useful vintage code out there.<\/p>\n<h3>Links<\/h3>\n<ul>\n<li><a href=\"http:\/\/www.applefritter.com\/node\/4103\">Apple I BASIC Users Manual<\/a><\/li>\n<li><a href=\"http:\/\/www.applefritter.com\/node\/2859\">Apple I BASIC Language Overview<\/a>\u0001<\/li>\n<li><a href=\"http:\/\/www.sbprojects.com\/projects\/apple1\/a1basic.htm\">More Apple I BASIC Info<\/a><\/li>\n<li><i>Michael Steil<\/i>: <a href=\"http:\/\/softpear.sourceforge.net\/down\/steil-recompilation.pdf\">Dynamic Recompilation of Binary<br \/>\nRISC Code for CISC Architectures<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Update: Commodore BASIC as a Scripting Language for UNIX and Windows &#8211; now Open Source Recently, we reconstructed a perfect copy of Apple I BASIC, the first piece of software Apple ever sold &#8211; in 1976. Now it is time to make something useful out of it. Wouldn&#8217;t it be nice if you could use &#8230; <a title=\"Apple I BASIC as a Mac OS X Scripting Language\" class=\"read-more\" href=\"https:\/\/www.pagetable.com\/?p=35\" aria-label=\"Read more about Apple I BASIC as a Mac OS X Scripting Language\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,4,6,17],"tags":[],"class_list":["post-35","post","type-post","status-publish","format-standard","hentry","category-2","category-apple","category-basic","category-hacks"],"_links":{"self":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/35","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=35"}],"version-history":[{"count":0,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/35\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=35"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=35"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=35"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}