Wiki: SGC Format Specification

               The Sega Master System/Game Gear/Coleco Music Format

By Kevin Horton

10/21/03 - Revision 1.00
11/05/09 - Revision 2.00, finalized filename extention and a few other things
11/07/09 - Revision 2.10, fleshed out some things
12/30/09 - Revusion 2.50, Release version


This is a proposal for a ripped music format supporting the Sega Master System,
Game Gear, and Colecovision, and possibly others.

If you're familiar with the .GBS Gameboy music format, this will look fairly 
similar to that.  I have named it .SGC for "SMS, GG, CV".  The ordering of the
systems is somewhat arbitrary, and I googled for various iterations of the 
same letters.  .SGC came up the winner.

As for the format itself, it borrows heavily from the .GBS Gameboy music format,
and the NSF format.

Turns out, there's ALOT of systems that include a Z80 CPU and an SN76489 for
sound.  I can think of five right off the bat:  Sega Master System, Game Gear,
Colecovision, MSX, and the SG1000/3000 systems by Sega.

So far, I have outlined support for three of these systems.  I need additional
help to implement the SGxxxx stuff, and possibly any other systems I

MSX is specifically left out, since there's a decent MSX format already.  That MSX
format theoretically could handle SMS/GG/Coleco/SG1000 but it's ill-suited for that
task IMO, being designed mainly for MSX' banking and memory layouts.

The header is the same for all three currently supported systems, but the address
decoding and a few other things change depending on which system is being
emulated.  Without further ado, here is the header layout:


Here's what you need to emulate for each system:

        BIOS ROM | Z80 | mapper | YM2413
SMS    |            X       X        X   
GG     |            X       X            
CV     |    X       X                    

