diff --git a/opmplay/lxmplay/main.cpp b/opmplay/lxmplay/main.cpp index 825f98c..85296fa 100644 --- a/opmplay/lxmplay/main.cpp +++ b/opmplay/lxmplay/main.cpp @@ -68,14 +68,31 @@ vgm_context_t vgmctx; opm_context_t opmctx; class opna_interface_t : public ymfm::ymfm_interface { +protected: + int32_t timer_a_count, timer_a_reload; public: - opna_interface_t() {}; + opna_interface_t() : timer_a_count(0), timer_a_reload(0) {}; uint8_t ymfm_external_read(ymfm::access_class type, uint32_t address) { switch (type) { case ymfm::ACCESS_ADPCM_A: return YM2608_ADPCM_ROM[address & 0x1FFF]; default: return 0; } } + void ymfm_set_timer(uint32_t tnum, int32_t duration_in_clocks) { + if (tnum == 0) { + timer_a_reload = duration_in_clocks; + } + } + void timer_advance(int32_t ticks) { + // ripped from furnace :grins: + if (timer_a_reload >= 0) { + timer_a_count -= ticks; + if (timer_a_count < 0) { + m_engine->engine_timer_expired(0); + timer_a_count += timer_a_reload; + } + } + } }; // register write queue @@ -119,7 +136,7 @@ public: } }; -opna_interface_t opna_interface; +opna_interface_t opna_interface[2]; ymfm::ym2203 *opnachip[2]; opnx_register_queue_t opna_regqueue[2]; ymfm::ym2203::output_data opna_out[MAX_FRAMES_PER_BUFFER][2]; @@ -252,6 +269,7 @@ int synth_render(int16_t* buffer, uint32_t num_samples) { for (int chip = 0; chip < 2; chip++) { opna_regqueue[chip].pop_clock(); opnachip[chip]->generate(opna_out[chip] + i, 1); + opna_interface[chip].timer_advance(24); opna_out[chip][i].clamp16(); buffer[2*i+0] += 0.5*(0.5 * opna_out[chip][i].data[0] + 0.5 * (1.0*opna_out[chip][i].data[1] + 0.5*opna_out[chip][i].data[2] + 0.0*opna_out[chip][i].data[3])); // mix FM and SSG buffer[2*i+1] += 0.5*(0.5 * opna_out[chip][i].data[0] + 0.5 * (0.0*opna_out[chip][i].data[1] + 0.5*opna_out[chip][i].data[2] + 1.0*opna_out[chip][i].data[3])); @@ -268,6 +286,7 @@ int synth_render(int16_t* buffer, uint32_t num_samples) { for (int chip = 0; chip < 2; chip++) { opna_regqueue[chip].pop_clock(); opnachip[chip]->generate(opna_out[chip] + i, 1); + opna_interface[chip].timer_advance(24); opna_out[chip][i].clamp16(); buffer[2*i+0] += 0.5*(0.5 * opna_out[chip][i].data[0] + 0.5 * (1.0*opna_out[chip][i].data[1] + 0.5*opna_out[chip][i].data[2] + 0.0*opna_out[chip][i].data[3])); // mix FM and SSG buffer[2*i+1] += 0.5*(0.5 * opna_out[chip][i].data[0] + 0.5 * (0.0*opna_out[chip][i].data[1] + 0.5*opna_out[chip][i].data[2] + 1.0*opna_out[chip][i].data[3])); @@ -344,7 +363,7 @@ int main(int argc, char* argv[]) uint32_t sample_rate; for (int chip = 0; chip < 2; chip++) { - opnachip[chip] = new ymfm::ym2203(opna_interface); + opnachip[chip] = new ymfm::ym2203(opna_interface[chip]); if (opnachip[chip] == nullptr) { printf("error: unable to init ymfm!\n"); return 1; diff --git a/opmplay/lxmplay/opmplay.cpp b/opmplay/lxmplay/opmplay.cpp index 5b4ec9c..a414ebe 100644 --- a/opmplay/lxmplay/opmplay.cpp +++ b/opmplay/lxmplay/opmplay.cpp @@ -147,7 +147,7 @@ int opmplay_rewind(opmplay_context_t* ctx) { case OPM_FLAG_CHIP_OPN_DUAL: for (int chip = 0; chip < 2; chip++) { for (int r = 0; r < 0xF0; r++) { - opn_write_reg(chip, r, 0); + //opn_write_reg(chip, r, 0); } // setup prescaler opn_write_reg(chip, 0x2F, 0); @@ -201,7 +201,7 @@ static uint32_t opmplay_set_delay(const uint8_t** data) { // stream parsing procedures // bruuuuuuuhhhhhhhhhhhh extern "C" { - uint8_t chip_index; + int chip_index; bool endOfFrame; bool doNextOp; } @@ -212,7 +212,7 @@ const uint8_t* opmplay_parse_fm_control_stream(opmplay_context_t* ctx, opmplay_c // CSM/timer stuff int mask = *data; data++; - if (mask & OPM_CTRL_CMD80_REG25) opn_write_reg(chip_index, 0x24, *data++); + if (mask & OPM_CTRL_CMD80_REG25) opn_write_reg(chip_index, 0x25, *data++); if (mask & OPM_CTRL_CMD80_REG24) opn_write_reg(chip_index, 0x24, *data++); if (mask & OPM_CTRL_CMD80_REG27) opn_write_reg(chip_index, 0x27, *data++); if (mask & OPM_CTRL_CMD80_REG22) opn_write_reg(chip_index, 0x22, *data++);