BMS reverse-engineering project by nobody1089 at 9:08 PM EDT on July 4, 2016
So I've been working on my BMS reverse-engineering project on and off. I'm building a tool to translate BMS files into a (theoretically) abstract format which can be played back easily or converted into other games.

<github link removed>

One issue with the file format is that note-off commands do not operate on a note number, but rather on a "polyphonic ID", a number from 1 to 7 that is supplied with the note-on command. At any given time, there should only be one playing note with a given polyphonic ID. However, at different times in the song, the same "note-off" command will turn off very different notes.

Right now, my file format records note_off commands based on pitch, rather than poly_id. This makes it possible to translate function calls into other formats without "flattening" them (which takes up more space, especially on SNES). However, converting note_off commands to pitches without flattening the file (like the original BMS engine) is very difficult.

Apparently, 0xC4 address calls "preserve" the "note history" array (passed by reference). In fact, in the actual BMS engine, it's probably not "passed" at all; I think it just jumps to the new address (first pushing the old address to a stack).

(Note: I refer to functions and calls interchangably.)

Sometimes, the BMS file calls a function with one set of playing notes, then ends the function with another set. Because I'm trying to decode a file into a set of note-on and note-off commands, I can no longer assume the function is an independent unit, and must rely on global state to parse note_off commands.

- No function (in Dragon Roost theme) uses same note-off on multiple pitches.
- One function (volume fadeout) was called with different running notes, but did not touch them.

We can build a system to accommodate notes that overlap functions, and functions that don't touch notes.
The system will reject functions that uses the same note-off on multiple pitches.

# SIMULATION (bad)

Every time a note_off occurs, make sure it's the same pitch.

# ASSERTION

Record which poly_ids are "touched" (on or off).
We will encounter issues if any touched notes differ from the original call.
This is equivalent but MUCH faster than simulation.

different = (np.array(track.pre_history) != self.note_history)
if any(different & track.touched):
LOG.error(...)

# RESULT

I'm now able to parse the entire Dragon Roost theme without any detected inconsistencies. Now onto translating to SNES (SMW AMK)...
by robotortoise at 2:19 AM EDT on July 5, 2016
Holy cow, this is awesome! Can't say I really understand it, but I'd love to have MIDI and soundfonts of BMS eventually!
by nobody1089 at 2:31 PM EDT on July 5, 2016
I don't think I'll be working on MIDI/SF2. So far, my efforts have primarily been directed at sequence decoding, not sample banks. Also, the MIDI format is flat, making it inappropriate as an intermediate representation for converting between sequence formats.

More importantly (for casual listeners), MIDI files lack commands for smooth control change (pitch, volume, pan) slides.

TODO: I'll need some sort of "merge global events into first track". If I want to convert SNES files into generic, I'll also need "split global events from first track".

EDIT: What do you think of the name ".vgseq" for decoded files?
- For scripted transformations (instrument, volume, structure, etc.), "vgsh" or "vgscript"?
- For the playback engine, "vgplay"?

EDIT: Many (but not all) control changes are 16-bit. I need to figure out how u8, u16, and s16 are interpreted.

As a number? (u8 255 = u16 255)
Relative to the number of bits? (u8 128 = u16 32768 ≈ s16 32767)
Relative to the maximum value? (u16 65535 ≈ u16 32767)

I need to write a BMS reencoder, inject into Wind Waker, and test what happens.

edited 1:20 PM EDT July 6, 2016


Go to Page 0

Search this thread

Show all threads

Reply to this thread:

User Name Tags:

bold: [b]bold[/b]
italics: [i]italics[/i]
emphasis: [em]emphasis[/em]
underline: [u]underline[/u]
small: [small]small[/small]
Link: [url=http://www.google.com]Link[/url]

[img=https://www.hcs64.com/images/mm1.png]
Password
Subject
Message

HCS Forum Index
Halley's Comet Software
forum source