(Incidentally, the Sega mapper chip's part number is 315-5426).


00h-03h   STRING - "SGC",1Ah
    04h   BYTE   - version.  Currently 01h
    05h   BYTE   - PAL/NTSC flag.  00h = NTSC, 01h = PAL
    06h   BYTE   - # of scanlines between interrupts, 00h = not used.
                   NOTE: DO NOT USE THIS yet.  It is being reserved for this
    07h   BYTE   - reserved

08h,09h   WORD   - Start address of data in ROM space
0ah,0bh   WORD   - Init address
0ch,0dh   WORD   - Play address
0eh,0fh   WORD   - Stack pointer

10h,11h   WORD   - reserved
12h-1fh   WORD*7 - RST 08h through RST 38h pointers

20h-23h   BYTE   - Program words for the mapper chip, 20h = fffch, 
                   21h = fffdh, etc.

24h       BYTE   - Start song

25h       BYTE   - Total songs

26h       BYTE   - starting number for the first sound effect

27h       BYTE   - ending number for the last sound effect

28h       BYTE   - system type

29h-3fh   BYTE   - reserved

40h-5fh   STRING - Null terminated song name string

60h-7fh   STRING - Null terminated song author string

80h-9fh   STRING - Null terminated copyright string

a0h-EOF   BYTE   - the actual music/data code.

NOTE: All words are little endian, meaning the LSB is FIRST.


OK, a bit of explaination.

00h-03h  - this is the identification. It lets a player know what type
           of file this is.

04h      - version # (currently only version 1 is recognized)

05h      - NTSC/PAL flag.  0 = NTSC, 1 = PAL.  This changes the CPU clock and
           the frame interrupt rate.

06h      - Do not use this yet.  It will be used later IF it is required.
           Please let me know if this functionality is needed!

07h, etc - Reserved bytes:  Make sure these are set to 00h.  DO NOT use these
           for anything else!  It may break future tunes!! You have been 

08h, 09h - Start address.  This specifies in memory where the ROM data was
           ripped from.  Note: addresses must start at 0400h or higher.

0ah, 0bh - init address.  Load the accumulator with the desired song #
           (0 = song 1, 1 = song 2, etc) and then call this address.  It MUST
           end with an RET. 

0ch, 0dh - Play address.  Call this periodically to get music.  It should be
           called 50 times a second for PAL, 60 times a second for NTSC.  It
           must end with an RET.

0eh, 0fh - Stack pointer.  You need to spec a stack pointer to prevent
           over-writing stuff, depending on where RAM variables are at.  Ideally
           it should be placed where the game had it originally.

10h, 11h - not used at the moment.. it is here to fill the "hole" at RST 00h

12h- 1fh - RST pointers.  Put the address of the normal RST xx handler here.
           I.e. if RST 08h had "JMP 04000h" in it, use 4000h at 12h. (NOTE: The
           RST pointers are NOT USED on the Colecovision tunes, since they are
           vectored through the BIOS).

20h- 23h - Mapper Chip bytes.  (SMS/GG only) Use this to pre-configure the
           mapper. (see farther down for more info) If you do not use the mapper,
           and wish to have a "flat" address space from 00400h to 0bfffh, be sure
           to load it with these values:

           20h - 00h
           21h - 00h
           22h - 01h
           23h - 02h

24h      - Start song.  This is the first song that is run on loading.

25h      - Total songs.

26h      - First sound effect.  This is the entry # for the first sound effect.
           NOTE: it can and most likely WILL be larger than the total number
           of songs.  (I will explain this in a short section below)

27h      - Last sound effect.

28h      - System type.
           00h = SMS
           01h = GG                                                 
           02h = Colecovision
           03h and higher - not used yet.

29h- 3fh - Reserved. Maintain at 00h

40h- 5fh
60h- 7fh
80h- 9fh - Null terminated strings for song name, author, and copyright
           respectively. If the string is 32 bytes, no terminator is needed.
a0h      - your music data goes here.

System memory maps:


First, a word about the SMS/GG memory mapper.  This is the stock memory mapper
as found on the game cartridges.  It was very suitable for this purpose, and almost
every game used the same mapper.  Thus, it is good enough for our purposes.

This mapper sits in memory and is accessable through four memory addresses.  These
are FFFC through FFFF.  They are fully decoded and are not mirrored, and do not appear
anywhere else in memory.

fffch       - Control register (this is the 315-5426 mapper chip, almost)
        bits: 7 - not used
              6 - not used
              5 - not used
              4 - not used
              3 - RAM/ROM select 0 = ROM in bank 2, 1 = RAM in bank 2
              2 - not used*
              1 - not used
              0 - not used

        NOTE: *- the RAM page select was removed. It is not needed.

fffdh       - Page 0 select, select a 16K page. 

fffeh       - Page 1 select, select a 16K page.

ffffh       - Page 2 select, select a 16K page.

The SMS/GG memory map:

00000h-003FFh : Unbankable, unswitchable ROM.  This is always the first 1K of the ROM area.
                This lets you drop in a player stub for easier playback on *real* hardware
                and actual SMS/GG consoles.

00400h-03FFFh : ROM bank 0
04000h-07FFFh : ROM bank 1
08000h-0BFFFh : ROM bank 2 (or another 16K RAM bank)
0C000h-0DFFFh : RAM
0E000h-0FFFFh : Mirror of RAM at C000-DFFF

0FFFCh        : mapper register 0  (see above)
0FFFDh        : mapper register 1
0FFFEh        : mapper register 2
0FFFFh        : mapper register 3

The IO map between the SMS and GG are very similar.

006h      : Gamegear stereo control port (GG only)

07Eh,07Fh : SN76489 sound chip IO port (both)

090h,091h : YM2413 sound chip IO port (SMS only)

When in GG mode, you should disable the YM2413, and likewise when in SMS mode, you should disable
the GG's stereo control port.


00000h-01FFFh : BIOS ROM  (the Coleco's BIOS, which is usually named coleco.bin)

02000h-05FFFh : unused (you can put a player stub in here if you wish.  That is what I ended up doing)

06000h-07FFFh : 1K of RAM, mirrored 8 times

08000h-0FFFFh : ROM area where music data will be found.  There's no bankswitching
                on the Colecovision.

IO map:

0e0h - 0ffh   : SN76489 sound chip IO port

NOTE: There's no mapper registers to load, and the RST xxxh pointers do not need to be loaded,
since the BIOS vectors them through the cartridge ROM area!


Now here is how you load, initialize, and play a song.

SMS/GG loading:
1) allocate a chunk of memory to hold the music data.  4Mbytes is a good amount
simply because that is the maximum file size-  there are 256 banks of 16K each
which ends up being 4Mbytes.  Clear the first 48K of this buffer (0000h-bfffh).

2) Load the music data in starting at its load address.  So, if the music loads
in at 3000h,  load it starting at 3000h in the buffer, until EOF.

