Mercurial > repos > blastem
comparison ym2612.c @ 448:e85a107e6ec0
Fix handling of key on in YM2612 core
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 20 Jul 2013 23:49:31 -0700 |
parents | 7e8e179116af |
children | b7c3b2d22858 |
comparison
equal
deleted
inserted
replaced
447:e730fc040169 | 448:e85a107e6ec0 |
---|---|
160 } | 160 } |
161 if (!did_tbl_init) { | 161 if (!did_tbl_init) { |
162 //populate sine table | 162 //populate sine table |
163 for (int32_t i = 0; i < 512; i++) { | 163 for (int32_t i = 0; i < 512; i++) { |
164 double sine = sin( ((double)(i*2+1) / SINE_TABLE_SIZE) * M_PI_2 ); | 164 double sine = sin( ((double)(i*2+1) / SINE_TABLE_SIZE) * M_PI_2 ); |
165 | 165 |
166 //table stores 4.8 fixed pointed representation of the base 2 log | 166 //table stores 4.8 fixed pointed representation of the base 2 log |
167 sine_table[i] = round_fixed_point(-log2(sine), 8); | 167 sine_table[i] = round_fixed_point(-log2(sine), 8); |
168 } | 168 } |
169 //populate power table | 169 //populate power table |
170 for (int32_t i = 0; i < POW_TABLE_SIZE; i++) { | 170 for (int32_t i = 0; i < POW_TABLE_SIZE; i++) { |
306 operator->envelope = 0; | 306 operator->envelope = 0; |
307 operator->env_phase = PHASE_DECAY; | 307 operator->env_phase = PHASE_DECAY; |
308 } | 308 } |
309 } else { | 309 } else { |
310 if (first_key_on) { | 310 if (first_key_on) { |
311 dfprintf(debug_file, "Changing op %d envelope %d by %d in %s phase\n", op, operator->envelope, envelope_inc, | 311 dfprintf(debug_file, "Changing op %d envelope %d by %d in %s phase\n", op, operator->envelope, envelope_inc, |
312 operator->env_phase == PHASE_SUSTAIN ? "sustain" : (operator->env_phase == PHASE_DECAY ? "decay": "release")); | 312 operator->env_phase == PHASE_SUSTAIN ? "sustain" : (operator->env_phase == PHASE_DECAY ? "decay": "release")); |
313 } | 313 } |
314 operator->envelope += envelope_inc; | 314 operator->envelope += envelope_inc; |
315 //clamp to max attenuation value | 315 //clamp to max attenuation value |
316 if (operator->envelope > MAX_ENVELOPE) { | 316 if (operator->envelope > MAX_ENVELOPE) { |
326 if (context->current_env_op == NUM_OPERATORS) { | 326 if (context->current_env_op == NUM_OPERATORS) { |
327 context->current_env_op = 0; | 327 context->current_env_op = 0; |
328 context->env_counter++; | 328 context->env_counter++; |
329 } | 329 } |
330 } | 330 } |
331 | 331 |
332 //Update Phase Generator | 332 //Update Phase Generator |
333 uint32_t channel = context->current_op / 4; | 333 uint32_t channel = context->current_op / 4; |
334 if (channel != 5 || !context->dac_enable) { | 334 if (channel != 5 || !context->dac_enable) { |
335 uint32_t op = context->current_op; | 335 uint32_t op = context->current_op; |
336 //printf("updating operator %d of channel %d\n", op, channel); | 336 //printf("updating operator %d of channel %d\n", op, channel); |
346 if (operator->multiple) { | 346 if (operator->multiple) { |
347 lfo_mod *= operator->multiple; | 347 lfo_mod *= operator->multiple; |
348 } else { | 348 } else { |
349 lfo_mod >>= 1; | 349 lfo_mod >>= 1; |
350 } | 350 } |
351 operator->phase_counter += lfo_mod; | 351 operator->phase_counter += lfo_mod; |
352 } | 352 } |
353 int16_t mod = 0; | 353 int16_t mod = 0; |
354 switch (op % 4) | 354 switch (op % 4) |
355 { | 355 { |
356 case 0://Operator 1 | 356 case 0://Operator 1 |
411 } | 411 } |
412 if (first_key_on) { | 412 if (first_key_on) { |
413 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]); | 413 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]); |
414 } | 414 } |
415 phase += mod; | 415 phase += mod; |
416 | 416 |
417 int16_t output = pow_table[sine_table[phase & 0x1FF] + env]; | 417 int16_t output = pow_table[sine_table[phase & 0x1FF] + env]; |
418 if (phase & 0x200) { | 418 if (phase & 0x200) { |
419 output = -output; | 419 output = -output; |
420 } | 420 } |
421 operator->output = output; | 421 operator->output = output; |
559 } else { | 559 } else { |
560 inc <<= (channel->block-1); | 560 inc <<= (channel->block-1); |
561 } | 561 } |
562 //detune | 562 //detune |
563 detune = detune_table[channel->keycode][operator->detune & 0x3]; | 563 detune = detune_table[channel->keycode][operator->detune & 0x3]; |
564 } | 564 } |
565 if (operator->detune & 0x40) { | 565 if (operator->detune & 0x40) { |
566 inc -= detune; | 566 inc -= detune; |
567 //this can underflow, mask to 17-bit result | 567 //this can underflow, mask to 17-bit result |
568 inc &= 0x1FFFF; | 568 inc &= 0x1FFFF; |
569 } else { | 569 } else { |
598 context->lfo_enable = value & 0x8; | 598 context->lfo_enable = value & 0x8; |
599 if (!context->lfo_enable) { | 599 if (!context->lfo_enable) { |
600 context->lfo_am_step = context->lfo_pm_step = 0; | 600 context->lfo_am_step = context->lfo_pm_step = 0; |
601 } | 601 } |
602 context->lfo_freq = value & 0x7; | 602 context->lfo_freq = value & 0x7; |
603 | 603 |
604 break; | 604 break; |
605 case REG_TIMERA_HIGH: | 605 case REG_TIMERA_HIGH: |
606 context->timer_a_load &= 0x3; | 606 context->timer_a_load &= 0x3; |
607 context->timer_a_load |= value << 2; | 607 context->timer_a_load |= value << 2; |
608 break; | 608 break; |
642 if (channel > 2) { | 642 if (channel > 2) { |
643 channel--; | 643 channel--; |
644 } | 644 } |
645 for (uint8_t op = channel * 4, bit = 0x10; op < (channel + 1) * 4; op++, bit <<= 1) { | 645 for (uint8_t op = channel * 4, bit = 0x10; op < (channel + 1) * 4; op++, bit <<= 1) { |
646 if (value & bit) { | 646 if (value & bit) { |
647 first_key_on = 1; | 647 if (context->operators[op].env_phase == PHASE_RELEASE) |
648 //printf("Key On for operator %d in channel %d\n", op, channel); | 648 { |
649 context->operators[op].phase_counter = 0; | 649 first_key_on = 1; |
650 context->operators[op].env_phase = PHASE_ATTACK; | 650 //printf("Key On for operator %d in channel %d\n", op, channel); |
651 context->operators[op].envelope = MAX_ENVELOPE; | 651 context->operators[op].phase_counter = 0; |
652 context->operators[op].env_phase = PHASE_ATTACK; | |
653 } | |
652 } else { | 654 } else { |
653 //printf("Key Off for operator %d in channel %d\n", op, channel); | 655 //printf("Key Off for operator %d in channel %d\n", op, channel); |
654 context->operators[op].env_phase = PHASE_RELEASE; | 656 context->operators[op].env_phase = PHASE_RELEASE; |
655 } | 657 } |
656 } | 658 } |
751 //printf("Write of %X to LR_AMS_PMS reg for channel %d\n", value, channel); | 753 //printf("Write of %X to LR_AMS_PMS reg for channel %d\n", value, channel); |
752 break; | 754 break; |
753 } | 755 } |
754 } | 756 } |
755 } | 757 } |
756 | 758 |
757 context->write_cycle = context->current_cycle; | 759 context->write_cycle = context->current_cycle; |
758 context->status |= 0x80; | 760 context->status |= 0x80; |
759 } | 761 } |
760 | 762 |
761 uint8_t ym_read_status(ym2612_context * context) | 763 uint8_t ym_read_status(ym2612_context * context) |