Mercurial > repos > blastem
comparison ym2612.c @ 1931:374a5ae694e8 mame_interp
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 18 Apr 2020 11:42:53 -0700 |
parents | 00fb99805445 |
children | c3c62dbf1ceb |
comparison
equal
deleted
inserted
replaced
1843:13abdc98379e | 1931:374a5ae694e8 |
---|---|
19 #else | 19 #else |
20 #define dfprintf | 20 #define dfprintf |
21 #define dfopen(var, fname, mode) | 21 #define dfopen(var, fname, mode) |
22 #endif | 22 #endif |
23 | 23 |
24 #define BUSY_CYCLES_ADDRESS 17 | 24 #define BUSY_CYCLES 32 |
25 #define BUSY_CYCLES_DATA_LOW 83 | |
26 #define BUSY_CYCLES_DATA_HIGH 47 | |
27 #define OP_UPDATE_PERIOD 144 | 25 #define OP_UPDATE_PERIOD 144 |
28 | 26 |
29 #define BIT_TIMERA_ENABLE 0x1 | 27 #define BIT_TIMERA_ENABLE 0x1 |
30 #define BIT_TIMERB_ENABLE 0x2 | 28 #define BIT_TIMERB_ENABLE 0x2 |
31 #define BIT_TIMERA_OVEREN 0x4 | 29 #define BIT_TIMERA_OVEREN 0x4 |
118 } | 116 } |
119 | 117 |
120 void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock) | 118 void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock) |
121 { | 119 { |
122 render_audio_adjust_clock(context->audio, master_clock, context->clock_inc * NUM_OPERATORS); | 120 render_audio_adjust_clock(context->audio, master_clock, context->clock_inc * NUM_OPERATORS); |
121 } | |
122 | |
123 void ym_adjust_cycles(ym2612_context *context, uint32_t deduction) | |
124 { | |
125 context->current_cycle -= deduction; | |
126 if (context->write_cycle != CYCLE_NEVER && context->write_cycle >= deduction) { | |
127 context->write_cycle -= deduction; | |
128 } else { | |
129 context->write_cycle = CYCLE_NEVER; | |
130 } | |
131 if (context->busy_start != CYCLE_NEVER && context->busy_start >= deduction) { | |
132 context->busy_start -= deduction; | |
133 } else { | |
134 context->busy_start = CYCLE_NEVER; | |
135 } | |
136 if (context->last_status_cycle != CYCLE_NEVER && context->last_status_cycle >= deduction) { | |
137 context->last_status_cycle -= deduction; | |
138 } else { | |
139 context->last_status = 0; | |
140 context->last_status_cycle = CYCLE_NEVER; | |
141 } | |
123 } | 142 } |
124 | 143 |
125 #ifdef __ANDROID__ | 144 #ifdef __ANDROID__ |
126 #define log2(x) (log(x)/log(2)) | 145 #define log2(x) (log(x)/log(2)) |
127 #endif | 146 #endif |
171 { | 190 { |
172 static uint8_t registered_finalize; | 191 static uint8_t registered_finalize; |
173 dfopen(debug_file, "ym_debug.txt", "w"); | 192 dfopen(debug_file, "ym_debug.txt", "w"); |
174 memset(context, 0, sizeof(*context)); | 193 memset(context, 0, sizeof(*context)); |
175 context->clock_inc = clock_div * 6; | 194 context->clock_inc = clock_div * 6; |
195 context->busy_cycles = BUSY_CYCLES * context->clock_inc; | |
176 context->audio = render_audio_source(master_clock, context->clock_inc * NUM_OPERATORS, 2); | 196 context->audio = render_audio_source(master_clock, context->clock_inc * NUM_OPERATORS, 2); |
197 //TODO: pick a randomish high initial value and lower it over time | |
198 context->invalid_status_decay = 225000 * context->clock_inc; | |
199 context->status_address_mask = (options & YM_OPT_3834) ? 0 : 3; | |
177 | 200 |
178 //some games seem to expect that the LR flags start out as 1 | 201 //some games seem to expect that the LR flags start out as 1 |
179 for (int i = 0; i < NUM_CHANNELS; i++) { | 202 for (int i = 0; i < NUM_CHANNELS; i++) { |
180 if (options & YM_OPT_WAVE_LOG) { | 203 if (options & YM_OPT_WAVE_LOG) { |
181 char fname[64]; | 204 char fname[64]; |
336 keyoff(context->operators + op); | 359 keyoff(context->operators + op); |
337 } | 360 } |
338 } | 361 } |
339 } | 362 } |
340 | 363 |
364 void ym_run_timers(ym2612_context *context) | |
365 { | |
366 if (context->timer_control & BIT_TIMERA_ENABLE) { | |
367 if (context->timer_a != TIMER_A_MAX) { | |
368 context->timer_a++; | |
369 if (context->csm_keyon) { | |
370 csm_keyoff(context); | |
371 } | |
372 } else { | |
373 if (context->timer_control & BIT_TIMERA_LOAD) { | |
374 context->timer_control &= ~BIT_TIMERA_LOAD; | |
375 } else if (context->timer_control & BIT_TIMERA_OVEREN) { | |
376 context->status |= BIT_STATUS_TIMERA; | |
377 } | |
378 context->timer_a = context->timer_a_load; | |
379 if (!context->csm_keyon && context->ch3_mode == CSM_MODE) { | |
380 context->csm_keyon = 0xF0; | |
381 uint8_t changes = 0xF0 ^ context->channels[2].keyon;; | |
382 for (uint8_t op = 2*4, bit = 0; op < 3*4; op++, bit++) | |
383 { | |
384 if (changes & keyon_bits[bit]) { | |
385 keyon(context->operators + op, context->channels + 2); | |
386 } | |
387 } | |
388 } | |
389 } | |
390 } | |
391 if (!context->sub_timer_b) { | |
392 if (context->timer_control & BIT_TIMERB_ENABLE) { | |
393 if (context->timer_b != TIMER_B_MAX) { | |
394 context->timer_b++; | |
395 } else { | |
396 if (context->timer_control & BIT_TIMERB_LOAD) { | |
397 context->timer_control &= ~BIT_TIMERB_LOAD; | |
398 } else if (context->timer_control & BIT_TIMERB_OVEREN) { | |
399 context->status |= BIT_STATUS_TIMERB; | |
400 } | |
401 context->timer_b = context->timer_b_load; | |
402 } | |
403 } | |
404 } | |
405 context->sub_timer_b += 0x10; | |
406 //Update LFO | |
407 if (context->lfo_enable) { | |
408 if (context->lfo_counter) { | |
409 context->lfo_counter--; | |
410 } else { | |
411 context->lfo_counter = lfo_timer_values[context->lfo_freq]; | |
412 context->lfo_am_step += 2; | |
413 context->lfo_am_step &= 0xFE; | |
414 uint8_t old_pm_step = context->lfo_pm_step; | |
415 context->lfo_pm_step = context->lfo_am_step / 8; | |
416 if (context->lfo_pm_step != old_pm_step) { | |
417 for (int chan = 0; chan < NUM_CHANNELS; chan++) | |
418 { | |
419 if (context->channels[chan].pms) { | |
420 for (int op = chan * 4; op < (chan + 1) * 4; op++) | |
421 { | |
422 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); | |
423 } | |
424 } | |
425 } | |
426 } | |
427 } | |
428 } | |
429 } | |
430 | |
431 void ym_run_envelope(ym2612_context *context, ym_channel *channel, ym_operator *operator) | |
432 { | |
433 uint32_t env_cyc = context->env_counter; | |
434 uint8_t rate; | |
435 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) { | |
436 //operator->envelope = operator->sustain_level; | |
437 operator->env_phase = PHASE_SUSTAIN; | |
438 } | |
439 rate = operator->rates[operator->env_phase]; | |
440 if (rate) { | |
441 uint8_t ks = channel->keycode >> operator->key_scaling;; | |
442 rate = rate*2 + ks; | |
443 if (rate > 63) { | |
444 rate = 63; | |
445 } | |
446 } | |
447 uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0; | |
448 if (!(env_cyc & ((1 << cycle_shift) - 1))) { | |
449 uint32_t update_cycle = env_cyc >> cycle_shift & 0x7; | |
450 uint16_t envelope_inc = rate_table[rate * 8 + update_cycle]; | |
451 if (operator->env_phase == PHASE_ATTACK) { | |
452 //this can probably be optimized to a single shift rather than a multiply + shift | |
453 uint16_t old_env = operator->envelope; | |
454 operator->envelope += ((~operator->envelope * envelope_inc) >> 4) & 0xFFFFFFFC; | |
455 if (operator->envelope > old_env) { | |
456 //Handle overflow | |
457 operator->envelope = 0; | |
458 } | |
459 if (!operator->envelope) { | |
460 operator->env_phase = PHASE_DECAY; | |
461 } | |
462 } else { | |
463 if (operator->ssg) { | |
464 if (operator->envelope < SSG_CENTER) { | |
465 envelope_inc *= 4; | |
466 } else { | |
467 envelope_inc = 0; | |
468 } | |
469 } | |
470 //envelope value is 10-bits, but it will be used as a 4.8 value | |
471 operator->envelope += envelope_inc << 2; | |
472 //clamp to max attenuation value | |
473 if ( | |
474 operator->envelope > MAX_ENVELOPE | |
475 || (operator->env_phase == PHASE_RELEASE && operator->envelope >= SSG_CENTER) | |
476 ) { | |
477 operator->envelope = MAX_ENVELOPE; | |
478 } | |
479 } | |
480 } | |
481 } | |
482 | |
483 void ym_run_phase(ym2612_context *context, uint32_t channel, uint32_t op) | |
484 { | |
485 if (channel != 5 || !context->dac_enable) { | |
486 //printf("updating operator %d of channel %d\n", op, channel); | |
487 ym_operator * operator = context->operators + op; | |
488 ym_channel * chan = context->channels + channel; | |
489 uint16_t phase = operator->phase_counter >> 10 & 0x3FF; | |
490 operator->phase_counter += operator->phase_inc;//ym_calc_phase_inc(context, operator, op); | |
491 int16_t mod = 0; | |
492 if (op & 3) { | |
493 if (operator->mod_src[0]) { | |
494 mod = *operator->mod_src[0]; | |
495 if (operator->mod_src[1]) { | |
496 mod += *operator->mod_src[1]; | |
497 } | |
498 mod >>= YM_MOD_SHIFT; | |
499 } | |
500 } else { | |
501 if (chan->feedback) { | |
502 mod = (chan->op1_old + operator->output) >> (10-chan->feedback); | |
503 } | |
504 } | |
505 uint16_t env = operator->envelope; | |
506 if (operator->ssg) { | |
507 if (env >= SSG_CENTER) { | |
508 if (operator->ssg & SSG_ALTERNATE) { | |
509 if (operator->env_phase != PHASE_RELEASE && ( | |
510 !(operator->ssg & SSG_HOLD) || ((operator->ssg ^ operator->inverted) & SSG_INVERT) == 0 | |
511 )) { | |
512 operator->inverted ^= SSG_INVERT; | |
513 } | |
514 } else if (!(operator->ssg & SSG_HOLD)) { | |
515 phase = operator->phase_counter = 0; | |
516 } | |
517 if ( | |
518 (operator->env_phase == PHASE_DECAY || operator->env_phase == PHASE_SUSTAIN) | |
519 && !(operator->ssg & SSG_HOLD) | |
520 ) { | |
521 start_envelope(operator, chan); | |
522 env = operator->envelope; | |
523 } | |
524 } | |
525 if (operator->inverted) { | |
526 env = (SSG_CENTER - env) & MAX_ENVELOPE; | |
527 } | |
528 } | |
529 env += operator->total_level; | |
530 if (operator->am) { | |
531 uint16_t base_am = (context->lfo_am_step & 0x80 ? context->lfo_am_step : ~context->lfo_am_step) & 0x7E; | |
532 if (ams_shift[chan->ams] >= 0) { | |
533 env += (base_am >> ams_shift[chan->ams]) & MAX_ENVELOPE; | |
534 } else { | |
535 env += base_am << (-ams_shift[chan->ams]); | |
536 } | |
537 } | |
538 if (env > MAX_ENVELOPE) { | |
539 env = MAX_ENVELOPE; | |
540 } | |
541 if (first_key_on) { | |
542 dfprintf(debug_file, "op %d, base phase: %d, mod: %d, sine: %d, out: %d\n", op, phase, mod, sine_table[(phase+mod) & 0x1FF], pow_table[sine_table[phase & 0x1FF] + env]); | |
543 } | |
544 //if ((channel != 0 && channel != 4) || chan->algorithm != 5) { | |
545 phase += mod; | |
546 //} | |
547 | |
548 int16_t output = pow_table[sine_table[phase & 0x1FF] + env]; | |
549 if (phase & 0x200) { | |
550 output = -output; | |
551 } | |
552 if (op % 4 == 0) { | |
553 chan->op1_old = operator->output; | |
554 } else if (op % 4 == 2) { | |
555 chan->op2_old = operator->output; | |
556 } | |
557 operator->output = output; | |
558 //Update the channel output if we've updated all operators | |
559 if (op % 4 == 3) { | |
560 if (chan->algorithm < 4) { | |
561 chan->output = operator->output; | |
562 } else if(chan->algorithm == 4) { | |
563 chan->output = operator->output + context->operators[channel * 4 + 2].output; | |
564 } else { | |
565 output = 0; | |
566 for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) { | |
567 output += context->operators[op].output; | |
568 } | |
569 chan->output = output; | |
570 } | |
571 if (first_key_on) { | |
572 int16_t value = context->channels[channel].output & 0x3FE0; | |
573 if (value & 0x2000) { | |
574 value |= 0xC000; | |
575 } | |
576 } | |
577 } | |
578 //puts("operator update done"); | |
579 } | |
580 } | |
581 | |
582 void ym_output_sample(ym2612_context *context) | |
583 { | |
584 int16_t left = 0, right = 0; | |
585 for (int i = 0; i < NUM_CHANNELS; i++) { | |
586 int16_t value = context->channels[i].output; | |
587 if (value > 0x1FE0) { | |
588 value = 0x1FE0; | |
589 } else if (value < -0x1FF0) { | |
590 value = -0x1FF0; | |
591 } else { | |
592 value &= 0x3FE0; | |
593 if (value & 0x2000) { | |
594 value |= 0xC000; | |
595 } | |
596 } | |
597 if (value >= 0) { | |
598 value += context->zero_offset; | |
599 } else { | |
600 value -= context->zero_offset; | |
601 } | |
602 if (context->channels[i].logfile) { | |
603 fwrite(&value, sizeof(value), 1, context->channels[i].logfile); | |
604 } | |
605 if (context->channels[i].lr & 0x80) { | |
606 left += (value * context->volume_mult) / context->volume_div; | |
607 } else if (context->zero_offset) { | |
608 if (value >= 0) { | |
609 left += (context->zero_offset * context->volume_mult) / context->volume_div; | |
610 } else { | |
611 left -= (context->zero_offset * context->volume_mult) / context->volume_div; | |
612 } | |
613 } | |
614 if (context->channels[i].lr & 0x40) { | |
615 right += (value * context->volume_mult) / context->volume_div; | |
616 } else if (context->zero_offset) { | |
617 if (value >= 0) { | |
618 right += (context->zero_offset * context->volume_mult) / context->volume_div; | |
619 } else { | |
620 right -= (context->zero_offset * context->volume_mult) / context->volume_div; | |
621 } | |
622 } | |
623 } | |
624 render_put_stereo_sample(context->audio, left, right); | |
625 } | |
626 | |
341 void ym_run(ym2612_context * context, uint32_t to_cycle) | 627 void ym_run(ym2612_context * context, uint32_t to_cycle) |
342 { | 628 { |
629 if (context->current_cycle >= to_cycle) { | |
630 return; | |
631 } | |
343 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle); | 632 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle); |
344 //TODO: Fix channel update order OR remap channels in register write | 633 //TODO: Fix channel update order OR remap channels in register write |
345 for (; context->current_cycle < to_cycle; context->current_cycle += context->clock_inc) { | 634 for (; context->current_cycle < to_cycle; context->current_cycle += context->clock_inc) { |
346 //Update timers at beginning of 144 cycle period | 635 //Update timers at beginning of 144 cycle period |
347 if (!context->current_op) { | 636 if (!context->current_op) { |
348 if (context->timer_control & BIT_TIMERA_ENABLE) { | 637 ym_run_timers(context); |
349 if (context->timer_a != TIMER_A_MAX) { | |
350 context->timer_a++; | |
351 if (context->csm_keyon) { | |
352 csm_keyoff(context); | |
353 } | |
354 } else { | |
355 if (context->timer_control & BIT_TIMERA_LOAD) { | |
356 context->timer_control &= ~BIT_TIMERA_LOAD; | |
357 } else if (context->timer_control & BIT_TIMERA_OVEREN) { | |
358 context->status |= BIT_STATUS_TIMERA; | |
359 } | |
360 context->timer_a = context->timer_a_load; | |
361 if (!context->csm_keyon && context->ch3_mode == CSM_MODE) { | |
362 context->csm_keyon = 0xF0; | |
363 uint8_t changes = 0xF0 ^ context->channels[2].keyon;; | |
364 for (uint8_t op = 2*4, bit = 0; op < 3*4; op++, bit++) | |
365 { | |
366 if (changes & keyon_bits[bit]) { | |
367 keyon(context->operators + op, context->channels + 2); | |
368 } | |
369 } | |
370 } | |
371 } | |
372 } | |
373 if (!context->sub_timer_b) { | |
374 if (context->timer_control & BIT_TIMERB_ENABLE) { | |
375 if (context->timer_b != TIMER_B_MAX) { | |
376 context->timer_b++; | |
377 } else { | |
378 if (context->timer_control & BIT_TIMERB_LOAD) { | |
379 context->timer_control &= ~BIT_TIMERB_LOAD; | |
380 } else if (context->timer_control & BIT_TIMERB_OVEREN) { | |
381 context->status |= BIT_STATUS_TIMERB; | |
382 } | |
383 context->timer_b = context->timer_b_load; | |
384 } | |
385 } | |
386 } | |
387 context->sub_timer_b += 0x10; | |
388 //Update LFO | |
389 if (context->lfo_enable) { | |
390 if (context->lfo_counter) { | |
391 context->lfo_counter--; | |
392 } else { | |
393 context->lfo_counter = lfo_timer_values[context->lfo_freq]; | |
394 context->lfo_am_step += 2; | |
395 context->lfo_am_step &= 0xFE; | |
396 context->lfo_pm_step = context->lfo_am_step / 8; | |
397 } | |
398 } | |
399 } | 638 } |
400 //Update Envelope Generator | 639 //Update Envelope Generator |
401 if (!(context->current_op % 3)) { | 640 if (!(context->current_op % 3)) { |
402 uint32_t env_cyc = context->env_counter; | |
403 uint32_t op = context->current_env_op; | 641 uint32_t op = context->current_env_op; |
404 ym_operator * operator = context->operators + op; | 642 ym_operator * operator = context->operators + op; |
405 ym_channel * channel = context->channels + op/4; | 643 ym_channel * channel = context->channels + op/4; |
406 uint8_t rate; | 644 ym_run_envelope(context, channel, operator); |
407 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) { | |
408 //operator->envelope = operator->sustain_level; | |
409 operator->env_phase = PHASE_SUSTAIN; | |
410 } | |
411 rate = operator->rates[operator->env_phase]; | |
412 if (rate) { | |
413 uint8_t ks = channel->keycode >> operator->key_scaling;; | |
414 rate = rate*2 + ks; | |
415 if (rate > 63) { | |
416 rate = 63; | |
417 } | |
418 } | |
419 uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0; | |
420 if (first_key_on) { | |
421 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)); | |
422 } | |
423 if (!(env_cyc & ((1 << cycle_shift) - 1))) { | |
424 uint32_t update_cycle = env_cyc >> cycle_shift & 0x7; | |
425 uint16_t envelope_inc = rate_table[rate * 8 + update_cycle]; | |
426 if (operator->env_phase == PHASE_ATTACK) { | |
427 //this can probably be optimized to a single shift rather than a multiply + shift | |
428 if (first_key_on) { | |
429 dfprintf(debug_file, "Changing op %d envelope %d by %d(%d * %d) in attack phase\n", op, operator->envelope, (~operator->envelope * envelope_inc) >> 4, ~operator->envelope, envelope_inc); | |
430 } | |
431 uint16_t old_env = operator->envelope; | |
432 operator->envelope += ((~operator->envelope * envelope_inc) >> 4) & 0xFFFFFFFC; | |
433 if (operator->envelope > old_env) { | |
434 //Handle overflow | |
435 operator->envelope = 0; | |
436 } | |
437 if (!operator->envelope) { | |
438 operator->env_phase = PHASE_DECAY; | |
439 } | |
440 } else { | |
441 if (first_key_on) { | |
442 dfprintf(debug_file, "Changing op %d envelope %d by %d in %s phase\n", op, operator->envelope, envelope_inc, | |
443 operator->env_phase == PHASE_SUSTAIN ? "sustain" : (operator->env_phase == PHASE_DECAY ? "decay": "release")); | |
444 } | |
445 if (operator->ssg) { | |
446 if (operator->envelope < SSG_CENTER) { | |
447 envelope_inc *= 4; | |
448 } else { | |
449 envelope_inc = 0; | |
450 } | |
451 } | |
452 //envelope value is 10-bits, but it will be used as a 4.8 value | |
453 operator->envelope += envelope_inc << 2; | |
454 //clamp to max attenuation value | |
455 if ( | |
456 operator->envelope > MAX_ENVELOPE | |
457 || (operator->env_phase == PHASE_RELEASE && operator->envelope >= SSG_CENTER) | |
458 ) { | |
459 operator->envelope = MAX_ENVELOPE; | |
460 } | |
461 } | |
462 } | |
463 context->current_env_op++; | 645 context->current_env_op++; |
464 if (context->current_env_op == NUM_OPERATORS) { | 646 if (context->current_env_op == NUM_OPERATORS) { |
465 context->current_env_op = 0; | 647 context->current_env_op = 0; |
466 context->env_counter++; | 648 context->env_counter++; |
467 } | 649 } |
468 } | 650 } |
469 | 651 |
470 //Update Phase Generator | 652 //Update Phase Generator |
471 uint32_t channel = context->current_op / 4; | 653 ym_run_phase(context, context->current_op / 4, context->current_op); |
472 if (channel != 5 || !context->dac_enable) { | |
473 uint32_t op = context->current_op; | |
474 //printf("updating operator %d of channel %d\n", op, channel); | |
475 ym_operator * operator = context->operators + op; | |
476 ym_channel * chan = context->channels + channel; | |
477 uint16_t phase = operator->phase_counter >> 10 & 0x3FF; | |
478 operator->phase_counter += ym_calc_phase_inc(context, operator, context->current_op); | |
479 int16_t mod = 0; | |
480 if (op & 3) { | |
481 if (operator->mod_src[0]) { | |
482 mod = *operator->mod_src[0]; | |
483 if (operator->mod_src[1]) { | |
484 mod += *operator->mod_src[1]; | |
485 } | |
486 mod >>= YM_MOD_SHIFT; | |
487 } | |
488 } else { | |
489 if (chan->feedback) { | |
490 mod = (chan->op1_old + operator->output) >> (10-chan->feedback); | |
491 } | |
492 } | |
493 uint16_t env = operator->envelope; | |
494 if (operator->ssg) { | |
495 if (env >= SSG_CENTER) { | |
496 if (operator->ssg & SSG_ALTERNATE) { | |
497 if (operator->env_phase != PHASE_RELEASE && ( | |
498 !(operator->ssg & SSG_HOLD) || ((operator->ssg ^ operator->inverted) & SSG_INVERT) == 0 | |
499 )) { | |
500 operator->inverted ^= SSG_INVERT; | |
501 } | |
502 } else if (!(operator->ssg & SSG_HOLD)) { | |
503 phase = operator->phase_counter = 0; | |
504 } | |
505 if ( | |
506 (operator->env_phase == PHASE_DECAY || operator->env_phase == PHASE_SUSTAIN) | |
507 && !(operator->ssg & SSG_HOLD) | |
508 ) { | |
509 start_envelope(operator, chan); | |
510 env = operator->envelope; | |
511 } | |
512 } | |
513 if (operator->inverted) { | |
514 env = (SSG_CENTER - env) & MAX_ENVELOPE; | |
515 } | |
516 } | |
517 env += operator->total_level; | |
518 if (operator->am) { | |
519 uint16_t base_am = (context->lfo_am_step & 0x80 ? context->lfo_am_step : ~context->lfo_am_step) & 0x7E; | |
520 if (ams_shift[chan->ams] >= 0) { | |
521 env += (base_am >> ams_shift[chan->ams]) & MAX_ENVELOPE; | |
522 } else { | |
523 env += base_am << (-ams_shift[chan->ams]); | |
524 } | |
525 } | |
526 if (env > MAX_ENVELOPE) { | |
527 env = MAX_ENVELOPE; | |
528 } | |
529 if (first_key_on) { | |
530 dfprintf(debug_file, "op %d, base phase: %d, mod: %d, sine: %d, out: %d\n", op, phase, mod, sine_table[(phase+mod) & 0x1FF], pow_table[sine_table[phase & 0x1FF] + env]); | |
531 } | |
532 //if ((channel != 0 && channel != 4) || chan->algorithm != 5) { | |
533 phase += mod; | |
534 //} | |
535 | |
536 int16_t output = pow_table[sine_table[phase & 0x1FF] + env]; | |
537 if (phase & 0x200) { | |
538 output = -output; | |
539 } | |
540 if (op % 4 == 0) { | |
541 chan->op1_old = operator->output; | |
542 } else if (op % 4 == 2) { | |
543 chan->op2_old = operator->output; | |
544 } | |
545 operator->output = output; | |
546 //Update the channel output if we've updated all operators | |
547 if (op % 4 == 3) { | |
548 if (chan->algorithm < 4) { | |
549 chan->output = operator->output; | |
550 } else if(chan->algorithm == 4) { | |
551 chan->output = operator->output + context->operators[channel * 4 + 2].output; | |
552 } else { | |
553 output = 0; | |
554 for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) { | |
555 output += context->operators[op].output; | |
556 } | |
557 chan->output = output; | |
558 } | |
559 if (first_key_on) { | |
560 int16_t value = context->channels[channel].output & 0x3FE0; | |
561 if (value & 0x2000) { | |
562 value |= 0xC000; | |
563 } | |
564 dfprintf(debug_file, "channel %d output: %d\n", channel, (value * context->volume_mult) / context->volume_div); | |
565 } | |
566 } | |
567 //puts("operator update done"); | |
568 } | |
569 context->current_op++; | 654 context->current_op++; |
570 if (context->current_op == NUM_OPERATORS) { | 655 if (context->current_op == NUM_OPERATORS) { |
571 context->current_op = 0; | 656 context->current_op = 0; |
572 | 657 ym_output_sample(context); |
573 int16_t left = 0, right = 0; | |
574 for (int i = 0; i < NUM_CHANNELS; i++) { | |
575 int16_t value = context->channels[i].output; | |
576 if (value > 0x1FE0) { | |
577 value = 0x1FE0; | |
578 } else if (value < -0x1FF0) { | |
579 value = -0x1FF0; | |
580 } else { | |
581 value &= 0x3FE0; | |
582 if (value & 0x2000) { | |
583 value |= 0xC000; | |
584 } | |
585 } | |
586 if (value >= 0) { | |
587 value += context->zero_offset; | |
588 } else { | |
589 value -= context->zero_offset; | |
590 } | |
591 if (context->channels[i].logfile) { | |
592 fwrite(&value, sizeof(value), 1, context->channels[i].logfile); | |
593 } | |
594 if (context->channels[i].lr & 0x80) { | |
595 left += (value * context->volume_mult) / context->volume_div; | |
596 } else if (context->zero_offset) { | |
597 if (value >= 0) { | |
598 left += (context->zero_offset * context->volume_mult) / context->volume_div; | |
599 } else { | |
600 left -= (context->zero_offset * context->volume_mult) / context->volume_div; | |
601 } | |
602 } | |
603 if (context->channels[i].lr & 0x40) { | |
604 right += (value * context->volume_mult) / context->volume_div; | |
605 } else if (context->zero_offset) { | |
606 if (value >= 0) { | |
607 right += (context->zero_offset * context->volume_mult) / context->volume_div; | |
608 } else { | |
609 right -= (context->zero_offset * context->volume_mult) / context->volume_div; | |
610 } | |
611 } | |
612 } | |
613 render_put_stereo_sample(context->audio, left, right); | |
614 } | 658 } |
615 | 659 |
616 } | |
617 if (context->current_cycle >= context->write_cycle + (context->busy_cycles * context->clock_inc / 6)) { | |
618 context->status &= 0x7F; | |
619 context->write_cycle = CYCLE_NEVER; | |
620 } | 660 } |
621 //printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle); | 661 //printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle); |
622 } | 662 } |
623 | 663 |
624 void ym_address_write_part1(ym2612_context * context, uint8_t address) | 664 void ym_address_write_part1(ym2612_context * context, uint8_t address) |
625 { | 665 { |
626 //printf("address_write_part1: %X\n", address); | 666 //printf("address_write_part1: %X\n", address); |
627 context->selected_reg = address; | 667 context->selected_reg = address; |
628 context->selected_part = 0; | 668 context->selected_part = 0; |
629 context->write_cycle = context->current_cycle; | |
630 context->busy_cycles = BUSY_CYCLES_ADDRESS; | |
631 context->status |= 0x80; | |
632 } | 669 } |
633 | 670 |
634 void ym_address_write_part2(ym2612_context * context, uint8_t address) | 671 void ym_address_write_part2(ym2612_context * context, uint8_t address) |
635 { | 672 { |
636 //printf("address_write_part2: %X\n", address); | 673 //printf("address_write_part2: %X\n", address); |
637 context->selected_reg = address; | 674 context->selected_reg = address; |
638 context->selected_part = 1; | 675 context->selected_part = 1; |
639 context->write_cycle = context->current_cycle; | |
640 context->busy_cycles = BUSY_CYCLES_ADDRESS; | |
641 context->status |= 0x80; | |
642 } | 676 } |
643 | 677 |
644 static uint8_t fnum_to_keycode[] = { | 678 static uint8_t fnum_to_keycode[] = { |
645 //F11 = 0 | 679 //F11 = 0 |
646 0,0,0,0,0,0,0,1, | 680 0,0,0,0,0,0,0,1, |
743 } | 777 } |
744 //printf("phase_inc for operator %d: %d, block: %d, fnum: %d, detune: %d, multiple: %d\n", op, inc, channel->block, channel->fnum, detune, operator->multiple); | 778 //printf("phase_inc for operator %d: %d, block: %d, fnum: %d, detune: %d, multiple: %d\n", op, inc, channel->block, channel->fnum, detune, operator->multiple); |
745 return inc; | 779 return inc; |
746 } | 780 } |
747 | 781 |
782 void ym_vgm_log(ym2612_context *context, uint32_t master_clock, vgm_writer *vgm) | |
783 { | |
784 vgm_ym2612_init(vgm, 6 * master_clock / context->clock_inc); | |
785 context->vgm = vgm; | |
786 for (uint8_t reg = YM_PART1_START; reg < YM_REG_END; reg++) { | |
787 if ((reg >= REG_DETUNE_MULT && (reg & 3) == 3) || (reg >= 0x2D && reg < REG_DETUNE_MULT) || reg == 0x23 || reg == 0x29) { | |
788 //skip invalid registers | |
789 continue; | |
790 } | |
791 vgm_ym2612_part1_write(context->vgm, context->current_cycle, reg, context->part1_regs[reg - YM_PART1_START]); | |
792 } | |
793 | |
794 for (uint8_t reg = YM_PART2_START; reg < YM_REG_END; reg++) { | |
795 if ((reg & 3) == 3 || (reg >= REG_FNUM_LOW_CH3 && reg < REG_ALG_FEEDBACK)) { | |
796 //skip invalid registers | |
797 continue; | |
798 } | |
799 vgm_ym2612_part2_write(context->vgm, context->current_cycle, reg, context->part2_regs[reg - YM_PART2_START]); | |
800 } | |
801 } | |
802 | |
748 void ym_data_write(ym2612_context * context, uint8_t value) | 803 void ym_data_write(ym2612_context * context, uint8_t value) |
749 { | 804 { |
805 context->write_cycle = context->current_cycle; | |
806 context->busy_start = context->current_cycle + context->clock_inc; | |
807 | |
750 if (context->selected_reg >= YM_REG_END) { | 808 if (context->selected_reg >= YM_REG_END) { |
751 return; | 809 return; |
752 } | 810 } |
753 if (context->selected_part) { | 811 if (context->selected_part) { |
754 if (context->selected_reg < YM_PART2_START) { | 812 if (context->selected_reg < YM_PART2_START) { |
755 return; | 813 return; |
814 } | |
815 if (context->vgm) { | |
816 vgm_ym2612_part2_write(context->vgm, context->current_cycle, context->selected_reg, value); | |
756 } | 817 } |
757 context->part2_regs[context->selected_reg - YM_PART2_START] = value; | 818 context->part2_regs[context->selected_reg - YM_PART2_START] = value; |
758 } else { | 819 } else { |
759 if (context->selected_reg < YM_PART1_START) { | 820 if (context->selected_reg < YM_PART1_START) { |
760 return; | 821 return; |
822 } | |
823 if (context->vgm) { | |
824 vgm_ym2612_part1_write(context->vgm, context->current_cycle, context->selected_reg, value); | |
761 } | 825 } |
762 context->part1_regs[context->selected_reg - YM_PART1_START] = value; | 826 context->part1_regs[context->selected_reg - YM_PART1_START] = value; |
763 } | 827 } |
764 dfprintf(debug_file, "write of %X to reg %X in part %d\n", value, context->selected_reg, context->selected_part+1); | 828 dfprintf(debug_file, "write of %X to reg %X in part %d\n", value, context->selected_reg, context->selected_part+1); |
765 if (context->selected_reg < 0x30) { | 829 if (context->selected_reg < 0x30) { |
771 /*if ((value & 0x8) && !context->lfo_enable) { | 835 /*if ((value & 0x8) && !context->lfo_enable) { |
772 printf("LFO Enabled, Freq: %d\n", value & 0x7); | 836 printf("LFO Enabled, Freq: %d\n", value & 0x7); |
773 }*/ | 837 }*/ |
774 context->lfo_enable = value & 0x8; | 838 context->lfo_enable = value & 0x8; |
775 if (!context->lfo_enable) { | 839 if (!context->lfo_enable) { |
840 uint8_t old_pm_step = context->lfo_pm_step; | |
776 context->lfo_am_step = context->lfo_pm_step = 0; | 841 context->lfo_am_step = context->lfo_pm_step = 0; |
842 if (old_pm_step) { | |
843 for (int chan = 0; chan < NUM_CHANNELS; chan++) | |
844 { | |
845 if (context->channels[chan].pms) { | |
846 for (int op = chan * 4; op < (chan + 1) * 4; op++) | |
847 { | |
848 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); | |
849 } | |
850 } | |
851 } | |
852 } | |
777 } | 853 } |
778 context->lfo_freq = value & 0x7; | 854 context->lfo_freq = value & 0x7; |
779 | 855 |
780 break; | 856 break; |
781 case REG_TIMERA_HIGH: | 857 case REG_TIMERA_HIGH: |
807 context->status &= ~BIT_STATUS_TIMERB; | 883 context->status &= ~BIT_STATUS_TIMERB; |
808 } | 884 } |
809 if (context->ch3_mode == CSM_MODE && (value & 0xC0) != CSM_MODE && context->csm_keyon) { | 885 if (context->ch3_mode == CSM_MODE && (value & 0xC0) != CSM_MODE && context->csm_keyon) { |
810 csm_keyoff(context); | 886 csm_keyoff(context); |
811 } | 887 } |
888 uint8_t old_mode = context->ch3_mode; | |
812 context->ch3_mode = value & 0xC0; | 889 context->ch3_mode = value & 0xC0; |
890 if (context->ch3_mode != old_mode) { | |
891 for (int op = 2 * 4; op < 3*4; op++) | |
892 { | |
893 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); | |
894 } | |
895 } | |
813 break; | 896 break; |
814 } | 897 } |
815 case REG_KEY_ONOFF: { | 898 case REG_KEY_ONOFF: { |
816 uint8_t channel = value & 0x7; | 899 uint8_t channel = value & 0x7; |
817 if (channel != 3 && channel != 7) { | 900 if (channel != 3 && channel != 7) { |
859 switch (context->selected_reg & 0xF0) | 942 switch (context->selected_reg & 0xF0) |
860 { | 943 { |
861 case REG_DETUNE_MULT: | 944 case REG_DETUNE_MULT: |
862 operator->detune = value >> 4 & 0x7; | 945 operator->detune = value >> 4 & 0x7; |
863 operator->multiple = value & 0xF; | 946 operator->multiple = value & 0xF; |
947 operator->phase_inc = ym_calc_phase_inc(context, operator, op); | |
864 break; | 948 break; |
865 case REG_TOTAL_LEVEL: | 949 case REG_TOTAL_LEVEL: |
866 operator->total_level = (value & 0x7F) << 5; | 950 operator->total_level = (value & 0x7F) << 5; |
867 break; | 951 break; |
868 case REG_ATTACK_KS: | 952 case REG_ATTACK_KS: |
905 { | 989 { |
906 case REG_FNUM_LOW: | 990 case REG_FNUM_LOW: |
907 context->channels[channel].block = context->channels[channel].block_fnum_latch >> 3 & 0x7; | 991 context->channels[channel].block = context->channels[channel].block_fnum_latch >> 3 & 0x7; |
908 context->channels[channel].fnum = (context->channels[channel].block_fnum_latch & 0x7) << 8 | value; | 992 context->channels[channel].fnum = (context->channels[channel].block_fnum_latch & 0x7) << 8 | value; |
909 context->channels[channel].keycode = context->channels[channel].block << 2 | fnum_to_keycode[context->channels[channel].fnum >> 7]; | 993 context->channels[channel].keycode = context->channels[channel].block << 2 | fnum_to_keycode[context->channels[channel].fnum >> 7]; |
994 for (int op = channel * 4; op < (channel + 1) * 4; op++) | |
995 { | |
996 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); | |
997 } | |
910 break; | 998 break; |
911 case REG_BLOCK_FNUM_H:{ | 999 case REG_BLOCK_FNUM_H:{ |
912 context->channels[channel].block_fnum_latch = value; | 1000 context->channels[channel].block_fnum_latch = value; |
913 break; | 1001 break; |
914 } | 1002 } |
915 case REG_FNUM_LOW_CH3: | 1003 case REG_FNUM_LOW_CH3: |
916 if (channel < 3) { | 1004 if (channel < 3) { |
917 context->ch3_supp[channel].block = context->ch3_supp[channel].block_fnum_latch >> 3 & 0x7; | 1005 context->ch3_supp[channel].block = context->ch3_supp[channel].block_fnum_latch >> 3 & 0x7; |
918 context->ch3_supp[channel].fnum = (context->ch3_supp[channel].block_fnum_latch & 0x7) << 8 | value; | 1006 context->ch3_supp[channel].fnum = (context->ch3_supp[channel].block_fnum_latch & 0x7) << 8 | value; |
919 context->ch3_supp[channel].keycode = context->ch3_supp[channel].block << 2 | fnum_to_keycode[context->ch3_supp[channel].fnum >> 7]; | 1007 context->ch3_supp[channel].keycode = context->ch3_supp[channel].block << 2 | fnum_to_keycode[context->ch3_supp[channel].fnum >> 7]; |
1008 if (context->ch3_mode) { | |
1009 int op = 2 * 4 + (channel < 2 ? (channel ^ 1) : channel); | |
1010 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); | |
1011 } | |
920 } | 1012 } |
921 break; | 1013 break; |
922 case REG_BLOCK_FN_CH3: | 1014 case REG_BLOCK_FN_CH3: |
923 if (channel < 3) { | 1015 if (channel < 3) { |
924 context->ch3_supp[channel].block_fnum_latch = value; | 1016 context->ch3_supp[channel].block_fnum_latch = value; |
1040 break; | 1132 break; |
1041 } | 1133 } |
1042 context->channels[channel].feedback = value >> 3 & 0x7; | 1134 context->channels[channel].feedback = value >> 3 & 0x7; |
1043 //printf("Algorithm %d, feedback %d for channel %d\n", value & 0x7, value >> 3 & 0x7, channel); | 1135 //printf("Algorithm %d, feedback %d for channel %d\n", value & 0x7, value >> 3 & 0x7, channel); |
1044 break; | 1136 break; |
1045 case REG_LR_AMS_PMS: | 1137 case REG_LR_AMS_PMS: { |
1138 uint8_t old_pms = context->channels[channel].pms; | |
1046 context->channels[channel].pms = (value & 0x7) * 32; | 1139 context->channels[channel].pms = (value & 0x7) * 32; |
1047 context->channels[channel].ams = value >> 4 & 0x3; | 1140 context->channels[channel].ams = value >> 4 & 0x3; |
1048 context->channels[channel].lr = value & 0xC0; | 1141 context->channels[channel].lr = value & 0xC0; |
1142 if (old_pms != context->channels[channel].pms) { | |
1143 for (int op = channel * 4; op < (channel + 1) * 4; op++) | |
1144 { | |
1145 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); | |
1146 } | |
1147 } | |
1049 //printf("Write of %X to LR_AMS_PMS reg for channel %d\n", value, channel); | 1148 //printf("Write of %X to LR_AMS_PMS reg for channel %d\n", value, channel); |
1050 break; | 1149 break; |
1051 } | 1150 } |
1052 } | 1151 } |
1053 } | 1152 } |
1054 | 1153 } |
1055 context->write_cycle = context->current_cycle; | 1154 } |
1056 context->busy_cycles = context->selected_reg < 0xA0 ? BUSY_CYCLES_DATA_LOW : BUSY_CYCLES_DATA_HIGH; | 1155 |
1057 context->status |= 0x80; | 1156 uint8_t ym_read_status(ym2612_context * context, uint32_t cycle, uint32_t port) |
1058 } | 1157 { |
1059 | 1158 uint8_t status; |
1060 uint8_t ym_read_status(ym2612_context * context) | 1159 port &= context->status_address_mask; |
1061 { | 1160 if (port) { |
1062 return context->status; | 1161 if (context->last_status_cycle != CYCLE_NEVER && cycle - context->last_status_cycle > context->invalid_status_decay) { |
1162 context->last_status = 0; | |
1163 } | |
1164 status = context->last_status; | |
1165 } else { | |
1166 status = context->status; | |
1167 if (cycle >= context->busy_start && cycle < context->busy_start + context->busy_cycles) { | |
1168 status |= 0x80; | |
1169 } | |
1170 context->last_status = status; | |
1171 context->last_status_cycle = cycle; | |
1172 } | |
1173 return status; | |
1174 | |
1063 } | 1175 } |
1064 | 1176 |
1065 void ym_print_channel_info(ym2612_context *context, int channel) | 1177 void ym_print_channel_info(ym2612_context *context, int channel) |
1066 { | 1178 { |
1067 ym_channel *chan = context->channels + channel; | 1179 ym_channel *chan = context->channels + channel; |
1169 save_int8(buf, context->status); | 1281 save_int8(buf, context->status); |
1170 save_int8(buf, context->selected_reg); | 1282 save_int8(buf, context->selected_reg); |
1171 save_int8(buf, context->selected_part); | 1283 save_int8(buf, context->selected_part); |
1172 save_int32(buf, context->current_cycle); | 1284 save_int32(buf, context->current_cycle); |
1173 save_int32(buf, context->write_cycle); | 1285 save_int32(buf, context->write_cycle); |
1174 save_int32(buf, context->busy_cycles); | 1286 save_int32(buf, context->busy_start); |
1287 save_int32(buf, context->last_status_cycle); | |
1288 save_int32(buf, context->invalid_status_decay); | |
1289 save_int8(buf, context->last_status); | |
1175 } | 1290 } |
1176 | 1291 |
1177 void ym_deserialize(deserialize_buffer *buf, void *vcontext) | 1292 void ym_deserialize(deserialize_buffer *buf, void *vcontext) |
1178 { | 1293 { |
1179 ym2612_context *context = vcontext; | 1294 ym2612_context *context = vcontext; |
1244 context->status = load_int8(buf); | 1359 context->status = load_int8(buf); |
1245 context->selected_reg = load_int8(buf); | 1360 context->selected_reg = load_int8(buf); |
1246 context->selected_part = load_int8(buf); | 1361 context->selected_part = load_int8(buf); |
1247 context->current_cycle = load_int32(buf); | 1362 context->current_cycle = load_int32(buf); |
1248 context->write_cycle = load_int32(buf); | 1363 context->write_cycle = load_int32(buf); |
1249 context->busy_cycles = load_int32(buf); | 1364 context->busy_start = load_int32(buf); |
1250 } | 1365 if (buf->size > buf->cur_pos) { |
1366 context->last_status_cycle = load_int32(buf); | |
1367 context->invalid_status_decay = load_int32(buf); | |
1368 context->last_status = load_int8(buf); | |
1369 } else { | |
1370 context->last_status = context->status; | |
1371 context->last_status_cycle = context->write_cycle; | |
1372 } | |
1373 } |