DRO Format

From ModdingWiki
Jump to: navigation, search
DRO Format
Format typeMusic
Notation typeOPL
InstrumentsOPL
Max channel count9 or 11 (OPL2), 18 or 22 (Dual OPL2 and OPL3)
Max track count1
Max pattern countUnknown
Max order countUnknown
Tags?Unknown
GamesNone

The DOSBox Raw OPL (DRO) format is used for storing captured OPL data from a game running in the cross-platform DOS emulator DOSBox.

File format

The file begins with a header:

Data type Name Description
BYTE[8] cSignature "DBRAWOPL" (not NULL-terminated)
UINT16LE iVersionMajor Version number (high)
UINT16LE iVersionMinor Version number (low)

The rest of the header depends on the version. If iVersionMajor is 5 and iVersionMinor is 6, then the version would be called "5.6" here.

Version 0.1

The first version of the DRO Format was used up to and including DOSBox version 0.72. Note that the major and minor field names were swapped beginning with DOSBox 0.73, so this version used to be 1.0, but after DOSBox 0.73 it became 0.1 instead.

Header

The version 0.1 header follows on directly from the main file header.

Data type Name Description
UINT32LE iLengthMS Length of the song in milliseconds
UINT32LE iLengthBytes Length of the song data in bytes
UINT8 iHardwareType Flag listing the hardware used in the song
UINT8[3] iHardwareExtra Rest of hardware type or song data (see below)

iHardwareType is one of the following values:

iHardwareType Description
0 OPL2
1 OPL3
2 Dual OPL2

In early files, the field was a UINT8, however in most common (recent) files it is a UINT32LE with only the first byte used. Unfortunately the version number was not changed between these revisions, so the only way to correctly identify the formats is to check the three iHardwareExtra bytes. If these are all zero then they can safely be ignored (iHardwareType was a UINT32.) If any of the three bytes in iHardwareExtra are non-zero, then this is an early revision of the format and those three bytes are actually song data[1].

Song data

Directly following the header is iLengthBytes bytes of OPL data. The first byte in the song data will be the OPL register, followed by the byte to send to that register. The "register" can also be one of these control values:

Register value Data size Purpose
0x00 1 Delay. The single data byte following should be incremented by one, and is then the delay in milliseconds.
0x01 2 Delay. Same as above only there are two bytes following, in the form of a UINT16LE integer.
0x02 0 Switch to "low" OPL chip (#0)
0x03 0 Switch to "high" OPL chip (#1)
0x04 2 Escape - the next two bytes are normal register/value pairs even though the register might be 0x00-0x04
Other 1 Anything else should be treated as an OPL register, with the byte following being the data to send to that register.

The delays all need to be incremented by one, as having a delay of zero milliseconds would be a waste of space. Codes 0x02 and 0x03 switch between two OPL chips in dual OPL2 mode, or between register banks in OPL3 mode. These should only be used if the hardware flag in the header indicates the file is in dual-OPL2 or OPL3 format.

All delays are in milliseconds (which can be treated as 1000Hz if converting between other formats.)

Version 2.0

Version 2.0 of the DRO Format was introduced with DOSBox 0.73.

Header

The version 2.0 header also follows on directly from the main file header.

Data type Name Description
UINT32LE iLengthPairs Length of the song in register/value pairs (TODO: confirm - 1 == one register + one value, or two bytes)
UINT32LE iLengthMS Length of the song data ("chunk" -?) in milliseconds
UINT8 iHardwareType Flag listing the hardware used in the song
UINT8 iFormat Data arrangement
UINT8 iCompression Compression type, zero means no compression (currently only zero is used)
UINT8 iShortDelayCode Command code for short delay (1-256ms)
UINT8 iLongDelayCode Command code for short delay (> 256ms)
UINT8 iCodemapLength Number of entries in codemap table
UINT8[iCodemapLength] iCodemap Codemap table (see below)

iHardwareType is one of the following values: (which are different in v1.0 and v2.0)

iHardwareType Description
0 OPL2
1 Dual OPL2
2 OPL3

iFormat is one of the following values:

iFormat Description
0 Commands and data are interleaved (default/as per v1.0)
1 Maybe all commands, followed by all data (unused? - TODO: Confirm)

Notes:

  • iLengthMS is at a different offset in v1.0 and v2.0
  • The iShortDelayCode value must have one added to it, as per v1.0 (so a short delay of 2 == a 3ms delay)
  • The iLongDelayCode value must have one added to it, then be multiplied by 256 (or "<< 8"), so a long delay of 2 == a 768ms delay
  • Because the high bit in each codeword is used to refer to the second OPL2 chip (or the second set of registers in an OPL3), there are only 128 possible codewords (0-127). Therefore iCodemapLength must always be 128 or less.
  • DOSBox dumps a snapshot of the current register state at the beginning of a capture. (Any other registers are assumed initialised to zero.) This means that even an OPL2 only song will appear to have some data sent to the second OPL chip, because of this initial snapshot. To really know whether the second OPL chip is in use, you can find out if it is actually making any sound, like so:
    • Examine bit 5 (0x20) on registers 0xB0 to 0xB8. If this bit is set, a note is playing and the chip is being used.
    • Check whether bitmask 0x1F on register 0xBD is greater than 0x10 (i.e. if (reg[0xBD] & 0x1F > 0x10) ...). If so, the chip is in percussive mode and a rhythm instrument is being played, so the chip is being used.
Codemap table

The codemap table maps index numbers to OPL registers. As there are 256 possible OPL registers but only a subset of these actually used, the mapping table allows up to 128 OPL registers to be used in a song. The other 128 (with the high bit set) are used for the second OPL2 chip in a dual-OPL2 capture.

The table is a list of iCodemapLength bytes, with the index used later in the file. For example this code table:

01 04 05 08 BD

Means that when the song references register #0 the data should be sent to OPL register 0x01, when the song references register #4 the data should go to OPL register 0xBD. If the song references register #128 (i.e. register 128+0), data should be sent to OPL register 0x01 on the second chip (in dual OPL2 mode) or the second set of registers (OPL3 mode). Likewise register #132 (128+4) is OPL register 0xBD on the second chip.

Song data

Directly following the header is the song data in register index and value pairs.

Data type Name Description
UINT8 iRegisterIndex Register to write to. This is an index into the codemap table.
UINT8 iValue Value to write to the OPL register

This structure is repeated iLengthPairs times. Note that while iRegisterIndex is normally an index into the codemap table, it can also match iShortDelayCode or iLongDelayCode if iValue is to be treated as a delay length (see above.) If the high bit is set (iRegisterIndex & 0x80) then it is a register on the second OPL chip in a dual-OPL2 song (so the high bit should be removed and the value looked up as normal, but then sent to the second OPL chip instead.)

Related information

Tools

  • DRO2MIDI - converts .dro files into .mid files
  • DRO2IMF - converts .dro files into .imf files
  • DRO Trimmer - edits .dro files to remove unwanted notes from the start and end
  • DOSBox - produces .dro files as a result of capturing Adlib data from DOS games and applications

Similar formats

  • Rdos' RAW format serves the same purpose, only these files were originally created through the RAC (Rdos Adlib Capture) TSR running under native DOS.
  • The id Software Music Format (IMF) stores Adlib data in a similar manner in order to provide background music in many Apogee games.

References

  1. In the AdPlug distribution, tests/samurai.dro is the early one-byte format, and doofus.dro is the later four-byte variant.