Sonic and Sega Retro Message Board: GEMS sound driver research - Sonic and Sega Retro Message Board

Jump to content

Hey there, Guest!  (Log In · Register) Help
Page 1 of 1
    Locked
    Locked Forum

GEMS sound driver research Happy new year

#1 User is offline Andlabs 

Posted 31 December 2009 - 07:26 PM

  • 「いっきまーす」
  • Posts: 2175
  • Joined: 11-July 08
  • Gender:Male
  • Project:Writing my own MD/Genesis sound driver :D
  • Wiki edits:7,061
So in the spirit of the new year, I decided to give you all what I know about GEMS's sequence format. I don't know everything yet, but I will soon enough v.png

First, read this post from a while ago. That post describes GEMS's general layout; this post describes the sequence format. From my notes:

CODE
The demonstration code for the Ship game included in the GEMS devkit shows that the song data format is very simple:

                [pointers to songs]
    song 0            [number of channels]
                [pointers to channels]
    song 1            [number of channels]
                [pointers to channels]
    ...
    song 0 channel 0    [sequencer data]
    song 0 channel 1    [sequencer data]
    ...

However, we don't know the format of the sequencer data, which is stored as raw data in the code. Fortunately, the GEMS devkit also contains the source code to the Z80 driver, as comments in the file GEMS\Z80.ASM. I went through the sound driver and documented the sequencer data format. Here is what I found by observing both the driver and how Sonic Spinball's sequencer data works.

The driver is basically an infinite loop of the form

    if a note is to be played
        play note for a given amount of time, known as "duration"
        release note
    else
        perform the command
    wait a specific amount of time, known as "delay" (except for some commands)