3) If you wish to play on hardware, or to make your code simpler, you can load a
player stub in at 00000-03ffh at this time.

4) Set up the bankswitching registers.  Load the four bytes from the header and 
write them to FFFCh-FFFFh.  (see below for more about this bankswitching)

5) Clear system RAM at C000-DFFF.

6) Set up your stack pointer from the SP value in the header.

7) Run the music initialization routine, with the desired song # in the accumulator.

8) Call the play address at 50Hz or 60Hz depending on the header's PAL/NTSC rate bit.

Colecovision loading:
1) Allocate a 64K chunk of memory to hold the music data + RAM + BIOS ROM.

2) Clear all 64K of this memory.  Load the Colecovision BIOS ROM at 0000-1FFFh.  This
is required by most tunes.

3) Load the music data in as specified by the header.  It must be in the range of 8000-FFFF.

4) Set up the stack pointer from the value in the header.

5) Load song # in the accimulator, and call the initialization routine.

6) Call the play address at 50/60 Hz as specified in the header.


About song and SFX numbering:  

Let's imagine we have the following list of tunes and SFX:

000h - first song
001h - second song
002h - third song
003h - first sound effect
004h - second sound effect
005h - last sound effect

The first song is always 000h, regardless of the tune.  The number of songs
specifies how many there are, which is 3.

Since the SFX are after the music, the start SFX number is 003h, and the
end SFX number is 005h.

Because you can specify the starting and ending SFX number, they don't have to
be directly after the music... So, you can have something  like this:

000h - first song
001h - second song
002h - third song
040h - first sound effect
041h - second sound effect
042h - last sound effect

So as before, the number of songs is 3, but the start SFX number is now 40h
and the end SFX number is now 42h.

Tips on use:

The first 1K is reserved (SMS/GG) so that player code can be written and plugged in
here to play the tunes on real hardware.  There's not a whole lot really to
it.  You just load the ROM data into the appropriate spot in memory, load
the mapper hardware (from the header), load the RST jumps (from the header),
load the stack pointer, load the value from 24h in the header into the 
accumulator, then call the init address.

Then, periodically call the play address at the correct NTSC or PAL rate.
That's about it.

NOTE:  song data cannot exceed 4Mbytes (SMS/GG) or 32K (CV).  I highly doubt
they will ever need to be this big, but that's how much space 8 bits of mapper
select gives you.

NOTE:  Interrupts may be used later to play digi sounds.. I don't know if
this is required or not.

NOTE:  When ripping songs, make sure the accumulator is what is used to
select the song.  Song #1 is 00h, song #2 is 01h, etc.  Also, make sure that
ONLY the accumulator can affect the selected song.  The flags and other
registers could be essentially random.  Some times, a little "stub" piece
of code has to be written and appended on the front or back that "converts"
the song number into what the music code is looking for.  An example would
be a small lookup table that selects the songs in a certain order.

Other things are possible, but for now this will good enough for starters.


Notes on the text strings.

To make things easier, please follow this convention!  It is the same that
is used by the HV SIDs collection, and I think it's very good.

If you do not know what a field should contain, please use the string "<?>"
to indicate it is not known, and "(?)" to indicate suspect information.
ALso, these fields are NOT for ripper credits.  Please put those at the end 
of the file or inside the file somewhere (this is what I usually do). If
you do not know the copyright date, use question marks as indicated.



Sonic the Hedgehog  <- proper game name
<?>                 <- field was not known
Sega 19??           <- exact copyright date is not known


Example Game
Guido 1998        <- everything is known


Example Game
Guido(?)          <- author's name is not known for certain
Guido 199?        <- The date is some time from 1990-1999


Sonic 1           <- no good.  This is not the complete name
Ripmaster 2000    <- Bad.  This is not the author of the song
dorks             <- nope.  Should be a copyright string



Latest Albums

Latest ReMixes