spu2x work 1

This commit is contained in:
Robert 2016-09-24 12:45:38 +02:00
parent 9af34cc611
commit 3aabc1adbf
8 changed files with 455 additions and 178 deletions

View File

@ -17,7 +17,7 @@
// Let's enable this to free the IOP event handler of some considerable load. // Let's enable this to free the IOP event handler of some considerable load.
// Games are highly unlikely to need timed IRQ's for PAD and MemoryCard handling anyway (rama). // Games are highly unlikely to need timed IRQ's for PAD and MemoryCard handling anyway (rama).
#define SIO_INLINE_IRQS //#define SIO_INLINE_IRQS
#include "MemoryCardFile.h" #include "MemoryCardFile.h"
@ -30,8 +30,8 @@ struct _mcd
u32 transferAddr; // Transfer address u32 transferAddr; // Transfer address
u8 FLAG; // for PSX; u8 FLAG; // for PSX;
u8 port; // port u8 port; // port
u8 slot; // and slot for this memcard u8 slot; // and slot for this memcard
// Auto Eject // Auto Eject
@ -55,13 +55,13 @@ struct _mcd
} }
// Read from memorycard to dest // Read from memorycard to dest
void Read(u8 *dest, int size) void Read(u8 *dest, int size)
{ {
SysPlugins.McdRead(port, slot, dest, transferAddr, size); SysPlugins.McdRead(port, slot, dest, transferAddr, size);
} }
// Write to memorycard from src // Write to memorycard from src
void Write(u8 *src, int size) void Write(u8 *src, int size)
{ {
SysPlugins.McdSave(port, slot, src,transferAddr, size); SysPlugins.McdSave(port, slot, src,transferAddr, size);
} }

View File

@ -214,7 +214,10 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
else else
DMA7LogWrite(pMem,size<<1); DMA7LogWrite(pMem,size<<1);
TSA &= 0xfffff; if (psxmode)
TSA &= 0x7ffff;
else
TSA &= 0xfffff;
u32 buff1end = TSA + size; u32 buff1end = TSA + size;
u32 buff2end=0; u32 buff2end=0;
@ -235,14 +238,11 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
cacheLine++; cacheLine++;
} while ( cacheLine != &cacheEnd ); } while ( cacheLine != &cacheEnd );
//ConLog( "* SPU2-X: Cache Clear Range! TSA=0x%x, TDA=0x%x (low8=0x%x, high8=0x%x, len=0x%x)\n",
// TSA, buff1end, flagTSA, flagTDA, clearLen );
// First Branch needs cleared: // First Branch needs cleared:
// It starts at TSA and goes to buff1end. // It starts at TSA and goes to buff1end.
const u32 buff1size = (buff1end-TSA); const u32 buff1size = (buff1end-TSA);
ConLog("* SPU2-X: DMA exec! TSA = %x buff1size*2 = %x\n", TSA, buff1size*2);
memcpy( GetMemPtr( TSA ), pMem, buff1size*2 ); memcpy( GetMemPtr( TSA ), pMem, buff1size*2 );
u32 TDA; u32 TDA;
@ -261,7 +261,8 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
// 0x2800? Hard to know for sure (almost no games depend on this) // 0x2800? Hard to know for sure (almost no games depend on this)
memcpy( GetMemPtr( 0 ), &pMem[buff1size], buff2end*2 ); memcpy( GetMemPtr( 0 ), &pMem[buff1size], buff2end*2 );
TDA = (buff2end+1) & 0xfffff; if (psxmode) TDA = (buff2end + 1) & 0x7ffff;
else TDA = (buff2end+1) & 0xfffff;
// Flag interrupt? If IRQA occurs between start and dest, flag it. // Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA! // Important: Test both core IRQ settings for either DMA!
@ -297,7 +298,8 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
// Buffer doesn't wrap/overflow! // Buffer doesn't wrap/overflow!
// Just set the TDA and check for an IRQ... // Just set the TDA and check for an IRQ...
TDA = (buff1end + 1) & 0xfffff; if (psxmode) TDA = (buff1end + 1) & 0x7ffff;
else TDA = (buff1end + 1) & 0xfffff;
// Flag interrupt? If IRQA occurs between start and dest, flag it. // Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA! // Important: Test both core IRQ settings for either DMA!
@ -402,6 +404,7 @@ void V_Core::DoDMAwrite(u16* pMem, u32 size)
if(size<2) { if(size<2) {
//if(dma7callback) dma7callback(); //if(dma7callback) dma7callback();
ConLog("* SPU2-X: Warning DMA Transfer of 0 bytes? size is %x\n", size);
Regs.STATX &= ~0x80; Regs.STATX &= ~0x80;
//Regs.ATTR |= 0x30; //Regs.ATTR |= 0x30;
DMAICounter=1; DMAICounter=1;
@ -422,11 +425,12 @@ void V_Core::DoDMAwrite(u16* pMem, u32 size)
} }
} }
TSA &= 0xfffff; if (psxmode) TSA &= 0x7ffff;
else TSA &= 0xfffff;
bool adma_enable = ((AutoDMACtrl&(Index+1))==(Index+1)); bool adma_enable = ((AutoDMACtrl&(Index+1))==(Index+1));
if(adma_enable) if(adma_enable && !psxmode) // no adma in psx mode
{ {
TSA&=0x1fff; TSA&=0x1fff;
StartADMAWrite(pMem,size); StartADMAWrite(pMem,size);

View File

@ -20,6 +20,8 @@
#define NOMINMAX #define NOMINMAX
extern bool psxmode;
struct StereoOut16; struct StereoOut16;
struct StereoOut32; struct StereoOut32;
struct StereoOutFloat; struct StereoOutFloat;

View File

@ -128,7 +128,8 @@ static void __forceinline IncrementNextA(V_Core& thiscore, uint voiceidx)
} }
vc.NextA++; vc.NextA++;
vc.NextA&=0xFFFFF; if (psxmode) vc.NextA &= 0x7FFFF;
else vc.NextA&=0xFFFFF;
} }
// decoded pcm data, used to cache the decoded data so that it needn't be decoded // decoded pcm data, used to cache the decoded data so that it needn't be decoded
@ -588,9 +589,10 @@ static __forceinline StereoOut32 MixVoice( uint coreidx, uint voiceidx )
// Write-back of raw voice data (post ADSR applied) // Write-back of raw voice data (post ADSR applied)
if (voiceidx==1) spu2M_WriteFast( ( (0==coreidx) ? 0x400 : 0xc00 ) + OutPos, vc.OutX ); if (!psxmode) { // i'm not sure if this is correct for psxmode. it doesn't seem to hurt to have it off so i assume it is bad.
else if (voiceidx==3) spu2M_WriteFast( ( (0==coreidx) ? 0x600 : 0xe00 ) + OutPos, vc.OutX ); if (voiceidx == 1) spu2M_WriteFast(((0 == coreidx) ? 0x400 : 0xc00) + OutPos, vc.OutX);
else if (voiceidx == 3) spu2M_WriteFast(((0 == coreidx) ? 0x600 : 0xe00) + OutPos, vc.OutX);
}
return ApplyVolume( StereoOut32( Value, Value ), vc.Volume ); return ApplyVolume( StereoOut32( Value, Value ), vc.Volume );
} }
else else
@ -609,9 +611,10 @@ static __forceinline StereoOut32 MixVoice( uint coreidx, uint voiceidx )
} }
// Write-back of raw voice data (some zeros since the voice is "dead") // Write-back of raw voice data (some zeros since the voice is "dead")
if (voiceidx==1) spu2M_WriteFast( ( (0==coreidx) ? 0x400 : 0xc00 ) + OutPos, 0 ); if (!psxmode) { // i'm not sure if this is correct for psxmode. it doesn't seem to hurt to have it off so i assume it is bad.
else if (voiceidx==3) spu2M_WriteFast( ( (0==coreidx) ? 0x600 : 0xe00 ) + OutPos, 0 ); if (voiceidx == 1) spu2M_WriteFast(((0 == coreidx) ? 0x400 : 0xc00) + OutPos, 0);
else if (voiceidx == 3) spu2M_WriteFast(((0 == coreidx) ? 0x600 : 0xe00) + OutPos, 0);
}
return StereoOut32( 0, 0 ); return StereoOut32( 0, 0 );
} }
} }
@ -642,11 +645,13 @@ StereoOut32 V_Core::Mix( const VoiceMixSet& inVoices, const StereoOut32& Input,
// Saturate final result to standard 16 bit range. // Saturate final result to standard 16 bit range.
const VoiceMixSet Voices( clamp_mix( inVoices.Dry ), clamp_mix( inVoices.Wet ) ); const VoiceMixSet Voices( clamp_mix( inVoices.Dry ), clamp_mix( inVoices.Wet ) );
// Write Mixed results To Output Area if (!psxmode) {
spu2M_WriteFast( ( (0==Index) ? 0x1000 : 0x1800 ) + OutPos, Voices.Dry.Left ); // Write Mixed results To Output Area
spu2M_WriteFast( ( (0==Index) ? 0x1200 : 0x1A00 ) + OutPos, Voices.Dry.Right ); spu2M_WriteFast(((0 == Index) ? 0x1000 : 0x1800) + OutPos, Voices.Dry.Left);
spu2M_WriteFast( ( (0==Index) ? 0x1400 : 0x1C00 ) + OutPos, Voices.Wet.Left ); spu2M_WriteFast(((0 == Index) ? 0x1200 : 0x1A00) + OutPos, Voices.Dry.Right);
spu2M_WriteFast( ( (0==Index) ? 0x1600 : 0x1E00 ) + OutPos, Voices.Wet.Right ); spu2M_WriteFast(((0 == Index) ? 0x1400 : 0x1C00) + OutPos, Voices.Wet.Left);
spu2M_WriteFast(((0 == Index) ? 0x1600 : 0x1E00) + OutPos, Voices.Wet.Right);
}
// Write mixed results to logfile (if enabled) // Write mixed results to logfile (if enabled)
@ -833,10 +838,12 @@ void Mix()
Ext = clamp_mix( ApplyVolume( Ext, Cores[0].MasterVol ) ); Ext = clamp_mix( ApplyVolume( Ext, Cores[0].MasterVol ) );
} }
// Commit Core 0 output to ram before mixing Core 1: if (!psxmode) {
// Commit Core 0 output to ram before mixing Core 1:
spu2M_WriteFast(0x800 + OutPos, Ext.Left);
spu2M_WriteFast(0xA00 + OutPos, Ext.Right);
}
spu2M_WriteFast( 0x800 + OutPos, Ext.Left );
spu2M_WriteFast( 0xA00 + OutPos, Ext.Right );
WaveDump::WriteCore( 0, CoreSrc_External, Ext ); WaveDump::WriteCore( 0, CoreSrc_External, Ext );
Ext = ApplyVolume( Ext, Cores[1].ExtVol ); Ext = ApplyVolume( Ext, Cores[1].ExtVol );

