Mercurial > repos > blastem
comparison ym2612.c @ 487:c08a4efeee7f opengl
Update opengl branch from default. Fix build breakage unrelated to merge
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 26 Oct 2013 22:38:47 -0700 |
parents | 3e1573fa22cf |
children | b7b7a1cab44a |
comparison
equal
deleted
inserted
replaced
449:7696d824489d | 487:c08a4efeee7f |
---|---|
1 /* | |
2 Copyright 2013 Michael Pavone | |
3 This file is part of BlastEm. | |
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. | |
5 */ | |
1 #include <string.h> | 6 #include <string.h> |
2 #include <math.h> | 7 #include <math.h> |
3 #include <stdio.h> | 8 #include <stdio.h> |
4 #include <stdlib.h> | 9 #include <stdlib.h> |
5 #include "ym2612.h" | 10 #include "ym2612.h" |
120 if (log_context->channels[i].logfile) { | 125 if (log_context->channels[i].logfile) { |
121 wave_finalize(log_context->channels[i].logfile); | 126 wave_finalize(log_context->channels[i].logfile); |
122 } | 127 } |
123 } | 128 } |
124 } | 129 } |
130 #define BUFFER_INC_RES 1000000000UL | |
131 | |
132 void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock) | |
133 { | |
134 uint64_t old_inc = context->buffer_inc; | |
135 context->buffer_inc = ((BUFFER_INC_RES * (uint64_t)context->sample_rate) / (uint64_t)master_clock) * (uint64_t)context->clock_inc; | |
136 } | |
125 | 137 |
126 void ym_init(ym2612_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t sample_limit, uint32_t options) | 138 void ym_init(ym2612_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t sample_limit, uint32_t options) |
127 { | 139 { |
128 dfopen(debug_file, "ym_debug.txt", "w"); | 140 dfopen(debug_file, "ym_debug.txt", "w"); |
129 memset(context, 0, sizeof(*context)); | 141 memset(context, 0, sizeof(*context)); |
130 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); | 142 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); |
131 context->back_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); | 143 context->back_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); |
132 context->buffer_inc = ((double)sample_rate / (double)master_clock) * clock_div * 6; | 144 context->sample_rate = sample_rate; |
133 context->clock_inc = clock_div * 6; | 145 context->clock_inc = clock_div * 6; |
146 ym_adjust_master_clock(context, master_clock); | |
147 | |
134 context->sample_limit = sample_limit*2; | 148 context->sample_limit = sample_limit*2; |
135 context->write_cycle = CYCLE_NEVER; | 149 context->write_cycle = CYCLE_NEVER; |
136 for (int i = 0; i < NUM_OPERATORS; i++) { | 150 for (int i = 0; i < NUM_OPERATORS; i++) { |
137 context->operators[i].envelope = MAX_ENVELOPE; | 151 context->operators[i].envelope = MAX_ENVELOPE; |
138 context->operators[i].env_phase = PHASE_RELEASE; | 152 context->operators[i].env_phase = PHASE_RELEASE; |
160 } | 174 } |
161 if (!did_tbl_init) { | 175 if (!did_tbl_init) { |
162 //populate sine table | 176 //populate sine table |
163 for (int32_t i = 0; i < 512; i++) { | 177 for (int32_t i = 0; i < 512; i++) { |
164 double sine = sin( ((double)(i*2+1) / SINE_TABLE_SIZE) * M_PI_2 ); | 178 double sine = sin( ((double)(i*2+1) / SINE_TABLE_SIZE) * M_PI_2 ); |
165 | 179 |
166 //table stores 4.8 fixed pointed representation of the base 2 log | 180 //table stores 4.8 fixed pointed representation of the base 2 log |
167 sine_table[i] = round_fixed_point(-log2(sine), 8); | 181 sine_table[i] = round_fixed_point(-log2(sine), 8); |
168 } | 182 } |
169 //populate power table | 183 //populate power table |
170 for (int32_t i = 0; i < POW_TABLE_SIZE; i++) { | 184 for (int32_t i = 0; i < POW_TABLE_SIZE; i++) { |
306 operator->envelope = 0; | 320 operator->envelope = 0; |
307 operator->env_phase = PHASE_DECAY; | 321 operator->env_phase = PHASE_DECAY; |
308 } | 322 } |
309 } else { | 323 } else { |
310 if (first_key_on) { | 324 if (first_key_on) { |
311 dfprintf(debug_file, "Changing op %d envelope %d by %d in %s phase\n", op, operator->envelope, envelope_inc, | 325 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")); | 326 operator->env_phase == PHASE_SUSTAIN ? "sustain" : (operator->env_phase == PHASE_DECAY ? "decay": "release")); |
313 } | 327 } |
314 operator->envelope += envelope_inc; | 328 operator->envelope += envelope_inc; |
315 //clamp to max attenuation value | 329 //clamp to max attenuation value |
316 if (operator->envelope > MAX_ENVELOPE) { | 330 if (operator->envelope > MAX_ENVELOPE) { |
326 if (context->current_env_op == NUM_OPERATORS) { | 340 if (context->current_env_op == NUM_OPERATORS) { |
327 context->current_env_op = 0; | 341 context->current_env_op = 0; |
328 context->env_counter++; | 342 context->env_counter++; |
329 } | 343 } |
330 } | 344 } |
331 | 345 |
332 //Update Phase Generator | 346 //Update Phase Generator |
333 uint32_t channel = context->current_op / 4; | 347 uint32_t channel = context->current_op / 4; |
334 if (channel != 5 || !context->dac_enable) { | 348 if (channel != 5 || !context->dac_enable) { |
335 uint32_t op = context->current_op; | 349 uint32_t op = context->current_op; |
336 //printf("updating operator %d of channel %d\n", op, channel); | 350 //printf("updating operator %d of channel %d\n", op, channel); |
346 if (operator->multiple) { | 360 if (operator->multiple) { |
347 lfo_mod *= operator->multiple; | 361 lfo_mod *= operator->multiple; |
348 } else { | 362 } else { |
349 lfo_mod >>= 1; | 363 lfo_mod >>= 1; |
350 } | 364 } |
351 operator->phase_counter += lfo_mod; | 365 operator->phase_counter += lfo_mod; |
352 } | 366 } |
353 int16_t mod = 0; | 367 int16_t mod = 0; |
354 switch (op % 4) | 368 switch (op % 4) |
355 { | 369 { |
356 case 0://Operator 1 | 370 case 0://Operator 1 |
411 } | 425 } |
412 if (first_key_on) { | 426 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]); | 427 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 } | 428 } |
415 phase += mod; | 429 phase += mod; |
416 | 430 |
417 int16_t output = pow_table[sine_table[phase & 0x1FF] + env]; | 431 int16_t output = pow_table[sine_table[phase & 0x1FF] + env]; |
418 if (phase & 0x200) { | 432 if (phase & 0x200) { |
419 output = -output; | 433 output = -output; |
420 } | 434 } |
421 operator->output = output; | 435 operator->output = output; |
444 } | 458 } |
445 context->current_op++; | 459 context->current_op++; |
446 context->buffer_fraction += context->buffer_inc; | 460 context->buffer_fraction += context->buffer_inc; |
447 if (context->current_op == NUM_OPERATORS) { | 461 if (context->current_op == NUM_OPERATORS) { |
448 context->current_op = 0; | 462 context->current_op = 0; |
449 if (context->buffer_fraction > 1.0) { | 463 } |
450 context->buffer_fraction -= 1.0; | 464 if (context->buffer_fraction > BUFFER_INC_RES) { |
451 context->audio_buffer[context->buffer_pos] = 0; | 465 context->buffer_fraction -= BUFFER_INC_RES; |
452 context->audio_buffer[context->buffer_pos + 1] = 0; | 466 context->audio_buffer[context->buffer_pos] = 0; |
453 for (int i = 0; i < NUM_CHANNELS; i++) { | 467 context->audio_buffer[context->buffer_pos + 1] = 0; |
454 int16_t value = context->channels[i].output & 0x3FE0; | 468 for (int i = 0; i < NUM_CHANNELS; i++) { |
455 if (value & 0x2000) { | 469 int16_t value = context->channels[i].output & 0x3FE0; |
456 value |= 0xC000; | 470 if (value & 0x2000) { |
457 } | 471 value |= 0xC000; |
458 if (context->channels[i].logfile) { | 472 } |
459 fwrite(&value, sizeof(value), 1, context->channels[i].logfile); | 473 if (context->channels[i].logfile) { |
460 } | 474 fwrite(&value, sizeof(value), 1, context->channels[i].logfile); |
461 if (context->channels[i].lr & 0x80) { | 475 } |
462 context->audio_buffer[context->buffer_pos] += value / YM_VOLUME_DIVIDER; | 476 if (context->channels[i].lr & 0x80) { |
463 } | 477 context->audio_buffer[context->buffer_pos] += value / YM_VOLUME_DIVIDER; |
464 if (context->channels[i].lr & 0x40) { | 478 } |
465 context->audio_buffer[context->buffer_pos+1] += value / YM_VOLUME_DIVIDER; | 479 if (context->channels[i].lr & 0x40) { |
466 } | 480 context->audio_buffer[context->buffer_pos+1] += value / YM_VOLUME_DIVIDER; |
467 } | 481 } |
468 context->buffer_pos += 2; | 482 } |
469 if (context->buffer_pos == context->sample_limit) { | 483 context->buffer_pos += 2; |
470 render_wait_ym(context); | 484 if (context->buffer_pos == context->sample_limit) { |
471 } | 485 render_wait_ym(context); |
472 } | 486 } |
473 } | 487 } |
474 } | 488 } |
475 if (context->current_cycle >= context->write_cycle + (BUSY_CYCLES * context->clock_inc / 6)) { | 489 if (context->current_cycle >= context->write_cycle + (BUSY_CYCLES * context->clock_inc / 6)) { |
476 context->status &= 0x7F; | 490 context->status &= 0x7F; |
559 } else { | 573 } else { |
560 inc <<= (channel->block-1); | 574 inc <<= (channel->block-1); |
561 } | 575 } |
562 //detune | 576 //detune |
563 detune = detune_table[channel->keycode][operator->detune & 0x3]; | 577 detune = detune_table[channel->keycode][operator->detune & 0x3]; |
564 } | 578 } |
565 if (operator->detune & 0x40) { | 579 if (operator->detune & 0x40) { |
566 inc -= detune; | 580 inc -= detune; |
567 //this can underflow, mask to 17-bit result | 581 //this can underflow, mask to 17-bit result |
568 inc &= 0x1FFFF; | 582 inc &= 0x1FFFF; |
569 } else { | 583 } else { |
580 operator->phase_inc = inc; | 594 operator->phase_inc = inc; |
581 } | 595 } |
582 | 596 |
583 void ym_data_write(ym2612_context * context, uint8_t value) | 597 void ym_data_write(ym2612_context * context, uint8_t value) |
584 { | 598 { |
585 if (context->selected_reg < 0x21 || context->selected_reg > 0xB6 || (context->selected_reg < 0x30 && context->selected_part)) { | 599 if (context->selected_reg >= YM_REG_END) { |
586 return; | 600 return; |
601 } | |
602 if (context->selected_part) { | |
603 if (context->selected_reg < YM_PART2_START) { | |
604 return; | |
605 } | |
606 context->part2_regs[context->selected_reg - YM_PART2_START] = value; | |
607 } else { | |
608 if (context->selected_reg < YM_PART1_START) { | |
609 return; | |
610 } | |
611 context->part1_regs[context->selected_reg - YM_PART1_START] = value; | |
587 } | 612 } |
588 dfprintf(debug_file, "write of %X to reg %X in part %d\n", value, context->selected_reg, context->selected_part+1); | 613 dfprintf(debug_file, "write of %X to reg %X in part %d\n", value, context->selected_reg, context->selected_part+1); |
589 if (context->selected_reg < 0x30) { | 614 if (context->selected_reg < 0x30) { |
590 //Shared regs | 615 //Shared regs |
591 switch (context->selected_reg) | 616 switch (context->selected_reg) |
598 context->lfo_enable = value & 0x8; | 623 context->lfo_enable = value & 0x8; |
599 if (!context->lfo_enable) { | 624 if (!context->lfo_enable) { |
600 context->lfo_am_step = context->lfo_pm_step = 0; | 625 context->lfo_am_step = context->lfo_pm_step = 0; |
601 } | 626 } |
602 context->lfo_freq = value & 0x7; | 627 context->lfo_freq = value & 0x7; |
603 | 628 |
604 break; | 629 break; |
605 case REG_TIMERA_HIGH: | 630 case REG_TIMERA_HIGH: |
606 context->timer_a_load &= 0x3; | 631 context->timer_a_load &= 0x3; |
607 context->timer_a_load |= value << 2; | 632 context->timer_a_load |= value << 2; |
608 break; | 633 break; |
642 if (channel > 2) { | 667 if (channel > 2) { |
643 channel--; | 668 channel--; |
644 } | 669 } |
645 for (uint8_t op = channel * 4, bit = 0x10; op < (channel + 1) * 4; op++, bit <<= 1) { | 670 for (uint8_t op = channel * 4, bit = 0x10; op < (channel + 1) * 4; op++, bit <<= 1) { |
646 if (value & bit) { | 671 if (value & bit) { |
647 first_key_on = 1; | 672 if (context->operators[op].env_phase == PHASE_RELEASE) |
648 //printf("Key On for operator %d in channel %d\n", op, channel); | 673 { |
649 context->operators[op].phase_counter = 0; | 674 first_key_on = 1; |
650 context->operators[op].env_phase = PHASE_ATTACK; | 675 //printf("Key On for operator %d in channel %d\n", op, channel); |
651 context->operators[op].envelope = MAX_ENVELOPE; | 676 context->operators[op].phase_counter = 0; |
677 context->operators[op].env_phase = PHASE_ATTACK; | |
678 } | |
652 } else { | 679 } else { |
653 //printf("Key Off for operator %d in channel %d\n", op, channel); | 680 //printf("Key Off for operator %d in channel %d\n", op, channel); |
654 context->operators[op].env_phase = PHASE_RELEASE; | 681 context->operators[op].env_phase = PHASE_RELEASE; |
655 } | 682 } |
656 } | 683 } |
751 //printf("Write of %X to LR_AMS_PMS reg for channel %d\n", value, channel); | 778 //printf("Write of %X to LR_AMS_PMS reg for channel %d\n", value, channel); |
752 break; | 779 break; |
753 } | 780 } |
754 } | 781 } |
755 } | 782 } |
756 | 783 |
757 context->write_cycle = context->current_cycle; | 784 context->write_cycle = context->current_cycle; |
758 context->status |= 0x80; | 785 context->status |= 0x80; |
759 } | 786 } |
760 | 787 |
761 uint8_t ym_read_status(ym2612_context * context) | 788 uint8_t ym_read_status(ym2612_context * context) |
762 { | 789 { |
763 return context->status; | 790 return context->status; |
764 } | 791 } |
765 | 792 |
766 #define GST_YM_OFFSET 0x1E4 | |
767 #define GST_YM_SIZE (0x3E4-GST_YM_OFFSET) | |
768 | |
769 uint8_t ym_load_gst(ym2612_context * context, FILE * gstfile) | |
770 { | |
771 uint8_t regdata[GST_YM_SIZE]; | |
772 fseek(gstfile, GST_YM_OFFSET, SEEK_SET); | |
773 if (fread(regdata, 1, sizeof(regdata), gstfile) != sizeof(regdata)) { | |
774 return 0; | |
775 } | |
776 for (int i = 0; i < sizeof(regdata); i++) { | |
777 if (i & 0x100) { | |
778 ym_address_write_part2(context, i & 0xFF); | |
779 } else { | |
780 ym_address_write_part1(context, i); | |
781 } | |
782 ym_data_write(context, regdata[i]); | |
783 } | |
784 return 1; | |
785 } | |
786 |