Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save beanieaxolotl/665b314bed710488c388cd50dbc1b8b3 to your computer and use it in GitHub Desktop.
Save beanieaxolotl/665b314bed710488c388cd50dbc1b8b3 to your computer and use it in GitHub Desktop.
Shin'en GHX Sound Engine documentation
Additional binary context from BinarySerializer
History context and research made possible by www.vgmpf.com
//
AHX/GHX sound engines programmed by Martin Wodok (Dexter)
==
Special thanks to Manfred Linzner (Pink) for their mind-blowing and awesome tunez!
--------------------------------------------------------------------
GHX Sound Engine (November 23rd, 1999/December 31st, 2001)
- First used in Crazy Zone/JetPak DX
- Saw last use in Planet of the Apes
- Coded in Z80* ASM
- The software used to create and edit AHX tracks is a specially-modified variant of AHX v2.3d-sp3(1) for the Commodore Amiga.
- The software can convert ProTracker(4), as well as FastTracker II and Commodore 64 .sid music formats(5) into the GHX format.
//
//////////////////////////////////////////////////////////////
GHX Audio Engine (shinen.com GHX demos)
[TBC]
==
GHX Sound Engine - Ver. 00530
(used in Barbie: Magic Genie Adventure, Blue's Clues: Blue's Alphabet Book, NASCAR Heat)
//
GHX Sound Engine - Ver. 01206t (WIP)
(used in SpongeBob SquarePants: Legend of the Lost Spatula, Tomb Raider: Curse of the Sword)
==
[GHX file format]
> Tip: The pointers are relative to the bank the
GHX version info (and likely the replayer) is in
==========================================
uint16 - Unknown pointer
[File header]
[ASCII] - "GHX"
uint8 - Number of subsongs
uint8 - Number of rows (Shared across all subsongs)
uint8 - Reserved
uint16 - Pointer to pattern data
uint16 - Pointer to instrument data
//
uint16 - Pointer to song playback settings
//
[Song playback settings]
For each song:
uint8 - Song length
uint16 - Pointer to start of pattern playlist
uint8 - Length of loop (after the song loops)
uint16 - Restart position (pointer to a pattern playlist)
[Pattern list format]
For each pattern in the song:
>>Pattern number corresponds to an ID into the pattern pointers struct.
uint8 - Pulse #1 pattern number
int8 - Pulse #1 transpose
==
uint8 - Pulse #2 pattern number
int8 - Pulse #2 transpose
==
uint8 - Wave pattern number
int8 - Wave #1 transpose
==
uint8 - Noise pattern number
[Pattern pointers]
For each pattern in the data file:
uint16 - Pattern start offset
[Instrument data (WIP)](2)
uint8 - Number of steps
uint8 - Step speed
** Bit 7 - Use wavetable
// - Allows the use of realtime generated wave patterns(3) (i.e Wacky Racers, Rinkapink (unreleased), and Asterix: Search for Dogmatix)
uint8 - Volume control bitfield
**
** Lower nybble - Volume
** Upper nybble:
** Bit 3 - Fade type
** Bit 2:0 - Fade length (0 - No fade)
[For each instrument step]
int8 - Note transpose
uint8[2] - Effect type and param bitfield
**
** Lower nybble:
** Bit 7-6
** 0 - None
** 1 - Set volume
** 2 - Jump to step
** 3 - Set waveform
** Lower-upper nybble:
** Bit 5:0 - Effect param
[If the instrument is a wavetable]
uint8 - Number of steps
uint8 - Step speed
** Bit 7 - Use wavetable = Set to 1 here
uint8 - Wavetable volume?
uint8 - Reserved?
uint8 - Vibrato controls
** Lower nybble - Vibrato speed
** Upper nybble - Vibrato depth
uint8 - Wavetable sweep strength
uint8 - Wavetable settings
** Bit 7-6 - ??
** Bit 5-4 - ??
** Upper nybble - Wavetable init
uint24 - Null
uint16 - Loop bitfield
** Upper nybble -
** 0 | No loop
** 1 | Loop
** Lower nybble + uint8 - Number of wave ticks to wait until playing waveform again (0-65295)
uint8 - Wavetable step
uint16 - Wavetable parameters
[For each instrument step]
int8 - Note transpose
uint8[2] - Effect type and param bitfield
**
** Lower nybble:
** Bit 7-6
** 0 - None
** 1 - Set volume
** 2 - Jump to step
** 3 - Init square
** Lower-upper nybble:
** Bit 5:0 - Effect param
[Sequence data (WIP)]
uint8 - Note
** Bit 7 -
1 | Note + effect(s) <if note is not 0>
1 | Effect only <if note is 0 + effect bitfield is blank>
0 | Note only
Effect bitfield >
** Bit 6 -
Effect type = Set volume
** Bit 5 only in lower nybble-
Slide to defined pitch
Upper nybble is now pitch value (-6 : +8)
The resulting command is 1 byte.
** Only bit 6 set -
Effect only, set volume. The next is the effect param and the resulting command is 2 bytes
uint8 - Instrument
** Bit 7:6 - If a set volume command is present, it is set to the volume param.
** Bit 5:0 - Instrument number (0-63)
[If effect bit is set]
uint8 - Effect type and param bitfield
** Lower nybble - Effect param
** Upper nybble - Effect type
uint8 - Command byte
An empty row is represented with 0x00.
Available effects:
00 | None
??
0C | Set volume
0F | Set speed
FF | Stop song
AHX effects:
00 | None (Filter position if given param)
01 | Portamento up
02 | Portamento down
03 | Init square modulation
04 | Start/stop modulation
05 | Jump to step
0C | Set volume
0F | Set speed
[Song "metadata"]
[ASCII] - 'SONG'
******************
Song ID and name list formatted as:
00: MAIN MENU.......01: CUTSCENES.......02: SUBSCREENS......
**************************************************************
The list can be viewed properly if one sets the bytes per row in a hex editor to 20 bytes.
[ASCII] The song's ID (00-99) followed by a colon and a space.
(Sometimes the space is absent and the rest of the string is padded with 0x2e.)
[ASCII] The song's internal name (max. 16 characters, padded by 0x2e/period)
> The name is uppercase for most of the time, but this doesn't mean the titles can't be uppercase.
Example from Blue's Clues: Blue's Alphabet Book (USA):
00: EMPTy...........
07:Thinking Chair...
//
Tyrannosaurus Tex and the GHX demos don't have this metadata saved.
[Sample data]
(uint4) - 4-bit PCM data
==Citations==
///
* - Sharp LR35902
==
1 - https://web.archive.org/web/20071027020933/http://www.shinen.com/music/images/ahx-1.gif
2 - https://web.archive.org/web/20231119210018/https://shinen.com/music/images/ahx-2.gif, http://www.abyss-online.de/static/www.amigascne.org/abyss/ahx/
3 - https://gbstudiocentral.com/interviews/making-game-boy-music-during-its-heyday/#:~:text=use%20of%20custom%20voices%20in%20the%20wave%20channel
4 - https://gbstudiocentral.com/interviews/making-game-boy-music-during-its-heyday/#:~:text=We%20could%20import%20different%20music%20formats%20(like%20ProTracker%20etc.)
5 - https://www.shinen.com/music/music.php3?ghx#:~:text=We%20already%20have%20some%20music%20composed%20as%20MID/WAV/MOD/XM/SID
///
==End of citations==
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment