Mercurial > repos > blastem
comparison ym2612.c @ 803:236a184bf6f0
Merge
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 26 Jul 2015 16:51:03 -0700 |
parents | 25c9e9d39997 |
children | 3a18b5f63afc |
comparison
equal
deleted
inserted
replaced
802:6811f601008f | 803:236a184bf6f0 |
---|---|
105 {0, 0, 8, 0xc,0x10,0x10,0x14,0x18}, | 105 {0, 0, 8, 0xc,0x10,0x10,0x14,0x18}, |
106 {0, 0,0x10,0x18,0x20,0x20,0x28,0x30}, | 106 {0, 0,0x10,0x18,0x20,0x20,0x28,0x30}, |
107 {0, 0,0x20,0x30,0x40,0x40,0x50,0x60} | 107 {0, 0,0x20,0x30,0x40,0x40,0x50,0x60} |
108 }; | 108 }; |
109 int16_t lfo_pm_table[128 * 32 * 8]; | 109 int16_t lfo_pm_table[128 * 32 * 8]; |
110 | |
111 uint16_t ams_shift[] = {8, 3, 1, 0}; | |
110 | 112 |
111 #define MAX_ENVELOPE 0xFFC | 113 #define MAX_ENVELOPE 0xFFC |
112 #define YM_DIVIDER 2 | 114 #define YM_DIVIDER 2 |
113 #define CYCLE_NEVER 0xFFFFFFFF | 115 #define CYCLE_NEVER 0xFFFFFFFF |
114 | 116 |
266 context->status |= BIT_STATUS_TIMERB; | 268 context->status |= BIT_STATUS_TIMERB; |
267 } | 269 } |
268 context->timer_b = context->timer_b_load; | 270 context->timer_b = context->timer_b_load; |
269 } | 271 } |
270 } | 272 } |
271 } | 273 //Update LFO |
272 //Update LFO | 274 if (context->lfo_enable) { |
273 if (context->lfo_enable) { | 275 if (context->lfo_counter) { |
274 if (context->lfo_counter) { | 276 context->lfo_counter--; |
275 context->lfo_counter--; | 277 } else { |
276 } else { | 278 context->lfo_counter = lfo_timer_values[context->lfo_freq]; |
277 context->lfo_counter = lfo_timer_values[context->lfo_freq]; | 279 context->lfo_am_step += 2; |
278 context->lfo_am_step += 2; | 280 context->lfo_am_step &= 0xFE; |
279 context->lfo_am_step &= 0xFE; | 281 context->lfo_pm_step = context->lfo_am_step / 8; |
280 context->lfo_pm_step = context->lfo_am_step / 8; | 282 } |
281 } | 283 } |
282 } | 284 } |
283 //Update Envelope Generator | 285 //Update Envelope Generator |
284 if (!(context->current_op % 3)) { | 286 if (!(context->current_op % 3)) { |
285 uint32_t env_cyc = context->env_counter; | 287 uint32_t env_cyc = context->env_counter; |
425 break; | 427 break; |
426 } | 428 } |
427 break; | 429 break; |
428 } | 430 } |
429 uint16_t env = operator->envelope + operator->total_level; | 431 uint16_t env = operator->envelope + operator->total_level; |
432 if (operator->am) { | |
433 uint16_t base_am = (context->lfo_am_step & 0x80 ? context->lfo_am_step : ~context->lfo_am_step) & 0x7E; | |
434 env += base_am >> ams_shift[chan->ams]; | |
435 } | |
430 if (env > MAX_ENVELOPE) { | 436 if (env > MAX_ENVELOPE) { |
431 env = MAX_ENVELOPE; | 437 env = MAX_ENVELOPE; |
432 } | 438 } |
433 if (first_key_on) { | 439 if (first_key_on) { |
434 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]); | 440 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]); |
519 //printf("address_write_part1: %X\n", address); | 525 //printf("address_write_part1: %X\n", address); |
520 context->selected_reg = address; | 526 context->selected_reg = address; |
521 context->selected_part = 0; | 527 context->selected_part = 0; |
522 context->write_cycle = context->current_cycle; | 528 context->write_cycle = context->current_cycle; |
523 context->busy_cycles = BUSY_CYCLES_ADDRESS; | 529 context->busy_cycles = BUSY_CYCLES_ADDRESS; |
530 context->status |= 0x80; | |
524 } | 531 } |
525 | 532 |
526 void ym_address_write_part2(ym2612_context * context, uint8_t address) | 533 void ym_address_write_part2(ym2612_context * context, uint8_t address) |
527 { | 534 { |
528 //printf("address_write_part2: %X\n", address); | 535 //printf("address_write_part2: %X\n", address); |
529 context->selected_reg = address; | 536 context->selected_reg = address; |
530 context->selected_part = 1; | 537 context->selected_part = 1; |
531 context->write_cycle = context->current_cycle; | 538 context->write_cycle = context->current_cycle; |
532 context->busy_cycles = BUSY_CYCLES_ADDRESS; | 539 context->busy_cycles = BUSY_CYCLES_ADDRESS; |
540 context->status |= 0x80; | |
533 } | 541 } |
534 | 542 |
535 uint8_t fnum_to_keycode[] = { | 543 uint8_t fnum_to_keycode[] = { |
536 //F11 = 0 | 544 //F11 = 0 |
537 0,0,0,0,0,0,0,1, | 545 0,0,0,0,0,0,0,1, |
581 //printf("ym_update_phase_inc | channel: %d, op: %d\n", chan_num, op); | 589 //printf("ym_update_phase_inc | channel: %d, op: %d\n", chan_num, op); |
582 //base frequency | 590 //base frequency |
583 ym_channel * channel = context->channels + chan_num; | 591 ym_channel * channel = context->channels + chan_num; |
584 uint32_t inc, detune; | 592 uint32_t inc, detune; |
585 if (chan_num == 2 && context->ch3_mode && (op < (2*4 + 3))) { | 593 if (chan_num == 2 && context->ch3_mode && (op < (2*4 + 3))) { |
586 inc = context->ch3_supp[op-2*4].fnum; | 594 //supplemental fnum registers are in a different order than normal slot paramters |
587 if (!context->ch3_supp[op-2*4].block) { | 595 int index = (op-2*4) ^ 2; |
596 inc = context->ch3_supp[index].fnum; | |
597 if (!context->ch3_supp[index].block) { | |
588 inc >>= 1; | 598 inc >>= 1; |
589 } else { | 599 } else { |
590 inc <<= (context->ch3_supp[op-2*4].block-1); | 600 inc <<= (context->ch3_supp[index].block-1); |
591 } | 601 } |
592 //detune | 602 //detune |
593 detune = detune_table[context->ch3_supp[op-2*4].keycode][operator->detune & 0x3]; | 603 detune = detune_table[context->ch3_supp[index].keycode][operator->detune & 0x3]; |
594 } else { | 604 } else { |
595 inc = channel->fnum; | 605 inc = channel->fnum; |
596 if (!channel->block) { | 606 if (!channel->block) { |
597 inc >>= 1; | 607 inc >>= 1; |
598 } else { | 608 } else { |
599 inc <<= (channel->block-1); | 609 inc <<= (channel->block-1); |
600 } | 610 } |
601 //detune | 611 //detune |
602 detune = detune_table[channel->keycode][operator->detune & 0x3]; | 612 detune = detune_table[channel->keycode][operator->detune & 0x3]; |
603 } | 613 } |
604 if (operator->detune & 0x40) { | 614 if (operator->detune & 0x4) { |
605 inc -= detune; | 615 inc -= detune; |
606 //this can underflow, mask to 17-bit result | 616 //this can underflow, mask to 17-bit result |
607 inc &= 0x1FFFF; | 617 inc &= 0x1FFFF; |
608 } else { | 618 } else { |
609 inc += detune; | 619 inc += detune; |
610 } | 620 } |
611 //multiple | 621 //multiple |
612 if (operator->multiple) { | 622 if (operator->multiple) { |
613 inc *= operator->multiple; | 623 inc *= operator->multiple; |
624 inc &= 0xFFFFF; | |
614 } else { | 625 } else { |
615 //0.5 | 626 //0.5 |
616 inc >>= 1; | 627 inc >>= 1; |
617 } | 628 } |
618 //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); | 629 //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); |
742 operator->key_scaling = 3 - (value >> 6); | 753 operator->key_scaling = 3 - (value >> 6); |
743 operator->rates[PHASE_ATTACK] = value & 0x1F; | 754 operator->rates[PHASE_ATTACK] = value & 0x1F; |
744 break; | 755 break; |
745 case REG_DECAY_AM: | 756 case REG_DECAY_AM: |
746 //TODO: AM flag for LFO | 757 //TODO: AM flag for LFO |
758 operator->am = value & 0x80; | |
747 operator->rates[PHASE_DECAY] = value & 0x1F; | 759 operator->rates[PHASE_DECAY] = value & 0x1F; |
748 break; | 760 break; |
749 case REG_SUSTAIN_RATE: | 761 case REG_SUSTAIN_RATE: |
750 operator->rates[PHASE_SUSTAIN] = value & 0x1F; | 762 operator->rates[PHASE_SUSTAIN] = value & 0x1F; |
751 break; | 763 break; |
815 uint8_t ym_read_status(ym2612_context * context) | 827 uint8_t ym_read_status(ym2612_context * context) |
816 { | 828 { |
817 return context->status; | 829 return context->status; |
818 } | 830 } |
819 | 831 |
832 void ym_print_channel_info(ym2612_context *context, int channel) | |
833 { | |
834 ym_channel *chan = context->channels + channel; | |
835 printf("\n***Channel %d***\n" | |
836 "Algorithm: %d\n" | |
837 "Feedback: %d\n" | |
838 "Pan: %s\n" | |
839 "AMS: %d\n" | |
840 "PMS: %d\n", | |
841 channel+1, chan->algorithm, chan->feedback, | |
842 chan->lr == 0xC0 ? "LR" : chan->lr == 0x80 ? "L" : chan->lr == 0x40 ? "R" : "", | |
843 chan->ams, chan->pms); | |
844 for (int operator = channel * 4; operator < channel * 4+4; operator++) | |
845 { | |
846 int dispnum = operator - channel * 4 + 1; | |
847 if (dispnum == 2) { | |
848 dispnum = 3; | |
849 } else if (dispnum == 3) { | |
850 dispnum = 2; | |
851 } | |
852 ym_operator *op = context->operators + operator; | |
853 printf("\nOperator %d:\n" | |
854 " Multiple: %d\n" | |
855 " Detune: %d\n" | |
856 " Total Level: %d\n" | |
857 " Attack Rate: %d\n" | |
858 " Key Scaling: %d\n" | |
859 " Decay Rate: %d\n" | |
860 " Sustain Level: %d\n" | |
861 " Sustain Rate: %d\n" | |
862 " Release Rate: %d\n" | |
863 " Amplitude Modulation %s\n", | |
864 dispnum, op->multiple, op->detune, op->total_level, | |
865 op->rates[PHASE_ATTACK], op->key_scaling, op->rates[PHASE_DECAY], | |
866 op->sustain_level, op->rates[PHASE_SUSTAIN], op->rates[PHASE_RELEASE], | |
867 op->am ? "On" : "Off"); | |
868 } | |
869 } | |
870 |