# HG changeset patch # User Mike Pavone # Date 1370406192 25200 # Node ID 72933100c55c17c36a35571554bbea16e99aef72 # Parent b904859964e562a83e6f9a231b652b4a8431b5af Initial implementation of channel 3 special mode diff -r b904859964e5 -r 72933100c55c ym2612.c --- a/ym2612.c Tue Jun 04 09:16:41 2013 -0700 +++ b/ym2612.c Tue Jun 04 21:23:12 2013 -0700 @@ -454,14 +454,26 @@ //printf("ym_update_phase_inc | channel: %d, op: %d\n", chan_num, op); //base frequency ym_channel * channel = context->channels + chan_num; - uint32_t inc = channel->fnum; - if (!channel->block) { - inc >>= 1; + uint32_t inc, detune; + if (chan_num == 2 && context->ch3_mode && (op < (2*4 + 3))) { + inc = context->ch3_supp[op-2*4].fnum; + if (!context->ch3_supp[op-2*4].block) { + inc >>= 1; + } else { + inc <<= (context->ch3_supp[op-2*4].block-1); + } + //detune + detune = detune_table[context->ch3_supp[op-2*4].keycode][operator->detune & 0x3]; } else { - inc <<= (channel->block-1); - } - //detune - uint32_t detune = detune_table[channel->keycode][operator->detune & 0x3]; + inc = channel->fnum; + if (!channel->block) { + inc >>= 1; + } else { + inc <<= (channel->block-1); + } + //detune + detune = detune_table[channel->keycode][operator->detune & 0x3]; + } if (operator->detune & 0x40) { inc -= detune; //this can underflow, mask to 17-bit result @@ -502,9 +514,17 @@ case REG_TIMERB: context->timer_b_load = value; break; - case REG_TIME_CTRL: - context->timer_control = value; + case REG_TIME_CTRL: { + context->timer_control = value & 0x3F; + uint8_t old_mode = context->ch3_mode; + context->ch3_mode = value & 0xC0; + if (context->ch3_mode != old_mode) { + ym_update_phase_inc(context, context->operators + 2*4, 2*4); + ym_update_phase_inc(context, context->operators + 2*4+1, 2*4+1); + ym_update_phase_inc(context, context->operators + 2*4+2, 2*4+2); + } break; + } case REG_KEY_ONOFF: { uint8_t channel = value & 0x7; if (channel < NUM_CHANNELS) { @@ -591,7 +611,21 @@ context->channels[channel].block_fnum_latch = value; break; } - //TODO: Channel 3 special/CSM modes + case REG_FNUM_LOW_CH3: + if (channel < 3) { + context->ch3_supp[channel].block = context->ch3_supp[channel].block_fnum_latch >> 3 & 0x7; + context->ch3_supp[channel].fnum = (context->ch3_supp[channel].block_fnum_latch & 0x7) << 8 | value; + context->ch3_supp[channel].keycode = context->ch3_supp[channel].block << 2 | fnum_to_keycode[context->ch3_supp[channel].fnum >> 7]; + if (context->ch3_mode) { + ym_update_phase_inc(context, context->operators + 2*4 + channel, 2*4); + } + } + break; + case REG_BLOCK_FN_CH3: + if (channel < 3) { + context->ch3_supp[channel].block_fnum_latch = value; + } + break; case REG_ALG_FEEDBACK: context->channels[channel].algorithm = value & 0x7; context->channels[channel].feedback = value >> 3 & 0x7; diff -r b904859964e5 -r 72933100c55c ym2612.h --- a/ym2612.h Tue Jun 04 09:16:41 2013 -0700 +++ b/ym2612.h Tue Jun 04 21:23:12 2013 -0700 @@ -35,6 +35,13 @@ } ym_channel; typedef struct { + uint16_t fnum; + uint8_t block; + uint8_t block_fnum_latch; + uint8_t keycode; +} ym_supp; + +typedef struct { int16_t *audio_buffer; int16_t *back_buffer; double buffer_fraction; @@ -49,6 +56,8 @@ uint16_t timer_a; uint16_t timer_a_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;