Each channel has their own delay and duration value, so you can set the duration and delay for a group of notes first, then issue the notes sequentially. This implies that unlike most sound drivers (and unlike most people's expectation of how music would be stored), GEMS expects the duration BEFORE the note.

Sequencer commands always start with a byte denoting what the command does.

    | 7 6   | 5 4 3 2 1 0 |
    |-------|-------------|
    |Command|Datum        |

Command    00    N - Note.
    01    Bit 5 off    Note
        Bit 5 on    Other command
    10    R - Duration. Consecutive Rs are combined BEFORE processing.
    11    D - Delay. Consecutive Ds are combined BEFORE processing.
Datum    If N, the whole byte is the note value:
        FM/Tone    0 is C0, 1 is C#0/Db0, ..., 95 is B7
        Noise    (?)
        DAC    For backwards compatibility with something (the comment is cut off for some reason), take note:
            48 (C4) is sample 0, 49 (C#4) is 1, ..., 95 (B7) is 47, 0 (C0) is 48, 1 (C#0) is 49, ..., 47 (B4) is 95 (96?) (?)
    If R, is the length of the duration in subbeats.
    If D, is the length of the delay in subbeats.

In the case that the Command bits are 01, a new table of commands is used in which the entire byte is the command:

Byte    Command
96    End of sequence. Used for sfx and jingles to end the song.
97    Change patch - next byte in the sequence is the new patch number.
98    (?) (byte parameter)
99    No operation
100    Start loop. Next byte in the sequence is the number of iterations, or 127 for an infinte loop. Loops are stored in a stack.
101    End loop. This completes the loop at the top of the stack.
102    Toggle retrigger mode. (?)
103    Toggle sustain mode. (?)
104    Set tempo for entire song. Next byte is tempo - 40 in beats per minute. (?)
105    Mute, though how it works is weird and involves MIDI channels (?)
106    Set channel priority. Priority goes from 0 (least) to 127 (most).
107    Start another song; next byte is the song number. Unsure if this merely saves the current song on the stack (todo)
108    Pitch bend. Next byte is the low byte of bend data (?), followed by high byte.
109    Set song to use SFX timebase.
110    Set DAC sample playback rate to value of the next byte (?).
111    Jump to position indicicated in next two bytes (lower byte first).
112    Store a byte into one of 32 byte-sized "mailboxes." Next byte is the mailbox number, followed by the value.
113    Conditional branch (if statement). The bytes thereafter take the form [mailbox #][condition][mailbox #][location].
    Condition    Test
    1        mailbox != mailbox
    2        mailbox > mailbox
    3        mailbox >= mailbox
    4        mailbox < mailbox
    5        mailbox <= mailbox
    all other    mailbox == mailbox
    If the expression yields true, the address given is jumped to; if false, do nothing. BEWARE: the address to jump to is a byte that is always offset from 0 — the if statement can only jump to addresses 0 through 255!
114    Even more functionality! Next byte is the command, followed by value
    Command        Action
    0        Stop sequence. (?)
    1        Pause sequence. (?)
    2        Resume all. Value ignred (but must still be specified).
    3        Pause music. (?) Value ignred (but must still be specified).
    4        Set master volume to value. Volume goes from 0 (loudest) to 127 (softest), just like the YM2612 FM operators's TL field.
    5        Set channel volume to value. Volume goes from 0 (loudest) to 127 (softest), just like the YM2612 FM operators's TL field.
    all other    Do nothing.

All other command values are ignored (" *** THIS COULD USE SOME FANCY ERROR DETECTION RIGHT ABOUT NOW"). After a command is executed (except 96, 100, 101, 111, and the R and D commands), delays are processed.


There is one important thing to note: sequences are not assigned output audio channels. The current output channel of the sequence depends on the current voice, so a sequence can change output channels on the fly. Except for voices that take advantage of FM channel 3 multifrequency mode, FM channels are specified at runtime by an allocator method (think malloc()), so there is no way of knowing what FM channel a sequence would output to until it's time to actually play the note! This is a problem, and I've already seen it explode into a mess of hackery when I wrote my GEMS to SMPS converter. I think I'm going to have to start it over again.

I also don't know the locations of the sequence data in GEMS ROMs. If people want to help by finding out, then great! I'll provide instructions for people with disassemblies later.

Until then, I hope this information proves useful for some people!
This post has been edited by Andlabs: 31 December 2009 - 07:30 PM

#2 User is offline SegaLoco 

Posted 31 December 2009 - 11:21 PM

  • W)(at did you say?
  • Posts: 999
  • Joined: 16-August 06
  • Gender:Male
  • Location:Corpus Christi, TX
  • Wiki edits:79
Well, I might start learning audio on the Mega Drive. Might as well try this driver out. =P

#3 User is offline Smoke 

Posted 31 October 2011 - 11:54 AM

  • Posts: 8
  • Joined: 09-October 11
  • Gender:Male
  • Location:Russia
I am working on GEMS2SMPS converter for now and achieved some decent results. Loops and modulation and many other features are not supported for now. Can't demonstrate the soft because it's too unstable right now. However, I uploaded a game rom with 3 converted gems songs from Zero Tolerance and Vectorman. Converted songs are $D, $F and $10 I think the results are very close to the originals. Your thoughts?

ROM is here
This post has been edited by Smoke: 31 October 2011 - 12:01 PM

#4 User is offline Andlabs 

Posted 31 October 2011 - 12:40 PM

  • 「いっきまーす」
  • Posts: 2175
  • Joined: 11-July 08
  • Gender:Male
  • Project:Writing my own MD/Genesis sound driver :D
  • Wiki edits:7,061
Cool. How are you dealing with mailboxes and channel changes? I gave up trying to write a SMPS converter because of the mailoxe sand ability to change output channels by changing instruments...
This post has been edited by Andlabs: 31 October 2011 - 12:41 PM

#5 User is offline Smoke 

Posted 31 October 2011 - 01:30 PM

  • Posts: 8
  • Joined: 09-October 11
  • Gender:Male
  • Location:Russia
Mailboxes are not supported now (mmm, 112 and 113 commands). Dynamic voice allocation only for FM channels is working. PSG and DAC are not supported (have to separate dac and psg patches from FM). Firstly, the program search channel and sequence with the smallest current playback time. Then it's dealing with these channel and sequence. I declared 2 variables for Sequence and Hardware Channel. Busy time (for channel) and Full time (for sequence). By comparing them the program understands if hardware channel busy or not. Next by comparing full time and busy time the rest note ($80) is put with duration equal (full time-busy time). Before write a note the program checks what is current voice in channel and which patch a sequence uses in that time. If they are not the same $EF flag is put. Same for volume. After that current duration is put and Full time variable is incremented by current delay value. Busy time is incremented by current duration value.
Sorry I'm not good in explaining and English language. hope you understand me :)
This post has been edited by Smoke: 31 October 2011 - 01:30 PM

#6 User is offline saxman 

Posted 31 October 2011 - 01:48 PM

  • Oldbie
  • Posts: 2625
  • Joined: 08-April 04
  • Gender:Male
  • Location:United States of America
  • Wiki edits:136
I'll contribute the voice format for GEMS:


GEMS voice format:


0x00 - type
	0 = FM
	1 = PSG noise
	2 = PSG tone


TYPE2 (6 bytes):
0x01 - ?
0x02 - attack rate
0x03 - D1L (0-F) -- 0 is loud, F is soft
0x04 - AR (0-1F) -- 1F is slow, 0 is fast
0x05 - ?
0x06 - release rate (0-FF) -- 0 is slow, FF is fast


TYPE1 (1 byte):
0x01 - Pitch (4-bit -- low = high pitch, high = low pitch)


TYPE0 (38 bytes):
0x01 - reg022
0x02 - reg027
0x03 - reg0B0
0x04 - reg0B4
0x05 - reg030
0x06 - reg040
0x07 - reg050
0x08 - reg060
0x09 - reg070
0x0A - reg080
0x0B - reg034
0x0C - reg044
0x0D - reg054
0x0E - reg064
0x0F - reg074
0x10 - reg084
0x11 - reg038
0x12 - reg048
0x13 - reg058
0x14 - reg068
0x15 - reg078
0x16 - reg088
0x17 - reg03C
0x18 - reg04C
0x19 - reg05C
0x1A - reg06C
0x1B - reg07C
0x1C - reg08C
0x1D - reg0A2 (in special CH3 mode)
0x1E - reg0A6 (in special CH3 mode)
0x1F - reg0A8 (in special CH3 mode)
0x20 - reg0AC (in special CH3 mode)
0x21 - reg0A9 (in special CH3 mode)
0x22 - reg0AD (in special CH3 mode)
0x23 - reg0AA (in special CH3 mode)
0x24 - reg0AE (in special CH3 mode)
0x25 - reg028 (*lower* 4 bits used to enable/disable operators)
0x26 - Unused?



#7 User is offline Smoke 

Posted 16 November 2011 - 01:52 PM

  • Posts: 8
  • Joined: 09-October 11
  • Gender:Male
  • Location:Russia
Thank you, saxman. Are formats of PSG tones the same in GEMS and SMPS?

#8 User is offline saxman 

Posted 16 November 2011 - 02:59 PM

  • Oldbie
  • Posts: 2625
  • Joined: 08-April 04
  • Gender:Male
  • Location:United States of America
  • Wiki edits:136

View PostSmoke, on 16 November 2011 - 01:52 PM, said:

Thank you, saxman. Are formats of PSG tones the same in GEMS and SMPS?

Well GEMS creates voices out of the PSG tones in that it allows you to specify an attack rate, decay rate, etc. SMPS simply allows you to play notes through the PSG, no attack or decay information specified. So GEMS uses voice data even for the PSG, while SMPS doesn't use voice data for the PSG.

Now as far as the actual sequence data, I don't know much about how that is formatted in GEMS. Looking at my DOOM 32X notes, here's what I documented:

Quote

data: 00-5F -- Note
data: 60-7F -- Controllers
controller: 6B xx -- Play track xx
data: 80-BF -- Note sustain time (lower = quicker)
data: C0-FF -- Note interval (lower = quicker)


I haven't touched it in a while, so I don't know much more than that.

#9 User is offline Andlabs 

Posted 16 November 2011 - 11:59 PM

  • 「いっきまーす」
  • Posts: 2175
  • Joined: 11-July 08
  • Gender:Male
  • Project:Writing my own MD/Genesis sound driver :D
  • Wiki edits:7,061
SMPS does use voice data for the PSG, however it's just a linear array of attenuation levels read at constant intervals and ending with a value with its high bit set, not an ADSR. The voice list is global to all songs and SFX and is specific for each instance of the sound drivers.

#10 User is offline ValleyBell 

Posted 27 October 2013 - 01:28 PM

  • Posts: 204
  • Joined: 08-September 10
  • Gender:Male
  • Project:researching SMPS sound drivers
  • Wiki edits:10
Another week, another bump, another release.

So today we have GEMS, because I did some research on it during the last 2 years.

The most interesting tool I made is GemsPlay.
Like SMPSPlay, it is a program that plays back GEMS songs. It was made by porting the original GEMS ASM code to C.
I actually started to work on it, because I wanted to do something easy while sitting in the bus to university. I worked on it from January to April 2013.

You can download a Win32 binary or the source code.
It includes a seperate .exe that emulates 2 YM2612 chips for 6 additional FM channels. (only normal ones - no second special FM3 or DAC channel)
This really makes a difference for some songs. (example: Cool Spot's Rave Dancetune, about 40 seconds into the song)

It can play from ROMs (you must include all 4 pointers though) or from pre-extracted GEMS files. (It works to drop all 4 extracted files on the .exe, but read the readme for that.)
And as usual, it can log VGMs. (Sorry, no loop detection this time.)

For people who want to look at the source, I kept all comments from the original GEMS source and included "cleaned" versions of the original source code.


Then we have a few GEMS tools: gems2mid and gemsscan.
gemsscan scans a ROM for the GEMS driver and extracts all data (driver, sequences, instruments, etc.) It might not find every set of data in games that contain more than one.
gems2mid does what the name says - it converts GEMS sequences to .mid files. (And it is over a year old, actually.) It can also extract samples (to .raw) and convert the instruments to .gyb files.


Finally, I took notes of the driver variants I found in the (comparatively small amount of) GEMS games I checked, wrote down pointers to everything and ripped all data files.
You can download everything here.
It also includes some notes on the GEMS format, the sample table format and a file with information on how to detect GEMS in ROMs by searching for certain ASM codes.

Enjoy!

Page 1 of 1
    Locked
    Locked Forum

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users