Code critique: "Altair Music of a Sort"

Name of software:PROGRAM TO MAKE AN ALTAIR 8800 PLAY MUSIC
Programming language:Intel 8080 Assembly
Hardware requirements:Altair 8080, Altair 8080b
Software requirements:N/A
Author:Steven Dompier
Publication:People's Computer Company, Vol. 3, No. 5, May 1975.
(Reprinted without illustrations in: Dr. Dobb's Journal of Computer Calisthenics & Orthodontia, Vol. 1, No. 2, February 1976.)


Altair 8800b Fool on the Hill Demo, billdeg, 6 May 2009.

In 1975, shortly after assembling an Altair 8800 kit that he flew to Albuquerque to purchase, Steven Dompier wrote a program to play music "of a sort." The program took advantage of the lack of shielding on the microcomputer's case to radiate electromagnetic waves that could be detected by a nearby transistor radio. A demo of this oddball program at the Homebrew Computer Club is often included in historical accounts of the period, due in no small part to its dramatization in Steven Levy's Hackers:

"An amateur pilot, Dompier listened to a low-frequency radio broadcasting the weather while he worked, and after he tested a program to sort some numbers, a very strange thing happened when he hit the switch to 'run' the program: the radio started making ZIPPPP! ZIIIP! ZIIIIIIIIIPPPP! noises. [Hobbyist computing] involved no less than a major rewriting of computer history, and somehow this simple little music recital by Steve Dompier's Altair seemed the first step" -- Levy, S. (1984, 1994). Hackers, pp. 171. Penguin.

Although hyperbolic in his retelling, Levy's amazement with Dompier's program was shared by several others in the audience. Bill Gates, who was visiting the Homebrew Computer Club as a part of a nationwide "Altair tour" that summer, wrote about Dompier's program in the company newsletter, Computer Notes:

"The best demo programs I've seen for the Altair are the ones that control the signals on the bus to give musical output. Steven Dompier has an article about the musical program that he wrote for the Altair in the People's Computer Company publication. The article gives a listing of his program and the musical data for "The Fool on the Hill" and "Daisy." All that is required is an AM radio that sits near your Altair. His article gives an explanation of how to output different notes, spaces and rests. He doesn't explain why it works and I don't see why. Does anyone know?" -- Gates, B. (1975). "Software Contest Winners Announced." Computer Notes, Vol. 1, Issue Two, July.

Gates decision to highlight Dompier's program as the "best demo program" for the Altair 8800 seems strange given that Gates' personal investment in the Altair was as a platform for Micro-Soft BASIC. Not only was Dompier's program written in 8080 assembly and not BASIC, it does not demonstrate any specific feature of the Altair - rather, it appears to work by exploiting a design flaw. On the other hand, perhaps Dompier's program provided a much-needed spectacle for an otherwise confounding machine. Once a hobbyist completed the grand drama of assembling the kit, the Altair more or less sat on your desk whirring and blinking its LEDs regardless of what you keyed into its 256 bytes.

Dompier published his own account of the music program in the People's Computer Company newsletter (it was later reprinted in Dr. Dobb's without his illustrations.) Alongside the story of discovering RF emitting from his Altair kit, Dompier included the music player code and data for two songs: "Fool on the Hill" and "Daisy." Both the program and data were published as a vertical list of octal values with the assembly instructions translated into 8080 opcodes.

"I had just finished setting in a 'sort' program, and at the same time I was listening to a weather broadcast on a little transistor low frequency radio which was sitting next to the Altair. The closest sheet of music that I could find was "THE FOOL ON THE HILL", by the Beatles, so I translated it into OCTAL code, picked up the Altair, and headed down to Menlo Park for the 3rd meeting of the 'BAACUH-HBCC'.* I thought everyone there should see just what a computer can do! [...] This being the Altairs' first recital, it was a bit shy at first, and refused to power up [...] During the demanded encore, the machine did break into its own rendition of 'Daisy', apparently genetically inherited." -- Dompier, S. (1975). "A music program of sorts". People's Computer Company, Vol. 3, No. 5, May.

I chose to submit this program to the group for a few reasons. First, the accessibility of Dompier's code and the availability of microcomputer emulators provide an opportunity to use critical code studies as a tool for historical inquiry. Second, the program is of manageable size - there are only 28 instructions. And, third, Dompier's code is inextricably tied to the material characteristics of its platform: there is no guarantee that it will work on a later version of the Altair - never mind an Altair compatible with the same 8080 chip. The propagation of radio signals on which Dompier relies seem to be an idiosyncratic side effect of the manufacturing process behind the first batch of 8800s.

The code

