BMS (File Format): Difference between revisions
Jump to navigation
Jump to search
(Page created) |
Super Hackio (talk | contribs) No edit summary |
||
Line 15: | Line 15: | ||
| 00<br />01<br />02<br />...<br />7D<br />7E<br />7F | | 00<br />01<br />02<br />...<br />7D<br />7E<br />7F | ||
| | | | ||
| {OpCode[1]} {Voice[1]} {Velocity[1]}<br />OpCode: one byte with range 0x00 through 0x7F. 0x00 = C-1, 0x60 = C4 (middle C), 0x7F = G9.<br />Voice: one byte with range 0x01 through 0x07 (needs testing/verification). Each Voice can only hold one Note.<br />Velocity: one byte with range 0x00 through 0x7F. 0x00 = 0, 0x7F = 127. | | {OpCode[1]} {Voice[1]} {Velocity[1]}<br />OpCode: one byte with range 0x00 through 0x7F. 0x00 = C-1, 0x60 = C4 (middle C), 0x7F = G9.<br />Voice: one byte with range 0x01 through 0x07 (needs testing/verification). Each Voice can only hold one Note.<br />Velocity: one byte with range 0x00 through 0x7F. 0x00 = 0, 0x7F = 127.<br/><br/>If the Voice is not 1 - 7, the game will treat this note as a Midi Gate note, and will expect a 4th value that is one or more bytes with range 0x00 through 0xFF. If the leading byte is 0x80 (bit 7 = 1) or greater, another following byte will be taken into account.<br/>It is unknown what effects this has on the output | ||
| 64 02 68<br /><br />64: Key E4<br />02: Voice 2<br />68: Velocity 104 | | 64 02 68<br /><br />64: Key E4<br />02: Voice 2<br />68: Velocity 104 | ||
| Starts playing a Note with the previously defined Instrument (see E1, E2 and E3). | | Starts playing a Note with the previously defined Instrument (see E1, E2 and E3). | ||
|- | |- | ||
| 80 | | 80 | ||
| Unknown | | Unknown.<br/>Seems to do nothing based on the code... | ||
| | | | ||
| | | | ||
Line 27: | Line 27: | ||
| 81<br />...<br />87 | | 81<br />...<br />87 | ||
| | | | ||
| {OpCode[1]}<br />OpCode: one byte with range 0x81 through 0x87 | | {OpCode[1]}<br />OpCode: one byte with range 0x81 through 0x87. 0x81 = Close Voice 1, 0x87 = Close Voice 7. | ||
| | | | ||
| Stops playing a Note. | | Stops playing a Note. |
Revision as of 15:09, 23 October 2024
File Format
BMS files are Binary Music Sequences that store commands for the audio engine to play notes, similar to the MIDI file format.
Data
BMS files contain raw instructions for the audio engine. There are no headers or filesize checks. Each instruction (OpCode) stands for its own function in the engine. The following table lists all JAudio2 OpCodes that have functions in SMG2:
OpCode | Function (SMG/SMG2) | Usage | Example | Description |
---|---|---|---|---|
00 01 02 ... 7D 7E 7F |
{OpCode[1]} {Voice[1]} {Velocity[1]} OpCode: one byte with range 0x00 through 0x7F. 0x00 = C-1, 0x60 = C4 (middle C), 0x7F = G9. Voice: one byte with range 0x01 through 0x07 (needs testing/verification). Each Voice can only hold one Note. Velocity: one byte with range 0x00 through 0x7F. 0x00 = 0, 0x7F = 127. If the Voice is not 1 - 7, the game will treat this note as a Midi Gate note, and will expect a 4th value that is one or more bytes with range 0x00 through 0xFF. If the leading byte is 0x80 (bit 7 = 1) or greater, another following byte will be taken into account. It is unknown what effects this has on the output |
64 02 68 64: Key E4 02: Voice 2 68: Velocity 104 |
Starts playing a Note with the previously defined Instrument (see E1, E2 and E3). | |
80 | Unknown. Seems to do nothing based on the code... |
|||
81 ... 87 |
{OpCode[1]} OpCode: one byte with range 0x81 through 0x87. 0x81 = Close Voice 1, 0x87 = Close Voice 7. |
Stops playing a Note. | ||
88 ... 8F |
Unknown | |||
90 ... 9F |
Unknown | |||
A0 | NULL | |||
A1 | NULL | |||
A2 | NULL | |||
A3 | NULL | |||
A4 | NULL | |||
A5 | NULL | |||
A6 | NULL | |||
A7 | NULL | |||
A8 | NULL | |||
A9 | NULL | |||
AA | NULL | |||
AB | NULL | |||
AC | NULL | |||
AD | NULL | |||
AE | NULL | |||
AF | NULL | |||
B0 | Extended Opcode Indicator | |||
B1 | JASSeqParser::cmdNoteOn | |||
B2 | JASSeqParser::cmdNoteOff | |||
B3 | JASSeqParser::cmdNote | |||
B4 | JASSeqParser::cmdSetLastNote | |||
B5 | NULL | |||
B6 | NULL | |||
B7 | NULL | |||
B8 | JASSeqParser::cmdParamE | |||
B9 | JASSeqParser::cmdParamI | |||
BA | JASSeqParser::cmdParamEI | |||
BB | JASSeqParser::cmdParamII | |||
BC | NULL | |||
BD | NULL | |||
BE | NULL | |||
BF | NULL | |||
C0 | NULL | |||
C1 | JASSeqParser::cmdOpenTrack | {OpCode[1]} {TrackNumber[1]} {Pointer[3]} OpCode: one byte, C1. TrackNumber: one byte with range 0x00 through 0x0F. 0x00 = Track 0, 0x0F = Track 15. Pointer: three bytes with range 0x000000 through 0xFFFFFF. Defines an offset in the file. |
C1 04 05 B4 73 C1: OpCode 04: Track 4 05 B4 73: Offset |
Creates a Track which can play Notes. Track 15 is usually reserved for Yoshi Drums. |
C2 | JASSeqParser::cmdCloseTrack | |||
C3 | JASSeqParser::cmdCall | {OpCode[1]} {Pointer[3]} OpCode: one byte, C3. Pointer: three bytes with range 0x000000 through 0xFFFFFF. Defines an offset in the file. |
C3 00 00 40 C3: OpCode 00 00 40: Offset |
Redirects execution to the defined offset. Execution can return with C5. |
C4 | JASSeqParser::cmdCallF | |||
C5 | JASSeqParser::cmdRet | {OpCode[1]} OpCode: one byte, C5. |
Returns redirected execution (like from C3) to the initial call. | |
C6 | JASSeqParser::cmdRetF | |||
C7 | JASSeqParser::cmdJmp | {OpCode[1]} {Pointer[3]} OpCode: one byte, C7. Pointer: three bytes with range 0x000000 through 0xFFFFFF. Defines an offset in the file. |
C7 08 02 34 C7: OpCode 08 02 34: Offset |
Redirects execution to the defined offset, used for Loops. |
C8 | JASSeqParser::cmdJmpF | |||
C9 | JASSeqParser::cmdJmpTable | |||
CA | JASSeqParser::cmdCallTable | |||
CB | JASSeqParser::cmdLoopS | |||
CC | JASSeqParser::cmdLoopE | |||
CD | NULL | |||
CE | NULL | |||
CF | NULL | |||
D0 | JASSeqParser::cmdReadPort | |||
D1 | JASSeqParser::cmdWritePort | |||
D2 | JASSeqParser::cmdCheckPortImport | |||
D3 | JASSeqParser::cmdCheckPortExport | |||
D4 | JASSeqParser::cmdParentWritePort | |||
D5 | JASSeqParser::cmdChildWritePort | |||
D6 | JASSeqParser::cmdParentReadPort | |||
D7 | JASSeqParser::cmdChildReadPort | |||
D8 | JASSeqParser::cmdRegLoad | |||
D9 | JASSeqParser::cmdReg | |||
DA | JASSeqParser::cmdReg | |||
DB | JASSeqParser::cmdRegUni | |||
DC | JASSeqParser::cmdRegTblLoad | |||
DD | NULL | |||
DE | NULL | |||
DF | NULL | |||
E0 | JASSeqParser::cmdTempo | {OpCode[1]} {Unknown[1]} {BPM[1]} OpCode: one byte, E0. Unknown: one byte with unknown range and purpose. BPM: one byte with range 0x00 through 0xFF. 0x78 = 120, F0 = 240. |
E0 00 90 E0: OpCode 00: Unknown 90: BPM 144 |
Defines the tempo (playback speed) of the BMS file. |
E1 | JASSeqParser::cmdBankPrg | {OpCode[1]} {Bank[1]} {Program[1]} OpCode: one byte, E1. Bank: one byte with range 0x00 through 0xFF. This byte represents a WSYS ID. Program: one byte ranging from 0x00 through 0xFF. This byte represents a LIST entry in the IBNK belonging to the defined WSYS ID. |
E1 01 0F E1: OpCode 01: WSYS ID 1 0F: IBNK LIST entry 15 (01 0F is the percussion set for Yoshi Drums) |
Defines the Instrument to be used in a Track. |
E2 | JASSeqParser::cmdBank | {OpCode[1]} {Bank[1]} OpCode: one byte, E2. Bank: one byte with range 0x00 through 0xFF. This byte represents a WSYS ID. |
E2 53 E2: OpCode 53: WSYS ID 83 (This bank holds sounds for Megahammer) |
Defines the WSYS/IBNK whose sounds are to be used in a Track. |
E3 | JASSeqParser::cmdPrg | {OpCode[1]} {Program[1]} OpCode: one byte, E3. Program: one byte with range 0x00 through 0xFF. This byte represents a LIST entry in the IBNK belonging to the defined WSYS ID. |
E3 0B E3: OpCode 0B: IBNK LIST entry 11 (In relation to Megahammer, this Program holds movement related sounds) |
Defines the Keyboard which holds more specific sounds to an IBNK. |
E4 | NULL | |||
E5 | NULL | |||
E6 | NULL | |||
E7 | JASSeqParser::cmdEnvScaleSet | |||
E8 | JASSeqParser::cmdEnvSet | |||
E9 | JASSeqParser::cmdSimpleADSR | |||
EA | JASSeqParser::cmdBusConnect | |||
EB | JASSeqParser::cmdIIRCutOff | |||
EC | JASSeqParser::cmdIIRSet | |||
ED | JASSeqParser::cmdFIRSet | |||
EE | NULL | |||
EF | NULL | |||
F0 | JASSeqParser::cmdWait | {OpCode[1]} {WaitTime[n]} OpCode: one byte, 0xF0. WaitTime: one or more bytes with range 0x00 through 0xFF. If the leading byte is 0x80 (bit 7 = 1) or greater, another following byte will be taken into account. Time is measured in ticks here. |
F0 60 (96 Ticks) F0 81 56 (214 Ticks) F0 83 81 30 (49328 Ticks) |
Creates a delay, used to define the length of a Note or gap between Notes. |
F1 | JASSeqParser::cmdWaitByte | |||
F2 | NULL | |||
F3 | JASSeqParser::cmdSetIntTable | |||
F4 | JASSeqParser::cmdSetInterrupt | |||
F5 | JASSeqParser::cmdDisInterrupt | |||
F6 | JASSeqParser::cmdRetI | |||
F7 | JASSeqParser::cmdClrI | |||
F8 | JASSeqParser::cmdIntTimer | |||
F9 | JASSeqParser::cmdSyncCPU | |||
FA | NULL | |||
FB | NULL | |||
FC | NULL | |||
FD | JASSeqParser::cmdPrintf | |||
FE | JASSeqParser::cmdNop | |||
FF | JASSeqParser::cmdFinish | {OpCode[1]} OpCode: one byte, 0xFF. |
Stops execution of a Track. | |
B000 | NULL | |||
B001 | JASSeqParser::cmdDump |
Tools
BMS_DEC (converts BMS to MIDI)
JaiSeqX (playback for JAudio1 and JAudio2 BMS files)