# HG changeset patch # User Mike Pavone # Date 1371369383 25200 # Node ID f0a3f86595ae90856ddb6a560e8855036f4c9c54 # Parent de2c085ce1740621fc063aa60aeef15128fee9a2 Fix YM2612 timers diff -r de2c085ce174 -r f0a3f86595ae ym2612.c --- a/ym2612.c Sat Jun 15 23:50:59 2013 -0700 +++ b/ym2612.c Sun Jun 16 00:56:23 2013 -0700 @@ -159,32 +159,34 @@ #define YM_VOLUME_DIVIDER 2 #define YM_MOD_SHIFT 1 +#define TIMER_A_MAX 1023 +#define TIMER_B_MAX (255*16) + void ym_run(ym2612_context * context, uint32_t to_cycle) { //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle); //TODO: Fix channel update order OR remap channels in register write for (; context->current_cycle < to_cycle; context->current_cycle += context->clock_inc) { //Update timers at beginning of 144 cycle period - if (!context->current_op && context->timer_control & BIT_TIMERA_ENABLE) { - if (context->timer_a) { - context->timer_a--; - } else { - if (context->timer_control & BIT_TIMERA_OVEREN) { - context->status |= BIT_STATUS_TIMERA; + if (!context->current_op) { + if (context->timer_control & BIT_TIMERA_ENABLE) { + if (context->timer_a != TIMER_A_MAX) { + context->timer_a++; + } else { + if (context->timer_control & BIT_TIMERA_OVEREN) { + context->status |= BIT_STATUS_TIMERA; + } + context->timer_a = context->timer_a_load; } - context->timer_a = context->timer_a_load; } if (context->timer_control & BIT_TIMERB_ENABLE) { - uint32_t b_cyc = (context->current_cycle / OP_UPDATE_PERIOD) % 16; - if (!b_cyc) { - if (context->timer_b) { - context->timer_b--; - } else { - if (context->timer_control & BIT_TIMERB_OVEREN) { - context->status |= BIT_STATUS_TIMERB; - } - context->timer_b = context->timer_b_load; + if (context->timer_b != TIMER_B_MAX) { + context->timer_b++; + } else { + if (context->timer_control & BIT_TIMERB_OVEREN) { + context->status |= BIT_STATUS_TIMERB; } + context->timer_b = context->timer_b_load; } } } @@ -512,10 +514,22 @@ context->timer_a_load |= value & 0x3; break; case REG_TIMERB: - context->timer_b_load = value; + context->timer_b_load = value * 16; break; case REG_TIME_CTRL: { - context->timer_control = value & 0x3F; + if (value & BIT_TIMERA_ENABLE && !(context->timer_control & BIT_TIMERA_ENABLE)) { + context->timer_a = context->timer_a_load; + } + if (value & BIT_TIMERB_ENABLE && !(context->timer_control & BIT_TIMERB_ENABLE)) { + context->timer_b = context->timer_b_load; + } + context->timer_control = value & 0xF; + if (value & BIT_TIMERA_RESET) { + context->status &= ~BIT_STATUS_TIMERA; + } + if (value & BIT_TIMERB_RESET) { + context->status &= ~BIT_STATUS_TIMERB; + } uint8_t old_mode = context->ch3_mode; context->ch3_mode = value & 0xC0; if (context->ch3_mode != old_mode) { diff -r de2c085ce174 -r f0a3f86595ae ym2612.h --- a/ym2612.h Sat Jun 15 23:50:59 2013 -0700 +++ b/ym2612.h Sun Jun 16 00:56:23 2013 -0700 @@ -55,13 +55,14 @@ ym_channel channels[NUM_CHANNELS]; uint16_t timer_a; uint16_t timer_a_load; + uint16_t timer_b; + uint16_t timer_b_load; uint16_t env_counter; ym_supp ch3_supp[3]; uint8_t ch3_mode; uint8_t current_op; uint8_t current_env_op; - uint8_t timer_b; - uint8_t timer_b_load; + uint8_t timer_control; uint8_t dac_enable; uint8_t status;