A transcription of Steven Dompier's original code is reproduced at the bottom of the page but the octal values and 8080 mnemonics he used are not understood directly by any of the emulators we have available today. The table below includes translations from octal and 8080 mnemonics into binary/hex and Z80. Hopefully this makes it easier for you to get the code up and running in an emulator.

AddressInstructionOpcodeNotes
BinHexBinHex8080Z80
00000000000010000121LXI HLD HLMove the address of the first "note"
00000001010010000020of the song into registers HL
00000010020000000000(20,00: "Fool"; 78,00: "Daisy")
0000001103011111107eMOV A, MLD A,(HL)Load 'note' from this address into register A
000001000411111110feCPICPCompare first 'note' to FF
000001010511111111ff
000001100611001010caJZJP Z,If the note is FF, restart.
00000111070000000000
00001000080000000000
00001001090001011016MVI DLD D,Load 20 into register D
000010100a0010000020This will set the "tempo"
000010110b0000010105DCR BDEC BDecrement the value in register B
000011000c11000010c2JNZJP NZ,If register B is not zero, jump to 10
000011010d0001000010
000011100e0000000000
000011110f0100011046MOV B,MLD B,(HL)Load the current 'note' into register B
0001000010000011010dDCR CDEC CDecrement the value in register C
000100011111000010c2JNZJP NZ,If register C is not zero, jump to 0B
0001001012000010110b
00010011130000000000
00010100140001010115DCR DDEC DDecrement the value in register D
000101011511000010c2JNZJP NZ,If register D is not zero, jump to 0b
0001011016000010110b
00010111170000000000
0001100018001011002cINR LINC LIncrement the value in register L
000110011911000011c3JMPJP,Jump back to 03
000110101a0000001103
000110111b0000000000
00100000200100010145First "note" of "Fool on the Hill"
00100001210100010145
00100010220101010155
00100011230100000040
00100100240011100139
00100101250011001133
00100110260011001133
00100111270011001133
00101000280011100139
00101001290011001133
001010102a001011012d
001010112b001010112b
001011002c001010112b
001011012d001011012d
001011102e0011100139
001011112f0011001133
00110000300010011026
00110001310010011026
00110010320010011026
00110011330011100139
00110100340011001133
00110101350010011026
00110110360010011026
0011011137001010112b
00111000380010001022
00111001390010011026
001110103a0010011026
001110113b0011001133
001111003c0011100139
001111013d0011001133
001111103e001010112b
001111113f001010112b
01000000400011001133
0100000141001010112b
01000010420011100139
01000011430011001133
01000100440011001133
01000101450011100139
01000110460011001133
01000111470010011026
01001000480010011026
01001001490010011026
010010104a001010112b
010010114b0010001022
010011004c001010112b
010011014d0010011026
010011104e0010011026
010011114f001010112b
0101000050001011012d
0101000151001010112b
01010010520011100139
01010011530011011036
01010100540100000040
01010101550011100139
01010110560011100139
01010111570100000040
01011000580011100139
01011001590011011036
010110105a0011011036
010110115b0011100139
010111005c0100000040
010111015d0100000040
010111105e0100000040
010111115f0011100139
01100000600011011036
01100001610011000030
01100010620011000030
01100011630011011036
01100100640011100139
01100101650011011036
01100110660011011036
01100111670011000030
0110100068001010112b
01101001690010011026
011010106a0010011026
011010116b0010011026
011011006c0010011026
011011016d0010010024
011011106e0010011026
011011116f001010112b
0111000070001010112b
0111000171001010112b
0111001072001010112b
0111001173001010112b
01110100740000001002
01110101750000001002
01110110760000001002
011101117711111111ffLast "note" of Fool
0111100078000111001cFirst "note" of "Daisy"
0111100179000111001c
011110107a000111001c
011110117b0010001022
011111007c0010001022
011111017d0010001022
011111107e001010112b
011111117f001010112b
1000000080001010112b
10000001810011100139
10000010820011100139
10000011830011100139
10000100840011001133
1000010185001011012d
1000011086001010112b
10000111870011001133
10001000880011001133
1000100189001010112b
100010108a0011100139
100010118b0011100139
100011008c0011100139
100011018d0011100139
100011108e0011100139
100011118f0011100139
10010000900010011026
10010001910010011026
10010010920010011026
1001001193000111001c
1001010094000111001c
1001010195000111001c
10010110960010001022
10010111970010001022
10011000980010001022
1001100199001010112b
100110109a001010112b
100110119b001010112b
100111009c0011001133
100111019d001011012d
100111109e001010112b
100111119f0010011026
10100000a00010011026
10100001a10010001022
10100010a20010011026
10100011a30010011026
10100100a40010011026
10100101a50010011026
10100110a60010011026
10100111a70010001022
10101000a80010000020
10101001a90010001022
10101010aa0010011026
10101011ab000111001c
10101100ac000111001c
10101101ad0010001022
10101110ae0010011026
10101111af001010112b
10110000b0001010112b
10110001b1001010112b
10110010b2001010112b
10110011b30010011026
10110100b40010001022
10110101b50010001022
10110110b6001010112b
10110111b70011001133
10111000b80011001133
10111001b9001010112b
10111010ba0011001133
10111011bb0011100139
10111100bc0011100139
10111101bd0011100139
10111110be0011100139
10111111bf0011100139
11000000c0001010112b
11000001c1001010112b
11000010c20010001022
11000011c30010011026
11000100c40010011026
11000101c50011100139
11000110c6001010112b
11000111c7001010112b
11001000c80010001022
11001001c90010011026
11001010ca0010001022
11001011cb0010000020
11001100cc000111001c
11001101cd0010001022
11001110ce001010112b
11001111cf0010011026
11010000d00010011026
11010001d10011100139
11010010d2001010112b
11010011d3001010112b
11010100d4001010112b
11010101d5001010112b
11010110d60000001002
11010111d711111111ffLast "note" of "Daisy"

