moe-bius/vgmplay/lxmplay/opmfile.h

165 lines
5.8 KiB
C

#pragma once
#include <stdint.h>
#pragma pack(push, 1)
enum {
OPM_FORMAT_VERSION = 0x0010
};
struct opm_header_stream_desc_t {
//uint16_t ptr; // offset to data stream in paragraphs (bytes*16)
uint16_t size; // stream data size in bytes (max. 65520 bytes)
};
enum {
OPM_CHIPTYPE_OPL = (0 << 0),
OPM_CHIPTYPE_OPN = (1 << 0),
};
enum {
OPM_FLAG_CHIP_OPN = (0 << 0),
OPM_FLAG_CHIP_OPN_DUAL = (1 << 0),
OPM_FLAG_CHIP_OPNA = (2 << 0),
OPM_FLAG_CHIP_OPN3 = (3 << 0),
OPM_FLAG_CHIP_TYPE = (3 << 0),
};
struct opm_header_t {
char magic[4]; // "OPM\x1A"
union {
struct {
uint8_t minor;
uint8_t major;
};
uint16_t v;
} version;
uint8_t chip_type; // see above
uint8_t reserved0; //
uint32_t clock_rate; // hz, integer
uint16_t frame_rate; // hz, 8.8 fixedpoint
uint16_t flags; // see above
uint8_t callstack_depth; // reserved, 0 at this moment
uint8_t streams; // including control streams
uint32_t stream_mask; // used channel mask, LSB = ch 0
// opm_header_stream_desc_t stream[opm_header_t::channels]; // first is control stream
};
// OPM v0 stream data, stream-independent commands
enum {
OPM_STREAM_END_FRAME = 0xFF, // end of frame, next channel
OPM_STREAM_END = 0xFE, // end of stream, stop here or loop to OPM_STREAM_LOOP stream point
OPM_STREAM_NOP = 0xFD,
OPM_STREAM_NEW_ORDER = 0xFC, // nop, marks new order
OPM_STREAM_SET_FRAME_RATE = 0xFB, // word rate (as in opm_header_t::frame_rate)
OPM_STREAM_LOOP = 0xFA, // set loop point here
// delay commands
OPM_STREAM_DELAY_INT32 = 0xF9, // dword delay
OPM_STREAM_DELAY_INT16 = 0xF8, // word delay
OPM_STREAM_DELAY_INT12 = 0xD0, // D0..DF - 0..4095 frames delay (hibyte in low 4 bits of command)
OPM_STERAM_DELAY_SHORT = 0xC0, // C0..CF - 1..16 frames delay
// back reference
OPM_STREAM_BACKREF = 0xE0, // E0..EF - word backrefpos (12 bit), byte frames
};
// OPN control stream commands
enum {
OPM_CTRL_EXTCH3 = 0x00, // 00..7F - ext. CH3 op1-3 frequency
OPM_CTRL_TIMER_CSM = 0x80, // 80..9F - set timer/CSM/LFO frequency
OPM_CTRL_RHYTHM = 0xA0, // A0..BF - rhythm control
OPM_CTRL_CMD80_REG24 = (1 << 0),
OPM_CTRL_CMD80_REG25 = (1 << 1),
OPM_CTRL_CMD80_REG27 = (1 << 2),
OPM_CTRL_CMD80_REG22 = (1 << 3),
OPM_CTRL_CMD80_EOF = (1 << 4),
OPM_CTRL_EXTCH3_OP1_LOW = (1 << 0),
OPM_CTRL_EXTCH3_OP1_HIGH = (1 << 1),
OPM_CTRL_EXTCH3_OP2_LOW = (1 << 2),
OPM_CTRL_EXTCH3_OP2_HIGH = (1 << 3),
OPM_CTRL_EXTCH3_OP3_LOW = (1 << 4),
OPM_CTRL_EXTCH3_OP3_HIGH = (1 << 5),
OPM_CTRL_EXTCH3_EOF = (1 << 6),
OPM_CTRL_CMDA0_REG_MASK = (0x0F << 0),
OPM_CTRL_CMDA0_EOF = (1 << 4),
};
// OPN FM stream commands
enum {
OPM_FM_ADSR = 0x00, // 00..3F - set ADSR
OPM_FM_MUL_TL_EG = 0x40, // 40..7F - set MULT/TL/SSG-EG
OPM_FM_FREQ_FB_PAN = 0x80, // 80..9F - set frequency/feedback/panning
OPM_FM_KEY = 0xA0, // A0..BF - key on/off
OPM_FM_CMD00_REG50 = (1 << 0),
OPM_FM_CMD00_REG60 = (1 << 1),
OPM_FM_CMD00_REG70 = (1 << 2),
OPM_FM_CMD00_REG80 = (1 << 3),
OPM_FM_CMD00_OP_SHIFT = 4,
OPM_FM_CMD00_OP_MASK = (3 << OPM_FM_CMD00_OP_SHIFT),
OPM_FM_CMD40_REG30 = (1 << 0),
OPM_FM_CMD40_REG40 = (1 << 1),
OPM_FM_CMD40_REG90 = (1 << 2),
OPM_FM_CMD40_EOF = (1 << 3),
OPM_FM_CMD40_OP_SHIFT = OPM_FM_CMD00_OP_SHIFT,
OPM_FM_CMD40_OP_MASK = OPM_FM_CMD00_OP_MASK,
OPM_FM_CMD80_REGA0 = (1 << 0),
OPM_FM_CMD80_REGA4 = (1 << 1),
OPM_FM_CMD80_REGB0 = (1 << 2),
OPM_FM_CMD80_REGB4 = (1 << 3),
OPM_FM_CMD80_EOF = (1 << 4),
OPM_FM_CMDA0_OP_SHIFT = 0,
OPM_FM_CMDA0_OP_MASK = (0x0F << OPM_FM_CMDA0_OP_SHIFT),
OPM_FM_CMDA0_EOF = (1 << 4),
};
// OPN SSG tone stream commands (shared with AY chip type)
enum {
OPM_AYTONE_REGS = 0x00, // 00..7F - set volume and period low
OPM_AYTONE_PERIOD = 0x80, // 80..BF - set period
OPM_AYTONE_MASK = 0xF0, // F0..F7 - set tone/noise mask
OPM_AYTONE_CMD00_VOLUME_MASK = (0x1F << 0),
OPM_AYTONE_CMD00_PERIOD_LOW = (1 << 5),
OPM_AYTONE_CMD00_EOF = (1 << 6),
OPM_AYTONE_CMD80_PERIOD_HIGH = (0xF << 0),
OPM_AYTONE_CMD80_PERIOD_LOW = (1 << 4),
OPM_AYTONE_CMD80_EOF = (1 << 5),
OPM_AYTONE_MASK_TONE = (1 << 0),
OPM_AYTONE_MASK_NOISE = (1 << 1),
OPM_AYTONE_MASK_EOF = (1 << 2),
};
// OPN SSG envelope/noise stream commands (shared with AY chip type)
enum {
OPM_AYENV_REGS = 0x00, // 00..7F - set noise and period low
OPM_AYENV_ENVTYPE = 0x80, // 80..BF - set env type and period low
OPM_AYENV_PERIOD_FULL = 0xF0, // F0..F7 - set full envelope period
OPM_AYENV_CMD00_NOISE_MASK = (0x1F << 0),
OPM_AYENV_CMD00_PERIOD_LOW = (1 << 5),
OPM_AYENV_CMD00_EOF = (1 << 6),
OPM_AYENV_CMD80_ENV_TYPE = (0xF << 0),
OPM_AYENV_CMD80_PERIOD_LOW = (1 << 4),
OPM_AYENV_CMD80_EOF = (1 << 5),
OPM_AYENV_CMDF0_PERIOD_LOW = (1 << 0),
OPM_AYENV_CMDF0_PERIOD_HIGH = (1 << 1),
OPM_AYENV_CMDF0_EOF = (1 << 2),
};
#pragma pack(pop)