F-Zero Sound Hacking Document (Written by MajinBlueDragon) Preface -------- To get the full effect of this document, you must be able to understand basic emulation terms such as pointers, offsets, &h, etc. You also must know your way around a hex editor. Also for your convenience, you should probably use Word Wrap if you are viewing this in Notepad, or else a few charts may not show up properly. Most importantly, you should note that alot of this data also applies to many other Super Nintendo games, with the eexception of adresses. The commands, among other things, can apply to any other game using this sound engine. Contents --------- - Intro - Engine and Commands - Instrument and Sample Tables - Sample Data - Demo Code - Locations Database - Credits Etc. Intro ---- Welcome to the world of SPC700 sound. You're probably reading this because you want to take that extra step in your hack to make it cool. Well, that's great, but it's gonna take alot of hard work and patience. Music hacking is NOT as easy as just copying a few bytes around. In fact, despite popular belief, you cannot do somthing so "simple" as inserting a MIDI, Wave, or MP3 as music. If anyone tells you otherwise, you have my permission to kick them in the teeth :) Here is why what everyone thinks is wrong. The SPC700 is not that powerful of a chip. In fact, it kinda sucks. Alot. It can only have 8 monophonic chanels, 3 of which F-Zero sacrifices to engine noise. It has a limited amount of space for everything and cannot hold more than 65KB of Memory. Yep. You have 65KB to fit everything you want into the game. So why do some game soundtracks sound so good? They took advantage of what little they had. Why can't you convert MIDIs etc. to go into it? Well if you reading this section, I explained that there are 8 monophonic channels. MIDI has 16 polyphonic channels. If this makes no sence to you, then just think of it like this. YOU CAN'T INSERT MIDIS. THX HAVE A NICE DAY. I can't seem to stress this enough, as the amount of e-mails and IMs I get asking about this is often times overwhelming. Perhaps this will put those questions to rest. Now that this is cleared out of the way, and you have a pretty decent idea of what your limitations are, I'm going to talk about the engine used by F-Zero, as well as many other Nintendo made games (for the reason, we'll refer to the engine as N-SPC format, for convenience purposes). To get the full effect of this document, you must be able to understand basic emulation terms such as pointers, offsets, &h, etc. You also must know your way around a hex editor. Engine and Commands ------------------- The N-SPC engine is pretty straight forward. It uses a pattern based system, and is perhaps the easiest in my experience to code for. It uses rhe standard SPC pointer format, which is almost too simple. Switch the high and low bytes, and subtract 1. Say you had an adress, like...4537. The pointer to that adress would be 3744. Now that this is out of the why, I should probably mention you'll be writting about a dozen or so pointers within your first 15 minutes of coding. Yep. Alot of work. I'll start out by explaining each part of the sound system, and its significance, and any related pointers. I'll start off small. There are sets of 8 pointers called track pointers. These point to the data of 8 individual channels. If not all channels are used, the remaining pointers are filled with FFFF. A set of 8 pointers is rquired for each section, or "pattern" of the song you make. The set of 8 pointers collectivly form a pattern. As a result, there are pointers pointing to each set. These are known as pattern pointers. You need to set one of these for each set of track pointers you create. Now in addition to this, there is one final pointer which points to the pattern pointers (basicly, it points to the first one). In my experience I've only ever had to play around with that pointer once, and in F-Zero it was located no where near the others (pattern and track pointers are at least closely knit, location wise), however this may not necessarily be the case for every game. With all this in mind, you're ready to set up your first track. But how, you may ask? Well, you may want to start by setting up the different variants that make your music sound cool - Panning, Echo, Vibrato, etc. Here is a pretty extensive list of (for the most part) all N-SPC commands. 00 - track end 01 [tv] - note length 1, t gate time, v velocity 02 [tv] - note length 2 03 [tv] - note length 3 04 [tv] - note length 4 .. 7f [tv] - note length 7F 80 - note off channel 81 - note 81 82 - note 82 83 - note 83 84 - note 84 .. c7 - note C7 c8 - note extend local track (double note value) c9 - note off local track ("rest") ca - unused cb - unused cc - unused cd - unused ce - unused cf - unused d0 - unused d1 - unused d2 - unused d3 - unused d4 - unused d5 - unused d6 - unused d7 - unused d8 - unused d9 - unused da - unused db - unused dc - unused dd - unused de - unused df - unused e0 ii - inst e1 pp - pan e2 tt pp - pan sweep e3 tt ss dd - vibrato e4 - unused e5 vv - global volume e6 tt vv - global volume ramp e7 ss - speed e8 tt ss - speed ramp e9 tt - global transpose ea tt - channel transpose eb tt ss dd - tremolo ec ?? ed vv - volume ee tt vv - volume ramp ef ll hh nn - call loop f0 ?? - f1 tt ss nn - pslide to f2 tt ss nn - pslide from f3 - unused f4 ff - fine tune f5 ?? ?? ?? - echo f6 - unused f7 ?? ?? ?? - surround f8 ?? ?? ?? f9 tt ss nn - pslide fa ?? fb ?? ?? fc - crash fd - crash fe - crash ff - crash Now that you know what commands are what, you're probably going to want to know the note values to make all those cool sounds! Here is a simple note chart, which will more or less satisy the need of any instrument you decide to choose. C C# D D# E F F# G G# A A# B 1 81 82 83 84 85 86 87 88 89 8A 8B 2 8C 8D 8E 8F 90 91 92 93 94 95 96 97 3 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 4 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF 5 B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB 6 BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 Note that this chart may be off by an octave or so for a few instruments, that's normal. It may just be using a different frequency. Also, most of F-Zero's Percussives use note &hA4 (note C4) for their "center" pitch. Oh! I almost forgot, to set anote length, put the hex number of the length before the note. If you set a value, you don't need to set it again unless you change from like, an eigth to a quarter note then back to eigth. Anways, here's a basic list of note lengths, obviously there are more than this :p 03 - 32nd Note 04 - 16th Note Tripplets 06 - 16th Note 08 - 8th Note Tripplets 0C - 8th Note 12 - Dotted 8th Note 18 - Quarter Note 24 - Dotted Quarter Note 30 - Half Note 48 - Dotted Half Note 60 - Whole Note Instrument and Sample Tables ----------------------------- You thought you were done with pointers at the end of last section, huh? Well, there is one last set of pointers, but you won't really be screwing with them unless you know what you are doing. In other words, don't touch them :p There is a table with pointers for the sample data, and another table for the envelope data for the instruments constructed from these samples. Now normally, the sample table is located at &h3D00 and the instrument at &h3E00 in the SPC. However, the guy who programed F-Zero apparently wanted to be difficult and moved the instrument table to &h0618 for whatever reason. In the ROM, the sample table is at &hE2B6 and the instrument table at &h821C. The sample table consists of two sets of pointers: the adress of the sample, and the adress of the sample's loop point. You need to set these two pointers for every sample you put in in order for it to work. If a sample such as a drum has no loop point, it is simply set to the end of the sample (or the start of the next sample. But that's the same thing :p). The instrument table consists of 6 bytes per instrument. The first instrument is assigned to the first sample in the sample table, the second to the second sample, etc. The 6 bytes are as follows: Instrument number, attack, Sustain, Gain, Middle C frequency hi-byte, Middle C frequency lo-byte. As for the sustain and gain, I may be off as to the exact purpose of those bytes. If I'm wrong and anyone wants to clear that up, then thanks. Even if I am wrong, it shouldn't matter unless you wanty to craft your own instrument to be percisly what you want. Which isn't necessary, because most of us are just fine copying instrument data (save the frequency) from an already existing instrument :p Sample Data ------------ Samples are located at &h4100 SPC adress,&hE34A ROM adress. &hE348 in ROM contains SPC pointer to adress in SPC data of sample location (should be 0040, which points to 4100 in the SPC.) Samples are compressed in BRR format, like in any other SNES game. If you came across sample data in another SNES game, you could copy it over, and try to set it up to work (I won't be explaining that here, however. It is a little bit more advanced for most people taking their first go at this.) Sample data in the SPC ends at about &HA178, and in the ROM ends at &h143C2. There is about &h6078 bytes worth of samples, going over this would overwrite songs in the SPC and probbaly some other SPC700-relative data in the ROM. However, if you found space in the ROM, you could try to repoint the samples (technicly, that can work in the SPC, but I don't suggest it, as when you are working in there you want to leave as much free space as possible for song coding, usualy. But to each their own). Here is a breif list of Instruments in F-zero, along with their corresponding hex numbers. 00 - Synth Chord 01 - Mellow Wave 1 02 - Mellow Wave 2 03 - Trumpet 1 04 - Distortion Noise 05 - Wave 1(Smooth) 06 - Wave 2(Attack) 07 - Electric Piano 1 08 - Fretless Bass 09 - Electric Bass 1 0A - Electric Bass 2 0B - Square Wave 0C - Clap 0D - Brush Hits 0E - Strings 0F - Electric Piano 2 10 - French Horn 11 - Bass Drum 12 - Snare Drum 1(Brush) 13 - Snare Drum 2 14 - Snare Drum 3 15 - Hi-Hat(Closed) 16 - Synth Brass 1 17 - Synth Brass 2 18 - Slap Bass 19 - Electric Noise 1A - Percussive Organ 1B - Banjo 1C - Tom Drum 1D - Saxophone 1 1E - Saxophone 2 1F - Reed Organ 20 - Electric Piano 3 21 - Electric Piano 4 22 - Wave 3 Demo Code --------- Alright. I'm going to walk you through your first song. Now it is a learning experience so here's the deal. I'm going to walk you through setting up the track. I'll walk you through setting up your pointers. I'm going to paste some small code for you to type in, and you can figure out what it means. If you've read the document, you'll have a good idea as to what it all is, and it isn't even a whole lot of code (only &h2E bytes to be exact.) Open up an SPC of F-Zero's Race Begin music. Go to the adress &h00A9. This is the ID tag, that say the title of the SPC and some other stuff no one really cares about (like the dumper. Wow you dumped an SPC, AREN'T YOU SPECIAL). At &h00A9, you are at the part which sets the time of the SPC. It's currently 4 seconds. We have the otpion of changing it to whatever we want, or go overboard and make it 16 minutes long. I like my second idea better (better to have too much than not enough :D), so go to the ASCII section of your hex editor and type 1019289. No period, though. That was just to end my sentence...er, yeah. Now, when you play your SPC, it should be 16 minutes long (or 15:59. But do we really need to get picky :p). Go to the adress &h06EE, you will see a pointer to &h06FE (meaning the pointer says &hFE05). Type in &hA407. Using your knowledge of SPC pointers, you should know that this leads to &h08A5. Now before you jump the gun and go to that adress, I'm going to teach you somthing cool. We're going to make the song loop, but we need to do somthing first. If you go to &h6EA, you'll notice a pointer that leads to the first pattern pointer I just had you change. Now you will also notice there is two bytes after it. This is bad, as we need 4 bytes to set a loop (In order for a song to loop, you type &hFF00 after the last pattern pointer, followed by a pointer to the pattern pointer who's tracks you want to loop back to). So how are we going to fix this dilema? A quick search for the pointer &hEA05 comes up with a result at the adress &h20D8. perfect. Now, we're just gonna repoint this to some of that convenient blank space up above the pattern pointers. Type in a pointer to &H05B0, and save this. Good job. Now, go to &h05B0 and type a pointer to &h06EE. After this, type &hFF00, followed by another pointer to &h05B0 (telling it to loop the pattern being pointed to at this adress). Great! Now, it is going to loop your song :) NOW. Go to &h08A5. I'm going to ask you to type in the following code. Do it by hand, copy and paste, whatever. Just make sure if you copy and paste that you overwrite. If an SPC gets expanded, it gets royally screwed up. don't EVER make an SPC larger or smaller than it already is, even one byte too many or few will cause it to go haywire. Okay so with out further ado, here is the code. ED D0 E7 20 E1 00 E0 00 0C A3 06 9E A3 18 AA 06 C9 C9 0C A3 AA AD AC A8 30 A3 06 C9 C9 A3 A5 30 A6 06 C9 C9 0C A3 A6 AA 40 A8 06 C9 C9 00 Using the information you have learned from this document, you should be able to figure out what this all means on your own. After this is all done, save and play back your SPC. Sound familliar? Be proud of yourself, you just wrote your first song :D If you remembered from the section on N-SPC commands, you'll remmeber than E0 changes the instrument. As you can see, it is set to 00 in this song. Just change it to whatever to hear other sounds. Play arund with the other things like voulme and speed and see what you get. Have fun :) Locations Data Base -------------------- I'm going to put in all the stuff here later. Stuff like the pointers for each song, etc. Right now, it's on my other pc, and I'm just too lazy to find it :p You do know where Race Start's music is, so from there you can just change the pointers and write your own stuff in the blank space of the SPC. Credits Etc. ------------- I'd like in this section to thank Bouche for first getting me interested in SPC700 hacking, for teaching me a thing or two about the N-SPC format, and for just plain being cool. I'd also like to thank d4s for explaining to me a little better what the bytes besides number and frequency in the instruments did, even though I forgot them :p. And last, I'd like to thank the people who read this, dosn't plan on ripping me off, and hopefully had every question answered so they don't need to ask if I can put in Nintendo 64 music directly :p I hope this has been a helpful document to you, and if not...oh well :p -MajinBlueDragon-