Mercurial > repos > blastem
comparison ymz263b.c @ 2466:b5640ac9aea9
Initial stab at PCM/ADPCM support in YMZ263B emulation
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 24 Feb 2024 20:41:02 -0800 |
parents | a25e8f304343 |
children | bf8a77a8ddc4 |
comparison
equal
deleted
inserted
replaced
2465:b0408f38f464 | 2466:b5640ac9aea9 |
---|---|
34 | 34 |
35 #define TIMER_RUN_MASK (BIT_ST0|BIT_ST1|BIT_ST2) | 35 #define TIMER_RUN_MASK (BIT_ST0|BIT_ST1|BIT_ST2) |
36 #define TIMER_INT_MASK (BIT_T0_MSK|BIT_T1_MSK|BIT_T2_MSK) | 36 #define TIMER_INT_MASK (BIT_T0_MSK|BIT_T1_MSK|BIT_T2_MSK) |
37 | 37 |
38 //YMZ_PCM_PLAY_CTRL | 38 //YMZ_PCM_PLAY_CTRL |
39 #define BIT_ADP_ST 0x01 | |
40 #define BIT_PLY_REC 0x02 | |
41 #define BIT_PCM 0x04 | |
42 #define BIT_PAN_L 0x20 | |
43 #define BIT_PAN_R 0x40 | |
39 #define BIT_ADP_RST 0x80 | 44 #define BIT_ADP_RST 0x80 |
45 | |
46 //YMZ_PCM_FIFO_CTRL | |
47 #define BIT_DMA_ENB 0x01 | |
48 #define BIT_MSK_FIF 0x02 | |
49 #define BIT_DMA_MOD 0x80 | |
40 | 50 |
41 //YMZ_MIDI_CTRL | 51 //YMZ_MIDI_CTRL |
42 #define BIT_MSK_RRQ 0x01 | 52 #define BIT_MSK_RRQ 0x01 |
43 #define BIT_MRC_RST 0x02 | 53 #define BIT_MRC_RST 0x02 |
44 #define BIT_MSK_TRQ 0x04 | 54 #define BIT_MSK_TRQ 0x04 |
53 #define STATUS_T0 0x10 | 63 #define STATUS_T0 0x10 |
54 #define STATUS_T1 0x20 | 64 #define STATUS_T1 0x20 |
55 #define STATUS_T2 0x40 | 65 #define STATUS_T2 0x40 |
56 #define STATUS_OV 0x80 | 66 #define STATUS_OV 0x80 |
57 | 67 |
68 #define TIMER_DIVIDER 32 | |
58 #define MIDI_BYTE_DIVIDER 170 | 69 #define MIDI_BYTE_DIVIDER 170 |
70 #define PCM_BASE_DIVIDER 12 | |
59 | 71 |
60 #define FIFO_EMPTY 255 | 72 #define FIFO_EMPTY 255 |
61 void ymz263b_init(ymz263b *ymz, uint32_t clock_divider) | 73 void ymz263b_init(ymz263b *ymz, uint32_t master_clock, uint32_t clock_divider) |
62 { | 74 { |
63 memset(ymz, 0, sizeof(*ymz)); | 75 memset(ymz, 0, sizeof(*ymz)); |
64 ymz->clock_inc = clock_divider * 32; | 76 ymz->clock_inc = clock_divider * TIMER_DIVIDER; |
77 ymz->audio = render_audio_source("YMZ263B", master_clock, ymz->clock_inc * PCM_BASE_DIVIDER, 2); | |
65 ymz->base_regs[YMZ_SELT] = 1; | 78 ymz->base_regs[YMZ_SELT] = 1; |
66 ymz->pcm[0].regs[0] = BIT_ADP_RST; | 79 ymz->pcm[0].regs[0] = BIT_ADP_RST; |
67 ymz->pcm[1].regs[0] = BIT_ADP_RST; | 80 ymz->pcm[1].regs[0] = BIT_ADP_RST; |
81 ymz->pcm[0].counter = 1; | |
82 ymz->pcm[0].fifo_read = FIFO_EMPTY; | |
83 ymz->pcm[1].counter = 1; | |
84 ymz->pcm[1].fifo_read = FIFO_EMPTY; | |
68 ymz->midi_regs[0] = BIT_MTR_RST | BIT_MRC_RST; | 85 ymz->midi_regs[0] = BIT_MTR_RST | BIT_MRC_RST; |
69 ymz->midi_trs.read = ymz->midi_rcv.read = FIFO_EMPTY; | 86 ymz->midi_trs.read = ymz->midi_rcv.read = FIFO_EMPTY; |
70 ymz->status = 0; | 87 ymz->status = 0; |
88 ymz->pcm_counter = PCM_BASE_DIVIDER; | |
71 } | 89 } |
72 | 90 |
73 static uint8_t fifo_empty(ymz_midi_fifo *fifo) | 91 static uint8_t fifo_empty(ymz_midi_fifo *fifo) |
74 { | 92 { |
75 return fifo->read == FIFO_EMPTY; | 93 return fifo->read == FIFO_EMPTY; |
103 } | 121 } |
104 if (fifo->read == fifo->write) { | 122 if (fifo->read == fifo->write) { |
105 return 16; | 123 return 16; |
106 } | 124 } |
107 return (fifo->write - fifo->read) & 15; | 125 return (fifo->write - fifo->read) & 15; |
126 } | |
127 | |
128 static uint8_t pcm_fifo_empty(ymz263b_pcm *pcm) | |
129 { | |
130 return pcm->fifo_read == FIFO_EMPTY; | |
131 } | |
132 | |
133 static uint16_t pcm_fifo_read(ymz263b_pcm *pcm, uint8_t nibbles) | |
134 { | |
135 uint16_t ret = 0; | |
136 for (; nibbles && !pcm_fifo_empty(pcm); nibbles--) | |
137 { | |
138 ret <<= 4; | |
139 if (pcm->nibble) { | |
140 ret |= pcm->fifo[pcm->fifo_read++] & 0xF; | |
141 pcm->fifo_read &= sizeof(pcm->fifo) - 1; | |
142 pcm->nibble = 0; | |
143 if (pcm->fifo_read == pcm->fifo_write) { | |
144 pcm->fifo_read = FIFO_EMPTY; | |
145 } | |
146 } else { | |
147 ret |= pcm->fifo[pcm->fifo_read] >> 4; | |
148 pcm->nibble = 1; | |
149 } | |
150 } | |
151 return ret; | |
152 } | |
153 | |
154 static uint8_t pcm_fifo_write(ymz263b_pcm *pcm, uint8_t nibbles, uint16_t value) | |
155 { | |
156 uint8_t overflow = 0; | |
157 value <<= (4 - nibbles) * 4; | |
158 for (; nibbles; nibbles--) | |
159 { | |
160 if (pcm->nibble_write) { | |
161 pcm->fifo[pcm->fifo_write++] |= value >> 12; | |
162 pcm->fifo_write &= sizeof(pcm->fifo) - 1; | |
163 pcm->nibble_write = 0; | |
164 } else { | |
165 if (pcm->fifo_read == FIFO_EMPTY) { | |
166 pcm->fifo_read = pcm->fifo_write; | |
167 } else if (pcm->fifo_read == pcm->fifo_write) { | |
168 overflow = 1; | |
169 } | |
170 pcm->fifo[pcm->fifo_write] = value >> 8 & 0xF0; | |
171 pcm->nibble_write = 1; | |
172 } | |
173 value <<= 4; | |
174 } | |
175 return overflow; | |
176 } | |
177 | |
178 static uint8_t pcm_fifo_free(ymz263b_pcm *pcm) | |
179 { | |
180 if (pcm->fifo_read == FIFO_EMPTY) { | |
181 return sizeof(pcm->fifo); | |
182 } | |
183 return (pcm->fifo_read - pcm->fifo_write) & (sizeof(pcm->fifo) - 1); | |
184 } | |
185 | |
186 static uint8_t pcm_dividers[] = {1, 2, 4, 6, 8}; | |
187 static void ymz263b_pcm_run(ymz263b *ymz, ymz263b_pcm *pcm, int16_t *output) | |
188 { | |
189 if ((pcm->regs[0] & (BIT_ADP_RST|BIT_ADP_ST)) != BIT_ADP_ST) { | |
190 //PCM channel is either in reset or not started | |
191 return; | |
192 } | |
193 pcm->counter--; | |
194 if (!pcm->counter) { | |
195 uint8_t fs = pcm->regs[0] >> 3 & 3; | |
196 if (!(pcm->regs[0] & BIT_PCM)) { | |
197 //ADPCM can't use 44.1 kHz, but gains 5.5125 kHz | |
198 fs++; | |
199 } | |
200 pcm->counter = pcm_dividers[fs]; | |
201 uint8_t nibbles = (pcm->regs[3] >> 5 & 3) + 2; | |
202 if (nibbles > 4) { | |
203 //4-bit format is encoded as the highest value for some reason | |
204 nibbles = 1; | |
205 } | |
206 //adlib driver suggests that FMT should be 3 for 4-bit ADPCM, but Copera games seem to use zero | |
207 //maybe FMT is ignored for ADPCM mode? | |
208 if (!(pcm->regs[0] & BIT_PCM)) { | |
209 nibbles = 1; | |
210 } | |
211 //adlib driver sets SELF to 5 for playback to trigger int "when less than 32 bytes in fifo" aka 96 bytes free | |
212 //adlib driver sets SELF to 3 for recording to trigger int "when more than 64 bytes in fifo" aka 64 bytes free | |
213 uint8_t fifo_threshold = ((pcm->regs[3] >> 2 & 7) + 1) << 4; | |
214 if (pcm->regs[0] & BIT_PLY_REC) { | |
215 //Playback mode | |
216 uint16_t sample = pcm_fifo_read(pcm, nibbles); | |
217 if (pcm->regs[0] & BIT_PCM) { | |
218 //TODO: Presumably SELT bit impacts this | |
219 if (sample & (1 << (nibbles * 4 - 1))) { | |
220 sample |= 0xFFF << (nibbles * 4); | |
221 } | |
222 switch (nibbles) | |
223 { | |
224 case 1: | |
225 sample <<= 8; | |
226 break; | |
227 case 2: | |
228 sample <<= 4; | |
229 break; | |
230 case 4: | |
231 //PCem's code seems to imply the "hole" is in the middle | |
232 //but that's ugly so hoping it's incorrect | |
233 sample >>= 4; | |
234 break; | |
235 } | |
236 pcm->output = sample; | |
237 } else { | |
238 //Values taken from YMFM 2610 ADPCM-A implementation | |
239 //They are almost certainly wrong for YMZ263B | |
240 static const int16_t mults[49] = { | |
241 16, 17, 19, 21, 23, 25, 28, | |
242 31, 34, 37, 41, 45, 50, 55, | |
243 60, 66, 73, 80, 88, 97, 107, | |
244 118, 130, 143, 157, 173, 190, 209, | |
245 230, 253, 279, 307, 337, 371, 408, | |
246 449, 494, 544, 598, 658, 724, 796, | |
247 876, 963, 1060, 1166, 1282, 1411, 1552 | |
248 }; | |
249 static const int8_t index_deltas[8] = { | |
250 -1, -1, -1, -1, 2, 5, 7, 9 | |
251 }; | |
252 uint16_t mag = sample & 7; | |
253 int16_t delta = (((mag << 1) + 1) * mults[pcm->adpcm_mul_index]) >> 3; | |
254 if (sample & 8) { | |
255 delta = -delta; | |
256 } | |
257 uint8_t old_index = pcm->adpcm_mul_index; | |
258 pcm->output += delta; | |
259 if (pcm->adpcm_mul_index || mag > 3) { | |
260 pcm->adpcm_mul_index += index_deltas[mag]; | |
261 if (pcm->adpcm_mul_index >= sizeof(mults)) { | |
262 pcm->adpcm_mul_index = sizeof(mults) - 1; | |
263 } | |
264 } | |
265 int16_t output = pcm->output; | |
266 //Supposedly the YM2610 and YM2608 wrap around rather than clamp | |
267 //but since my tables have the wrong values I need to clamp | |
268 //in order to get something resembling the correct output | |
269 if (output > 0x7FF) { | |
270 pcm->output = 0x7FF; | |
271 } else if (output < -0x800) { | |
272 pcm->output = -0x800; | |
273 } | |
274 //printf("Sample %X, mag %X, delta %d, old index %d, new index %d, out %d\n", sample, mag, delta, old_index, pcm->adpcm_mul_index, (int16_t)pcm->output); | |
275 } | |
276 if (pcm->output & 0x800) { | |
277 pcm->output |= 0xF000; | |
278 } else { | |
279 pcm->output &= 0x0FFF; | |
280 } | |
281 if (pcm_fifo_free(pcm) > fifo_threshold) { | |
282 ymz->status |= pcm == &ymz->pcm[0] ? STATUS_FIF1 : STATUS_FIF2; | |
283 } | |
284 } else { | |
285 //Recording mode | |
286 //TODO: support recording actual audio input | |
287 if (pcm_fifo_write(pcm, nibbles, 0)) { | |
288 ymz->status |= STATUS_OV; | |
289 } | |
290 if (pcm_fifo_free(pcm) < fifo_threshold) { | |
291 ymz->status |= pcm == &ymz->pcm[0] ? STATUS_FIF1 : STATUS_FIF2; | |
292 } | |
293 } | |
294 | |
295 } | |
296 | |
297 if (pcm->regs[0] & BIT_PLY_REC) { | |
298 //TODO: Volume | |
299 if (pcm->regs[0] & BIT_PAN_L) { | |
300 output[0] += pcm->output; | |
301 } | |
302 if (pcm->regs[0] & BIT_PAN_R) { | |
303 output[1] += pcm->output; | |
304 } | |
305 } | |
108 } | 306 } |
109 | 307 |
110 void ymz263b_run(ymz263b *ymz, uint32_t target_cycle) | 308 void ymz263b_run(ymz263b *ymz, uint32_t target_cycle) |
111 { | 309 { |
112 uint8_t timer_ctrl = ymz->base_regs[YMZ_TIMER_CTRL]; | 310 uint8_t timer_ctrl = ymz->base_regs[YMZ_TIMER_CTRL]; |
153 if (fifo_empty(&ymz->midi_trs)) { | 351 if (fifo_empty(&ymz->midi_trs)) { |
154 ymz->status |= STATUS_TRQ; | 352 ymz->status |= STATUS_TRQ; |
155 } | 353 } |
156 } | 354 } |
157 } | 355 } |
158 } | 356 ymz->pcm_counter--; |
357 if (!ymz->pcm_counter) { | |
358 ymz->pcm_counter = PCM_BASE_DIVIDER; | |
359 int16_t output[2] = {0, 0}; | |
360 ymz263b_pcm_run(ymz, &ymz->pcm[0], output); | |
361 ymz263b_pcm_run(ymz, &ymz->pcm[1], output); | |
362 render_put_stereo_sample(ymz->audio, output[0], output[1]); | |
363 } | |
364 } | |
365 } | |
366 | |
367 static uint32_t predict_fifo_thres(ymz263b *ymz, ymz263b_pcm *pcm) | |
368 { | |
369 if ((pcm->regs[0] & (BIT_ADP_RST|BIT_ADP_ST)) != BIT_ADP_ST) { | |
370 //PCM channel is either in reset or not started | |
371 return CYCLE_NEVER; | |
372 } | |
373 uint32_t next_pcm_cycle = ymz->cycle + ymz->pcm_counter * ymz->clock_inc; | |
374 next_pcm_cycle += (pcm->counter - 1) * PCM_BASE_DIVIDER * ymz->clock_inc; | |
375 uint32_t fifo_free = pcm_fifo_free(pcm); | |
376 //convert to nibbles | |
377 fifo_free <<= 1; | |
378 uint32_t fifo_threshold = ((pcm->regs[3] >> 2 & 7) + 1) << 5; | |
379 uint32_t diff; | |
380 if (pcm->regs[0] & BIT_PLY_REC) { | |
381 if (pcm->nibble) { | |
382 fifo_free++; | |
383 } | |
384 diff = fifo_threshold - fifo_free + 1; | |
385 } else { | |
386 if (pcm->nibble_write) { | |
387 fifo_free--; | |
388 } | |
389 diff = fifo_free - fifo_threshold + 1; | |
390 } | |
391 uint32_t nibbles_per_samp = (pcm->regs[3] >> 5 & 3) + 2; | |
392 if (nibbles_per_samp > 4) { | |
393 //4-bit format is encoded as the highest value for some reason | |
394 nibbles_per_samp = 1; | |
395 } | |
396 uint8_t fs = pcm->regs[0] >> 3 & 3; | |
397 if (!(pcm->regs[0] & BIT_PCM)) { | |
398 //ADPCM can't use 44.1 kHz, but gains 5.5125 kHz | |
399 fs++; | |
400 //see note in PCM playback code | |
401 nibbles_per_samp = 1; | |
402 } | |
403 diff /= nibbles_per_samp; | |
404 | |
405 next_pcm_cycle += diff * PCM_BASE_DIVIDER * pcm_dividers[fs] * ymz->clock_inc; | |
406 return next_pcm_cycle; | |
159 } | 407 } |
160 | 408 |
161 uint32_t ymz263b_next_int(ymz263b *ymz) | 409 uint32_t ymz263b_next_int(ymz263b *ymz) |
162 { | 410 { |
163 //TODO: Handle FIFO and MIDI receive interrupts | 411 //TODO: Handle MIDI receive interrupts |
164 uint8_t enabled_ints = (~ymz->base_regs[YMZ_TIMER_CTRL]) & TIMER_INT_MASK; | 412 uint8_t enabled_ints = (~ymz->base_regs[YMZ_TIMER_CTRL]) & TIMER_INT_MASK; |
165 if (!(ymz->base_regs[YMZ_MIDI_CTRL] & (BIT_MTR_RST|BIT_MSK_TRQ))) { | 413 if (!(ymz->base_regs[YMZ_MIDI_CTRL] & (BIT_MTR_RST|BIT_MSK_TRQ))) { |
166 enabled_ints |= STATUS_TRQ; | 414 enabled_ints |= STATUS_TRQ; |
167 } | 415 } |
416 if (!(ymz->pcm[0].regs[3] & BIT_MSK_FIF)) { | |
417 enabled_ints |= STATUS_FIF1; | |
418 } | |
419 if (!(ymz->pcm[1].regs[3] & BIT_MSK_FIF)) { | |
420 enabled_ints |= STATUS_FIF2; | |
421 } | |
168 if (!enabled_ints) { | 422 if (!enabled_ints) { |
169 return CYCLE_NEVER; | 423 return CYCLE_NEVER; |
170 } | 424 } |
171 //Handle currently pending interrupts | 425 //Handle currently pending interrupts |
172 if (enabled_ints & ymz->status) { | 426 if (enabled_ints & ymz->status) { |
173 return ymz->cycle; | 427 return ymz->cycle; |
174 } | 428 } |
429 | |
175 uint32_t ret = CYCLE_NEVER; | 430 uint32_t ret = CYCLE_NEVER; |
176 if (enabled_ints & STATUS_TRQ) { | 431 if (enabled_ints & STATUS_TRQ) { |
177 uint8_t bytes = fifo_size(&ymz->midi_trs); | 432 uint8_t bytes = fifo_size(&ymz->midi_trs); |
178 if (bytes) { | 433 if (bytes) { |
179 ret = ymz->cycle + (ymz->midi_transmit + 1) * ymz->clock_inc; | 434 ret = ymz->cycle + (ymz->midi_transmit + 1) * ymz->clock_inc; |
180 if (bytes > 1) { | 435 if (bytes > 1) { |
181 ret += MIDI_BYTE_DIVIDER * ymz->clock_inc * (bytes - 1); | 436 ret += MIDI_BYTE_DIVIDER * ymz->clock_inc * (bytes - 1); |
182 } | 437 } |
183 } | 438 } |
184 } | 439 } |
440 | |
441 if (enabled_ints & STATUS_FIF1) { | |
442 uint32_t next_pcm = predict_fifo_thres(ymz, &ymz->pcm[0]); | |
443 if (next_pcm < ret) { | |
444 ret = next_pcm; | |
445 } | |
446 } | |
447 if (enabled_ints & STATUS_FIF2) { | |
448 uint32_t next_pcm = predict_fifo_thres(ymz, &ymz->pcm[1]); | |
449 if (next_pcm < ret) { | |
450 ret = next_pcm; | |
451 } | |
452 } | |
453 | |
185 enabled_ints >>= 4; | 454 enabled_ints >>= 4; |
186 //If timers aren't already expired, interrupts can't fire unless the timers are enabled | 455 //If timers aren't already expired, interrupts can't fire unless the timers are enabled |
187 enabled_ints &= ymz->base_regs[YMZ_TIMER_CTRL]; | 456 enabled_ints &= ymz->base_regs[YMZ_TIMER_CTRL]; |
188 if (!(ymz->base_regs[YMZ_TIMER_CTRL] & BIT_STBC)) { | 457 if (!(ymz->base_regs[YMZ_TIMER_CTRL] & BIT_STBC)) { |
189 //Timer 1 and Timer 2 depend on the base timer | 458 //Timer 1 and Timer 2 depend on the base timer |
226 | 495 |
227 void ymz263b_data_write(ymz263b *ymz, uint32_t channel, uint8_t value) | 496 void ymz263b_data_write(ymz263b *ymz, uint32_t channel, uint8_t value) |
228 { | 497 { |
229 if (channel) { | 498 if (channel) { |
230 if (ymz->address >= YMZ_PCM_PLAY_CTRL && ymz->address < YMZ_MIDI_CTRL) { | 499 if (ymz->address >= YMZ_PCM_PLAY_CTRL && ymz->address < YMZ_MIDI_CTRL) { |
500 if (ymz->address == YMZ_PCM_PLAY_CTRL) { | |
501 if (((value ^ ymz->pcm[1].regs[0]) & ymz->pcm[1].regs[0]) & BIT_ADP_RST) { | |
502 //Perform reset on falling edge of reset bit | |
503 ymz->pcm[1].counter = 1; | |
504 ymz->pcm[1].fifo_read = FIFO_EMPTY; | |
505 ymz->pcm[1].nibble = ymz->pcm[1].nibble_write = 0; | |
506 ymz->pcm[1].output = 0; | |
507 ymz->pcm[1].adpcm_mul_index = 0; | |
508 } | |
509 } | |
231 ymz->pcm[1].regs[ymz->address - YMZ_PCM_PLAY_CTRL] = value; | 510 ymz->pcm[1].regs[ymz->address - YMZ_PCM_PLAY_CTRL] = value; |
511 if (ymz->address == YMZ_PCM_DATA) { | |
512 pcm_fifo_write(&ymz->pcm[1], 2, value); | |
513 //Does an overflow here set the overflow statu sflag? | |
514 } | |
232 } | 515 } |
233 } else { | 516 } else { |
234 if (ymz->address < YMZ_PCM_PLAY_CTRL) { | 517 if (ymz->address < YMZ_PCM_PLAY_CTRL) { |
235 ymz->base_regs[ymz->address] = value; | 518 ymz->base_regs[ymz->address] = value; |
236 } else if (ymz->address < YMZ_MIDI_CTRL) { | 519 } else if (ymz->address < YMZ_MIDI_CTRL) { |
520 if (((value ^ ymz->pcm[0].regs[0]) & ymz->pcm[1].regs[0]) & BIT_ADP_RST) { | |
521 //Perform reset on falling edge of reset bit | |
522 ymz->pcm[0].counter = 1; | |
523 ymz->pcm[0].fifo_read = FIFO_EMPTY; | |
524 ymz->pcm[0].nibble = ymz->pcm[1].nibble_write = 0; | |
525 ymz->pcm[0].output = 0; | |
526 ymz->pcm[0].adpcm_mul_index = 0; | |
527 } | |
237 ymz->pcm[0].regs[ymz->address - YMZ_PCM_PLAY_CTRL] = value; | 528 ymz->pcm[0].regs[ymz->address - YMZ_PCM_PLAY_CTRL] = value; |
529 if (ymz->address == YMZ_PCM_DATA) { | |
530 pcm_fifo_write(&ymz->pcm[0], 2, value); | |
531 //Does an overflow here set the overflow statu sflag? | |
532 } | |
238 } else { | 533 } else { |
239 ymz->midi_regs[ymz->address - YMZ_MIDI_CTRL] = value; | 534 ymz->midi_regs[ymz->address - YMZ_MIDI_CTRL] = value; |
240 if (ymz->address == YMZ_MIDI_DATA) { | 535 if (ymz->address == YMZ_MIDI_DATA) { |
241 ymz->status &= ~STATUS_TRQ; | 536 ymz->status &= ~STATUS_TRQ; |
242 if (fifo_empty(&ymz->midi_trs)) { | 537 if (fifo_empty(&ymz->midi_trs)) { |
251 uint8_t ymz263b_data_read(ymz263b *ymz, uint32_t channel) | 546 uint8_t ymz263b_data_read(ymz263b *ymz, uint32_t channel) |
252 { | 547 { |
253 //TODO: Supposedly only a few registers are actually readable | 548 //TODO: Supposedly only a few registers are actually readable |
254 if (channel) { | 549 if (channel) { |
255 if (ymz->address >= YMZ_PCM_PLAY_CTRL && ymz->address < YMZ_MIDI_CTRL) { | 550 if (ymz->address >= YMZ_PCM_PLAY_CTRL && ymz->address < YMZ_MIDI_CTRL) { |
551 if (ymz->address == YMZ_PCM_DATA) { | |
552 return pcm_fifo_read(&ymz->pcm[1], 2); | |
553 } | |
256 return ymz->pcm[1].regs[ymz->address - YMZ_PCM_PLAY_CTRL]; | 554 return ymz->pcm[1].regs[ymz->address - YMZ_PCM_PLAY_CTRL]; |
257 } | 555 } |
258 } else { | 556 } else { |
259 if (ymz->address < YMZ_PCM_PLAY_CTRL) { | 557 if (ymz->address < YMZ_PCM_PLAY_CTRL) { |
260 return ymz->base_regs[ymz->address]; | 558 return ymz->base_regs[ymz->address]; |
261 } else if (ymz->address < YMZ_MIDI_CTRL) { | 559 } else if (ymz->address < YMZ_MIDI_CTRL) { |
560 if (ymz->address == YMZ_PCM_DATA) { | |
561 return pcm_fifo_read(&ymz->pcm[0], 2); | |
562 } | |
262 return ymz->pcm[0].regs[ymz->address - YMZ_PCM_PLAY_CTRL]; | 563 return ymz->pcm[0].regs[ymz->address - YMZ_PCM_PLAY_CTRL]; |
263 } else { | 564 } else { |
264 return ymz->midi_regs[ymz->address - YMZ_MIDI_CTRL]; | 565 return ymz->midi_regs[ymz->address - YMZ_MIDI_CTRL]; |
265 } | 566 } |
266 } | 567 } |