Modernized MultiPCM, mjkjidai, renegage, ninjaw_subwoofer devices [Osso]

Multisession bug fix for exidy440 audio from Osso (nw)
This commit is contained in:
Scott Stone 2013-07-30 17:09:46 +00:00
parent ad4546e878
commit 6cf4b6c27f
14 changed files with 492 additions and 529 deletions

View File

@ -33,79 +33,11 @@
#include "emu.h" #include "emu.h"
#include "multipcm.h" #include "multipcm.h"
#include "devlegcy.h"
//???? //????
#define MULTIPCM_CLOCKDIV (180.0) #define MULTIPCM_CLOCKDIV (180.0)
struct Sample_t
{
unsigned int Start;
unsigned int Loop;
unsigned int End;
unsigned char AR,DR1,DR2,DL,RR;
unsigned char KRS;
unsigned char LFOVIB;
unsigned char AM;
};
enum STATE {ATTACK,DECAY1,DECAY2,RELEASE};
ALLOW_SAVE_TYPE(STATE); // allow save_item on a non-fundamental type ALLOW_SAVE_TYPE(STATE); // allow save_item on a non-fundamental type
struct EG_t
{
int volume; //
STATE state;
int step;
//step vals
int AR; //Attack
int D1R; //Decay1
int D2R; //Decay2
int RR; //Release
int DL; //Decay level
};
struct LFO_t
{
unsigned short phase;
UINT32 phase_step;
int *table;
int *scale;
};
struct SLOT
{
unsigned char Num;
unsigned char Regs[8];
int Playing;
Sample_t *Sample;
unsigned int Base;
unsigned int offset;
unsigned int step;
unsigned int Pan,TL;
unsigned int DstTL;
int TLStep;
signed int Prev;
EG_t EG;
LFO_t PLFO; //Phase lfo
LFO_t ALFO; //AM lfo
};
struct MultiPCM
{
sound_stream * stream;
Sample_t Samples[0x200]; //Max 512 samples
SLOT Slots[28];
unsigned int CurSlot;
unsigned int Address;
unsigned int BankR,BankL;
float Rate;
INT8 *ROM;
//I include these in the chip because they depend on the chip clock
unsigned int ARStep[0x40],DRStep[0x40]; //Envelope step table
unsigned int FNS_Table[0x400]; //Frequency step table
};
static signed int LPANTABLE[0x800],RPANTABLE[0x800]; static signed int LPANTABLE[0x800],RPANTABLE[0x800];
@ -126,12 +58,6 @@ static const int val2chan[] =
#define MULTIPCM_RATE 44100.0 #define MULTIPCM_RATE 44100.0
INLINE MultiPCM *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == MULTIPCM);
return (MultiPCM *)downcast<multipcm_device *>(device)->token();
}
/******************************* /*******************************
@ -202,7 +128,7 @@ static unsigned int Get_RATE(unsigned int *Steps,unsigned int rate,unsigned int
return Steps[r]; return Steps[r];
} }
static void EG_Calc(MultiPCM *ptChip,SLOT *slot) void multipcm_device::EG_Calc(SLOT *slot)
{ {
int octave=((slot->Regs[3]>>4)-1)&0xf; int octave=((slot->Regs[3]>>4)-1)&0xf;
int rate; int rate;
@ -212,10 +138,10 @@ static void EG_Calc(MultiPCM *ptChip,SLOT *slot)
else else
rate=0; rate=0;
slot->EG.AR=Get_RATE(ptChip->ARStep,rate,slot->Sample->AR); slot->EG.AR=Get_RATE(m_ARStep,rate,slot->Sample->AR);
slot->EG.D1R=Get_RATE(ptChip->DRStep,rate,slot->Sample->DR1); slot->EG.D1R=Get_RATE(m_DRStep,rate,slot->Sample->DR1);
slot->EG.D2R=Get_RATE(ptChip->DRStep,rate,slot->Sample->DR2); slot->EG.D2R=Get_RATE(m_DRStep,rate,slot->Sample->DR2);
slot->EG.RR=Get_RATE(ptChip->DRStep,rate,slot->Sample->RR); slot->EG.RR=Get_RATE(m_DRStep,rate,slot->Sample->RR);
slot->EG.DL=0xf-slot->Sample->DL; slot->EG.DL=0xf-slot->Sample->DL;
} }
@ -302,9 +228,9 @@ INLINE signed int ALFO_Step(LFO_t *LFO)
return p<<(SHIFT-LFO_SHIFT); return p<<(SHIFT-LFO_SHIFT);
} }
static void LFO_ComputeStep(MultiPCM *ptChip,LFO_t *LFO,UINT32 LFOF,UINT32 LFOS,int ALFO) void multipcm_device::LFO_ComputeStep(LFO_t *LFO,UINT32 LFOF,UINT32 LFOS,int ALFO)
{ {
float step=(float) LFOFreq[LFOF]*256.0/(float) ptChip->Rate; float step=(float) LFOFreq[LFOF]*256.0/(float) m_Rate;
LFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step); LFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step);
if(ALFO) if(ALFO)
{ {
@ -320,7 +246,7 @@ static void LFO_ComputeStep(MultiPCM *ptChip,LFO_t *LFO,UINT32 LFOF,UINT32 LFOS,
static void WriteSlot(MultiPCM *ptChip,SLOT *slot,int reg,unsigned char data) void multipcm_device::WriteSlot(SLOT *slot,int reg,unsigned char data)
{ {
slot->Regs[reg]=data; slot->Regs[reg]=data;
@ -333,9 +259,9 @@ static void WriteSlot(MultiPCM *ptChip,SLOT *slot,int reg,unsigned char data)
//according to YMF278 sample write causes some base params written to the regs (envelope+lfos) //according to YMF278 sample write causes some base params written to the regs (envelope+lfos)
//the game should never change the sample while playing. //the game should never change the sample while playing.
{ {
Sample_t *Sample=ptChip->Samples+slot->Regs[1]; Sample_t *Sample=m_Samples+slot->Regs[1];
WriteSlot(ptChip,slot,6,Sample->LFOVIB); WriteSlot(slot,6,Sample->LFOVIB);
WriteSlot(ptChip,slot,7,Sample->AM); WriteSlot(slot,7,Sample->AM);
} }
break; break;
case 2: //Pitch case 2: //Pitch
@ -343,35 +269,35 @@ static void WriteSlot(MultiPCM *ptChip,SLOT *slot,int reg,unsigned char data)
{ {
unsigned int oct=((slot->Regs[3]>>4)-1)&0xf; unsigned int oct=((slot->Regs[3]>>4)-1)&0xf;
unsigned int pitch=((slot->Regs[3]&0xf)<<6)|(slot->Regs[2]>>2); unsigned int pitch=((slot->Regs[3]&0xf)<<6)|(slot->Regs[2]>>2);
pitch=ptChip->FNS_Table[pitch]; pitch=m_FNS_Table[pitch];
if(oct&0x8) if(oct&0x8)
pitch>>=(16-oct); pitch>>=(16-oct);
else else
pitch<<=oct; pitch<<=oct;
slot->step=pitch/ptChip->Rate; slot->step=pitch/m_Rate;
} }
break; break;
case 4: //KeyOn/Off (and more?) case 4: //KeyOn/Off (and more?)
{ {
if(data&0x80) //KeyOn if(data&0x80) //KeyOn
{ {
slot->Sample=ptChip->Samples+slot->Regs[1]; slot->Sample=m_Samples+slot->Regs[1];
slot->Playing=1; slot->Playing=1;
slot->Base=slot->Sample->Start; slot->Base=slot->Sample->Start;
slot->offset=0; slot->offset=0;
slot->Prev=0; slot->Prev=0;
slot->TL=slot->DstTL<<SHIFT; slot->TL=slot->DstTL<<SHIFT;
EG_Calc(ptChip,slot); EG_Calc(slot);
slot->EG.state=ATTACK; slot->EG.state=ATTACK;
slot->EG.volume=0; slot->EG.volume=0;
if(slot->Base>=0x100000) if(slot->Base>=0x100000)
{ {
if(slot->Pan&8) if(slot->Pan&8)
slot->Base=(slot->Base&0xfffff)|(ptChip->BankL); slot->Base=(slot->Base&0xfffff)|(m_BankL);
else else
slot->Base=(slot->Base&0xfffff)|(ptChip->BankR); slot->Base=(slot->Base&0xfffff)|(m_BankR);
} }
} }
@ -405,8 +331,8 @@ static void WriteSlot(MultiPCM *ptChip,SLOT *slot,int reg,unsigned char data)
{ {
if(data) if(data)
{ {
LFO_ComputeStep(ptChip,&(slot->PLFO),(slot->Regs[6]>>3)&7,slot->Regs[6]&7,0); LFO_ComputeStep(&(slot->PLFO),(slot->Regs[6]>>3)&7,slot->Regs[6]&7,0);
LFO_ComputeStep(ptChip,&(slot->ALFO),(slot->Regs[6]>>3)&7,slot->Regs[7]&7,1); LFO_ComputeStep(&(slot->ALFO),(slot->Regs[6]>>3)&7,slot->Regs[7]&7,1);
} }
} }
break; break;
@ -414,96 +340,87 @@ static void WriteSlot(MultiPCM *ptChip,SLOT *slot,int reg,unsigned char data)
{ {
if(data) if(data)
{ {
LFO_ComputeStep(ptChip,&(slot->PLFO),(slot->Regs[6]>>3)&7,slot->Regs[6]&7,0); LFO_ComputeStep(&(slot->PLFO),(slot->Regs[6]>>3)&7,slot->Regs[6]&7,0);
LFO_ComputeStep(ptChip,&(slot->ALFO),(slot->Regs[6]>>3)&7,slot->Regs[7]&7,1); LFO_ComputeStep(&(slot->ALFO),(slot->Regs[6]>>3)&7,slot->Regs[7]&7,1);
} }
} }
break; break;
} }
} }
static STREAM_UPDATE( MultiPCM_update ) READ8_MEMBER( multipcm_device::read )
{ {
MultiPCM *ptChip = (MultiPCM *)param;
stream_sample_t *datap[2];
int i,sl;
datap[0] = outputs[0];
datap[1] = outputs[1];
memset(datap[0], 0, sizeof(*datap[0])*samples);
memset(datap[1], 0, sizeof(*datap[1])*samples);
for(i=0;i<samples;++i)
{
signed int smpl=0;
signed int smpr=0;
for(sl=0;sl<28;++sl)
{
SLOT *slot=ptChip->Slots+sl;
if(slot->Playing)
{
unsigned int vol=(slot->TL>>SHIFT)|(slot->Pan<<7);
unsigned int adr=slot->offset>>SHIFT;
signed int sample;
unsigned int step=slot->step;
signed int csample=(signed short) (ptChip->ROM[slot->Base+adr]<<8);
signed int fpart=slot->offset&((1<<SHIFT)-1);
sample=(csample*fpart+slot->Prev*((1<<SHIFT)-fpart))>>SHIFT;
if(slot->Regs[6]&7) //Vibrato enabled
{
step=step*PLFO_Step(&(slot->PLFO));
step>>=SHIFT;
}
slot->offset+=step;
if(slot->offset>=(slot->Sample->End<<SHIFT))
{
slot->offset=slot->Sample->Loop<<SHIFT;
}
if(adr^(slot->offset>>SHIFT))
{
slot->Prev=csample;
}
if((slot->TL>>SHIFT)!=slot->DstTL)
slot->TL+=slot->TLStep;
if(slot->Regs[7]&7) //Tremolo enabled
{
sample=sample*ALFO_Step(&(slot->ALFO));
sample>>=SHIFT;
}
sample=(sample*EG_Update(slot))>>10;
smpl+=(LPANTABLE[vol]*sample)>>SHIFT;
smpr+=(RPANTABLE[vol]*sample)>>SHIFT;
}
}
#define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x)
datap[0][i]=ICLIP16(smpl);
datap[1][i]=ICLIP16(smpr);
}
}
READ8_DEVICE_HANDLER( multipcm_r )
{
// MultiPCM *ptChip = get_safe_token(device);
return 0; return 0;
} }
static DEVICE_START( multipcm )
WRITE8_MEMBER( multipcm_device::write )
{ {
MultiPCM *ptChip = get_safe_token(device); switch(offset)
int i; {
case 0: //Data write
WriteSlot(m_Slots+m_CurSlot,m_Address,data);
break;
case 1:
m_CurSlot=val2chan[data&0x1f];
break;
ptChip->ROM=*device->region(); case 2:
ptChip->Rate=(float) device->clock() / MULTIPCM_CLOCKDIV; m_Address=(data>7)?7:data;
break;
}
}
ptChip->stream = device->machine().sound().stream_alloc(*device, 0, 2, ptChip->Rate, ptChip, MultiPCM_update); /* MAME/M1 access functions */
void multipcm_device::set_bank(UINT32 leftoffs, UINT32 rightoffs)
{
m_BankL = leftoffs;
m_BankR = rightoffs;
}
const device_type MULTIPCM = &device_creator<multipcm_device>;
multipcm_device::multipcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MULTIPCM, "Sega/Yamaha 315-5560", tag, owner, clock, "multipcm", __FILE__),
device_sound_interface(mconfig, *this),
m_stream(NULL),
//m_Samples(0x200),
//m_Slots[28],
m_CurSlot(0),
m_Address(0),
m_BankR(0),
m_BankL(0),
m_Rate(0),
m_ROM(NULL)
//m_ARStep(0),
//m_DRStep(0),
//m_FNS_Table(0)
{
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void multipcm_device::device_config_complete()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void multipcm_device::device_start()
{
int i;
m_ROM=*region();
m_Rate=(float) clock() / MULTIPCM_CLOCKDIV;
m_stream = machine().sound().stream_alloc(*this, 0, 2, m_Rate, this);
//Volume+pan table //Volume+pan table
for(i=0;i<0x800;++i) for(i=0;i<0x800;++i)
@ -561,20 +478,20 @@ static DEVICE_START( multipcm )
//Pitch steps //Pitch steps
for(i=0;i<0x400;++i) for(i=0;i<0x400;++i)
{ {
float fcent=ptChip->Rate*(1024.0+(float) i)/1024.0; float fcent=m_Rate*(1024.0+(float) i)/1024.0;
ptChip->FNS_Table[i]=(unsigned int ) ((float) (1<<SHIFT) *fcent); m_FNS_Table[i]=(unsigned int ) ((float) (1<<SHIFT) *fcent);
} }
//Envelope steps //Envelope steps
for(i=0;i<0x40;++i) for(i=0;i<0x40;++i)
{ {
//Times are based on 44100 clock, adjust to real chip clock //Times are based on 44100 clock, adjust to real chip clock
ptChip->ARStep[i]=(float) (0x400<<EG_SHIFT)/(BaseTimes[i]*44100.0/(1000.0)); m_ARStep[i]=(float) (0x400<<EG_SHIFT)/(BaseTimes[i]*44100.0/(1000.0));
ptChip->DRStep[i]=(float) (0x400<<EG_SHIFT)/(BaseTimes[i]*AR2DR*44100.0/(1000.0)); m_DRStep[i]=(float) (0x400<<EG_SHIFT)/(BaseTimes[i]*AR2DR*44100.0/(1000.0));
} }
ptChip->ARStep[0]=ptChip->ARStep[1]=ptChip->ARStep[2]=ptChip->ARStep[3]=0; m_ARStep[0]=m_ARStep[1]=m_ARStep[2]=m_ARStep[3]=0;
ptChip->ARStep[0x3f]=0x400<<EG_SHIFT; m_ARStep[0x3f]=0x400<<EG_SHIFT;
ptChip->DRStep[0]=ptChip->DRStep[1]=ptChip->DRStep[2]=ptChip->DRStep[3]=0; m_DRStep[0]=m_DRStep[1]=m_DRStep[2]=m_DRStep[3]=0;
//TL Interpolation steps //TL Interpolation steps
//lower //lower
@ -592,121 +509,124 @@ static DEVICE_START( multipcm )
for(i=0;i<512;++i) for(i=0;i<512;++i)
{ {
UINT8 *ptSample=(UINT8 *) ptChip->ROM+i*12; UINT8 *ptSample=(UINT8 *) m_ROM+i*12;
ptChip->Samples[i].Start=(ptSample[0]<<16)|(ptSample[1]<<8)|(ptSample[2]<<0); m_Samples[i].Start=(ptSample[0]<<16)|(ptSample[1]<<8)|(ptSample[2]<<0);
ptChip->Samples[i].Loop=(ptSample[3]<<8)|(ptSample[4]<<0); m_Samples[i].Loop=(ptSample[3]<<8)|(ptSample[4]<<0);
ptChip->Samples[i].End=0xffff-((ptSample[5]<<8)|(ptSample[6]<<0)); m_Samples[i].End=0xffff-((ptSample[5]<<8)|(ptSample[6]<<0));
ptChip->Samples[i].LFOVIB=ptSample[7]; m_Samples[i].LFOVIB=ptSample[7];
ptChip->Samples[i].DR1=ptSample[8]&0xf; m_Samples[i].DR1=ptSample[8]&0xf;
ptChip->Samples[i].AR=(ptSample[8]>>4)&0xf; m_Samples[i].AR=(ptSample[8]>>4)&0xf;
ptChip->Samples[i].DR2=ptSample[9]&0xf; m_Samples[i].DR2=ptSample[9]&0xf;
ptChip->Samples[i].DL=(ptSample[9]>>4)&0xf; m_Samples[i].DL=(ptSample[9]>>4)&0xf;
ptChip->Samples[i].RR=ptSample[10]&0xf; m_Samples[i].RR=ptSample[10]&0xf;
ptChip->Samples[i].KRS=(ptSample[10]>>4)&0xf; m_Samples[i].KRS=(ptSample[10]>>4)&0xf;
ptChip->Samples[i].AM=ptSample[11]; m_Samples[i].AM=ptSample[11];
} }
device->save_item(NAME(ptChip->CurSlot)); save_item(NAME(m_CurSlot));
device->save_item(NAME(ptChip->Address)); save_item(NAME(m_Address));
device->save_item(NAME(ptChip->BankL)); save_item(NAME(m_BankL));
device->save_item(NAME(ptChip->BankR)); save_item(NAME(m_BankR));
for(i=0;i<28;++i) for(i=0;i<28;++i)
{ {
ptChip->Slots[i].Num=i; m_Slots[i].Num=i;
ptChip->Slots[i].Playing=0; m_Slots[i].Playing=0;
device->save_item(NAME(ptChip->Slots[i].Num), i); save_item(NAME(m_Slots[i].Num), i);
device->save_item(NAME(ptChip->Slots[i].Regs), i); save_item(NAME(m_Slots[i].Regs), i);
device->save_item(NAME(ptChip->Slots[i].Playing), i); save_item(NAME(m_Slots[i].Playing), i);
device->save_item(NAME(ptChip->Slots[i].Base), i); save_item(NAME(m_Slots[i].Base), i);
device->save_item(NAME(ptChip->Slots[i].offset), i); save_item(NAME(m_Slots[i].offset), i);
device->save_item(NAME(ptChip->Slots[i].step), i); save_item(NAME(m_Slots[i].step), i);
device->save_item(NAME(ptChip->Slots[i].Pan), i); save_item(NAME(m_Slots[i].Pan), i);
device->save_item(NAME(ptChip->Slots[i].TL), i); save_item(NAME(m_Slots[i].TL), i);
device->save_item(NAME(ptChip->Slots[i].DstTL), i); save_item(NAME(m_Slots[i].DstTL), i);
device->save_item(NAME(ptChip->Slots[i].TLStep), i); save_item(NAME(m_Slots[i].TLStep), i);
device->save_item(NAME(ptChip->Slots[i].Prev), i); save_item(NAME(m_Slots[i].Prev), i);
device->save_item(NAME(ptChip->Slots[i].EG.volume), i); save_item(NAME(m_Slots[i].EG.volume), i);
device->save_item(NAME(ptChip->Slots[i].EG.state), i); save_item(NAME(m_Slots[i].EG.state), i);
device->save_item(NAME(ptChip->Slots[i].EG.step), i); save_item(NAME(m_Slots[i].EG.step), i);
device->save_item(NAME(ptChip->Slots[i].EG.AR), i); save_item(NAME(m_Slots[i].EG.AR), i);
device->save_item(NAME(ptChip->Slots[i].EG.D1R), i); save_item(NAME(m_Slots[i].EG.D1R), i);
device->save_item(NAME(ptChip->Slots[i].EG.D2R), i); save_item(NAME(m_Slots[i].EG.D2R), i);
device->save_item(NAME(ptChip->Slots[i].EG.RR), i); save_item(NAME(m_Slots[i].EG.RR), i);
device->save_item(NAME(ptChip->Slots[i].EG.DL), i); save_item(NAME(m_Slots[i].EG.DL), i);
device->save_item(NAME(ptChip->Slots[i].PLFO.phase), i); save_item(NAME(m_Slots[i].PLFO.phase), i);
device->save_item(NAME(ptChip->Slots[i].PLFO.phase_step), i); save_item(NAME(m_Slots[i].PLFO.phase_step), i);
device->save_item(NAME(ptChip->Slots[i].ALFO.phase), i); save_item(NAME(m_Slots[i].ALFO.phase), i);
device->save_item(NAME(ptChip->Slots[i].ALFO.phase_step), i); save_item(NAME(m_Slots[i].ALFO.phase_step), i);
} }
LFO_Init(); LFO_Init();
} }
WRITE8_DEVICE_HANDLER( multipcm_w )
{
MultiPCM *ptChip = get_safe_token(device);
switch(offset)
{
case 0: //Data write
WriteSlot(ptChip,ptChip->Slots+ptChip->CurSlot,ptChip->Address,data);
break;
case 1:
ptChip->CurSlot=val2chan[data&0x1f];
break;
case 2:
ptChip->Address=(data>7)?7:data;
break;
}
}
/* MAME/M1 access functions */
void multipcm_set_bank(device_t *device, UINT32 leftoffs, UINT32 rightoffs)
{
MultiPCM *ptChip = get_safe_token(device);
ptChip->BankL = leftoffs;
ptChip->BankR = rightoffs;
}
const device_type MULTIPCM = &device_creator<multipcm_device>;
multipcm_device::multipcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MULTIPCM, "Sega/Yamaha 315-5560", tag, owner, clock, "multipcm", __FILE__),
device_sound_interface(mconfig, *this)
{
m_token = global_alloc_clear(MultiPCM);
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void multipcm_device::device_config_complete()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void multipcm_device::device_start()
{
DEVICE_START_NAME( multipcm )(this);
}
//------------------------------------------------- //-------------------------------------------------
// sound_stream_update - handle a stream update // sound_stream_update - handle a stream update
//------------------------------------------------- //-------------------------------------------------
void multipcm_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) void multipcm_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{ {
// should never get here stream_sample_t *datap[2];
fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); int i,sl;
datap[0] = outputs[0];
datap[1] = outputs[1];
memset(datap[0], 0, sizeof(*datap[0])*samples);
memset(datap[1], 0, sizeof(*datap[1])*samples);
for(i=0;i<samples;++i)
{
signed int smpl=0;
signed int smpr=0;
for(sl=0;sl<28;++sl)
{
SLOT *slot=m_Slots+sl;
if(slot->Playing)
{
unsigned int vol=(slot->TL>>SHIFT)|(slot->Pan<<7);
unsigned int adr=slot->offset>>SHIFT;
signed int sample;
unsigned int step=slot->step;
signed int csample=(signed short) (m_ROM[slot->Base+adr]<<8);
signed int fpart=slot->offset&((1<<SHIFT)-1);
sample=(csample*fpart+slot->Prev*((1<<SHIFT)-fpart))>>SHIFT;
if(slot->Regs[6]&7) //Vibrato enabled
{
step=step*PLFO_Step(&(slot->PLFO));
step>>=SHIFT;
}
slot->offset+=step;
if(slot->offset>=(slot->Sample->End<<SHIFT))
{
slot->offset=slot->Sample->Loop<<SHIFT;
}
if(adr^(slot->offset>>SHIFT))
{
slot->Prev=csample;
}
if((slot->TL>>SHIFT)!=slot->DstTL)
slot->TL+=slot->TLStep;
if(slot->Regs[7]&7) //Tremolo enabled
{
sample=sample*ALFO_Step(&(slot->ALFO));
sample>>=SHIFT;
}
sample=(sample*EG_Update(slot))>>10;
smpl+=(LPANTABLE[vol]*sample)>>SHIFT;
smpr+=(RPANTABLE[vol]*sample)>>SHIFT;
}
}
#define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x)
datap[0][i]=ICLIP16(smpl);
datap[1][i]=ICLIP16(smpr);
}
} }