Note: Dompier expected PCC readers to modify the code to play different music. He included a table translating between octal values and the twelve-tone scale and left remarks next to the code for altering the tempo/duration of the song. I haven't come across records of any modified versions yet but they evidently existed:

"After the article was published, I received many phone calls (as far away as India) from people that wanted to play me the songs that they had entered into the Altair." -- Steve Dompier on the occasion of the 2005 Homebrew@30 event

How to run the code

Option 1: Altair emulation

altair32 emulator running steven dompier's music program

If you have access to Windows, you can run the Dompier code in the Altair32 8800 emulator. For this option, you'll want to use the binary code above. There's not a lot of documentation with the emulator itself but it so faithfully replicates the original that you can use the actual Altair 8800 Operators Manual[PDF] to figure out how to input and execute the program.

Option 2: 8080 emulation

If you have a new-ish browser, you can also run the code in Stefan Tramm's Javascript emulator of an Intel 8080 microcomputer. For this option, you have to use the hex values in the table above. You lose a little of the switches & LEDs romance with this option but the step-by-step execution displays the status of each register as you go which makes it a lot easier to understand what's happening.

Resources

Transcription of Dompier's original article

Altair Music of a Sort

IT WORKS!

I received my ALTAIR 8800 in the mail at 10 am, and 30 hours later it was up and running with only one bug in the memory! That turned out to be a scratch in a printed circut land that took 6 more hours to find. After that was fixed, everything worked!!

Now, what do you do with a machine that so far has no I/O boards or peripherals?? Well, there's always the front panel switches and machine language, so I was soon busy making up programs to test all of the 8080's functions; and getting a good set of caluses on my ten input devices! There's a lot of 8080 instructions!!

ZZZIIIPPP!

I had just finished setting in a 'sort' program, and at the same time I was listening to a weather broadcast on a little transistor low frequency radio, which was sitting next to the Altair. I hit the 'run' switch on the computer and it took off sorting the same list of numbers over and over again.

At the same time my radio also took off !!

The computer was sorting numbers and the radio was going ZZZIIIPP! ZZZIIPP! ZZZIIIPP!!!

"Well what da ya know! My first peripheral device!!!"

The radio was picking up the switching noise of the 8800! I tried some other programs to see what they sounded like, and after about 8 hours of messing around I had myself a program that could produce musical tones and actually make music; of a sort. (Or any other program you have!)

MUSIC!

