DOSBox-X
|
00001 // license:GPL-2.0+ 00002 // copyright-holders:Jarek Burczynski 00003 /* 00004 ** 00005 ** File: ymdeltat.c 00006 ** 00007 ** YAMAHA DELTA-T adpcm sound emulation subroutine 00008 ** used by fmopl.c (Y8950) and fm.c (YM2608 and YM2610/B) 00009 ** 00010 ** Base program is YM2610 emulator by Hiromitsu Shioya. 00011 ** Written by Tatsuyuki Satoh 00012 ** Improvements by Jarek Burczynski (bujar at mame dot net) 00013 ** 00014 ** 00015 ** History: 00016 ** 00017 ** 03-08-2003 Jarek Burczynski: 00018 ** - fixed BRDY flag implementation. 00019 ** 00020 ** 24-07-2003 Jarek Burczynski, Frits Hilderink: 00021 ** - fixed delault value for control2 in YM_DELTAT_ADPCM_Reset 00022 ** 00023 ** 22-07-2003 Jarek Burczynski, Frits Hilderink: 00024 ** - fixed external memory support 00025 ** 00026 ** 15-06-2003 Jarek Burczynski: 00027 ** - implemented CPU -> AUDIO ADPCM synthesis (via writes to the ADPCM data reg $08) 00028 ** - implemented support for the Limit address register 00029 ** - supported two bits from the control register 2 ($01): RAM TYPE (x1 bit/x8 bit), ROM/RAM 00030 ** - implemented external memory access (read/write) via the ADPCM data reg reads/writes 00031 ** Thanks go to Frits Hilderink for the example code. 00032 ** 00033 ** 14-06-2003 Jarek Burczynski: 00034 ** - various fixes to enable proper support for status register flags: BSRDY, PCM BSY, ZERO 00035 ** - modified EOS handling 00036 ** 00037 ** 05-04-2003 Jarek Burczynski: 00038 ** - implemented partial support for external/processor memory on sample replay 00039 ** 00040 ** 01-12-2002 Jarek Burczynski: 00041 ** - fixed first missing sound in gigandes thanks to previous fix (interpolator) by ElSemi 00042 ** - renamed/removed some YM_DELTAT struct fields 00043 ** 00044 ** 28-12-2001 Acho A. Tang 00045 ** - added EOS status report on ADPCM playback. 00046 ** 00047 ** 05-08-2001 Jarek Burczynski: 00048 ** - now_step is initialized with 0 at the start of play. 00049 ** 00050 ** 12-06-2001 Jarek Burczynski: 00051 ** - corrected end of sample bug in YM_DELTAT_ADPCM_CALC. 00052 ** Checked on real YM2610 chip - address register is 24 bits wide. 00053 ** Thanks go to Stefan Jokisch (stefan.jokisch@gmx.de) for tracking down the problem. 00054 ** 00055 ** TO DO: 00056 ** Check size of the address register on the other chips.... 00057 ** 00058 ** Version 0.72 00059 ** 00060 ** sound chips that have this unit: 00061 ** YM2608 OPNA 00062 ** YM2610/B OPNB 00063 ** Y8950 MSX AUDIO 00064 ** 00065 */ 00066 00067 #include "emu.h" 00068 #include "ymdeltat.h" 00069 00070 #define YM_DELTAT_SHIFT (16) 00071 00072 #define YM_DELTAT_DELTA_MAX (24576) 00073 #define YM_DELTAT_DELTA_MIN (127) 00074 #define YM_DELTAT_DELTA_DEF (127) 00075 00076 #define YM_DELTAT_DECODE_RANGE 32768 00077 #define YM_DELTAT_DECODE_MIN (-(YM_DELTAT_DECODE_RANGE)) 00078 #define YM_DELTAT_DECODE_MAX ((YM_DELTAT_DECODE_RANGE)-1) 00079 00080 00081 /* Forecast to next Forecast (rate = *8) */ 00082 /* 1/8 , 3/8 , 5/8 , 7/8 , 9/8 , 11/8 , 13/8 , 15/8 */ 00083 static const int32_t ym_deltat_decode_tableB1[16] = { 00084 1, 3, 5, 7, 9, 11, 13, 15, 00085 -1, -3, -5, -7, -9, -11, -13, -15, 00086 }; 00087 /* delta to next delta (rate= *64) */ 00088 /* 0.9 , 0.9 , 0.9 , 0.9 , 1.2 , 1.6 , 2.0 , 2.4 */ 00089 static const int32_t ym_deltat_decode_tableB2[16] = { 00090 57, 57, 57, 57, 77, 102, 128, 153, 00091 57, 57, 57, 57, 77, 102, 128, 153 00092 }; 00093 00094 #if 0 00095 void YM_DELTAT::BRDY_callback() 00096 { 00097 logerror("BRDY_callback reached (flag set) !\n"); 00098 00099 /* set BRDY bit in status register */ 00100 if(status_set_handler) 00101 if(status_change_BRDY_bit) 00102 (status_set_handler)(status_change_which_chip, status_change_BRDY_bit); 00103 } 00104 #endif 00105 00106 uint8_t YM_DELTAT::ADPCM_Read() 00107 { 00108 uint8_t v = 0; 00109 00110 /* external memory read */ 00111 if ((portstate & 0xe0) == 0x20) 00112 { 00113 /* two dummy reads */ 00114 if (memread) 00115 { 00116 now_addr = start << 1; 00117 memread--; 00118 return 0; 00119 } 00120 00121 00122 if (now_addr != (end << 1)) 00123 { 00124 v = memory[now_addr>>1]; 00125 00126 /*logerror("YM Delta-T memory read $%08x, v=$%02x\n", now_addr >> 1, v);*/ 00127 00128 now_addr += 2; /* two nibbles at a time */ 00129 00130 /* reset BRDY bit in status register, which means we are reading the memory now */ 00131 if (status_reset_handler && status_change_BRDY_bit) 00132 (status_reset_handler)(status_change_which_chip, status_change_BRDY_bit); 00133 00134 /* setup a timer that will callback us in 10 master clock cycles for Y8950 00135 * in the callback set the BRDY flag to 1 , which means we have another data ready. 00136 * For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work. 00137 */ 00138 /* set BRDY bit in status register */ 00139 if (status_set_handler && status_change_BRDY_bit) 00140 (status_set_handler)(status_change_which_chip, status_change_BRDY_bit); 00141 } 00142 else 00143 { 00144 /* set EOS bit in status register */ 00145 if (status_set_handler && status_change_EOS_bit) 00146 (status_set_handler)(status_change_which_chip, status_change_EOS_bit); 00147 } 00148 } 00149 00150 return v; 00151 } 00152 00153 00154 /* 0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */ 00155 static const uint8_t dram_rightshift[4]={3,0,0,0}; 00156 00157 /* DELTA-T ADPCM write register */ 00158 void YM_DELTAT::ADPCM_Write(int r, int v) 00159 { 00160 if (r >= 0x10) return; 00161 reg[r] = v; /* stock data */ 00162 00163 switch (r) 00164 { 00165 case 0x00: 00166 /* 00167 START: 00168 Accessing *external* memory is started when START bit (D7) is set to "1", so 00169 you must set all conditions needed for recording/playback before starting. 00170 If you access *CPU-managed* memory, recording/playback starts after 00171 read/write of ADPCM data register $08. 00172 00173 REC: 00174 0 = ADPCM synthesis (playback) 00175 1 = ADPCM analysis (record) 00176 00177 MEMDATA: 00178 0 = processor (*CPU-managed*) memory (means: using register $08) 00179 1 = external memory (using start/end/limit registers to access memory: RAM or ROM) 00180 00181 00182 SPOFF: 00183 controls output pin that should disable the speaker while ADPCM analysis 00184 00185 RESET and REPEAT only work with external memory. 00186 00187 00188 some examples: 00189 value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning: 00190 C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register 00191 E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register 00192 80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register 00193 a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register 00194 00195 60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08 00196 20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08 00197 00198 */ 00199 /* handle emulation mode */ 00200 if (emulation_mode == EMULATION_MODE_YM2610) 00201 { 00202 v |= 0x20; /* YM2610 always uses external memory and doesn't even have memory flag bit. */ 00203 } 00204 00205 portstate = v & (0x80|0x40|0x20|0x10|0x01); /* start, rec, memory mode, repeat flag copy, reset(bit0) */ 00206 00207 if (portstate & 0x80)/* START,REC,MEMDATA,REPEAT,SPOFF,--,--,RESET */ 00208 { 00209 /* set PCM BUSY bit */ 00210 PCM_BSY = 1; 00211 00212 /* start ADPCM */ 00213 now_step = 0; 00214 acc = 0; 00215 prev_acc = 0; 00216 adpcml = 0; 00217 adpcmd = YM_DELTAT_DELTA_DEF; 00218 now_data = 0; 00219 00220 } 00221 00222 if (portstate & 0x20) /* do we access external memory? */ 00223 { 00224 now_addr = start << 1; 00225 memread = 2; /* two dummy reads needed before accesing external memory via register $08*/ 00226 00227 /* if yes, then let's check if ADPCM memory is mapped and big enough */ 00228 if (!memory) 00229 { 00230 device->logerror("YM Delta-T ADPCM rom not mapped\n"); 00231 portstate = 0x00; 00232 PCM_BSY = 0; 00233 } 00234 else 00235 { 00236 if (end >= memory_size) /* Check End in Range */ 00237 { 00238 device->logerror("YM Delta-T ADPCM end out of range: $%08x\n", end); 00239 end = memory_size - 1; 00240 } 00241 if (start >= memory_size) /* Check Start in Range */ 00242 { 00243 device->logerror("YM Delta-T ADPCM start out of range: $%08x\n", start); 00244 portstate = 0x00; 00245 PCM_BSY = 0; 00246 } 00247 } 00248 } 00249 else /* we access CPU memory (ADPCM data register $08) so we only reset now_addr here */ 00250 { 00251 now_addr = 0; 00252 } 00253 00254 if (portstate & 0x01) 00255 { 00256 portstate = 0x00; 00257 00258 /* clear PCM BUSY bit (in status register) */ 00259 PCM_BSY = 0; 00260 00261 /* set BRDY flag */ 00262 if (status_set_handler && status_change_BRDY_bit) 00263 (status_set_handler)(status_change_which_chip, status_change_BRDY_bit); 00264 } 00265 break; 00266 00267 case 0x01: /* L,R,-,-,SAMPLE,DA/AD,RAMTYPE,ROM */ 00268 /* handle emulation mode */ 00269 if (emulation_mode == EMULATION_MODE_YM2610) 00270 { 00271 v |= 0x01; /* YM2610 always uses ROM as an external memory and doesn't tave ROM/RAM memory flag bit. */ 00272 } 00273 00274 pan = &output_pointer[(v >> 6) & 0x03]; 00275 if ((control2 & 3) != (v & 3)) 00276 { 00277 /*0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */ 00278 if (DRAMportshift != dram_rightshift[v & 3]) 00279 { 00280 DRAMportshift = dram_rightshift[v & 3]; 00281 00282 /* final shift value depends on chip type and memory type selected: 00283 8 for YM2610 (ROM only), 00284 5 for ROM for Y8950 and YM2608, 00285 5 for x8bit DRAMs for Y8950 and YM2608, 00286 2 for x1bit DRAMs for Y8950 and YM2608. 00287 */ 00288 00289 /* refresh addresses */ 00290 start = (reg[0x3] * 0x0100 | reg[0x2]) << (portshift - DRAMportshift); 00291 end = (reg[0x5] * 0x0100 | reg[0x4]) << (portshift - DRAMportshift); 00292 end += (1 << (portshift - DRAMportshift)) - 1; 00293 limit = (reg[0xd]*0x0100 | reg[0xc]) << (portshift - DRAMportshift); 00294 } 00295 } 00296 control2 = v; 00297 break; 00298 00299 case 0x02: /* Start Address L */ 00300 case 0x03: /* Start Address H */ 00301 start = (reg[0x3] * 0x0100 | reg[0x2]) << (portshift - DRAMportshift); 00302 /*logerror("DELTAT start: 02=%2x 03=%2x addr=%8x\n",reg[0x2], reg[0x3],start );*/ 00303 break; 00304 00305 case 0x04: /* Stop Address L */ 00306 case 0x05: /* Stop Address H */ 00307 end = (reg[0x5]*0x0100 | reg[0x4]) << (portshift - DRAMportshift); 00308 end += (1 << (portshift - DRAMportshift)) - 1; 00309 /*logerror("DELTAT end : 04=%2x 05=%2x addr=%8x\n",reg[0x4], reg[0x5],end );*/ 00310 break; 00311 00312 case 0x06: /* Prescale L (ADPCM and Record frq) */ 00313 case 0x07: /* Prescale H */ 00314 break; 00315 00316 case 0x08: /* ADPCM data */ 00317 /* 00318 some examples: 00319 value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning: 00320 C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register 00321 E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register 00322 80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register 00323 a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register 00324 00325 60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08 00326 20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08 00327 00328 */ 00329 00330 /* external memory write */ 00331 if ((portstate & 0xe0) == 0x60) 00332 { 00333 if (memread) 00334 { 00335 now_addr = start << 1; 00336 memread = 0; 00337 } 00338 00339 /*logerror("YM Delta-T memory write $%08x, v=$%02x\n", now_addr >> 1, v);*/ 00340 00341 if (now_addr != (end << 1)) 00342 { 00343 memory[now_addr >> 1] = v; 00344 now_addr += 2; /* two nybbles at a time */ 00345 00346 /* reset BRDY bit in status register, which means we are processing the write */ 00347 if (status_reset_handler && status_change_BRDY_bit) 00348 (status_reset_handler)(status_change_which_chip, status_change_BRDY_bit); 00349 00350 /* setup a timer that will callback us in 10 master clock cycles for Y8950 00351 * in the callback set the BRDY flag to 1 , which means we have written the data. 00352 * For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work. 00353 */ 00354 /* set BRDY bit in status register */ 00355 if (status_set_handler && status_change_BRDY_bit) 00356 (status_set_handler)(status_change_which_chip, status_change_BRDY_bit); 00357 00358 } 00359 else 00360 { 00361 /* set EOS bit in status register */ 00362 if (status_set_handler && status_change_EOS_bit) 00363 (status_set_handler)(status_change_which_chip, status_change_EOS_bit); 00364 } 00365 00366 return; 00367 } 00368 00369 /* ADPCM synthesis from CPU */ 00370 if ((portstate & 0xe0) == 0x80) 00371 { 00372 CPU_data = v; 00373 00374 /* Reset BRDY bit in status register, which means we are full of data */ 00375 if (status_reset_handler && status_change_BRDY_bit) 00376 (status_reset_handler)(status_change_which_chip, status_change_BRDY_bit); 00377 return; 00378 } 00379 00380 break; 00381 00382 case 0x09: /* DELTA-N L (ADPCM Playback Prescaler) */ 00383 case 0x0a: /* DELTA-N H */ 00384 delta = (reg[0xa] * 0x0100 | reg[0x9]); 00385 step = uint32_t(double(delta /* *(1<<(YM_DELTAT_SHIFT-16)) */) * freqbase); 00386 /*logerror("DELTAT deltan:09=%2x 0a=%2x\n",reg[0x9], reg[0xa]);*/ 00387 break; 00388 00389 case 0x0b: /* Output level control (volume, linear) */ 00390 { 00391 const int32_t oldvol = volume; 00392 volume = (v & 0xff) * (output_range / 256) / YM_DELTAT_DECODE_RANGE; 00393 /* v * ((1<<16)>>8) >> 15; 00394 * thus: v * (1<<8) >> 15; 00395 * thus: output_range must be (1 << (15+8)) at least 00396 * v * ((1<<23)>>8) >> 15; 00397 * v * (1<<15) >> 15; 00398 */ 00399 /*logerror("DELTAT vol = %2x\n",v&0xff);*/ 00400 if (oldvol != 0) 00401 { 00402 adpcml = int(double(adpcml) / double(oldvol) * double(volume)); 00403 } 00404 } 00405 break; 00406 00407 case 0x0c: /* Limit Address L */ 00408 case 0x0d: /* Limit Address H */ 00409 limit = (reg[0xd] * 0x0100 | reg[0xc]) << (portshift - DRAMportshift); 00410 /*logerror("DELTAT limit: 0c=%2x 0d=%2x addr=%8x\n",reg[0xc], reg[0xd],limit );*/ 00411 break; 00412 } 00413 } 00414 00415 void YM_DELTAT::ADPCM_Reset(int panidx, int mode, device_t *dev) 00416 { 00417 device = dev; 00418 now_addr = 0; 00419 now_step = 0; 00420 step = 0; 00421 start = 0; 00422 end = 0; 00423 limit = ~0; /* this way YM2610 and Y8950 (both of which don't have limit address reg) will still work */ 00424 volume = 0; 00425 pan = &output_pointer[panidx]; 00426 acc = 0; 00427 prev_acc = 0; 00428 adpcmd = 127; 00429 adpcml = 0; 00430 emulation_mode = uint8_t(mode); 00431 portstate = (emulation_mode == EMULATION_MODE_YM2610) ? 0x20 : 0; 00432 control2 = (emulation_mode == 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 */ 00433 DRAMportshift = dram_rightshift[control2 & 3]; 00434 00435 /* The flag mask register disables the BRDY after the reset, however 00436 ** as soon as the mask is enabled the flag needs to be set. */ 00437 00438 /* set BRDY bit in status register */ 00439 if (status_set_handler && status_change_BRDY_bit) 00440 (status_set_handler)(status_change_which_chip, status_change_BRDY_bit); 00441 } 00442 00443 void YM_DELTAT::postload(uint8_t *regs) 00444 { 00445 /* to keep adpcml */ 00446 volume = 0; 00447 /* update */ 00448 for (int r = 1; r < 16; r++) 00449 ADPCM_Write(r, regs[r]); 00450 reg[0] = regs[0]; 00451 00452 /* current rom data */ 00453 if (memory) 00454 now_data = *(memory + (now_addr >> 1)); 00455 00456 } 00457 void YM_DELTAT::savestate(device_t *device) 00458 { 00459 #ifdef MAME_EMU_SAVE_H 00460 YM_DELTAT *const DELTAT = this; // makes the save name sensible 00461 device->save_item(NAME(DELTAT->portstate)); 00462 device->save_item(NAME(DELTAT->now_addr)); 00463 device->save_item(NAME(DELTAT->now_step)); 00464 device->save_item(NAME(DELTAT->acc)); 00465 device->save_item(NAME(DELTAT->prev_acc)); 00466 device->save_item(NAME(DELTAT->adpcmd)); 00467 device->save_item(NAME(DELTAT->adpcml)); 00468 #else 00469 (void)device; 00470 #endif 00471 } 00472 00473 00474 #define YM_DELTAT_Limit(val,max,min) \ 00475 { \ 00476 if ( val > max ) val = max; \ 00477 else if ( val < min ) val = min; \ 00478 } 00479 00480 static inline void YM_DELTAT_synthesis_from_external_memory(YM_DELTAT *DELTAT) 00481 { 00482 uint32_t step; 00483 int data; 00484 00485 DELTAT->now_step += DELTAT->step; 00486 if ( DELTAT->now_step >= (1<<YM_DELTAT_SHIFT) ) 00487 { 00488 step = DELTAT->now_step >> YM_DELTAT_SHIFT; 00489 DELTAT->now_step &= (1<<YM_DELTAT_SHIFT)-1; 00490 do{ 00491 if ( DELTAT->now_addr == (DELTAT->limit<<1) ) 00492 DELTAT->now_addr = 0; 00493 00494 if ( DELTAT->now_addr == (DELTAT->end<<1) ) { /* 12-06-2001 JB: corrected comparison. Was > instead of == */ 00495 if( DELTAT->portstate&0x10 ){ 00496 /* repeat start */ 00497 DELTAT->now_addr = DELTAT->start<<1; 00498 DELTAT->acc = 0; 00499 DELTAT->adpcmd = YM_DELTAT_DELTA_DEF; 00500 DELTAT->prev_acc = 0; 00501 }else{ 00502 /* set EOS bit in status register */ 00503 if(DELTAT->status_set_handler) 00504 if(DELTAT->status_change_EOS_bit) 00505 (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit); 00506 00507 /* clear PCM BUSY bit (reflected in status register) */ 00508 DELTAT->PCM_BSY = 0; 00509 00510 DELTAT->portstate = 0; 00511 DELTAT->adpcml = 0; 00512 DELTAT->prev_acc = 0; 00513 return; 00514 } 00515 } 00516 00517 if( DELTAT->now_addr&1 ) data = DELTAT->now_data & 0x0f; 00518 else 00519 { 00520 DELTAT->now_data = *(DELTAT->memory + (DELTAT->now_addr>>1)); 00521 data = DELTAT->now_data >> 4; 00522 } 00523 00524 DELTAT->now_addr++; 00525 /* 12-06-2001 JB: */ 00526 /* YM2610 address register is 24 bits wide.*/ 00527 /* The "+1" is there because we use 1 bit more for nibble calculations.*/ 00528 /* WARNING: */ 00529 /* Side effect: we should take the size of the mapped ROM into account */ 00530 DELTAT->now_addr &= ( (1<<(24+1))-1); 00531 00532 /* store accumulator value */ 00533 DELTAT->prev_acc = DELTAT->acc; 00534 00535 /* Forecast to next Forecast */ 00536 DELTAT->acc += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8); 00537 YM_DELTAT_Limit(DELTAT->acc,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN); 00538 00539 /* delta to next delta */ 00540 DELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64; 00541 YM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN ); 00542 00543 /* ElSemi: Fix interpolator. */ 00544 /*DELTAT->prev_acc = prev_acc + ((DELTAT->acc - prev_acc) / 2 );*/ 00545 00546 }while(--step); 00547 00548 } 00549 00550 /* ElSemi: Fix interpolator. */ 00551 DELTAT->adpcml = DELTAT->prev_acc * (int)((1<<YM_DELTAT_SHIFT)-DELTAT->now_step); 00552 DELTAT->adpcml += (DELTAT->acc * (int)DELTAT->now_step); 00553 DELTAT->adpcml = (DELTAT->adpcml>>YM_DELTAT_SHIFT) * (int)DELTAT->volume; 00554 00555 /* output for work of output channels (outd[OPNxxxx])*/ 00556 *(DELTAT->pan) += DELTAT->adpcml; 00557 } 00558 00559 00560 00561 static inline void YM_DELTAT_synthesis_from_CPU_memory(YM_DELTAT *DELTAT) 00562 { 00563 uint32_t step; 00564 int data; 00565 00566 DELTAT->now_step += DELTAT->step; 00567 if ( DELTAT->now_step >= (1<<YM_DELTAT_SHIFT) ) 00568 { 00569 step = DELTAT->now_step >> YM_DELTAT_SHIFT; 00570 DELTAT->now_step &= (1<<YM_DELTAT_SHIFT)-1; 00571 do{ 00572 if( DELTAT->now_addr&1 ) 00573 { 00574 data = DELTAT->now_data & 0x0f; 00575 00576 DELTAT->now_data = DELTAT->CPU_data; 00577 00578 /* after we used CPU_data, we set BRDY bit in status register, 00579 * which means we are ready to accept another byte of data */ 00580 if(DELTAT->status_set_handler) 00581 if(DELTAT->status_change_BRDY_bit) 00582 (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit); 00583 } 00584 else 00585 { 00586 data = DELTAT->now_data >> 4; 00587 } 00588 00589 DELTAT->now_addr++; 00590 00591 /* store accumulator value */ 00592 DELTAT->prev_acc = DELTAT->acc; 00593 00594 /* Forecast to next Forecast */ 00595 DELTAT->acc += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8); 00596 YM_DELTAT_Limit(DELTAT->acc,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN); 00597 00598 /* delta to next delta */ 00599 DELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64; 00600 YM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN ); 00601 00602 00603 }while(--step); 00604 00605 } 00606 00607 /* ElSemi: Fix interpolator. */ 00608 DELTAT->adpcml = DELTAT->prev_acc * (int)((1<<YM_DELTAT_SHIFT)-DELTAT->now_step); 00609 DELTAT->adpcml += (DELTAT->acc * (int)DELTAT->now_step); 00610 DELTAT->adpcml = (DELTAT->adpcml>>YM_DELTAT_SHIFT) * (int)DELTAT->volume; 00611 00612 /* output for work of output channels (outd[OPNxxxx])*/ 00613 *(DELTAT->pan) += DELTAT->adpcml; 00614 } 00615 00616 00617 00618 /* ADPCM B (Delta-T control type) */ 00619 void YM_DELTAT::ADPCM_CALC() 00620 { 00621 /* 00622 some examples: 00623 value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning: 00624 80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register 00625 a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register 00626 C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register 00627 E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register 00628 00629 60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08 00630 20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08 00631 00632 */ 00633 00634 if ( (portstate & 0xe0)==0xa0 ) 00635 { 00636 YM_DELTAT_synthesis_from_external_memory(this); 00637 return; 00638 } 00639 00640 if ( (portstate & 0xe0)==0x80 ) 00641 { 00642 /* ADPCM synthesis from CPU-managed memory (from reg $08) */ 00643 YM_DELTAT_synthesis_from_CPU_memory(this); /* change output based on data in ADPCM data reg ($08) */ 00644 return; 00645 } 00646 00647 //todo: ADPCM analysis 00648 // if ( (portstate & 0xe0)==0xc0 ) 00649 // if ( (portstate & 0xe0)==0xe0 ) 00650 00651 return; 00652 }