Actions

SCHG

Music Hacking/Pointer and Header Format

From Sonic Retro

Revision as of 05:11, 23 May 2011 by ValleyBell (talk | contribs)
Music Hacking: Pointer and Header Format | Voice and Note Editing | DAC Samples, Coordination Flags, Game Specifics, and Real-Time Music Editing | Other Games and Data Locations | Tricks of the Trade



Pointer format

Pointers, as they pertain to SMPS, are values used to locate data at any point in the file. In the context of music editing, pointers will be used to locate the start of each channel's notation data; in addition, they are also used to branch to certain portions of data within the actual data through the use of coordination flags. This section in particular will describe the format used in the song headers and within the branching flags--F6, F7, and F8, respectively.

68k SMPS

Header

Pointers in the header of a song are 16-bits (two bytes) and work relative to the beginning of the song file. For example, when working with a standalone piece of SMPS data, if the voice pointer reads 0180, you would go to offset $180 within the file to locate the voice data.

If you're working with a song inside a full compiled ROM, the process is similar--simply take the offset where the song data starts and add the voice pointer's value to calculate the offset of the data. So, for example, if your music is at offset $E8900 in the ROM, you'd take the voice pointer value--in this case, $180--and you'd add it to the offset in order to locate the data. In this particular instance, $E8A80 would be the resulting offset, and subsequently the location of the voice data in the song.

This pointer format applies to all pointers within the header of a piece of SMPS data.

Coordination Flags

In contrast to Z80 SMPS, the pointer format in branching coordination flags differs slightly. As before, each pointer is two bytes, but this time pointers are relative to the start of the pointer--not the start of the song file. To clarify, if you were using the format of the F7 flag--F7 xx yy zzzz--the pointer would be relative to the offset in the file where zzzz is stored.

Pointers in coordination flags use signed relative values to locate data both after and before the current location. To do this, there is an imposed limit of about $8000 bytes in either direction on how far one single flag can branch in the song. When dealing with these flags, a value of FFFF acts as zero; in other words, a pointer value of FFFF would branch to the current location--nowhere.

To branch ahead of the current location, one would increase the value beyond FFFF to jump ahead. So, for example, if our pointer was 0298, we would be branching ahead $299 bytes from our current location. Assuming the current location is $E8000, this branch would be locating data at offset $E8299. A general formula you could use in order to calculate the length of positive branches quickly would be to increase a pointer value by $1--this would help you get into the mindset of locating data more adeptly.

To branch before the current location, one would decrease the value beyond FFFF to jump back. So, for example, if our pointer was FFE8, we would be branching $17 bytes before the current location. Assuming our current location is, once again, $E8000, this branch would be locating data at offset $E7FE9. The easiest way to calculate the length of a negative branch would be to take the pointer value and subtract it from FFFF. In our previous example, subtracting FFE8 from FFFF gives a result of $17.

68k SMPS is unique in that each song is literally self-contained--a song can be stored at any offset within a ROM and the relative nature of the pointers will always locate data properly. This is a significant advantage over the Z80 variant of the engine, which requires all data to be at absolute offsets within a data bank.

Points of note:

  • Ristar's coordination flag pointers have $1 added to them, compared to the pointers in other 68k SMPS games. If you want to convert between the two, just add or subtract $1 thusly.
  • Some 68k SMPS games use the Sonic 3-style coordination flags.

Z80 SMPS

Z80 SMPS differs from its 68k counterpart in a few different ways.

First and foremost, unlike 68k SMPS, the same pointer format is used in both the coordination flags and the header. All pointers are stored in little-endian format due to the nature of the processor; in other words, the byte order is reversed. If a pointer reads 7880, you should mentally parse it as referring to bank offset 8078.

Secondly, pointers are absolute instead of relative, but are only absolute in terms of the current Z80 data bank. Pointer values will always start with a value of 8000, regardless of whether or not the bank itself is stored at an offset that contains 8000 as part of the address; this is so the music can be properly located in the context of the Z80 bank. So, for example, if the current Z80 bank is at offset $70000, a pointer value of 7880 (which, when swapped, becomes 8078) would be locating data at offset $70078.

When dealing with standalone Z80 SMPS files, it is required that you first make note of the starting offset of the song within its respective Z80 bank before you can properly calculate pointer values within the song. So, for example, if a song is located at offset $F0900 in the ROM, your starting offset for the song will be 8900. To calculate relative offsets within the file where data is stored, subtract the starting offset from your pointer value. So, for example, if our DAC pointer reads value 508E (which after swapping the bytes becomes 8E50), the relative offset of our DAC notation within the file will be offset $550, or $550 bytes from the start of the song file.