View File

@ -3,21 +3,71 @@
#ifndef __MULTIPCM_H__ #ifndef __MULTIPCM_H__
#define __MULTIPCM_H__ #define __MULTIPCM_H__
struct Sample_t
{
unsigned int Start;
unsigned int Loop;
unsigned int End;
unsigned char AR,DR1,DR2,DL,RR;
unsigned char KRS;
unsigned char LFOVIB;
unsigned char AM;
};
DECLARE_WRITE8_DEVICE_HANDLER( multipcm_w ); enum STATE {ATTACK,DECAY1,DECAY2,RELEASE};
DECLARE_READ8_DEVICE_HANDLER( multipcm_r );
void multipcm_set_bank(device_t *device, UINT32 leftoffs, UINT32 rightoffs); struct EG_t
{
int volume; //
STATE state;
int step;
//step vals
int AR; //Attack
int D1R; //Decay1
int D2R; //Decay2
int RR; //Release
int DL; //Decay level
};
struct LFO_t
{
unsigned short phase;
UINT32 phase_step;
int *table;
int *scale;
};
struct SLOT
{
unsigned char Num;
unsigned char Regs[8];
int Playing;
Sample_t *Sample;
unsigned int Base;
unsigned int offset;
unsigned int step;
unsigned int Pan,TL;
unsigned int DstTL;
int TLStep;
signed int Prev;
EG_t EG;
LFO_t PLFO; //Phase lfo
LFO_t ALFO; //AM lfo
};
class multipcm_device : public device_t, class multipcm_device : public device_t,
public device_sound_interface public device_sound_interface
{ {
public: public:
multipcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); multipcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~multipcm_device() { global_free(m_token); } ~multipcm_device() {}
DECLARE_WRITE8_MEMBER( write );
DECLARE_READ8_MEMBER( read );
void set_bank(UINT32 leftoffs, UINT32 rightoffs);
// access to legacy token
void *token() const { assert(m_token != NULL); return m_token; }
protected: protected:
// device-level overrides // device-level overrides
virtual void device_config_complete(); virtual void device_config_complete();
@ -25,9 +75,24 @@ protected:
// sound stream update overrides // sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
private: private:
// internal state // internal state
void *m_token; sound_stream * m_stream;
Sample_t m_Samples[0x200]; //Max 512 samples
SLOT m_Slots[28];
unsigned int m_CurSlot;
unsigned int m_Address;
unsigned int m_BankR, m_BankL;
float m_Rate;
INT8 *m_ROM;
//I include these in the chip because they depend on the chip clock
unsigned int m_ARStep[0x40], m_DRStep[0x40]; //Envelope step table
unsigned int m_FNS_Table[0x400]; //Frequency step table
void EG_Calc(SLOT *slot);
void LFO_ComputeStep(LFO_t *LFO,UINT32 LFOF,UINT32 LFOS,int ALFO);
void WriteSlot(SLOT *slot,int reg,unsigned char data);
}; };
extern const device_type MULTIPCM; extern const device_type MULTIPCM;

