Cog/Frameworks/HighlyExperimental/HighlyExperimental/Core/spu.c
2013-09-30 03:36:30 -07:00

812 lines
45 KiB
C

/////////////////////////////////////////////////////////////////////////////
//
// spu - Top-level SPU emulation, for SPU and SPU2
//
/////////////////////////////////////////////////////////////////////////////
#ifndef EMU_COMPILE
#error "Hi I forgot to set EMU_COMPILE"
#endif
#include "spu.h"
#include "spucore.h"
////////////////////////////////////////////////////////////////////////////////
/*
** Static information
*/
sint32 EMU_CALL spu_init(void) { return 0; }
////////////////////////////////////////////////////////////////////////////////
/*
** State information
*/
#define SPUSTATE ((struct SPU_STATE*)(state))
#define CORESTATE(n) ((void*)(((char*)(state))+(SPUSTATE->offset_to_core[(n)])))
#define SPURAM ((void*)(((char*)(state))+(SPUSTATE->offset_to_ram)))
struct SPU_STATE {
uint8 version;
uint32 offset_to_ram;
uint32 offset_to_core[2];
/* actual plugin option */
uint8 global_main_on;
uint8 global_effect_on;
uint32 tsa[2];
uint8 dma_mode[2];
uint8 is_on[2];
uint8 is_audible[2];
uint8 is_reverb_enabled[2];
uint8 is_irq_enabled[2];
uint16 mystery_dma[2];
};
/*
** Get size depending on version
*/
uint32 EMU_CALL spu_get_state_size(uint8 version) {
uint32 size = 0;
if(version != 2) { version = 1; }
size += sizeof(struct SPU_STATE);
switch(version) {
case 1:
size += spucore_get_state_size();
size += 0x80000;
break;
case 2:
size += spucore_get_state_size() * 2;
size += 0x200000;
break;
}
return size;
}
/*
** Initialize SPU state
*/
void EMU_CALL spu_clear_state(void *state, uint8 version) {
uint32 offset;
if(version != 2) { version = 1; }
/*
** Clear to zero
*/
memset(state, 0, sizeof(struct SPU_STATE));
/*
** Set version
*/
SPUSTATE->version = version;
/*
** Set offsets
*/
offset = sizeof(struct SPU_STATE);
switch(version) {
case 1:
/* Both cores point to the same place (safety) */
SPUSTATE->offset_to_core[0] = offset;
SPUSTATE->offset_to_core[1] = offset; offset += spucore_get_state_size();
SPUSTATE->offset_to_ram = offset;
break;
case 2:
SPUSTATE->offset_to_core[0] = offset; offset += spucore_get_state_size();
SPUSTATE->offset_to_core[1] = offset; offset += spucore_get_state_size();
SPUSTATE->offset_to_ram = offset;
break;
}
//
// Set local flags
//
SPUSTATE->global_main_on = 1;
SPUSTATE->global_effect_on = 1;
/*
** Init SPU core states / clear SPU RAM
*/
switch(version) {
case 1:
spucore_clear_state(CORESTATE(0));
spucore_set_mem_size(CORESTATE(0), 0x80000);
memset(SPURAM, 0, 0x80000);
break;
case 2:
spucore_clear_state(CORESTATE(0));
spucore_clear_state(CORESTATE(1));
spucore_set_mem_size(CORESTATE(0), 0x200000);
spucore_set_mem_size(CORESTATE(1), 0x200000);
memset(SPURAM, 0, 0x200000);
break;
}
}
/*
** Enable/disable reverb
*/
void EMU_CALL spu_enable_reverb(void *state, uint8 enable) {
SPUSTATE->global_effect_on = enable;
}
void EMU_CALL spu_enable_main(void *state, uint8 enable) {
SPUSTATE->global_main_on = enable;
}
////////////////////////////////////////////////////////////////////////////////
/*
** Hardware register load/store
*/
static uint32 EMU_CALL get_tsa(struct SPU_STATE *state, uint32 core) {
return state->tsa[core];
}
static void EMU_CALL set_tsa(struct SPU_STATE *state, uint32 core, uint32 a, uint32 mask) {
state->tsa[core] &= ~mask;
state->tsa[core] |= a & mask;
}
static EMU_INLINE uint16 EMU_CALL get_transfer(struct SPU_STATE *state, uint32 core) {
uint32 memmask = (state->version == 2) ? 0x001FFFFE : 0x0007FFFE;
uint16 d = *((uint16*)(((uint8*)(SPURAM)) + ((state->tsa[core]) & memmask)));
state->tsa[core] += 2;
state->tsa[core] &= memmask;
return d;
}
static EMU_INLINE void EMU_CALL set_transfer(struct SPU_STATE *state, uint32 core, uint16 d) {
uint32 memmask = (state->version == 2) ? 0x001FFFFE : 0x0007FFFE;
*((uint16*)(((uint8*)(SPURAM)) + ((state->tsa[core]) & memmask))) = d;
state->tsa[core] += 2;
state->tsa[core] &= memmask;
}
void EMU_CALL spu_dma(void *state, uint32 core, void *mem, uint32 mem_ofs, uint32 mem_mask, uint32 bytes, int iswrite) {
uint32 words = (bytes + 3) / 4;
mem_ofs &= (~3);
if(iswrite) {
while(words--) {
uint32 d;
mem_ofs &= mem_mask;
d = *((uint32*)(((uint8*)mem)+mem_ofs));
set_transfer(state, core, d );
set_transfer(state, core, d >> 16);
mem_ofs += 4;
}
} else {
while(words--) {
uint32 d;
mem_ofs &= mem_mask;
d = ((uint32)(get_transfer(state, core))) ;
d |= ((uint32)(get_transfer(state, core))) << 16;
*((uint32*)(((uint8*)mem)+mem_ofs)) = d;
mem_ofs += 4;
}
}
// complete flag?
SPUSTATE->mystery_dma[core] |= 0x80;
}
static uint16 EMU_CALL get_mystery_dma(struct SPU_STATE *state, uint32 core) {
uint16 m = state->mystery_dma[core];
state->mystery_dma[core] = 0;
return m;
}
static void EMU_CALL set_mystery_dma(struct SPU_STATE *state, uint32 core, uint16 n) {
}
static uint16 EMU_CALL get_ctrl(struct SPU_STATE *state, uint32 core) {
uint32 on = !!(spucore_getflag(CORESTATE(core), SPUREG_FLAG_ON));
uint32 main_enable = !!(spucore_getflag(CORESTATE(core), SPUREG_FLAG_MAIN_ENABLE));
uint32 noiseclock = spucore_getreg(CORESTATE(core), SPUREG_NOISECLOCK) & 0x3F;
uint32 reverb_enable = !!(spucore_getflag(CORESTATE(core), SPUREG_FLAG_REVERB_ENABLE));
uint32 irq_enable = !!(spucore_getflag(CORESTATE(core), SPUREG_FLAG_IRQ_ENABLE));
uint32 dmamode = state->dma_mode[core] & 3;
uint32 er = !!(spucore_getflag(CORESTATE(core), SPUREG_FLAG_ER));
uint32 cr = !!(spucore_getflag(CORESTATE(core), SPUREG_FLAG_CR));
uint32 ee = !!(spucore_getflag(CORESTATE(core), SPUREG_FLAG_EE));
uint32 ce = !!(spucore_getflag(CORESTATE(core), SPUREG_FLAG_CE));
return (
(on << 15) |
(main_enable << 14) |
(noiseclock << 8) |
(reverb_enable << 7) |
(irq_enable << 6) |
(dmamode << 4) |
(er << 3) |
(cr << 2) |
(ee << 1) |
(ce << 0)
);
}
static void EMU_CALL set_ctrl(struct SPU_STATE *state, uint32 core, uint16 d) {
spucore_setflag(CORESTATE(core), SPUREG_FLAG_ON , !!(d & (1<<15)));
spucore_setflag(CORESTATE(core), SPUREG_FLAG_MAIN_ENABLE , !!(d & (1<<14)));
spucore_setreg (CORESTATE(core), SPUREG_NOISECLOCK, (d >> 8) & 0x3F, 0x3F);
spucore_setflag(CORESTATE(core), SPUREG_FLAG_REVERB_ENABLE, !!(d & (1<< 7)));
spucore_setflag(CORESTATE(core), SPUREG_FLAG_IRQ_ENABLE , !!(d & (1<< 6)));
state->dma_mode[core] = (d >> 4) & 3;
spucore_setflag(CORESTATE(core), SPUREG_FLAG_ER , !!(d & (1<< 3)));
spucore_setflag(CORESTATE(core), SPUREG_FLAG_CR , !!(d & (1<< 2)));
spucore_setflag(CORESTATE(core), SPUREG_FLAG_EE , !!(d & (1<< 1)));
spucore_setflag(CORESTATE(core), SPUREG_FLAG_CE , !!(d & (1<< 0)));
}
static uint16 EMU_CALL get_mmix(struct SPU_STATE *state, uint32 core) {
uint16 d = 0;
if(spucore_getflag(CORESTATE(core), SPUREG_FLAG_MSNDL )) d |= (1<<11);
if(spucore_getflag(CORESTATE(core), SPUREG_FLAG_MSNDR )) d |= (1<<10);
if(spucore_getflag(CORESTATE(core), SPUREG_FLAG_MSNDEL)) d |= (1<< 9);
if(spucore_getflag(CORESTATE(core), SPUREG_FLAG_MSNDER)) d |= (1<< 8);
if(spucore_getflag(CORESTATE(core), SPUREG_FLAG_MINL )) d |= (1<< 7);
if(spucore_getflag(CORESTATE(core), SPUREG_FLAG_MINR )) d |= (1<< 6);
if(spucore_getflag(CORESTATE(core), SPUREG_FLAG_MINEL )) d |= (1<< 5);
if(spucore_getflag(CORESTATE(core), SPUREG_FLAG_MINER )) d |= (1<< 4);
if(spucore_getflag(CORESTATE(core), SPUREG_FLAG_SINL )) d |= (1<< 3);
if(spucore_getflag(CORESTATE(core), SPUREG_FLAG_SINR )) d |= (1<< 2);
if(spucore_getflag(CORESTATE(core), SPUREG_FLAG_SINEL )) d |= (1<< 1);
if(spucore_getflag(CORESTATE(core), SPUREG_FLAG_SINER )) d |= (1<< 0);
return d;
}
static void EMU_CALL set_mmix(struct SPU_STATE *state, uint32 core, uint16 d) {
spucore_setflag(CORESTATE(core), SPUREG_FLAG_MSNDL , (d >> 11) & 1);
spucore_setflag(CORESTATE(core), SPUREG_FLAG_MSNDR , (d >> 10) & 1);
spucore_setflag(CORESTATE(core), SPUREG_FLAG_MSNDEL, (d >> 9) & 1);
spucore_setflag(CORESTATE(core), SPUREG_FLAG_MSNDER, (d >> 8) & 1);
spucore_setflag(CORESTATE(core), SPUREG_FLAG_MINL , (d >> 7) & 1);
spucore_setflag(CORESTATE(core), SPUREG_FLAG_MINR , (d >> 6) & 1);
spucore_setflag(CORESTATE(core), SPUREG_FLAG_MINEL , (d >> 5) & 1);
spucore_setflag(CORESTATE(core), SPUREG_FLAG_MINER , (d >> 4) & 1);
spucore_setflag(CORESTATE(core), SPUREG_FLAG_SINL , (d >> 3) & 1);
spucore_setflag(CORESTATE(core), SPUREG_FLAG_SINR , (d >> 2) & 1);
spucore_setflag(CORESTATE(core), SPUREG_FLAG_SINEL , (d >> 1) & 1);
spucore_setflag(CORESTATE(core), SPUREG_FLAG_SINER , (d >> 0) & 1);
}
////////////////////////////////////////////////////////////////////////////////
/*
** SPU1 register accesses: lh1/sh1
*/
static uint16 EMU_CALL lh1(struct SPU_STATE *state, uint32 a) {
a &= 0x1FE;
if(a < 0x180) {
uint32 voice = a >> 4;
switch(a & 0xE) {
case 0x0: return spucore_getreg_voice(CORESTATE(0), voice, SPUREG_VOICE_VOLL );
case 0x2: return spucore_getreg_voice(CORESTATE(0), voice, SPUREG_VOICE_VOLR );
case 0x4: return spucore_getreg_voice(CORESTATE(0), voice, SPUREG_VOICE_PITCH);
case 0x6: return spucore_getreg_voice(CORESTATE(0), voice, SPUREG_VOICE_SSA ) >> 3;
case 0x8: return spucore_getreg_voice(CORESTATE(0), voice, SPUREG_VOICE_ADSR1);
case 0xA: return spucore_getreg_voice(CORESTATE(0), voice, SPUREG_VOICE_ADSR2);
case 0xC: return spucore_getreg_voice(CORESTATE(0), voice, SPUREG_VOICE_ENVX );
case 0xE: return spucore_getreg_voice(CORESTATE(0), voice, SPUREG_VOICE_LSAX ) >> 3;
}
} else {
switch(a) {
case 0x180: return spucore_getreg(CORESTATE(0), SPUREG_MVOLL);
case 0x182: return spucore_getreg(CORESTATE(0), SPUREG_MVOLR);
case 0x184: return spucore_getreg(CORESTATE(0), SPUREG_EVOLL);
case 0x186: return spucore_getreg(CORESTATE(0), SPUREG_EVOLR);
case 0x188: return spucore_getreg(CORESTATE(0), SPUREG_KON);
case 0x18A: return spucore_getreg(CORESTATE(0), SPUREG_KON) >> 16;
case 0x18C: return spucore_getreg(CORESTATE(0), SPUREG_KOFF);
case 0x18E: return spucore_getreg(CORESTATE(0), SPUREG_KOFF) >> 16;
case 0x190: return spucore_getreg(CORESTATE(0), SPUREG_FM);
case 0x192: return spucore_getreg(CORESTATE(0), SPUREG_FM) >> 16;
case 0x194: return spucore_getreg(CORESTATE(0), SPUREG_NOISE);
case 0x196: return spucore_getreg(CORESTATE(0), SPUREG_NOISE) >> 16;
case 0x198: return spucore_getreg(CORESTATE(0), SPUREG_VMIXE);
case 0x19A: return spucore_getreg(CORESTATE(0), SPUREG_VMIXE) >> 16;
// case 0x19C: return spucore_getreg(CORESTATE(0), SPUREG_VMIX);
// case 0x19E: return spucore_getreg(CORESTATE(0), SPUREG_VMIX) >> 16;
case 0x19C: return 0;
case 0x19E: return 0;
case 0x1A0: return 0;
case 0x1A2: return spucore_getreg(CORESTATE(0), SPUREG_ESA) >> 3;
case 0x1A4: return spucore_getreg(CORESTATE(0), SPUREG_IRQA) >> 3;
case 0x1A6: return get_tsa (state, 0) >> 3;
case 0x1A8: return get_transfer(state, 0);
case 0x1AA: return get_ctrl (state, 0);
case 0x1AC: return 0; /* TODO: what does this reg do? */
case 0x1AE: return 0; /* TODO: implement status bits (0 should be ok though) */
case 0x1B0: return spucore_getreg(CORESTATE(0), SPUREG_AVOLL);
case 0x1B2: return spucore_getreg(CORESTATE(0), SPUREG_AVOLR);
case 0x1B4: return spucore_getreg(CORESTATE(0), SPUREG_BVOLL);
case 0x1B6: return spucore_getreg(CORESTATE(0), SPUREG_BVOLR);
case 0x1B8: return 0;
case 0x1BA: return 0;
case 0x1BC: return 0;
case 0x1BE: return 0;
case 0x1C0: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_FB_SRC_A ) >> 3;
case 0x1C2: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_FB_SRC_B ) >> 3;
case 0x1C4: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_IIR_ALPHA );
case 0x1C6: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_ACC_COEF_A );
case 0x1C8: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_ACC_COEF_B );
case 0x1CA: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_ACC_COEF_C );
case 0x1CC: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_ACC_COEF_D );
case 0x1CE: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_IIR_COEF );
case 0x1D0: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_FB_ALPHA );
case 0x1D2: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_FB_X );
case 0x1D4: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_IIR_DEST_A0) >> 3;
case 0x1D6: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_IIR_DEST_A1) >> 3;
case 0x1D8: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_A0 ) >> 3;
case 0x1DA: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_A1 ) >> 3;
case 0x1DC: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_B0 ) >> 3;
case 0x1DE: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_B1 ) >> 3;
case 0x1E0: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_IIR_SRC_A0 ) >> 3;
case 0x1E2: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_IIR_SRC_A1 ) >> 3;
case 0x1E4: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_IIR_DEST_B0) >> 3;
case 0x1E6: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_IIR_DEST_B1) >> 3;
case 0x1E8: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_C0 ) >> 3;
case 0x1EA: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_C1 ) >> 3;
case 0x1EC: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_D0 ) >> 3;
case 0x1EE: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_D1 ) >> 3;
case 0x1F0: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_IIR_SRC_B1 ) >> 3;
case 0x1F2: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_IIR_SRC_B0 ) >> 3;
case 0x1F4: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_MIX_DEST_A0) >> 3;
case 0x1F6: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_MIX_DEST_A1) >> 3;
case 0x1F8: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_MIX_DEST_B0) >> 3;
case 0x1FA: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_MIX_DEST_B1) >> 3;
case 0x1FC: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_IN_COEF_L );
case 0x1FE: return spucore_getreg(CORESTATE(0), SPUREG_REVERB_IN_COEF_R );
}
}
return 0;
}
static void EMU_CALL sh1(struct SPU_STATE *state, uint32 a, uint16 d) {
a &= 0x1FE;
if(a < 0x180) {
uint32 voice = a >> 4;
switch(a & 0xE) {
case 0x0: spucore_setreg_voice(CORESTATE(0), voice, SPUREG_VOICE_VOLL , d, 0xFFFF); break;
case 0x2: spucore_setreg_voice(CORESTATE(0), voice, SPUREG_VOICE_VOLR , d, 0xFFFF); break;
case 0x4: spucore_setreg_voice(CORESTATE(0), voice, SPUREG_VOICE_PITCH, d, 0xFFFF); break;
case 0x6: spucore_setreg_voice(CORESTATE(0), voice, SPUREG_VOICE_SSA , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x8: spucore_setreg_voice(CORESTATE(0), voice, SPUREG_VOICE_ADSR1, d, 0xFFFF); break;
case 0xA: spucore_setreg_voice(CORESTATE(0), voice, SPUREG_VOICE_ADSR2, d, 0xFFFF); break;
case 0xC: spucore_setreg_voice(CORESTATE(0), voice, SPUREG_VOICE_ENVX , d, 0xFFFF); break;
case 0xE: spucore_setreg_voice(CORESTATE(0), voice, SPUREG_VOICE_LSAX , ((uint32)d) << 3, 0xFFFFFFFF); break;
}
} else {
switch(a) {
case 0x180: spucore_setreg (CORESTATE(0), SPUREG_MVOLL, d, 0xFFFF); break;
case 0x182: spucore_setreg (CORESTATE(0), SPUREG_MVOLR, d, 0xFFFF); break;
case 0x184: spucore_setreg (CORESTATE(0), SPUREG_EVOLL, d, 0xFFFF); break;
case 0x186: spucore_setreg (CORESTATE(0), SPUREG_EVOLR, d, 0xFFFF); break;
case 0x188: spucore_setreg (CORESTATE(0), SPUREG_KON , ((uint32)d) << 0, 0x0000FFFF); break;
case 0x18A: spucore_setreg (CORESTATE(0), SPUREG_KON , ((uint32)d) << 16, 0xFFFF0000); break;
case 0x18C: spucore_setreg (CORESTATE(0), SPUREG_KOFF , ((uint32)d) << 0, 0x0000FFFF); break;
case 0x18E: spucore_setreg (CORESTATE(0), SPUREG_KOFF , ((uint32)d) << 16, 0xFFFF0000); break;
case 0x190: spucore_setreg (CORESTATE(0), SPUREG_FM , ((uint32)d) << 0, 0x0000FFFF); break;
case 0x192: spucore_setreg (CORESTATE(0), SPUREG_FM , ((uint32)d) << 16, 0xFFFF0000); break;
case 0x194: spucore_setreg (CORESTATE(0), SPUREG_NOISE, ((uint32)d) << 0, 0x0000FFFF); break;
case 0x196: spucore_setreg (CORESTATE(0), SPUREG_NOISE, ((uint32)d) << 16, 0xFFFF0000); break;
case 0x198: spucore_setreg (CORESTATE(0), SPUREG_VMIXE, ((uint32)d) << 0, 0x0000FFFF); break;
case 0x19A: spucore_setreg (CORESTATE(0), SPUREG_VMIXE, ((uint32)d) << 16, 0xFFFF0000); break;
// case 0x19C: spucore_setreg (CORESTATE(0), SPUREG_VMIX , ((uint32)d) << 0, 0x0000FFFF); break;
// case 0x19E: spucore_setreg (CORESTATE(0), SPUREG_VMIX , ((uint32)d) << 16, 0xFFFF0000); break;
case 0x19C: break;
case 0x19E: break;
case 0x1A0: break;
case 0x1A2: spucore_setreg (CORESTATE(0), SPUREG_ESA , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1A4: spucore_setreg (CORESTATE(0), SPUREG_IRQA, ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1A6: set_tsa (state, 0, ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1A8: set_transfer(state, 0, d); break;
case 0x1AA: set_ctrl (state, 0, d); break;
case 0x1AC: break; /* TODO: what does this reg do? */
case 0x1AE: break; /* TODO: implement status bits (0 should be ok though) */
case 0x1B0: spucore_setreg (CORESTATE(0), SPUREG_AVOLL, d, 0xFFFF); break;
case 0x1B2: spucore_setreg (CORESTATE(0), SPUREG_AVOLR, d, 0xFFFF); break;
case 0x1B4: spucore_setreg (CORESTATE(0), SPUREG_BVOLL, d, 0xFFFF); break;
case 0x1B6: spucore_setreg (CORESTATE(0), SPUREG_BVOLR, d, 0xFFFF); break;
case 0x1B8: break;
case 0x1BA: break;
case 0x1BC: break;
case 0x1BE: break;
case 0x1C0: spucore_setreg(CORESTATE(0), SPUREG_REVERB_FB_SRC_A , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1C2: spucore_setreg(CORESTATE(0), SPUREG_REVERB_FB_SRC_B , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1C4: spucore_setreg(CORESTATE(0), SPUREG_REVERB_IIR_ALPHA , ((uint32)d) , 0x0000FFFF); break;
case 0x1C6: spucore_setreg(CORESTATE(0), SPUREG_REVERB_ACC_COEF_A , ((uint32)d) , 0x0000FFFF); break;
case 0x1C8: spucore_setreg(CORESTATE(0), SPUREG_REVERB_ACC_COEF_B , ((uint32)d) , 0x0000FFFF); break;
case 0x1CA: spucore_setreg(CORESTATE(0), SPUREG_REVERB_ACC_COEF_C , ((uint32)d) , 0x0000FFFF); break;
case 0x1CC: spucore_setreg(CORESTATE(0), SPUREG_REVERB_ACC_COEF_D , ((uint32)d) , 0x0000FFFF); break;
case 0x1CE: spucore_setreg(CORESTATE(0), SPUREG_REVERB_IIR_COEF , ((uint32)d) , 0x0000FFFF); break;
case 0x1D0: spucore_setreg(CORESTATE(0), SPUREG_REVERB_FB_ALPHA , ((uint32)d) , 0x0000FFFF); break;
case 0x1D2: spucore_setreg(CORESTATE(0), SPUREG_REVERB_FB_X , ((uint32)d) , 0x0000FFFF); break;
case 0x1D4: spucore_setreg(CORESTATE(0), SPUREG_REVERB_IIR_DEST_A0, ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1D6: spucore_setreg(CORESTATE(0), SPUREG_REVERB_IIR_DEST_A1, ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1D8: spucore_setreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_A0 , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1DA: spucore_setreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_A1 , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1DC: spucore_setreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_B0 , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1DE: spucore_setreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_B1 , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1E0: spucore_setreg(CORESTATE(0), SPUREG_REVERB_IIR_SRC_A0 , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1E2: spucore_setreg(CORESTATE(0), SPUREG_REVERB_IIR_SRC_A1 , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1E4: spucore_setreg(CORESTATE(0), SPUREG_REVERB_IIR_DEST_B0, ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1E6: spucore_setreg(CORESTATE(0), SPUREG_REVERB_IIR_DEST_B1, ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1E8: spucore_setreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_C0 , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1EA: spucore_setreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_C1 , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1EC: spucore_setreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_D0 , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1EE: spucore_setreg(CORESTATE(0), SPUREG_REVERB_ACC_SRC_D1 , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1F0: spucore_setreg(CORESTATE(0), SPUREG_REVERB_IIR_SRC_B1 , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1F2: spucore_setreg(CORESTATE(0), SPUREG_REVERB_IIR_SRC_B0 , ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1F4: spucore_setreg(CORESTATE(0), SPUREG_REVERB_MIX_DEST_A0, ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1F6: spucore_setreg(CORESTATE(0), SPUREG_REVERB_MIX_DEST_A1, ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1F8: spucore_setreg(CORESTATE(0), SPUREG_REVERB_MIX_DEST_B0, ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1FA: spucore_setreg(CORESTATE(0), SPUREG_REVERB_MIX_DEST_B1, ((uint32)d) << 3, 0xFFFFFFFF); break;
case 0x1FC: spucore_setreg(CORESTATE(0), SPUREG_REVERB_IN_COEF_L , ((uint32)d) , 0x0000FFFF); break;
case 0x1FE: spucore_setreg(CORESTATE(0), SPUREG_REVERB_IN_COEF_R , ((uint32)d) , 0x0000FFFF); break;
}
}
}
////////////////////////////////////////////////////////////////////////////////
/*
** SPU2 register accesses: lh2/sh2
*/
/*
** Returns "normalized to core0" address
** Also sets *core to 0 or 1
*/
static EMU_INLINE uint32 EMU_CALL spu2_reg_addr_normal(uint32 a, uint32 *core) {
a &= 0x7FE;
if(a < 0x400) { *core = 0; return a; }
if(a < 0x760) { *core = 1; return a-0x400; }
if(a < 0x788) { *core = 0; return a; }
if(a < 0x7B0) { *core = 1; return a-0x28; }
*core = 0; return a;
}
static uint16 EMU_CALL lh2(struct SPU_STATE *state, uint32 a) {
uint32 core = 0; a = spu2_reg_addr_normal(a, &core);
if(a < 0x180) {
uint32 voice = a >> 4;
switch(a & 0xE) {
case 0x0: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_VOLL );
case 0x2: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_VOLR );
case 0x4: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_PITCH);
case 0x6: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_ADSR1);
case 0x8: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_ADSR2);
case 0xA: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_ENVX );
case 0xC: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_VOLXL);
case 0xE: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_VOLXR);
}
} else if(a < 0x1C0) {
switch(a) {
case 0x180: return spucore_getreg(CORESTATE(core), SPUREG_FM);
case 0x182: return spucore_getreg(CORESTATE(core), SPUREG_FM) >> 16;
case 0x184: return spucore_getreg(CORESTATE(core), SPUREG_NOISE);
case 0x186: return spucore_getreg(CORESTATE(core), SPUREG_NOISE) >> 16;
case 0x188: return spucore_getreg(CORESTATE(core), SPUREG_VMIXL);
case 0x18A: return spucore_getreg(CORESTATE(core), SPUREG_VMIXL) >> 16;
case 0x18C: return spucore_getreg(CORESTATE(core), SPUREG_VMIXEL);
case 0x18E: return spucore_getreg(CORESTATE(core), SPUREG_VMIXEL) >> 16;
case 0x190: return spucore_getreg(CORESTATE(core), SPUREG_VMIXR);
case 0x192: return spucore_getreg(CORESTATE(core), SPUREG_VMIXR) >> 16;
case 0x194: return spucore_getreg(CORESTATE(core), SPUREG_VMIXER);
case 0x196: return spucore_getreg(CORESTATE(core), SPUREG_VMIXER) >> 16;
case 0x198: return get_mmix(state, core);
case 0x19A: return get_ctrl(state, core);
case 0x19C: return spucore_getreg(CORESTATE(core), SPUREG_IRQA) >> 17;
case 0x19E: return spucore_getreg(CORESTATE(core), SPUREG_IRQA) >> 1;
case 0x1A0: return spucore_getreg(CORESTATE(core), SPUREG_KON);
case 0x1A2: return spucore_getreg(CORESTATE(core), SPUREG_KON) >> 16;
case 0x1A4: return spucore_getreg(CORESTATE(core), SPUREG_KOFF);
case 0x1A6: return spucore_getreg(CORESTATE(core), SPUREG_KOFF) >> 16;
case 0x1A8: return get_tsa(state, core) >> 17;
case 0x1AA: return get_tsa(state, core) >> 1;
case 0x1AC: return get_transfer(state, core);
case 0x1AE: return 0; // do not know what this is yet but it may be important
case 0x1B0: return 0; // do not know what this is yet but it may be important
case 0x1B2: return 0;
case 0x1B4: return 0;
case 0x1B6: return 0;
case 0x1B8: return 0;
case 0x1BA: return 0;
case 0x1BC: return 0;
case 0x1BE: return 0;
}
} else if(a < 0x2E0) {
uint32 voice = (a-0x1C0)/12;
switch((a-0x1C0)%12) {
case 0x0: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_SSA ) >> 17;
case 0x2: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_SSA ) >> 1;
case 0x4: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_LSAX) >> 17;
case 0x6: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_LSAX) >> 1;
case 0x8: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_NAX ) >> 17;
case 0xA: return spucore_getreg_voice(CORESTATE(core), voice, SPUREG_VOICE_NAX ) >> 1;
}
} else {
switch(a) {
case 0x2E0: return spucore_getreg(CORESTATE(core), SPUREG_ESA) >> 17;
case 0x2E2: return spucore_getreg(CORESTATE(core), SPUREG_ESA) >> 1;
case 0x2E4: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_FB_SRC_A ) >> 17;
case 0x2E6: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_FB_SRC_A ) >> 1;
case 0x2E8: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_FB_SRC_B ) >> 17;
case 0x2EA: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_FB_SRC_B ) >> 1;
case 0x2EC: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_A0) >> 17;
case 0x2EE: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_A0) >> 1;
case 0x2F0: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_A1) >> 17;
case 0x2F2: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_A1) >> 1;
case 0x2F4: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_A0 ) >> 17;
case 0x2F6: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_A0 ) >> 1;
case 0x2F8: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_A1 ) >> 17;
case 0x2FA: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_A1 ) >> 1;
case 0x2FC: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_B0 ) >> 17;
case 0x2FE: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_B0 ) >> 1;
case 0x300: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_B1 ) >> 17;
case 0x302: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_B1 ) >> 1;
case 0x304: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_A0 ) >> 17;
case 0x306: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_A0 ) >> 1;
case 0x308: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_A1 ) >> 17;
case 0x30A: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_A1 ) >> 1;
case 0x30C: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_B0) >> 17;
case 0x30E: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_B0) >> 1;
case 0x310: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_B1) >> 17;
case 0x312: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_B1) >> 1;
case 0x314: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_C0 ) >> 17;
case 0x316: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_C0 ) >> 1;
case 0x318: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_C1 ) >> 17;
case 0x31A: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_C1 ) >> 1;
case 0x31C: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_D0 ) >> 17;
case 0x31E: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_D0 ) >> 1;
case 0x320: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_D1 ) >> 17;
case 0x322: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_D1 ) >> 1;
case 0x324: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_B1 ) >> 17;
case 0x326: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_B1 ) >> 1;
case 0x328: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_B0 ) >> 17;
case 0x32A: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_B0 ) >> 1;
case 0x32C: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_A0) >> 17;
case 0x32E: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_A0) >> 1;
case 0x330: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_A1) >> 17;
case 0x332: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_A1) >> 1;
case 0x334: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_B0) >> 17;
case 0x336: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_B0) >> 1;
case 0x338: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_B1) >> 17;
case 0x33A: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_B1) >> 1;
case 0x33C: return spucore_getreg(CORESTATE(core), SPUREG_EEA) >> 17;
case 0x33E: return spucore_getreg(CORESTATE(core), SPUREG_EEA) >> 1;
case 0x340: return spucore_getreg(CORESTATE(core), SPUREG_EAX) >> 17;
case 0x342: return spucore_getreg(CORESTATE(core), SPUREG_EAX) >> 1;
case 0x344: return get_mystery_dma(state, core);
case 0x760: return spucore_getreg(CORESTATE(core), SPUREG_MVOLL);
case 0x762: return spucore_getreg(CORESTATE(core), SPUREG_MVOLR);
case 0x764: return spucore_getreg(CORESTATE(core), SPUREG_EVOLL);
case 0x766: return spucore_getreg(CORESTATE(core), SPUREG_EVOLR);
case 0x768: return spucore_getreg(CORESTATE(core), SPUREG_AVOLL);
case 0x76A: return spucore_getreg(CORESTATE(core), SPUREG_AVOLR);
case 0x76C: return spucore_getreg(CORESTATE(core), SPUREG_BVOLL);
case 0x76E: return spucore_getreg(CORESTATE(core), SPUREG_BVOLR);
case 0x770: return spucore_getreg(CORESTATE(core), SPUREG_MVOLXL);
case 0x772: return spucore_getreg(CORESTATE(core), SPUREG_MVOLXR);
case 0x774: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_ALPHA );
case 0x776: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_COEF_A);
case 0x778: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_COEF_B);
case 0x77A: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_COEF_C);
case 0x77C: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_ACC_COEF_D);
case 0x77E: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IIR_COEF );
case 0x780: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_FB_ALPHA );
case 0x782: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_FB_X );
case 0x784: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IN_COEF_L );
case 0x786: return spucore_getreg(CORESTATE(core), SPUREG_REVERB_IN_COEF_R );
}
}
return 0;
}
static void EMU_CALL sh2(struct SPU_STATE *state, uint32 a, uint16 d) {
uint32 core = 0; a = spu2_reg_addr_normal(a, &core);
if(a < 0x180) {
uint32 voice = a >> 4;
switch(a & 0xE) {
case 0x0: spucore_setreg_voice(CORESTATE(core), voice, SPUREG_VOICE_VOLL , d, 0xFFFF); break;
case 0x2: spucore_setreg_voice(CORESTATE(core), voice, SPUREG_VOICE_VOLR , d, 0xFFFF); break;
case 0x4: spucore_setreg_voice(CORESTATE(core), voice, SPUREG_VOICE_PITCH, d, 0xFFFF); break;
case 0x6: spucore_setreg_voice(CORESTATE(core), voice, SPUREG_VOICE_ADSR1, d, 0xFFFF); break;
case 0x8: spucore_setreg_voice(CORESTATE(core), voice, SPUREG_VOICE_ADSR2, d, 0xFFFF); break;
case 0xA: break; /* ENVX is read-only */
case 0xC: break; /* VOLXL is read-only */
case 0xE: break; /* VOLXR is read-only */
}
} else if(a < 0x1C0) {
switch(a) {
case 0x180: spucore_setreg(CORESTATE(core), SPUREG_FM , ((uint32)d) , 0x0000FFFF); break;
case 0x182: spucore_setreg(CORESTATE(core), SPUREG_FM , ((uint32)d) << 16, 0xFFFF0000); break;
case 0x184: spucore_setreg(CORESTATE(core), SPUREG_NOISE , ((uint32)d) , 0x0000FFFF); break;
case 0x186: spucore_setreg(CORESTATE(core), SPUREG_NOISE , ((uint32)d) << 16, 0xFFFF0000); break;
case 0x188: spucore_setreg(CORESTATE(core), SPUREG_VMIXL , ((uint32)d) , 0x0000FFFF); break;
case 0x18A: spucore_setreg(CORESTATE(core), SPUREG_VMIXL , ((uint32)d) << 16, 0xFFFF0000); break;
case 0x18C: spucore_setreg(CORESTATE(core), SPUREG_VMIXEL, ((uint32)d) , 0x0000FFFF); break;
case 0x18E: spucore_setreg(CORESTATE(core), SPUREG_VMIXEL, ((uint32)d) << 16, 0xFFFF0000); break;
case 0x190: spucore_setreg(CORESTATE(core), SPUREG_VMIXR , ((uint32)d) , 0x0000FFFF); break;
case 0x192: spucore_setreg(CORESTATE(core), SPUREG_VMIXR , ((uint32)d) << 16, 0xFFFF0000); break;
case 0x194: spucore_setreg(CORESTATE(core), SPUREG_VMIXER, ((uint32)d) , 0x0000FFFF); break;
case 0x196: spucore_setreg(CORESTATE(core), SPUREG_VMIXER, ((uint32)d) << 16, 0xFFFF0000); break;
case 0x198: set_mmix(state, core, d); break;
case 0x19A: set_ctrl(state, core, d); break;
case 0x19C: spucore_setreg(CORESTATE(core), SPUREG_IRQA, ((uint32)d) << 17, 0xFFFE0000); break;
case 0x19E: spucore_setreg(CORESTATE(core), SPUREG_IRQA, ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x1A0: spucore_setreg(CORESTATE(core), SPUREG_KON , ((uint32)d) , 0x0000FFFF); break;
case 0x1A2: spucore_setreg(CORESTATE(core), SPUREG_KON , ((uint32)d) << 16, 0xFFFF0000); break;
case 0x1A4: spucore_setreg(CORESTATE(core), SPUREG_KOFF, ((uint32)d) , 0x0000FFFF); break;
case 0x1A6: spucore_setreg(CORESTATE(core), SPUREG_KOFF, ((uint32)d) << 16, 0xFFFF0000); break;
case 0x1A8: set_tsa(state, core, ((uint32)d) << 17, 0xFFFE0000); break;
case 0x1AA: set_tsa(state, core, ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x1AC: set_transfer(state, core, d); break;
case 0x1AE: break; // do not know what this is yet but it may be important
case 0x1B0: break; // do not know what this is yet but it may be important
case 0x1B2: break;
case 0x1B4: break;
case 0x1B6: break;
case 0x1B8: break;
case 0x1BA: break;
case 0x1BC: break;
case 0x1BE: break;
}
} else if(a < 0x2E0) {
uint32 voice = (a-0x1C0)/12;
switch((a-0x1C0)%12) {
case 0x0: spucore_setreg_voice(CORESTATE(core), voice, SPUREG_VOICE_SSA , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x2: spucore_setreg_voice(CORESTATE(core), voice, SPUREG_VOICE_SSA , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x4: spucore_setreg_voice(CORESTATE(core), voice, SPUREG_VOICE_LSAX, ((uint32)d) << 17, 0xFFFE0000); break;
case 0x6: spucore_setreg_voice(CORESTATE(core), voice, SPUREG_VOICE_LSAX, ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x8: break; /* NAX is read-only */
case 0xA: break; /* NAX is read-only */
}
} else {
switch(a) {
case 0x2E0: spucore_setreg(CORESTATE(core), SPUREG_ESA , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x2E2: spucore_setreg(CORESTATE(core), SPUREG_ESA , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x2E4: spucore_setreg(CORESTATE(core), SPUREG_REVERB_FB_SRC_A , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x2E6: spucore_setreg(CORESTATE(core), SPUREG_REVERB_FB_SRC_A , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x2E8: spucore_setreg(CORESTATE(core), SPUREG_REVERB_FB_SRC_B , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x2EA: spucore_setreg(CORESTATE(core), SPUREG_REVERB_FB_SRC_B , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x2EC: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_A0, ((uint32)d) << 17, 0xFFFE0000); break;
case 0x2EE: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_A0, ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x2F0: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_A1, ((uint32)d) << 17, 0xFFFE0000); break;
case 0x2F2: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_A1, ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x2F4: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_A0 , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x2F6: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_A0 , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x2F8: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_A1 , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x2FA: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_A1 , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x2FC: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_B0 , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x2FE: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_B0 , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x300: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_B1 , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x302: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_B1 , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x304: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_A0 , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x306: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_A0 , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x308: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_A1 , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x30A: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_A1 , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x30C: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_B0, ((uint32)d) << 17, 0xFFFE0000); break;
case 0x30E: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_B0, ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x310: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_B1, ((uint32)d) << 17, 0xFFFE0000); break;
case 0x312: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_DEST_B1, ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x314: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_C0 , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x316: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_C0 , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x318: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_C1 , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x31A: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_C1 , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x31C: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_D0 , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x31E: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_D0 , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x320: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_D1 , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x322: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_SRC_D1 , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x324: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_B1 , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x326: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_B1 , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x328: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_B0 , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x32A: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_SRC_B0 , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x32C: spucore_setreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_A0, ((uint32)d) << 17, 0xFFFE0000); break;
case 0x32E: spucore_setreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_A0, ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x330: spucore_setreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_A1, ((uint32)d) << 17, 0xFFFE0000); break;
case 0x332: spucore_setreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_A1, ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x334: spucore_setreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_B0, ((uint32)d) << 17, 0xFFFE0000); break;
case 0x336: spucore_setreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_B0, ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x338: spucore_setreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_B1, ((uint32)d) << 17, 0xFFFE0000); break;
case 0x33A: spucore_setreg(CORESTATE(core), SPUREG_REVERB_MIX_DEST_B1, ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x33C: spucore_setreg(CORESTATE(core), SPUREG_EEA , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x33E: spucore_setreg(CORESTATE(core), SPUREG_EEA , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x340: spucore_setreg(CORESTATE(core), SPUREG_EAX , ((uint32)d) << 17, 0xFFFE0000); break;
case 0x342: spucore_setreg(CORESTATE(core), SPUREG_EAX , ((uint32)d) << 1 , 0x0001FFFF); break;
case 0x344: set_mystery_dma(state, core, d); break;
case 0x760: spucore_setreg(CORESTATE(core), SPUREG_MVOLL, d, 0xFFFF); break;
case 0x762: spucore_setreg(CORESTATE(core), SPUREG_MVOLR, d, 0xFFFF); break;
case 0x764: spucore_setreg(CORESTATE(core), SPUREG_EVOLL, d, 0xFFFF); break;
case 0x766: spucore_setreg(CORESTATE(core), SPUREG_EVOLR, d, 0xFFFF); break;
case 0x768: spucore_setreg(CORESTATE(core), SPUREG_AVOLL, d, 0xFFFF); break;
case 0x76A: spucore_setreg(CORESTATE(core), SPUREG_AVOLR, d, 0xFFFF); break;
case 0x76C: spucore_setreg(CORESTATE(core), SPUREG_BVOLL, d, 0xFFFF); break;
case 0x76E: spucore_setreg(CORESTATE(core), SPUREG_BVOLR, d, 0xFFFF); break;
case 0x770: break; /* MVOLXL is read-only */
case 0x772: break; /* MVOLXR is read-only */
case 0x774: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_ALPHA , d, 0xFFFF); break;
case 0x776: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_COEF_A, d, 0xFFFF); break;
case 0x778: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_COEF_B, d, 0xFFFF); break;
case 0x77A: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_COEF_C, d, 0xFFFF); break;
case 0x77C: spucore_setreg(CORESTATE(core), SPUREG_REVERB_ACC_COEF_D, d, 0xFFFF); break;
case 0x77E: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IIR_COEF , d, 0xFFFF); break;
case 0x780: spucore_setreg(CORESTATE(core), SPUREG_REVERB_FB_ALPHA , d, 0xFFFF); break;
case 0x782: spucore_setreg(CORESTATE(core), SPUREG_REVERB_FB_X , d, 0xFFFF); break;
case 0x784: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IN_COEF_L , d, 0xFFFF); break;
case 0x786: spucore_setreg(CORESTATE(core), SPUREG_REVERB_IN_COEF_R , d, 0xFFFF); break;
}
}
}
////////////////////////////////////////////////////////////////////////////////
/*
** Externally-accessible lh/sh
*/
uint16 EMU_CALL spu_lh(void *state, uint32 a) {
a &= 0x1FFFFFFE;
if(a >= 0x1F801C00 && a <= 0x1F801DFF) {
return lh1(SPUSTATE, a);
} else if(a >= 0x1F900000 && a <= 0x1F9007FF) {
if(SPUSTATE->version == 2) return lh2(SPUSTATE, a);
}
return 0;
}
void EMU_CALL spu_sh(void *state, uint32 a, uint16 d) {
a &= 0x1FFFFFFE;
if(a >= 0x1F801C00 && a <= 0x1F801DFF) {
sh1(SPUSTATE, a, d);
} else if(a >= 0x1F900000 && a <= 0x1F9007FF) {
if(SPUSTATE->version == 2) sh2(SPUSTATE, a, d);
}
}
////////////////////////////////////////////////////////////////////////////////
void EMU_CALL spu_render(void *state, sint16 *buf, uint32 samples) {
uint8 mainout = SPUSTATE->global_main_on;
uint8 effectout = SPUSTATE->global_effect_on;
// mainout = 0;
if(SPUSTATE->version == 1) {
spucore_render(CORESTATE(0), SPURAM, buf, NULL, samples, mainout, effectout);
} else {
spucore_render(CORESTATE(0), SPURAM, buf, NULL, samples, mainout, effectout);
spucore_render(CORESTATE(1), SPURAM, buf, buf , samples, mainout, effectout);
// spucore_render(CORESTATE(1), SPURAM, buf, NULL, samples);
}
}
////////////////////////////////////////////////////////////////////////////////
void EMU_CALL spu_render_ext(void *state, sint16 *buf, sint16 *ext, uint32 samples) {
uint8 mainout = SPUSTATE->global_main_on;
uint8 effectout = SPUSTATE->global_effect_on;
// mainout = 0;
if(SPUSTATE->version == 1) {
spucore_render(CORESTATE(0), SPURAM, buf, ext, samples, mainout, effectout);
} else {
spucore_render(CORESTATE(0), SPURAM, buf, ext, samples, mainout, effectout);
spucore_render(CORESTATE(1), SPURAM, buf, buf, samples, mainout, effectout);
// spucore_render(CORESTATE(1), SPURAM, buf, NULL, samples);
}
}
////////////////////////////////////////////////////////////////////////////////
uint32 EMU_CALL spu_cycles_until_interrupt(void *state, uint32 samples) {
if(SPUSTATE->version == 1) {
return spucore_cycles_until_interrupt(CORESTATE(0), SPURAM, samples);
} else {
uint32 cycles1 = spucore_cycles_until_interrupt(CORESTATE(0), SPURAM, samples);
uint32 cycles2 = spucore_cycles_until_interrupt(CORESTATE(1), SPURAM, samples);
return cycles1 < cycles2 ? cycles1 : cycles2;
}
}
////////////////////////////////////////////////////////////////////////////////