Note: The source code is available for this project however it was one of the first C++ applications I ever wrote. This project is not a good representation of my current coding capabilities.
Chrono Trigger MusiCompanion (CTM) is a program that attaches itself to an emulator running Chrono Trigger and allows you to replace the in-game music with high-quality music. The program makes patches to the Chrono Trigger ROM in memory in order to hook into the game and detect when actions need to be taken. The user configures what in-game tracks are replaced and what file replaces them. This track-list is then used when patching the ROM to determine what songs need to be changed in-game and which ones should stay the same. Tracks that are not replaced will use their normal music in-game.
CTM is one of the first C++ programs I ever wrote; It was developed over a couple months time which includes both the time spent reverse engineering Chrono Trigger as well as the time spent coding. A lot of time was spent playing through Chrono Trigger in a debug emulator tracking assembly and using breakpoints to find code that needed to be changed. Each time Chrono Trigger tries to make changes to its audio I needed a way to hook into it and communicate these changes to my code. This is done by patching multiple pieces of code inside Chrono Trigger to jump to a special bit of code I add to the ROM as a patch; This code places information about the change at the end of the SNES’s RAM which my code can then monitor and react to. Along with needing to make patches for sound changes done by Chrono Trigger’s engine I also had to track down a couple other issues and patch them. For example, the title screen and party select screen will not show if music is not playing. Also, there are 2 scenes in the game which are synced to music tracks, if the correct music is not playing the scenes will softlock.
CTM works by launching an emulator, allocating memory within the process and then injecting a DLL into that memory and executing it (this code largely came from Code Project, the source code properly credits it). Once the DLL is running inside the emulator it uses memory locations for each emulator known to contain pointers to the emulated SNES’s ROM and RAM to being inspecting the ‘SNES’. Once Chrono Trigger has been detected as being loaded in the ROM area, the emulator is suspended while CTM makes some patches. Patches are made to insert the code that allows my code to detect changes with the audio engine in Chrono Trigger. Patches are made to fix a couple bugs/soft locks that arise when Chrono Trigger isn’t playing music when it should be. More patches are made to have code that executes song changes, volume changes, and more jump to my newly inserted code to allow monitoring. And finally, patches are made to the pointer table containing the locations of each song in Chrono Trigger; If the user has specified that a song should be replaced its pointer inside the table is changed to point to the ‘silence’ song track (track 0). Once patching is done the emulator is resumed; Because these patches are made in RAM the actual ROM file for the game is never modified.
Once these changes are in place, CTM’s code begins watching memory at the end of the SNES’s RAM for certain values. When Chrono Trigger executes a sound change that we care about it executes a jump to the code we added to the ROM which copies information about the change (what it was, any parameters such as time, volume, track number, etc) to the end of the SNES’s RAM. From there CTM’s code is able to pick it up and execute on it. For the most part, that’s all there is to it!
I have had interest and plans to eventually improve/expand upon CTM and the work done on this. For one thing, CTM has been rewritten to function more effectively and have better quality code in general. The rewritten version works by changing code on the SNES’s SPU (an SPC700) which uses a different instruction set from the main CPU. The advantage to doing this is that there are only two locations on the SPU that recieve sound commands from the CPU versus the various locations on the CPU that can send them. I do have a version of CTM working that does this, however it makes use of signaling between CTM and the SPC (the SPC will wait for CTM to recieve the command before continuing execution). This causes Chrono Trigger to sometimes soft-lock as it takes the SPU too long to respond to sound commands sent by the CPU; I’m sure this could be worked around but I have yet to do it.
I have also put time into reverse engineering the music format used in Chrono Trigger which could be used to create a music editor for the game. Chrono Trigger’s music format is interesting in that it executes a bit like a scripting language (if it were compiled into bytecode). The music has the ability to change things such as channel volume, echo levels, instruments used for the channel, and more; It can even setup basic loops that execute a series of notes and commands a specified number of times. The main advantage of creating a music editor, compared to something like CTM, is that it can be used to create music that will work on any platform that accurately emulates the SNES (as well as on actual hardware).
Also, I have a very rough proof of concept version of CTM using the MSU1 developed for the SNES. The MSU1 is a chip capable of decoding and mixing CD quality audio with the SNES’s audio. There are 2 emulators capable of emulating the MSU1 (both developed by the author of the MSU1) and one flash cart that can run on actual hardware. I have a proof of concept version of CTM working, but it’s in no way ready for release and has various bugs (however, it does run on actual hardware).