The closest sheet of music that I could find was "THE FOOL ON THE HILL", by the Beatles, so I translated it into OCTAL code, picked up the Altair, and headed down to Menlo Park for the 3rd meeting of the `BAACUG-HBCC'.* I thought everyone there should see just what a computer can do!

* Initalization of "BAY AREA AMATEUR COMPUTER USERS GROUP-HOME BREW COMPUTER CLUB"

RECITAL!

This being the Altairs' first recital , it was a bit shy at first, and refused to power up. (Even though Freds tape recorder was plugged into the same wall outlet and working just fine.) One forty foot extension cord and half an hour later we were ready. Freds tape machine turned out to be running on its own battery power, and all of the wall plugs were dead!

The recital then proceeded with nary a glitch, much to everyones delight. (Although during the demanded encore, the machine did break into its own rendition of 'Daisy's apparently genetically inherited.)

PROGRAM TO MAKE AN ALTAIR 8800 PLAY MUSIC

000 LXI H   041
001 b2      xxx -   ADDRESS OF FIRST 
002 b3      xxx    DATA ENTRY 
003 MOV A,M 176
004 CPI     376
005 b2      377 -  START OVER DATA
006 JZ      312
007 b2      000
010 b3      000

011 MVI D   026
012 b2      xxx -   TEMPO DATA
013 DCR B   005 
014 JNZ     302
015 b2      020
016 b3      000
017 MOV B,M 106 TO RUN THE PROGRAM: 
                -------------------
020 DCR C   015 To run the program, push the 'RESET' switch,
021 JNZ     302 then push the 'RUN' switch.
022 b2      013 To stop the program, push the 'STOP' switch.
023 b3      000
024 DCR D   025 TO MAKE YOUR OWN MUSIC:
025 JNZ     302 ----------------------- 
026 b2      013 Begin loading your music data anyplace after
027 b3      000 address 034. Be sure to load the starting address

030 INR L   054 into H&L at address 002, 003.
031 JMP     303 Each data entry will be one beat of music.
032 b2      003
033 b3      000

OCTAL CODES FOR NOTES
---------------------
C   252
C#  240 LOW OCTAVE
D   230
D#  220
E   211
F   200
F#  172
G   162
G#  154
A   146
A#  140
B   132

C   125
C#  120 MIDDLE OCTAVE
D   114
D#  110
E   105
F   100
F#  075
G   071
G#  066
A   063
A#  060
B   055

C   053
C#  050 HIGH OCTAVE
D   046
D#  044
E   042
F   040
F#  036
G   034
G#  033
A   031
A#  030
B   026
C   025

Q   002 Note; This is the quietest of the data notes.
              It can be used for spaces and rests.
              You may also like to put a number of
              these quiet 'notes' at teh end of the
              music data, to give a space between playings.

Data For "THE FOOL ON THE HILL" Beatles

Address Data    Address Data 
------- ----    ------- ----

040     105     120     055
041     105     121     053
042     125     122     071
043     100     123     066
044     071     124     100
045     063     125     071
046     063     126     071
047     063     127     100

050     071     130     071
051     063     131     066
052     055     132     066
053     053     133     071
054     053     134     100
055     055     135     100
056     071     136     100
057     063     137     071

060     046     140     066
061     046     141     060
062     046     142     060
063     071     143     066
064     063     144     071
065     046     145     066
066     046     146     066
067     053     147     060

070     042     150     053
071     046     151     046
072     046     152     046
073     063     153     046
074     071     154     046
075     063     155     044
076     053     156     046
077     053     157     053

100     063     160     053
101     053     161     053
102     071     162     053
103     063     163     053
104     063     164     002
105     071     165     002
106     063     166     002
107     046     167     377

110     046     
111     046
112     053     
113     042
114     053     
115     046
116     046     
117     053

Data for "DAISY"

Address Data    Address Data 
------- ----    ------- ----

170     034     250     040
171     034     251     042
172     034     252     046
173     042     253     034
174     042     254     034
175     042     255     042
176     053     256     046
177     053     257     053

200     053     260     053
201     071     261     053
202     071     262     053
203     071     263     046
204     063     264     042
205     055     265     042
206     053     266     053
207     063     267     063

210     063     270     063
211     053     271     053
212     071     272     063
213     071     273     071
214     071     274     071
215     071     275     071
216     071     276     071
217     071     277     071

220     046     300     053
221     046     301     053
222     046     302     042
223     034     303     046
224     034     304     046
225     034     305     071
226     042     306     053
227     042     307     053

230     042     310     042
231     053     311     046
232     053     312     042
233     053     313     040
234     063     314     034
235     055     315     042
236     053     316     053
237     046     317     046

240     046     320     046
241     042     321     071
242     046     322     053
243     046     323     053
244     046     324     053
245     046     325     053
246     046     326     002
247     042     327     377

NOTES:

TEMPO;

The tempo is controlled by the value in address 012. Start out by trying 040.

TO PLAY BACKWARDS:

Put 377 in front of all music data.(to cause looping)
Change address 001 to read the END of the music data.
Change address 030 to DCR L (055).

TO PLAY ALL OF THE MEMORY:

Change address 001 data to a NOP (000)
Change address 004, 005, 006 to NOP (000)
This will cause program to read all of the memory, including the program instructions themselves.

RADIO INFORMATION:

A low frequency radio around 330 KC works best, but any AM radio will pick up the music at quiet places on the dial.

Set the radio on or very close to the computer, start the program, and turn the dial on the radio until you get good sound. Some places will be much better than others, and some will pick up different sounds from the computer. Also, try moving the radio to different positions on or around the computer. Just rotating the radio 90 degrees can make a lot of difference in the sound you will get.

With a little experimentation, you can make all kinds of interesting sounds. ie;sirens, ray-guns, etc.

Steven Dompier