trunk/src/emu/sound/multipcm.c
| r24581 | r24582 | |
| 33 | 33 | |
| 34 | 34 | #include "emu.h" |
| 35 | 35 | #include "multipcm.h" |
| 36 | | #include "devlegcy.h" |
| 37 | 36 | |
| 38 | 37 | //???? |
| 39 | 38 | #define MULTIPCM_CLOCKDIV (180.0) |
| 40 | 39 | |
| 41 | | struct Sample_t |
| 42 | | { |
| 43 | | unsigned int Start; |
| 44 | | unsigned int Loop; |
| 45 | | unsigned int End; |
| 46 | | unsigned char AR,DR1,DR2,DL,RR; |
| 47 | | unsigned char KRS; |
| 48 | | unsigned char LFOVIB; |
| 49 | | unsigned char AM; |
| 50 | | }; |
| 51 | | |
| 52 | | enum STATE {ATTACK,DECAY1,DECAY2,RELEASE}; |
| 53 | 40 | ALLOW_SAVE_TYPE(STATE); // allow save_item on a non-fundamental type |
| 54 | | struct EG_t |
| 55 | | { |
| 56 | | int volume; // |
| 57 | | STATE state; |
| 58 | | int step; |
| 59 | | //step vals |
| 60 | | int AR; //Attack |
| 61 | | int D1R; //Decay1 |
| 62 | | int D2R; //Decay2 |
| 63 | | int RR; //Release |
| 64 | | int DL; //Decay level |
| 65 | | }; |
| 66 | 41 | |
| 67 | | struct LFO_t |
| 68 | | { |
| 69 | | unsigned short phase; |
| 70 | | UINT32 phase_step; |
| 71 | | int *table; |
| 72 | | int *scale; |
| 73 | | }; |
| 74 | | |
| 75 | | |
| 76 | | struct SLOT |
| 77 | | { |
| 78 | | unsigned char Num; |
| 79 | | unsigned char Regs[8]; |
| 80 | | int Playing; |
| 81 | | Sample_t *Sample; |
| 82 | | unsigned int Base; |
| 83 | | unsigned int offset; |
| 84 | | unsigned int step; |
| 85 | | unsigned int Pan,TL; |
| 86 | | unsigned int DstTL; |
| 87 | | int TLStep; |
| 88 | | signed int Prev; |
| 89 | | EG_t EG; |
| 90 | | LFO_t PLFO; //Phase lfo |
| 91 | | LFO_t ALFO; //AM lfo |
| 92 | | }; |
| 93 | | |
| 94 | | struct MultiPCM |
| 95 | | { |
| 96 | | sound_stream * stream; |
| 97 | | Sample_t Samples[0x200]; //Max 512 samples |
| 98 | | SLOT Slots[28]; |
| 99 | | unsigned int CurSlot; |
| 100 | | unsigned int Address; |
| 101 | | unsigned int BankR,BankL; |
| 102 | | float Rate; |
| 103 | | INT8 *ROM; |
| 104 | | //I include these in the chip because they depend on the chip clock |
| 105 | | unsigned int ARStep[0x40],DRStep[0x40]; //Envelope step table |
| 106 | | unsigned int FNS_Table[0x400]; //Frequency step table |
| 107 | | }; |
| 108 | | |
| 109 | | |
| 110 | 42 | static signed int LPANTABLE[0x800],RPANTABLE[0x800]; |
| 111 | 43 | |
| 112 | 44 | #define FIX(v) ((UINT32) ((float) (1<<SHIFT)*(v))) |
| r24581 | r24582 | |
| 126 | 58 | #define MULTIPCM_RATE 44100.0 |
| 127 | 59 | |
| 128 | 60 | |
| 129 | | INLINE MultiPCM *get_safe_token(device_t *device) |
| 130 | | { |
| 131 | | assert(device != NULL); |
| 132 | | assert(device->type() == MULTIPCM); |
| 133 | | return (MultiPCM *)downcast<multipcm_device *>(device)->token(); |
| 134 | | } |
| 135 | 61 | |
| 136 | 62 | |
| 137 | 63 | /******************************* |
| r24581 | r24582 | |
| 202 | 128 | return Steps[r]; |
| 203 | 129 | } |
| 204 | 130 | |
| 205 | | static void EG_Calc(MultiPCM *ptChip,SLOT *slot) |
| 131 | void multipcm_device::EG_Calc(SLOT *slot) |
| 206 | 132 | { |
| 207 | 133 | int octave=((slot->Regs[3]>>4)-1)&0xf; |
| 208 | 134 | int rate; |
| r24581 | r24582 | |
| 212 | 138 | else |
| 213 | 139 | rate=0; |
| 214 | 140 | |
| 215 | | slot->EG.AR=Get_RATE(ptChip->ARStep,rate,slot->Sample->AR); |
| 216 | | slot->EG.D1R=Get_RATE(ptChip->DRStep,rate,slot->Sample->DR1); |
| 217 | | slot->EG.D2R=Get_RATE(ptChip->DRStep,rate,slot->Sample->DR2); |
| 218 | | slot->EG.RR=Get_RATE(ptChip->DRStep,rate,slot->Sample->RR); |
| 141 | slot->EG.AR=Get_RATE(m_ARStep,rate,slot->Sample->AR); |
| 142 | slot->EG.D1R=Get_RATE(m_DRStep,rate,slot->Sample->DR1); |
| 143 | slot->EG.D2R=Get_RATE(m_DRStep,rate,slot->Sample->DR2); |
| 144 | slot->EG.RR=Get_RATE(m_DRStep,rate,slot->Sample->RR); |
| 219 | 145 | slot->EG.DL=0xf-slot->Sample->DL; |
| 220 | 146 | |
| 221 | 147 | } |
| r24581 | r24582 | |
| 302 | 228 | return p<<(SHIFT-LFO_SHIFT); |
| 303 | 229 | } |
| 304 | 230 | |
| 305 | | static void LFO_ComputeStep(MultiPCM *ptChip,LFO_t *LFO,UINT32 LFOF,UINT32 LFOS,int ALFO) |
| 231 | void multipcm_device::LFO_ComputeStep(LFO_t *LFO,UINT32 LFOF,UINT32 LFOS,int ALFO) |
| 306 | 232 | { |
| 307 | | float step=(float) LFOFreq[LFOF]*256.0/(float) ptChip->Rate; |
| 233 | float step=(float) LFOFreq[LFOF]*256.0/(float) m_Rate; |
| 308 | 234 | LFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step); |
| 309 | 235 | if(ALFO) |
| 310 | 236 | { |
| r24581 | r24582 | |
| 320 | 246 | |
| 321 | 247 | |
| 322 | 248 | |
| 323 | | static void WriteSlot(MultiPCM *ptChip,SLOT *slot,int reg,unsigned char data) |
| 249 | void multipcm_device::WriteSlot(SLOT *slot,int reg,unsigned char data) |
| 324 | 250 | { |
| 325 | 251 | slot->Regs[reg]=data; |
| 326 | 252 | |
| r24581 | r24582 | |
| 333 | 259 | //according to YMF278 sample write causes some base params written to the regs (envelope+lfos) |
| 334 | 260 | //the game should never change the sample while playing. |
| 335 | 261 | { |
| 336 | | Sample_t *Sample=ptChip->Samples+slot->Regs[1]; |
| 337 | | WriteSlot(ptChip,slot,6,Sample->LFOVIB); |
| 338 | | WriteSlot(ptChip,slot,7,Sample->AM); |
| 262 | Sample_t *Sample=m_Samples+slot->Regs[1]; |
| 263 | WriteSlot(slot,6,Sample->LFOVIB); |
| 264 | WriteSlot(slot,7,Sample->AM); |
| 339 | 265 | } |
| 340 | 266 | break; |
| 341 | 267 | case 2: //Pitch |
| r24581 | r24582 | |
| 343 | 269 | { |
| 344 | 270 | unsigned int oct=((slot->Regs[3]>>4)-1)&0xf; |
| 345 | 271 | unsigned int pitch=((slot->Regs[3]&0xf)<<6)|(slot->Regs[2]>>2); |
| 346 | | pitch=ptChip->FNS_Table[pitch]; |
| 272 | pitch=m_FNS_Table[pitch]; |
| 347 | 273 | if(oct&0x8) |
| 348 | 274 | pitch>>=(16-oct); |
| 349 | 275 | else |
| 350 | 276 | pitch<<=oct; |
| 351 | | slot->step=pitch/ptChip->Rate; |
| 277 | slot->step=pitch/m_Rate; |
| 352 | 278 | } |
| 353 | 279 | break; |
| 354 | 280 | case 4: //KeyOn/Off (and more?) |
| 355 | 281 | { |
| 356 | 282 | if(data&0x80) //KeyOn |
| 357 | 283 | { |
| 358 | | slot->Sample=ptChip->Samples+slot->Regs[1]; |
| 284 | slot->Sample=m_Samples+slot->Regs[1]; |
| 359 | 285 | slot->Playing=1; |
| 360 | 286 | slot->Base=slot->Sample->Start; |
| 361 | 287 | slot->offset=0; |
| 362 | 288 | slot->Prev=0; |
| 363 | 289 | slot->TL=slot->DstTL<<SHIFT; |
| 364 | 290 | |
| 365 | | EG_Calc(ptChip,slot); |
| 291 | EG_Calc(slot); |
| 366 | 292 | slot->EG.state=ATTACK; |
| 367 | 293 | slot->EG.volume=0; |
| 368 | 294 | |
| 369 | 295 | if(slot->Base>=0x100000) |
| 370 | 296 | { |
| 371 | 297 | if(slot->Pan&8) |
| 372 | | slot->Base=(slot->Base&0xfffff)|(ptChip->BankL); |
| 298 | slot->Base=(slot->Base&0xfffff)|(m_BankL); |
| 373 | 299 | else |
| 374 | | slot->Base=(slot->Base&0xfffff)|(ptChip->BankR); |
| 300 | slot->Base=(slot->Base&0xfffff)|(m_BankR); |
| 375 | 301 | } |
| 376 | 302 | |
| 377 | 303 | } |
| r24581 | r24582 | |
| 405 | 331 | { |
| 406 | 332 | if(data) |
| 407 | 333 | { |
| 408 | | LFO_ComputeStep(ptChip,&(slot->PLFO),(slot->Regs[6]>>3)&7,slot->Regs[6]&7,0); |
| 409 | | LFO_ComputeStep(ptChip,&(slot->ALFO),(slot->Regs[6]>>3)&7,slot->Regs[7]&7,1); |
| 334 | LFO_ComputeStep(&(slot->PLFO),(slot->Regs[6]>>3)&7,slot->Regs[6]&7,0); |
| 335 | LFO_ComputeStep(&(slot->ALFO),(slot->Regs[6]>>3)&7,slot->Regs[7]&7,1); |
| 410 | 336 | } |
| 411 | 337 | } |
| 412 | 338 | break; |
| r24581 | r24582 | |
| 414 | 340 | { |
| 415 | 341 | if(data) |
| 416 | 342 | { |
| 417 | | LFO_ComputeStep(ptChip,&(slot->PLFO),(slot->Regs[6]>>3)&7,slot->Regs[6]&7,0); |
| 418 | | LFO_ComputeStep(ptChip,&(slot->ALFO),(slot->Regs[6]>>3)&7,slot->Regs[7]&7,1); |
| 343 | LFO_ComputeStep(&(slot->PLFO),(slot->Regs[6]>>3)&7,slot->Regs[6]&7,0); |
| 344 | LFO_ComputeStep(&(slot->ALFO),(slot->Regs[6]>>3)&7,slot->Regs[7]&7,1); |
| 419 | 345 | } |
| 420 | 346 | } |
| 421 | 347 | break; |
| 422 | 348 | } |
| 423 | 349 | } |
| 424 | 350 | |
| 425 | | static STREAM_UPDATE( MultiPCM_update ) |
| 351 | READ8_MEMBER( multipcm_device::read ) |
| 426 | 352 | { |
| 427 | | MultiPCM *ptChip = (MultiPCM *)param; |
| 428 | | stream_sample_t *datap[2]; |
| 429 | | int i,sl; |
| 353 | return 0; |
| 354 | } |
| 430 | 355 | |
| 431 | | datap[0] = outputs[0]; |
| 432 | | datap[1] = outputs[1]; |
| 433 | 356 | |
| 434 | | memset(datap[0], 0, sizeof(*datap[0])*samples); |
| 435 | | memset(datap[1], 0, sizeof(*datap[1])*samples); |
| 436 | | |
| 437 | | |
| 438 | | for(i=0;i<samples;++i) |
| 357 | WRITE8_MEMBER( multipcm_device::write ) |
| 358 | { |
| 359 | switch(offset) |
| 439 | 360 | { |
| 440 | | signed int smpl=0; |
| 441 | | signed int smpr=0; |
| 442 | | for(sl=0;sl<28;++sl) |
| 443 | | { |
| 444 | | SLOT *slot=ptChip->Slots+sl; |
| 445 | | if(slot->Playing) |
| 446 | | { |
| 447 | | unsigned int vol=(slot->TL>>SHIFT)|(slot->Pan<<7); |
| 448 | | unsigned int adr=slot->offset>>SHIFT; |
| 449 | | signed int sample; |
| 450 | | unsigned int step=slot->step; |
| 451 | | signed int csample=(signed short) (ptChip->ROM[slot->Base+adr]<<8); |
| 452 | | signed int fpart=slot->offset&((1<<SHIFT)-1); |
| 453 | | sample=(csample*fpart+slot->Prev*((1<<SHIFT)-fpart))>>SHIFT; |
| 361 | case 0: //Data write |
| 362 | WriteSlot(m_Slots+m_CurSlot,m_Address,data); |
| 363 | break; |
| 364 | case 1: |
| 365 | m_CurSlot=val2chan[data&0x1f]; |
| 366 | break; |
| 454 | 367 | |
| 455 | | if(slot->Regs[6]&7) //Vibrato enabled |
| 456 | | { |
| 457 | | step=step*PLFO_Step(&(slot->PLFO)); |
| 458 | | step>>=SHIFT; |
| 459 | | } |
| 368 | case 2: |
| 369 | m_Address=(data>7)?7:data; |
| 370 | break; |
| 371 | } |
| 372 | } |
| 460 | 373 | |
| 461 | | slot->offset+=step; |
| 462 | | if(slot->offset>=(slot->Sample->End<<SHIFT)) |
| 463 | | { |
| 464 | | slot->offset=slot->Sample->Loop<<SHIFT; |
| 465 | | } |
| 466 | | if(adr^(slot->offset>>SHIFT)) |
| 467 | | { |
| 468 | | slot->Prev=csample; |
| 469 | | } |
| 374 | /* MAME/M1 access functions */ |
| 470 | 375 | |
| 471 | | if((slot->TL>>SHIFT)!=slot->DstTL) |
| 472 | | slot->TL+=slot->TLStep; |
| 376 | void multipcm_device::set_bank(UINT32 leftoffs, UINT32 rightoffs) |
| 377 | { |
| 378 | m_BankL = leftoffs; |
| 379 | m_BankR = rightoffs; |
| 380 | } |
| 473 | 381 | |
| 474 | | if(slot->Regs[7]&7) //Tremolo enabled |
| 475 | | { |
| 476 | | sample=sample*ALFO_Step(&(slot->ALFO)); |
| 477 | | sample>>=SHIFT; |
| 478 | | } |
| 382 | const device_type MULTIPCM = &device_creator<multipcm_device>; |
| 479 | 383 | |
| 480 | | sample=(sample*EG_Update(slot))>>10; |
| 481 | | |
| 482 | | smpl+=(LPANTABLE[vol]*sample)>>SHIFT; |
| 483 | | smpr+=(RPANTABLE[vol]*sample)>>SHIFT; |
| 484 | | } |
| 485 | | } |
| 486 | | #define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x) |
| 487 | | datap[0][i]=ICLIP16(smpl); |
| 488 | | datap[1][i]=ICLIP16(smpr); |
| 489 | | } |
| 384 | multipcm_device::multipcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 385 | : device_t(mconfig, MULTIPCM, "Sega/Yamaha 315-5560", tag, owner, clock, "multipcm", __FILE__), |
| 386 | device_sound_interface(mconfig, *this), |
| 387 | m_stream(NULL), |
| 388 | //m_Samples(0x200), |
| 389 | //m_Slots[28], |
| 390 | m_CurSlot(0), |
| 391 | m_Address(0), |
| 392 | m_BankR(0), |
| 393 | m_BankL(0), |
| 394 | m_Rate(0), |
| 395 | m_ROM(NULL) |
| 396 | //m_ARStep(0), |
| 397 | //m_DRStep(0), |
| 398 | //m_FNS_Table(0) |
| 399 | { |
| 490 | 400 | } |
| 491 | 401 | |
| 492 | | READ8_DEVICE_HANDLER( multipcm_r ) |
| 402 | //------------------------------------------------- |
| 403 | // device_config_complete - perform any |
| 404 | // operations now that the configuration is |
| 405 | // complete |
| 406 | //------------------------------------------------- |
| 407 | |
| 408 | void multipcm_device::device_config_complete() |
| 493 | 409 | { |
| 494 | | // MultiPCM *ptChip = get_safe_token(device); |
| 495 | | return 0; |
| 496 | 410 | } |
| 497 | 411 | |
| 498 | | static DEVICE_START( multipcm ) |
| 412 | //------------------------------------------------- |
| 413 | // device_start - device-specific startup |
| 414 | //------------------------------------------------- |
| 415 | |
| 416 | void multipcm_device::device_start() |
| 499 | 417 | { |
| 500 | | MultiPCM *ptChip = get_safe_token(device); |
| 501 | | int i; |
| 418 | int i; |
| 502 | 419 | |
| 503 | | ptChip->ROM=*device->region(); |
| 504 | | ptChip->Rate=(float) device->clock() / MULTIPCM_CLOCKDIV; |
| 420 | m_ROM=*region(); |
| 421 | m_Rate=(float) clock() / MULTIPCM_CLOCKDIV; |
| 505 | 422 | |
| 506 | | ptChip->stream = device->machine().sound().stream_alloc(*device, 0, 2, ptChip->Rate, ptChip, MultiPCM_update); |
| 423 | m_stream = machine().sound().stream_alloc(*this, 0, 2, m_Rate, this); |
| 507 | 424 | |
| 508 | 425 | //Volume+pan table |
| 509 | 426 | for(i=0;i<0x800;++i) |
| r24581 | r24582 | |
| 561 | 478 | //Pitch steps |
| 562 | 479 | for(i=0;i<0x400;++i) |
| 563 | 480 | { |
| 564 | | float fcent=ptChip->Rate*(1024.0+(float) i)/1024.0; |
| 565 | | ptChip->FNS_Table[i]=(unsigned int ) ((float) (1<<SHIFT) *fcent); |
| 481 | float fcent=m_Rate*(1024.0+(float) i)/1024.0; |
| 482 | m_FNS_Table[i]=(unsigned int ) ((float) (1<<SHIFT) *fcent); |
| 566 | 483 | } |
| 567 | 484 | |
| 568 | 485 | //Envelope steps |
| 569 | 486 | for(i=0;i<0x40;++i) |
| 570 | 487 | { |
| 571 | 488 | //Times are based on 44100 clock, adjust to real chip clock |
| 572 | | ptChip->ARStep[i]=(float) (0x400<<EG_SHIFT)/(BaseTimes[i]*44100.0/(1000.0)); |
| 573 | | ptChip->DRStep[i]=(float) (0x400<<EG_SHIFT)/(BaseTimes[i]*AR2DR*44100.0/(1000.0)); |
| 489 | m_ARStep[i]=(float) (0x400<<EG_SHIFT)/(BaseTimes[i]*44100.0/(1000.0)); |
| 490 | m_DRStep[i]=(float) (0x400<<EG_SHIFT)/(BaseTimes[i]*AR2DR*44100.0/(1000.0)); |
| 574 | 491 | } |
| 575 | | ptChip->ARStep[0]=ptChip->ARStep[1]=ptChip->ARStep[2]=ptChip->ARStep[3]=0; |
| 576 | | ptChip->ARStep[0x3f]=0x400<<EG_SHIFT; |
| 577 | | ptChip->DRStep[0]=ptChip->DRStep[1]=ptChip->DRStep[2]=ptChip->DRStep[3]=0; |
| 492 | m_ARStep[0]=m_ARStep[1]=m_ARStep[2]=m_ARStep[3]=0; |
| 493 | m_ARStep[0x3f]=0x400<<EG_SHIFT; |
| 494 | m_DRStep[0]=m_DRStep[1]=m_DRStep[2]=m_DRStep[3]=0; |
| 578 | 495 | |
| 579 | 496 | //TL Interpolation steps |
| 580 | 497 | //lower |
| r24581 | r24582 | |
| 592 | 509 | |
| 593 | 510 | for(i=0;i<512;++i) |
| 594 | 511 | { |
| 595 | | UINT8 *ptSample=(UINT8 *) ptChip->ROM+i*12; |
| 596 | | ptChip->Samples[i].Start=(ptSample[0]<<16)|(ptSample[1]<<8)|(ptSample[2]<<0); |
| 597 | | ptChip->Samples[i].Loop=(ptSample[3]<<8)|(ptSample[4]<<0); |
| 598 | | ptChip->Samples[i].End=0xffff-((ptSample[5]<<8)|(ptSample[6]<<0)); |
| 599 | | ptChip->Samples[i].LFOVIB=ptSample[7]; |
| 600 | | ptChip->Samples[i].DR1=ptSample[8]&0xf; |
| 601 | | ptChip->Samples[i].AR=(ptSample[8]>>4)&0xf; |
| 602 | | ptChip->Samples[i].DR2=ptSample[9]&0xf; |
| 603 | | ptChip->Samples[i].DL=(ptSample[9]>>4)&0xf; |
| 604 | | ptChip->Samples[i].RR=ptSample[10]&0xf; |
| 605 | | ptChip->Samples[i].KRS=(ptSample[10]>>4)&0xf; |
| 606 | | ptChip->Samples[i].AM=ptSample[11]; |
| 512 | UINT8 *ptSample=(UINT8 *) m_ROM+i*12; |
| 513 | m_Samples[i].Start=(ptSample[0]<<16)|(ptSample[1]<<8)|(ptSample[2]<<0); |
| 514 | m_Samples[i].Loop=(ptSample[3]<<8)|(ptSample[4]<<0); |
| 515 | m_Samples[i].End=0xffff-((ptSample[5]<<8)|(ptSample[6]<<0)); |
| 516 | m_Samples[i].LFOVIB=ptSample[7]; |
| 517 | m_Samples[i].DR1=ptSample[8]&0xf; |
| 518 | m_Samples[i].AR=(ptSample[8]>>4)&0xf; |
| 519 | m_Samples[i].DR2=ptSample[9]&0xf; |
| 520 | m_Samples[i].DL=(ptSample[9]>>4)&0xf; |
| 521 | m_Samples[i].RR=ptSample[10]&0xf; |
| 522 | m_Samples[i].KRS=(ptSample[10]>>4)&0xf; |
| 523 | m_Samples[i].AM=ptSample[11]; |
| 607 | 524 | } |
| 608 | 525 | |
| 609 | | device->save_item(NAME(ptChip->CurSlot)); |
| 610 | | device->save_item(NAME(ptChip->Address)); |
| 611 | | device->save_item(NAME(ptChip->BankL)); |
| 612 | | device->save_item(NAME(ptChip->BankR)); |
| 526 | save_item(NAME(m_CurSlot)); |
| 527 | save_item(NAME(m_Address)); |
| 528 | save_item(NAME(m_BankL)); |
| 529 | save_item(NAME(m_BankR)); |
| 613 | 530 | |
| 614 | 531 | for(i=0;i<28;++i) |
| 615 | 532 | { |
| 616 | | ptChip->Slots[i].Num=i; |
| 617 | | ptChip->Slots[i].Playing=0; |
| 533 | m_Slots[i].Num=i; |
| 534 | m_Slots[i].Playing=0; |
| 618 | 535 | |
| 619 | | device->save_item(NAME(ptChip->Slots[i].Num), i); |
| 620 | | device->save_item(NAME(ptChip->Slots[i].Regs), i); |
| 621 | | device->save_item(NAME(ptChip->Slots[i].Playing), i); |
| 622 | | device->save_item(NAME(ptChip->Slots[i].Base), i); |
| 623 | | device->save_item(NAME(ptChip->Slots[i].offset), i); |
| 624 | | device->save_item(NAME(ptChip->Slots[i].step), i); |
| 625 | | device->save_item(NAME(ptChip->Slots[i].Pan), i); |
| 626 | | device->save_item(NAME(ptChip->Slots[i].TL), i); |
| 627 | | device->save_item(NAME(ptChip->Slots[i].DstTL), i); |
| 628 | | device->save_item(NAME(ptChip->Slots[i].TLStep), i); |
| 629 | | device->save_item(NAME(ptChip->Slots[i].Prev), i); |
| 630 | | device->save_item(NAME(ptChip->Slots[i].EG.volume), i); |
| 631 | | device->save_item(NAME(ptChip->Slots[i].EG.state), i); |
| 632 | | device->save_item(NAME(ptChip->Slots[i].EG.step), i); |
| 633 | | device->save_item(NAME(ptChip->Slots[i].EG.AR), i); |
| 634 | | device->save_item(NAME(ptChip->Slots[i].EG.D1R), i); |
| 635 | | device->save_item(NAME(ptChip->Slots[i].EG.D2R), i); |
| 636 | | device->save_item(NAME(ptChip->Slots[i].EG.RR), i); |
| 637 | | device->save_item(NAME(ptChip->Slots[i].EG.DL), i); |
| 638 | | device->save_item(NAME(ptChip->Slots[i].PLFO.phase), i); |
| 639 | | device->save_item(NAME(ptChip->Slots[i].PLFO.phase_step), i); |
| 640 | | device->save_item(NAME(ptChip->Slots[i].ALFO.phase), i); |
| 641 | | device->save_item(NAME(ptChip->Slots[i].ALFO.phase_step), i); |
| 536 | save_item(NAME(m_Slots[i].Num), i); |
| 537 | save_item(NAME(m_Slots[i].Regs), i); |
| 538 | save_item(NAME(m_Slots[i].Playing), i); |
| 539 | save_item(NAME(m_Slots[i].Base), i); |
| 540 | save_item(NAME(m_Slots[i].offset), i); |
| 541 | save_item(NAME(m_Slots[i].step), i); |
| 542 | save_item(NAME(m_Slots[i].Pan), i); |
| 543 | save_item(NAME(m_Slots[i].TL), i); |
| 544 | save_item(NAME(m_Slots[i].DstTL), i); |
| 545 | save_item(NAME(m_Slots[i].TLStep), i); |
| 546 | save_item(NAME(m_Slots[i].Prev), i); |
| 547 | save_item(NAME(m_Slots[i].EG.volume), i); |
| 548 | save_item(NAME(m_Slots[i].EG.state), i); |
| 549 | save_item(NAME(m_Slots[i].EG.step), i); |
| 550 | save_item(NAME(m_Slots[i].EG.AR), i); |
| 551 | save_item(NAME(m_Slots[i].EG.D1R), i); |
| 552 | save_item(NAME(m_Slots[i].EG.D2R), i); |
| 553 | save_item(NAME(m_Slots[i].EG.RR), i); |
| 554 | save_item(NAME(m_Slots[i].EG.DL), i); |
| 555 | save_item(NAME(m_Slots[i].PLFO.phase), i); |
| 556 | save_item(NAME(m_Slots[i].PLFO.phase_step), i); |
| 557 | save_item(NAME(m_Slots[i].ALFO.phase), i); |
| 558 | save_item(NAME(m_Slots[i].ALFO.phase_step), i); |
| 642 | 559 | } |
| 643 | 560 | |
| 644 | 561 | LFO_Init(); |
| 645 | 562 | } |
| 646 | 563 | |
| 564 | //------------------------------------------------- |
| 565 | // sound_stream_update - handle a stream update |
| 566 | //------------------------------------------------- |
| 647 | 567 | |
| 648 | | WRITE8_DEVICE_HANDLER( multipcm_w ) |
| 568 | void multipcm_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 649 | 569 | { |
| 650 | | MultiPCM *ptChip = get_safe_token(device); |
| 651 | | switch(offset) |
| 652 | | { |
| 653 | | case 0: //Data write |
| 654 | | WriteSlot(ptChip,ptChip->Slots+ptChip->CurSlot,ptChip->Address,data); |
| 655 | | break; |
| 656 | | case 1: |
| 657 | | ptChip->CurSlot=val2chan[data&0x1f]; |
| 658 | | break; |
| 570 | stream_sample_t *datap[2]; |
| 571 | int i,sl; |
| 659 | 572 | |
| 660 | | case 2: |
| 661 | | ptChip->Address=(data>7)?7:data; |
| 662 | | break; |
| 663 | | } |
| 664 | | } |
| 573 | datap[0] = outputs[0]; |
| 574 | datap[1] = outputs[1]; |
| 665 | 575 | |
| 666 | | /* MAME/M1 access functions */ |
| 576 | memset(datap[0], 0, sizeof(*datap[0])*samples); |
| 577 | memset(datap[1], 0, sizeof(*datap[1])*samples); |
| 667 | 578 | |
| 668 | | void multipcm_set_bank(device_t *device, UINT32 leftoffs, UINT32 rightoffs) |
| 669 | | { |
| 670 | | MultiPCM *ptChip = get_safe_token(device); |
| 671 | | ptChip->BankL = leftoffs; |
| 672 | | ptChip->BankR = rightoffs; |
| 673 | | } |
| 674 | 579 | |
| 580 | for(i=0;i<samples;++i) |
| 581 | { |
| 582 | signed int smpl=0; |
| 583 | signed int smpr=0; |
| 584 | for(sl=0;sl<28;++sl) |
| 585 | { |
| 586 | SLOT *slot=m_Slots+sl; |
| 587 | if(slot->Playing) |
| 588 | { |
| 589 | unsigned int vol=(slot->TL>>SHIFT)|(slot->Pan<<7); |
| 590 | unsigned int adr=slot->offset>>SHIFT; |
| 591 | signed int sample; |
| 592 | unsigned int step=slot->step; |
| 593 | signed int csample=(signed short) (m_ROM[slot->Base+adr]<<8); |
| 594 | signed int fpart=slot->offset&((1<<SHIFT)-1); |
| 595 | sample=(csample*fpart+slot->Prev*((1<<SHIFT)-fpart))>>SHIFT; |
| 675 | 596 | |
| 676 | | const device_type MULTIPCM = &device_creator<multipcm_device>; |
| 597 | if(slot->Regs[6]&7) //Vibrato enabled |
| 598 | { |
| 599 | step=step*PLFO_Step(&(slot->PLFO)); |
| 600 | step>>=SHIFT; |
| 601 | } |
| 677 | 602 | |
| 678 | | multipcm_device::multipcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 679 | | : device_t(mconfig, MULTIPCM, "Sega/Yamaha 315-5560", tag, owner, clock, "multipcm", __FILE__), |
| 680 | | device_sound_interface(mconfig, *this) |
| 681 | | { |
| 682 | | m_token = global_alloc_clear(MultiPCM); |
| 683 | | } |
| 603 | slot->offset+=step; |
| 604 | if(slot->offset>=(slot->Sample->End<<SHIFT)) |
| 605 | { |
| 606 | slot->offset=slot->Sample->Loop<<SHIFT; |
| 607 | } |
| 608 | if(adr^(slot->offset>>SHIFT)) |
| 609 | { |
| 610 | slot->Prev=csample; |
| 611 | } |
| 684 | 612 | |
| 685 | | //------------------------------------------------- |
| 686 | | // device_config_complete - perform any |
| 687 | | // operations now that the configuration is |
| 688 | | // complete |
| 689 | | //------------------------------------------------- |
| 613 | if((slot->TL>>SHIFT)!=slot->DstTL) |
| 614 | slot->TL+=slot->TLStep; |
| 690 | 615 | |
| 691 | | void multipcm_device::device_config_complete() |
| 692 | | { |
| 693 | | } |
| 616 | if(slot->Regs[7]&7) //Tremolo enabled |
| 617 | { |
| 618 | sample=sample*ALFO_Step(&(slot->ALFO)); |
| 619 | sample>>=SHIFT; |
| 620 | } |
| 694 | 621 | |
| 695 | | //------------------------------------------------- |
| 696 | | // device_start - device-specific startup |
| 697 | | //------------------------------------------------- |
| 622 | sample=(sample*EG_Update(slot))>>10; |
| 698 | 623 | |
| 699 | | void multipcm_device::device_start() |
| 700 | | { |
| 701 | | DEVICE_START_NAME( multipcm )(this); |
| 624 | smpl+=(LPANTABLE[vol]*sample)>>SHIFT; |
| 625 | smpr+=(RPANTABLE[vol]*sample)>>SHIFT; |
| 626 | } |
| 627 | } |
| 628 | #define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x) |
| 629 | datap[0][i]=ICLIP16(smpl); |
| 630 | datap[1][i]=ICLIP16(smpr); |
| 631 | } |
| 702 | 632 | } |
| 703 | | |
| 704 | | //------------------------------------------------- |
| 705 | | // sound_stream_update - handle a stream update |
| 706 | | //------------------------------------------------- |
| 707 | | |
| 708 | | void multipcm_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 709 | | { |
| 710 | | // should never get here |
| 711 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
| 712 | | } |
trunk/src/mame/drivers/mjkjidai.c
| r24581 | r24582 | |
| 24 | 24 | #include "emu.h" |
| 25 | 25 | #include "cpu/z80/z80.h" |
| 26 | 26 | #include "sound/sn76496.h" |
| 27 | | #include "sound/okiadpcm.h" |
| 28 | 27 | #include "includes/mjkjidai.h" |
| 29 | | #include "devlegcy.h" |
| 30 | 28 | #include "mcfglgcy.h" |
| 31 | 29 | |
| 32 | | class mjkjidai_adpcm_device : public device_t, |
| 33 | | public device_sound_interface |
| 34 | | { |
| 35 | | public: |
| 36 | | mjkjidai_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 37 | | ~mjkjidai_adpcm_device() { global_free(m_token); } |
| 38 | | |
| 39 | | // access to legacy token |
| 40 | | void *token() const { assert(m_token != NULL); return m_token; } |
| 41 | | protected: |
| 42 | | // device-level overrides |
| 43 | | virtual void device_config_complete(); |
| 44 | | virtual void device_start(); |
| 45 | | |
| 46 | | // sound stream update overrides |
| 47 | | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
| 48 | | private: |
| 49 | | // internal state |
| 50 | | void *m_token; |
| 51 | | }; |
| 52 | | |
| 53 | | extern const device_type MJKJIDAI; |
| 54 | | |
| 55 | 30 | /* Start of ADPCM custom chip code */ |
| 56 | | struct mjkjidai_adpcm_state |
| 57 | | { |
| 58 | | oki_adpcm_state m_adpcm; |
| 59 | | sound_stream *m_stream; |
| 60 | | UINT32 m_current; |
| 61 | | UINT32 m_end; |
| 62 | | UINT8 m_nibble; |
| 63 | | UINT8 m_playing; |
| 64 | | UINT8 *m_base; |
| 65 | | } _mjkjidai_adpcm_state_dummy; |
| 66 | 31 | |
| 67 | | static STREAM_UPDATE( mjkjidai_adpcm_callback ) |
| 68 | | { |
| 69 | | mjkjidai_adpcm_state *state = (mjkjidai_adpcm_state *)param; |
| 70 | | stream_sample_t *dest = outputs[0]; |
| 71 | | |
| 72 | | while (state->m_playing && samples > 0) |
| 73 | | { |
| 74 | | int val = (state->m_base[state->m_current] >> state->m_nibble) & 15; |
| 75 | | |
| 76 | | state->m_nibble ^= 4; |
| 77 | | if (state->m_nibble == 4) |
| 78 | | { |
| 79 | | state->m_current++; |
| 80 | | if (state->m_current >= state->m_end) |
| 81 | | state->m_playing = 0; |
| 82 | | } |
| 83 | | |
| 84 | | *dest++ = state->m_adpcm.clock(val) << 4; |
| 85 | | samples--; |
| 86 | | } |
| 87 | | while (samples > 0) |
| 88 | | { |
| 89 | | *dest++ = 0; |
| 90 | | samples--; |
| 91 | | } |
| 92 | | } |
| 93 | | |
| 94 | | static DEVICE_START( mjkjidai_adpcm ) |
| 95 | | { |
| 96 | | running_machine &machine = device->machine(); |
| 97 | | mjkjidai_adpcm_state *state = (mjkjidai_adpcm_state *)downcast<mjkjidai_adpcm_device *>(device)->token(); |
| 98 | | |
| 99 | | state->m_playing = 0; |
| 100 | | state->m_stream = device->machine().sound().stream_alloc(*device, 0, 1, device->clock(), state, mjkjidai_adpcm_callback); |
| 101 | | state->m_base = machine.root_device().memregion("adpcm")->base(); |
| 102 | | state->m_adpcm.reset(); |
| 103 | | } |
| 104 | | |
| 105 | 32 | const device_type MJKJIDAI = &device_creator<mjkjidai_adpcm_device>; |
| 106 | 33 | |
| 107 | 34 | mjkjidai_adpcm_device::mjkjidai_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 108 | 35 | : device_t(mconfig, MJKJIDAI, "Custom ADPCM", tag, owner, clock, "mjkjidai_adpcm", __FILE__), |
| 109 | | device_sound_interface(mconfig, *this) |
| 36 | device_sound_interface(mconfig, *this), |
| 37 | m_stream(NULL), |
| 38 | m_current(0), |
| 39 | m_end(0), |
| 40 | m_nibble(0), |
| 41 | m_playing(0), |
| 42 | m_base(NULL) |
| 110 | 43 | { |
| 111 | | m_token = global_alloc_clear(mjkjidai_adpcm_state); |
| 112 | 44 | } |
| 113 | 45 | |
| 114 | 46 | //------------------------------------------------- |
| r24581 | r24582 | |
| 127 | 59 | |
| 128 | 60 | void mjkjidai_adpcm_device::device_start() |
| 129 | 61 | { |
| 130 | | DEVICE_START_NAME( mjkjidai_adpcm )(this); |
| 62 | m_playing = 0; |
| 63 | m_stream = machine().sound().stream_alloc(*this, 0, 1, clock(), this); |
| 64 | m_base = machine().root_device().memregion("adpcm")->base(); |
| 65 | m_adpcm.reset(); |
| 66 | |
| 67 | save_item(NAME(m_current)); |
| 68 | save_item(NAME(m_end)); |
| 69 | save_item(NAME(m_nibble)); |
| 70 | save_item(NAME(m_playing)); |
| 131 | 71 | } |
| 132 | 72 | |
| 133 | 73 | //------------------------------------------------- |
| r24581 | r24582 | |
| 136 | 76 | |
| 137 | 77 | void mjkjidai_adpcm_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 138 | 78 | { |
| 139 | | // should never get here |
| 140 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
| 141 | | } |
| 79 | stream_sample_t *dest = outputs[0]; |
| 142 | 80 | |
| 81 | while (m_playing && samples > 0) |
| 82 | { |
| 83 | int val = (m_base[m_current] >> m_nibble) & 15; |
| 143 | 84 | |
| 85 | m_nibble ^= 4; |
| 86 | if (m_nibble == 4) |
| 87 | { |
| 88 | m_current++; |
| 89 | if (m_current >= m_end) |
| 90 | m_playing = 0; |
| 91 | } |
| 144 | 92 | |
| 93 | *dest++ = m_adpcm.clock(val) << 4; |
| 94 | samples--; |
| 95 | } |
| 96 | while (samples > 0) |
| 97 | { |
| 98 | *dest++ = 0; |
| 99 | samples--; |
| 100 | } |
| 101 | } |
| 145 | 102 | |
| 146 | | static void mjkjidai_adpcm_play (mjkjidai_adpcm_state *state, int offset, int length) |
| 103 | void mjkjidai_adpcm_device::mjkjidai_adpcm_play (int offset, int length) |
| 147 | 104 | { |
| 148 | | state->m_current = offset; |
| 149 | | state->m_end = offset + length/2; |
| 150 | | state->m_nibble = 4; |
| 151 | | state->m_playing = 1; |
| 105 | m_current = offset; |
| 106 | m_end = offset + length/2; |
| 107 | m_nibble = 4; |
| 108 | m_playing = 1; |
| 152 | 109 | } |
| 153 | 110 | |
| 154 | 111 | WRITE8_MEMBER(mjkjidai_state::adpcm_w) |
| 155 | 112 | { |
| 156 | | device_t *device = machine().device("adpcm"); |
| 157 | | mjkjidai_adpcm_state *state = (mjkjidai_adpcm_state *)downcast<mjkjidai_adpcm_device *>(device)->token(); |
| 158 | | mjkjidai_adpcm_play (state, (data & 0x07) * 0x1000, 0x1000 * 2); |
| 113 | m_mjk_adpcm->mjkjidai_adpcm_play ((data & 0x07) * 0x1000, 0x1000 * 2); |
| 159 | 114 | } |
| 160 | 115 | /* End of ADPCM custom chip code */ |
| 161 | 116 | |
trunk/src/mame/drivers/renegade.c
| r24581 | r24582 | |
| 105 | 105 | #include "cpu/m6809/m6809.h" |
| 106 | 106 | #include "cpu/m6805/m6805.h" |
| 107 | 107 | #include "sound/3526intf.h" |
| 108 | | #include "sound/okiadpcm.h" |
| 109 | 108 | #include "includes/renegade.h" |
| 110 | | #include "devlegcy.h" |
| 111 | 109 | |
| 112 | 110 | |
| 113 | 111 | /********************************************************************************************/ |
| 114 | 112 | |
| 115 | | struct renegade_adpcm_state |
| 116 | | { |
| 117 | | oki_adpcm_state m_adpcm; |
| 118 | | sound_stream *m_stream; |
| 119 | | UINT32 m_current; |
| 120 | | UINT32 m_end; |
| 121 | | UINT8 m_nibble; |
| 122 | | UINT8 m_playing; |
| 123 | | UINT8 *m_base; |
| 124 | | } _renegade_adpcm_state_dummy; |
| 125 | | |
| 126 | | class renegade_adpcm_device : public device_t, |
| 127 | | public device_sound_interface |
| 128 | | { |
| 129 | | public: |
| 130 | | renegade_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 131 | | ~renegade_adpcm_device() { global_free(m_token); } |
| 132 | | |
| 133 | | // access to legacy token |
| 134 | | void *token() const { assert(m_token != NULL); return m_token; } |
| 135 | | protected: |
| 136 | | // device-level overrides |
| 137 | | virtual void device_config_complete(); |
| 138 | | virtual void device_start(); |
| 139 | | |
| 140 | | // sound stream update overrides |
| 141 | | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
| 142 | | private: |
| 143 | | // internal state |
| 144 | | void *m_token; |
| 145 | | }; |
| 146 | | |
| 147 | | extern const device_type RENEGADE_ADPCM; |
| 148 | | |
| 149 | | |
| 150 | | INLINE renegade_adpcm_state *get_safe_token(device_t *device) |
| 151 | | { |
| 152 | | assert(device != NULL); |
| 153 | | assert(device->type() == RENEGADE_ADPCM); |
| 154 | | |
| 155 | | return (renegade_adpcm_state *)downcast<renegade_adpcm_device *>(device)->token(); |
| 156 | | } |
| 157 | | |
| 158 | | static STREAM_UPDATE( renegade_adpcm_callback ) |
| 159 | | { |
| 160 | | renegade_adpcm_state *state = (renegade_adpcm_state *)param; |
| 161 | | stream_sample_t *dest = outputs[0]; |
| 162 | | |
| 163 | | while (state->m_playing && samples > 0) |
| 164 | | { |
| 165 | | int val = (state->m_base[state->m_current] >> state->m_nibble) & 15; |
| 166 | | |
| 167 | | state->m_nibble ^= 4; |
| 168 | | if (state->m_nibble == 4) |
| 169 | | { |
| 170 | | state->m_current++; |
| 171 | | if (state->m_current >= state->m_end) |
| 172 | | state->m_playing = 0; |
| 173 | | } |
| 174 | | |
| 175 | | *dest++ = state->m_adpcm.clock(val) << 4; |
| 176 | | samples--; |
| 177 | | } |
| 178 | | while (samples > 0) |
| 179 | | { |
| 180 | | *dest++ = 0; |
| 181 | | samples--; |
| 182 | | } |
| 183 | | } |
| 184 | | |
| 185 | | static DEVICE_START( renegade_adpcm ) |
| 186 | | { |
| 187 | | renegade_adpcm_state *state = get_safe_token(device); |
| 188 | | state->m_playing = 0; |
| 189 | | state->m_stream = device->machine().sound().stream_alloc(*device, 0, 1, device->clock(), state, renegade_adpcm_callback); |
| 190 | | state->m_base = device->machine().root_device().memregion("adpcm")->base(); |
| 191 | | state->m_adpcm.reset(); |
| 192 | | } |
| 193 | | |
| 194 | 113 | const device_type RENEGADE_ADPCM = &device_creator<renegade_adpcm_device>; |
| 195 | 114 | |
| 196 | 115 | renegade_adpcm_device::renegade_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 197 | 116 | : device_t(mconfig, RENEGADE_ADPCM, "Renegade Custom ADPCM", tag, owner, clock, "renegade_adpcm", __FILE__), |
| 198 | | device_sound_interface(mconfig, *this) |
| 117 | device_sound_interface(mconfig, *this), |
| 118 | m_stream(NULL), |
| 119 | m_current(0), |
| 120 | m_end(0), |
| 121 | m_nibble(0), |
| 122 | m_playing(0), |
| 123 | m_base(NULL) |
| 199 | 124 | { |
| 200 | | m_token = global_alloc_clear(renegade_adpcm_state); |
| 201 | 125 | } |
| 202 | 126 | |
| 203 | 127 | //------------------------------------------------- |
| r24581 | r24582 | |
| 216 | 140 | |
| 217 | 141 | void renegade_adpcm_device::device_start() |
| 218 | 142 | { |
| 219 | | DEVICE_START_NAME( renegade_adpcm )(this); |
| 143 | m_playing = 0; |
| 144 | m_stream = machine().sound().stream_alloc(*this, 0, 1, clock(), this); |
| 145 | m_base = machine().root_device().memregion("adpcm")->base(); |
| 146 | m_adpcm.reset(); |
| 147 | |
| 148 | save_item(NAME(m_current)); |
| 149 | save_item(NAME(m_end)); |
| 150 | save_item(NAME(m_nibble)); |
| 151 | save_item(NAME(m_playing)); |
| 220 | 152 | } |
| 221 | 153 | |
| 222 | 154 | //------------------------------------------------- |
| r24581 | r24582 | |
| 225 | 157 | |
| 226 | 158 | void renegade_adpcm_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 227 | 159 | { |
| 228 | | // should never get here |
| 229 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
| 230 | | } |
| 160 | stream_sample_t *dest = outputs[0]; |
| 231 | 161 | |
| 162 | while (m_playing && samples > 0) |
| 163 | { |
| 164 | int val = (m_base[m_current] >> m_nibble) & 15; |
| 232 | 165 | |
| 166 | m_nibble ^= 4; |
| 167 | if (m_nibble == 4) |
| 168 | { |
| 169 | m_current++; |
| 170 | if (m_current >= m_end) |
| 171 | m_playing = 0; |
| 172 | } |
| 233 | 173 | |
| 174 | *dest++ = m_adpcm.clock(val) << 4; |
| 175 | samples--; |
| 176 | } |
| 177 | while (samples > 0) |
| 178 | { |
| 179 | *dest++ = 0; |
| 180 | samples--; |
| 181 | } |
| 182 | } |
| 234 | 183 | |
| 235 | | WRITE8_MEMBER(renegade_state::adpcm_play_w) |
| 184 | |
| 185 | WRITE8_MEMBER(renegade_adpcm_device::play_w) |
| 236 | 186 | { |
| 237 | | device_t *device = machine().device("adpcm"); |
| 238 | | renegade_adpcm_state *renstate = get_safe_token(device); |
| 239 | 187 | int offs = (data - 0x2c) * 0x2000; |
| 240 | 188 | int len = 0x2000 * 2; |
| 241 | 189 | |
| r24581 | r24582 | |
| 245 | 193 | |
| 246 | 194 | if (offs >= 0 && offs+len <= 0x20000) |
| 247 | 195 | { |
| 248 | | renstate->m_stream->update(); |
| 249 | | renstate->m_adpcm.reset(); |
| 196 | m_stream->update(); |
| 197 | m_adpcm.reset(); |
| 250 | 198 | |
| 251 | | renstate->m_current = offs; |
| 252 | | renstate->m_end = offs + len/2; |
| 253 | | renstate->m_nibble = 4; |
| 254 | | renstate->m_playing = 1; |
| 199 | m_current = offs; |
| 200 | m_end = offs + len/2; |
| 201 | m_nibble = 4; |
| 202 | m_playing = 1; |
| 255 | 203 | } |
| 256 | 204 | else |
| 257 | 205 | logerror("out of range adpcm command: 0x%02x\n", data); |
| r24581 | r24582 | |
| 705 | 653 | AM_RANGE(0x0000, 0x0fff) AM_RAM |
| 706 | 654 | AM_RANGE(0x1000, 0x1000) AM_READ(soundlatch_byte_r) |
| 707 | 655 | AM_RANGE(0x1800, 0x1800) AM_WRITENOP // this gets written the same values as 0x2000 |
| 708 | | AM_RANGE(0x2000, 0x2000) AM_WRITE(adpcm_play_w) |
| 656 | AM_RANGE(0x2000, 0x2000) AM_DEVWRITE("adpcm", renegade_adpcm_device, play_w) |
| 709 | 657 | AM_RANGE(0x2800, 0x2801) AM_DEVREADWRITE("ymsnd", ym3526_device, read, write) |
| 710 | 658 | AM_RANGE(0x3000, 0x3000) AM_WRITENOP /* adpcm related? stereo pan? */ |
| 711 | 659 | AM_RANGE(0x8000, 0xffff) AM_ROM |