This process is relatively simpler for the SMPS variant used in the SMS version of Sonic 2; since all music data is contained in bank 2 ($8000-$FFFF), simply convert the pointer to big endian and use that as your absolute address in the ROM.

In addition to within Z80 SMPS data, this format is also used to locate data within a game's music pointer index.

Sonic 2 Final/Mega Man: Wily Wars

Sonic 2 is a special case amongst games that use the Z80 SMPS engine in that its music is compressed to individual files in the saxman compression, which are subsequently parsed within Z80 RAM.

In contrast to normal Z80 SMPS music, the only difference is that compressed music in Sonic 2 always has a starting offset of 1380. All operations regarding the calculation of offsets from pointers remains the same. It is, however, worth noting that not all music in Sonic 2 is compressed; exceptions are noted as such later on in the guide.

Mega Man: Wily Wars stores songs uncompressed, but also has music copied to Z80 RAM. The starting offset for this game is always $1002.

Header format

Mega Drive SMPS

All pointers in this section differ according to the game you are editing. Remember, relative pointers for 68k SMPS, and absolute little endian pointers for Z80 SMPS. The music header format listed is a universal format used in all incarnations of the SMPS engine except for Knuckles' Chaotix, which uses a slightly modified version to accommodate for the extra sound hardware (the PWM sound channels).

Byte offset Description
$00-$01 Voice pointer. This points to the location of the voice data, or instruments, in the song.
$02-$03 Channel setup. This is usually 0603, and means there are 1 DAC, 5 FM channels, and 3 PSG channels. Changing these bytes will either make the header larger or smaller, depending on what you change them to. If you want to use the 6th FM channel, the 6th FM channel will be located after the 5th FM channel modifier. The same applies if you decide to use the PSG noise channel. It will be located right after the instrument modifier for the 3rd PSG modifier.
$04-$05 Tempo modifier. First byte is the dividing timing, and the second is the main tempo modifier. Change the second byte to make the music faster or slower, and change the first byte to determine the range of tempo values you can achieve. The higher the divider, the slower the tempo can be.
$06-$07 DAC pointer. This channel is generally used for the drums you hear in the music, though it can be used to play any type of DAC sample available for use.
$08-$09 DAC modifier. Unused.
$0A-$0B FM channel 1 pointer. It points to FM channel 1.
$0C-$0D FM channel 1 modifier. First byte modifies pitch — that is, the initial channel key displacement, and second byte modifies volume (same for all).
  • NOTE: Volume works "backwards" - the lower the value, the higher the volume.
$0E-$0F FM channel 2 pointer.
$10-$11 FM channel 2 modifier
$12-$13 FM channel 3 pointer.
$14-$15 FM channel 3 modifier.
$16-$17 FM channel 4 pointer.
$18-$19 FM channel 4 modifier.
$1A-$1B FM channel 5 pointer.
$1C-$1D FM channel 5 modifier.
$1E-$1F PSG channel 1 pointer.
$20-$21 PSG channel 1 modifier.
$22-$23 Current PSG 1 instrument. First byte is redundant. Change the value to change the sound of the PSG tone produced.
$24-$25 PSG channel 2 pointer.
$26-$27 PSG channel 2 modifier.
$28-$29 Current PSG 2 instrument.
$2A-$2B PSG channel 3 pointer.
$2C-$2D PSG channel 3 modifier.
$2E-$2F Current PSG 3 Instrument.

32X SMPS

The format for the SMPS music header is slightly different to accommodate for the 32x's extra sound hardware.

Word offset Description
$00-$01 Voice pointer.
$02-$03 Channel setup.
$04-$05 Tempo modifier.
$06-$07 FM channel 1 pointer.
$08-$09 FM channel 1 modifier.
$0A-$0B FM channel 2 pointer.
$0C-$0D FM channel 2 modifier.
$0E-$0F FM channel 3 pointer.
$10-$11 FM channel 3 modifier.
$12-$13 FM channel 4 pointer.
$14-$15 FM channel 4 modifier.
$16-$17 FM channel 5 pointer.
$18-$19 FM channel 5 modifier.
$1A-$1B FM channel 6 pointer.
$1C-$1D FM channel 6 modifier.
$1E-$1F PSG channel 1 pointer.
$20-$21 PSG channel 1 modifier.
$22-$23 Current PSG 1 instrument.
$24-$25 PSG channel 2 pointer.
$26-$27 PSG channel 2 modifier.
$28-$29 Current PSG 2 instrument.
$2A-$2B PSG channel 3 pointer.
$2C-$2D PSG channel 3 modifier.
$2E-$2F Current PSG 3 instrument.
$30-$31 PWM channel 1 pointer. This will point to one of the four available PWM channels used for percussion and other samples that can be played in the song. It works exactly like DAC, except there are more channels available for use.
$32-$33 PWM channel 1 modifier. Unlike DAC, the pitch and volume of a PWM channel can be changed, and in the same way as any other melodic sound channel. However, the volume byte will work by output strength, and not resistance--in other words, the higher the value, the louder the sample.
$34-$35 PWM channel 2 pointer.
$36-$37 PWM channel 2 modifier.
$38-$39 PWM channel 3 pointer.
$3A-$3B PWM channel 3 modifier.
$3C-$3D PWM channel 4 pointer.
$3E-$3F PWM channel 4 modifier.