View File

@ -31,6 +31,7 @@
// //
StereoOut32 V_Core::ReadInput_HiFi() StereoOut32 V_Core::ReadInput_HiFi()
{ {
if (psxmode)ConLog("ReadInput_HiFi!!!!!\n");
InputPosRead &= ~1; InputPosRead &= ~1;
// //
//#ifdef PCM24_S1_INTERLEAVE //#ifdef PCM24_S1_INTERLEAVE

View File

@ -164,13 +164,6 @@ void UpdateDebugDialog()
TextOut(hdc,IX+4,IY+32,t,6); TextOut(hdc,IX+4,IY+32,t,6);
vcd.displayPeak = 0; vcd.displayPeak = 0;
if(vcd.lastSetStartA != vc.StartA)
{
printf(" *** Warning! Core %d Voice %d: StartA should be %06x, and is %06x.\n",
c,v,vcd.lastSetStartA,vc.StartA);
vcd.lastSetStartA = vc.StartA;
}
} }
// top now: 400 // top now: 400

View File

@ -28,6 +28,7 @@
extern s16* GetMemPtr(u32 addr); extern s16* GetMemPtr(u32 addr);
extern s16 spu2M_Read( u32 addr ); extern s16 spu2M_Read( u32 addr );
extern s16 spu2M_ReadPSX(u32 addr);
extern void spu2M_Write( u32 addr, s16 value ); extern void spu2M_Write( u32 addr, s16 value );
extern void spu2M_Write( u32 addr, u16 value ); extern void spu2M_Write( u32 addr, u16 value );
@ -154,6 +155,10 @@ struct V_Voice
s32 Prev1; s32 Prev1;
s32 Prev2; s32 Prev2;
// psx caches
u16 psxPitch;
u16 psxLoopStartA;
u16 psxStartA;
// Pitch Modulated by previous voice // Pitch Modulated by previous voice
bool Modulated; bool Modulated;
// Source (Wave/Noise) // Source (Wave/Noise)
@ -441,6 +446,15 @@ struct V_Core
u32 KeyOn; // not the KON register (though maybe it is) u32 KeyOn; // not the KON register (though maybe it is)
// psxmode caches
u16 psxIRQA;
u16 psxTSA;
u16 psxSPUCNT;
u16 psxSoundDataTransferControl;
u16 psxSPUSTAT;
u16 psxReverbStartA;
StereoOut32 downbuf[8]; StereoOut32 downbuf[8];
StereoOut32 upbuf[8]; StereoOut32 upbuf[8];
int dbpos, ubpos; int dbpos, ubpos;
@ -505,12 +519,25 @@ struct V_Core
return ret; return ret;
} }
__forceinline u16 DmaReadPSX()
{
const u16 ret = (u16)spu2M_ReadPSX(TSA);
++TSA; TSA &= 0x7ffff;
return ret;
}
__forceinline void DmaWrite(u16 value) __forceinline void DmaWrite(u16 value)
{ {
spu2M_Write( TSA, value ); spu2M_Write( TSA, value );
++TSA; TSA &= 0xfffff; ++TSA; TSA &= 0xfffff;
} }
__forceinline void DmaWritePSX(u16 value)
{
spu2M_Write(TSA, value);
++TSA; TSA &= 0x7ffff;
}
void LogAutoDMA( FILE* fp ); void LogAutoDMA( FILE* fp );
s32 NewDmaRead(u32* data, u32 bytesLeft, u32* bytesProcessed); s32 NewDmaRead(u32* data, u32 bytesLeft, u32* bytesProcessed);

View File