View File

@ -61,6 +61,14 @@ exidy440_sound_device::exidy440_sound_device(const machine_config &mconfig, cons
m_m6844_chain(0x00), m_m6844_chain(0x00),
m_stream(NULL) m_stream(NULL)
{ {
m_sound_banks[0] = m_sound_banks[1] = m_sound_banks[2] = m_sound_banks[3] = 0;
for (int i = 0; i < 4; i++)
{
m_sound_channel[i].base = NULL;
m_sound_channel[i].offset = 0;
m_sound_channel[i].remaining = 0;
}
} }
//------------------------------------------------- //-------------------------------------------------
@ -100,7 +108,7 @@ void exidy440_sound_device::device_start()
save_item(NAME(m_m6844_priority)); save_item(NAME(m_m6844_priority));
save_item(NAME(m_m6844_interrupt)); save_item(NAME(m_m6844_interrupt));
save_item(NAME(m_m6844_chain)); save_item(NAME(m_m6844_chain));
m_channel_frequency[0] = clock(); /* channels 0 and 1 are run by FCLK */ m_channel_frequency[0] = clock(); /* channels 0 and 1 are run by FCLK */
m_channel_frequency[1] = clock(); m_channel_frequency[1] = clock();
m_channel_frequency[2] = clock()/2; /* channels 2 and 3 are run by SCLK */ m_channel_frequency[2] = clock()/2; /* channels 2 and 3 are run by SCLK */

View File

@ -24,91 +24,23 @@ TODO:
#include "emu.h" #include "emu.h"
#include "cpu/z80/z80.h" #include "cpu/z80/z80.h"
#include "sound/sn76496.h" #include "sound/sn76496.h"
#include "sound/okiadpcm.h"
#include "includes/mjkjidai.h" #include "includes/mjkjidai.h"
#include "devlegcy.h"
#include "mcfglgcy.h" #include "mcfglgcy.h"
class mjkjidai_adpcm_device : public device_t,
public device_sound_interface
{
public:
mjkjidai_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~mjkjidai_adpcm_device() { global_free(m_token); }
// access to legacy token
void *token() const { assert(m_token != NULL); return m_token; }
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
private:
// internal state
void *m_token;
};
extern const device_type MJKJIDAI;
/* Start of ADPCM custom chip code */ /* Start of ADPCM custom chip code */
struct mjkjidai_adpcm_state
{
oki_adpcm_state m_adpcm;
sound_stream *m_stream;
UINT32 m_current;
UINT32 m_end;
UINT8 m_nibble;
UINT8 m_playing;
UINT8 *m_base;
} _mjkjidai_adpcm_state_dummy;
static STREAM_UPDATE( mjkjidai_adpcm_callback )
{
mjkjidai_adpcm_state *state = (mjkjidai_adpcm_state *)param;
stream_sample_t *dest = outputs[0];
while (state->m_playing && samples > 0)
{
int val = (state->m_base[state->m_current] >> state->m_nibble) & 15;
state->m_nibble ^= 4;
if (state->m_nibble == 4)
{
state->m_current++;
if (state->m_current >= state->m_end)
state->m_playing = 0;
}
*dest++ = state->m_adpcm.clock(val) << 4;
samples--;
}
while (samples > 0)
{
*dest++ = 0;
samples--;
}
}
static DEVICE_START( mjkjidai_adpcm )
{
running_machine &machine = device->machine();
mjkjidai_adpcm_state *state = (mjkjidai_adpcm_state *)downcast<mjkjidai_adpcm_device *>(device)->token();
state->m_playing = 0;
state->m_stream = device->machine().sound().stream_alloc(*device, 0, 1, device->clock(), state, mjkjidai_adpcm_callback);
state->m_base = machine.root_device().memregion("adpcm")->base();
state->m_adpcm.reset();
}
const device_type MJKJIDAI = &device_creator<mjkjidai_adpcm_device>; const device_type MJKJIDAI = &device_creator<mjkjidai_adpcm_device>;
mjkjidai_adpcm_device::mjkjidai_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) mjkjidai_adpcm_device::mjkjidai_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MJKJIDAI, "Custom ADPCM", tag, owner, clock, "mjkjidai_adpcm", __FILE__), : device_t(mconfig, MJKJIDAI, "Custom ADPCM", tag, owner, clock, "mjkjidai_adpcm", __FILE__),
device_sound_interface(mconfig, *this) device_sound_interface(mconfig, *this),
m_stream(NULL),
m_current(0),
m_end(0),
m_nibble(0),
m_playing(0),
m_base(NULL)
{ {
m_token = global_alloc_clear(mjkjidai_adpcm_state);
} }
//------------------------------------------------- //-------------------------------------------------
@ -127,7 +59,15 @@ void mjkjidai_adpcm_device::device_config_complete()
void mjkjidai_adpcm_device::device_start() void mjkjidai_adpcm_device::device_start()
{ {
DEVICE_START_NAME( mjkjidai_adpcm )(this); m_playing = 0;
m_stream = machine().sound().stream_alloc(*this, 0, 1, clock(), this);
m_base = machine().root_device().memregion("adpcm")->base();
m_adpcm.reset();
save_item(NAME(m_current));
save_item(NAME(m_end));
save_item(NAME(m_nibble));
save_item(NAME(m_playing));
} }
//------------------------------------------------- //-------------------------------------------------
@ -136,26 +76,41 @@ void mjkjidai_adpcm_device::device_start()
void mjkjidai_adpcm_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) void mjkjidai_adpcm_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{ {
// should never get here stream_sample_t *dest = outputs[0];
fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
while (m_playing && samples > 0)
{
int val = (m_base[m_current] >> m_nibble) & 15;
m_nibble ^= 4;
if (m_nibble == 4)
{
m_current++;
if (m_current >= m_end)
m_playing = 0;
}
*dest++ = m_adpcm.clock(val) << 4;
samples--;
}
while (samples > 0)
{
*dest++ = 0;
samples--;
}
} }
void mjkjidai_adpcm_device::mjkjidai_adpcm_play (int offset, int length)
static void mjkjidai_adpcm_play (mjkjidai_adpcm_state *state, int offset, int length)
{ {
state->m_current = offset; m_current = offset;
state->m_end = offset + length/2; m_end = offset + length/2;
state->m_nibble = 4; m_nibble = 4;
state->m_playing = 1; m_playing = 1;
} }
WRITE8_MEMBER(mjkjidai_state::adpcm_w) WRITE8_MEMBER(mjkjidai_state::adpcm_w)
{ {
device_t *device = machine().device("adpcm"); m_mjk_adpcm->mjkjidai_adpcm_play ((data & 0x07) * 0x1000, 0x1000 * 2);
mjkjidai_adpcm_state *state = (mjkjidai_adpcm_state *)downcast<mjkjidai_adpcm_device *>(device)->token();
mjkjidai_adpcm_play (state, (data & 0x07) * 0x1000, 0x1000 * 2);
} }
/* End of ADPCM custom chip code */ /* End of ADPCM custom chip code */

