scsp is modern device, thanks Osso for most of the work (nw)

This commit is contained in:
Miodrag Milanovic 2014-03-21 07:37:26 +00:00
parent c12b058645
commit 343c6a3866
7 changed files with 727 additions and 719 deletions

1
.gitattributes vendored
View File

@ -2882,7 +2882,6 @@ src/emu/sound/scsp.c svneol=native#text/plain
src/emu/sound/scsp.h svneol=native#text/plain
src/emu/sound/scspdsp.c svneol=native#text/plain
src/emu/sound/scspdsp.h svneol=native#text/plain
src/emu/sound/scsplfo.inc svneol=native#text/plain
src/emu/sound/segapcm.c svneol=native#text/plain
src/emu/sound/segapcm.h svneol=native#text/plain
src/emu/sound/sid.c svneol=native#text/plain

View File

@ -752,7 +752,7 @@ void saturn_state::m68k_reset_callback(device_t *device)
printf("m68k RESET opcode triggered\n");
}
WRITE_LINE_MEMBER(saturn_state::scsp_irq)
WRITE8_MEMBER(saturn_state::scsp_irq)
{
// don't bother the 68k if it's off
if (!m_en_68k)
@ -760,18 +760,14 @@ WRITE_LINE_MEMBER(saturn_state::scsp_irq)
return;
}
if (state > 0)
if (offset != 0)
{
m_scsp_last_line = state;
m_audiocpu->set_input_line(state, ASSERT_LINE);
}
else if (state < 0)
{
m_audiocpu->set_input_line(-state, CLEAR_LINE);
}
if (data == ASSERT_LINE) m_scsp_last_line = offset;
m_audiocpu->set_input_line(offset, data);
}
else
{
m_audiocpu->set_input_line(m_scsp_last_line, CLEAR_LINE);
m_audiocpu->set_input_line(m_scsp_last_line, data);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -7,45 +7,204 @@
#ifndef __SCSP_H__
#define __SCSP_H__
#include "scspdsp.h"
struct scsp_interface
#define FM_DELAY 0 // delay in number of slots processed before samples are written to the FM ring buffer
// driver code indicates should be 4, but sounds distorted then
#define MCFG_SCSP_ROFFSET(_offs) \
scsp_device::set_roffset(*device, _offs);
#define MCFG_SCSP_IRQ_CB(_devcb) \
devcb = &scsp_device::set_irq_callback(*device, DEVCB2_##_devcb);
#define MCFG_SCSP_MAIN_IRQ_CB(_devcb) \
devcb = &scsp_device::set_main_irq_callback(*device, DEVCB2_##_devcb);
enum SCSP_STATE {SCSP_ATTACK,SCSP_DECAY1,SCSP_DECAY2,SCSP_RELEASE};
struct SCSP_EG_t
{
int roffset; /* offset in the region */
devcb_write_line irq_callback; /* irq callback */
devcb_write_line main_irq;
int volume; //
SCSP_STATE state;
int step;
//step vals
int AR; //Attack
int D1R; //Decay1
int D2R; //Decay2
int RR; //Release
int DL; //Decay level
UINT8 EGHOLD;
UINT8 LPLINK;
};
void scsp_set_ram_base(device_t *device, void *base);
struct SCSP_LFO_t
{
unsigned short phase;
UINT32 phase_step;
int *table;
int *scale;
};
// SCSP register access
DECLARE_READ16_DEVICE_HANDLER( scsp_r );
DECLARE_WRITE16_DEVICE_HANDLER( scsp_w );
struct SCSP_SLOT
{
union
{
UINT16 data[0x10]; //only 0x1a bytes used
UINT8 datab[0x20];
} udata;
UINT8 Backwards; //the wave is playing backwards
UINT8 active; //this slot is currently playing
UINT8 *base; //samples base address
UINT32 cur_addr; //current play address (24.8)
UINT32 nxt_addr; //next play address
UINT32 step; //pitch step (24.8)
SCSP_EG_t EG; //Envelope
SCSP_LFO_t PLFO; //Phase LFO
SCSP_LFO_t ALFO; //Amplitude LFO
int slot;
signed short Prev; //Previous sample (for interpolation)
};
// MIDI I/O access (used for comms on Model 2/3)
DECLARE_WRITE16_DEVICE_HANDLER( scsp_midi_in );
DECLARE_READ16_DEVICE_HANDLER( scsp_midi_out_r );
extern UINT32* stv_scu;
class scsp_device : public device_t,
public device_sound_interface
{
public:
scsp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~scsp_device();
~scsp_device() {}
static void set_roffset(device_t &device, int roffset) { downcast<scsp_device &>(device).m_roffset = roffset; }
template<class _Object> static devcb2_base &set_irq_callback(device_t &device, _Object object) { return downcast<scsp_device &>(device).m_irq_cb.set_callback(object); }
template<class _Object> static devcb2_base &set_main_irq_callback(device_t &device, _Object object) { return downcast<scsp_device &>(device).m_main_irq_cb.set_callback(object); }
// SCSP register access
DECLARE_READ16_MEMBER( read );
DECLARE_WRITE16_MEMBER( write );
// MIDI I/O access (used for comms on Model 2/3)
DECLARE_WRITE16_MEMBER( midi_in );
DECLARE_READ16_MEMBER( midi_out_r );
void set_ram_base(void *base);
// access to legacy token
struct scsp_state *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
struct scsp_state *m_token;
int m_roffset; /* offset in the region */
devcb2_write8 m_irq_cb; /* irq callback */
devcb2_write_line m_main_irq_cb;
union
{
UINT16 data[0x30/2];
UINT8 datab[0x30];
} m_udata;
SCSP_SLOT m_Slots[32];
signed short m_RINGBUF[128];
unsigned char m_BUFPTR;
#if FM_DELAY
signed short m_DELAYBUF[FM_DELAY];
unsigned char m_DELAYPTR;
#endif
unsigned char *m_SCSPRAM;
UINT32 m_SCSPRAM_LENGTH;
char m_Master;
sound_stream * m_stream;
INT32 *m_buffertmpl,*m_buffertmpr;
UINT32 m_IrqTimA;
UINT32 m_IrqTimBC;
UINT32 m_IrqMidi;
UINT8 m_MidiOutW, m_MidiOutR;
UINT8 m_MidiStack[32];
UINT8 m_MidiW, m_MidiR;
INT32 m_EG_TABLE[0x400];
int m_LPANTABLE[0x10000];
int m_RPANTABLE[0x10000];
int m_TimPris[3];
int m_TimCnt[3];
// timers
emu_timer *m_timerA, *m_timerB, *m_timerC;
// DMA stuff
struct
{
UINT32 dmea;
UINT16 drga;
UINT16 dtlg;
UINT8 dgate;
UINT8 ddir;
} m_dma;
UINT16 m_mcieb;
UINT16 m_mcipd;
int m_ARTABLE[64], m_DRTABLE[64];
SCSPDSP m_DSP;
stream_sample_t *m_bufferl;
stream_sample_t *m_bufferr;
int m_length;
signed short *m_RBUFDST; //this points to where the sample will be stored in the RingBuf
//LFO
int m_PLFO_TRI[256], m_PLFO_SQR[256], m_PLFO_SAW[256], m_PLFO_NOI[256];
int m_ALFO_TRI[256], m_ALFO_SQR[256], m_ALFO_SAW[256], m_ALFO_NOI[256];
int m_PSCALES[8][256];
int m_ASCALES[8][256];
void exec_dma(address_space &space); /*state DMA transfer function*/
unsigned char DecodeSCI(unsigned char irq);
void CheckPendingIRQ();
void MainCheckPendingIRQ(UINT16 irq_type);
void ResetInterrupts();
TIMER_CALLBACK_MEMBER( timerA_cb );
TIMER_CALLBACK_MEMBER( timerB_cb );
TIMER_CALLBACK_MEMBER( timerC_cb );
int Get_AR(int base, int R);
int Get_DR(int base, int R);
int Get_RR(int base, int R);
void Compute_EG(SCSP_SLOT *slot);
int EG_Update(SCSP_SLOT *slot);
UINT32 Step(SCSP_SLOT *slot);
void Compute_LFO(SCSP_SLOT *slot);
void StartSlot(SCSP_SLOT *slot);
void StopSlot(SCSP_SLOT *slot,int keyoff);
void init();
void UpdateSlotReg(int s,int r);
void UpdateReg(address_space &space, int reg);
void UpdateSlotRegR(int slot,int reg);
void UpdateRegR(address_space &space, int reg);
void w16(address_space &space,unsigned int addr,unsigned short val);
unsigned short r16(address_space &space, unsigned int addr);
inline INT32 UpdateSlot(SCSP_SLOT *slot);
void DoMasterSamples(int nsamples);
//LFO
void LFO_Init();
signed int PLFO_Step(SCSP_LFO_t *LFO);
signed int ALFO_Step(SCSP_LFO_t *LFO);
void LFO_ComputeStep(SCSP_LFO_t *LFO,UINT32 LFOF,UINT32 LFOWS,UINT32 LFOS,int ALFO);
};
extern const device_type SCSP;

View File

@ -1,5 +1,4 @@
#include "emu.h"
#include "scsp.h"
#include "scspdsp.h"
static UINT16 PACK(INT32 val)

View File

@ -1,160 +0,0 @@
/*
SCSP LFO handling
Part of the SCSP (YMF292-F) emulator package.
(not compiled directly, #included from scsp.c)
By ElSemi
MAME/M1 conversion and cleanup by R. Belmont
*/
#define LFO_SHIFT 8
struct LFO_t
{
unsigned short phase;
UINT32 phase_step;
int *table;
int *scale;
};
#define LFIX(v) ((unsigned int) ((float) (1<<LFO_SHIFT)*(v)))
//Convert DB to multiply amplitude
#define DB(v) LFIX(pow(10.0,v/20.0))
//Convert cents to step increment
#define CENTS(v) LFIX(pow(2.0,v/1200.0))
static int PLFO_TRI[256],PLFO_SQR[256],PLFO_SAW[256],PLFO_NOI[256];
static int ALFO_TRI[256],ALFO_SQR[256],ALFO_SAW[256],ALFO_NOI[256];
static const float LFOFreq[32]=
{
0.17f,0.19f,0.23f,0.27f,0.34f,0.39f,0.45f,0.55f,0.68f,0.78f,0.92f,1.10f,1.39f,1.60f,1.87f,2.27f,
2.87f,3.31f,3.92f,4.79f,6.15f,7.18f,8.60f,10.8f,14.4f,17.2f,21.5f,28.7f,43.1f,57.4f,86.1f,172.3f
};
static const float ASCALE[8]={0.0f,0.4f,0.8f,1.5f,3.0f,6.0f,12.0f,24.0f};
static const float PSCALE[8]={0.0f,7.0f,13.5f,27.0f,55.0f,112.0f,230.0f,494.0f};
static int PSCALES[8][256];
static int ASCALES[8][256];
static void LFO_Init(running_machine &machine)
{
int i,s;
for(i=0;i<256;++i)
{
int a,p;
// float TL;
//Saw
a=255-i;
if(i<128)
p=i;
else
p=i-256;
ALFO_SAW[i]=a;
PLFO_SAW[i]=p;
//Square
if(i<128)
{
a=255;
p=127;
}
else
{
a=0;
p=-128;
}
ALFO_SQR[i]=a;
PLFO_SQR[i]=p;
//Tri
if(i<128)
a=255-(i*2);
else
a=(i*2)-256;
if(i<64)
p=i*2;
else if(i<128)
p=255-i*2;
else if(i<192)
p=256-i*2;
else
p=i*2-511;
ALFO_TRI[i]=a;
PLFO_TRI[i]=p;
//noise
//a=lfo_noise[i];
a=machine.rand()&0xff;
p=128-a;
ALFO_NOI[i]=a;
PLFO_NOI[i]=p;
}
for(s=0;s<8;++s)
{
float limit=PSCALE[s];
for(i=-128;i<128;++i)
{
PSCALES[s][i+128]=CENTS(((limit*(float) i)/128.0));
}
limit=-ASCALE[s];
for(i=0;i<256;++i)
{
ASCALES[s][i]=DB(((limit*(float) i)/256.0));
}
}
}
INLINE signed int PLFO_Step(LFO_t *LFO)
{
int p;
LFO->phase+=LFO->phase_step;
#if LFO_SHIFT!=8
LFO->phase&=(1<<(LFO_SHIFT+8))-1;
#endif
p=LFO->table[LFO->phase>>LFO_SHIFT];
p=LFO->scale[p+128];
return p<<(SHIFT-LFO_SHIFT);
}
INLINE signed int ALFO_Step(LFO_t *LFO)
{
int p;
LFO->phase+=LFO->phase_step;
#if LFO_SHIFT!=8
LFO->phase&=(1<<(LFO_SHIFT+8))-1;
#endif
p=LFO->table[LFO->phase>>LFO_SHIFT];
p=LFO->scale[p];
return p<<(SHIFT-LFO_SHIFT);
}
static void LFO_ComputeStep(LFO_t *LFO,UINT32 LFOF,UINT32 LFOWS,UINT32 LFOS,int ALFO)
{
float step=(float) LFOFreq[LFOF]*256.0/(float)44100;
LFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step);
if(ALFO)
{
switch(LFOWS)
{
case 0: LFO->table=ALFO_SAW; break;
case 1: LFO->table=ALFO_SQR; break;
case 2: LFO->table=ALFO_TRI; break;
case 3: LFO->table=ALFO_NOI; break;
}
LFO->scale=ASCALES[LFOS];
}
else
{
switch(LFOWS)
{
case 0: LFO->table=PLFO_SAW; break;
case 1: LFO->table=PLFO_SQR; break;
case 2: LFO->table=PLFO_TRI; break;
case 3: LFO->table=PLFO_NOI; break;
}
LFO->scale=PSCALES[LFOS];
}
}

View File

@ -536,7 +536,6 @@ ifneq ($(filter AICA,$(SOUNDS)),)
SOUNDOBJS += $(SOUNDOBJ)/aica.o $(SOUNDOBJ)/aicadsp.o
endif
$(SOUNDOBJ)/scsp.o: $(SOUNDSRC)/scsplfo.inc
$(SOUNDOBJ)/aica.o: $(SOUNDSRC)/aicalfo.inc