165 lines
5.8 KiB
C
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)
|