{"id":32,"date":"2008-07-14T00:29:52","date_gmt":"2008-07-14T08:29:52","guid":{"rendered":"http:\/\/www.pagetable.com\/?p=32"},"modified":"2008-07-14T00:29:52","modified_gmt":"2008-07-14T08:29:52","slug":"1200-baud-archeology-reconstructing-apple-i-basic-from-a-cassette-tape","status":"publish","type":"post","link":"https:\/\/www.pagetable.com\/?p=32","title":{"rendered":"1200 Baud Archeology: Reconstructing Apple I BASIC from a Cassette Tape"},"content":{"rendered":"<p>The <a href=\"http:\/\/www.weihenstephan.org\/~michaste\/temp\/pagetable\/apple1basic.mp3\">audio file<\/a> that was <a href=\"http:\/\/www.pagetable.com\/?p=31\">posted two weeks ago<\/a> is indeed a very important artifact of computer history: It is a recording of the &#8220;<a href=\"http:\/\/www.applefritter.com\/node\/2859\">Apple I BASIC<\/a>&#8221; cassette tape that came with the Apple I. It is the first piece of Software ever sold by Apple (not counting computer firmware).<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.weihenstephan.org\/~michaste\/temp\/pagetable\/apple1basic.jpg\"><\/p>\n<p>Here is the first confirmed perfect dump of the 4096 bytes: <a href=\"http:\/\/www.weihenstephan.org\/~michaste\/temp\/pagetable\/apple1basic.bin\">apple1basic.bin<\/a><\/p>\n<p>The Apple I is extremely rare. Only 200 were built, and less than 100 are believed to be in existence. Neither Steve nor Woz own an Apple I any more, and neither does Apple Inc. <i>(Update: <a href=\"http:\/\/entertainment.slashdot.org\/comments.pl?sid=614033&#038;cid=24198317\">Woz still owns some<\/a>.)<\/i> The cassettes are even rarer, as not every Apple I came with one. There has not been a dump of the tape until 2002, when Achim Breidenbach of <a href=\"http:\/\/www.boinx.com\/\">Boinx Software<\/a> got an MP3 recording of an original Apple 1 BASIC tape by Larry Nelson, <a href=\"http:\/\/www.applefritter.com\/apple1\">an Apple I owner<\/a>, and, with a little help from his father (who worked with an Apple I back in 1976), managed to decode it by writing a program &#8211; in GFA BASIC on an Atari ST. Here is a screenshot of the visualization this program could provide:<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.weihenstephan.org\/~michaste\/temp\/pagetable\/apple1basic-waveform-atari.png\"><\/p>\n<p>Achim wrote an <a href=\"http:\/\/www.google.com\/search?q=sim6502\">Apple I emulator<\/a>, included a commented disassembly of his Apple I BASIC dump, and published it on the internet. Other people continued working on the disassembly and changed instructions that they thought were mistakes in the dump. <a href=\"http:\/\/members.aol.com\/MJMahon\/AP1BASIC.txt\">The only dump that can be easily found today<\/a> includes these changes. It was time to analyze the tape again and get an authoritative dump of the 4096 bytes.<\/p>\n<p>So here is how to decode the signal. Let us first open the <a href=\"http:\/\/www.weihenstephan.org\/~michaste\/temp\/pagetable\/apple1basic.mp3\">audio file<\/a> in Audacity and look at the waveform. The signal is mono, and as it turns out that the quality of the left channel is better, let us delete the other channel. This is what the whole ~35 second recording looks like:<\/a><\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.weihenstephan.org\/~michaste\/temp\/pagetable\/apple1basic-waveform1.png\"><\/p>\n<p>There is silence at the beginning and at the end &#8211; but we can just as well hear that. We need to zoom in to see the actual waveform. From about 2 seconds to 12.4 seconds, when we hear a continuous beep, the signal signal consists of uniform waves:<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.weihenstephan.org\/~michaste\/temp\/pagetable\/apple1basic-waveform2.png\"><\/p>\n<p>Afterwards, during what sounds like noise, the waveform looks very different:  There are shorter waves and loger waves.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.weihenstephan.org\/~michaste\/temp\/pagetable\/apple1basic-waveform3.png\"><\/p>\n<p>The original output of the Apple I when writing the tape was a square wave, but the signal was filtered by the properties of the magnetic tape, so high frequencies were removed, and the signal became rounder. On the way back in from tape, the op-amp of the <a href=\"http:\/\/www.sbprojects.com\/projects\/apple1\/aci.htm\">Cassette Interface<\/a> converted the signal back into a square wave by converting all samples above a certain value into 1, and all samples below into 0. While the threshold in the op-amp was fixed, it could be effectively manipulated by changing the output volume of the cassette player. Effect->Amplify in Audacity gives us the following picture:<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.weihenstephan.org\/~michaste\/temp\/pagetable\/apple1basic-waveform4.png\"><\/p>\n<p>It is now time to write a small program to measure and dump the width of the pulses. We need to be able to parametrize the threshold (the volume knob) to be able to try different settings. In Audacity, we have to save the file as &#8220;WAV&#8221; first, because it is easy to decode this file format: We just skip the 44 byte header, and every following byte is a signed 16 bit value representing the sample.<\/p>\n<p>First runs show us that all pulses in the first part of the file are around 56 samples long, while the rest of the file contains pulses which have a length of either around 22 or around 45. It seems the first part is a sync signal, so that the reader knows when the data starts. The two pulse lengths afterwards represent ones and zeros. It turns out that the shorter pulses are zeros; this way we get readable 6502 assembly code and some ASCII data (though with bit #7 set).<\/p>\n<p>Here is a hexdump of the first few bytes:<\/p>\n<pre>\n0000000 4c b0 e2 ad 11 d0 10 fb ad 10 d0 60 8a 29 20 f0\n0000010 23 a9 a0 85 e4 4c c9 e3 a9 20 c5 24 b0 0c a9 8d\n0000020 a0 07 20 c9 e3 a9 a0 88 d0 f8 a0 00 b1 e2 e6 e2\n0000030 d0 02 e6 e3 60 20 15 e7 20 76 e5 a5 e2 c5 e6 a5\n<\/pre>\n<p>In order to verify that our decoded data is correct, we must make sure that after the sync, there are only pulses that fall into the 22 or 45 category. If we play with the volume and find a volume region (i.e. different but similar volume settings) that has no pulse length errors and decodes into the same data, we can be confident that the data is correct. According to what is printed on the cassette, Apple 1 BASIC is supposed to reside in RAM at 0xE000 to 0xEFFF, so<br \/>\nthe length of the decoded data should be 4096 bytes.<\/p>\n<p>The following program is a possibly minimal implementation of the required algorithm:<\/p>\n<p><a href=\"http:\/\/www.weihenstephan.org\/~michaste\/temp\/pagetable\/apple1basic-decode.c\">apple1basic-decode.c<\/a><\/p>\n<pre>\n#include &lt;stdio.h&gt;\n\n#define DIVISOR 30\n\nint main() {\n    int index = 0, last = 0, direction = 1, syncstate = 0, bitindex = 0;\n    int distance;\n    unsigned char outbyte;\n    signed short sample;\n\n    while (!feof(stdin)) {\n        sample = getchar() | getchar()<<8;\n        if (!direction) {\n            if (sample>(32768\/DIVISOR)) {\n                distance = index-last;\n                if (distance<50) {\n                    if (syncstate == 2) {\n                        outbyte = outbyte << 1 | (distance<32? 0:1);\n                        if (!((++bitindex)&#038;7)) putchar(outbyte);\n                    }\n                    if (syncstate == 1) syncstate++;\n                } else if ((distance<70) &#038;&#038; !syncstate)\n                    syncstate++;\n                last = index;\n                direction++;\n            }\n        } else\n            if (sample<-(32768\/DIVISOR))\n                direction--;\n        index++;\n    }\n\n    return bitindex\/8;\n}\n<\/pre>\n<p>Run it like this:<\/p>\n<pre>\ncat apple1basic-mono.wav | .\/apple1basic-decode > apple1basic.bin\n<\/pre>\n<p>You can optionally specify a parameter to the program which overrides the default value of 30 for \"DIVISOR\". Values between ~25 and ~95 will reconstruct the data correctly.<\/p>\n<p><a href=\"http:\/\/www.weihenstephan.org\/~michaste\/temp\/pagetable\/apple1basic.bin\">apple1basic.bin<\/a><\/p>\n<p>If you can read 6502 assembly, you should definitely have a look at the disassembly, as this is very high quality (in the 1970s, this meant: very tightly compressed) code.<\/p>\n<p><i>Update<\/i>: You can run <a href=\"http:\/\/www.pagetable.com\/?p=35\">Apple I BASIC as a scripting language on Mac OS X<\/a> now!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The audio file that was posted two weeks ago is indeed a very important artifact of computer history: It is a recording of the &#8220;Apple I BASIC&#8221; cassette tape that came with the Apple I. It is the first piece of Software ever sold by Apple (not counting computer firmware). Here is the first confirmed &#8230; <a title=\"1200 Baud Archeology: Reconstructing Apple I BASIC from a Cassette Tape\" class=\"read-more\" href=\"https:\/\/www.pagetable.com\/?p=32\" aria-label=\"Read more about 1200 Baud Archeology: Reconstructing Apple I BASIC from a Cassette Tape\">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,5,6,17,29],"tags":[],"class_list":["post-32","post","type-post","status-publish","format-standard","hentry","category-2","category-apple","category-archeology","category-basic","category-hacks","category-tapes"],"_links":{"self":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/32","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=32"}],"version-history":[{"count":0,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/32\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=32"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=32"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=32"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}