#pragma once #include #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)