aica is modern device as well now (nw)

This commit is contained in:
Miodrag Milanovic 2014-03-21 09:56:48 +00:00
parent a8b5250590
commit e683baeadf
12 changed files with 811 additions and 820 deletions

1
.gitattributes vendored
View File

@ -2735,7 +2735,6 @@ src/emu/sound/aica.c svneol=native#text/plain
src/emu/sound/aica.h svneol=native#text/plain
src/emu/sound/aicadsp.c svneol=native#text/plain
src/emu/sound/aicadsp.h svneol=native#text/plain
src/emu/sound/aicalfo.inc svneol=native#text/plain
src/emu/sound/asc.c svneol=native#text/plain
src/emu/sound/asc.h svneol=native#text/plain
src/emu/sound/astrocde.c svneol=native#text/plain

File diff suppressed because it is too large Load Diff

View File

@ -6,45 +6,203 @@
#ifndef __AICA_H__
#define __AICA_H__
#include "aicadsp.h"
struct aica_interface
#define MCFG_AICA_MASTER \
aica_device::set_master(*device);
#define MCFG_AICA_ROFFSET(_offs) \
aica_device::set_roffset(*device, _offs);
#define MCFG_AICA_IRQ_CB(_devcb) \
devcb = &aica_device::set_irq_callback(*device, DEVCB2_##_devcb);
#define MCFG_AICA_MAIN_IRQ_CB(_devcb) \
devcb = &aica_device::set_main_irq_callback(*device, DEVCB2_##_devcb);
enum AICA_STATE {AICA_ATTACK,AICA_DECAY1,AICA_DECAY2,AICA_RELEASE};
struct AICA_LFO_t
{
int master;
int roffset; /* offset in the region */
devcb_write_line irq_callback; /* irq callback */
devcb_write_line master_irq_callback;
unsigned short phase;
UINT32 phase_step;
int *table;
int *scale;
};
void aica_set_ram_base(device_t *device, void *base, int size);
// AICA register access
DECLARE_READ16_DEVICE_HANDLER( aica_r );
DECLARE_WRITE16_DEVICE_HANDLER( aica_w );
struct AICA_EG_t
{
int volume; //
AICA_STATE state;
int step;
//step vals
int AR; //Attack
int D1R; //Decay1
int D2R; //Decay2
int RR; //Release
// MIDI I/O access
DECLARE_WRITE16_DEVICE_HANDLER( aica_midi_in );
DECLARE_READ16_DEVICE_HANDLER( aica_midi_out_r );
int DL; //Decay level
UINT8 LPLINK;
};
struct AICA_SLOT
{
union
{
UINT16 data[0x40]; //only 0x1a bytes used
UINT8 datab[0x80];
} udata;
UINT8 active; //this slot is currently playing
UINT8 *base; //samples base address
UINT32 prv_addr; // previous play address (for ADPCM)
UINT32 cur_addr; //current play address (24.8)
UINT32 nxt_addr; //next play address
UINT32 step; //pitch step (24.8)
UINT8 Backwards; //the wave is playing backwards
AICA_EG_t EG; //Envelope
AICA_LFO_t PLFO; //Phase LFO
AICA_LFO_t ALFO; //Amplitude LFO
int slot;
int cur_sample; //current ADPCM sample
int cur_quant; //current ADPCM step
int curstep;
int cur_lpquant, cur_lpsample, cur_lpstep;
UINT8 *adbase, *adlpbase;
UINT8 lpend;
};
class aica_device : public device_t,
public device_sound_interface
{
public:
aica_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~aica_device();
// access to legacy token
struct aica_state *token() const { assert(m_token != NULL); return m_token; }
static void set_master(device_t &device) { downcast<aica_device &>(device).m_master = true; }
static void set_roffset(device_t &device, int roffset) { downcast<aica_device &>(device).m_roffset = roffset; }
template<class _Object> static devcb2_base &set_irq_callback(device_t &device, _Object object) { return downcast<aica_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<aica_device &>(device).m_main_irq_cb.set_callback(object); }
// AICA register access
DECLARE_READ16_MEMBER( read );
DECLARE_WRITE16_MEMBER( write );
// MIDI I/O access
DECLARE_WRITE16_MEMBER( midi_in );
DECLARE_READ16_MEMBER( midi_out_r );
void set_ram_base(void *base, int size);
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
virtual void device_stop();
// 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 aica_state *m_token;
unsigned char DecodeSCI(unsigned char irq);
void ResetInterrupts();
void CheckPendingIRQ();
void CheckPendingIRQ_SH4();
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(AICA_SLOT *slot);
int EG_Update(AICA_SLOT *slot);
UINT32 Step(AICA_SLOT *slot);
void Compute_LFO(AICA_SLOT *slot);
void InitADPCM(int *PrevSignal, int *PrevQuant);
inline signed short DecodeADPCM(int *PrevSignal, unsigned char Delta, int *PrevQuant);
void StartSlot(AICA_SLOT *slot);
void StopSlot(AICA_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(AICA_SLOT *slot);
void DoMasterSamples(int nsamples);
void aica_exec_dma(address_space &space);
void AICALFO_Init();
inline signed int AICAPLFO_Step(AICA_LFO_t *LFO);
inline signed int AICAALFO_Step(AICA_LFO_t *LFO);
void AICALFO_ComputeStep(AICA_LFO_t *LFO,UINT32 LFOF,UINT32 LFOWS,UINT32 LFOS,int ALFO);
bool m_master;
int m_roffset; /* offset in the region */
devcb2_write_line m_irq_cb;
devcb2_write_line m_main_irq_cb;
union
{
UINT16 data[0xc0/2];
UINT8 datab[0xc0];
} m_udata;
UINT16 m_IRQL, m_IRQR;
UINT16 m_EFSPAN[0x48];
AICA_SLOT m_Slots[64];
signed short m_RINGBUF[64];
unsigned char m_BUFPTR;
unsigned char *m_AICARAM;
UINT32 m_AICARAM_LENGTH, m_RAM_MASK, m_RAM_MASK16;
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[16];
UINT8 m_MidiW,m_MidiR;
int m_LPANTABLE[0x20000];
int m_RPANTABLE[0x20000];
int m_TimPris[3];
int m_TimCnt[3];
UINT16 m_mcieb, m_mcipd;
// timers
emu_timer *m_timerA, *m_timerB, *m_timerC;
// DMA stuff
struct{
UINT32 dmea;
UINT16 drga;
UINT16 dlg;
UINT8 dgate;
UINT8 ddir;
}m_dma;
int m_ARTABLE[64], m_DRTABLE[64];
AICADSP 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
INT32 m_EG_TABLE[0x400];
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];
};
extern const device_type AICA;

View File

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

View File

@ -1,159 +0,0 @@
/*
AICA LFO handling
Part of the AICA emulator package.
(not compiled directly, #included from aica.c)
By ElSemi, kingshriek, Deunan Knute, and 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 AICALFO_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 AICAPLFO_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 AICAALFO_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 AICALFO_ComputeStep(LFO_t *LFO,UINT32 LFOF,UINT32 LFOWS,UINT32 LFOS,int ALFO)
{
float step=(float) LFOFreq[LFOF]*256.0/(float)44100.0;
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;
default: printf("Unknown ALFO %d\n", LFOWS);
}
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;
default: printf("Unknown PLFO %d\n", LFOWS);
}
LFO->scale=PSCALES[LFOS];
}
}

View File

@ -204,13 +204,10 @@ void scsp_device::device_start()
init();
// set up the IRQ callbacks
{
m_irq_cb.resolve_safe();
m_stream = machine().sound().stream_alloc(*this, 0, 2, 44100, this);
}
m_irq_cb.resolve_safe();
m_main_irq_cb.resolve_safe();
m_stream = machine().sound().stream_alloc(*this, 0, 2, 44100, this);
}
//-------------------------------------------------

View File

@ -76,7 +76,6 @@ class scsp_device : public device_t,
{
public:
scsp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~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); }

View File

@ -536,10 +536,6 @@ ifneq ($(filter AICA,$(SOUNDS)),)
SOUNDOBJS += $(SOUNDOBJ)/aica.o $(SOUNDOBJ)/aicadsp.o
endif
$(SOUNDOBJ)/aica.o: $(SOUNDSRC)/aicalfo.inc
#-------------------------------------------------
# Seta custom sound chips
#@src/emu/sound/st0016.h,SOUNDS += ST0016

View File

@ -1812,15 +1812,6 @@ WRITE_LINE_MEMBER(naomi_state::sh4_aica_irq)
dc_update_interrupt_status();
}
static const aica_interface aica_config =
{
TRUE,
0,
DEVCB_DRIVER_LINE_MEMBER(naomi_state,aica_irq),
DEVCB_DRIVER_LINE_MEMBER(naomi_state,sh4_aica_irq)
};
static ADDRESS_MAP_START( dc_audio_map, AS_PROGRAM, 32, naomi_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x00000000, 0x007fffff) AM_RAM AM_SHARE("dc_sound_ram") /* shared with SH-4 */
@ -2487,7 +2478,7 @@ INPUT_PORTS_END
MACHINE_RESET_MEMBER(naomi_state,naomi)
{
naomi_state::machine_reset();
aica_set_ram_base(machine().device("aica"), dc_sound_ram, 8*1024*1024);
m_aica->set_ram_base(dc_sound_ram, 8*1024*1024);
}
/*
@ -2521,7 +2512,10 @@ static MACHINE_CONFIG_START( naomi_aw_base, naomi_state )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_SOUND_ADD("aica", AICA, 0)
MCFG_SOUND_CONFIG(aica_config)
MCFG_AICA_MASTER
MCFG_AICA_IRQ_CB(WRITELINE(naomi_state, aica_irq))
MCFG_AICA_MAIN_IRQ_CB(WRITELINE(naomi_state, sh4_aica_irq))
MCFG_SOUND_ROUTE(0, "lspeaker", 2.0)
MCFG_SOUND_ROUTE(1, "rspeaker", 2.0)

View File

@ -10,6 +10,7 @@
#include "video/powervr2.h"
#include "machine/naomig1.h"
#include "machine/maple-dc.h"
#include "sound/aica.h"
class dc_state : public driver_device
{
@ -24,7 +25,8 @@ class dc_state : public driver_device
m_soundcpu(*this, "soundcpu"),
m_powervr2(*this, "powervr2"),
m_maple(*this, "maple_dc"),
m_naomig1(*this, "rom_board") { }
m_naomig1(*this, "rom_board"),
m_aica(*this, "aica") { }
required_shared_ptr<UINT64> dc_framebuffer_ram; // '32-bit access area'
required_shared_ptr<UINT64> dc_texture_ram; // '64-bit access area'
@ -80,6 +82,7 @@ class dc_state : public driver_device
required_device<powervr2_device> m_powervr2;
required_device<maple_dc_device> m_maple;
optional_device<naomi_g1_device> m_naomig1;
required_device<aica_device> m_aica;
void generic_dma(UINT32 main_adr, void *dma_ptr, UINT32 length, UINT32 size, bool to_mainram);
TIMER_DEVICE_CALLBACK_MEMBER(dc_scanline);

View File

@ -8,7 +8,6 @@
#include "debugger.h"
#include "includes/dc.h"
#include "cpu/sh4/sh4.h"
#include "sound/aica.h"
#include "machine/mie.h"
#include "machine/naomig1.h"
#include "video/powervr2.h"
@ -681,7 +680,7 @@ READ32_MEMBER(dc_state::dc_aica_reg_r)
if(offset == 0x2c00/4)
return m_armrst;
return aica_r(machine().device("aica"), space, offset*2, 0xffff);
return m_aica->read(space, offset*2, 0xffff);
}
WRITE32_MEMBER(dc_state::dc_aica_reg_w)
@ -705,19 +704,19 @@ WRITE32_MEMBER(dc_state::dc_aica_reg_w)
}
}
aica_w(machine().device("aica"), space, offset*2, data, 0xffff);
m_aica->write(space, offset*2, data, 0xffff);
// mame_printf_verbose("AICA REG: [%08x=%x] write %x to %x, mask %" I64FMT "x\n", 0x700000+reg*4, data, offset, mem_mask);
}
READ32_MEMBER(dc_state::dc_arm_aica_r)
{
return aica_r(machine().device("aica"), space, offset*2, 0xffff) & 0xffff;
return m_aica->read(space, offset*2, 0xffff) & 0xffff;
}
WRITE32_MEMBER(dc_state::dc_arm_aica_w)
{
aica_w(machine().device("aica"), space, offset*2, data, mem_mask&0xffff);
m_aica->write(space, offset*2, data, mem_mask&0xffff);
}
TIMER_DEVICE_CALLBACK_MEMBER(dc_state::dc_scanline)

View File

@ -576,9 +576,8 @@ INPUT_PORTS_END
MACHINE_RESET_MEMBER(dc_cons_state,dc_console)
{
device_t *aica = machine().device("aica");
dc_state::machine_reset();
aica_set_ram_base(aica, dc_sound_ram, 2*1024*1024);
m_aica->set_ram_base(dc_sound_ram, 2*1024*1024);
}
WRITE_LINE_MEMBER(dc_cons_state::aica_irq)
@ -596,14 +595,6 @@ WRITE_LINE_MEMBER(dc_cons_state::sh4_aica_irq)
dc_update_interrupt_status();
}
static const aica_interface dc_aica_interface =
{
TRUE,
0,
DEVCB_DRIVER_LINE_MEMBER(dc_cons_state,aica_irq),
DEVCB_DRIVER_LINE_MEMBER(dc_cons_state,sh4_aica_irq)
};
static const struct sh4_config sh4cpu_config = { 1, 0, 1, 0, 0, 0, 1, 1, 0, CPU_CLOCK };
static MACHINE_CONFIG_FRAGMENT( gdrom_config )
@ -642,7 +633,9 @@ static MACHINE_CONFIG_START( dc, dc_cons_state )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_SOUND_ADD("aica", AICA, 0)
MCFG_SOUND_CONFIG(dc_aica_interface)
MCFG_AICA_MASTER
MCFG_AICA_IRQ_CB(WRITELINE(dc_cons_state, aica_irq))
MCFG_AICA_MAIN_IRQ_CB(WRITELINE(dc_cons_state, sh4_aica_irq))
MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
MCFG_SOUND_ROUTE(0, "rspeaker", 1.0)