fix extch3, implement (roughly) CSM timers

This commit is contained in:
wbcbz7 2025-08-13 04:30:17 +07:00
parent 397a060633
commit 299b3fc236
2 changed files with 25 additions and 6 deletions

View file

@ -68,14 +68,31 @@ vgm_context_t vgmctx;
opm_context_t opmctx; opm_context_t opmctx;
class opna_interface_t : public ymfm::ymfm_interface { class opna_interface_t : public ymfm::ymfm_interface {
protected:
int32_t timer_a_count, timer_a_reload;
public: 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) { uint8_t ymfm_external_read(ymfm::access_class type, uint32_t address) {
switch (type) { switch (type) {
case ymfm::ACCESS_ADPCM_A: return YM2608_ADPCM_ROM[address & 0x1FFF]; case ymfm::ACCESS_ADPCM_A: return YM2608_ADPCM_ROM[address & 0x1FFF];
default: return 0; 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 // register write queue
@ -119,7 +136,7 @@ public:
} }
}; };
opna_interface_t opna_interface; opna_interface_t opna_interface[2];
ymfm::ym2203 *opnachip[2]; ymfm::ym2203 *opnachip[2];
opnx_register_queue_t opna_regqueue[2]; opnx_register_queue_t opna_regqueue[2];
ymfm::ym2203::output_data opna_out[MAX_FRAMES_PER_BUFFER][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++) { for (int chip = 0; chip < 2; chip++) {
opna_regqueue[chip].pop_clock(); opna_regqueue[chip].pop_clock();
opnachip[chip]->generate(opna_out[chip] + i, 1); opnachip[chip]->generate(opna_out[chip] + i, 1);
opna_interface[chip].timer_advance(24);
opna_out[chip][i].clamp16(); 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+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])); 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++) { for (int chip = 0; chip < 2; chip++) {
opna_regqueue[chip].pop_clock(); opna_regqueue[chip].pop_clock();
opnachip[chip]->generate(opna_out[chip] + i, 1); opnachip[chip]->generate(opna_out[chip] + i, 1);
opna_interface[chip].timer_advance(24);
opna_out[chip][i].clamp16(); 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+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])); 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; uint32_t sample_rate;
for (int chip = 0; chip < 2; chip++) { 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) { if (opnachip[chip] == nullptr) {
printf("error: unable to init ymfm!\n"); printf("error: unable to init ymfm!\n");
return 1; return 1;

View file

@ -147,7 +147,7 @@ int opmplay_rewind(opmplay_context_t* ctx) {
case OPM_FLAG_CHIP_OPN_DUAL: case OPM_FLAG_CHIP_OPN_DUAL:
for (int chip = 0; chip < 2; chip++) { for (int chip = 0; chip < 2; chip++) {
for (int r = 0; r < 0xF0; r++) { for (int r = 0; r < 0xF0; r++) {
opn_write_reg(chip, r, 0); //opn_write_reg(chip, r, 0);
} }
// setup prescaler // setup prescaler
opn_write_reg(chip, 0x2F, 0); opn_write_reg(chip, 0x2F, 0);
@ -201,7 +201,7 @@ static uint32_t opmplay_set_delay(const uint8_t** data) {
// stream parsing procedures // stream parsing procedures
// bruuuuuuuhhhhhhhhhhhh // bruuuuuuuhhhhhhhhhhhh
extern "C" { extern "C" {
uint8_t chip_index; int chip_index;
bool endOfFrame; bool endOfFrame;
bool doNextOp; bool doNextOp;
} }
@ -212,7 +212,7 @@ const uint8_t* opmplay_parse_fm_control_stream(opmplay_context_t* ctx, opmplay_c
// CSM/timer stuff // CSM/timer stuff
int mask = *data; int mask = *data;
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_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_REG27) opn_write_reg(chip_index, 0x27, *data++);
if (mask & OPM_CTRL_CMD80_REG22) opn_write_reg(chip_index, 0x22, *data++); if (mask & OPM_CTRL_CMD80_REG22) opn_write_reg(chip_index, 0x22, *data++);