comparison ym2612.c @ 2558:3f58fec775df

Initial work on YMF262 (aka OPL3) emulation
author Michael Pavone <pavone@retrodev.com>
date Sun, 19 Jan 2025 00:31:16 -0800
parents 78e1769efcdb
children eb588f22ec76
comparison
equal deleted inserted replaced
2557:75dd7536c467 2558:3f58fec775df
2 Copyright 2013 Michael Pavone 2 Copyright 2013 Michael Pavone
3 This file is part of BlastEm. 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. 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 */ 5 */
6 #include <string.h> 6 #include <string.h>
7 #include <math.h>
8 #include <stdio.h>
9 #include <stdlib.h> 7 #include <stdlib.h>
10 #include "ym2612.h" 8 #include "ym2612.h"
11 #include "render.h" 9 #include "render.h"
12 #include "wave.h" 10 #include "wave.h"
13 #include "blastem.h" 11 #include "blastem.h"
45 PHASE_DECAY, 43 PHASE_DECAY,
46 PHASE_SUSTAIN, 44 PHASE_SUSTAIN,
47 PHASE_RELEASE 45 PHASE_RELEASE
48 }; 46 };
49 47
50 uint8_t did_tbl_init = 0; 48 static int16_t ams_shift[] = {8, 1, -1, -2};
51 //According to Nemesis, real hardware only uses a 256 entry quarter sine table; however,
52 //memory is cheap so using a half sine table will probably save some cycles
53 //a full sine table would be nice, but negative numbers don't get along with log2
54 #define SINE_TABLE_SIZE 512
55 static uint16_t sine_table[SINE_TABLE_SIZE];
56 //Similar deal here with the power table for log -> linear conversion
57 //According to Nemesis, real hardware only uses a 256 entry table for the fractional part
58 //and uses the whole part as a shift amount.
59 #define POW_TABLE_SIZE (1 << 13)
60 static uint16_t pow_table[POW_TABLE_SIZE];
61
62 static uint16_t rate_table_base[] = {
63 //main portion
64 0,1,0,1,0,1,0,1,
65 0,1,0,1,1,1,0,1,
66 0,1,1,1,0,1,1,1,
67 0,1,1,1,1,1,1,1,
68 //top end
69 1,1,1,1,1,1,1,1,
70 1,1,1,2,1,1,1,2,
71 1,2,1,2,1,2,1,2,
72 1,2,2,2,1,2,2,2,
73 };
74
75 static uint16_t rate_table[64*8];
76
77 static uint8_t lfo_timer_values[] = {108, 77, 71, 67, 62, 44, 8, 5}; 49 static uint8_t lfo_timer_values[] = {108, 77, 71, 67, 62, 44, 8, 5};
78 static uint8_t lfo_pm_base[][8] = { 50
79 {0, 0, 0, 0, 0, 0, 0, 0},
80 {0, 0, 0, 0, 4, 4, 4, 4},
81 {0, 0, 0, 4, 4, 4, 8, 8},
82 {0, 0, 4, 4, 8, 8, 0xc, 0xc},
83 {0, 0, 4, 8, 8, 8, 0xc,0x10},
84 {0, 0, 8, 0xc,0x10,0x10,0x14,0x18},
85 {0, 0,0x10,0x18,0x20,0x20,0x28,0x30},
86 {0, 0,0x20,0x30,0x40,0x40,0x50,0x60}
87 };
88 static int16_t lfo_pm_table[128 * 32 * 8];
89
90 int16_t ams_shift[] = {8, 1, -1, -2};
91
92 #define MAX_ENVELOPE 0xFFC
93 #define YM_DIVIDER 2 51 #define YM_DIVIDER 2
94 #define CYCLE_NEVER 0xFFFFFFFF 52 #define CYCLE_NEVER 0xFFFFFFFF
95 53
96 static uint16_t round_fixed_point(double value, int dec_bits)
97 {
98 return value * (1 << dec_bits) + 0.5;
99 }
100
101 static FILE * debug_file = NULL; 54 static FILE * debug_file = NULL;
102 static uint32_t first_key_on=0; 55 static uint32_t first_key_on=0;
103 56
104 static ym2612_context * log_context = NULL; 57 static ym2612_context * log_context = NULL;
105 58
106 static void ym_finalize_log() 59 static void ym_finalize_log()
107 { 60 {
108 if (!log_context) { 61 if (!log_context) {
109 return; 62 return;
110 } 63 }
111 for (int i = 0; i < NUM_CHANNELS; i++) { 64 for (int i = 0; i < OPN2_NUM_CHANNELS; i++) {
112 if (log_context->channels[i].logfile) { 65 if (log_context->channels[i].logfile) {
113 wave_finalize(log_context->channels[i].logfile); 66 wave_finalize(log_context->channels[i].logfile);
114 } 67 }
115 } 68 }
116 log_context = NULL; 69 log_context = NULL;
117 } 70 }
118 71
119 void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock) 72 void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock)
120 { 73 {
121 render_audio_adjust_clock(context->audio, master_clock, context->clock_inc * NUM_OPERATORS); 74 render_audio_adjust_clock(context->audio, master_clock, context->clock_inc * OPN2_NUM_OPERATORS);
122 } 75 }
123 76
124 void ym_adjust_cycles(ym2612_context *context, uint32_t deduction) 77 void ym_adjust_cycles(ym2612_context *context, uint32_t deduction)
125 { 78 {
126 context->current_cycle -= deduction; 79 context->current_cycle -= deduction;
140 context->last_status = 0; 93 context->last_status = 0;
141 context->last_status_cycle = CYCLE_NEVER; 94 context->last_status_cycle = CYCLE_NEVER;
142 } 95 }
143 } 96 }
144 97
145 #ifdef __ANDROID__
146 #define log2(x) (log(x)/log(2))
147 #endif
148
149
150 #define TIMER_A_MAX 1023 98 #define TIMER_A_MAX 1023
151 #define TIMER_B_MAX 255 99 #define TIMER_B_MAX 255
152 100
153 void ym_reset(ym2612_context *context) 101 void ym_reset(ym2612_context *context)
154 { 102 {
155 memset(context->part1_regs, 0, sizeof(context->part1_regs)); 103 memset(context->part1_regs, 0, sizeof(context->part1_regs));
156 memset(context->part2_regs, 0, sizeof(context->part2_regs)); 104 memset(context->part2_regs, 0, sizeof(context->part2_regs));
157 memset(context->operators, 0, sizeof(context->operators)); 105 memset(context->operators, 0, sizeof(context->operators));
158 FILE* savedlogs[NUM_CHANNELS]; 106 FILE* savedlogs[OPN2_NUM_CHANNELS];
159 uint8_t saved_scope_channel[NUM_CHANNELS]; 107 uint8_t saved_scope_channel[OPN2_NUM_CHANNELS];
160 for (int i = 0; i < NUM_CHANNELS; i++) 108 for (int i = 0; i < OPN2_NUM_CHANNELS; i++)
161 { 109 {
162 savedlogs[i] = context->channels[i].logfile; 110 savedlogs[i] = context->channels[i].logfile;
163 saved_scope_channel[i] = context->channels[i].scope_channel; 111 saved_scope_channel[i] = context->channels[i].scope_channel;
164 } 112 }
165 memset(context->channels, 0, sizeof(context->channels)); 113 memset(context->channels, 0, sizeof(context->channels));
176 context->timer_b = TIMER_B_MAX; 124 context->timer_b = TIMER_B_MAX;
177 125
178 //TODO: Reset LFO state 126 //TODO: Reset LFO state
179 127
180 //some games seem to expect that the LR flags start out as 1 128 //some games seem to expect that the LR flags start out as 1
181 for (int i = 0; i < NUM_CHANNELS; i++) { 129 for (int i = 0; i < OPN2_NUM_CHANNELS; i++) {
182 context->channels[i].lr = 0xC0; 130 context->channels[i].lr = 0xC0;
183 context->channels[i].logfile = savedlogs[i]; 131 context->channels[i].logfile = savedlogs[i];
184 context->channels[i].scope_channel = saved_scope_channel[i]; 132 context->channels[i].scope_channel = saved_scope_channel[i];
185 if (i < 3) { 133 if (i < 3) {
186 context->part1_regs[REG_LR_AMS_PMS - YM_PART1_START + i] = 0xC0; 134 context->part1_regs[REG_LR_AMS_PMS - YM_PART1_START + i] = 0xC0;
187 } else { 135 } else {
188 context->part2_regs[REG_LR_AMS_PMS - YM_PART2_START + i - 3] = 0xC0; 136 context->part2_regs[REG_LR_AMS_PMS - YM_PART2_START + i - 3] = 0xC0;
189 } 137 }
190 } 138 }
191 context->write_cycle = CYCLE_NEVER; 139 context->write_cycle = CYCLE_NEVER;
192 for (int i = 0; i < NUM_OPERATORS; i++) { 140 for (int i = 0; i < OPN2_NUM_OPERATORS; i++) {
193 context->operators[i].envelope = MAX_ENVELOPE; 141 context->operators[i].envelope = MAX_ENVELOPE;
194 context->operators[i].env_phase = PHASE_RELEASE; 142 context->operators[i].env_phase = PHASE_RELEASE;
195 } 143 }
196 } 144 }
197 145
200 static uint8_t registered_finalize; 148 static uint8_t registered_finalize;
201 dfopen(debug_file, "ym_debug.txt", "w"); 149 dfopen(debug_file, "ym_debug.txt", "w");
202 memset(context, 0, sizeof(*context)); 150 memset(context, 0, sizeof(*context));
203 context->clock_inc = clock_div * 6; 151 context->clock_inc = clock_div * 6;
204 context->busy_cycles = BUSY_CYCLES * context->clock_inc; 152 context->busy_cycles = BUSY_CYCLES * context->clock_inc;
205 context->audio = render_audio_source("YM2612", master_clock, context->clock_inc * NUM_OPERATORS, 2); 153 context->audio = render_audio_source("YM2612", master_clock, context->clock_inc * OPN2_NUM_OPERATORS, 2);
206 //TODO: pick a randomish high initial value and lower it over time 154 //TODO: pick a randomish high initial value and lower it over time
207 context->invalid_status_decay = 225000 * context->clock_inc; 155 context->invalid_status_decay = 225000 * context->clock_inc;
208 context->status_address_mask = (options & YM_OPT_3834) ? 0 : 3; 156 context->status_address_mask = (options & YM_OPT_3834) ? 0 : 3;
209 157
210 //some games seem to expect that the LR flags start out as 1 158 //some games seem to expect that the LR flags start out as 1
211 for (int i = 0; i < NUM_CHANNELS; i++) { 159 for (int i = 0; i < OPN2_NUM_CHANNELS; i++) {
212 if (options & YM_OPT_WAVE_LOG) { 160 if (options & YM_OPT_WAVE_LOG) {
213 char fname[64]; 161 char fname[64];
214 sprintf(fname, "ym_channel_%d.wav", i); 162 sprintf(fname, "ym_channel_%d.wav", i);
215 FILE * f = context->channels[i].logfile = fopen(fname, "wb"); 163 FILE * f = context->channels[i].logfile = fopen(fname, "wb");
216 if (!f) { 164 if (!f) {
217 fprintf(stderr, "Failed to open WAVE log file %s for writing\n", fname); 165 fprintf(stderr, "Failed to open WAVE log file %s for writing\n", fname);
218 continue; 166 continue;
219 } 167 }
220 if (!wave_init(f, master_clock / (context->clock_inc * NUM_OPERATORS), 16, 1)) { 168 if (!wave_init(f, master_clock / (context->clock_inc * OPN2_NUM_OPERATORS), 16, 1)) {
221 fclose(f); 169 fclose(f);
222 context->channels[i].logfile = NULL; 170 context->channels[i].logfile = NULL;
223 } 171 }
224 } 172 }
225 } 173 }
228 if (!registered_finalize) { 176 if (!registered_finalize) {
229 atexit(ym_finalize_log); 177 atexit(ym_finalize_log);
230 registered_finalize = 1; 178 registered_finalize = 1;
231 } 179 }
232 } 180 }
233 if (!did_tbl_init) { 181 ym_init_tables();
234 //populate sine table
235 for (int32_t i = 0; i < 512; i++) {
236 double sine = sin( ((double)(i*2+1) / SINE_TABLE_SIZE) * M_PI_2 );
237
238 //table stores 4.8 fixed pointed representation of the base 2 log
239 sine_table[i] = round_fixed_point(-log2(sine), 8);
240 }
241 //populate power table
242 for (int32_t i = 0; i < POW_TABLE_SIZE; i++) {
243 double linear = pow(2, -((double)((i & 0xFF)+1) / 256.0));
244 int32_t tmp = round_fixed_point(linear, 11);
245 int32_t shift = (i >> 8) - 2;
246 if (shift < 0) {
247 tmp <<= 0-shift;
248 } else {
249 tmp >>= shift;
250 }
251 pow_table[i] = tmp;
252 }
253 //populate envelope generator rate table, from small base table
254 for (int rate = 0; rate < 64; rate++) {
255 for (int cycle = 0; cycle < 8; cycle++) {
256 uint16_t value;
257 if (rate < 2) {
258 value = 0;
259 } else if (rate >= 60) {
260 value = 8;
261 } else if (rate < 8) {
262 value = rate_table_base[((rate & 6) == 6 ? 16 : 0) + cycle];
263 } else if (rate < 48) {
264 value = rate_table_base[(rate & 0x3) * 8 + cycle];
265 } else {
266 value = rate_table_base[32 + (rate & 0x3) * 8 + cycle] << ((rate - 48) >> 2);
267 }
268 rate_table[rate * 8 + cycle] = value;
269 }
270 }
271 //populate LFO PM table from small base table
272 //seems like there must be a better way to derive this
273 for (int freq = 0; freq < 128; freq++) {
274 for (int pms = 0; pms < 8; pms++) {
275 for (int step = 0; step < 32; step++) {
276 int16_t value = 0;
277 for (int bit = 0x40, shift = 0; bit > 0; bit >>= 1, shift++) {
278 if (freq & bit) {
279 value += lfo_pm_base[pms][(step & 0x8) ? 7-step & 7 : step & 7] >> shift;
280 }
281 }
282 if (step & 0x10) {
283 value = -value;
284 }
285 lfo_pm_table[freq * 256 + pms * 32 + step] = value;
286 }
287 }
288 }
289 }
290 ym_reset(context); 182 ym_reset(context);
291 ym_enable_zero_offset(context, 1); 183 ym_enable_zero_offset(context, 1);
292 } 184 }
293 185
294 void ym_free(ym2612_context *context) 186 void ym_free(ym2612_context *context)
428 } 320 }
429 } else { 321 } else {
430 context->lfo_am_step = context->lfo_pm_step = 0; 322 context->lfo_am_step = context->lfo_pm_step = 0;
431 } 323 }
432 if (context->lfo_pm_step != old_pm_step) { 324 if (context->lfo_pm_step != old_pm_step) {
433 for (int chan = 0; chan < NUM_CHANNELS; chan++) 325 for (int chan = 0; chan < OPN2_NUM_CHANNELS; chan++)
434 { 326 {
435 if (context->channels[chan].pms) { 327 if (context->channels[chan].pms) {
436 for (int op = chan * 4; op < (chan + 1) * 4; op++) 328 for (int op = chan * 4; op < (chan + 1) * 4; op++)
437 { 329 {
438 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); 330 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op);
563 } 455 }
564 } 456 }
565 if (env > MAX_ENVELOPE) { 457 if (env > MAX_ENVELOPE) {
566 env = MAX_ENVELOPE; 458 env = MAX_ENVELOPE;
567 } 459 }
568 if (first_key_on) { 460 int16_t output = ym_sine(phase, mod, env);
569 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]);
570 }
571 //if ((channel != 0 && channel != 4) || chan->algorithm != 5) {
572 phase += mod;
573 //}
574
575 int16_t output = pow_table[sine_table[phase & 0x1FF] + env];
576 if (phase & 0x200) {
577 output = -output;
578 }
579 if (op % 4 == 0) { 461 if (op % 4 == 0) {
580 chan->op1_old = operator->output; 462 chan->op1_old = operator->output;
581 } else if (op % 4 == 2) { 463 } else if (op % 4 == 2) {
582 chan->op2_old = operator->output; 464 chan->op2_old = operator->output;
583 } 465 }
623 } 505 }
624 506
625 void ym_output_sample(ym2612_context *context) 507 void ym_output_sample(ym2612_context *context)
626 { 508 {
627 int16_t left = 0, right = 0; 509 int16_t left = 0, right = 0;
628 for (int i = 0; i < NUM_CHANNELS; i++) { 510 for (int i = 0; i < OPN2_NUM_CHANNELS; i++) {
629 int16_t value = context->channels[i].output; 511 int16_t value = context->channels[i].output;
630 if (value >= 0) { 512 if (value >= 0) {
631 value += context->zero_offset; 513 value += context->zero_offset;
632 } else { 514 } else {
633 value -= context->zero_offset; 515 value -= context->zero_offset;
681 uint32_t op = context->current_env_op; 563 uint32_t op = context->current_env_op;
682 ym_operator * operator = context->operators + op; 564 ym_operator * operator = context->operators + op;
683 ym_channel * channel = context->channels + op/4; 565 ym_channel * channel = context->channels + op/4;
684 ym_run_envelope(context, channel, operator); 566 ym_run_envelope(context, channel, operator);
685 context->current_env_op++; 567 context->current_env_op++;
686 if (context->current_env_op == NUM_OPERATORS) { 568 if (context->current_env_op == OPN2_NUM_OPERATORS) {
687 context->current_env_op = 0; 569 context->current_env_op = 0;
688 context->env_counter++; 570 context->env_counter++;
689 } 571 }
690 } 572 }
691 573
692 //Update Phase Generator 574 //Update Phase Generator
693 ym_run_phase(context, context->current_op / 4, context->current_op); 575 ym_run_phase(context, context->current_op / 4, context->current_op);
694 context->current_op++; 576 context->current_op++;
695 if (context->current_op == NUM_OPERATORS) { 577 if (context->current_op == OPN2_NUM_OPERATORS) {
696 context->current_op = 0; 578 context->current_op = 0;
697 ym_output_sample(context); 579 ym_output_sample(context);
698 } 580 }
699 581
700 } 582 }
961 context->dac_enable = value & 0x80; 843 context->dac_enable = value & 0x80;
962 break; 844 break;
963 } 845 }
964 } else if (context->selected_reg < 0xA0) { 846 } else if (context->selected_reg < 0xA0) {
965 //part 847 //part
966 uint8_t op = context->selected_part ? (NUM_OPERATORS/2) : 0; 848 uint8_t op = context->selected_part ? (OPN2_NUM_OPERATORS/2) : 0;
967 //channel in part 849 //channel in part
968 if ((context->selected_reg & 0x3) != 0x3) { 850 if ((context->selected_reg & 0x3) != 0x3) {
969 op += 4 * (context->selected_reg & 0x3) + ((context->selected_reg & 0xC) / 4); 851 op += 4 * (context->selected_reg & 0x3) + ((context->selected_reg & 0xC) / 4);
970 //printf("write targets operator %d (%d of channel %d)\n", op, op % 4, op / 4); 852 //printf("write targets operator %d (%d of channel %d)\n", op, op % 4, op / 4);
971 ym_operator * operator = context->operators + op; 853 ym_operator * operator = context->operators + op;
1274 1156
1275 void ym_serialize(ym2612_context *context, serialize_buffer *buf) 1157 void ym_serialize(ym2612_context *context, serialize_buffer *buf)
1276 { 1158 {
1277 save_buffer8(buf, context->part1_regs, YM_PART1_REGS); 1159 save_buffer8(buf, context->part1_regs, YM_PART1_REGS);
1278 save_buffer8(buf, context->part2_regs, YM_PART2_REGS); 1160 save_buffer8(buf, context->part2_regs, YM_PART2_REGS);
1279 for (int i = 0; i < NUM_OPERATORS; i++) 1161 for (int i = 0; i < OPN2_NUM_OPERATORS; i++)
1280 { 1162 {
1281 save_int32(buf, context->operators[i].phase_counter); 1163 save_int32(buf, context->operators[i].phase_counter);
1282 save_int16(buf, context->operators[i].envelope); 1164 save_int16(buf, context->operators[i].envelope);
1283 save_int16(buf, context->operators[i].output); 1165 save_int16(buf, context->operators[i].output);
1284 save_int8(buf, context->operators[i].env_phase); 1166 save_int8(buf, context->operators[i].env_phase);
1285 save_int8(buf, context->operators[i].inverted); 1167 save_int8(buf, context->operators[i].inverted);
1286 } 1168 }
1287 for (int i = 0; i < NUM_CHANNELS; i++) 1169 for (int i = 0; i < OPN2_NUM_CHANNELS; i++)
1288 { 1170 {
1289 save_int16(buf, context->channels[i].output); 1171 save_int16(buf, context->channels[i].output);
1290 save_int16(buf, context->channels[i].op1_old); 1172 save_int16(buf, context->channels[i].op1_old);
1291 //Due to the latching behavior, these need to be saved 1173 //Due to the latching behavior, these need to be saved
1292 //even though duplicate info is probably in the regs array 1174 //even though duplicate info is probably in the regs array
1345 if (reg != REG_FNUM_LOW) { 1227 if (reg != REG_FNUM_LOW) {
1346 context->selected_reg = reg; 1228 context->selected_reg = reg;
1347 ym_data_write(context, temp_regs[i]); 1229 ym_data_write(context, temp_regs[i]);
1348 } 1230 }
1349 } 1231 }
1350 for (int i = 0; i < NUM_OPERATORS; i++) 1232 for (int i = 0; i < OPN2_NUM_OPERATORS; i++)
1351 { 1233 {
1352 context->operators[i].phase_counter = load_int32(buf); 1234 context->operators[i].phase_counter = load_int32(buf);
1353 context->operators[i].envelope = load_int16(buf); 1235 context->operators[i].envelope = load_int16(buf);
1354 context->operators[i].output = load_int16(buf); 1236 context->operators[i].output = load_int16(buf);
1355 context->operators[i].env_phase = load_int8(buf); 1237 context->operators[i].env_phase = load_int8(buf);
1356 if (context->operators[i].env_phase > PHASE_RELEASE) { 1238 if (context->operators[i].env_phase > PHASE_RELEASE) {
1357 context->operators[i].env_phase = PHASE_RELEASE; 1239 context->operators[i].env_phase = PHASE_RELEASE;
1358 } 1240 }
1359 context->operators[i].inverted = load_int8(buf) != 0 ? SSG_INVERT : 0; 1241 context->operators[i].inverted = load_int8(buf) != 0 ? SSG_INVERT : 0;
1360 } 1242 }
1361 for (int i = 0; i < NUM_CHANNELS; i++) 1243 for (int i = 0; i < OPN2_NUM_CHANNELS; i++)
1362 { 1244 {
1363 context->channels[i].output = load_int16(buf); 1245 context->channels[i].output = load_int16(buf);
1364 context->channels[i].op1_old = load_int16(buf); 1246 context->channels[i].op1_old = load_int16(buf);
1365 context->channels[i].block = load_int8(buf); 1247 context->channels[i].block = load_int8(buf);
1366 context->channels[i].fnum = load_int16(buf); 1248 context->channels[i].fnum = load_int16(buf);
1377 context->timer_a = load_int16(buf); 1259 context->timer_a = load_int16(buf);
1378 context->timer_b = load_int8(buf); 1260 context->timer_b = load_int8(buf);
1379 context->sub_timer_b = load_int8(buf); 1261 context->sub_timer_b = load_int8(buf);
1380 context->env_counter = load_int16(buf); 1262 context->env_counter = load_int16(buf);
1381 context->current_op = load_int8(buf); 1263 context->current_op = load_int8(buf);
1382 if (context->current_op >= NUM_OPERATORS) { 1264 if (context->current_op >= OPN2_NUM_OPERATORS) {
1383 context->current_op = 0; 1265 context->current_op = 0;
1384 } 1266 }
1385 context->current_env_op = load_int8(buf); 1267 context->current_env_op = load_int8(buf);
1386 if (context->current_env_op >= NUM_OPERATORS) { 1268 if (context->current_env_op >= OPN2_NUM_OPERATORS) {
1387 context->current_env_op = 0; 1269 context->current_env_op = 0;
1388 } 1270 }
1389 context->lfo_counter = load_int8(buf); 1271 context->lfo_counter = load_int8(buf);
1390 context->csm_keyon = load_int8(buf); 1272 context->csm_keyon = load_int8(buf);
1391 context->status = load_int8(buf); 1273 context->status = load_int8(buf);
1414 "YM2612 #4", 1296 "YM2612 #4",
1415 "YM2612 #5", 1297 "YM2612 #5",
1416 "YM2612 #6" 1298 "YM2612 #6"
1417 }; 1299 };
1418 context->scope = scope; 1300 context->scope = scope;
1419 for (int i = 0; i < NUM_CHANNELS; i++) 1301 for (int i = 0; i < OPN2_NUM_CHANNELS; i++)
1420 { 1302 {
1421 context->channels[i].scope_channel = scope_add_channel(scope, names[i], master_clock / (context->clock_inc * NUM_OPERATORS)); 1303 context->channels[i].scope_channel = scope_add_channel(scope, names[i], master_clock / (context->clock_inc * OPN2_NUM_OPERATORS));
1422 } 1304 }
1423 #endif 1305 #endif
1424 } 1306 }