FF6 Beyond Chaos
Music Appropriation Guide

emberling 2019.12.31

The purpose of this guide is to demonstrate how to transfer music from other Final Fantasy VI hacks into Beyond Chaos (EX).

Requirements

This guide is written for Windows. Everything in the process SHOULD be possible cross-platform but I don't have the experience to write a direct guide for how to achieve this.

Python 3.7+ is required.

You'll need your source song in SPC format. (It must be from an FF6 mod, not some other game!)

There's no hex editing in this guide, but there are hex values used in this process and you should have a basic understanding of what hexadecimal is and how to convert to and from it.

One-Time Setup

You'll need a way to listen to and test your songs quickly, without going through all the trouble to get Beyond Chaos to give you the right song in a seed. That means you need:

For the ROM, use an IPS patching utility (such as Floating IPS) to apply the included "BCx-Inst.ips" patch to a clean, unheadered 1.0 US FF6 ROM. Finding this ROM is up to you cough try the BC discord. Using this ROM will allow you to work with the expanded instruments used by Beyond Chaos.

The song insertion script is "_TEST.py". It just needs a tiny bit of configuration first. Open it with your favorite text editor and set the "ROMFILE" path to the ROM you just created.

_TEST.py

By default, this script will replace "Searching for Friends" with your new song. You can change this by changing the "IDP" value below "ROMFILE". A list of possible values can be found here. Don't worry about "IDN" and "IDM" - they're not used for Beyond Chaos purposes. Just make sure all three are set to something different and below 0x55.

A save file (SRM) is included that loads directly into "Searching for Friends" from the first file - "mytest.srm"

Extraction

Once you're set up, the first step is to extract the data from your SPC file. This is done using VGMTrans (also available in cross-platform beta).

Detected Music Files

Drag an SPC onto the VGMTrans window and you should get something like this: three items under "Detected Music Files", one sequence, one sample collection, and one instrument set. What you want to do is right click the sequence and select "Save as original format", and then right click the instrument set and select "Convert to Soundfont2". You're done with VGMTrans now.

Conversion

Run "mfvi2mml.py" and enter the filename of the "original format" you just saved, or else just drag that file onto mfvi2mml.py. You should get an MML file out of it. Open the MML in a text editor.

mfvi2mml example raw mml output

Samples

That's all we need for our song data, but we also need to set samples (instruments) if we want our song to actually sound like music. This is still pretty easy on the surface, but it's a task with a lot of layers to it that can really reward you with quality results if you put in more effort and have more expertise. I'll just go into the bare necessities here, and a little later I'll go into the most important of the complications.

For this guide I'll give my own usual method of sample selection - extracting to soundfont and then matching. There are other ways to do this, such as digging into the ROM for instrument ids (the SPC doesn't store them) and figuring out what they correspond to. Using soundfonts is, in my experience, the simplest method because it works in more or less any situation.

IMPORTANT: by "soundfont" I am specifically referring to files in the SoundFont format developed and trademarked by E-MU and Creative Labs. You'll just get confused if you try to read it as a generic word for a selection of samples or instruments, because I use it more specifically than that. Also, y'all who do that sound like someone calling a glass of orange juice "Coke."

For soundfont viewing and editing I use Polyphone. There are probably many other viable choices, but I'll use this one for examples.

Polyphone Presets

Open the soundfont you extracted with VGMTrans in Polyphone. Click the arrow next to "Presets" to expand it. You'll see eight samples marked 0 through 7 and some selection of additional samples. These numbers correspond with the sample ID used by the SPC700 in memory. For our purposes, we can ignore 0 through 7 - they're always loaded since they are used by sound effects. What we care about are the customizable samples that are loaded specifically for each song, which use ids 32 through 47. (We also often refer to these in hexadecimal - 0x20 through 0x2F.) In the pictured example we'll have to choose six custom samples, 0x20 through 0x25. (These IDs should not be confused with the ROM sample IDs, which range from 0x01 to, potentially, 0xFF, and remain constant within the same romhack.)

Test Keyboard

Click on the first customizable preset (num32, almost always) and test it out using the keyboard at the top right. This one sounds like a trumpet or trombone, so we need to find a matching trumpet or trombone in the BC sample set. Open another Polyphone window and load the FF6BCx soundfont, then scroll through the presets, click on anything that sounds like it could be a match, and try it out. Switch back and forth a couple times to compare. In this case, I easily found an identical match: "0E Trumpet".

It's important to try to find a match on the same note, because different samples are recorded at different octaves. If you don't match it up, you'll get some odd sounding results. This is one of those things where you can get better results by diving deeper: you can change the octave of the sample if you edit the MML accordingly, but that's beyond the scope of this guide.

Once you've found a possible match, you have to enter it into the MML. Samples are specified using this syntax: #WAVE 0xAA 0xBB will load the sample with ROM ID BB into SPC memory with id AA.

#WAVE 0x20 0x0E

At this point you can actually insert the song and listen to it - you'll only hear that one sample, though. Everything else will be silent. No need to get ahead of ourselves, though! Repeat this whole process with each of the other presets (num33 through num37 in our example).

All samples set

