comparison ym2612.c @ 364:62177cc39049

Incredibly broken YM2612 support plus a fix to Z80 bus request
author Mike Pavone <pavone@retrodev.com>
date Wed, 29 May 2013 00:57:19 -0700
parents b7c3facee762
children 3ba3b6656fff
comparison
equal deleted inserted replaced
363:c708dea45f8b 364:62177cc39049
1 #include <string.h> 1 #include <string.h>
2 #include <math.h> 2 #include <math.h>
3 #include <stdio.h> 3 #include <stdio.h>
4 #include <stdlib.h>
4 #include "ym2612.h" 5 #include "ym2612.h"
6 #include "render.h"
5 7
6 #define BUSY_CYCLES 17 8 #define BUSY_CYCLES 17
7 #define TIMERA_UPDATE_PERIOD 144 9 #define OP_UPDATE_PERIOD 144
8 10
9 enum { 11 enum {
10 REG_TIMERA_HIGH = 0x24, 12 REG_TIMERA_HIGH = 0x24,
11 REG_TIMERA_LOW, 13 REG_TIMERA_LOW,
12 REG_TIMERB, 14 REG_TIMERB,
73 }; 75 };
74 76
75 uint16_t rate_table[64]; 77 uint16_t rate_table[64];
76 78
77 #define MAX_ENVELOPE 0xFFC 79 #define MAX_ENVELOPE 0xFFC
78 80 #define YM_DIVIDER 2
79 81
80 uint16_t round_fixed_point(double value, int dec_bits) 82 uint16_t round_fixed_point(double value, int dec_bits)
81 { 83 {
82 return value * (1 << dec_bits) + 0.5; 84 return value * (1 << dec_bits) + 0.5;
83 } 85 }
84 86
85 void ym_init(ym2612_context * context) 87 void ym_init(ym2612_context * context, uint32_t sample_rate, uint32_t clock_rate, uint32_t sample_limit)
86 { 88 {
87 memset(context, 0, sizeof(*context)); 89 memset(context, 0, sizeof(*context));
90 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2);
91 context->back_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2);
92 context->buffer_inc = (double)sample_rate / (double)(clock_rate/OP_UPDATE_PERIOD);
93 context->sample_limit = sample_limit*2;
88 for (int i = 0; i < NUM_OPERATORS; i++) { 94 for (int i = 0; i < NUM_OPERATORS; i++) {
89 context->operators[i].envelope = MAX_ENVELOPE; 95 context->operators[i].envelope = MAX_ENVELOPE;
90 context->operators[i].env_phase = PHASE_RELEASE; 96 context->operators[i].env_phase = PHASE_RELEASE;
91 } 97 }
92 if (!did_tbl_init) { 98 if (!did_tbl_init) {
132 void ym_run(ym2612_context * context, uint32_t to_cycle) 138 void ym_run(ym2612_context * context, uint32_t to_cycle)
133 { 139 {
134 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle); 140 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle);
135 //TODO: Fix channel update order OR remap channels in register write 141 //TODO: Fix channel update order OR remap channels in register write
136 for (; context->current_cycle < to_cycle; context->current_cycle += 6) { 142 for (; context->current_cycle < to_cycle; context->current_cycle += 6) {
137 uint32_t update_cyc = context->current_cycle % 144;
138 //Update timers at beginning of 144 cycle period 143 //Update timers at beginning of 144 cycle period
139 if (!update_cyc && context->timer_control & BIT_TIMERA_ENABLE) { 144 if (!context->current_op && context->timer_control & BIT_TIMERA_ENABLE) {
140 if (context->timer_a) { 145 if (context->timer_a) {
141 context->timer_a--; 146 context->timer_a--;
142 } else { 147 } else {
143 if (context->timer_control & BIT_TIMERA_OVEREN) { 148 if (context->timer_control & BIT_TIMERA_OVEREN) {
144 context->status |= BIT_STATUS_TIMERA; 149 context->status |= BIT_STATUS_TIMERA;
145 } 150 }
146 context->timer_a = context->timer_a_load; 151 context->timer_a = context->timer_a_load;
147 } 152 }
148 if (context->timer_control & BIT_TIMERB_ENABLE) { 153 if (context->timer_control & BIT_TIMERB_ENABLE) {
149 uint32_t b_cyc = (context->current_cycle / 144) % 16; 154 uint32_t b_cyc = (context->current_cycle / OP_UPDATE_PERIOD) % 16;
150 if (!b_cyc) { 155 if (!b_cyc) {
151 if (context->timer_b) { 156 if (context->timer_b) {
152 context->timer_b--; 157 context->timer_b--;
153 } else { 158 } else {
154 if (context->timer_control & BIT_TIMERB_OVEREN) { 159 if (context->timer_control & BIT_TIMERB_OVEREN) {
158 } 163 }
159 } 164 }
160 } 165 }
161 } 166 }
162 //Update Envelope Generator 167 //Update Envelope Generator
163 if (update_cyc == 0 || update_cyc == 72) { 168 if (!(context->current_op % 3)) {
164 uint32_t env_cyc = context->current_cycle / 72; 169 uint32_t env_cyc = context->env_counter;
165 uint32_t op = env_cyc % 24; 170 uint32_t op = context->current_env_op;
166 env_cyc /= 24;
167 ym_operator * operator = context->operators + op; 171 ym_operator * operator = context->operators + op;
168 ym_channel * channel = context->channels + op/4; 172 ym_channel * channel = context->channels + op/4;
169 uint8_t rate; 173 uint8_t rate;
170 for(;;) { 174 for(;;) {
171 rate = operator->rates[operator->env_phase]; 175 rate = operator->rates[operator->env_phase];
212 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) { 216 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) {
213 operator->envelope = operator->sustain_level; 217 operator->envelope = operator->sustain_level;
214 operator->env_phase = PHASE_SUSTAIN; 218 operator->env_phase = PHASE_SUSTAIN;
215 } 219 }
216 } 220 }
217 221 }
218 222 context->current_env_op++;
223 if (context->current_env_op == NUM_OPERATORS) {
224 context->current_env_op = 0;
225 context->env_counter++;
219 } 226 }
220 } 227 }
221 228
222 //Update Phase Generator 229 //Update Phase Generator
223 uint32_t channel = update_cyc / 24; 230 uint32_t channel = context->current_op / 4;
224 if (channel != 5 || !context->dac_enable) { 231 if (channel != 5 || !context->dac_enable) {
225 uint32_t op = (update_cyc) / 6; 232 uint32_t op = context->current_op;
226 //printf("updating operator %d of channel %d\n", op, channel); 233 //printf("updating operator %d of channel %d\n", op, channel);
227 ym_operator * operator = context->operators + op; 234 ym_operator * operator = context->operators + op;
228 ym_channel * chan = context->channels + channel; 235 ym_channel * chan = context->channels + channel;
229 //TODO: Modulate phase by LFO if necessary 236 //TODO: Modulate phase by LFO if necessary
230 operator->phase_counter += operator->phase_inc; 237 operator->phase_counter += operator->phase_inc;
301 chan->output = output; 308 chan->output = output;
302 } 309 }
303 } 310 }
304 //puts("operator update done"); 311 //puts("operator update done");
305 } 312 }
313 context->current_op++;
314 if (context->current_op == NUM_OPERATORS) {
315 context->current_op = 0;
316 context->buffer_fraction += context->buffer_inc;
317 if (context->buffer_fraction > 1.0) {
318 context->buffer_fraction -= 1.0;
319 context->audio_buffer[context->buffer_pos] = 0;
320 context->audio_buffer[context->buffer_pos + 1] = 0;
321 for (int i = 0; i < NUM_CHANNELS; i++) {
322 uint16_t value = context->channels[i].output & 0x3FE0;
323 if (value & 0x2000) {
324 value |= 0xC000;
325 }
326 if (context->channels[i].lr & 0x80) {
327 context->audio_buffer[context->buffer_pos] += value / 2;
328 }
329 if (context->channels[i].lr & 0x40) {
330 context->audio_buffer[context->buffer_pos+1] += value / 2;
331 }
332 }
333 context->buffer_pos += 2;
334 if (context->buffer_pos == context->sample_limit) {
335 render_wait_ym(context);
336 }
337 }
338 }
306 } 339 }
307 if (context->current_cycle >= context->write_cycle + BUSY_CYCLES) { 340 if (context->current_cycle >= context->write_cycle + BUSY_CYCLES) {
308 context->status &= 0x7F; 341 context->status &= 0x7F;
309 } 342 }
310 //printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle); 343 //printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle);
311 } 344 }
312 345
313 void ym_address_write_part1(ym2612_context * context, uint8_t address) 346 void ym_address_write_part1(ym2612_context * context, uint8_t address)
314 { 347 {
348 //printf("address_write_part1: %X\n", address);
315 context->selected_reg = address; 349 context->selected_reg = address;
316 context->selected_part = 0; 350 context->selected_part = 0;
317 } 351 }
318 352
319 void ym_address_write_part2(ym2612_context * context, uint8_t address) 353 void ym_address_write_part2(ym2612_context * context, uint8_t address)
320 { 354 {
355 //printf("address_write_part2: %X\n", address);
321 context->selected_reg = address; 356 context->selected_reg = address;
322 context->selected_part = 1; 357 context->selected_part = 1;
323 } 358 }
324 359
325 uint8_t fnum_to_keycode[] = { 360 uint8_t fnum_to_keycode[] = {
391 inc *= operator->multiple; 426 inc *= operator->multiple;
392 } else { 427 } else {
393 //0.5 428 //0.5
394 inc >>= 1; 429 inc >>= 1;
395 } 430 }
431 operator->phase_inc = inc;
396 } 432 }
397 433
398 void ym_data_write(ym2612_context * context, uint8_t value) 434 void ym_data_write(ym2612_context * context, uint8_t value)
399 { 435 {
400 if (context->selected_reg < 0x21 || context->selected_reg > 0xB6 || (context->selected_reg < 0x30 && context->selected_part)) { 436 if (context->selected_reg < 0x21 || context->selected_reg > 0xB6 || (context->selected_reg < 0x30 && context->selected_part)) {
438 break; 474 break;
439 } 475 }
440 case REG_DAC: 476 case REG_DAC:
441 if (context->dac_enable) { 477 if (context->dac_enable) {
442 context->channels[5].output = (((int16_t)value) - 0x80) << 6; 478 context->channels[5].output = (((int16_t)value) - 0x80) << 6;
479 //printf("DAC Write %X(%d)\n", context->channels[5].output, context->channels[5].output);
443 } 480 }
444 break; 481 break;
445 case REG_DAC_ENABLE: 482 case REG_DAC_ENABLE:
483 //printf("DAC Enable: %X\n", value);
446 context->dac_enable = value & 0x80; 484 context->dac_enable = value & 0x80;
447 break; 485 break;
448 } 486 }
449 } else if (context->selected_reg < 0xA0) { 487 } else if (context->selected_reg < 0xA0) {
450 //part 488 //part