Update: I got sampled startup chimes working since I first posted this hack. See my latest post.
There’s been a cool project I’ve been working on for the last month or so, and I finally got to a good point where I could share what I’ve done! In summary, I have given my old Macintosh IIci a custom startup chime. Get ready for a long-winded post if you dare to read it all…or skip to the bottom if you just want to see and hear my custom IIci start up.
I’ve seen the question asked online. How do you change that sound a Mac makes immediately after you press the power button? The answer is inevitably “you can’t.” The sound is stored in the Mac’s ROM, making it impossible to change in software. It’s hiding somewhere in read-only memory chips (usually) soldered onto your Mac’s motherboard, nestled alongside other code that sets up all the Mac’s hardware when you first turn it on.
A year ago, I was talking with a coworker and we thought it would be awesome to try to hack the hardware to change the sound. I decided at that time that the IIci would be a perfect candidate because first of all, I have two of them. Second, its ROM chips are DIP (dual-inline package) chips, which I feel safe soldering. I just don’t have enough surface-mount soldering experience to risk damaging a motherboard. The big problem was that I found out the IIci’s startup sound is not a sampled sound. That means it isn’t just a sound file embedded into the ROM that you can easily replace. Instead, the Mac creates the sound from scratch, given a few instructions about what notes to play and how fast they should play. I’ll talk more about that further down in this post.
Well, about a month ago, I started thinking about this idea again and decided to go for it. I started out by booting up my old IIcis and deciding which one to hack. One of them had a very faint startup chime, it wouldn’t boot up unless left unplugged for a while, and the hard drive wouldn’t spin up. I decided to hack this one because it was in the worst shape of the two. After checking out the 68k Mac Liberation Army forums, it became clear that the faint startup chime was probably because the electrolytic capacitors on the motherboard had spewed electrolyte all over. I inspected the motherboard and sure enough, many of the capacitors had gunk nearby. Here’s an example of what I’m talking about:
Gross, right? This one happens to be right next to the power button. Perhaps it was causing the power button to work intermittently. Several of the other capacitors looked very similar, and in some cases it appeared that some of the electrolyte had actually gotten onto nearby components. This stuff is nasty and can corrode the motherboard over time, so I knew I had to get it off.
You may notice that these capacitors are surface-mount, and I just got done explaining how I’m not very comfortable with surface-mount soldering. Well, this isn’t terribly complicated soldering. I get nervous when I’m doing components with tens of pins very close together. This stuff wasn’t so bad–there’s a connection on each side, so you really just have to be careful about lifting pads. I did kind of lift one, but it is still electrically connected and everything’s fine. Anyway, I removed all the capacitors (including the through-hole ones as well). I could definitely tell the capacitors were bad when they began smelling like fish as I removed them. After taking them all out, I cleaned the board with 99% isopropyl alcohol (great for cleaning circuit boards! It evaporates almost instantly). I especially went over the areas that looked like the one pictured above. I then put in brand new capacitors.
While I had the board out, I removed the four ROM chips:
Removing them was pretty interesting. I did a lot of research on the web to see what other people thought about removing DIP chips in old forum posts, tutorials, videos, etc. The attitude I found online was mostly: “you can save the board or the chip, but not both.” Most suggestions were to cut the old chips out and then easily remove the remnants of the pins with a soldering iron. I also found a few videos of people who had vacuum desoldering guns — in particular, the Hakko 808. The thing had great reviews, so I got one. It’ll be nice to have in my set of tools anyway. It requires a lot of maintenance to keep it working and prevent the pump from getting messed up, but it’s definitely worth it just for the convenience. I really wanted to get the original ROM chips out intact, too, so I’m happy with that. I ran into a bit of trouble with either the ground or VCC pin (can’t remember which) because it takes longer to heat, but other than that, it was pretty easy to use it to remove the chips. I added a bit of extra solder to help the old solder heat up, and the gun sucked most of it out painlessly after that. Sometimes the chips did not lift out easily, even though I couldn’t find any visible solder with my eye loupe. I could tell that the solder was essentially gone, though, so I yanked the chip out with a bit of force to break the miniscule connection the solder still had, and it didn’t damage anything. That may have been stupid on my part, but it worked out for me!
So I replaced the ROMs with sockets:
Then, I stuck the original ROMs back in the sockets, and booted the IIci up. Success! Not only did it boot, but the sound was no longer faint and the power button worked every time, so the capacitor replacement fixed that. However, I knew I’d be using some kind of EEPROM in place of the original ROMs. Notice that one of the original ROMs says it is a TC531001CP. I somehow managed to find a (really old) datasheet for it online and discovered it uses a standard pinout that most 32-pin DIP devices also use.
I found a couple of reprogrammable SST chips of the same capacity which seem to fit the pinout and electrical specs: the SST27SF010 and the SST29EE010. It looks like Greenliant broke off from some of SST’s flash stuff, so they are actually now the GLS27SF010 and the GLS29EE010. I started out with the GLS27SF010. It has a couple of extra pins for programming the chip that are not connected on the IIci’s original ROM, so I had to tie them to VCC on the bottom of the motherboard. The GLS27SF010 was really annoying to program with my Willem programmer, though, because I had to change a jumper on the programmer board any time I wanted to erase it, and remove it to program it. So I switched to the GLS29EE010, which is a lot easier to use, is rated for many more erase cycles, and only has one pin that has to be connected to VCC. I read the contents of the original ROMs, burned the contents to my EEPROMs, stuck them in the motherboard, and it booted!
This completed the hardware portion of my hack. At this point I knew I could reprogram my EEPROMs, stick them in the IIci, and get it to do cool stuff.
I figured out that the four ROM chips are each 8-bit ROMs and the computer itself addresses 32 bits at once. How this works is one of the ROMs is connected to data lines 0 through 7, one is connected to 8 through 15, another is connected to 16 through 23, and the final one is connected to data lines 24 through 31. This means that as far as what the computer sees, to turn the four ROM images into a single ROM image I could disassemble, I had to take one byte at a time from each chip:
Chip 1, Byte 0 |
Chip 2, Byte 0 |
Chip 3, Byte 0 |
Chip 4, Byte 0 |
Chip 1, Byte 1 |
Chip 2, Byte 1 |
Chip 3, Byte 1 |
Chip 4, Byte 1 |
… |
I wrote a quick program to do this and was on my way.
In order to get any further, I had to turn to posts by Dennis Nedry on the 68k Mac Liberation Army forums. After following his posts around I was able to discover he had done a lot of the dirty work for ROM hacking. It turns out that Macs have a checksum in the first four bytes of their ROMs, and if it doesn’t match, the Mac won’t start. He had already figured all this out and written code to calculate and check the checksum of a ROM image. Without his work, there’s no way I would have gotten any further — I probably would have given up and just said “whatever — Apple’s protecting their ROM from being modified, I guess I’ll go mess around with something else.” Anyway, he had a ton of useful information here and here.
I started out with the basics and changed an icon. After some crazy searching in the ROM image, I was able to locate the floppy disk icon that appears if you boot a Mac without a startup disk present. There are actually three icons: a floppy disk, a floppy disk with a question mark on it, and a floppy disk with an X on it. When there’s no startup disk present, it alternates between the plain floppy disk and the floppy disk with a question mark. I changed the plain floppy disk icon to a black Apple logo, and the question mark floppy icon to a white Apple logo. Then I recalculated the checksum, split the ROM image into four files, burned them, stuck them into the IIci, and got this:
OK, that’s great! I had proven that I could do it. But then I wanted to move on to bigger and better things–my original goal. The custom startup chime.
At this point, I have to once again thank the people on the 68k Mac Liberation Army forums who gave me some great pointers on what to look for in my post. Trash80toHP_Mini was kind enough to scan a bunch of pages of an old out-of-print Apple hardware book for me as well. Let me tell you, there are some really cool people on those forums!
I started disassembling the ROM code and searching for places that referenced the Apple Sound Chip located at 0x50F14000 (and other repeated addresses as well). It took a while to get comfortable with 68k assembly, but it’s really not that bad. It’s actually kind of nice compared to x86 assembly in my opinion. This site was an invaluable reference. In the middle of this, I installed MPW (Apple’s old software development setup) and happened to discover that it included several Mac ROM maps! The IIci was one of those. I found some interesting labels in the ROM maps called BOOTBEEP, BOOTBEEP6, ERRORBEEP1, ERRORBEEP2, ERRORBEEP3, and ERRORBEEP4. Using that info, I later discovered that the ROM location I was in the middle of disassembling did indeed happen to be the startup chime.
Once I got a clue as to what the code was doing, I figured out a way to play the various chimes provided by writing a Mac app that played them. It turns out BOOTBEEP is just a handler that plays BOOTBEEP6, which is the actual startup chime. ERRORBEEP1 is the minor chord that plays in the chimes of death before the arpeggio. ERRORBEEP2 is a weird tone I had never heard before. ERRORBEEP3 is that same tone, with another note added at the end. ERRORBEEP4 is the familiar arpeggio error chime.
Each one of these sounds is a structure in the ROM that is passed to a ROM sound synthesis function that plays it using the Apple Sound Chip. When you hear the chimes of death, it’s actually playing two sounds consecutively: first ERRORBEEP1 for the chord, then ERRORBEEP4. After doing some serious disassembly of the sound synthesis function, I more or less understand what it does. The MAME source code was extremely useful to help me understand some of what the function was telling the Apple Sound Chip to do.
The synthesis function uses the wavetable synthesis capability of the sound chip. It is given one to four frequencies to play. It also is given several time values. One tells it how long before the wavetable should be updated. I believe it essentially specifies how quickly the waveform evolves and eventually fades out to nothing. Another time value sets how many steps should occur between playing each of the frequencies it’s given. Once a frequency is playing, it leaves it running and starts the next frequency in another voice. So at the end of the chord, all four voices are playing. If you make this a small number, it will play them all close together and it will be a chord like the startup chime. If you make it a large number, it will play them spaced apart, more like the death chime arpeggio. There is also a time value that specifies how long the sound should play in total. This would allow you to keep the sound going for a while after all the notes are playing. The frequencies are specified in terms of a 24-bit fixed-point increment value, basically telling the wavetable synthesizer how many entries in the wavetable to skip each time it reads a value. This effectively changes the frequency of the sound that plays based on what you set the increment value to.
It may sound complicated (it is!) but what it comes down to is this: the startup chime on a Mac IIci takes up 32 bytes of ROM space (not counting the synthesis function, which is reused for all the other startup sounds like the error chime). That’s pretty impressive, and you can see why they went that route to save ROM space.
So, here’s some info on the structure of a synthesized sound in the ROM:
- A 16-bit number that seems to specify some kind of a volume setting.
- A 32-bit number that sets how fast the waveform changes (a “step length” perhaps?)
- A 32-bit number that sets how many steps elapse before starting to play the next frequency in the list of frequencies
- A 32-bit number that sets how many steps before the sound is done.
- A 16-bit number that specifies the number of frequencies (maximum of 4, since the sound chip has 4 voices)
- For each frequency, a 32-bit number that contains the 24-bit fixed-point increment value I described earlier. The top 8 bits are not used.
Once I figured all this out, I just had to find some space in the ROM to put my Mario tune. I found what appears to be 35 KB of empty space, filled with many repetitions of an Apple copyright notice and a date. I made several of these sound structures for all the different chords I needed to play, and stuck them in there, along with code to play them in the correct sequence. I then modified the startup chime code to jump to my code instead. Here are the results:
Yes, that’s right. a Super Mario Bros IIci. It reboots after the first Happy Mac because I don’t have a PRAM battery installed on the motherboard. After that it continues booting fine.
I’d like to figure out how to make it play a sampled startup sound, but it may be difficult to figure out how to set up the sound chip for that mode. (Forget that, I now have sampled startup sounds working!) Anyway, let me know if you have any questions and I’ll try to answer them…and thanks again to everyone who helped me out with this project either directly or indirectly!
P.S.: Remember how I said the hard drive wouldn’t spin up? Well, I found a really, really old newsgroup posting online where someone with the exact same drive model had the exact same problem. The advice given? Give it a smack (not too gentle, but not too rough either) while it’s powered up. I hit it with a screwdriver and sure enough, it started spinning up. It’s been fine ever since through many power cycles! All the data was still intact. I certainly wouldn’t try that trick with the hard drives we have today, but I guess with stuff from the lower-density storage era, it’s not a terrible idea!