View File

@ -629,7 +629,6 @@ Notes:
#include "video/segaic24.h" #include "video/segaic24.h"
#include "cpu/m68000/m68000.h" #include "cpu/m68000/m68000.h"
#include "cpu/mb86233/mb86233.h" #include "cpu/mb86233/mb86233.h"
#include "sound/multipcm.h"
#include "sound/2612intf.h" #include "sound/2612intf.h"
#include "machine/nvram.h" #include "machine/nvram.h"
#include "includes/model1.h" #include "includes/model1.h"
@ -1013,13 +1012,11 @@ READ16_MEMBER(model1_state::m1_snd_v60_ready_r)
WRITE16_MEMBER(model1_state::m1_snd_mpcm_bnk1_w) WRITE16_MEMBER(model1_state::m1_snd_mpcm_bnk1_w)
{ {
device_t *device = machine().device("sega1"); m_multipcm_1->set_bank(0x100000 * (data & 3), 0x100000 * (data & 3));
multipcm_set_bank(device, 0x100000 * (data & 3), 0x100000 * (data & 3));
} }
WRITE16_MEMBER(model1_state::m1_snd_mpcm_bnk2_w) WRITE16_MEMBER(model1_state::m1_snd_mpcm_bnk2_w)
{ {
device_t *device = machine().device("sega2"); m_multipcm_2->set_bank(0x100000 * (data & 3), 0x100000 * (data & 3));
multipcm_set_bank(device, 0x100000 * (data & 3), 0x100000 * (data & 3));
} }
WRITE16_MEMBER(model1_state::m1_snd_68k_latch1_w) WRITE16_MEMBER(model1_state::m1_snd_68k_latch1_w)
{ {
@ -1033,10 +1030,10 @@ static ADDRESS_MAP_START( model1_snd, AS_PROGRAM, 16, model1_state )
AM_RANGE(0x000000, 0x0bffff) AM_ROM AM_RANGE(0x000000, 0x0bffff) AM_ROM
AM_RANGE(0xc20000, 0xc20001) AM_READWRITE(m1_snd_68k_latch_r, m1_snd_68k_latch1_w ) AM_RANGE(0xc20000, 0xc20001) AM_READWRITE(m1_snd_68k_latch_r, m1_snd_68k_latch1_w )
AM_RANGE(0xc20002, 0xc20003) AM_READWRITE(m1_snd_v60_ready_r, m1_snd_68k_latch2_w ) AM_RANGE(0xc20002, 0xc20003) AM_READWRITE(m1_snd_v60_ready_r, m1_snd_68k_latch2_w )
AM_RANGE(0xc40000, 0xc40007) AM_DEVREADWRITE8_LEGACY("sega1", multipcm_r, multipcm_w, 0x00ff ) AM_RANGE(0xc40000, 0xc40007) AM_DEVREADWRITE8("sega1", multipcm_device, read, write, 0x00ff )
AM_RANGE(0xc40012, 0xc40013) AM_WRITENOP AM_RANGE(0xc40012, 0xc40013) AM_WRITENOP
AM_RANGE(0xc50000, 0xc50001) AM_WRITE(m1_snd_mpcm_bnk1_w ) AM_RANGE(0xc50000, 0xc50001) AM_WRITE(m1_snd_mpcm_bnk1_w )
AM_RANGE(0xc60000, 0xc60007) AM_DEVREADWRITE8_LEGACY("sega2", multipcm_r, multipcm_w, 0x00ff ) AM_RANGE(0xc60000, 0xc60007) AM_DEVREADWRITE8("sega2", multipcm_device, read, write, 0x00ff )
AM_RANGE(0xc70000, 0xc70001) AM_WRITE(m1_snd_mpcm_bnk2_w ) AM_RANGE(0xc70000, 0xc70001) AM_WRITE(m1_snd_mpcm_bnk2_w )
AM_RANGE(0xd00000, 0xd00007) AM_DEVREADWRITE8("ymsnd", ym3438_device, read, write, 0x00ff ) AM_RANGE(0xd00000, 0xd00007) AM_DEVREADWRITE8("ymsnd", ym3438_device, read, write, 0x00ff )
AM_RANGE(0xf00000, 0xf0ffff) AM_RAM AM_RANGE(0xf00000, 0xf0ffff) AM_RAM

View File

@ -96,7 +96,6 @@
#include "cpu/mb86233/mb86233.h" #include "cpu/mb86233/mb86233.h"
#include "cpu/z80/z80.h" #include "cpu/z80/z80.h"
#include "sound/scsp.h" #include "sound/scsp.h"
#include "sound/multipcm.h"
#include "sound/2612intf.h" #include "sound/2612intf.h"
#include "includes/model2.h" #include "includes/model2.h"
@ -1808,14 +1807,12 @@ READ16_MEMBER(model2_state::m1_snd_v60_ready_r)
WRITE16_MEMBER(model2_state::m1_snd_mpcm_bnk1_w) WRITE16_MEMBER(model2_state::m1_snd_mpcm_bnk1_w)
{ {
device_t *device = machine().device("sega1"); m_multipcm_1->set_bank(0x100000 * (data & 0xf), 0x100000 * (data & 0xf));
multipcm_set_bank(device, 0x100000 * (data & 0xf), 0x100000 * (data & 0xf));
} }
WRITE16_MEMBER(model2_state::m1_snd_mpcm_bnk2_w) WRITE16_MEMBER(model2_state::m1_snd_mpcm_bnk2_w)
{ {
device_t *device = machine().device("sega2"); m_multipcm_2->set_bank(0x100000 * (data & 0xf), 0x100000 * (data & 0xf));
multipcm_set_bank(device, 0x100000 * (data & 0xf), 0x100000 * (data & 0xf));
} }
WRITE16_MEMBER(model2_state::m1_snd_68k_latch1_w) WRITE16_MEMBER(model2_state::m1_snd_68k_latch1_w)
@ -1831,10 +1828,10 @@ static ADDRESS_MAP_START( model1_snd, AS_PROGRAM, 16, model2_state )
AM_RANGE(0x080000, 0x0bffff) AM_ROM AM_REGION("audiocpu", 0x20000) // mirror of second program ROM AM_RANGE(0x080000, 0x0bffff) AM_ROM AM_REGION("audiocpu", 0x20000) // mirror of second program ROM
AM_RANGE(0xc20000, 0xc20001) AM_READWRITE(m1_snd_68k_latch_r, m1_snd_68k_latch1_w ) AM_RANGE(0xc20000, 0xc20001) AM_READWRITE(m1_snd_68k_latch_r, m1_snd_68k_latch1_w )
AM_RANGE(0xc20002, 0xc20003) AM_READWRITE(m1_snd_v60_ready_r, m1_snd_68k_latch2_w ) AM_RANGE(0xc20002, 0xc20003) AM_READWRITE(m1_snd_v60_ready_r, m1_snd_68k_latch2_w )
AM_RANGE(0xc40000, 0xc40007) AM_DEVREADWRITE8_LEGACY("sega1", multipcm_r, multipcm_w, 0x00ff ) AM_RANGE(0xc40000, 0xc40007) AM_DEVREADWRITE8("sega1", multipcm_device, read, write, 0x00ff )
AM_RANGE(0xc40012, 0xc40013) AM_WRITENOP AM_RANGE(0xc40012, 0xc40013) AM_WRITENOP
AM_RANGE(0xc50000, 0xc50001) AM_WRITE(m1_snd_mpcm_bnk1_w ) AM_RANGE(0xc50000, 0xc50001) AM_WRITE(m1_snd_mpcm_bnk1_w )
AM_RANGE(0xc60000, 0xc60007) AM_DEVREADWRITE8_LEGACY("sega2", multipcm_r, multipcm_w, 0x00ff ) AM_RANGE(0xc60000, 0xc60007) AM_DEVREADWRITE8("sega2", multipcm_device, read, write, 0x00ff )
AM_RANGE(0xc70000, 0xc70001) AM_WRITE(m1_snd_mpcm_bnk2_w ) AM_RANGE(0xc70000, 0xc70001) AM_WRITE(m1_snd_mpcm_bnk2_w )
AM_RANGE(0xd00000, 0xd00007) AM_DEVREADWRITE8("ymsnd", ym3438_device, read, write, 0x00ff ) AM_RANGE(0xd00000, 0xd00007) AM_DEVREADWRITE8("ymsnd", ym3438_device, read, write, 0x00ff )
AM_RANGE(0xf00000, 0xf0ffff) AM_RAM AM_RANGE(0xf00000, 0xf0ffff) AM_RAM

View File

@ -642,31 +642,15 @@ WRITE_LINE_MEMBER(ninjaw_state::irqhandler)
/************************************************************** /**************************************************************
SUBWOOFER (SOUND) SUBWOOFER (SOUND)
**************************************************************/ **************************************************************/
#if 0 #if 0
static DEVICE_START( subwoofer )
{
/* Adjust the lowpass filter of the first three YM2610 channels */
/* The 150 Hz is a common top frequency played by a generic */
/* subwoofer, the real Arcade Machine may differs */
mixer_set_lowpass_frequency(0, 20);
mixer_set_lowpass_frequency(1, 20);
mixer_set_lowpass_frequency(2, 20);
return 0;
}
class subwoofer_device : public device_t, class subwoofer_device : public device_t,
public device_sound_interface public device_sound_interface
{ {
public: public:
subwoofer_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); subwoofer_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~subwoofer_device() { global_free(m_token); } ~subwoofer_device() {}
// access to legacy token
void *token() const { assert(m_token != NULL); return m_token; }
protected: protected:
// device-level overrides // device-level overrides
virtual void device_config_complete(); virtual void device_config_complete();
@ -674,9 +658,10 @@ protected:
// sound stream update overrides // sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
private: private:
// internal state // internal state
void *m_token;
}; };
extern const device_type SUBWOOFER; extern const device_type SUBWOOFER;
@ -687,7 +672,6 @@ subwoofer_device::subwoofer_device(const machine_config &mconfig, const char *ta
: device_t(mconfig, SUBWOOFER, "Subwoofer", tag, owner, clock), : device_t(mconfig, SUBWOOFER, "Subwoofer", tag, owner, clock),
device_sound_interface(mconfig, *this) device_sound_interface(mconfig, *this)
{ {
m_token = global_alloc_array_clear(UINT8, sizeof());
} }
//------------------------------------------------- //-------------------------------------------------
@ -706,7 +690,16 @@ void subwoofer_device::device_config_complete()
void subwoofer_device::device_start() void subwoofer_device::device_start()
{ {
DEVICE_START_NAME( subwoofer )(this); /* Adjust the lowpass filter of the first three YM2610 channels */
/* The 150 Hz is a common top frequency played by a generic */
/* subwoofer, the real Arcade Machine may differs */
mixer_set_lowpass_frequency(0, 20);
mixer_set_lowpass_frequency(1, 20);
mixer_set_lowpass_frequency(2, 20);
return 0;
} }
//------------------------------------------------- //-------------------------------------------------
@ -715,8 +708,6 @@ void subwoofer_device::device_start()
void subwoofer_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) void subwoofer_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{ {
// should never get here
fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
} }

View File

@ -105,99 +105,23 @@ $8000 - $ffff ROM
#include "cpu/m6809/m6809.h" #include "cpu/m6809/m6809.h"
#include "cpu/m6805/m6805.h" #include "cpu/m6805/m6805.h"
#include "sound/3526intf.h" #include "sound/3526intf.h"
#include "sound/okiadpcm.h"
#include "includes/renegade.h" #include "includes/renegade.h"
#include "devlegcy.h"
/********************************************************************************************/ /********************************************************************************************/
struct renegade_adpcm_state
{
oki_adpcm_state m_adpcm;
sound_stream *m_stream;
UINT32 m_current;
UINT32 m_end;
UINT8 m_nibble;
UINT8 m_playing;
UINT8 *m_base;
} _renegade_adpcm_state_dummy;
class renegade_adpcm_device : public device_t,
public device_sound_interface
{
public:
renegade_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~renegade_adpcm_device() { global_free(m_token); }
// access to legacy token
void *token() const { assert(m_token != NULL); return m_token; }
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
private:
// internal state
void *m_token;
};
extern const device_type RENEGADE_ADPCM;
INLINE renegade_adpcm_state *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == RENEGADE_ADPCM);
return (renegade_adpcm_state *)downcast<renegade_adpcm_device *>(device)->token();
}
static STREAM_UPDATE( renegade_adpcm_callback )
{
renegade_adpcm_state *state = (renegade_adpcm_state *)param;
stream_sample_t *dest = outputs[0];
while (state->m_playing && samples > 0)
{
int val = (state->m_base[state->m_current] >> state->m_nibble) & 15;
state->m_nibble ^= 4;
if (state->m_nibble == 4)
{
state->m_current++;
if (state->m_current >= state->m_end)
state->m_playing = 0;
}
*dest++ = state->m_adpcm.clock(val) << 4;
samples--;
}
while (samples > 0)
{
*dest++ = 0;
samples--;
}
}
static DEVICE_START( renegade_adpcm )
{
renegade_adpcm_state *state = get_safe_token(device);
state->m_playing = 0;
state->m_stream = device->machine().sound().stream_alloc(*device, 0, 1, device->clock(), state, renegade_adpcm_callback);
state->m_base = device->machine().root_device().memregion("adpcm")->base();
state->m_adpcm.reset();
}
const device_type RENEGADE_ADPCM = &device_creator<renegade_adpcm_device>; const device_type RENEGADE_ADPCM = &device_creator<renegade_adpcm_device>;
renegade_adpcm_device::renegade_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) renegade_adpcm_device::renegade_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, RENEGADE_ADPCM, "Renegade Custom ADPCM", tag, owner, clock, "renegade_adpcm", __FILE__), : device_t(mconfig, RENEGADE_ADPCM, "Renegade Custom ADPCM", tag, owner, clock, "renegade_adpcm", __FILE__),
device_sound_interface(mconfig, *this) device_sound_interface(mconfig, *this),
m_stream(NULL),
m_current(0),
m_end(0),
m_nibble(0),
m_playing(0),
m_base(NULL)
{ {
m_token = global_alloc_clear(renegade_adpcm_state);
} }
//------------------------------------------------- //-------------------------------------------------
@ -216,7 +140,15 @@ void renegade_adpcm_device::device_config_complete()
void renegade_adpcm_device::device_start() void renegade_adpcm_device::device_start()
{ {
DEVICE_START_NAME( renegade_adpcm )(this); m_playing = 0;
m_stream = machine().sound().stream_alloc(*this, 0, 1, clock(), this);
m_base = machine().root_device().memregion("adpcm")->base();
m_adpcm.reset();
save_item(NAME(m_current));
save_item(NAME(m_end));
save_item(NAME(m_nibble));
save_item(NAME(m_playing));
} }
//------------------------------------------------- //-------------------------------------------------
@ -225,17 +157,33 @@ void renegade_adpcm_device::device_start()
void renegade_adpcm_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) void renegade_adpcm_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{ {
// should never get here stream_sample_t *dest = outputs[0];
fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
while (m_playing && samples > 0)
{
int val = (m_base[m_current] >> m_nibble) & 15;
m_nibble ^= 4;
if (m_nibble == 4)
{
m_current++;
if (m_current >= m_end)
m_playing = 0;
}
*dest++ = m_adpcm.clock(val) << 4;
samples--;
}
while (samples > 0)
{
*dest++ = 0;
samples--;
}
} }
WRITE8_MEMBER(renegade_adpcm_device::play_w)
WRITE8_MEMBER(renegade_state::adpcm_play_w)
{ {
device_t *device = machine().device("adpcm");
renegade_adpcm_state *renstate = get_safe_token(device);
int offs = (data - 0x2c) * 0x2000; int offs = (data - 0x2c) * 0x2000;
int len = 0x2000 * 2; int len = 0x2000 * 2;
@ -245,13 +193,13 @@ WRITE8_MEMBER(renegade_state::adpcm_play_w)
if (offs >= 0 && offs+len <= 0x20000) if (offs >= 0 && offs+len <= 0x20000)
{ {
renstate->m_stream->update(); m_stream->update();
renstate->m_adpcm.reset(); m_adpcm.reset();
renstate->m_current = offs; m_current = offs;
renstate->m_end = offs + len/2; m_end = offs + len/2;
renstate->m_nibble = 4; m_nibble = 4;
renstate->m_playing = 1; m_playing = 1;
} }
else else
logerror("out of range adpcm command: 0x%02x\n", data); logerror("out of range adpcm command: 0x%02x\n", data);
@ -705,7 +653,7 @@ static ADDRESS_MAP_START( renegade_sound_map, AS_PROGRAM, 8, renegade_state )
AM_RANGE(0x0000, 0x0fff) AM_RAM AM_RANGE(0x0000, 0x0fff) AM_RAM
AM_RANGE(0x1000, 0x1000) AM_READ(soundlatch_byte_r) AM_RANGE(0x1000, 0x1000) AM_READ(soundlatch_byte_r)
AM_RANGE(0x1800, 0x1800) AM_WRITENOP // this gets written the same values as 0x2000 AM_RANGE(0x1800, 0x1800) AM_WRITENOP // this gets written the same values as 0x2000
AM_RANGE(0x2000, 0x2000) AM_WRITE(adpcm_play_w) AM_RANGE(0x2000, 0x2000) AM_DEVWRITE("adpcm", renegade_adpcm_device, play_w)
AM_RANGE(0x2800, 0x2801) AM_DEVREADWRITE("ymsnd", ym3526_device, read, write) AM_RANGE(0x2800, 0x2801) AM_DEVREADWRITE("ymsnd", ym3526_device, read, write)
AM_RANGE(0x3000, 0x3000) AM_WRITENOP /* adpcm related? stereo pan? */ AM_RANGE(0x3000, 0x3000) AM_WRITENOP /* adpcm related? stereo pan? */
AM_RANGE(0x8000, 0xffff) AM_ROM AM_RANGE(0x8000, 0xffff) AM_ROM

View File

@ -338,7 +338,6 @@ orunners: Interleaved with the dj and << >> buttons is the data the drives the
#include "machine/eepromser.h" #include "machine/eepromser.h"
#include "sound/2612intf.h" #include "sound/2612intf.h"
#include "sound/rf5c68.h" #include "sound/rf5c68.h"
#include "sound/multipcm.h"
#include "radr.lh" #include "radr.lh"
@ -1133,15 +1132,13 @@ WRITE8_MEMBER(segas32_state::sound_bank_hi_w)
WRITE8_MEMBER(segas32_state::multipcm_bank_w) WRITE8_MEMBER(segas32_state::multipcm_bank_w)
{ {
device_t *device = machine().device("sega"); m_multipcm->set_bank(0x80000 * ((data >> 3) & 7), 0x80000 * (data & 7));
multipcm_set_bank(device, 0x80000 * ((data >> 3) & 7), 0x80000 * (data & 7));
} }
WRITE8_MEMBER(segas32_state::scross_bank_w) WRITE8_MEMBER(segas32_state::scross_bank_w)
{ {
multipcm_device *multipcm = machine().device<multipcm_device>("sega"); m_multipcm->set_bank(0x80000 * (data & 7), 0x80000 * (data & 7));
multipcm_set_bank(multipcm, 0x80000 * (data & 7), 0x80000 * (data & 7));
} }
@ -1243,7 +1240,7 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( multi32_sound_map, AS_PROGRAM, 8, segas32_state ) static ADDRESS_MAP_START( multi32_sound_map, AS_PROGRAM, 8, segas32_state )
AM_RANGE(0x0000, 0x9fff) AM_ROM AM_REGION("soundcpu", 0x100000) AM_RANGE(0x0000, 0x9fff) AM_ROM AM_REGION("soundcpu", 0x100000)
AM_RANGE(0xa000, 0xbfff) AM_ROMBANK("bank1") AM_RANGE(0xa000, 0xbfff) AM_ROMBANK("bank1")
AM_RANGE(0xc000, 0xdfff) AM_DEVREADWRITE_LEGACY("sega", multipcm_r, multipcm_w) AM_RANGE(0xc000, 0xdfff) AM_DEVREADWRITE("sega", multipcm_device, read, write)
AM_RANGE(0xe000, 0xffff) AM_RAM AM_SHARE("z80_shared_ram") AM_RANGE(0xe000, 0xffff) AM_RAM AM_SHARE("z80_shared_ram")
ADDRESS_MAP_END ADDRESS_MAP_END

View File

@ -1,3 +1,7 @@
#include "sound/okiadpcm.h"
class mjkjidai_adpcm_device;
class mjkjidai_state : public driver_device class mjkjidai_state : public driver_device
{ {
public: public:
@ -8,13 +12,17 @@ public:
m_spriteram2(*this, "spriteram2"), m_spriteram2(*this, "spriteram2"),
m_spriteram3(*this, "spriteram3"), m_spriteram3(*this, "spriteram3"),
m_videoram(*this, "videoram"), m_videoram(*this, "videoram"),
m_maincpu(*this, "maincpu") { } m_maincpu(*this, "maincpu"),
m_mjk_adpcm(*this, "adpcm") { }
required_shared_ptr<UINT8> m_nvram; required_shared_ptr<UINT8> m_nvram;
required_shared_ptr<UINT8> m_spriteram1; required_shared_ptr<UINT8> m_spriteram1;
required_shared_ptr<UINT8> m_spriteram2; required_shared_ptr<UINT8> m_spriteram2;
required_shared_ptr<UINT8> m_spriteram3; required_shared_ptr<UINT8> m_spriteram3;
required_shared_ptr<UINT8> m_videoram; required_shared_ptr<UINT8> m_videoram;
required_device<cpu_device> m_maincpu;
required_device<mjkjidai_adpcm_device> m_mjk_adpcm;
int m_keyb; int m_keyb;
int m_nvram_init_count; int m_nvram_init_count;
@ -32,5 +40,33 @@ public:
UINT32 screen_update_mjkjidai(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); UINT32 screen_update_mjkjidai(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(vblank_irq); INTERRUPT_GEN_MEMBER(vblank_irq);
void draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect); void draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect);
required_device<cpu_device> m_maincpu;
}; };
class mjkjidai_adpcm_device : public device_t,
public device_sound_interface
{
public:
mjkjidai_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~mjkjidai_adpcm_device() {}
void mjkjidai_adpcm_play (int offset, int length);
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
private:
// internal state
oki_adpcm_state m_adpcm;
sound_stream *m_stream;
UINT32 m_current;
UINT32 m_end;
UINT8 m_nibble;
UINT8 m_playing;
UINT8 *m_base;
};
extern const device_type MJKJIDAI;

View File

@ -1,4 +1,5 @@
#include "audio/dsbz80.h" #include "audio/dsbz80.h"
#include "sound/multipcm.h"
typedef void (*tgp_func)(running_machine &machine); typedef void (*tgp_func)(running_machine &machine);
@ -12,6 +13,8 @@ public:
: driver_device(mconfig, type, tag), : driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"), m_maincpu(*this, "maincpu"),
m_audiocpu(*this, "audiocpu"), m_audiocpu(*this, "audiocpu"),
m_multipcm_1(*this, "sega1"),
m_multipcm_2(*this, "sega2"),
m_dsbz80(*this, DSBZ80_TAG), m_dsbz80(*this, DSBZ80_TAG),
m_mr2(*this, "mr2"), m_mr2(*this, "mr2"),
m_mr(*this, "mr"), m_mr(*this, "mr"),
@ -21,6 +24,8 @@ public:
required_device<cpu_device> m_maincpu; // V60 required_device<cpu_device> m_maincpu; // V60
required_device<cpu_device> m_audiocpu; // sound 68000 required_device<cpu_device> m_audiocpu; // sound 68000
required_device<multipcm_device> m_multipcm_1;
required_device<multipcm_device> m_multipcm_2;
optional_device<dsbz80_device> m_dsbz80; // Digital Sound Board optional_device<dsbz80_device> m_dsbz80; // Digital Sound Board
required_shared_ptr<UINT16> m_mr2; required_shared_ptr<UINT16> m_mr2;

View File

@ -1,6 +1,7 @@
#include "video/poly.h" #include "video/poly.h"
#include "audio/dsbz80.h" #include "audio/dsbz80.h"
#include "machine/eepromser.h" #include "machine/eepromser.h"
#include "sound/multipcm.h"
struct raster_state; struct raster_state;
struct geo_state; struct geo_state;
@ -11,7 +12,6 @@ class model2_state : public driver_device
public: public:
model2_state(const machine_config &mconfig, device_type type, const char *tag) model2_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag), : driver_device(mconfig, type, tag),
m_maincpu(*this,"maincpu"),
m_workram(*this, "workram"), m_workram(*this, "workram"),
m_bufferram(*this, "bufferram"), m_bufferram(*this, "bufferram"),
m_paletteram32(*this, "paletteram32"), m_paletteram32(*this, "paletteram32"),
@ -20,15 +20,17 @@ public:
m_textureram1(*this, "textureram1"), m_textureram1(*this, "textureram1"),
m_lumaram(*this, "lumaram"), m_lumaram(*this, "lumaram"),
m_soundram(*this, "soundram"), m_soundram(*this, "soundram"),
m_dsbz80(*this, DSBZ80_TAG),
m_tgp_program(*this, "tgp_program"), m_tgp_program(*this, "tgp_program"),
m_maincpu(*this,"maincpu"),
m_dsbz80(*this, DSBZ80_TAG),
m_audiocpu(*this, "audiocpu"), m_audiocpu(*this, "audiocpu"),
m_multipcm_1(*this, "sega1"),
m_multipcm_2(*this, "sega2"),
m_tgp(*this, "tgp"), m_tgp(*this, "tgp"),
m_dsp(*this, "dsp"), m_dsp(*this, "dsp"),
m_drivecpu(*this, "drivecpu"), m_drivecpu(*this, "drivecpu"),
m_eeprom(*this, "eeprom") { } m_eeprom(*this, "eeprom") { }
required_device<cpu_device> m_maincpu;
required_shared_ptr<UINT32> m_workram; required_shared_ptr<UINT32> m_workram;
required_shared_ptr<UINT32> m_bufferram; required_shared_ptr<UINT32> m_bufferram;
required_shared_ptr<UINT32> m_paletteram32; required_shared_ptr<UINT32> m_paletteram32;
@ -37,8 +39,17 @@ public:
required_shared_ptr<UINT32> m_textureram1; required_shared_ptr<UINT32> m_textureram1;
required_shared_ptr<UINT32> m_lumaram; required_shared_ptr<UINT32> m_lumaram;
optional_shared_ptr<UINT16> m_soundram; optional_shared_ptr<UINT16> m_soundram;
optional_device<dsbz80_device> m_dsbz80; // Z80-based MPEG Digital Sound Board
optional_shared_ptr<UINT32> m_tgp_program; optional_shared_ptr<UINT32> m_tgp_program;
required_device<cpu_device> m_maincpu;
optional_device<dsbz80_device> m_dsbz80; // Z80-based MPEG Digital Sound Board
required_device<cpu_device> m_audiocpu;
optional_device<multipcm_device> m_multipcm_1;
optional_device<multipcm_device> m_multipcm_2;
optional_device<cpu_device> m_tgp;
optional_device<cpu_device> m_dsp;
optional_device<cpu_device> m_drivecpu;
required_device<eeprom_serial_93cxx_device> m_eeprom;
UINT32 m_intreq; UINT32 m_intreq;
UINT32 m_intena; UINT32 m_intena;
@ -176,11 +187,6 @@ public:
TIMER_DEVICE_CALLBACK_MEMBER(model2c_interrupt); TIMER_DEVICE_CALLBACK_MEMBER(model2c_interrupt);
void model2_exit(); void model2_exit();
DECLARE_WRITE_LINE_MEMBER(scsp_irq); DECLARE_WRITE_LINE_MEMBER(scsp_irq);
required_device<cpu_device> m_audiocpu;
optional_device<cpu_device> m_tgp;
optional_device<cpu_device> m_dsp;
optional_device<cpu_device> m_drivecpu;
required_device<eeprom_serial_93cxx_device> m_eeprom;
}; };
/*----------- defined in video/model2.c -----------*/ /*----------- defined in video/model2.c -----------*/

