summaryrefslogtreecommitdiff
path: root/apps/codecs/libgme/ymdeltat.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libgme/ymdeltat.c')
-rw-r--r--apps/codecs/libgme/ymdeltat.c655
1 files changed, 655 insertions, 0 deletions
diff --git a/apps/codecs/libgme/ymdeltat.c b/apps/codecs/libgme/ymdeltat.c
new file mode 100644
index 0000000000..ea0be59013
--- /dev/null
+++ b/apps/codecs/libgme/ymdeltat.c
@@ -0,0 +1,655 @@
1/*
2**
3** File: ymdeltat.c
4**
5** YAMAHA DELTA-T adpcm sound emulation subroutine
6** used by fmopl.c (Y8950) and fm.c (YM2608 and YM2610/B)
7**
8** Base program is YM2610 emulator by Hiromitsu Shioya.
9** Written by Tatsuyuki Satoh
10** Improvements by Jarek Burczynski (bujar at mame dot net)
11**
12**
13** History:
14**
15** 03-08-2003 Jarek Burczynski:
16** - fixed BRDY flag implementation.
17**
18** 24-07-2003 Jarek Burczynski, Frits Hilderink:
19** - fixed delault value for control2 in YM_DELTAT_ADPCM_Reset
20**
21** 22-07-2003 Jarek Burczynski, Frits Hilderink:
22** - fixed external memory support
23**
24** 15-06-2003 Jarek Burczynski:
25** - implemented CPU -> AUDIO ADPCM synthesis (via writes to the ADPCM data reg $08)
26** - implemented support for the Limit address register
27** - supported two bits from the control register 2 ($01): RAM TYPE (x1 bit/x8 bit), ROM/RAM
28** - implemented external memory access (read/write) via the ADPCM data reg reads/writes
29** Thanks go to Frits Hilderink for the example code.
30**
31** 14-06-2003 Jarek Burczynski:
32** - various fixes to enable proper support for status register flags: BSRDY, PCM BSY, ZERO
33** - modified EOS handling
34**
35** 05-04-2003 Jarek Burczynski:
36** - implemented partial support for external/processor memory on sample replay
37**
38** 01-12-2002 Jarek Burczynski:
39** - fixed first missing sound in gigandes thanks to previous fix (interpolator) by ElSemi
40** - renamed/removed some YM_DELTAT struct fields
41**
42** 28-12-2001 Acho A. Tang
43** - added EOS status report on ADPCM playback.
44**
45** 05-08-2001 Jarek Burczynski:
46** - now_step is initialized with 0 at the start of play.
47**
48** 12-06-2001 Jarek Burczynski:
49** - corrected end of sample bug in YM_DELTAT_ADPCM_CALC.
50** Checked on real YM2610 chip - address register is 24 bits wide.
51** Thanks go to Stefan Jokisch (stefan.jokisch@gmx.de) for tracking down the problem.
52**
53** TO DO:
54** Check size of the address register on the other chips....
55**
56** Version 0.72
57**
58** sound chips that have this unit:
59** YM2608 OPNA
60** YM2610/B OPNB
61** Y8950 MSX AUDIO
62**
63*/
64
65#include "ymdeltat.h"
66#define INLINE __inline
67#define logerror (void)
68
69#define YM_DELTAT_DELTA_MAX (24576)
70#define YM_DELTAT_DELTA_MIN (127)
71#define YM_DELTAT_DELTA_DEF (127)
72
73#define YM_DELTAT_DECODE_RANGE 32768
74#define YM_DELTAT_DECODE_MIN (-(YM_DELTAT_DECODE_RANGE))
75#define YM_DELTAT_DECODE_MAX ((YM_DELTAT_DECODE_RANGE)-1)
76
77
78/* Forecast to next Forecast (rate = *8) */
79/* 1/8 , 3/8 , 5/8 , 7/8 , 9/8 , 11/8 , 13/8 , 15/8 */
80static const INT32 ym_deltat_decode_tableB1[16] ICONST_ATTR = {
81 1, 3, 5, 7, 9, 11, 13, 15,
82 -1, -3, -5, -7, -9, -11, -13, -15,
83};
84/* delta to next delta (rate= *64) */
85/* 0.9 , 0.9 , 0.9 , 0.9 , 1.2 , 1.6 , 2.0 , 2.4 */
86static const INT32 ym_deltat_decode_tableB2[16] ICONST_ATTR = {
87 57, 57, 57, 57, 77, 102, 128, 153,
88 57, 57, 57, 57, 77, 102, 128, 153
89};
90
91#if 0
92void YM_DELTAT_BRDY_callback(YM_DELTAT *DELTAT)
93{
94 logerror("BRDY_callback reached (flag set) !\n");
95
96 /* set BRDY bit in status register */
97 if(DELTAT->status_set_handler)
98 if(DELTAT->status_change_BRDY_bit)
99 (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
100}
101#endif
102
103UINT8 YM_DELTAT_ADPCM_Read(YM_DELTAT *DELTAT)
104{
105 UINT8 v = 0;
106
107 /* external memory read */
108 if ( (DELTAT->portstate & 0xe0)==0x20 )
109 {
110 /* two dummy reads */
111 if (DELTAT->memread)
112 {
113 DELTAT->now_addr = DELTAT->start << 1;
114 DELTAT->memread--;
115 return 0;
116 }
117
118
119 if ( DELTAT->now_addr != (DELTAT->end<<1) )
120 {
121 v = DELTAT->memory[DELTAT->now_addr>>1];
122
123 /*logerror("YM Delta-T memory read $%08x, v=$%02x\n", DELTAT->now_addr >> 1, v);*/
124
125 DELTAT->now_addr+=2; /* two nibbles at a time */
126
127 /* reset BRDY bit in status register, which means we are reading the memory now */
128 if(DELTAT->status_reset_handler)
129 if(DELTAT->status_change_BRDY_bit)
130 (DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
131
132 /* setup a timer that will callback us in 10 master clock cycles for Y8950
133 * in the callback set the BRDY flag to 1 , which means we have another data ready.
134 * For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work.
135 */
136 /* set BRDY bit in status register */
137 if(DELTAT->status_set_handler)
138 if(DELTAT->status_change_BRDY_bit)
139 (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
140 }
141 else
142 {
143 /* set EOS bit in status register */
144 if(DELTAT->status_set_handler)
145 if(DELTAT->status_change_EOS_bit)
146 (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit);
147 }
148 }
149
150 return v;
151}
152
153
154/* 0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */
155static const UINT8 dram_rightshift[4] ICONST_ATTR ={3,0,0,0};
156
157/* DELTA-T ADPCM write register */
158void YM_DELTAT_ADPCM_Write(YM_DELTAT *DELTAT,int r,int v)
159{
160 if(r>=0x10) return;
161 DELTAT->reg[r] = v; /* stock data */
162
163 switch( r )
164 {
165 case 0x00:
166/*
167START:
168 Accessing *external* memory is started when START bit (D7) is set to "1", so
169 you must set all conditions needed for recording/playback before starting.
170 If you access *CPU-managed* memory, recording/playback starts after
171 read/write of ADPCM data register $08.
172
173REC:
174 0 = ADPCM synthesis (playback)
175 1 = ADPCM analysis (record)
176
177MEMDATA:
178 0 = processor (*CPU-managed*) memory (means: using register $08)
179 1 = external memory (using start/end/limit registers to access memory: RAM or ROM)
180
181
182SPOFF:
183 controls output pin that should disable the speaker while ADPCM analysis
184
185RESET and REPEAT only work with external memory.
186
187
188some examples:
189value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning:
190 C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register
191 E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register
192 80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register
193 a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register
194
195 60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08
196 20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08
197
198*/
199 /* handle emulation mode */
200 if(DELTAT->emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610)
201 {
202 v |= 0x20; /* YM2610 always uses external memory and doesn't even have memory flag bit. */
203 }
204
205 DELTAT->portstate = v & (0x80|0x40|0x20|0x10|0x01); /* start, rec, memory mode, repeat flag copy, reset(bit0) */
206
207 if( DELTAT->portstate&0x80 )/* START,REC,MEMDATA,REPEAT,SPOFF,--,--,RESET */
208 {
209 /* set PCM BUSY bit */
210 DELTAT->PCM_BSY = 1;
211
212 /* start ADPCM */
213 DELTAT->now_step = 0;
214 DELTAT->acc = 0;
215 DELTAT->prev_acc = 0;
216 DELTAT->adpcml = 0;
217 DELTAT->adpcmd = YM_DELTAT_DELTA_DEF;
218 DELTAT->now_data = 0;
219
220 }
221
222 if( DELTAT->portstate&0x20 ) /* do we access external memory? */
223 {
224 DELTAT->now_addr = DELTAT->start << 1;
225 DELTAT->memread = 2; /* two dummy reads needed before accesing external memory via register $08*/
226
227 /* if yes, then let's check if ADPCM memory is mapped and big enough */
228 if(DELTAT->memory == 0)
229 {
230 logerror("YM Delta-T ADPCM rom not mapped\n");
231 DELTAT->portstate = 0x00;
232 DELTAT->PCM_BSY = 0;
233 }
234 else
235 {
236 if( DELTAT->end >= DELTAT->memory_size ) /* Check End in Range */
237 {
238 /* logerror("YM Delta-T ADPCM end out of range: $%08x\n", DELTAT->end); */
239 DELTAT->end = DELTAT->memory_size - 1;
240 }
241 if( DELTAT->start >= DELTAT->memory_size ) /* Check Start in Range */
242 {
243 /* logerror("YM Delta-T ADPCM start out of range: $%08x\n", DELTAT->start); */
244 DELTAT->portstate = 0x00;
245 DELTAT->PCM_BSY = 0;
246 }
247 }
248 }
249 else /* we access CPU memory (ADPCM data register $08) so we only reset now_addr here */
250 {
251 DELTAT->now_addr = 0;
252 }
253
254 if( DELTAT->portstate&0x01 )
255 {
256 DELTAT->portstate = 0x00;
257
258 /* clear PCM BUSY bit (in status register) */
259 DELTAT->PCM_BSY = 0;
260
261 /* set BRDY flag */
262 if(DELTAT->status_set_handler)
263 if(DELTAT->status_change_BRDY_bit)
264 (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
265 }
266 break;
267 case 0x01: /* L,R,-,-,SAMPLE,DA/AD,RAMTYPE,ROM */
268 /* handle emulation mode */
269 if(DELTAT->emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610)
270 {
271 v |= 0x01; /* YM2610 always uses ROM as an external memory and doesn't tave ROM/RAM memory flag bit. */
272 }
273
274 DELTAT->pan = &DELTAT->output_pointer[(v>>6)&0x03];
275 if ((DELTAT->control2 & 3) != (v & 3))
276 {
277 /*0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */
278 if (DELTAT->DRAMportshift != dram_rightshift[v&3])
279 {
280 DELTAT->DRAMportshift = dram_rightshift[v&3];
281
282 /* final shift value depends on chip type and memory type selected:
283 8 for YM2610 (ROM only),
284 5 for ROM for Y8950 and YM2608,
285 5 for x8bit DRAMs for Y8950 and YM2608,
286 2 for x1bit DRAMs for Y8950 and YM2608.
287 */
288
289 /* refresh addresses */
290 DELTAT->start = (DELTAT->reg[0x3]*0x0100 | DELTAT->reg[0x2]) << (DELTAT->portshift - DELTAT->DRAMportshift);
291 DELTAT->end = (DELTAT->reg[0x5]*0x0100 | DELTAT->reg[0x4]) << (DELTAT->portshift - DELTAT->DRAMportshift);
292 DELTAT->end += (1 << (DELTAT->portshift-DELTAT->DRAMportshift) ) - 1;
293 DELTAT->limit = (DELTAT->reg[0xd]*0x0100 | DELTAT->reg[0xc]) << (DELTAT->portshift - DELTAT->DRAMportshift);
294 }
295 }
296 DELTAT->control2 = v;
297 break;
298 case 0x02: /* Start Address L */
299 case 0x03: /* Start Address H */
300 DELTAT->start = (DELTAT->reg[0x3]*0x0100 | DELTAT->reg[0x2]) << (DELTAT->portshift - DELTAT->DRAMportshift);
301 /*logerror("DELTAT start: 02=%2x 03=%2x addr=%8x\n",DELTAT->reg[0x2], DELTAT->reg[0x3],DELTAT->start );*/
302 break;
303 case 0x04: /* Stop Address L */
304 case 0x05: /* Stop Address H */
305 DELTAT->end = (DELTAT->reg[0x5]*0x0100 | DELTAT->reg[0x4]) << (DELTAT->portshift - DELTAT->DRAMportshift);
306 DELTAT->end += (1 << (DELTAT->portshift-DELTAT->DRAMportshift) ) - 1;
307 /*logerror("DELTAT end : 04=%2x 05=%2x addr=%8x\n",DELTAT->reg[0x4], DELTAT->reg[0x5],DELTAT->end );*/
308 break;
309 case 0x06: /* Prescale L (ADPCM and Record frq) */
310 case 0x07: /* Prescale H */
311 break;
312 case 0x08: /* ADPCM data */
313
314/*
315some examples:
316value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning:
317 C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register
318 E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register
319 80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register
320 a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register
321
322 60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08
323 20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08
324
325*/
326
327 /* external memory write */
328 if ( (DELTAT->portstate & 0xe0)==0x60 )
329 {
330 if (DELTAT->memread)
331 {
332 DELTAT->now_addr = DELTAT->start << 1;
333 DELTAT->memread = 0;
334 }
335
336 /*logerror("YM Delta-T memory write $%08x, v=$%02x\n", DELTAT->now_addr >> 1, v);*/
337
338 if ( DELTAT->now_addr != (DELTAT->end<<1) )
339 {
340 DELTAT->memory[DELTAT->now_addr>>1] = v;
341 DELTAT->now_addr+=2; /* two nibbles at a time */
342
343 /* reset BRDY bit in status register, which means we are processing the write */
344 if(DELTAT->status_reset_handler)
345 if(DELTAT->status_change_BRDY_bit)
346 (DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
347
348 /* setup a timer that will callback us in 10 master clock cycles for Y8950
349 * in the callback set the BRDY flag to 1 , which means we have written the data.
350 * For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work.
351 */
352 /* set BRDY bit in status register */
353 if(DELTAT->status_set_handler)
354 if(DELTAT->status_change_BRDY_bit)
355 (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
356
357 }
358 else
359 {
360 /* set EOS bit in status register */
361 if(DELTAT->status_set_handler)
362 if(DELTAT->status_change_EOS_bit)
363 (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit);
364 }
365
366 return;
367 }
368
369 /* ADPCM synthesis from CPU */
370 if ( (DELTAT->portstate & 0xe0)==0x80 )
371 {
372 DELTAT->CPU_data = v;
373
374 /* Reset BRDY bit in status register, which means we are full of data */
375 if(DELTAT->status_reset_handler)
376 if(DELTAT->status_change_BRDY_bit)
377 (DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
378 return;
379 }
380
381 break;
382 case 0x09: /* DELTA-N L (ADPCM Playback Prescaler) */
383 case 0x0a: /* DELTA-N H */
384 DELTAT->delta = (DELTAT->reg[0xa]*0x0100 | DELTAT->reg[0x9]);
385 DELTAT->step = (UINT32)( (double)(DELTAT->delta /* *(1<<(YM_DELTAT_SHIFT-16)) */ ) * (DELTAT->freqbase) );
386 /*logerror("DELTAT deltan:09=%2x 0a=%2x\n",DELTAT->reg[0x9], DELTAT->reg[0xa]);*/
387 break;
388 case 0x0b: /* Output level control (volume, linear) */
389 {
390 INT32 oldvol = DELTAT->volume;
391 DELTAT->volume = (v&0xff) * (DELTAT->output_range/256) / YM_DELTAT_DECODE_RANGE;
392/* v * ((1<<16)>>8) >> 15;
393* thus: v * (1<<8) >> 15;
394* thus: output_range must be (1 << (15+8)) at least
395* v * ((1<<23)>>8) >> 15;
396* v * (1<<15) >> 15;
397*/
398 /*logerror("DELTAT vol = %2x\n",v&0xff);*/
399 if( oldvol != 0 )
400 {
401 DELTAT->adpcml = (int)((double)DELTAT->adpcml / (double)oldvol * (double)DELTAT->volume);
402 }
403 }
404 break;
405 case 0x0c: /* Limit Address L */
406 case 0x0d: /* Limit Address H */
407 DELTAT->limit = (DELTAT->reg[0xd]*0x0100 | DELTAT->reg[0xc]) << (DELTAT->portshift - DELTAT->DRAMportshift);
408 /*logerror("DELTAT limit: 0c=%2x 0d=%2x addr=%8x\n",DELTAT->reg[0xc], DELTAT->reg[0xd],DELTAT->limit );*/
409 break;
410 }
411}
412
413void YM_DELTAT_ADPCM_Reset(YM_DELTAT *DELTAT,int pan,int emulation_mode)
414{
415 DELTAT->now_addr = 0;
416 DELTAT->now_step = 0;
417 DELTAT->step = 0;
418 DELTAT->start = 0;
419 DELTAT->end = 0;
420 DELTAT->limit = ~0; /* this way YM2610 and Y8950 (both of which don't have limit address reg) will still work */
421 DELTAT->volume = 0;
422 DELTAT->pan = &DELTAT->output_pointer[pan];
423 DELTAT->acc = 0;
424 DELTAT->prev_acc = 0;
425 DELTAT->adpcmd = 127;
426 DELTAT->adpcml = 0;
427 DELTAT->emulation_mode = (UINT8)emulation_mode;
428 DELTAT->portstate = (emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610) ? 0x20 : 0;
429 DELTAT->control2 = (emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610) ? 0x01 : 0; /* default setting depends on the emulation mode. MSX demo called "facdemo_4" doesn't setup control2 register at all and still works */
430 DELTAT->DRAMportshift = dram_rightshift[DELTAT->control2 & 3];
431
432 /* The flag mask register disables the BRDY after the reset, however
433 ** as soon as the mask is enabled the flag needs to be set. */
434
435 /* set BRDY bit in status register */
436 if(DELTAT->status_set_handler)
437 if(DELTAT->status_change_BRDY_bit)
438 (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
439}
440
441#if 0
442void YM_DELTAT_postload(YM_DELTAT *DELTAT,UINT8 *regs)
443{
444 int r;
445
446 /* to keep adpcml */
447 DELTAT->volume = 0;
448 /* update */
449 for(r=1;r<16;r++)
450 YM_DELTAT_ADPCM_Write(DELTAT,r,regs[r]);
451 DELTAT->reg[0] = regs[0];
452
453 /* current rom data */
454 if (DELTAT->memory)
455 DELTAT->now_data = *(DELTAT->memory + (DELTAT->now_addr>>1) );
456
457}
458void YM_DELTAT_savestate(const device_config *device,YM_DELTAT *DELTAT)
459{
460#ifdef __STATE_H__
461 state_save_register_device_item(device, 0, DELTAT->portstate);
462 state_save_register_device_item(device, 0, DELTAT->now_addr);
463 state_save_register_device_item(device, 0, DELTAT->now_step);
464 state_save_register_device_item(device, 0, DELTAT->acc);
465 state_save_register_device_item(device, 0, DELTAT->prev_acc);
466 state_save_register_device_item(device, 0, DELTAT->adpcmd);
467 state_save_register_device_item(device, 0, DELTAT->adpcml);
468#endif
469}
470#endif
471
472
473#define YM_DELTAT_Limit(val,max,min) \
474{ \
475 if ( val > max ) val = max; \
476 else if ( val < min ) val = min; \
477}
478
479static INLINE void YM_DELTAT_synthesis_from_external_memory(YM_DELTAT *DELTAT)
480{
481 UINT32 step;
482 int data;
483
484 DELTAT->now_step += DELTAT->step;
485 if ( DELTAT->now_step >= (1<<YM_DELTAT_SHIFT) )
486 {
487 step = DELTAT->now_step >> YM_DELTAT_SHIFT;
488 DELTAT->now_step &= (1<<YM_DELTAT_SHIFT)-1;
489 do{
490
491 if ( DELTAT->now_addr == (DELTAT->limit<<1) )
492 DELTAT->now_addr = 0;
493
494 if ( DELTAT->now_addr == (DELTAT->end<<1) ) { /* 12-06-2001 JB: corrected comparison. Was > instead of == */
495 if( DELTAT->portstate&0x10 ){
496 /* repeat start */
497 DELTAT->now_addr = DELTAT->start<<1;
498 DELTAT->acc = 0;
499 DELTAT->adpcmd = YM_DELTAT_DELTA_DEF;
500 DELTAT->prev_acc = 0;
501 }else{
502 /* set EOS bit in status register */
503 if(DELTAT->status_set_handler)
504 if(DELTAT->status_change_EOS_bit)
505 (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit);
506
507 /* clear PCM BUSY bit (reflected in status register) */
508 DELTAT->PCM_BSY = 0;
509
510 DELTAT->portstate = 0;
511 DELTAT->adpcml = 0;
512 DELTAT->prev_acc = 0;
513 return;
514 }
515 }
516
517 if( DELTAT->now_addr&1 ) data = DELTAT->now_data & 0x0f;
518 else
519 {
520 DELTAT->now_data = *(DELTAT->memory + (DELTAT->now_addr>>1));
521 data = DELTAT->now_data >> 4;
522 }
523
524 DELTAT->now_addr++;
525 /* 12-06-2001 JB: */
526 /* YM2610 address register is 24 bits wide.*/
527 /* The "+1" is there because we use 1 bit more for nibble calculations.*/
528 /* WARNING: */
529 /* Side effect: we should take the size of the mapped ROM into account */
530 DELTAT->now_addr &= ( (1<<(24+1))-1);
531
532 /* store accumulator value */
533 DELTAT->prev_acc = DELTAT->acc;
534
535 /* Forecast to next Forecast */
536 DELTAT->acc += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8);
537 YM_DELTAT_Limit(DELTAT->acc,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN);
538
539 /* delta to next delta */
540 DELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64;
541 YM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN );
542
543 /* ElSemi: Fix interpolator. */
544 /*DELTAT->prev_acc = prev_acc + ((DELTAT->acc - prev_acc) / 2 );*/
545
546 }while(--step);
547
548 }
549
550 /* ElSemi: Fix interpolator. */
551 DELTAT->adpcml = DELTAT->prev_acc * (int)((1<<YM_DELTAT_SHIFT)-DELTAT->now_step);
552 DELTAT->adpcml += (DELTAT->acc * (int)DELTAT->now_step);
553 DELTAT->adpcml = (DELTAT->adpcml>>YM_DELTAT_SHIFT) * (int)DELTAT->volume;
554
555 /* output for work of output channels (outd[OPNxxxx])*/
556 *(DELTAT->pan) += DELTAT->adpcml;
557}
558
559
560
561static INLINE void YM_DELTAT_synthesis_from_CPU_memory(YM_DELTAT *DELTAT)
562{
563 UINT32 step;
564 int data;
565
566 DELTAT->now_step += DELTAT->step;
567 if ( DELTAT->now_step >= (1<<YM_DELTAT_SHIFT) )
568 {
569 step = DELTAT->now_step >> YM_DELTAT_SHIFT;
570 DELTAT->now_step &= (1<<YM_DELTAT_SHIFT)-1;
571 do{
572
573 if( DELTAT->now_addr&1 )
574 {
575 data = DELTAT->now_data & 0x0f;
576
577 DELTAT->now_data = DELTAT->CPU_data;
578
579 /* after we used CPU_data, we set BRDY bit in status register,
580 * which means we are ready to accept another byte of data */
581 if(DELTAT->status_set_handler)
582 if(DELTAT->status_change_BRDY_bit)
583 (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
584 }
585 else
586 {
587 data = DELTAT->now_data >> 4;
588 }
589
590 DELTAT->now_addr++;
591
592 /* store accumulator value */
593 DELTAT->prev_acc = DELTAT->acc;
594
595 /* Forecast to next Forecast */
596 DELTAT->acc += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8);
597 YM_DELTAT_Limit(DELTAT->acc,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN);
598
599 /* delta to next delta */
600 DELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64;
601 YM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN );
602
603
604 }while(--step);
605
606 }
607
608 /* ElSemi: Fix interpolator. */
609 DELTAT->adpcml = DELTAT->prev_acc * (int)((1<<YM_DELTAT_SHIFT)-DELTAT->now_step);
610 DELTAT->adpcml += (DELTAT->acc * (int)DELTAT->now_step);
611 DELTAT->adpcml = (DELTAT->adpcml>>YM_DELTAT_SHIFT) * (int)DELTAT->volume;
612
613 /* output for work of output channels (outd[OPNxxxx])*/
614 *(DELTAT->pan) += DELTAT->adpcml;
615}
616
617
618
619/* ADPCM B (Delta-T control type) */
620void YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT)
621{
622
623/*
624some examples:
625value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning:
626 80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register
627 a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register
628 C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register
629 E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register
630
631 60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08
632 20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08
633
634*/
635
636 if ( (DELTAT->portstate & 0xe0)==0xa0 )
637 {
638 YM_DELTAT_synthesis_from_external_memory(DELTAT);
639 return;
640 }
641
642 if ( (DELTAT->portstate & 0xe0)==0x80 )
643 {
644 /* ADPCM synthesis from CPU-managed memory (from reg $08) */
645 YM_DELTAT_synthesis_from_CPU_memory(DELTAT); /* change output based on data in ADPCM data reg ($08) */
646 return;
647 }
648
649//todo: ADPCM analysis
650// if ( (DELTAT->portstate & 0xe0)==0xc0 )
651// if ( (DELTAT->portstate & 0xe0)==0xe0 )
652
653 return;
654}
655