Skip to content

Commit 798da41

Browse files
committed
Update README.md, add GAX 1 support
1 parent 08e116a commit 798da41

File tree

4 files changed

+21
-4
lines changed

4 files changed

+21
-4
lines changed

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
# GaXM
22
Experimental GAX (Shin'en GBA audio engine) to XM converter
33

4-
Many GAX features are not supported in XM. As such the resulting files will likely sound different from in-game.
4+
All GAX versions are supported, so it should be possible to create XM files for most games using this engine.
5+
However, many GAX features are not supported in XM. As such the resulting files will likely sound different from in-game.
56

6-
At the moment, GAX 1 is not yet supported.
7+
Some of these features are:
8+
9+
* Tempo in XM is specified using a BPM and Speed value (= number of ticks per row). The tempo change effect either affects the BPM value (when parameter >= 32) or the Speed value (when parameter < 32), but not both. GAX's tempo system is different: it only uses a Speed value very similar to XM's (that matches XM's tempo when BPM is about 149-150). Because the tempo change effect can only affect the Speed value, it can be set to larger values than in XM. Additionally, to achieve that would require a non-integer speed value, compositions in GAX often change the tempo on each row. GAX includes a separate effect for this that starts this speed value alternating system and allows one to use different effects in the next rows. XM does not have this, so I translated this effect by using the closest single speed value that is faster. As a result, many GAX -> XM conversions are faster than the original track.
10+
11+
* While XM processes one pattern at a time per channel, GAX processes two: the pattern specified for that channel and the pattern specified in the current instrument. Instrument patterns can advance at a different speed (again, number of ticks per row) than the regular pattern. These "instrument rows" include information like the sample (& corresponding pitch, loop info, etc.), relative note number, and 2 effects which include volume, changing the instrument pattern speed... Arpeggios are a great use case for this system, so they are often missing entirely from GAX -> XM conversions.
12+
13+
* Of course, some that I haven't fully reverse-engineered yet. :)
14+
15+
However, for some games these exports sound close to perfect. Most likely, they can be perfected by creating a custom GAX player using the GAX structs provided in [BinarySerializer.GBA.Audio](https://github.com/BinarySerializer/BinarySerializer.GBA.Audio).
16+
17+
## Note
18+
If you download the repo as a zip folder the submodules won't be included, causing the project not to compile. To solve this, download the submodule repos as well and place them in the specified folders:
19+
* [BinarySerializer](https://github.com/BinarySerializer/BinarySerializer) (submodules/BinarySerializer)
20+
* [BinarySerializer.Audio](https://github.com/BinarySerializer/BinarySerializer.Audio) (submodules/BinarySerializer.Audio)
21+
* [BinarySerializer.GBA.Audio](https://github.com/BinarySerializer/BinarySerializer.GBA.Audio) (submodules/BinarySerializer.GBA.Audio)

src/GAX/GAXHelpers.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public static void ExportGAX(string basePath, string mainDirectory, IGAX_Song so
7474
}
7575
}
7676
var h = song;
77-
if (h.Info.SampleRate == 0) return;
77+
if (h.Info.SampleRate == 0 && h.Info.Context.GetGAXSettings().MajorVersion >= 2) return;
7878

7979

8080
GAX_XMWriter xmw = new GAX_XMWriter();

src/Program.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ private static void ParseROM(Options options) {
103103
try {
104104
IGAX_Song Song = null;
105105
switch (gaxVersion) {
106+
case 1:
106107
case 2:
107108
Song = s.SerializeObject<GAX2_Song>(default, name: nameof(Song));
108109
break;
@@ -150,6 +151,7 @@ private static void ParseROM(Options options) {
150151
s.DoAt(song.Offset, () => {
151152
IGAX_Song Song = null;
152153
switch (gaxVersion) {
154+
case 1:
153155
case 2:
154156
Song = s.SerializeObject<GAX2_Song>(default, name: nameof(Song));
155157
break;

0 commit comments

Comments
 (0)