comparison ym2612.c @ 2081:cfd53c94fffb

Initial stab at RF5C164 emulation
author Michael Pavone <pavone@retrodev.com>
date Thu, 03 Feb 2022 23:15:42 -0800
parents 1e7a63f0ccf4
children 0d1d5dccdd28
comparison
equal deleted inserted replaced
2080:bafb757e1cd2 2081:cfd53c94fffb
170 context->timer_a_load = 0; 170 context->timer_a_load = 0;
171 context->timer_b_load = 0; 171 context->timer_b_load = 0;
172 //TODO: Confirm these on hardware 172 //TODO: Confirm these on hardware
173 context->timer_a = TIMER_A_MAX; 173 context->timer_a = TIMER_A_MAX;
174 context->timer_b = TIMER_B_MAX; 174 context->timer_b = TIMER_B_MAX;
175 175
176 //TODO: Reset LFO state 176 //TODO: Reset LFO state
177 177
178 //some games seem to expect that the LR flags start out as 1 178 //some games seem to expect that the LR flags start out as 1
179 for (int i = 0; i < NUM_CHANNELS; i++) { 179 for (int i = 0; i < NUM_CHANNELS; i++) {
180 context->channels[i].lr = 0xC0; 180 context->channels[i].lr = 0xC0;
181 context->channels[i].logfile = savedlogs[i]; 181 context->channels[i].logfile = savedlogs[i];
182 if (i < 3) { 182 if (i < 3) {
197 static uint8_t registered_finalize; 197 static uint8_t registered_finalize;
198 dfopen(debug_file, "ym_debug.txt", "w"); 198 dfopen(debug_file, "ym_debug.txt", "w");
199 memset(context, 0, sizeof(*context)); 199 memset(context, 0, sizeof(*context));
200 context->clock_inc = clock_div * 6; 200 context->clock_inc = clock_div * 6;
201 context->busy_cycles = BUSY_CYCLES * context->clock_inc; 201 context->busy_cycles = BUSY_CYCLES * context->clock_inc;
202 context->audio = render_audio_source(master_clock, context->clock_inc * NUM_OPERATORS, 2); 202 context->audio = render_audio_source("YM2612", master_clock, context->clock_inc * NUM_OPERATORS, 2);
203 //TODO: pick a randomish high initial value and lower it over time 203 //TODO: pick a randomish high initial value and lower it over time
204 context->invalid_status_decay = 225000 * context->clock_inc; 204 context->invalid_status_decay = 225000 * context->clock_inc;
205 context->status_address_mask = (options & YM_OPT_3834) ? 0 : 3; 205 context->status_address_mask = (options & YM_OPT_3834) ? 0 : 3;
206 206
207 //some games seem to expect that the LR flags start out as 1 207 //some games seem to expect that the LR flags start out as 1
208 for (int i = 0; i < NUM_CHANNELS; i++) { 208 for (int i = 0; i < NUM_CHANNELS; i++) {
209 if (options & YM_OPT_WAVE_LOG) { 209 if (options & YM_OPT_WAVE_LOG) {
210 char fname[64]; 210 char fname[64];
211 sprintf(fname, "ym_channel_%d.wav", i); 211 sprintf(fname, "ym_channel_%d.wav", i);
478 } 478 }
479 //envelope value is 10-bits, but it will be used as a 4.8 value 479 //envelope value is 10-bits, but it will be used as a 4.8 value
480 operator->envelope += envelope_inc << 2; 480 operator->envelope += envelope_inc << 2;
481 //clamp to max attenuation value 481 //clamp to max attenuation value
482 if ( 482 if (
483 operator->envelope > MAX_ENVELOPE 483 operator->envelope > MAX_ENVELOPE
484 || (operator->env_phase == PHASE_RELEASE && operator->envelope >= SSG_CENTER) 484 || (operator->env_phase == PHASE_RELEASE && operator->envelope >= SSG_CENTER)
485 ) { 485 ) {
486 operator->envelope = MAX_ENVELOPE; 486 operator->envelope = MAX_ENVELOPE;
487 } 487 }
488 } 488 }
522 } 522 }
523 } else if (!(operator->ssg & SSG_HOLD)) { 523 } else if (!(operator->ssg & SSG_HOLD)) {
524 phase = operator->phase_counter = 0; 524 phase = operator->phase_counter = 0;
525 } 525 }
526 if ( 526 if (
527 (operator->env_phase == PHASE_DECAY || operator->env_phase == PHASE_SUSTAIN) 527 (operator->env_phase == PHASE_DECAY || operator->env_phase == PHASE_SUSTAIN)
528 && !(operator->ssg & SSG_HOLD) 528 && !(operator->ssg & SSG_HOLD)
529 ) { 529 ) {
530 start_envelope(operator, chan); 530 start_envelope(operator, chan);
531 env = operator->envelope; 531 env = operator->envelope;
532 } 532 }
663 context->current_op++; 663 context->current_op++;
664 if (context->current_op == NUM_OPERATORS) { 664 if (context->current_op == NUM_OPERATORS) {
665 context->current_op = 0; 665 context->current_op = 0;
666 ym_output_sample(context); 666 ym_output_sample(context);
667 } 667 }
668 668
669 } 669 }
670 //printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle); 670 //printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle);
671 } 671 }
672 672
673 void ym_address_write_part1(ym2612_context * context, uint8_t address) 673 void ym_address_write_part1(ym2612_context * context, uint8_t address)
797 //skip invalid registers 797 //skip invalid registers
798 continue; 798 continue;
799 } 799 }
800 vgm_ym2612_part1_write(context->vgm, context->current_cycle, reg, context->part1_regs[reg - YM_PART1_START]); 800 vgm_ym2612_part1_write(context->vgm, context->current_cycle, reg, context->part1_regs[reg - YM_PART1_START]);
801 } 801 }
802 802
803 for (uint8_t reg = YM_PART2_START; reg < YM_REG_END; reg++) { 803 for (uint8_t reg = YM_PART2_START; reg < YM_REG_END; reg++) {
804 if ((reg & 3) == 3 || (reg >= REG_FNUM_LOW_CH3 && reg < REG_ALG_FEEDBACK)) { 804 if ((reg & 3) == 3 || (reg >= REG_FNUM_LOW_CH3 && reg < REG_ALG_FEEDBACK)) {
805 //skip invalid registers 805 //skip invalid registers
806 continue; 806 continue;
807 } 807 }
811 811
812 void ym_data_write(ym2612_context * context, uint8_t value) 812 void ym_data_write(ym2612_context * context, uint8_t value)
813 { 813 {
814 context->write_cycle = context->current_cycle; 814 context->write_cycle = context->current_cycle;
815 context->busy_start = context->current_cycle + context->clock_inc; 815 context->busy_start = context->current_cycle + context->clock_inc;
816 816
817 if (context->selected_reg >= YM_REG_END) { 817 if (context->selected_reg >= YM_REG_END) {
818 return; 818 return;
819 } 819 }
820 if (context->selected_part) { 820 if (context->selected_part) {
821 if (context->selected_reg < YM_PART2_START) { 821 if (context->selected_reg < YM_PART2_START) {
910 uint8_t channel = value & 0x7; 910 uint8_t channel = value & 0x7;
911 if (channel != 3 && channel != 7) { 911 if (channel != 3 && channel != 7) {
912 if (channel > 2) { 912 if (channel > 2) {
913 channel--; 913 channel--;
914 } 914 }
915 uint8_t changes = channel == 2 915 uint8_t changes = channel == 2
916 ? (value | context->csm_keyon) ^ (context->channels[channel].keyon | context->csm_keyon) 916 ? (value | context->csm_keyon) ^ (context->channels[channel].keyon | context->csm_keyon)
917 : value ^ context->channels[channel].keyon; 917 : value ^ context->channels[channel].keyon;
918 context->channels[channel].keyon = value & 0xF0; 918 context->channels[channel].keyon = value & 0xF0;
919 for (uint8_t op = channel * 4, bit = 0; op < (channel + 1) * 4; op++, bit++) { 919 for (uint8_t op = channel * 4, bit = 0; op < (channel + 1) * 4; op++, bit++) {
920 if (changes & keyon_bits[bit]) { 920 if (changes & keyon_bits[bit]) {
1035 //operator 3 modulated by operator 2 1035 //operator 3 modulated by operator 2
1036 //this uses a special op2 result reg on HW, but that reg will have the most recent 1036 //this uses a special op2 result reg on HW, but that reg will have the most recent
1037 //result from op2 when op3 starts executing 1037 //result from op2 when op3 starts executing
1038 context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+2].output; 1038 context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+2].output;
1039 context->operators[channel*4+1].mod_src[1] = NULL; 1039 context->operators[channel*4+1].mod_src[1] = NULL;
1040 1040
1041 //operator 2 modulated by operator 1 1041 //operator 2 modulated by operator 1
1042 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; 1042 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output;
1043 1043
1044 //operator 4 modulated by operator 3 1044 //operator 4 modulated by operator 3
1045 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output; 1045 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output;
1046 context->operators[channel*4+3].mod_src[1] = NULL; 1046 context->operators[channel*4+3].mod_src[1] = NULL;
1047 break; 1047 break;
1048 case 1: 1048 case 1:
1051 //not available and instead the previous result is used 1051 //not available and instead the previous result is used
1052 context->operators[channel*4+1].mod_src[0] = &context->channels[channel].op1_old; 1052 context->operators[channel*4+1].mod_src[0] = &context->channels[channel].op1_old;
1053 //this uses a special op2 result reg on HW, but that reg will have the most recent 1053 //this uses a special op2 result reg on HW, but that reg will have the most recent
1054 //result from op2 when op3 starts executing 1054 //result from op2 when op3 starts executing
1055 context->operators[channel*4+1].mod_src[1] = &context->operators[channel*4+2].output; 1055 context->operators[channel*4+1].mod_src[1] = &context->operators[channel*4+2].output;
1056 1056
1057 //operator 2 unmodulated 1057 //operator 2 unmodulated
1058 context->operators[channel*4+2].mod_src[0] = NULL; 1058 context->operators[channel*4+2].mod_src[0] = NULL;
1059 1059
1060 //operator 4 modulated by operator 3 1060 //operator 4 modulated by operator 3
1061 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output; 1061 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output;
1062 context->operators[channel*4+3].mod_src[1] = NULL; 1062 context->operators[channel*4+3].mod_src[1] = NULL;
1063 break; 1063 break;
1064 case 2: 1064 case 2:
1065 //operator 3 modulated by operator 2 1065 //operator 3 modulated by operator 2
1066 //this uses a special op2 result reg on HW, but that reg will have the most recent 1066 //this uses a special op2 result reg on HW, but that reg will have the most recent
1067 //result from op2 when op3 starts executing 1067 //result from op2 when op3 starts executing
1068 context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+2].output; 1068 context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+2].output;
1069 context->operators[channel*4+1].mod_src[1] = NULL; 1069 context->operators[channel*4+1].mod_src[1] = NULL;
1070 1070
1071 //operator 2 unmodulated 1071 //operator 2 unmodulated
1072 context->operators[channel*4+2].mod_src[0] = NULL; 1072 context->operators[channel*4+2].mod_src[0] = NULL;
1073 1073
1074 //operator 4 modulated by operator 1+3 1074 //operator 4 modulated by operator 1+3
1075 //this uses a special op1 result reg on HW, but that reg will have the most recent 1075 //this uses a special op1 result reg on HW, but that reg will have the most recent
1076 //result from op1 when op4 starts executing 1076 //result from op1 when op4 starts executing
1077 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+0].output; 1077 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+0].output;
1078 context->operators[channel*4+3].mod_src[1] = &context->operators[channel*4+1].output; 1078 context->operators[channel*4+3].mod_src[1] = &context->operators[channel*4+1].output;
1079 break; 1079 break;
1080 case 3: 1080 case 3:
1081 //operator 3 unmodulated 1081 //operator 3 unmodulated
1082 context->operators[channel*4+1].mod_src[0] = NULL; 1082 context->operators[channel*4+1].mod_src[0] = NULL;
1083 context->operators[channel*4+1].mod_src[1] = NULL; 1083 context->operators[channel*4+1].mod_src[1] = NULL;
1084 1084
1085 //operator 2 modulated by operator 1 1085 //operator 2 modulated by operator 1
1086 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; 1086 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output;
1087 1087
1088 //operator 4 modulated by operator 2+3 1088 //operator 4 modulated by operator 2+3
1089 //op2 starts executing before this, but due to pipeline length the most current result is 1089 //op2 starts executing before this, but due to pipeline length the most current result is
1090 //not available and instead the previous result is used 1090 //not available and instead the previous result is used
1091 context->operators[channel*4+3].mod_src[0] = &context->channels[channel].op2_old; 1091 context->operators[channel*4+3].mod_src[0] = &context->channels[channel].op2_old;
1092 context->operators[channel*4+3].mod_src[1] = &context->operators[channel*4+1].output; 1092 context->operators[channel*4+3].mod_src[1] = &context->operators[channel*4+1].output;
1093 break; 1093 break;
1094 case 4: 1094 case 4:
1095 //operator 3 unmodulated 1095 //operator 3 unmodulated
1096 context->operators[channel*4+1].mod_src[0] = NULL; 1096 context->operators[channel*4+1].mod_src[0] = NULL;
1097 context->operators[channel*4+1].mod_src[1] = NULL; 1097 context->operators[channel*4+1].mod_src[1] = NULL;
1098 1098
1099 //operator 2 modulated by operator 1 1099 //operator 2 modulated by operator 1
1100 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; 1100 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output;
1101 1101
1102 //operator 4 modulated by operator 3 1102 //operator 4 modulated by operator 3
1103 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output; 1103 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output;
1104 context->operators[channel*4+3].mod_src[1] = NULL; 1104 context->operators[channel*4+3].mod_src[1] = NULL;
1105 break; 1105 break;
1106 case 5: 1106 case 5:
1107 //operator 3 modulated by operator 1 1107 //operator 3 modulated by operator 1
1108 //op1 starts executing before this, but due to pipeline length the most current result is 1108 //op1 starts executing before this, but due to pipeline length the most current result is
1109 //not available and instead the previous result is used 1109 //not available and instead the previous result is used
1110 context->operators[channel*4+1].mod_src[0] = &context->channels[channel].op1_old; 1110 context->operators[channel*4+1].mod_src[0] = &context->channels[channel].op1_old;
1111 context->operators[channel*4+1].mod_src[1] = NULL; 1111 context->operators[channel*4+1].mod_src[1] = NULL;
1112 1112
1113 //operator 2 modulated by operator 1 1113 //operator 2 modulated by operator 1
1114 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; 1114 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output;
1115 1115
1116 //operator 4 modulated by operator 1 1116 //operator 4 modulated by operator 1
1117 //this uses a special op1 result reg on HW, but that reg will have the most recent 1117 //this uses a special op1 result reg on HW, but that reg will have the most recent
1118 //result from op1 when op4 starts executing 1118 //result from op1 when op4 starts executing
1119 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+0].output; 1119 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+0].output;
1120 context->operators[channel*4+3].mod_src[1] = NULL; 1120 context->operators[channel*4+3].mod_src[1] = NULL;
1121 break; 1121 break;
1122 case 6: 1122 case 6:
1123 //operator 3 unmodulated 1123 //operator 3 unmodulated
1124 context->operators[channel*4+1].mod_src[0] = NULL; 1124 context->operators[channel*4+1].mod_src[0] = NULL;
1125 context->operators[channel*4+1].mod_src[1] = NULL; 1125 context->operators[channel*4+1].mod_src[1] = NULL;
1126 1126
1127 //operator 2 modulated by operator 1 1127 //operator 2 modulated by operator 1
1128 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; 1128 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output;
1129 1129
1130 //operator 4 unmodulated 1130 //operator 4 unmodulated
1131 context->operators[channel*4+3].mod_src[0] = NULL; 1131 context->operators[channel*4+3].mod_src[0] = NULL;
1132 context->operators[channel*4+3].mod_src[1] = NULL; 1132 context->operators[channel*4+3].mod_src[1] = NULL;
1133 break; 1133 break;
1134 case 7: 1134 case 7:
1135 //everything is an output so no modulation (except for op 1 feedback) 1135 //everything is an output so no modulation (except for op 1 feedback)
1136 context->operators[channel*4+1].mod_src[0] = NULL; 1136 context->operators[channel*4+1].mod_src[0] = NULL;
1137 context->operators[channel*4+1].mod_src[1] = NULL; 1137 context->operators[channel*4+1].mod_src[1] = NULL;
1138 1138
1139 context->operators[channel*4+2].mod_src[0] = NULL; 1139 context->operators[channel*4+2].mod_src[0] = NULL;
1140 1140
1141 context->operators[channel*4+3].mod_src[0] = NULL; 1141 context->operators[channel*4+3].mod_src[0] = NULL;
1142 context->operators[channel*4+3].mod_src[1] = NULL; 1142 context->operators[channel*4+3].mod_src[1] = NULL;
1143 break; 1143 break;
1144 } 1144 }
1145 context->channels[channel].feedback = value >> 3 & 0x7; 1145 context->channels[channel].feedback = value >> 3 & 0x7;
1180 } 1180 }
1181 context->last_status = status; 1181 context->last_status = status;
1182 context->last_status_cycle = cycle; 1182 context->last_status_cycle = cycle;
1183 } 1183 }
1184 return status; 1184 return status;
1185 1185
1186 } 1186 }
1187 1187
1188 void ym_print_channel_info(ym2612_context *context, int channel) 1188 void ym_print_channel_info(ym2612_context *context, int channel)
1189 { 1189 {
1190 ym_channel *chan = context->channels + channel; 1190 ym_channel *chan = context->channels + channel;