From 312f6123678f691f2bedd21a7807cded7e62adac Mon Sep 17 00:00:00 2001 From: JackMacWindows Date: Fri, 9 Oct 2020 01:01:04 -0400 Subject: [PATCH] Version 3.0 --- README.md | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d3c7171..ff37a5c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # UnkrawerterGBA -A tool to rip music from Gameboy Advance games that use the Krawall sound engine. +A tool to rip music from Game Boy Advance games that use the Krawall sound engine. Exports the audio as XM or S3M module files. ## Compiling The latest version can be downloaded precompiled on the Releases tab, or you can compile it yourself: @@ -14,22 +14,30 @@ In its most basic form, you can run UnkrawerterGBA with just the ROM path, and i -i
Override instrument list address -l Read module names from a file (one name/line, same format as -n) -m
Add an extra module address to the list - -n = Assign a name to a module address (max. 20 characters) + -n = Assign a name to a module address (max. 20 characters for XM, 28 for S3M) -o Output directory -s
Override sample list address -t Search threshold, lower = slower but finds smaller modules, higher = faster but misses smaller modules (defaults to 4) + -3 Force extraction to output S3M modules (only supported with some modules) -a Do not trim extra instruments; this will make modules much larger in size! + -c Disable compatibility fixes, makes patterns more accurate but worsens playback -e Export samples to WAV files -v Enable verbose mode - -x Disable compatibility fixes, makes patterns more accurate but worsens playback + -x Force extraction to output XM modules + -h Show this help ``` ### Threshold argument -UnkrawerterGBA searches for Krawall data by looking through the ROM for lists of pointers to structures with the Krawall data. These lists can either be the master instrument list, the master sample list, or a module's list of patterns. By default, UnkrawerterGBA ignores any lists with less than four addresses. This is to avoid detecting single variables that are unrelated to Krawall, speeding up detection time. But some songs may have less than four patterns, and so they won't be detected with the default threshold. You can adjust this number to detect modules with fewer patterns, but it may take longer for it to filter out all of the addresses that are not related to Krawall. +UnkrawerterGBA searches for Krawall data by looking through the ROM for lists of pointers to structures with the Krawall data. These lists can either be the master instrument list, the master sample list, or a module's list of patterns. By default, UnkrawerterGBA ignores any lists with less than four addresses. This is to avoid detecting single variables that are unrelated to Krawall, speeding up detection time. But some songs may have less than four patterns, and so they won't be detected with the default threshold. You can adjust this number with the `-t` argument to detect modules with fewer patterns, but it may take longer for it to filter out all of the addresses that are not related to Krawall. ### Verbose mode -Enable verbose mode to show all of the detected addresses and their types. This can be useful if UnkrawerterGBA isn't detecting one of the required lists properly. +Enable verbose mode (`-v`) to show all of the detected addresses and their types. This can be useful if UnkrawerterGBA isn't detecting one of the required lists properly. + +### XM vs. S3M +UnkrawerterGBA 3.0 supports ripping music to either the XM module format or the S3M module format. Krawall natively supports both of these formats, but UnkrawerterGBA has to pick which format it needs to use. XM supports instruments and more than 64 rows per pattern, but S3M has a different effect syntax that is mostly incompatible with XM. Some compatibility fixes are available when exporting to XM, but it is better to export modules originally created as S3Ms to S3M files. + +UnkrawerterGBA makes a good guess at whether a module is best converted to XM or S3M. However, if it gets this wrong, or you want to force a different format, you can use the `-3` or `-x` arguments ## Library API UnkrawerterGBA also supports usage as a library for embedding in another program. These functions can be used to rip Krawall music from ROMs in another program. @@ -68,22 +76,34 @@ Writes a single XM module at an offset from a ROM file, using the specified samp * `instrumentOffsets`: A list of instrument addresses. * `filename`: The path to the XM file to write to. * `trimInstruments`: Whether to remove instruments that are not used by the module. Defaults to true. -* `name`: The name of the module; if unset then the module is named "Krawall conversion". Defaults to `NULL`. -* `fixCompatibility`: Whether to attempt to fix some effects that behave differently in Krawall. This will modify the extracted patterns and reduces extraction accuracy, but improves playback accuracy. Defaults to true. +* `name`: The name of the module; if unset then the module is named "Krawall conversion". Defaults to `NULL`. (The name must be <= 20 characters long.) +* `fixCompatibility`: Whether to attempt to fix some effects that behave differently in Krawall/S3M. This will modify the extracted patterns and reduces extraction accuracy, but improves playback accuracy. Defaults to true. +* Returns: 0 on success, non-zero on error. + +### `int unkrawerter_writeModuleToS3M(FILE* fp, uint32_t moduleOffset, const std::vector &sampleOffsets, const char * filename, bool trimInstruments = true, const char * name = NULL)` +Writes a single S3M module at an offset from a ROM file, using the specified samples. This will not work for instrument-based modules, or for patterns that have <> 64 rows. +* `fp`: The file to read from. +* `moduleOffset`: The address of the module to read. +* `sampleOffsets`: A list of sample addresses. +* `filename`: The path to the S3M file to write to. +* `trimInstruments`: Whether to remove instruments that are not used by the module. Defaults to true. +* `name`: The name of the module; if unset then the module is named "Krawall conversion". Defaults to `NULL`. (The name must be <= 28 characters long.) * Returns: 0 on success, non-zero on error. ### Finding Krawall data structures in ROMs manually If you desire to find the offsets on your own (such as if the automatic finder isn't working properly), you can search through the ROM for the offsets manually. This process will require the use of a hex editor, as well as some basic knowledge on reading hexadecimal from files. In most cases this is unnecessary, since the automatic detector is pretty good at finding the offsets itself. +(Note: I've written an in-depth write-up of the format Krawall uses to store data on [The Cutting Room Floor](https://tcrf.net/Format:Krawall). Look there for more info on how the music is stored in the ROM.) + #### Modules -Modules are probably the easiest structure to locate in a ROM. Search for a block of at least 256 bytes of 0's. Just before this block, check for a chunk of bytes that are ascending from 0. Before that, look for a byte that will likely be 8, as well as another byte that should tell you the number of bytes in that ascending chunk. At the end of the block of 0's, the first byte will likely be 0x80 (but don't rely on it). The next byte should be below 10, and the byte after that should be a reasonable BPM (probably 60 <= n <= 180). The next 6 bytes should be either 1 or 0, with the last byte definitely being 0. Lastly, there will be a list of 4-byte addresses in the decoded form `0x08xxxxxx`, or `xx xx xx 08` in the hex editor. +Modules are probably the easiest structure to locate in a ROM. Search for a block of at least 256 bytes of 0's. Just before this block, check for a chunk of bytes that are ascending from 0. Before that, look for a byte that will likely be 8, as well as another byte that should tell you the number of bytes in that ascending chunk. At the end of the block of 0's, the first byte will likely be 0x80 (but don't rely on it). The next byte should be below 10, and the byte after that should be a reasonable BPM (probably 60 <= n <= 180). The next 6 bytes should be either 1 or 0, with the last byte definitely being 0. Lastly, there will be a list of 4-byte addresses in the decoded form `0x0[89]xxxxxx`, or `xx xx xx 0[89]` in the hex editor. If the block you found matches this description: congratulations, you found a module structure! The offset you need is the address of the first byte that was probably 8, before the increasing bytes and 0 chunk. #### Sample lists & instrument lists -Krawall stores the list of samples & instruments in two blocks of data as pointer arrays. You will need to look for chunks of data that are in the form `xx xx xx 08 xx xx xx 08 xx xx xx 08 xx xx xx 08` in each row. This command should help you find a few candidates: +Krawall stores the list of samples & instruments in two blocks of data as pointer arrays. You will need to look for chunks of data that are in the form `xx xx xx 0[89] xx xx xx 0[89] xx xx xx 0[89] xx xx xx 0[89]` in each row. This command should help you find a few candidates: ```sh -xxd ../2403\ -\ 3\ in\ 1\ -\ Life,\ Yahtzee,\ Payday\ \(U\)\(Trashman\).gba | grep -E '[0-9a-f][0-9a-f][0-9a-f][0-9a-f] [1-9a-f][0-9a-f]08 .... ..08 .... ..08 .... ..08' +xxd rom.gba | grep -E '[0-9a-f][0-9a-f][0-9a-f][0-9a-f] [1-9a-f][0-9a-f]0[89] .... ..0[89] .... ..0[89] .... ..0[89]' ``` Rule out any lines that are not in chunks of at least 4 lines, or are filled with 08080808 or another regular pattern. You should end up with two blocks of consecutive addresses: one is the list of instruments, and the other is the list of samples. Keep track of the start addresses for each block; these will be your offsets. To find which one each is, take the first address in each block, reverse the bytes (since it's in little-endian), and take off the high 08 bit (for ROMs <= 16MB, take off the high byte; for 32MB ROMs, subtract 8 from the high byte). Then jump to that offset in the file through the hex editor. You will be brought to whatever structure is located there.