@ -42,6 +42,8 @@ int PlayMode;
bool has_to_call_irq=false; bool has_to_call_irq=false;
bool psxmode = false;
void SetIrqCall(int core) void SetIrqCall(int core)
{ {
// reset by an irq disable/enable cycle, behaviour found by // reset by an irq disable/enable cycle, behaviour found by
@ -67,6 +69,11 @@ __forceinline s16 spu2M_Read( u32 addr )
return *GetMemPtr( addr & 0xfffff ); return *GetMemPtr( addr & 0xfffff );
} }
__forceinline s16 spu2M_ReadPSX(u32 addr)
{
return *GetMemPtr(addr & 0x7ffff);
}
// writes a signed value to the SPU2 ram // writes a signed value to the SPU2 ram
// Invalidates the ADPCM cache in the process. // Invalidates the ADPCM cache in the process.
__forceinline void spu2M_Write( u32 addr, s16 value ) __forceinline void spu2M_Write( u32 addr, s16 value )
@ -116,6 +123,7 @@ void V_Core::Init( int index )
{ {
ConLog( "* SPU2-X: Init SPU2 core %d \n", index ); ConLog( "* SPU2-X: Init SPU2 core %d \n", index );
memset( this, 0, sizeof(V_Core) ); memset( this, 0, sizeof(V_Core) );
psxmode = false;
const int c = Index = index; const int c = Index = index;
@ -191,32 +199,32 @@ void V_Core::AnalyzeReverbPreset()
{ {
ConLog("Reverb Parameter Update for Core %d:\n", Index); ConLog("Reverb Parameter Update for Core %d:\n", Index);
ConLog("----------------------------------------------------------\n"); ConLog("----------------------------------------------------------\n");
ConLog(" IN_COEF_L, IN_COEF_R 0x%08x, 0x%08x\n", Revb.IN_COEF_L, Revb.IN_COEF_R); ConLog(" IN_COEF_L, IN_COEF_R 0x%08x, 0x%08x\n", Revb.IN_COEF_L, Revb.IN_COEF_R);
ConLog(" FB_SRC_A, FB_SRC_B 0x%08x, 0x%08x\n", Revb.FB_SRC_A, Revb.FB_SRC_B); ConLog(" FB_SRC_A, FB_SRC_B 0x%08x, 0x%08x\n", Revb.FB_SRC_A, Revb.FB_SRC_B);
ConLog(" FB_ALPHA, FB_X 0x%08x, 0x%08x\n", Revb.FB_ALPHA, Revb.FB_X); ConLog(" FB_ALPHA, FB_X 0x%08x, 0x%08x\n", Revb.FB_ALPHA, Revb.FB_X);
ConLog(" ACC_COEF_A 0x%08x\n", Revb.ACC_COEF_A); ConLog(" ACC_COEF_A 0x%08x\n", Revb.ACC_COEF_A);
ConLog(" ACC_COEF_B 0x%08x\n", Revb.ACC_COEF_B); ConLog(" ACC_COEF_B 0x%08x\n", Revb.ACC_COEF_B);
ConLog(" ACC_COEF_C 0x%08x\n", Revb.ACC_COEF_C); ConLog(" ACC_COEF_C 0x%08x\n", Revb.ACC_COEF_C);
ConLog(" ACC_COEF_D 0x%08x\n", Revb.ACC_COEF_D); ConLog(" ACC_COEF_D 0x%08x\n", Revb.ACC_COEF_D);
ConLog(" ACC_SRC_A0, ACC_SRC_A1 0x%08x, 0x%08x\n", Revb.ACC_SRC_A0, Revb.ACC_SRC_A1); ConLog(" ACC_SRC_A0, ACC_SRC_A1 0x%08x, 0x%08x\n", Revb.ACC_SRC_A0, Revb.ACC_SRC_A1);
ConLog(" ACC_SRC_B0, ACC_SRC_B1 0x%08x, 0x%08x\n", Revb.ACC_SRC_B0, Revb.ACC_SRC_B1); ConLog(" ACC_SRC_B0, ACC_SRC_B1 0x%08x, 0x%08x\n", Revb.ACC_SRC_B0, Revb.ACC_SRC_B1);
ConLog(" ACC_SRC_C0, ACC_SRC_C1 0x%08x, 0x%08x\n", Revb.ACC_SRC_C0, Revb.ACC_SRC_C1); ConLog(" ACC_SRC_C0, ACC_SRC_C1 0x%08x, 0x%08x\n", Revb.ACC_SRC_C0, Revb.ACC_SRC_C1);
ConLog(" ACC_SRC_D0, ACC_SRC_D1 0x%08x, 0x%08x\n", Revb.ACC_SRC_D0, Revb.ACC_SRC_D1); ConLog(" ACC_SRC_D0, ACC_SRC_D1 0x%08x, 0x%08x\n", Revb.ACC_SRC_D0, Revb.ACC_SRC_D1);
ConLog(" IIR_SRC_A0, IIR_SRC_A1 0x%08x, 0x%08x\n", Revb.IIR_SRC_A0, Revb.IIR_SRC_A1); ConLog(" IIR_SRC_A0, IIR_SRC_A1 0x%08x, 0x%08x\n", Revb.IIR_SRC_A0, Revb.IIR_SRC_A1);
ConLog(" IIR_SRC_B0, IIR_SRC_B1 0x%08x, 0x%08x\n", Revb.IIR_SRC_B0, Revb.IIR_SRC_B1); ConLog(" IIR_SRC_B0, IIR_SRC_B1 0x%08x, 0x%08x\n", Revb.IIR_SRC_B0, Revb.IIR_SRC_B1);
ConLog(" IIR_DEST_A0, IIR_DEST_A1 0x%08x, 0x%08x\n", Revb.IIR_DEST_A0, Revb.IIR_DEST_A1); ConLog(" IIR_DEST_A0, IIR_DEST_A1 0x%08x, 0x%08x\n", Revb.IIR_DEST_A0, Revb.IIR_DEST_A1);
ConLog(" IIR_DEST_B0, IIR_DEST_B1 0x%08x, 0x%08x\n", Revb.IIR_DEST_B0, Revb.IIR_DEST_B1); ConLog(" IIR_DEST_B0, IIR_DEST_B1 0x%08x, 0x%08x\n", Revb.IIR_DEST_B0, Revb.IIR_DEST_B1);
ConLog(" IIR_ALPHA, IIR_COEF 0x%08x, 0x%08x\n", Revb.IIR_ALPHA, Revb.IIR_COEF); ConLog(" IIR_ALPHA, IIR_COEF 0x%08x, 0x%08x\n", Revb.IIR_ALPHA, Revb.IIR_COEF);
ConLog(" MIX_DEST_A0 0x%08x\n", Revb.MIX_DEST_A0); ConLog(" MIX_DEST_A0 0x%08x\n", Revb.MIX_DEST_A0);
ConLog(" MIX_DEST_A1 0x%08x\n", Revb.MIX_DEST_A1); ConLog(" MIX_DEST_A1 0x%08x\n", Revb.MIX_DEST_A1);
ConLog(" MIX_DEST_B0 0x%08x\n", Revb.MIX_DEST_B0); ConLog(" MIX_DEST_B0 0x%08x\n", Revb.MIX_DEST_B0);
ConLog(" MIX_DEST_B1 0x%08x\n", Revb.MIX_DEST_B1); ConLog(" MIX_DEST_B1 0x%08x\n", Revb.MIX_DEST_B1);
ConLog(" EffectsBufferSize 0x%x\n", EffectsBufferSize); ConLog(" EffectsBufferSize 0x%x\n", EffectsBufferSize);
ConLog("----------------------------------------------------------\n"); ConLog("----------------------------------------------------------\n");
} }
@ -226,7 +234,7 @@ s32 V_Core::EffectsBufferIndexer( s32 offset ) const
// that it *4's all addresses before upping them to the SPU2 -- so our buffers are // that it *4's all addresses before upping them to the SPU2 -- so our buffers are
// already x4'd. It doesn't really make sense that we should x4 them again, and this // already x4'd. It doesn't really make sense that we should x4 them again, and this
// seems to work. (feedback-free in bios and DDS) --air // seems to work. (feedback-free in bios and DDS) --air
u32 pos = EffectsStartA + offset; u32 pos = EffectsStartA + offset;
// Need to use modulus here, because games can and will drop the buffer size // Need to use modulus here, because games can and will drop the buffer size
@ -261,12 +269,12 @@ void V_Core::UpdateEffectsBufferSize()
//printf("Rvb Area change: ESA = %x, EEA = %x, Size(dec) = %d, Size(hex) = %x FxEnable = %d\n", EffectsStartA, EffectsEndA, newbufsize * 2, newbufsize * 2, FxEnable); //printf("Rvb Area change: ESA = %x, EEA = %x, Size(dec) = %d, Size(hex) = %x FxEnable = %d\n", EffectsStartA, EffectsEndA, newbufsize * 2, newbufsize * 2, FxEnable);
if( (newbufsize*2) > 0x20000 ) // max 128kb per core if( (newbufsize*2) > 0x20000 ) // max 128kb per core
{ {
//printf("too big, returning\n"); //printf("too big, returning\n");
//return; //return;
} }
if (newbufsize == EffectsBufferSize && EffectsStartA == EffectsBufferStart) return; if (newbufsize == EffectsBufferSize && EffectsStartA == EffectsBufferStart) return;
RevBuffers.NeedsUpdated = false; RevBuffers.NeedsUpdated = false;
EffectsBufferSize = newbufsize; EffectsBufferSize = newbufsize;
EffectsBufferStart = EffectsStartA; EffectsBufferStart = EffectsStartA;
@ -274,7 +282,7 @@ void V_Core::UpdateEffectsBufferSize()
if( EffectsBufferSize <= 0 ) return; if( EffectsBufferSize <= 0 ) return;
//AnalyzeReverbPreset(); //AnalyzeReverbPreset();
// Rebuild buffer indexers. // Rebuild buffer indexers.
RevBuffers.ACC_SRC_A0 = EffectsBufferIndexer( Revb.ACC_SRC_A0 ); RevBuffers.ACC_SRC_A0 = EffectsBufferIndexer( Revb.ACC_SRC_A0 );
RevBuffers.ACC_SRC_A1 = EffectsBufferIndexer( Revb.ACC_SRC_A1 ); RevBuffers.ACC_SRC_A1 = EffectsBufferIndexer( Revb.ACC_SRC_A1 );
@ -401,6 +409,7 @@ __forceinline void TimeUpdate(u32 cClocks)
Cores[0].DMAICounter-=TickInterval; Cores[0].DMAICounter-=TickInterval;
if(Cores[0].DMAICounter<=0) if(Cores[0].DMAICounter<=0)
{ {
ConLog("counter set and callback!\n");
Cores[0].MADR=Cores[0].TADR; Cores[0].MADR=Cores[0].TADR;
Cores[0].DMAICounter=0; Cores[0].DMAICounter=0;
if(dma4callback) dma4callback(); if(dma4callback) dma4callback();
@ -489,6 +498,27 @@ void V_VolumeSlide::RegSet( u16 src )
Value = GetVol32( src ); Value = GetVol32( src );
} }
// Ah the joys of endian-specific code! :D
static __forceinline void SetHiWord(u32& src, u16 value)
{
((u16*)&src)[1] = value;
}
static __forceinline void SetLoWord(u32& src, u16 value)
{
((u16*)&src)[0] = value;
}
static __forceinline u16 GetHiWord(u32& src)
{
return ((u16*)&src)[1];
}
static __forceinline u16 GetLoWord(u32& src)
{
return ((u16*)&src)[0];
}
void V_Core::WriteRegPS1( u32 mem, u16 value ) void V_Core::WriteRegPS1( u32 mem, u16 value )
{ {
pxAssume( Index == 0 ); // Valid on Core 0 only! pxAssume( Index == 0 ); // Valid on Core 0 only!
@ -501,32 +531,89 @@ void V_Core::WriteRegPS1( u32 mem, u16 value )
//voice values //voice values
u8 voice = ((reg-0x1c00)>>4); u8 voice = ((reg-0x1c00)>>4);
u8 vval = reg&0xf; u8 vval = reg&0xf;
switch(vval) switch(vval)
{ {
case 0x0: //VOLL (Volume L) case 0x0: //VOLL (Volume L)
Voices[voice].Volume.Left.Mode = 0; {
Voices[voice].Volume.Left.RegSet( value << 1 ); V_VolumeSlide& thisvol = Voices[voice].Volume.Left;
Voices[voice].Volume.Left.Reg_VOL = value; thisvol.Reg_VOL = value;
break;
if (value & 0x8000) // +Lin/-Lin/+Exp/-Exp
{
thisvol.Mode = (value & 0xF000) >> 12;
thisvol.Increment = (value & 0x7F);
// We're not sure slides work 100%
if (IsDevBuild) ConLog("* SPU2: Voice uses Slides in Mode = %x, Increment = %x\n", thisvol.Mode, thisvol.Increment);
}
else
{
// Constant Volume mode (no slides or envelopes)
// Volumes range from 0x3fff to 0x7fff, with 0x4000 serving as
// the "sign" bit, so a simple bitwise extension will do the trick:
thisvol.RegSet(value << 1);
thisvol.Mode = 0;
thisvol.Increment = 0;
}
//ConLog("voice %x VOLL write: %x\n", voice, value);
break;
}
case 0x2: //VOLR (Volume R) case 0x2: //VOLR (Volume R)
Voices[voice].Volume.Right.Mode = 0; {
Voices[voice].Volume.Right.RegSet( value << 1 ); V_VolumeSlide& thisvol = Voices[voice].Volume.Right;
Voices[voice].Volume.Right.Reg_VOL = value; thisvol.Reg_VOL = value;
break;
case 0x4: Voices[voice].Pitch = value; break; if (value & 0x8000) // +Lin/-Lin/+Exp/-Exp
case 0x6: Voices[voice].StartA = (u32)value << 8; break; {
thisvol.Mode = (value & 0xF000) >> 12;
thisvol.Increment = (value & 0x7F);
// We're not sure slides work 100%
if (IsDevBuild) ConLog("* SPU2: Voice uses Slides in Mode = %x, Increment = %x\n", thisvol.Mode, thisvol.Increment);
}
else
{
// Constant Volume mode (no slides or envelopes)
// Volumes range from 0x3fff to 0x7fff, with 0x4000 serving as
// the "sign" bit, so a simple bitwise extension will do the trick:
thisvol.RegSet(value << 1);
thisvol.Mode = 0;
thisvol.Increment = 0;
}
//ConLog("voice %x VOLR write: %x\n", voice, value);
break;
}
case 0x4:
if (value > 0x3fff) ConLog("* SPU2: Pitch setting too big: 0x%x\n", value);
Voices[voice].Pitch = value & 0x3fff;
//ConLog("voice %x Pitch write: %x\n", voice, Voices[voice].Pitch);
break;
case 0x6:
Voices[voice].StartA = value * 8;
Voices[voice].psxStartA = value;
//ConLog("voice %x StartA write: %x\n", voice, Voices[voice].StartA);
break;
case 0x8: // ADSR1 (Envelope) case 0x8: // ADSR1 (Envelope)
Voices[voice].ADSR.regADSR1 = value; Voices[voice].ADSR.regADSR1 = value;
//ConLog("voice %x regADSR1 write: %x\n", voice, Voices[voice].ADSR.regADSR1);
break; break;
case 0xa: // ADSR2 (Envelope) case 0xa: // ADSR2 (Envelope)
Voices[voice].ADSR.regADSR2 = value; Voices[voice].ADSR.regADSR2 = value;
//ConLog("voice %x regADSR2 write: %x\n", voice, Voices[voice].ADSR.regADSR2);
break;
case 0xc: // Voice 0..23 ADSR Current Volume
// not commonly set by games
Voices[voice].ADSR.Value = (value << 16) | value;
//ConLog("voice %x ADSR.Value write: %x\n", voice, Voices[voice].ADSR.Value);
break;
case 0xe:
Voices[voice].LoopStartA = value * 8;
Voices[voice].psxLoopStartA = value;
//ConLog("voice %x LoopStartA write: %x\n", voice, Voices[voice].LoopStartA);
break; break;
case 0xe: Voices[voice].LoopStartA = (u32)value << 8; break;
jNO_DEFAULT; jNO_DEFAULT;
} }
@ -553,85 +640,193 @@ void V_Core::WriteRegPS1( u32 mem, u16 value )
break; break;
case 0x1d88:// Voice ON (0-15) case 0x1d88:// Voice ON (0-15)
SPU2_FastWrite(REG_S_KON,value); StartVoices(0, (u32)value);
break; break;
case 0x1d8a:// Voice ON (16-23) case 0x1d8a:// Voice ON (16-23)
SPU2_FastWrite(REG_S_KON+2,value); StartVoices(0, ((u32)value) << 16);
break; break;
case 0x1d8c:// Voice OFF (0-15) case 0x1d8c:// Voice OFF (0-15)
SPU2_FastWrite(REG_S_KOFF,value); StopVoices(0, (u32)value);
break; break;
case 0x1d8e:// Voice OFF (16-23) case 0x1d8e:// Voice OFF (16-23)
SPU2_FastWrite(REG_S_KOFF+2,value); StopVoices(0, ((u32)value) << 16);
break; break;
case 0x1d90:// Channel FM (pitch lfo) mode (0-15) case 0x1d90:// Channel FM (pitch lfo) mode (0-15)
SPU2_FastWrite(REG_S_PMON,value); Regs.PMON = value & 0xFFFF;
for (int vc = 1; vc<16; ++vc)
Voices[vc].Modulated = (value >> vc) & 1;
if (value != 0) ConLog("spu2x warning: wants to set Pitch Modulation reg1 to %x \n", value);
break; break;
case 0x1d92:// Channel FM (pitch lfo) mode (16-23) case 0x1d92:// Channel FM (pitch lfo) mode (16-23)
SPU2_FastWrite(REG_S_PMON+2,value); Regs.PMON = value << 16;
for (int vc = 0; vc<8; ++vc)
Voices[vc + 16].Modulated = (value >> vc) & 1;
break; break;
case 0x1d94:// Channel Noise mode (0-15) case 0x1d94:// Channel Noise mode (0-15)
SPU2_FastWrite(REG_S_NON,value); SetLoWord(Regs.NON, value);
for (int vc = 0; vc<16; ++vc)
Voices[vc].Noise = (value >> vc) & 1;
if (value != 0) ConLog("spu2x warning: wants to set Channel Noise mode reg1 to %x\n", value);
break; break;
case 0x1d96:// Channel Noise mode (16-23) case 0x1d96:// Channel Noise mode (16-23)
SPU2_FastWrite(REG_S_NON+2,value); SetHiWord(Regs.NON, value);
for (int vc = 0; vc<8; ++vc)
Voices[vc + 16].Noise = (value >> vc) & 1;
//ConLog("spu2x warning: wants to set Channel Noise mode reg2 to %x (ignored)\n", value);
break; break;
case 0x1d98:// Channel Reverb mode (0-15) case 0x1d98:// 1F801D98h - Voice 0..23 Reverb mode aka Echo On (EON) (R/W)
SPU2_FastWrite(REG_S_VMIXEL,value); //Regs.VMIXEL = value & 0xFFFF;
SPU2_FastWrite(REG_S_VMIXER,value); //ConLog("spu2x warning: setting reverb mode reg1 to %x \n", Regs.VMIXEL);
break; break;
case 0x1d9a:// Channel Reverb mode (16-23) case 0x1d9a:// 1F801D98h + 2 - Voice 0..23 Reverb mode aka Echo On (EON) (R/W)
SPU2_FastWrite(REG_S_VMIXEL+2,value); //Regs.VMIXEL = value << 16;
SPU2_FastWrite(REG_S_VMIXER+2,value); //ConLog("spu2x warning: setting reverb mode reg2 to %x \n", Regs.VMIXEL);
break; break;
case 0x1d9c:// Channel Reverb mode (0-15) // this was wrong? // edit: appears so!
SPU2_FastWrite(REG_S_VMIXL,value); //case 0x1d9c:// Channel Reverb mode (0-15)
SPU2_FastWrite(REG_S_VMIXR,value); // SPU2_FastWrite(REG_S_VMIXL,value);
// SPU2_FastWrite(REG_S_VMIXR,value);
//break;
//case 0x1d9e:// Channel Reverb mode (16-23)
// SPU2_FastWrite(REG_S_VMIXL+2,value);
// SPU2_FastWrite(REG_S_VMIXR+2,value);
//break;
case 0x1d9c: // Voice 0..15 ON/OFF (status) (ENDX) (R) // writeable but hw overrides it shortly after
Regs.ENDX &= 0xff0000;
ConLog("spu2x warning: wants to set ENDX reg1 to %x \n", value);
break; break;
case 0x1d9e:// Channel Reverb mode (16-23) case 0x1d9e:// // Voice 15..23 ON/OFF (status) (ENDX) (R) // writeable but hw overrides it shortly after
SPU2_FastWrite(REG_S_VMIXL+2,value); Regs.ENDX &= 0xffff;
SPU2_FastWrite(REG_S_VMIXR+2,value); ConLog("spu2x warning: wants to set ENDX reg2 to %x \n", value);
break; break;
case 0x1da2:// Reverb work area start case 0x1da2:// Reverb work area start
{ {
u32 val = (u32)value << 8; EffectsStartA = value * 8;
EffectsEndA = 0x7FFFF; // fixed EndA in psx mode
SPU2_FastWrite(REG_A_ESA, val&0xFFFF); psxReverbStartA = value;
SPU2_FastWrite(REG_A_ESA+2,val>>16); Cores[0].RevBuffers.NeedsUpdated = true;
} }
break; break;
case 0x1da4: case 0x1da4:
IRQA = (u32)value<<8; IRQA = value * 8;
psxIRQA = value;
ConLog("SPU2-X Setting IRQA to %x value was %x \n", IRQA, value);
break; break;
case 0x1da6: case 0x1da6:
TSA = (u32)value<<8; TSA = value * 8;
psxTSA = value;
ConLog("SPU2-X Setting TSA to %x value was %x \n", TSA, value);
break;
case 0x1da8: // Spu Write to Memory
ConLog("SPU direct DMA Write. Current TSA = %x\n", TSA);
if (Cores[0].IRQEnable && (Cores[0].IRQA <= Cores[0].TSA))
{
SetIrqCall(0);
_irqcallback();
}
DmaWritePSX(value);
show = false;
break; break;
case 0x1daa: case 0x1daa:
SPU2_FastWrite(REG_C_ATTR,value); {
psxSPUCNT = value;
ConLog("SPU Control register write with %x\n", value);
bool irqe = Cores[0].IRQEnable;
int bit0 = Cores[0].AttrBit0;
bool fxenable = Cores[0].FxEnable;
u8 oldDmaMode = Cores[0].DmaMode;
Cores[0].AttrBit0 = (value >> 0) & 0x01; //1 bit
Cores[0].DMABits = (value >> 1) & 0x07; //3 bits
Cores[0].DmaMode = (value >> 4) & 0x03; //2 bit (not necessary, we get the direction from the iop)
Cores[0].IRQEnable = (value >> 6) & 0x01; //1 bit
Cores[0].FxEnable = (value >> 7) & 0x01; //1 bit
Cores[0].NoiseClk = (value >> 8) & 0x3f; //6 bits
//thiscore.Mute =(value>>14) & 0x01; //1 bit
Cores[0].Mute = 0;
//thiscore.CoreEnabled=(value>>15) & 0x01; //1 bit
// no clue
if (value >> 15)
Cores[0].Regs.STATX = 0;
Cores[0].Regs.ATTR = value & 0x7fff;
if (fxenable && !Cores[0].FxEnable)
{
Cores[0].ReverbX = 0;
Cores[0].RevBuffers.NeedsUpdated = true;
}
if (oldDmaMode != Cores[0].DmaMode)
{
// FIXME... maybe: if this mode was cleared in the middle of a DMA, should we interrupt it?
ConLog("* SPU2-X: DMA mode changed. oldDmaMode = %x , newDmaMode = %x \n", oldDmaMode,Cores[0].DmaMode);
Cores[0].Regs.STATX &= ~0x400; // ready to transfer
}
if (value & 0x000E)
{
if (MsgToConsole()) ConLog("* SPU2-X: Core 0 ATTR unknown bits SET! value=%x\n", value);
}
if (Cores[0].AttrBit0 != bit0)
{
if (MsgToConsole()) ConLog("* SPU2-X: ATTR bit 0 set to %d\n", Cores[0].AttrBit0);
}
if (Cores[0].IRQEnable != irqe)
{
ConLog("* SPU2-X: write reg psx Core%d IRQ %s at cycle %d. Current IRQA = %x Current TSA = %x\n",
0, ((Cores[0].IRQEnable==0)?"disabled":"enabled"), Cycles, Cores[0].IRQA, Cores[0].TSA);
if (!Cores[0].IRQEnable)
Spdif.Info &= ~(4 << Cores[0].Index);
}
}
break; break;
case 0x1dae: case 0x1dac: // 1F801DACh - Sound RAM Data Transfer Control (should be 0004h)
SPU2_FastWrite(REG_P_STATX,value); ConLog("SPU Sound RAM Data Transfer Control (should be 0004h) : value = %x \n", value);
break; psxSoundDataTransferControl = value;
break;
case 0x1dae: // 1F801DAEh - SPU Status Register (SPUSTAT) (R)
// The SPUSTAT register should be treated read-only (writing is possible in so far that the written
// value can be read-back for a short moment, however, thereafter the hardware is overwriting that value).
//Regs.STATX = value;
break;
case 0x1DB0: // 1F801DB0h 4 CD Volume Left/Right
break; // cd left?
case 0x1DB2:
break;// cd right?
case 0x1DB4: // 1F801DB4h 4 Extern Volume Left / Right
break; // Extern left?
case 0x1DB6:
break; // Extern right?
case 0x1DB8: // 1F801DB8h 4 Current Main Volume Left/Right
break; // Current left?
case 0x1DBA:
break; // Current right?
case 0x1DBC: // 1F801DBCh 4 Unknown? (R/W)
break;
case 0x1DBE:
break;
case 0x1da8:// Spu Write to Memory
DmaWrite(value);
show=false;
break;
} }
if(show) FileLog("[%10d] (!) SPU write mem %08x value %04x\n",Cycles,mem,value); if(show) FileLog("[%10d] (!) SPU write mem %08x value %04x\n",Cycles,mem,value);
@ -641,6 +836,7 @@ void V_Core::WriteRegPS1( u32 mem, u16 value )
u16 V_Core::ReadRegPS1(u32 mem) u16 V_Core::ReadRegPS1(u32 mem)
{ {
//ConLog("ReadRegPS1 from %x on core %d\n", mem, Index);
pxAssume( Index == 0 ); // Valid on Core 0 only! pxAssume( Index == 0 ); // Valid on Core 0 only!
bool show=true; bool show=true;
@ -655,24 +851,40 @@ u16 V_Core::ReadRegPS1(u32 mem)
u8 vval = reg&0xf; u8 vval = reg&0xf;
switch(vval) switch(vval)
{ {
case 0: //VOLL (Volume L) case 0x0: //VOLL (Volume L)
//value=Voices[voice].VolumeL.Mode; //value=Voices[voice].VolumeL.Mode;
//value=Voices[voice].VolumeL.Value; //value=Voices[voice].VolumeL.Value;
value = Voices[voice].Volume.Left.Reg_VOL; value = Voices[voice].Volume.Left.Reg_VOL;
break; break;
case 1: //VOLR (Volume R) case 0x2: //VOLR (Volume R)
//value=Voices[voice].VolumeR.Mode; //value=Voices[voice].VolumeR.Mode;
//value=Voices[voice].VolumeR.Value; //value=Voices[voice].VolumeR.Value;
value = Voices[voice].Volume.Right.Reg_VOL; value = Voices[voice].Volume.Right.Reg_VOL;
break; break;
case 2: value = Voices[voice].Pitch; break; case 0x4:
case 3: value = Voices[voice].StartA; break; value = Voices[voice].Pitch;
case 4: value = Voices[voice].ADSR.regADSR1; break; //ConLog("voice %d read pitch result = %x\n", voice, value);
case 5: value = Voices[voice].ADSR.regADSR2; break; break;
case 6: value = Voices[voice].ADSR.Value >> 16; break; case 0x6:
case 7: value = Voices[voice].LoopStartA; break; value = Voices[voice].psxStartA;
//ConLog("voice %d read StartA result = %x\n", voice, value);
break;
case 0x8:
value = Voices[voice].ADSR.regADSR1;
break;
case 0xa:
value = Voices[voice].ADSR.regADSR2;
break;
case 0xc: // Voice 0..23 ADSR Current Volume
value = Voices[voice].ADSR.Value >> 16; // no clue
//if (value != 0) ConLog("voice %d read ADSR.Value result = %x\n", voice, value);
break;
case 0xe:
value = Voices[voice].psxLoopStartA;
//ConLog("voice %d read LoopStartA result = %x\n", voice, value);
break;
jNO_DEFAULT; jNO_DEFAULT;
} }
@ -684,75 +896,58 @@ u16 V_Core::ReadRegPS1(u32 mem)
case 0x1d84: value = FxVol.Left >> 16; break; case 0x1d84: value = FxVol.Left >> 16; break;
case 0x1d86: value = FxVol.Right >> 16; break; case 0x1d86: value = FxVol.Right >> 16; break;
case 0x1d88: value = 0; break; case 0x1d88: value = 0; break; // Voice 0..23 Key ON(Start Attack / Decay / Sustain) (W)
case 0x1d8a: value = 0; break; case 0x1d8a: value = 0; break;
case 0x1d8c: value = 0; break; case 0x1d8c: value = 0; break; // Voice 0..23 Key OFF (Start Release) (W)
case 0x1d8e: value = 0; break; case 0x1d8e: value = 0; break;
case 0x1d90: value = Regs.PMON&0xFFFF; break; case 0x1d90: value = Regs.PMON&0xFFFF; break; // Voice 0..23 Channel FM(pitch lfo) mode(R / W)
case 0x1d92: value = Regs.PMON>>16; break; case 0x1d92: value = Regs.PMON>>16; break;
case 0x1d94: value = Regs.NON&0xFFFF; break; case 0x1d94: value = Regs.NON&0xFFFF; break; // Voice 0..23 Channel Noise mode (R/W)
case 0x1d96: value = Regs.NON>>16; break; case 0x1d96: value = Regs.NON>>16; break;
case 0x1d98: value = Regs.VMIXEL&0xFFFF; break; case 0x1d98: value = Regs.VMIXEL&0xFFFF; break; // Voice 0..23 Channel Reverb mode (R/W)
case 0x1d9a: value = Regs.VMIXEL>>16; break; case 0x1d9a: value = Regs.VMIXEL>>16; break;
case 0x1d9c: value = Regs.VMIXL&0xFFFF; break; /*case 0x1d9c: value = Regs.VMIXL&0xFFFF; break;*/ // this is wrong?
case 0x1d9e: value = Regs.VMIXL>>16; break; /*case 0x1d9e: value = Regs.VMIXL >> 16; break;*/
case 0x1d9c: value = Regs.ENDX & 0xFFFF; break;// Voice 0..23 Channel ON / OFF(status) (R) (ENDX)
case 0x1d9e: value = Regs.ENDX >> 16;
case 0x1da2: case 0x1da2:
#if 0 value = psxReverbStartA;
// This smells of old hack
if( value != EffectsStartA>>3 )
{
value = EffectsStartA>>3;
UpdateEffectsBufferSize();
ReverbX = 0;
}
#else
value = EffectsStartA >> 3;
#endif
break;
case 0x1da4: value = IRQA>>3; break;
case 0x1da6: value = TSA>>3; break;
case 0x1daa:
value = SPU2read(REG_C_ATTR);
break; break;
case 0x1dae: case 0x1da4:
value = 0; //SPU2read(REG_P_STATX)<<3; value = psxIRQA;
ConLog("SPU2-X IRQA read: 0x1da4 = %x , (IRQA = %x)\n", value, IRQA);
break;
case 0x1da6:
value = psxTSA;
ConLog("SPU2-X TSA read: 0x1da6 = %x , (TSA = %x)\n", value, TSA);
break; break;
case 0x1da8: case 0x1da8:
value = DmaRead(); value = DmaRead();
show=false; show=false;
break; break;
case 0x1daa:
//value = psxSPUCNT;
value = Cores[0].Regs.ATTR;
ConLog("SPU2-X ps1 reg psxSPUCNT read return value: %x\n", value);
break;
case 0x1dac: // 1F801DACh - Sound RAM Data Transfer Control (should be 0004h)
value = psxSoundDataTransferControl;
break;
case 0x1dae:
value = Regs.STATX;
//value = Cores[0].Regs.STATX;
ConLog("SPU2-X ps1 reg REG_P_STATX read return value: %x\n", value);
break;
} }
if(show) FileLog("[%10d] (!) SPU read mem %08x value %04x\n",Cycles,mem,value); if(show) FileLog("[%10d] (!) SPU read mem %08x value %04x\n",Cycles,mem,value);
return value; return value;
} }
// Ah the joys of endian-specific code! :D
static __forceinline void SetHiWord( u32& src, u16 value )
{
((u16*)&src)[1] = value;
}
static __forceinline void SetLoWord( u32& src, u16 value )
{
((u16*)&src)[0] = value;
}
static __forceinline u16 GetHiWord( u32& src )
{
return ((u16*)&src)[1];
}
static __forceinline u16 GetLoWord( u32& src )
{
return ((u16*)&src)[0];
}
template< int CoreIdx, int VoiceIdx, int param > template< int CoreIdx, int VoiceIdx, int param >
static void __fastcall RegWrite_VoiceParams( u16 value ) static void __fastcall RegWrite_VoiceParams( u16 value )
{ {
@ -871,7 +1066,7 @@ static void __fastcall RegWrite_Core( u16 value )
const int omem = cAddr; const int omem = cAddr;
const int core = CoreIdx; const int core = CoreIdx;
V_Core& thiscore = Cores[core]; V_Core& thiscore = Cores[core];
//ConLog("RegWrite_Core #%d addr: %x value %x \n", core, omem, value);
switch(omem) switch(omem)
{ {
case REG__1AC: case REG__1AC:
@ -899,35 +1094,36 @@ static void __fastcall RegWrite_Core( u16 value )
case REG_C_ATTR: case REG_C_ATTR:
{ {
bool irqe = thiscore.IRQEnable; bool irqe = thiscore.IRQEnable;
int bit0 = thiscore.AttrBit0; int bit0 = thiscore.AttrBit0;
bool fxenable = thiscore.FxEnable; bool fxenable = thiscore.FxEnable;
u8 oldDmaMode = thiscore.DmaMode; u8 oldDmaMode = thiscore.DmaMode;
thiscore.AttrBit0 =(value>> 0) & 0x01; //1 bit thiscore.AttrBit0 = (value >> 0) & 0x01; //1 bit
thiscore.DMABits =(value>> 1) & 0x07; //3 bits thiscore.DMABits = (value >> 1) & 0x07; //3 bits
thiscore.DmaMode =(value>> 4) & 0x03; //2 bit (not necessary, we get the direction from the iop) thiscore.DmaMode = (value >> 4) & 0x03; //2 bit (not necessary, we get the direction from the iop)
thiscore.IRQEnable =(value>> 6) & 0x01; //1 bit thiscore.IRQEnable = (value >> 6) & 0x01; //1 bit
thiscore.FxEnable =(value>> 7) & 0x01; //1 bit thiscore.FxEnable = (value >> 7) & 0x01; //1 bit
thiscore.NoiseClk =(value>> 8) & 0x3f; //6 bits thiscore.NoiseClk = (value >> 8) & 0x3f; //6 bits
//thiscore.Mute =(value>>14) & 0x01; //1 bit //thiscore.Mute =(value>>14) & 0x01; //1 bit
thiscore.Mute =0; thiscore.Mute = 0;
//thiscore.CoreEnabled=(value>>15) & 0x01; //1 bit //thiscore.CoreEnabled=(value>>15) & 0x01; //1 bit
// no clue // no clue
if (value>>15) if (value >> 15)
thiscore.Regs.STATX = 0; thiscore.Regs.STATX = 0;
thiscore.Regs.ATTR =value&0x7fff; thiscore.Regs.ATTR = value & 0x7fff;
if (fxenable && !thiscore.FxEnable if (!psxmode) {
&& (thiscore.EffectsStartA != thiscore.ExtEffectsStartA if (fxenable && !thiscore.FxEnable
|| thiscore.EffectsEndA != thiscore.ExtEffectsEndA)) && (thiscore.EffectsStartA != thiscore.ExtEffectsStartA
{ || thiscore.EffectsEndA != thiscore.ExtEffectsEndA))
thiscore.EffectsStartA = thiscore.ExtEffectsStartA; {
thiscore.EffectsEndA = thiscore.ExtEffectsEndA; thiscore.EffectsStartA = thiscore.ExtEffectsStartA;
thiscore.ReverbX = 0; thiscore.EffectsEndA = thiscore.ExtEffectsEndA;
thiscore.RevBuffers.NeedsUpdated = true; thiscore.ReverbX = 0;
thiscore.RevBuffers.NeedsUpdated = true;
}
} }
if(oldDmaMode != thiscore.DmaMode) if(oldDmaMode != thiscore.DmaMode)
{ {
// FIXME... maybe: if this mode was cleared in the middle of a DMA, should we interrupt it? // FIXME... maybe: if this mode was cleared in the middle of a DMA, should we interrupt it?
@ -947,7 +1143,7 @@ static void __fastcall RegWrite_Core( u16 value )
{ {
//ConLog("* SPU2-X: Core%d IRQ %s at cycle %d. Current IRQA = %x Current EffectA = %x\n", //ConLog("* SPU2-X: Core%d IRQ %s at cycle %d. Current IRQA = %x Current EffectA = %x\n",
// core, ((thiscore.IRQEnable==0)?"disabled":"enabled"), Cycles, thiscore.IRQA, thiscore.EffectsStartA); // core, ((thiscore.IRQEnable==0)?"disabled":"enabled"), Cycles, thiscore.IRQA, thiscore.EffectsStartA);
if(!thiscore.IRQEnable) if(!thiscore.IRQEnable)
Spdif.Info &= ~(4 << thiscore.Index); Spdif.Info &= ~(4 << thiscore.Index);
} }
@ -990,8 +1186,8 @@ static void __fastcall RegWrite_Core( u16 value )
SetLoWord( thiscore.Regs.reg_out, value ); \ SetLoWord( thiscore.Regs.reg_out, value ); \
if( result == thiscore.Regs.reg_out ) break; \ if( result == thiscore.Regs.reg_out ) break; \
\ \
const uint start_bit = (hiword) ? 16 : 0; \ const uint start_bit = hiword ? 16 : 0; \
const uint end_bit = (hiword) ? 24 : 16; \ const uint end_bit = hiword ? 24 : 16; \
for (uint vc=start_bit, vx=1; vc<end_bit; ++vc, vx<<=1) \ for (uint vc=start_bit, vx=1; vc<end_bit; ++vc, vx<<=1) \
thiscore.VoiceGates[vc].mask_out = (value & vx) ? -1 : 0; \ thiscore.VoiceGates[vc].mask_out = (value & vx) ? -1 : 0; \
} }
@ -1072,6 +1268,7 @@ static void __fastcall RegWrite_Core( u16 value )
case REG_S_ENDX: case REG_S_ENDX:
thiscore.Regs.ENDX &= 0xff0000; thiscore.Regs.ENDX &= 0xff0000;
break; break;
case (REG_S_ENDX + 2): case (REG_S_ENDX + 2):
@ -1122,6 +1319,52 @@ static void __fastcall RegWrite_Core( u16 value )
case REG_S_ADMAS: case REG_S_ADMAS:
if ( MsgToConsole() ) ConLog("* SPU2-X: Core %d AutoDMAControl set to %d (at cycle %d)\n",core,value, Cycles); if ( MsgToConsole() ) ConLog("* SPU2-X: Core %d AutoDMAControl set to %d (at cycle %d)\n",core,value, Cycles);
// hack for ps1driver which writes -1 (and never turns the adma off after psxlogo).
// adma isn't available in psx mode either
if (value == 32767) {
psxmode = true;
//memset(spu2regs, 0, 0x010000);
memset(_spu2mem, 0, 0x200000);
Cores[0].EffectsStartA = 0x7FFF8;
Cores[0].EffectsEndA = 0x7FFFF;
Cores[0].ReverbX = 0;
Cores[0].RevBuffers.NeedsUpdated = true;
Cores[1].EffectsStartA = 0xFFFF8; // park core1 effect area in high mem
Cores[1].EffectsEndA = 0xFFFFF;
Cores[1].FxEnable = 0;
Cores[1].ExtEffectsStartA = 0xFFFF8; // park core1 ext effect area in high mem
Cores[1].ExtEffectsStartA = 0xFFFFF;
Cores[1].ReverbX = 0;
Cores[1].RevBuffers.NeedsUpdated = true;
Cores[1].Mute = 1; // silence core1 in psxmode
//for (uint v = 0; v < 24; ++v)
//{
// Cores[0].Voices[v].Volume = V_VolumeSlideLR(0, 0); // V_VolumeSlideLR::Max;
// Cores[0].Voices[v].SCurrent = 28;
// Cores[0].Voices[v].ADSR.Value = 0;
// Cores[0].Voices[v].ADSR.Phase = 0;
// Cores[0].Voices[v].Pitch = 0x1000;
// Cores[0].Voices[v].NextA = 0x1001;
// Cores[0].Voices[v].StartA = 0x1000;
// Cores[0].Voices[v].LoopStartA = 0x1000;
// Cores[0].Voices[v].Modulated = 0;
//}
for (uint v = 0; v < 24; ++v)
{
Cores[1].Voices[v].Volume = V_VolumeSlideLR(0, 0); // V_VolumeSlideLR::Max;
Cores[1].Voices[v].SCurrent = 28;
Cores[1].Voices[v].ADSR.Value = 0;
Cores[1].Voices[v].ADSR.Phase = 0;
Cores[1].Voices[v].Pitch = 0x0;
Cores[1].Voices[v].NextA = 0xBFFFF;
Cores[1].Voices[v].StartA = 0xBFFFF;
Cores[1].Voices[v].LoopStartA = 0xBFFFF;
Cores[1].Voices[v].Modulated = 0;
}
return;
}
thiscore.AutoDMACtrl=value; thiscore.AutoDMACtrl=value;
if(value==0) if(value==0)
@ -1264,10 +1507,10 @@ static void __fastcall RegWrite_Null( u16 value )
#define CoreParamsPair( core, omem ) \ #define CoreParamsPair( core, omem ) \
RegWrite_Core<core, omem>, RegWrite_Core<core, ((omem)+2)> RegWrite_Core<core, omem>, RegWrite_Core<core, (omem+2)>
#define ReverbPair( core, mem ) \ #define ReverbPair( core, mem ) \
RegWrite_Reverb<core, mem>, RegWrite_Core<core, ((mem)+2)> RegWrite_Reverb<core, mem>, RegWrite_Core<core, (mem+2)>
#define REGRAW(addr) RegWrite_Raw<addr> #define REGRAW(addr) RegWrite_Raw<addr>