And that's this song sorted - at least for our first test. Don't know for sure yet if it'll sound right, and maybe we want to try some other possibilities (for fun, or for higher fidelity, or just for the sake of having a different style than the hack it was taken from). Note that any text after the SPC and ROM ID on the #WAVE declarations is just ignored, so you can put whatever comments you like there. Noting what instrument it is can help keep your bearings when you don't have all the ids memorized, or if you're wanting to try a lot of different possibilities and don't want to get lost.

Testing

Drag your MML file onto _TEST.py, then load your patched ROM and load the first save file, then buckle up and listen. It's that simple. (Adjust accordingly if you made any changes to IDP in the test script, or if you're using a different save than the one I provided.)

If you want to take a closer look, maybe track down some glitches, it helps to rip your song to SPC and use an advanced SPC player. In snes9x, you'd want to select File -> Save Other -> Save SPC Data. The timing is actually very important for getting a proper rip (which can be either completely unimportant or very important, depending on what issues you're looking into). You want to save the data after the last note of the previous song is played, but before your song finishes loading. (This is why I use Searching for Friends rather than Omen or Prelude - it's easier to control when exactly it loads.) Song loading time is proportional to the amount of sample data it loads, so if you've got a quick one that you can't quite catch, you can load it down by temporarily adding some additional unused samples.

Recommended advanced SPC players:

knspc: click rightmost kanji to open English interface. click in the "Volume" area with eight channel level displays to swap to other views with more/different information.

spcplay: double click the area above the play/stop buttons to change displayed information, or use menu: Settings -> Information

Oops, I broke it

There are a couple of really important aspects of sample selection that I'd like to say are too in depth for this tutorial, but unfortunately, if you don't pay at least a little attention to them, your songs will sooner or later get loaded down with ugly glitches.

1. Sample memory

SPC700 has notoriously little memory, so you'd better believe it's something we have to pay attention to. After storing all the engine code, song data, sound effect data, and a healthy chunk reserved to calculate echoes, we get 33,714 bytes to play with for samples. That's a mouthful, so instead we can look at things in terms of the 9-byte blocks used by the BRR compression format used by the SPC. So, we have 3746 blocks to play with.

(You remember the thing where T-Edition requires a very specific, odd emulator or else the audio glitches like it's dying? That's because tsushiy used too much sample memory. The later loaded samples got overwritten by echoes and basically turned into garbage data, except when using an emulator that incorrectly didn't write echo data to memory.)

I've entered in all the BCx sample sizes into a spreadsheet (included - bcex.ods), so it's pretty simple to check if your planned loadout fits, and iterate if it doesn't.

Spreadsheet with room to spare

Spreadsheet overloaded

2. Pitch overflow

The other issue is, fortunately, pretty rare, but unfortunately can be hard to spot and frustrating to deal with. Basically, the SPC700 can only play samples up to two octaves higher than their original recording. The variable that stores the pitch (vxPitch) only goes up to 16384 (0x4000), and anything above that turns into garbage data, meaning a more or less random detuned note. Since all the samples are recorded at different pitches and adjusted by tuning values, this means that the point at which samples start to fail can vary significantly. FF6's bagpipe craps out at Db7, while Ralse's voice still functions (badly) up to A8.

There's not really much you can do if this problem turns up other than use a different sample. The thing is, while sometimes it's incredibly obvious, often it's very sneaky and just shows up as a clunk or weird sound in the background. So if anything seems a bit off, one of the first things to do is watch those vxPitch values in an SPC player. vxPitch - knspc vxPitch - spcplay

(Decimal numbers for knspc, hex for spcplay, so the danger level is 16384 and 4000 respectively.)

Note that some (far from all) samples have their maximum pitch levels set correctly in the FF6BCx soundfont file, so you can check the relative maximums that way - though it won't really tell you what the song itself is doing. If you want to check one out and it isn't set, you can trace the preset back to its corresponding sample, find the root note from there, and add two octaves.

beyond chaos

So we've got a completed song, now what? well, first let's talk filenames. BC expects music files to be named [game]_[song]_[variation]. Will it work if you don't follow this format? Maybe. I'm not sure. I'm pretty sure these are actual hard limits:
• No spaces in filenames. Capital letters are also probably bad if not on windows.
• Song uniqueness calculations cut off at the second underscore. So if you have songs named ff7_barret and ff7_barret_sad, you'd only see one of those in any given seed. Maybe you want that, maybe you don't. Name accordingly.

BC knows what songs to load by reading songs.txt from the custom folder. So, first drop your properly-named song into custom/music, then open up custom/songs.txt in your text editor.

Add new songs under [Imports] (or properly alphabetized, if you feel like it). First the filename (without .mml), then the list of places you want it to play. Even if you're only planning on using johnnyachaotic, you still need to add at least one thing to this list, or it won't show up. There are plenty of existing examples in the default file, so it shouldn't be hard to figure out.

Except for battles, which use that weird esoteric arcane system I designed in my sleep or something. The BattleIntensity tab on the included spreadsheet should help for visualizing how to interpret the battle markers and how they'll spread through the game in a seed.

You can refer to songlist.txt for the full list of song identifiers and the rough guidelines that I use when determining what songs to put where in johnnydmad.

that's it we're done

If you want to go deeper and figure out how to do things like adjusting octaves and volumes within the song data, this tutorial by Gi Nattak is...well, EXTREMELY outdated, but still the best place to pick up the basic MML syntax and concepts so you can understand enough to edit it yourself.