# HG changeset patch # User Michael Pavone # Date 1432879532 25200 # Node ID 85c98a222fea56346b58a6fbd7b91dbf854da280 # Parent 25c9e9d39997c29a94844c1cd7e18ed6443c6322# Parent 9d4d40f833d0a340bd6ea02de3e2e72c93cec079 Merge diff -r 9d4d40f833d0 -r 85c98a222fea debug.c --- a/debug.c Thu May 28 23:04:49 2015 -0700 +++ b/debug.c Thu May 28 23:05:32 2015 -0700 @@ -768,6 +768,23 @@ } break; } + case 'y': { + genesis_context * gen = context->system; + //YM-2612 debug commands + switch(input_buf[1]) + { + case 'c': + if (input_buf[2] == ' ') { + int channel = atoi(input_buf+3)-1; + ym_print_channel_info(gen->ym, channel); + } else { + for (int i = 0; i < 6; i++) { + ym_print_channel_info(gen->ym, i); + } + } + } + break; + } #ifndef NO_Z80 case 'z': { genesis_context * gen = context->system; diff -r 9d4d40f833d0 -r 85c98a222fea ym2612.c --- a/ym2612.c Thu May 28 23:04:49 2015 -0700 +++ b/ym2612.c Thu May 28 23:05:32 2015 -0700 @@ -108,6 +108,8 @@ }; int16_t lfo_pm_table[128 * 32 * 8]; +uint16_t ams_shift[] = {8, 3, 1, 0}; + #define MAX_ENVELOPE 0xFFC #define YM_DIVIDER 2 #define CYCLE_NEVER 0xFFFFFFFF @@ -268,16 +270,16 @@ context->timer_b = context->timer_b_load; } } - } - //Update LFO - if (context->lfo_enable) { - if (context->lfo_counter) { - context->lfo_counter--; - } else { - context->lfo_counter = lfo_timer_values[context->lfo_freq]; - context->lfo_am_step += 2; - context->lfo_am_step &= 0xFE; - context->lfo_pm_step = context->lfo_am_step / 8; + //Update LFO + if (context->lfo_enable) { + if (context->lfo_counter) { + context->lfo_counter--; + } else { + context->lfo_counter = lfo_timer_values[context->lfo_freq]; + context->lfo_am_step += 2; + context->lfo_am_step &= 0xFE; + context->lfo_pm_step = context->lfo_am_step / 8; + } } } //Update Envelope Generator @@ -427,6 +429,10 @@ break; } uint16_t env = operator->envelope + operator->total_level; + if (operator->am) { + uint16_t base_am = (context->lfo_am_step & 0x80 ? context->lfo_am_step : ~context->lfo_am_step) & 0x7E; + env += base_am >> ams_shift[chan->ams]; + } if (env > MAX_ENVELOPE) { env = MAX_ENVELOPE; } @@ -605,7 +611,7 @@ //detune detune = detune_table[channel->keycode][operator->detune & 0x3]; } - if (operator->detune & 0x40) { + if (operator->detune & 0x4) { inc -= detune; //this can underflow, mask to 17-bit result inc &= 0x1FFFF; @@ -615,6 +621,7 @@ //multiple if (operator->multiple) { inc *= operator->multiple; + inc &= 0xFFFFF; } else { //0.5 inc >>= 1; @@ -748,6 +755,7 @@ break; case REG_DECAY_AM: //TODO: AM flag for LFO + operator->am = value & 0x80; operator->rates[PHASE_DECAY] = value & 0x1F; break; case REG_SUSTAIN_RATE: @@ -821,3 +829,42 @@ return context->status; } +void ym_print_channel_info(ym2612_context *context, int channel) +{ + ym_channel *chan = context->channels + channel; + printf("\n***Channel %d***\n" + "Algorithm: %d\n" + "Feedback: %d\n" + "Pan: %s\n" + "AMS: %d\n" + "PMS: %d\n", + channel+1, chan->algorithm, chan->feedback, + chan->lr == 0xC0 ? "LR" : chan->lr == 0x80 ? "L" : chan->lr == 0x40 ? "R" : "", + chan->ams, chan->pms); + for (int operator = channel * 4; operator < channel * 4+4; operator++) + { + int dispnum = operator - channel * 4 + 1; + if (dispnum == 2) { + dispnum = 3; + } else if (dispnum == 3) { + dispnum = 2; + } + ym_operator *op = context->operators + operator; + printf("\nOperator %d:\n" + " Multiple: %d\n" + " Detune: %d\n" + " Total Level: %d\n" + " Attack Rate: %d\n" + " Key Scaling: %d\n" + " Decay Rate: %d\n" + " Sustain Level: %d\n" + " Sustain Rate: %d\n" + " Release Rate: %d\n" + " Amplitude Modulation %s\n", + dispnum, op->multiple, op->detune, op->total_level, + op->rates[PHASE_ATTACK], op->key_scaling, op->rates[PHASE_DECAY], + op->sustain_level, op->rates[PHASE_SUSTAIN], op->rates[PHASE_RELEASE], + op->am ? "On" : "Off"); + } +} + diff -r 9d4d40f833d0 -r 85c98a222fea ym2612.h --- a/ym2612.h Thu May 28 23:04:49 2015 -0700 +++ b/ym2612.h Thu May 28 23:05:32 2015 -0700 @@ -26,6 +26,7 @@ uint8_t key_scaling; uint8_t multiple; uint8_t detune; + uint8_t am; uint8_t env_phase; } ym_operator; @@ -105,6 +106,7 @@ uint8_t ym_read_status(ym2612_context * context); uint8_t ym_load_gst(ym2612_context * context, FILE * gstfile); uint8_t ym_save_gst(ym2612_context * context, FILE * gstfile); +void ym_print_channel_info(ym2612_context *context, int channel); #endif //YM2612_H_