View File

@ -1,5 +1,9 @@
#include "sound/okiadpcm.h"
#define MCU_BUFFER_MAX 6 #define MCU_BUFFER_MAX 6
class renegade_adpcm_device;
class renegade_state : public driver_device class renegade_state : public driver_device
{ {
public: public:
@ -81,3 +85,33 @@ public:
required_device<cpu_device> m_audiocpu; required_device<cpu_device> m_audiocpu;
optional_device<cpu_device> m_mcu; optional_device<cpu_device> m_mcu;
}; };
class renegade_adpcm_device : public device_t,
public device_sound_interface
{
public:
renegade_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~renegade_adpcm_device() {}
DECLARE_WRITE8_MEMBER(play_w);
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
private:
// internal state
oki_adpcm_state m_adpcm;
sound_stream *m_stream;
UINT32 m_current;
UINT32 m_end;
UINT8 m_nibble;
UINT8 m_playing;
UINT8 *m_base;
};
extern const device_type RENEGADE_ADPCM;

View File

@ -5,6 +5,7 @@
***************************************************************************/ ***************************************************************************/
#include "machine/eepromser.h" #include "machine/eepromser.h"
#include "sound/multipcm.h"
class segas32_state : public driver_device class segas32_state : public driver_device
@ -20,6 +21,7 @@ public:
m_system32_paletteram(*this,"paletteram", 0) , m_system32_paletteram(*this,"paletteram", 0) ,
m_maincpu(*this, "maincpu"), m_maincpu(*this, "maincpu"),
m_soundcpu(*this, "soundcpu"), m_soundcpu(*this, "soundcpu"),
m_multipcm(*this, "sega"),
m_eeprom(*this, "eeprom") { } m_eeprom(*this, "eeprom") { }
required_shared_ptr<UINT8> m_z80_shared_ram; required_shared_ptr<UINT8> m_z80_shared_ram;
@ -27,6 +29,12 @@ public:
optional_shared_ptr<UINT16> m_system32_workram; optional_shared_ptr<UINT16> m_system32_workram;
required_shared_ptr<UINT16> m_system32_videoram; required_shared_ptr<UINT16> m_system32_videoram;
required_shared_ptr<UINT16> m_system32_spriteram; required_shared_ptr<UINT16> m_system32_spriteram;
optional_shared_ptr_array<UINT16, 2> m_system32_paletteram;
required_device<cpu_device> m_maincpu;
required_device<cpu_device> m_soundcpu;
optional_device<multipcm_device> m_multipcm;
required_device<eeprom_serial_93cxx_device> m_eeprom;
typedef void (segas32_state::*sys32_output_callback)(int which, UINT16 data); typedef void (segas32_state::*sys32_output_callback)(int which, UINT16 data);
@ -68,7 +76,6 @@ public:
sys32_output_callback m_sw3_output; sys32_output_callback m_sw3_output;
UINT16* m_dual_pcb_comms; UINT16* m_dual_pcb_comms;
UINT16 *m_system32_protram; UINT16 *m_system32_protram;
optional_shared_ptr_array<UINT16, 2> m_system32_paletteram;
UINT16 m_system32_displayenable[2]; UINT16 m_system32_displayenable[2];
UINT16 m_system32_tilebank_external; UINT16 m_system32_tilebank_external;
UINT16 m_arescue_dsp_io[6]; UINT16 m_arescue_dsp_io[6];
@ -252,9 +259,6 @@ public:
void update_bitmap(screen_device &screen, struct layer_info *layer, const rectangle &cliprect); void update_bitmap(screen_device &screen, struct layer_info *layer, const rectangle &cliprect);
void update_background(struct layer_info *layer, const rectangle &cliprect); void update_background(struct layer_info *layer, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER(ym3438_irq_handler); DECLARE_WRITE_LINE_MEMBER(ym3438_irq_handler);
required_device<cpu_device> m_maincpu;
required_device<cpu_device> m_soundcpu;
required_device<eeprom_serial_93cxx_device> m_eeprom;
}; };
/*----------- defined in machine/segas32.c -----------*/ /*----------- defined in machine/segas32.c -----------*/