Mercurial > repos > blastem
comparison ym2612.c @ 2053:3414a4423de1 segacd
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 15 Jan 2022 13:15:21 -0800 |
parents | 1e7a63f0ccf4 |
children | cfd53c94fffb |
comparison
equal
deleted
inserted
replaced
1692:5dacaef602a7 | 2053:3414a4423de1 |
---|---|
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include "ym2612.h" | 10 #include "ym2612.h" |
11 #include "render.h" | 11 #include "render.h" |
12 #include "wave.h" | 12 #include "wave.h" |
13 #include "blastem.h" | 13 #include "blastem.h" |
14 #include "event_log.h" | |
14 | 15 |
15 //#define DO_DEBUG_PRINT | 16 //#define DO_DEBUG_PRINT |
16 #ifdef DO_DEBUG_PRINT | 17 #ifdef DO_DEBUG_PRINT |
17 #define dfprintf fprintf | 18 #define dfprintf fprintf |
18 #define dfopen(var, fname, mode) var=fopen(fname, mode) | 19 #define dfopen(var, fname, mode) var=fopen(fname, mode) |
19 #else | 20 #else |
20 #define dfprintf | 21 #define dfprintf |
21 #define dfopen(var, fname, mode) | 22 #define dfopen(var, fname, mode) |
22 #endif | 23 #endif |
23 | 24 |
24 #define BUSY_CYCLES_ADDRESS 17 | 25 #define BUSY_CYCLES 32 |
25 #define BUSY_CYCLES_DATA_LOW 83 | |
26 #define BUSY_CYCLES_DATA_HIGH 47 | |
27 #define OP_UPDATE_PERIOD 144 | 26 #define OP_UPDATE_PERIOD 144 |
28 | 27 |
29 #define BIT_TIMERA_ENABLE 0x1 | 28 #define BIT_TIMERA_ENABLE 0x1 |
30 #define BIT_TIMERB_ENABLE 0x2 | 29 #define BIT_TIMERB_ENABLE 0x2 |
31 #define BIT_TIMERA_OVEREN 0x4 | 30 #define BIT_TIMERA_OVEREN 0x4 |
118 } | 117 } |
119 | 118 |
120 void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock) | 119 void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock) |
121 { | 120 { |
122 render_audio_adjust_clock(context->audio, master_clock, context->clock_inc * NUM_OPERATORS); | 121 render_audio_adjust_clock(context->audio, master_clock, context->clock_inc * NUM_OPERATORS); |
122 } | |
123 | |
124 void ym_adjust_cycles(ym2612_context *context, uint32_t deduction) | |
125 { | |
126 context->current_cycle -= deduction; | |
127 if (context->write_cycle != CYCLE_NEVER && context->write_cycle >= deduction) { | |
128 context->write_cycle -= deduction; | |
129 } else { | |
130 context->write_cycle = CYCLE_NEVER; | |
131 } | |
132 if (context->busy_start != CYCLE_NEVER && context->busy_start >= deduction) { | |
133 context->busy_start -= deduction; | |
134 } else { | |
135 context->busy_start = CYCLE_NEVER; | |
136 } | |
137 if (context->last_status_cycle != CYCLE_NEVER && context->last_status_cycle >= deduction) { | |
138 context->last_status_cycle -= deduction; | |
139 } else { | |
140 context->last_status = 0; | |
141 context->last_status_cycle = CYCLE_NEVER; | |
142 } | |
123 } | 143 } |
124 | 144 |
125 #ifdef __ANDROID__ | 145 #ifdef __ANDROID__ |
126 #define log2(x) (log(x)/log(2)) | 146 #define log2(x) (log(x)/log(2)) |
127 #endif | 147 #endif |
157 | 177 |
158 //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 |
159 for (int i = 0; i < NUM_CHANNELS; i++) { | 179 for (int i = 0; i < NUM_CHANNELS; i++) { |
160 context->channels[i].lr = 0xC0; | 180 context->channels[i].lr = 0xC0; |
161 context->channels[i].logfile = savedlogs[i]; | 181 context->channels[i].logfile = savedlogs[i]; |
182 if (i < 3) { | |
183 context->part1_regs[REG_LR_AMS_PMS - YM_PART1_START + i] = 0xC0; | |
184 } else { | |
185 context->part2_regs[REG_LR_AMS_PMS - YM_PART2_START + i - 3] = 0xC0; | |
186 } | |
162 } | 187 } |
163 context->write_cycle = CYCLE_NEVER; | 188 context->write_cycle = CYCLE_NEVER; |
164 for (int i = 0; i < NUM_OPERATORS; i++) { | 189 for (int i = 0; i < NUM_OPERATORS; i++) { |
165 context->operators[i].envelope = MAX_ENVELOPE; | 190 context->operators[i].envelope = MAX_ENVELOPE; |
166 context->operators[i].env_phase = PHASE_RELEASE; | 191 context->operators[i].env_phase = PHASE_RELEASE; |
171 { | 196 { |
172 static uint8_t registered_finalize; | 197 static uint8_t registered_finalize; |
173 dfopen(debug_file, "ym_debug.txt", "w"); | 198 dfopen(debug_file, "ym_debug.txt", "w"); |
174 memset(context, 0, sizeof(*context)); | 199 memset(context, 0, sizeof(*context)); |
175 context->clock_inc = clock_div * 6; | 200 context->clock_inc = clock_div * 6; |
201 context->busy_cycles = BUSY_CYCLES * context->clock_inc; | |
176 context->audio = render_audio_source(master_clock, context->clock_inc * NUM_OPERATORS, 2); | 202 context->audio = render_audio_source(master_clock, context->clock_inc * NUM_OPERATORS, 2); |
203 //TODO: pick a randomish high initial value and lower it over time | |
204 context->invalid_status_decay = 225000 * context->clock_inc; | |
205 context->status_address_mask = (options & YM_OPT_3834) ? 0 : 3; | |
177 | 206 |
178 //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 |
179 for (int i = 0; i < NUM_CHANNELS; i++) { | 208 for (int i = 0; i < NUM_CHANNELS; i++) { |
180 if (options & YM_OPT_WAVE_LOG) { | 209 if (options & YM_OPT_WAVE_LOG) { |
181 char fname[64]; | 210 char fname[64]; |
254 } | 283 } |
255 } | 284 } |
256 } | 285 } |
257 } | 286 } |
258 ym_reset(context); | 287 ym_reset(context); |
288 ym_enable_zero_offset(context, 1); | |
259 } | 289 } |
260 | 290 |
261 void ym_free(ym2612_context *context) | 291 void ym_free(ym2612_context *context) |
262 { | 292 { |
263 render_free_source(context->audio); | 293 render_free_source(context->audio); |
265 ym_finalize_log(); | 295 ym_finalize_log(); |
266 } | 296 } |
267 free(context); | 297 free(context); |
268 } | 298 } |
269 | 299 |
270 #define YM_VOLUME_MULTIPLIER 2 | 300 void ym_enable_zero_offset(ym2612_context *context, uint8_t enabled) |
271 #define YM_VOLUME_DIVIDER 3 | 301 { |
302 if (enabled) { | |
303 context->zero_offset = 0x70; | |
304 context->volume_mult = 79; | |
305 context->volume_div = 120; | |
306 } else { | |
307 context->zero_offset = 0; | |
308 context->volume_mult = 2; | |
309 context->volume_div = 3; | |
310 } | |
311 } | |
272 #define YM_MOD_SHIFT 1 | 312 #define YM_MOD_SHIFT 1 |
273 | 313 |
274 #define CSM_MODE 0x80 | 314 #define CSM_MODE 0x80 |
275 | 315 |
276 #define SSG_ENABLE 8 | 316 #define SSG_ENABLE 8 |
325 keyoff(context->operators + op); | 365 keyoff(context->operators + op); |
326 } | 366 } |
327 } | 367 } |
328 } | 368 } |
329 | 369 |
370 void ym_run_timers(ym2612_context *context) | |
371 { | |
372 if (context->timer_control & BIT_TIMERA_ENABLE) { | |
373 if (context->timer_a != TIMER_A_MAX) { | |
374 context->timer_a++; | |
375 if (context->csm_keyon) { | |
376 csm_keyoff(context); | |
377 } | |
378 } else { | |
379 if (context->timer_control & BIT_TIMERA_LOAD) { | |
380 context->timer_control &= ~BIT_TIMERA_LOAD; | |
381 } else if (context->timer_control & BIT_TIMERA_OVEREN) { | |
382 context->status |= BIT_STATUS_TIMERA; | |
383 } | |
384 context->timer_a = context->timer_a_load; | |
385 if (!context->csm_keyon && context->ch3_mode == CSM_MODE) { | |
386 context->csm_keyon = 0xF0; | |
387 uint8_t changes = 0xF0 ^ context->channels[2].keyon;; | |
388 for (uint8_t op = 2*4, bit = 0; op < 3*4; op++, bit++) | |
389 { | |
390 if (changes & keyon_bits[bit]) { | |
391 keyon(context->operators + op, context->channels + 2); | |
392 } | |
393 } | |
394 } | |
395 } | |
396 } | |
397 if (!context->sub_timer_b) { | |
398 if (context->timer_control & BIT_TIMERB_ENABLE) { | |
399 if (context->timer_b != TIMER_B_MAX) { | |
400 context->timer_b++; | |
401 } else { | |
402 if (context->timer_control & BIT_TIMERB_LOAD) { | |
403 context->timer_control &= ~BIT_TIMERB_LOAD; | |
404 } else if (context->timer_control & BIT_TIMERB_OVEREN) { | |
405 context->status |= BIT_STATUS_TIMERB; | |
406 } | |
407 context->timer_b = context->timer_b_load; | |
408 } | |
409 } | |
410 } else if (context->timer_control & BIT_TIMERB_LOAD) { | |
411 context->timer_control &= ~BIT_TIMERB_LOAD; | |
412 context->timer_b = context->timer_b_load; | |
413 } | |
414 context->sub_timer_b += 0x10; | |
415 //Update LFO | |
416 if (context->lfo_enable) { | |
417 if (context->lfo_counter) { | |
418 context->lfo_counter--; | |
419 } else { | |
420 context->lfo_counter = lfo_timer_values[context->lfo_freq]; | |
421 context->lfo_am_step += 2; | |
422 context->lfo_am_step &= 0xFE; | |
423 uint8_t old_pm_step = context->lfo_pm_step; | |
424 context->lfo_pm_step = context->lfo_am_step / 8; | |
425 if (context->lfo_pm_step != old_pm_step) { | |
426 for (int chan = 0; chan < NUM_CHANNELS; chan++) | |
427 { | |
428 if (context->channels[chan].pms) { | |
429 for (int op = chan * 4; op < (chan + 1) * 4; op++) | |
430 { | |
431 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); | |
432 } | |
433 } | |
434 } | |
435 } | |
436 } | |
437 } | |
438 } | |
439 | |
440 void ym_run_envelope(ym2612_context *context, ym_channel *channel, ym_operator *operator) | |
441 { | |
442 uint32_t env_cyc = context->env_counter; | |
443 uint8_t rate; | |
444 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) { | |
445 //operator->envelope = operator->sustain_level; | |
446 operator->env_phase = PHASE_SUSTAIN; | |
447 } | |
448 rate = operator->rates[operator->env_phase]; | |
449 if (rate) { | |
450 uint8_t ks = channel->keycode >> operator->key_scaling;; | |
451 rate = rate*2 + ks; | |
452 if (rate > 63) { | |
453 rate = 63; | |
454 } | |
455 } | |
456 uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0; | |
457 if (!(env_cyc & ((1 << cycle_shift) - 1))) { | |
458 uint32_t update_cycle = env_cyc >> cycle_shift & 0x7; | |
459 uint16_t envelope_inc = rate_table[rate * 8 + update_cycle]; | |
460 if (operator->env_phase == PHASE_ATTACK) { | |
461 //this can probably be optimized to a single shift rather than a multiply + shift | |
462 uint16_t old_env = operator->envelope; | |
463 operator->envelope += ((~operator->envelope * envelope_inc) >> 4) & 0xFFFFFFFC; | |
464 if (operator->envelope > old_env) { | |
465 //Handle overflow | |
466 operator->envelope = 0; | |
467 } | |
468 if (!operator->envelope) { | |
469 operator->env_phase = PHASE_DECAY; | |
470 } | |
471 } else { | |
472 if (operator->ssg) { | |
473 if (operator->envelope < SSG_CENTER) { | |
474 envelope_inc *= 4; | |
475 } else { | |
476 envelope_inc = 0; | |
477 } | |
478 } | |
479 //envelope value is 10-bits, but it will be used as a 4.8 value | |
480 operator->envelope += envelope_inc << 2; | |
481 //clamp to max attenuation value | |
482 if ( | |
483 operator->envelope > MAX_ENVELOPE | |
484 || (operator->env_phase == PHASE_RELEASE && operator->envelope >= SSG_CENTER) | |
485 ) { | |
486 operator->envelope = MAX_ENVELOPE; | |
487 } | |
488 } | |
489 } | |
490 } | |
491 | |
492 void ym_run_phase(ym2612_context *context, uint32_t channel, uint32_t op) | |
493 { | |
494 if (channel != 5 || !context->dac_enable) { | |
495 //printf("updating operator %d of channel %d\n", op, channel); | |
496 ym_operator * operator = context->operators + op; | |
497 ym_channel * chan = context->channels + channel; | |
498 uint16_t phase = operator->phase_counter >> 10 & 0x3FF; | |
499 operator->phase_counter += operator->phase_inc;//ym_calc_phase_inc(context, operator, op); | |
500 int16_t mod = 0; | |
501 if (op & 3) { | |
502 if (operator->mod_src[0]) { | |
503 mod = *operator->mod_src[0]; | |
504 if (operator->mod_src[1]) { | |
505 mod += *operator->mod_src[1]; | |
506 } | |
507 mod >>= YM_MOD_SHIFT; | |
508 } | |
509 } else { | |
510 if (chan->feedback) { | |
511 mod = (chan->op1_old + operator->output) >> (10-chan->feedback); | |
512 } | |
513 } | |
514 uint16_t env = operator->envelope; | |
515 if (operator->ssg) { | |
516 if (env >= SSG_CENTER) { | |
517 if (operator->ssg & SSG_ALTERNATE) { | |
518 if (operator->env_phase != PHASE_RELEASE && ( | |
519 !(operator->ssg & SSG_HOLD) || ((operator->ssg ^ operator->inverted) & SSG_INVERT) == 0 | |
520 )) { | |
521 operator->inverted ^= SSG_INVERT; | |
522 } | |
523 } else if (!(operator->ssg & SSG_HOLD)) { | |
524 phase = operator->phase_counter = 0; | |
525 } | |
526 if ( | |
527 (operator->env_phase == PHASE_DECAY || operator->env_phase == PHASE_SUSTAIN) | |
528 && !(operator->ssg & SSG_HOLD) | |
529 ) { | |
530 start_envelope(operator, chan); | |
531 env = operator->envelope; | |
532 } | |
533 } | |
534 if (operator->inverted) { | |
535 env = (SSG_CENTER - env) & MAX_ENVELOPE; | |
536 } | |
537 } | |
538 env += operator->total_level; | |
539 if (operator->am) { | |
540 uint16_t base_am = (context->lfo_am_step & 0x80 ? context->lfo_am_step : ~context->lfo_am_step) & 0x7E; | |
541 if (ams_shift[chan->ams] >= 0) { | |
542 env += (base_am >> ams_shift[chan->ams]) & MAX_ENVELOPE; | |
543 } else { | |
544 env += base_am << (-ams_shift[chan->ams]); | |
545 } | |
546 } | |
547 if (env > MAX_ENVELOPE) { | |
548 env = MAX_ENVELOPE; | |
549 } | |
550 if (first_key_on) { | |
551 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]); | |
552 } | |
553 //if ((channel != 0 && channel != 4) || chan->algorithm != 5) { | |
554 phase += mod; | |
555 //} | |
556 | |
557 int16_t output = pow_table[sine_table[phase & 0x1FF] + env]; | |
558 if (phase & 0x200) { | |
559 output = -output; | |
560 } | |
561 if (op % 4 == 0) { | |
562 chan->op1_old = operator->output; | |
563 } else if (op % 4 == 2) { | |
564 chan->op2_old = operator->output; | |
565 } | |
566 operator->output = output; | |
567 //Update the channel output if we've updated all operators | |
568 if (op % 4 == 3) { | |
569 if (chan->algorithm < 4) { | |
570 chan->output = operator->output; | |
571 } else if(chan->algorithm == 4) { | |
572 chan->output = operator->output + context->operators[channel * 4 + 2].output; | |
573 } else { | |
574 output = 0; | |
575 for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) { | |
576 output += context->operators[op].output; | |
577 } | |
578 chan->output = output; | |
579 } | |
580 if (first_key_on) { | |
581 int16_t value = context->channels[channel].output & 0x3FE0; | |
582 if (value & 0x2000) { | |
583 value |= 0xC000; | |
584 } | |
585 } | |
586 } | |
587 //puts("operator update done"); | |
588 } | |
589 } | |
590 | |
591 void ym_output_sample(ym2612_context *context) | |
592 { | |
593 int16_t left = 0, right = 0; | |
594 for (int i = 0; i < NUM_CHANNELS; i++) { | |
595 int16_t value = context->channels[i].output; | |
596 if (value > 0x1FE0) { | |
597 value = 0x1FE0; | |
598 } else if (value < -0x1FF0) { | |
599 value = -0x1FF0; | |
600 } else { | |
601 value &= 0x3FE0; | |
602 if (value & 0x2000) { | |
603 value |= 0xC000; | |
604 } | |
605 } | |
606 if (value >= 0) { | |
607 value += context->zero_offset; | |
608 } else { | |
609 value -= context->zero_offset; | |
610 } | |
611 if (context->channels[i].logfile) { | |
612 fwrite(&value, sizeof(value), 1, context->channels[i].logfile); | |
613 } | |
614 if (context->channels[i].lr & 0x80) { | |
615 left += (value * context->volume_mult) / context->volume_div; | |
616 } else if (context->zero_offset) { | |
617 if (value >= 0) { | |
618 left += (context->zero_offset * context->volume_mult) / context->volume_div; | |
619 } else { | |
620 left -= (context->zero_offset * context->volume_mult) / context->volume_div; | |
621 } | |
622 } | |
623 if (context->channels[i].lr & 0x40) { | |
624 right += (value * context->volume_mult) / context->volume_div; | |
625 } else if (context->zero_offset) { | |
626 if (value >= 0) { | |
627 right += (context->zero_offset * context->volume_mult) / context->volume_div; | |
628 } else { | |
629 right -= (context->zero_offset * context->volume_mult) / context->volume_div; | |
630 } | |
631 } | |
632 } | |
633 render_put_stereo_sample(context->audio, left, right); | |
634 } | |
635 | |
330 void ym_run(ym2612_context * context, uint32_t to_cycle) | 636 void ym_run(ym2612_context * context, uint32_t to_cycle) |
331 { | 637 { |
638 if (context->current_cycle >= to_cycle) { | |
639 return; | |
640 } | |
332 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle); | 641 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle); |
333 //TODO: Fix channel update order OR remap channels in register write | 642 //TODO: Fix channel update order OR remap channels in register write |
334 for (; context->current_cycle < to_cycle; context->current_cycle += context->clock_inc) { | 643 for (; context->current_cycle < to_cycle; context->current_cycle += context->clock_inc) { |
335 //Update timers at beginning of 144 cycle period | 644 //Update timers at beginning of 144 cycle period |
336 if (!context->current_op) { | 645 if (!context->current_op) { |
337 if (context->timer_control & BIT_TIMERA_ENABLE) { | 646 ym_run_timers(context); |
338 if (context->timer_a != TIMER_A_MAX) { | |
339 context->timer_a++; | |
340 if (context->csm_keyon) { | |
341 csm_keyoff(context); | |
342 } | |
343 } else { | |
344 if (context->timer_control & BIT_TIMERA_LOAD) { | |
345 context->timer_control &= ~BIT_TIMERA_LOAD; | |
346 } else if (context->timer_control & BIT_TIMERA_OVEREN) { | |
347 context->status |= BIT_STATUS_TIMERA; | |
348 } | |
349 context->timer_a = context->timer_a_load; | |
350 if (!context->csm_keyon && context->ch3_mode == CSM_MODE) { | |
351 context->csm_keyon = 0xF0; | |
352 uint8_t changes = 0xF0 ^ context->channels[2].keyon;; | |
353 for (uint8_t op = 2*4, bit = 0; op < 3*4; op++, bit++) | |
354 { | |
355 if (changes & keyon_bits[bit]) { | |
356 keyon(context->operators + op, context->channels + 2); | |
357 } | |
358 } | |
359 } | |
360 } | |
361 } | |
362 if (!context->sub_timer_b) { | |
363 if (context->timer_control & BIT_TIMERB_ENABLE) { | |
364 if (context->timer_b != TIMER_B_MAX) { | |
365 context->timer_b++; | |
366 } else { | |
367 if (context->timer_control & BIT_TIMERB_LOAD) { | |
368 context->timer_control &= ~BIT_TIMERB_LOAD; | |
369 } else if (context->timer_control & BIT_TIMERB_OVEREN) { | |
370 context->status |= BIT_STATUS_TIMERB; | |
371 } | |
372 context->timer_b = context->timer_b_load; | |
373 } | |
374 } | |
375 } | |
376 context->sub_timer_b += 0x10; | |
377 //Update LFO | |
378 if (context->lfo_enable) { | |
379 if (context->lfo_counter) { | |
380 context->lfo_counter--; | |
381 } else { | |
382 context->lfo_counter = lfo_timer_values[context->lfo_freq]; | |
383 context->lfo_am_step += 2; | |
384 context->lfo_am_step &= 0xFE; | |
385 context->lfo_pm_step = context->lfo_am_step / 8; | |
386 } | |
387 } | |
388 } | 647 } |
389 //Update Envelope Generator | 648 //Update Envelope Generator |
390 if (!(context->current_op % 3)) { | 649 if (!(context->current_op % 3)) { |
391 uint32_t env_cyc = context->env_counter; | |
392 uint32_t op = context->current_env_op; | 650 uint32_t op = context->current_env_op; |
393 ym_operator * operator = context->operators + op; | 651 ym_operator * operator = context->operators + op; |
394 ym_channel * channel = context->channels + op/4; | 652 ym_channel * channel = context->channels + op/4; |
395 uint8_t rate; | 653 ym_run_envelope(context, channel, operator); |
396 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) { | |
397 //operator->envelope = operator->sustain_level; | |
398 operator->env_phase = PHASE_SUSTAIN; | |
399 } | |
400 rate = operator->rates[operator->env_phase]; | |
401 if (rate) { | |
402 uint8_t ks = channel->keycode >> operator->key_scaling;; | |
403 rate = rate*2 + ks; | |
404 if (rate > 63) { | |
405 rate = 63; | |
406 } | |
407 } | |
408 uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0; | |
409 if (first_key_on) { | |
410 dfprintf(debug_file, "Operator: %d, env rate: %d (2*%d+%d), env_cyc: %d, cycle_shift: %d, env_cyc & ((1 << cycle_shift) - 1): %d\n", op, rate, operator->rates[operator->env_phase], channel->keycode >> operator->key_scaling,env_cyc, cycle_shift, env_cyc & ((1 << cycle_shift) - 1)); | |
411 } | |
412 if (!(env_cyc & ((1 << cycle_shift) - 1))) { | |
413 uint32_t update_cycle = env_cyc >> cycle_shift & 0x7; | |
414 uint16_t envelope_inc = rate_table[rate * 8 + update_cycle]; | |
415 if (operator->env_phase == PHASE_ATTACK) { | |
416 //this can probably be optimized to a single shift rather than a multiply + shift | |
417 if (first_key_on) { | |
418 dfprintf(debug_file, "Changing op %d envelope %d by %d(%d * %d) in attack phase\n", op, operator->envelope, (~operator->envelope * envelope_inc) >> 4, ~operator->envelope, envelope_inc); | |
419 } | |
420 uint16_t old_env = operator->envelope; | |
421 operator->envelope += ((~operator->envelope * envelope_inc) >> 4) & 0xFFFFFFFC; | |
422 if (operator->envelope > old_env) { | |
423 //Handle overflow | |
424 operator->envelope = 0; | |
425 } | |
426 if (!operator->envelope) { | |
427 operator->env_phase = PHASE_DECAY; | |
428 } | |
429 } else { | |
430 if (first_key_on) { | |
431 dfprintf(debug_file, "Changing op %d envelope %d by %d in %s phase\n", op, operator->envelope, envelope_inc, | |
432 operator->env_phase == PHASE_SUSTAIN ? "sustain" : (operator->env_phase == PHASE_DECAY ? "decay": "release")); | |
433 } | |
434 if (operator->ssg) { | |
435 if (operator->envelope < SSG_CENTER) { | |
436 envelope_inc *= 4; | |
437 } else { | |
438 envelope_inc = 0; | |
439 } | |
440 } | |
441 //envelope value is 10-bits, but it will be used as a 4.8 value | |
442 operator->envelope += envelope_inc << 2; | |
443 //clamp to max attenuation value | |
444 if ( | |
445 operator->envelope > MAX_ENVELOPE | |
446 || (operator->env_phase == PHASE_RELEASE && operator->envelope >= SSG_CENTER) | |
447 ) { | |
448 operator->envelope = MAX_ENVELOPE; | |
449 } | |
450 } | |
451 } | |
452 context->current_env_op++; | 654 context->current_env_op++; |
453 if (context->current_env_op == NUM_OPERATORS) { | 655 if (context->current_env_op == NUM_OPERATORS) { |
454 context->current_env_op = 0; | 656 context->current_env_op = 0; |
455 context->env_counter++; | 657 context->env_counter++; |
456 } | 658 } |
457 } | 659 } |
458 | 660 |
459 //Update Phase Generator | 661 //Update Phase Generator |
460 uint32_t channel = context->current_op / 4; | 662 ym_run_phase(context, context->current_op / 4, context->current_op); |
461 if (channel != 5 || !context->dac_enable) { | |
462 uint32_t op = context->current_op; | |
463 //printf("updating operator %d of channel %d\n", op, channel); | |
464 ym_operator * operator = context->operators + op; | |
465 ym_channel * chan = context->channels + channel; | |
466 uint16_t phase = operator->phase_counter >> 10 & 0x3FF; | |
467 operator->phase_counter += ym_calc_phase_inc(context, operator, context->current_op); | |
468 int16_t mod = 0; | |
469 if (op & 3) { | |
470 if (operator->mod_src[0]) { | |
471 mod = *operator->mod_src[0]; | |
472 if (operator->mod_src[1]) { | |
473 mod += * | |
474 operator->mod_src[1]; | |
475 } | |
476 mod >>= YM_MOD_SHIFT; | |
477 } | |
478 } else { | |
479 if (chan->feedback) { | |
480 mod = (chan->op1_old + operator->output) >> (10-chan->feedback); | |
481 } | |
482 } | |
483 uint16_t env = operator->envelope; | |
484 if (operator->ssg) { | |
485 if (env >= SSG_CENTER) { | |
486 if (operator->ssg & SSG_ALTERNATE) { | |
487 if (operator->env_phase != PHASE_RELEASE && ( | |
488 !(operator->ssg & SSG_HOLD) || ((operator->ssg ^ operator->inverted) & SSG_INVERT) == 0 | |
489 )) { | |
490 operator->inverted ^= SSG_INVERT; | |
491 } | |
492 } else if (!(operator->ssg & SSG_HOLD)) { | |
493 phase = operator->phase_counter = 0; | |
494 } | |
495 if ( | |
496 (operator->env_phase == PHASE_DECAY || operator->env_phase == PHASE_SUSTAIN) | |
497 && !(operator->ssg & SSG_HOLD) | |
498 ) { | |
499 start_envelope(operator, chan); | |
500 env = operator->envelope; | |
501 } | |
502 } | |
503 if (operator->inverted) { | |
504 env = (SSG_CENTER - env) & MAX_ENVELOPE; | |
505 } | |
506 } | |
507 env += operator->total_level; | |
508 if (operator->am) { | |
509 uint16_t base_am = (context->lfo_am_step & 0x80 ? context->lfo_am_step : ~context->lfo_am_step) & 0x7E; | |
510 if (ams_shift[chan->ams] >= 0) { | |
511 env += base_am >> ams_shift[chan->ams]; | |
512 } else { | |
513 env += base_am << (-ams_shift[chan->ams]); | |
514 } | |
515 } | |
516 if (env > MAX_ENVELOPE) { | |
517 env = MAX_ENVELOPE; | |
518 } | |
519 if (first_key_on) { | |
520 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]); | |
521 } | |
522 //if ((channel != 0 && channel != 4) || chan->algorithm != 5) { | |
523 phase += mod; | |
524 //} | |
525 | |
526 int16_t output = pow_table[sine_table[phase & 0x1FF] + env]; | |
527 if (phase & 0x200) { | |
528 output = -output; | |
529 } | |
530 if (op % 4 == 0) { | |
531 chan->op1_old = operator->output; | |
532 } | |
533 operator->output = output; | |
534 //Update the channel output if we've updated all operators | |
535 if (op % 4 == 3) { | |
536 if (chan->algorithm < 4) { | |
537 chan->output = operator->output; | |
538 } else if(chan->algorithm == 4) { | |
539 chan->output = operator->output + context->operators[channel * 4 + 2].output; | |
540 } else { | |
541 output = 0; | |
542 for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) { | |
543 output += context->operators[op].output; | |
544 } | |
545 chan->output = output; | |
546 } | |
547 if (first_key_on) { | |
548 int16_t value = context->channels[channel].output & 0x3FE0; | |
549 if (value & 0x2000) { | |
550 value |= 0xC000; | |
551 } | |
552 dfprintf(debug_file, "channel %d output: %d\n", channel, (value * YM_VOLUME_MULTIPLIER) / YM_VOLUME_DIVIDER); | |
553 } | |
554 } | |
555 //puts("operator update done"); | |
556 } | |
557 context->current_op++; | 663 context->current_op++; |
558 if (context->current_op == NUM_OPERATORS) { | 664 if (context->current_op == NUM_OPERATORS) { |
559 context->current_op = 0; | 665 context->current_op = 0; |
560 | 666 ym_output_sample(context); |
561 int16_t left = 0, right = 0; | |
562 for (int i = 0; i < NUM_CHANNELS; i++) { | |
563 int16_t value = context->channels[i].output; | |
564 if (value > 0x1FE0) { | |
565 value = 0x1FE0; | |
566 } else if (value < -0x1FF0) { | |
567 value = -0x1FF0; | |
568 } else { | |
569 value &= 0x3FE0; | |
570 if (value & 0x2000) { | |
571 value |= 0xC000; | |
572 } | |
573 } | |
574 if (context->channels[i].logfile) { | |
575 fwrite(&value, sizeof(value), 1, context->channels[i].logfile); | |
576 } | |
577 if (context->channels[i].lr & 0x80) { | |
578 left += (value * YM_VOLUME_MULTIPLIER) / YM_VOLUME_DIVIDER; | |
579 } | |
580 if (context->channels[i].lr & 0x40) { | |
581 right += (value * YM_VOLUME_MULTIPLIER) / YM_VOLUME_DIVIDER; | |
582 } | |
583 } | |
584 render_put_stereo_sample(context->audio, left, right); | |
585 } | 667 } |
586 | 668 |
587 } | |
588 if (context->current_cycle >= context->write_cycle + (context->busy_cycles * context->clock_inc / 6)) { | |
589 context->status &= 0x7F; | |
590 context->write_cycle = CYCLE_NEVER; | |
591 } | 669 } |
592 //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); |
593 } | 671 } |
594 | 672 |
595 void ym_address_write_part1(ym2612_context * context, uint8_t address) | 673 void ym_address_write_part1(ym2612_context * context, uint8_t address) |
596 { | 674 { |
597 //printf("address_write_part1: %X\n", address); | 675 //printf("address_write_part1: %X\n", address); |
598 context->selected_reg = address; | 676 context->selected_reg = address; |
599 context->selected_part = 0; | 677 context->selected_part = 0; |
600 context->write_cycle = context->current_cycle; | |
601 context->busy_cycles = BUSY_CYCLES_ADDRESS; | |
602 context->status |= 0x80; | |
603 } | 678 } |
604 | 679 |
605 void ym_address_write_part2(ym2612_context * context, uint8_t address) | 680 void ym_address_write_part2(ym2612_context * context, uint8_t address) |
606 { | 681 { |
607 //printf("address_write_part2: %X\n", address); | 682 //printf("address_write_part2: %X\n", address); |
608 context->selected_reg = address; | 683 context->selected_reg = address; |
609 context->selected_part = 1; | 684 context->selected_part = 1; |
610 context->write_cycle = context->current_cycle; | |
611 context->busy_cycles = BUSY_CYCLES_ADDRESS; | |
612 context->status |= 0x80; | |
613 } | 685 } |
614 | 686 |
615 static uint8_t fnum_to_keycode[] = { | 687 static uint8_t fnum_to_keycode[] = { |
616 //F11 = 0 | 688 //F11 = 0 |
617 0,0,0,0,0,0,0,1, | 689 0,0,0,0,0,0,0,1, |
669 index ^= 1; | 741 index ^= 1; |
670 } | 742 } |
671 inc = context->ch3_supp[index].fnum; | 743 inc = context->ch3_supp[index].fnum; |
672 if (channel->pms) { | 744 if (channel->pms) { |
673 inc = inc * 2 + lfo_pm_table[(inc & 0x7F0) * 16 + channel->pms + context->lfo_pm_step]; | 745 inc = inc * 2 + lfo_pm_table[(inc & 0x7F0) * 16 + channel->pms + context->lfo_pm_step]; |
746 inc &= 0xFFF; | |
674 } | 747 } |
675 if (!context->ch3_supp[index].block) { | 748 if (!context->ch3_supp[index].block) { |
676 inc >>= 1; | 749 inc >>= 1; |
677 } else { | 750 } else { |
678 inc <<= (context->ch3_supp[index].block-1); | 751 inc <<= (context->ch3_supp[index].block-1); |
681 detune = detune_table[context->ch3_supp[index].keycode][operator->detune & 0x3]; | 754 detune = detune_table[context->ch3_supp[index].keycode][operator->detune & 0x3]; |
682 } else { | 755 } else { |
683 inc = channel->fnum; | 756 inc = channel->fnum; |
684 if (channel->pms) { | 757 if (channel->pms) { |
685 inc = inc * 2 + lfo_pm_table[(inc & 0x7F0) * 16 + channel->pms + context->lfo_pm_step]; | 758 inc = inc * 2 + lfo_pm_table[(inc & 0x7F0) * 16 + channel->pms + context->lfo_pm_step]; |
759 inc &= 0xFFF; | |
686 } | 760 } |
687 if (!channel->block) { | 761 if (!channel->block) { |
688 inc >>= 1; | 762 inc >>= 1; |
689 } else { | 763 } else { |
690 inc <<= (channel->block-1); | 764 inc <<= (channel->block-1); |
712 } | 786 } |
713 //printf("phase_inc for operator %d: %d, block: %d, fnum: %d, detune: %d, multiple: %d\n", op, inc, channel->block, channel->fnum, detune, operator->multiple); | 787 //printf("phase_inc for operator %d: %d, block: %d, fnum: %d, detune: %d, multiple: %d\n", op, inc, channel->block, channel->fnum, detune, operator->multiple); |
714 return inc; | 788 return inc; |
715 } | 789 } |
716 | 790 |
791 void ym_vgm_log(ym2612_context *context, uint32_t master_clock, vgm_writer *vgm) | |
792 { | |
793 vgm_ym2612_init(vgm, 6 * master_clock / context->clock_inc); | |
794 context->vgm = vgm; | |
795 for (uint8_t reg = YM_PART1_START; reg < YM_REG_END; reg++) { | |
796 if ((reg >= REG_DETUNE_MULT && (reg & 3) == 3) || (reg >= 0x2D && reg < REG_DETUNE_MULT) || reg == 0x23 || reg == 0x29) { | |
797 //skip invalid registers | |
798 continue; | |
799 } | |
800 vgm_ym2612_part1_write(context->vgm, context->current_cycle, reg, context->part1_regs[reg - YM_PART1_START]); | |
801 } | |
802 | |
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)) { | |
805 //skip invalid registers | |
806 continue; | |
807 } | |
808 vgm_ym2612_part2_write(context->vgm, context->current_cycle, reg, context->part2_regs[reg - YM_PART2_START]); | |
809 } | |
810 } | |
811 | |
717 void ym_data_write(ym2612_context * context, uint8_t value) | 812 void ym_data_write(ym2612_context * context, uint8_t value) |
718 { | 813 { |
814 context->write_cycle = context->current_cycle; | |
815 context->busy_start = context->current_cycle + context->clock_inc; | |
816 | |
719 if (context->selected_reg >= YM_REG_END) { | 817 if (context->selected_reg >= YM_REG_END) { |
720 return; | 818 return; |
721 } | 819 } |
722 if (context->selected_part) { | 820 if (context->selected_part) { |
723 if (context->selected_reg < YM_PART2_START) { | 821 if (context->selected_reg < YM_PART2_START) { |
724 return; | 822 return; |
823 } | |
824 if (context->vgm) { | |
825 vgm_ym2612_part2_write(context->vgm, context->current_cycle, context->selected_reg, value); | |
725 } | 826 } |
726 context->part2_regs[context->selected_reg - YM_PART2_START] = value; | 827 context->part2_regs[context->selected_reg - YM_PART2_START] = value; |
727 } else { | 828 } else { |
728 if (context->selected_reg < YM_PART1_START) { | 829 if (context->selected_reg < YM_PART1_START) { |
729 return; | 830 return; |
730 } | 831 } |
832 if (context->vgm) { | |
833 vgm_ym2612_part1_write(context->vgm, context->current_cycle, context->selected_reg, value); | |
834 } | |
731 context->part1_regs[context->selected_reg - YM_PART1_START] = value; | 835 context->part1_regs[context->selected_reg - YM_PART1_START] = value; |
732 } | 836 } |
837 uint8_t buffer[3] = {context->selected_part, context->selected_reg, value}; | |
838 event_log(EVENT_YM_REG, context->current_cycle, sizeof(buffer), buffer); | |
733 dfprintf(debug_file, "write of %X to reg %X in part %d\n", value, context->selected_reg, context->selected_part+1); | 839 dfprintf(debug_file, "write of %X to reg %X in part %d\n", value, context->selected_reg, context->selected_part+1); |
734 if (context->selected_reg < 0x30) { | 840 if (context->selected_reg < 0x30) { |
735 //Shared regs | 841 //Shared regs |
736 switch (context->selected_reg) | 842 switch (context->selected_reg) |
737 { | 843 { |
740 /*if ((value & 0x8) && !context->lfo_enable) { | 846 /*if ((value & 0x8) && !context->lfo_enable) { |
741 printf("LFO Enabled, Freq: %d\n", value & 0x7); | 847 printf("LFO Enabled, Freq: %d\n", value & 0x7); |
742 }*/ | 848 }*/ |
743 context->lfo_enable = value & 0x8; | 849 context->lfo_enable = value & 0x8; |
744 if (!context->lfo_enable) { | 850 if (!context->lfo_enable) { |
851 uint8_t old_pm_step = context->lfo_pm_step; | |
745 context->lfo_am_step = context->lfo_pm_step = 0; | 852 context->lfo_am_step = context->lfo_pm_step = 0; |
853 if (old_pm_step) { | |
854 for (int chan = 0; chan < NUM_CHANNELS; chan++) | |
855 { | |
856 if (context->channels[chan].pms) { | |
857 for (int op = chan * 4; op < (chan + 1) * 4; op++) | |
858 { | |
859 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); | |
860 } | |
861 } | |
862 } | |
863 } | |
746 } | 864 } |
747 context->lfo_freq = value & 0x7; | 865 context->lfo_freq = value & 0x7; |
748 | 866 |
749 break; | 867 break; |
750 case REG_TIMERA_HIGH: | 868 case REG_TIMERA_HIGH: |
776 context->status &= ~BIT_STATUS_TIMERB; | 894 context->status &= ~BIT_STATUS_TIMERB; |
777 } | 895 } |
778 if (context->ch3_mode == CSM_MODE && (value & 0xC0) != CSM_MODE && context->csm_keyon) { | 896 if (context->ch3_mode == CSM_MODE && (value & 0xC0) != CSM_MODE && context->csm_keyon) { |
779 csm_keyoff(context); | 897 csm_keyoff(context); |
780 } | 898 } |
899 uint8_t old_mode = context->ch3_mode; | |
781 context->ch3_mode = value & 0xC0; | 900 context->ch3_mode = value & 0xC0; |
901 if (context->ch3_mode != old_mode) { | |
902 for (int op = 2 * 4; op < 3*4; op++) | |
903 { | |
904 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); | |
905 } | |
906 } | |
782 break; | 907 break; |
783 } | 908 } |
784 case REG_KEY_ONOFF: { | 909 case REG_KEY_ONOFF: { |
785 uint8_t channel = value & 0x7; | 910 uint8_t channel = value & 0x7; |
786 if (channel != 3 && channel != 7) { | 911 if (channel != 3 && channel != 7) { |
828 switch (context->selected_reg & 0xF0) | 953 switch (context->selected_reg & 0xF0) |
829 { | 954 { |
830 case REG_DETUNE_MULT: | 955 case REG_DETUNE_MULT: |
831 operator->detune = value >> 4 & 0x7; | 956 operator->detune = value >> 4 & 0x7; |
832 operator->multiple = value & 0xF; | 957 operator->multiple = value & 0xF; |
958 operator->phase_inc = ym_calc_phase_inc(context, operator, op); | |
833 break; | 959 break; |
834 case REG_TOTAL_LEVEL: | 960 case REG_TOTAL_LEVEL: |
835 operator->total_level = (value & 0x7F) << 5; | 961 operator->total_level = (value & 0x7F) << 5; |
836 break; | 962 break; |
837 case REG_ATTACK_KS: | 963 case REG_ATTACK_KS: |
838 operator->key_scaling = 3 - (value >> 6); | 964 operator->key_scaling = 3 - (value >> 6); |
839 operator->rates[PHASE_ATTACK] = value & 0x1F; | 965 operator->rates[PHASE_ATTACK] = value & 0x1F; |
840 break; | 966 break; |
841 case REG_DECAY_AM: | 967 case REG_DECAY_AM: |
842 //TODO: AM flag for LFO | |
843 operator->am = value & 0x80; | 968 operator->am = value & 0x80; |
844 operator->rates[PHASE_DECAY] = value & 0x1F; | 969 operator->rates[PHASE_DECAY] = value & 0x1F; |
845 break; | 970 break; |
846 case REG_SUSTAIN_RATE: | 971 case REG_SUSTAIN_RATE: |
847 operator->rates[PHASE_SUSTAIN] = value & 0x1F; | 972 operator->rates[PHASE_SUSTAIN] = value & 0x1F; |
875 { | 1000 { |
876 case REG_FNUM_LOW: | 1001 case REG_FNUM_LOW: |
877 context->channels[channel].block = context->channels[channel].block_fnum_latch >> 3 & 0x7; | 1002 context->channels[channel].block = context->channels[channel].block_fnum_latch >> 3 & 0x7; |
878 context->channels[channel].fnum = (context->channels[channel].block_fnum_latch & 0x7) << 8 | value; | 1003 context->channels[channel].fnum = (context->channels[channel].block_fnum_latch & 0x7) << 8 | value; |
879 context->channels[channel].keycode = context->channels[channel].block << 2 | fnum_to_keycode[context->channels[channel].fnum >> 7]; | 1004 context->channels[channel].keycode = context->channels[channel].block << 2 | fnum_to_keycode[context->channels[channel].fnum >> 7]; |
1005 for (int op = channel * 4; op < (channel + 1) * 4; op++) | |
1006 { | |
1007 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); | |
1008 } | |
880 break; | 1009 break; |
881 case REG_BLOCK_FNUM_H:{ | 1010 case REG_BLOCK_FNUM_H:{ |
882 context->channels[channel].block_fnum_latch = value; | 1011 context->channels[channel].block_fnum_latch = value; |
883 break; | 1012 break; |
884 } | 1013 } |
885 case REG_FNUM_LOW_CH3: | 1014 case REG_FNUM_LOW_CH3: |
886 if (channel < 3) { | 1015 if (channel < 3) { |
887 context->ch3_supp[channel].block = context->ch3_supp[channel].block_fnum_latch >> 3 & 0x7; | 1016 context->ch3_supp[channel].block = context->ch3_supp[channel].block_fnum_latch >> 3 & 0x7; |
888 context->ch3_supp[channel].fnum = (context->ch3_supp[channel].block_fnum_latch & 0x7) << 8 | value; | 1017 context->ch3_supp[channel].fnum = (context->ch3_supp[channel].block_fnum_latch & 0x7) << 8 | value; |
889 context->ch3_supp[channel].keycode = context->ch3_supp[channel].block << 2 | fnum_to_keycode[context->ch3_supp[channel].fnum >> 7]; | 1018 context->ch3_supp[channel].keycode = context->ch3_supp[channel].block << 2 | fnum_to_keycode[context->ch3_supp[channel].fnum >> 7]; |
1019 if (context->ch3_mode) { | |
1020 int op = 2 * 4 + (channel < 2 ? (channel ^ 1) : channel); | |
1021 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); | |
1022 } | |
890 } | 1023 } |
891 break; | 1024 break; |
892 case REG_BLOCK_FN_CH3: | 1025 case REG_BLOCK_FN_CH3: |
893 if (channel < 3) { | 1026 if (channel < 3) { |
894 context->ch3_supp[channel].block_fnum_latch = value; | 1027 context->ch3_supp[channel].block_fnum_latch = value; |
898 context->channels[channel].algorithm = value & 0x7; | 1031 context->channels[channel].algorithm = value & 0x7; |
899 switch (context->channels[channel].algorithm) | 1032 switch (context->channels[channel].algorithm) |
900 { | 1033 { |
901 case 0: | 1034 case 0: |
902 //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 | |
1037 //result from op2 when op3 starts executing | |
903 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; |
904 context->operators[channel*4+1].mod_src[1] = NULL; | 1039 context->operators[channel*4+1].mod_src[1] = NULL; |
905 | 1040 |
906 //operator 2 modulated by operator 1 | 1041 //operator 2 modulated by operator 1 |
907 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; |
910 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; |
911 context->operators[channel*4+3].mod_src[1] = NULL; | 1046 context->operators[channel*4+3].mod_src[1] = NULL; |
912 break; | 1047 break; |
913 case 1: | 1048 case 1: |
914 //operator 3 modulated by operator 1+2 | 1049 //operator 3 modulated by operator 1+2 |
915 context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+0].output; | 1050 //op1 starts executing before this, but due to pipeline length the most current result is |
1051 //not available and instead the previous result is used | |
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 | |
1054 //result from op2 when op3 starts executing | |
916 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; |
917 | 1056 |
918 //operator 2 unmodulated | 1057 //operator 2 unmodulated |
919 context->operators[channel*4+2].mod_src[0] = NULL; | 1058 context->operators[channel*4+2].mod_src[0] = NULL; |
920 | 1059 |
922 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; |
923 context->operators[channel*4+3].mod_src[1] = NULL; | 1062 context->operators[channel*4+3].mod_src[1] = NULL; |
924 break; | 1063 break; |
925 case 2: | 1064 case 2: |
926 //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 | |
1067 //result from op2 when op3 starts executing | |
927 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; |
928 context->operators[channel*4+1].mod_src[1] = NULL; | 1069 context->operators[channel*4+1].mod_src[1] = NULL; |
929 | 1070 |
930 //operator 2 unmodulated | 1071 //operator 2 unmodulated |
931 context->operators[channel*4+2].mod_src[0] = NULL; | 1072 context->operators[channel*4+2].mod_src[0] = NULL; |
932 | 1073 |
933 //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 | |
1076 //result from op1 when op4 starts executing | |
934 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; |
935 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; |
936 break; | 1079 break; |
937 case 3: | 1080 case 3: |
938 //operator 3 unmodulated | 1081 //operator 3 unmodulated |
941 | 1084 |
942 //operator 2 modulated by operator 1 | 1085 //operator 2 modulated by operator 1 |
943 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; |
944 | 1087 |
945 //operator 4 modulated by operator 2+3 | 1088 //operator 4 modulated by operator 2+3 |
946 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+2].output; | 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 | |
1091 context->operators[channel*4+3].mod_src[0] = &context->channels[channel].op2_old; | |
947 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; |
948 break; | 1093 break; |
949 case 4: | 1094 case 4: |
950 //operator 3 unmodulated | 1095 //operator 3 unmodulated |
951 context->operators[channel*4+1].mod_src[0] = NULL; | 1096 context->operators[channel*4+1].mod_src[0] = NULL; |
958 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; |
959 context->operators[channel*4+3].mod_src[1] = NULL; | 1104 context->operators[channel*4+3].mod_src[1] = NULL; |
960 break; | 1105 break; |
961 case 5: | 1106 case 5: |
962 //operator 3 modulated by operator 1 | 1107 //operator 3 modulated by operator 1 |
963 context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+0].output; | 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 | |
1110 context->operators[channel*4+1].mod_src[0] = &context->channels[channel].op1_old; | |
964 context->operators[channel*4+1].mod_src[1] = NULL; | 1111 context->operators[channel*4+1].mod_src[1] = NULL; |
965 | 1112 |
966 //operator 2 modulated by operator 1 | 1113 //operator 2 modulated by operator 1 |
967 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; |
968 | 1115 |
969 //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 | |
1118 //result from op1 when op4 starts executing | |
970 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; |
971 context->operators[channel*4+3].mod_src[1] = NULL; | 1120 context->operators[channel*4+3].mod_src[1] = NULL; |
972 break; | 1121 break; |
973 case 6: | 1122 case 6: |
974 //operator 3 unmodulated | 1123 //operator 3 unmodulated |
994 break; | 1143 break; |
995 } | 1144 } |
996 context->channels[channel].feedback = value >> 3 & 0x7; | 1145 context->channels[channel].feedback = value >> 3 & 0x7; |
997 //printf("Algorithm %d, feedback %d for channel %d\n", value & 0x7, value >> 3 & 0x7, channel); | 1146 //printf("Algorithm %d, feedback %d for channel %d\n", value & 0x7, value >> 3 & 0x7, channel); |
998 break; | 1147 break; |
999 case REG_LR_AMS_PMS: | 1148 case REG_LR_AMS_PMS: { |
1149 uint8_t old_pms = context->channels[channel].pms; | |
1000 context->channels[channel].pms = (value & 0x7) * 32; | 1150 context->channels[channel].pms = (value & 0x7) * 32; |
1001 context->channels[channel].ams = value >> 4 & 0x3; | 1151 context->channels[channel].ams = value >> 4 & 0x3; |
1002 context->channels[channel].lr = value & 0xC0; | 1152 context->channels[channel].lr = value & 0xC0; |
1153 if (old_pms != context->channels[channel].pms) { | |
1154 for (int op = channel * 4; op < (channel + 1) * 4; op++) | |
1155 { | |
1156 context->operators[op].phase_inc = ym_calc_phase_inc(context, context->operators + op, op); | |
1157 } | |
1158 } | |
1003 //printf("Write of %X to LR_AMS_PMS reg for channel %d\n", value, channel); | 1159 //printf("Write of %X to LR_AMS_PMS reg for channel %d\n", value, channel); |
1004 break; | 1160 break; |
1005 } | 1161 } |
1006 } | 1162 } |
1007 } | 1163 } |
1008 | 1164 } |
1009 context->write_cycle = context->current_cycle; | 1165 } |
1010 context->busy_cycles = context->selected_reg < 0xA0 ? BUSY_CYCLES_DATA_LOW : BUSY_CYCLES_DATA_HIGH; | 1166 |
1011 context->status |= 0x80; | 1167 uint8_t ym_read_status(ym2612_context * context, uint32_t cycle, uint32_t port) |
1012 } | 1168 { |
1013 | 1169 uint8_t status; |
1014 uint8_t ym_read_status(ym2612_context * context) | 1170 port &= context->status_address_mask; |
1015 { | 1171 if (port) { |
1016 return context->status; | 1172 if (context->last_status_cycle != CYCLE_NEVER && cycle - context->last_status_cycle > context->invalid_status_decay) { |
1173 context->last_status = 0; | |
1174 } | |
1175 status = context->last_status; | |
1176 } else { | |
1177 status = context->status; | |
1178 if (cycle >= context->busy_start && cycle < context->busy_start + context->busy_cycles) { | |
1179 status |= 0x80; | |
1180 } | |
1181 context->last_status = status; | |
1182 context->last_status_cycle = cycle; | |
1183 } | |
1184 return status; | |
1185 | |
1017 } | 1186 } |
1018 | 1187 |
1019 void ym_print_channel_info(ym2612_context *context, int channel) | 1188 void ym_print_channel_info(ym2612_context *context, int channel) |
1020 { | 1189 { |
1021 ym_channel *chan = context->channels + channel; | 1190 ym_channel *chan = context->channels + channel; |
1123 save_int8(buf, context->status); | 1292 save_int8(buf, context->status); |
1124 save_int8(buf, context->selected_reg); | 1293 save_int8(buf, context->selected_reg); |
1125 save_int8(buf, context->selected_part); | 1294 save_int8(buf, context->selected_part); |
1126 save_int32(buf, context->current_cycle); | 1295 save_int32(buf, context->current_cycle); |
1127 save_int32(buf, context->write_cycle); | 1296 save_int32(buf, context->write_cycle); |
1128 save_int32(buf, context->busy_cycles); | 1297 save_int32(buf, context->busy_start); |
1298 save_int32(buf, context->last_status_cycle); | |
1299 save_int32(buf, context->invalid_status_decay); | |
1300 save_int8(buf, context->last_status); | |
1129 } | 1301 } |
1130 | 1302 |
1131 void ym_deserialize(deserialize_buffer *buf, void *vcontext) | 1303 void ym_deserialize(deserialize_buffer *buf, void *vcontext) |
1132 { | 1304 { |
1133 ym2612_context *context = vcontext; | 1305 ym2612_context *context = vcontext; |
1198 context->status = load_int8(buf); | 1370 context->status = load_int8(buf); |
1199 context->selected_reg = load_int8(buf); | 1371 context->selected_reg = load_int8(buf); |
1200 context->selected_part = load_int8(buf); | 1372 context->selected_part = load_int8(buf); |
1201 context->current_cycle = load_int32(buf); | 1373 context->current_cycle = load_int32(buf); |
1202 context->write_cycle = load_int32(buf); | 1374 context->write_cycle = load_int32(buf); |
1203 context->busy_cycles = load_int32(buf); | 1375 context->busy_start = load_int32(buf); |
1204 } | 1376 if (buf->size > buf->cur_pos) { |
1377 context->last_status_cycle = load_int32(buf); | |
1378 context->invalid_status_decay = load_int32(buf); | |
1379 context->last_status = load_int8(buf); | |
1380 } else { | |
1381 context->last_status = context->status; | |
1382 context->last_status_cycle = context->write_cycle; | |
1383 } | |
1384 } |