Created
April 15, 2024 05:49
-
-
Save beanieaxolotl/665b314bed710488c388cd50dbc1b8b3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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