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