Master System/Game Gear SMPS

Since the SMS only has 4 PSG channels (3 tone, 1 noise), the header format is changed to accomodate this.

Word offset Description
$00-$01 Unknown - pointer to PSG envelope data?
$02-$03 Channel setup. Only the first byte is used, and it can range from $01 to $04.
$04-$05 Tempo modifier.
$06-$07 PSG channel 1 pointer.
$08-$09 PSG channel 1 modifier.
$0A-$0B PSG channel 2 pointer.
$0C-$0D PSG channel 2 modifier.
$0E-$0F PSG channel 3 pointer.
$10-$11 PSG channel 3 modifier.
$12-$13 PSG channel 4 pointer. Channel 4 is always the noise channel.
$14-$15 PSG channel 4 modifier.

Understanding the header is essential to editing music. This is the basis of basic music editing, such as pitch and tempo editing. Once you understand the pointers and the header, then you are ready to start learning more advanced things.

Sega CD SMPS ("SMPS-PCM")

Since SMPS-PCM runs on a CPU that can only access the Sega CD's PCM chip which hooks into a global sample bank (for each SMPS program on disc), the header is different:

Offset Size Description
$00 Word 0 - as SMPS grabs sample data from its own bank
$02 Byte Channel setup. Usually 8 or 9.
$03 Byte 0 - only one sound source is used.
$04-$05 Byte, byte Tempo modifier; see above.
$06, $0A, $0E, etc. Word PCM channel n pointer
$08, $0C, $10, etc. Byte PCM channel n modifier. The signed value is added to the note value grabbed from the song; so if this is $FD (-$3) and the note byte in the song data is $93, it is treated as if it was a byte $90 instead. Coordination flag $FB changes this later.
$09, $0D, $11, etc. Byte Unknown (possibly channel pan modifier; L/R outputs have additional individual volumes)
Sonic Community Hacking Guide
General
SonED2 Manual | Subroutine Equivalency List
Game-Specific
Sonic the Hedgehog (16-bit) | Sonic the Hedgehog (8-bit) | Sonic CD (prototype 510) | Sonic CD | Sonic CD (PC) | Sonic CD (2011) | Sonic 2 (Simon Wai prototype) | Sonic 2 (16-bit) | Sonic 2 (Master System) | Sonic 3 | Sonic 3 & Knuckles | Chaotix | Sonic Jam | Sonic Jam 6 | Sonic Adventure | Sonic Adventure DX: Director's Cut | Sonic Adventure DX: PC | Sonic Adventure (2010) | Sonic Adventure 2 | Sonic Adventure 2: Battle | Sonic Adventure 2 (PC) | Sonic Heroes | Sonic Riders | Sonic the Hedgehog (2006) | Sonic & Sega All-Stars Racing | Sonic Unleashed (Xbox 360/PS3) | Sonic Colours | Sonic Generations | Sonic Forces
Technical information
Sonic Eraser | Sonic 2 (Nick Arcade prototype) | Sonic CD (prototype; 1992-12-04) | Dr. Robotnik's Mean Bean Machine | Sonic Triple Trouble | Tails Adventures | Sonic Crackers | Sonic 3D: Flickies' Island | Sonic & Knuckles Collection | Sonic R | Sonic Shuffle | Sonic Advance | Sonic Advance 3 | Sonic Battle | Shadow the Hedgehog | Sonic Rush | Sonic Classic Collection | Sonic Free Riders | Sonic Lost World
Legacy Guides
The Nemesis Hacking Guides The Esrael Hacking Guides
ROM: Sonic 1 | Sonic 2 | Sonic 2 Beta | Sonic 3

Savestate: Sonic 1 | Sonic 2 Beta/Final | Sonic 3

Sonic 1 (English / Portuguese) | Sonic 2 Beta (English / Portuguese) | Sonic 2 and Knuckles (English / Portuguese)
Move to Sega Retro
Number Systems (or scrap) | Assembly Hacking Guide | 68000 Instruction Set | 68000 ASM-to-Hex Code Reference | SMPS Music Hacking Guide | Mega Drive technical information