Audio Hacking - HeartHeroDE/th-hack-tools GitHub Wiki

Since build 0.5 the hacking toolkit provides new features to export audio files and write KTSS files from various audio formats. This makes it possible to replace the entire soundtrack as well as voice and sound effect files.

Here is an example with tracks from Fates:

1) Exporting audio

Each JPN sound archive is stored in ROMFS -> nx -> sound. English sound archives are within the Resource_EN subfolder. These sound archives have the file ending ktsl2stbin - a proprietary archive format used by Koei Tecmo.

Using the new KTSL2BIN Extractor tool you can export all audio files from these archives to a folder. Depending on the archive and your PC this might take a while. Once the files are extracted you should have a bunch of KTSS Files. This is a proprietary Switch Opus Container format used by Koei Tecmo.

2) Working with KTSS

2.1 Listening to KTSS

You can listen to KTSS files by using the mighty vgmstream library. There is an audio plugin compatible with foobar2000. Using this setup you can easily play the extracted KTSS files.

2.2 Converting KTSS

If you want to convert KTSS to other audio files you can use text.exe that comes with VGMStream.

test.exe -i -o file.wav file.ktss

Parameter i ignores loops. It is recommended when dealing with KTSS.

2.3 KTSS Structure

This is a very technical documentation of the KTSS format. You can skip it if you don't want to develop tools around KTSS.

KTSS Header

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |      'K'      |      'T'      |      'S'      |      'S'      |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                         File Length                           |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                             NULL                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                             NULL                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                             NULL                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                             NULL                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                             NULL                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                             NULL                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

KTSS Subheader

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                        Game Identifier                        |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |  HEADER SIZE  |     NULL      |     NULL      |     NULL      |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |  C_MULTIPLIER |    C_COUNT    |     NULL      |     NULL      |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                         Sampling Rate                         |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                         Total Samples                         |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                          Loop Start                           |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                          Loop Length                          |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                             NULL                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                       Switch Opus Start                       |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                       Switch Opus Length                      |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                             NULL                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                       Number of Packets                       |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |          Packet size          |              960              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                         Sampling Rate                         |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |       120     |     NULL      |       01      |     MONO?     |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |      NULL     |     MONO?     |      NULL     |     NULL      |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                             NULL                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                             NULL                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                             NULL                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                             NULL                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

3) Create new KTSS files

You can create new KTSS files compatible with Fire Emblem: Three Houses by using the KTSS Exporter tool. You can import WAV, AIFF, FLAC, OGG and OPUS files. All files will by converted to match the Switch OPUS format used by various switch games. If you import an OPUS file it is important to match the encoder settings used by Switch Opus: --bitrate 192 --padding 0 --hard-cbr --framesize 20

Once a file has been imported your window should look like this:

3.1 Creating loops

Before exporting to KTSS you can choose to loop a track. This is very important if you edit music files since they will only play once if they don't loop. You also cannot enter 0 as a starting point since a loop start of 0 will be interpreted as no loop.

When dealing with loops you have to know how samples work since the starting point and the length of the loop use samples.

If you divide your Sampling rate by 1000 you have the amount of samples for 1ms of audio. For example: If your Sampling rate is 48000Hz then 48 Samples would translate to 1ms.

Let's assume we want to import the track "Dusk Falls" from Fire Emblem Fates with a perfect loop. By listening to the track we can hear that 00:08.139 is a good point to start a loop and 02:40.361 a good point to end a loop. Let's do the math on these timestamps.

00:08.139 = 8139ms * 48 = 390672 Samples

02:40:361 = 160361ms * 48 = 7697328 Samples

To get the loop length we subtract the start point from the end point. Therefore the loop length is 7697328 - 390672 = 7306656 Samples.

Now we enter the values for the loop start and loop length in samples and export the KTSS. The result is a file that loops correctly when imported into Fire Emblem: Three Houses or being played by using VGMStream.

4) Import KTSS into KTSL2STBIN

If you sucessfully created new KTSS files you can now import them into KTSL2STBIN to make them playable in Fire Emblem. At the moment it is only possible to replace tracks with tracks that are equal or smaller in size.

Open your KTSL2STBIN file. Search for the Signature 09 D4 F4 15 - This is a signature used before each KTSS file within the archive file. Using a handy tool like HxD you can search for this byte sequence and get the Position of all KTSS files.

Let's say we want to replace the track "Winds of Fòdlan". If you exported all music by extracting BGM.ktsl2stbin the file 00.ktss is the right file. This means it's the first search result when searching for the signature 09 D4 F4 15. You should now be at the offset 0x40 and at the starting position of a subheader with information for the KTSS file that follows next.

This subheader has the following structure:

Name Length Description
09 D4 F4 15 4 Byte The signature of the subheader
Length with Subheader 4 Byte An Int32 declaring the total size of the following KTSS including this subheader
Unknown 4 Byte We can assume that it's some form of checksum. Doesn't seem to be important.
Subheader length 4 Byte The length of the subheader itself
KTSS length 4 Byte The length of the KTSS file
NULL Bytes Dynamic Subheader length - 20 Bytes = Count of NULL bytes

Imporant for now is only the KTSS length. Make sure that the file that replaces the KTSS has exactly the same length. You can achieve this by expanding your new KTSS file with 00 bytes until you have the exact same size as the file you want to replace. Then you simply replace the contents of the KTSS that follows the subheader and save your file.

Congratulations - You can now listen to new music in Fire Emblem: Three Houses. :)