mirror of
https://github.com/holub/mame
synced 2025-07-05 18:08:04 +03:00
scsp is modern device, thanks Osso for most of the work (nw)
This commit is contained in:
parent
c12b058645
commit
343c6a3866
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
1070
src/emu/sound/scsp.c
1070
src/emu/sound/scsp.c
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "emu.h"
|
||||
#include "scsp.h"
|
||||
#include "scspdsp.h"
|
||||
|
||||
static UINT16 PACK(INT32 val)
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user