Mercurial > repos > blastem
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 } |