comparison ym2612.c @ 1300:4b893b02444e

Basic implementation of CSM mode that should handle documented edge cases. Dodesn't handle the weird undocumented edge cases I don't have a good understanding of yet though
author Michael Pavone <pavone@retrodev.com>
date Sat, 25 Mar 2017 15:41:52 -0700
parents c15896605bf2
children babff81e4cfd
comparison
equal deleted inserted replaced
1299:da1ffc4026c4 1300:4b893b02444e
250 #define YM_MOD_SHIFT 1 250 #define YM_MOD_SHIFT 1
251 251
252 #define TIMER_A_MAX 1023 252 #define TIMER_A_MAX 1023
253 #define TIMER_B_MAX 255 253 #define TIMER_B_MAX 255
254 254
255 #define CSM_MODE 0x80
256
257 static void keyon(ym_operator *op, ym_channel *channel)
258 {
259 //Deal with "infinite" attack rates
260 uint8_t rate = op->rates[PHASE_ATTACK];
261 if (rate) {
262 uint8_t ks = channel->keycode >> op->key_scaling;;
263 rate = rate*2 + ks;
264 }
265 if (rate >= 62) {
266 op->env_phase = PHASE_DECAY;
267 op->envelope = 0;
268 } else {
269 op->env_phase = PHASE_ATTACK;
270 }
271 op->phase_counter = 0;
272 }
273
274 static const uint8_t keyon_bits[] = {0x10, 0x40, 0x20, 0x80};
275
276 static void csm_keyoff(ym2612_context *context)
277 {
278 context->csm_keyon = 0;
279 uint8_t changes = 0xF0 ^ context->channels[2].keyon;
280 for (uint8_t op = 2*4, bit = 0; op < 3*4; op++, bit++)
281 {
282 if (changes & keyon_bits[bit]) {
283 context->operators[op].env_phase = PHASE_RELEASE;
284 }
285 }
286 }
287
255 void ym_run(ym2612_context * context, uint32_t to_cycle) 288 void ym_run(ym2612_context * context, uint32_t to_cycle)
256 { 289 {
257 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle); 290 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle);
258 //TODO: Fix channel update order OR remap channels in register write 291 //TODO: Fix channel update order OR remap channels in register write
259 for (; context->current_cycle < to_cycle; context->current_cycle += context->clock_inc) { 292 for (; context->current_cycle < to_cycle; context->current_cycle += context->clock_inc) {
260 //Update timers at beginning of 144 cycle period 293 //Update timers at beginning of 144 cycle period
261 if (!context->current_op) { 294 if (!context->current_op) {
262 if (context->timer_control & BIT_TIMERA_ENABLE) { 295 if (context->timer_control & BIT_TIMERA_ENABLE) {
263 if (context->timer_a != TIMER_A_MAX) { 296 if (context->timer_a != TIMER_A_MAX) {
264 context->timer_a++; 297 context->timer_a++;
298 if (context->csm_keyon) {
299 csm_keyoff(context);
300 }
265 } else { 301 } else {
266 if (context->timer_control & BIT_TIMERA_LOAD) { 302 if (context->timer_control & BIT_TIMERA_LOAD) {
267 context->timer_control &= ~BIT_TIMERA_LOAD; 303 context->timer_control &= ~BIT_TIMERA_LOAD;
268 } else if (context->timer_control & BIT_TIMERA_OVEREN) { 304 } else if (context->timer_control & BIT_TIMERA_OVEREN) {
269 context->status |= BIT_STATUS_TIMERA; 305 context->status |= BIT_STATUS_TIMERA;
270 } 306 }
271 context->timer_a = context->timer_a_load; 307 context->timer_a = context->timer_a_load;
308 if (!context->csm_keyon && context->ch3_mode == CSM_MODE) {
309 context->csm_keyon = 0xF0;
310 uint8_t changes = 0xF0 ^ context->channels[2].keyon;;
311 for (uint8_t op = 2*4, bit = 0; op < 3*4; op++, bit++)
312 {
313 if (changes & keyon_bits[bit]) {
314 keyon(context->operators + op, context->channels + 2);
315 }
316 }
317 }
272 } 318 }
273 } 319 }
274 if (!context->sub_timer_b) { 320 if (!context->sub_timer_b) {
275 if (context->timer_control & BIT_TIMERB_ENABLE) { 321 if (context->timer_control & BIT_TIMERB_ENABLE) {
276 if (context->timer_b != TIMER_B_MAX) { 322 if (context->timer_b != TIMER_B_MAX) {
307 uint8_t rate; 353 uint8_t rate;
308 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) { 354 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) {
309 //operator->envelope = operator->sustain_level; 355 //operator->envelope = operator->sustain_level;
310 operator->env_phase = PHASE_SUSTAIN; 356 operator->env_phase = PHASE_SUSTAIN;
311 } 357 }
312 for(;;) { 358 rate = operator->rates[operator->env_phase];
313 rate = operator->rates[operator->env_phase]; 359 if (rate) {
314 if (rate) { 360 uint8_t ks = channel->keycode >> operator->key_scaling;;
315 uint8_t ks = channel->keycode >> operator->key_scaling;; 361 rate = rate*2 + ks;
316 rate = rate*2 + ks; 362 if (rate > 63) {
317 if (rate > 63) { 363 rate = 63;
318 rate = 63;
319 }
320 }
321 //Deal with "infinite" rates
322 //According to Nemesis this should be handled in key-on instead
323 if (rate >= 62 && operator->env_phase == PHASE_ATTACK) {
324 operator->env_phase = PHASE_DECAY;
325 operator->envelope = 0;
326 } else {
327 break;
328 } 364 }
329 } 365 }
330 uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0; 366 uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0;
331 if (first_key_on) { 367 if (first_key_on) {
332 dfprintf(debug_file, "Operator: %d, env rate: %d (2*%d+%d), env_cyc: %d, cycle_shift: %d, env_cyc & ((1 << cycle_shift) - 1): %d\n", op, rate, operator->rates[operator->env_phase], channel->keycode >> operator->key_scaling,env_cyc, cycle_shift, env_cyc & ((1 << cycle_shift) - 1)); 368 dfprintf(debug_file, "Operator: %d, env rate: %d (2*%d+%d), env_cyc: %d, cycle_shift: %d, env_cyc & ((1 << cycle_shift) - 1): %d\n", op, rate, operator->rates[operator->env_phase], channel->keycode >> operator->key_scaling,env_cyc, cycle_shift, env_cyc & ((1 << cycle_shift) - 1));
725 context->status &= ~BIT_STATUS_TIMERA; 761 context->status &= ~BIT_STATUS_TIMERA;
726 } 762 }
727 if (value & BIT_TIMERB_RESET) { 763 if (value & BIT_TIMERB_RESET) {
728 context->status &= ~BIT_STATUS_TIMERB; 764 context->status &= ~BIT_STATUS_TIMERB;
729 } 765 }
766 if (context->ch3_mode == CSM_MODE && (value & 0xC0) != CSM_MODE && context->csm_keyon) {
767 csm_keyoff(context);
768 }
730 context->ch3_mode = value & 0xC0; 769 context->ch3_mode = value & 0xC0;
731 break; 770 break;
732 } 771 }
733 case REG_KEY_ONOFF: { 772 case REG_KEY_ONOFF: {
734 uint8_t channel = value & 0x7; 773 uint8_t channel = value & 0x7;
735 if (channel != 3 && channel != 7) { 774 if (channel != 3 && channel != 7) {
736 if (channel > 2) { 775 if (channel > 2) {
737 channel--; 776 channel--;
738 } 777 }
739 uint8_t bits[] = {0x10, 0x40, 0x20, 0x80}; 778 uint8_t changes = channel == 2
779 ? (value | context->csm_keyon) ^ (context->channels[channel].keyon | context->csm_keyon)
780 : value ^ context->channels[channel].keyon;
781 context->channels[channel].keyon = value & 0xF0;
740 for (uint8_t op = channel * 4, bit = 0; op < (channel + 1) * 4; op++, bit++) { 782 for (uint8_t op = channel * 4, bit = 0; op < (channel + 1) * 4; op++, bit++) {
741 if (value & bits[bit]) { 783 if (changes & keyon_bits[bit]) {
742 if (context->operators[op].env_phase == PHASE_RELEASE) 784 if (value & keyon_bits[bit]) {
743 {
744 first_key_on = 1; 785 first_key_on = 1;
745 //printf("Key On for operator %d in channel %d\n", op, channel); 786 //printf("Key On for operator %d in channel %d\n", op, channel);
746 context->operators[op].phase_counter = 0; 787 keyon(context->operators + op, context->channels + channel);
747 context->operators[op].env_phase = PHASE_ATTACK; 788 } else {
789 //printf("Key Off for operator %d in channel %d\n", op, channel);
790 context->operators[op].env_phase = PHASE_RELEASE;
748 } 791 }
749 } else {
750 //printf("Key Off for operator %d in channel %d\n", op, channel);
751 context->operators[op].env_phase = PHASE_RELEASE;
752 } 792 }
753 } 793 }
754 } 794 }
755 break; 795 break;
756 } 796 }