2 EPOCH Super Cassette Vision Emulator 'eSCV'
4 Author : Takeda.Toshiya
12 #include "sound_tbl.h"
13 #include "../upd7801.h"
22 clear_channel(&noise);
23 clear_channel(&square1);
24 clear_channel(&square2);
25 clear_channel(&square3);
28 memset(params, 0, sizeof(params));
29 param_cnt = param_ptr = 0;
34 void SOUND::write_data8(uint32_t addr, uint32_t data)
36 if(register_id != -1) {
37 return; // ignore new commands before return ack
43 case 0x00: param_cnt = 1; break; // note off
44 case 0x01: param_cnt = 10; break; // noises & square
45 case 0x02: param_cnt = 4; break; // tone
46 case 0x1f: param_cnt = MAX_PARAM; break; // pcm
49 cmd_addr = get_cpu_pc(0); // for patch
51 this->out_debug_log(_T("PC=%4x\tSOUND\t"), cmd_addr);
56 this->out_debug_log(_T("%2x "), data);
60 params[param_ptr++] = data;
61 if(params[0] == 0x1f) {
64 memset(pcm_table, 0, sizeof(pcm_table));
65 pcm_len = pcm.ptr = 0;
66 } else if(param_ptr >= 7) {
67 // 0xfe,0x00 : end of pcm, intf1 must not be done except star speeder
68 if(params[param_ptr - 2] == 0xfe && data == 0x00 && cmd_addr != 0xa765) {
71 process_pcm(params[param_ptr - 2]);
76 if(register_id != -1) {
77 cancel_event(this, register_id);
79 register_event(this, 0, ACK_WAIT, false, ®ister_id);
86 this->out_debug_log(_T("\n"));
91 void SOUND::write_io8(uint32_t addr, uint32_t data)
98 clear_channel(&noise);
99 clear_channel(&square1);
100 clear_channel(&square2);
101 clear_channel(&square3);
103 if(cmd_addr == 0x8402) {
105 bool pause = (get_cpu_pc(0) == 0x96c);
106 if(pause || !(params[0] == 0x1f && param_ptr > 5)) {
108 if(register_id != -1) {
109 cancel_event(this, register_id);
111 memset(params, 0, sizeof(params));
112 param_cnt = param_ptr = 0;
114 // terminate pcm when pause
118 // } else if(register_id == -1) {
119 // vm->register_callback(this, 0, 100, false, ®ister_id);
124 memset(params, 0, sizeof(params));
125 param_cnt = param_ptr = 0;
126 // clear_channel(&pcm);
128 // if(register_id == -1) {
129 // vm->register_callback(this, 0, 100, false, ®ister_id);
133 this->out_debug_log(_T("PC3\n"));
138 void SOUND::event_callback(int event_id, int err)
140 if(pcm.count && param_ptr == 5 && params[0] == 0x1f && params[1] == 0x04 && params[2] == 0x64) {
142 register_event(this, 0, ACK_WAIT, false, ®ister_id);
145 d_cpu->write_signal(SIG_UPD7801_INTF1, 1, 1);
149 void SOUND::initialize_sound(int rate)
151 tone.diff = (int)((SOUND_CLOCK / rate) * 128.0 * 16.0 + 0.5);
152 noise.diff = (int)((NOISE_CLOCK / rate) * 128.0 * 16.0 + 0.5);
153 square1.diff = (int)((SQUARE_CLOCK / rate) * 128.0 * 16.0 + 0.5);
154 square2.diff = (int)((SQUARE_CLOCK / rate) * 128.0 * 16.0 + 0.5);
155 square3.diff = (int)((SQUARE_CLOCK / rate) * 128.0 * 16.0 + 0.5);
156 pcm.diff = (int)((SOUND_CLOCK / rate) * 128.0 * 16.0 + 0.5);
158 // create volume table
159 double vol = MAX_TONE;
160 for(int i = 0; i < 32; i++) {
161 volume_table[31 - i] = (int) vol;
162 vol /= 1.12201845439369;//1.258925412;
166 // create detune table
167 for(int i = 0; i < 32; i++) {
168 detune_table[i] = (int) (detune_rate[i] * 256 / 100 + 0.5);
175 void SOUND::process_cmd()
177 if(params[0] == 0x00) {
180 clear_channel(&tone);
181 clear_channel(&noise);
182 clear_channel(&square1);
183 clear_channel(&square2);
184 clear_channel(&square3);
185 } else if(params[0] == 0x01) {
188 noise.timbre = params[1] >> 5;
189 noise.period = params[2] << 8;
190 noise.volume = (MAX_NOISE * (params[3] > 0x1f ? 0x1f : params[3])) / 0x1f;
191 noise.output = (noise_table[noise.ptr] * noise.volume) >> 8;
193 square1.period = params[4] << 8;
194 square1.volume = (MAX_SQUARE * (params[7] > 0x7f ? 0x7f : params[7])) / 0x7f;
195 square1.output = (square_table[square1.ptr] * square1.volume) >> 8;
197 square2.period = params[5] << 8;
198 square2.volume = (MAX_SQUARE * (params[8] > 0x7f ? 0x7f : params[8])) / 0x7f;
199 square2.output = (square_table[square2.ptr] * square2.volume) >> 8;
201 square3.period = params[6] << 8;
202 square3.volume = (MAX_SQUARE * (params[9] > 0x7f ? 0x7f : params[9])) / 0x7f;
203 square3.output = (square_table[square3.ptr] * square3.volume) >> 8;
206 clear_channel(&tone);
207 } else if(params[0] == 0x02) { // note on : $02, timbre, period, volume ?
209 tone.timbre = params[1] >> 5;
210 tone.period = (params[2] * detune_table[params[1] & 0x1f]);
211 tone.volume = volume_table[params[3] & 0x1f];
212 tone.output = (timbre_table[tone.timbre][tone.ptr] * tone.volume) >> 8;
214 // noise & square off
215 clear_channel(&noise);
216 clear_channel(&square1);
217 clear_channel(&square2);
218 clear_channel(&square3);
221 // clear command buffer
222 memset(params, 0, sizeof(params));
223 param_cnt = param_ptr = 0;
226 void SOUND::process_pcm(uint8_t data)
228 // add pcm wave to buffer
229 pcm_table[pcm_len++] = (data & 0x80) ? MAX_PCM : 0;
230 pcm_table[pcm_len++] = (data & 0x40) ? MAX_PCM : 0;
231 pcm_table[pcm_len++] = (data & 0x20) ? MAX_PCM : 0;
232 pcm_table[pcm_len++] = (data & 0x10) ? MAX_PCM : 0;
233 pcm_table[pcm_len++] = (data & 0x08) ? MAX_PCM : 0;
234 pcm_table[pcm_len++] = (data & 0x04) ? MAX_PCM : 0;
235 pcm_table[pcm_len++] = (data & 0x02) ? MAX_PCM : 0;
236 pcm_table[pcm_len++] = (data & 0x01) ? MAX_PCM : 0;
239 pcm.count = PCM_PERIOD;
240 pcm.output = pcm_table[pcm_len - 8];
244 void SOUND::clear_channel(channel_t *ch)
252 void SOUND::mix(int32_t* buffer, int cnt)
254 // create sound buffer
255 for(int i = 0; i < cnt; i++) {
256 int vol = 0, vol_l, vol_r;
259 pcm.count -= pcm.diff;
260 while (pcm.count <= 0) {
261 pcm.count += PCM_PERIOD;
262 // low-pass filter for the next sample
263 if(++pcm.ptr < pcm_len) {
264 pcm.output = (pcm_table[pcm.ptr] + pcm_table[pcm.ptr + 1] + pcm_table[pcm.ptr + 2] + pcm_table[pcm.ptr + 3]) >> 2;
271 vol_l = apply_volume(vol, pcm_volume_l);
272 vol_r = apply_volume(vol, pcm_volume_r);
275 if(tone.volume && tone.period) {
276 tone.count -= tone.diff;
277 while (tone.count <= 0) {
278 tone.count += tone.period;
279 tone.ptr = (tone.ptr + 1) & 0xff;
280 tone.output = (timbre_table[tone.timbre][tone.ptr] * tone.volume) >> 8;
284 if(noise.volume && noise.period) {
285 noise.count -= noise.diff;
286 while (noise.count <= 0) {
287 noise.count += noise.period;
288 noise.ptr = (noise.ptr + 1) & 0xff;
289 // noise.output = (noise_table[noise.timbre][noise.ptr] * noise.volume) >> 8;
290 noise.output = (noise_table[noise.ptr] * noise.volume) >> 8;
294 if(square1.volume && square1.period) {
295 square1.count -= square1.diff;
296 while (square1.count <= 0) {
297 square1.count += square1.period;
298 square1.ptr = (square1.ptr + 1) & 0xff;
299 square1.output = (square_table[square1.ptr] * square1.volume) >> 8;
301 vol += square1.output;
303 if(square2.volume && square2.period) {
304 square2.count -= square2.diff;
305 while (square2.count <= 0) {
306 square2.count += square2.period;
307 square2.ptr = (square2.ptr + 1) & 0xff;
308 square2.output = (square_table[square2.ptr] * square2.volume) >> 8;
310 vol += square2.output;
312 if(square3.volume && square3.period) {
313 square3.count -= square3.diff;
314 while (square3.count <= 0) {
315 square3.count += square3.period;
316 square3.ptr = (square3.ptr + 1) & 0xff;
317 square3.output = (square_table[square3.ptr] * square3.volume) >> 8;
319 vol += square3.output;
321 vol_l = apply_volume(vol, psg_volume_l);
322 vol_r = apply_volume(vol, psg_volume_r);
324 *buffer++ += vol_l; // L
325 *buffer++ += vol_r; // R
329 void SOUND::set_volume(int ch, int decibel_l, int decibel_r)
332 psg_volume_l = decibel_to_volume(decibel_l);
333 psg_volume_r = decibel_to_volume(decibel_r);
335 pcm_volume_l = decibel_to_volume(decibel_l);
336 pcm_volume_r = decibel_to_volume(decibel_r);
340 #define STATE_VERSION 1
342 #include "../../statesub.h"
344 #define DECL_STATE_ENTRY_CHANNEL_T(__pname) { \
345 DECL_STATE_ENTRY_INT32((__pname.count)); \
346 DECL_STATE_ENTRY_INT32((__pname.diff)); \
347 DECL_STATE_ENTRY_INT32((__pname.period)); \
348 DECL_STATE_ENTRY_INT32((__pname.timbre)); \
349 DECL_STATE_ENTRY_INT32((__pname.volume)); \
350 DECL_STATE_ENTRY_INT32((__pname.output)); \
351 DECL_STATE_ENTRY_INT32((__pname.ptr)); \
354 void SOUND::decl_state()
356 enter_decl_state(STATE_VERSION);
358 DECL_STATE_ENTRY_CHANNEL_T(tone);
359 DECL_STATE_ENTRY_CHANNEL_T(noise);
360 DECL_STATE_ENTRY_CHANNEL_T(square1);
361 DECL_STATE_ENTRY_CHANNEL_T(square2);
362 DECL_STATE_ENTRY_CHANNEL_T(square3);
363 DECL_STATE_ENTRY_CHANNEL_T(pcm);
365 DECL_STATE_ENTRY_1D_ARRAY(pcm_table, sizeof(pcm_table) / sizeof(int));
366 DECL_STATE_ENTRY_UINT32(cmd_addr);
367 DECL_STATE_ENTRY_INT32(pcm_len);
368 DECL_STATE_ENTRY_INT32(param_cnt);
369 DECL_STATE_ENTRY_INT32(param_ptr);
370 DECL_STATE_ENTRY_INT32(register_id);
371 DECL_STATE_ENTRY_1D_ARRAY(params, sizeof(params));
376 void SOUND::save_state(FILEIO* state_fio)
378 if(state_entry != NULL) {
379 state_entry->save_state(state_fio);
381 // state_fio->FputUint32(STATE_VERSION);
382 // state_fio->FputInt32(this_device_id);
384 // state_fio->Fwrite(&tone, sizeof(tone), 1);
385 // state_fio->Fwrite(&noise, sizeof(noise), 1);
386 // state_fio->Fwrite(&square1, sizeof(square1), 1);
387 // state_fio->Fwrite(&square2, sizeof(square2), 1);
388 // state_fio->Fwrite(&square3, sizeof(square3), 1);
389 // state_fio->Fwrite(&pcm, sizeof(pcm), 1);
390 // state_fio->Fwrite(pcm_table, sizeof(pcm_table), 1);
391 // state_fio->FputUint32(cmd_addr);
392 // state_fio->FputInt32(pcm_len);
393 // state_fio->FputInt32(param_cnt);
394 // state_fio->FputInt32(param_ptr);
395 // state_fio->FputInt32(register_id);
396 // state_fio->Fwrite(params, sizeof(params), 1);
399 bool SOUND::load_state(FILEIO* state_fio)
402 int tone_diff = tone.diff;
403 int noise_diff = noise.diff;
404 int square1_diff = square1.diff;
405 int square2_diff = square2.diff;
406 int square3_diff = square3.diff;
407 int pcm_diff = pcm.diff;
410 if(state_entry != NULL) {
411 mb = state_entry->load_state(state_fio);
416 // if(state_fio->FgetUint32() != STATE_VERSION) {
419 // if(state_fio->FgetInt32() != this_device_id) {
422 // state_fio->Fread(&tone, sizeof(tone), 1);
423 // state_fio->Fread(&noise, sizeof(noise), 1);
424 // state_fio->Fread(&square1, sizeof(square1), 1);
425 // state_fio->Fread(&square2, sizeof(square2), 1);
426 // state_fio->Fread(&square3, sizeof(square3), 1);
427 // state_fio->Fread(&pcm, sizeof(pcm), 1);
428 // state_fio->Fread(pcm_table, sizeof(pcm_table), 1);
429 // cmd_addr = state_fio->FgetUint32();
430 // pcm_len = state_fio->FgetInt32();
431 // param_cnt = state_fio->FgetInt32();
432 // param_ptr = state_fio->FgetInt32();
433 // register_id = state_fio->FgetInt32();
434 // state_fio->Fread(params, sizeof(params), 1);
437 tone.diff = tone_diff;
438 noise.diff = noise_diff;
439 square1.diff = square1_diff;
440 square2.diff = square2_diff;
441 square3.diff = square3_diff;
446 bool SOUND::process_state(FILEIO* state_fio, bool loading)
449 int tone_diff = tone.diff;
450 int noise_diff = noise.diff;
451 int square1_diff = square1.diff;
452 int square2_diff = square2.diff;
453 int square3_diff = square3.diff;
454 int pcm_diff = pcm.diff;
456 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
459 if(!state_fio->StateCheckInt32(this_device_id)) {
462 state_fio->StateBuffer(&tone, sizeof(tone), 1);
463 state_fio->StateBuffer(&noise, sizeof(noise), 1);
464 state_fio->StateBuffer(&square1, sizeof(square1), 1);
465 state_fio->StateBuffer(&square2, sizeof(square2), 1);
466 state_fio->StateBuffer(&square3, sizeof(square3), 1);
467 state_fio->StateBuffer(&pcm, sizeof(pcm), 1);
468 state_fio->StateBuffer(pcm_table, sizeof(pcm_table), 1);
469 state_fio->StateUint32(cmd_addr);
470 state_fio->StateInt32(pcm_len);
471 state_fio->StateInt32(param_cnt);
472 state_fio->StateInt32(param_ptr);
473 state_fio->StateInt32(register_id);
474 state_fio->StateBuffer(params, sizeof(params), 1);
478 tone.diff = tone_diff;
479 noise.diff = noise_diff;
480 square1.diff = square1_diff;
481 square2.diff = square2_diff;
482 square3.diff = square3_diff;