SPU2: Get rid of dynamic allocations

This commit is contained in:
Stenzek 2023-05-13 16:11:10 +10:00 committed by refractionpcsx2
parent 191ea50663
commit 6426f4432e
10 changed files with 66 additions and 102 deletions

View File

@ -14,17 +14,22 @@
*/
#include "PrecompiledHeader.h"
#include "Global.h"
#include "SPU2/Global.h"
#include "common/Assertions.h"
#include <array>
static constexpr s32 ADSR_MAX_VOL = 0x7fffffff;
static const int InvExpOffsets[] = {0, 4, 6, 8, 9, 10, 11, 12};
static u32 PsxRates[160];
using PSXRateTable = std::array<u32, 160>;
void InitADSR() // INIT ADSR
static constexpr PSXRateTable ComputePSXRates()
{
PSXRateTable rates = {};
for (int i = 0; i < (32 + 128); i++)
{
const int shift = (i - 32) >> 2;
@ -35,10 +40,13 @@ void InitADSR() // INIT ADSR
rate <<= shift;
// Maximum rate is 0x4000.
PsxRates[i] = (int)std::min(rate, (s64)0x40000000LL);
rates[i] = (int)std::min(rate, (s64)0x40000000LL);
}
return rates;
}
static constexpr const PSXRateTable PsxRates = ComputePSXRates();
bool V_ADSR::Calculate()
{
pxAssume(Phase != 0);

View File

@ -113,7 +113,7 @@ static void __forceinline IncrementNextA(V_Core& thiscore, uint voiceidx)
// decoded pcm data, used to cache the decoded data so that it needn't be decoded
// multiple times. Cache chunks are decoded when the mixer requests the blocks, and
// invalided when DMA transfers and memory writes are performed.
PcmCacheEntry* pcm_cache_data = nullptr;
PcmCacheEntry pcm_cache_data[pcm_BlockCount];
int g_counter_cache_hits = 0;
int g_counter_cache_misses = 0;

View File

@ -16,6 +16,11 @@
#include "PrecompiledHeader.h"
#include "Global.h"
#define U16P(x) ((u16*)&(x))
// Returns the hiword of a 32 bit integer.
#define U16P_HI(x) (((u16*)&(x)) + 1)
#define PCORE(c, p) \
U16P(Cores[c].p)
@ -48,10 +53,10 @@
PCORE(c, Revb.n) + 1, \
PCORE(c, Revb.n)
u16* regtable[0x401];
u16 const* const regtable_original[0x401] =
{
static std::array<u16*, 0x401> ComputeRegTable()
{
static const std::array<u16*, 0x401> orig_table =
{{
// Voice Params: 8 params, 24 voices = 0x180 bytes
PVC(0, 0), PVC(0, 1), PVC(0, 2), PVC(0, 3), PVC(0, 4), PVC(0, 5),
PVC(0, 6), PVC(0, 7), PVC(0, 8), PVC(0, 9), PVC(0, 10), PVC(0, 11),
@ -299,4 +304,19 @@ u16 const* const regtable_original[0x401] =
PRAW(0x7F0), PRAW(0x7F2), PRAW(0x7F4), PRAW(0x7F6),
PRAW(0x7F8), PRAW(0x7FA), PRAW(0x7FC), PRAW(0x7FE),
nullptr};
nullptr}};
std::array<u16*, 0x401> table = orig_table;
for (uint mem = 0; mem < 0x800; mem++)
{
u16* ptr = table[mem >> 1];
if (!ptr)
{
table[mem >> 1] = &(spu2Ru16(mem));
}
}
return table;
}
const std::array<u16*, 0x401> regtable = ComputeRegTable();

View File

@ -15,9 +15,14 @@
#pragma once
#include "Mixer.h"
#include "SndOut.h"
#include "Global.h"
#include "SPU2/Mixer.h"
#include "SPU2/SndOut.h"
#include "SPU2/Global.h"
// --------------------------------------------------------------------------------------
// SPU2 Register Table LUT
// --------------------------------------------------------------------------------------
extern const std::array<u16*, 0x401> regtable;
// --------------------------------------------------------------------------------------
// SPU2 Memory Indexers
@ -560,15 +565,14 @@ extern u16 InputPos;
// SPU Mixing Cycles ("Ticks mixed" counter)
extern u32 Cycles;
extern s16* spu2regs;
extern s16* _spu2mem;
extern s16 spu2regs[0x010000 / sizeof(s16)];
extern s16 _spu2mem[0x200000 / sizeof(s16)];
extern int PlayMode;
extern void SetIrqCall(int core);
extern void SetIrqCallDMA(int core);
extern void StartVoices(int core, u32 value);
extern void StopVoices(int core, u32 value);
extern void InitADSR();
extern void CalculateADSR(V_Voice& vc);
extern void UpdateSpdifMode();
@ -584,6 +588,11 @@ namespace SPU2Savestate
// --------------------------------------------------------------------------------------
// ADPCM Decoder Cache
// --------------------------------------------------------------------------------------
// the cache data size is determined by taking the number of adpcm blocks
// (2MB / 16) and multiplying it by the decoded block size (28 samples).
// Thus: pcm_cache_data = 7,340,032 bytes (ouch!)
// Expanded: 16 bytes expands to 56 bytes [3.5:1 ratio]
// Resulting in 2MB * 3.5.
// The SPU2 has a dynamic memory range which is used for several internal operations, such as
// registers, CORE 1/2 mixing, AutoDMAs, and some other fancy stuff. We exclude this range
@ -607,4 +616,4 @@ struct PcmCacheEntry
s32 Prev2;
};
extern PcmCacheEntry* pcm_cache_data;
extern PcmCacheEntry pcm_cache_data[pcm_BlockCount];

View File

@ -178,16 +178,3 @@ Core attributes (SD_C)
#define VOICE_ADDR_LSAX 0x4 // Loop point address
#define VOICE_ADDR_NAX 0x8 // Waveform data that should be read next
// --------------------------------------------------------------------------------------
// SPU2 Register Table LUT
// --------------------------------------------------------------------------------------
#define U16P(x) ((u16*)&(x))
// Returns the hiword of a 32 bit integer.
#define U16P_HI(x) (((u16*)&(x)) + 1)
extern u16* regtable[0x401];
extern u16 const* const regtable_original[0x401];

View File

@ -177,44 +177,6 @@ void SPU2::SetDeviceSampleRateMultiplier(double multiplier)
UpdateSampleRate();
}
void SPU2::Initialize()
{
pxAssert(regtable[0x400] == nullptr);
spu2regs = (s16*)malloc(0x010000);
_spu2mem = (s16*)malloc(0x200000);
// adpcm decoder cache:
// the cache data size is determined by taking the number of adpcm blocks
// (2MB / 16) and multiplying it by the decoded block size (28 samples).
// Thus: pcm_cache_data = 7,340,032 bytes (ouch!)
// Expanded: 16 bytes expands to 56 bytes [3.5:1 ratio]
// Resulting in 2MB * 3.5.
pcm_cache_data = (PcmCacheEntry*)calloc(pcm_BlockCount, sizeof(PcmCacheEntry));
if (!spu2regs || !_spu2mem || !pcm_cache_data)
{
// If these memory allocations fail, we have much bigger problems.
pxFailRel("Failed to allocate SPU2 memory");
}
// Patch up a copy of regtable that directly maps "nullptrs" to SPU2 memory.
memcpy(regtable, regtable_original, sizeof(regtable));
for (uint mem = 0; mem < 0x800; mem++)
{
u16* ptr = regtable[mem >> 1];
if (!ptr)
{
regtable[mem >> 1] = &(spu2Ru16(mem));
}
}
InitADSR();
}
bool SPU2::Open()
{
#ifdef PCSX2_DEVBUILD
@ -257,13 +219,6 @@ void SPU2::Close()
#endif
}
void SPU2::Shutdown()
{
safe_free(spu2regs);
safe_free(_spu2mem);
safe_free(pcm_cache_data);
}
bool SPU2::IsRunningPSXMode()
{
return s_psxmode;

View File

@ -23,10 +23,6 @@ struct Pcsx2Config;
namespace SPU2
{
/// Initialization/cleanup, call at process startup/shutdown.
void Initialize();
void Shutdown();
/// Open/close, call at VM startup/shutdown.
bool Open();
void Close();

View File

@ -54,12 +54,8 @@ s32 SPU2Savestate::FreezeIt(DataBlock& spud)
spud.spu2id = SAVE_ID;
spud.version = SAVE_VERSION;
pxAssertMsg(spu2regs && _spu2mem, "Looks like PCSX2 is trying to savestate while components are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted.");
if (spu2regs != nullptr)
memcpy(spud.unkregs, spu2regs, sizeof(spud.unkregs));
if (_spu2mem != nullptr)
memcpy(spud.mem, _spu2mem, sizeof(spud.mem));
memcpy(spud.unkregs, spu2regs, sizeof(spud.unkregs));
memcpy(spud.mem, _spu2mem, sizeof(spud.mem));
memcpy(spud.Cores, Cores, sizeof(Cores));
memcpy(&spud.Spdif, &Spdif, sizeof(Spdif));
@ -127,13 +123,8 @@ s32 SPU2Savestate::ThawIt(DataBlock& spud)
{
SndBuffer::ClearContents();
pxAssertMsg(spu2regs && _spu2mem, "Looks like PCSX2 is trying to loadstate while components are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted.");
// base stuff
if (spu2regs)
memcpy(spu2regs, spud.unkregs, sizeof(spud.unkregs));
if (_spu2mem)
memcpy(_spu2mem, spud.mem, sizeof(spud.mem));
memcpy(spu2regs, spud.unkregs, sizeof(spud.unkregs));
memcpy(_spu2mem, spud.mem, sizeof(spud.mem));
memcpy(Cores, spud.Cores, sizeof(Cores));
memcpy(&Spdif, &spud.Spdif, sizeof(Spdif));

View File

@ -21,17 +21,17 @@
#include "PrecompiledHeader.h"
#include "Global.h"
#include "Dma.h"
#include "IopDma.h"
#include "IopCounters.h"
#include "R3000A.h"
#include "IopDma.h"
#include "IopHw.h"
#include "R3000A.h"
#include "SPU2/Dma.h"
#include "SPU2/Global.h"
#include "SPU2/spu2.h"
#include "spu2.h" // needed until I figure out a nice solution for irqcallback dependencies.
s16* spu2regs = nullptr;
s16* _spu2mem = nullptr;
s16 spu2regs[0x010000 / sizeof(s16)];
s16 _spu2mem[0x200000 / sizeof(s16)];
V_CoreDebug DebugCores[2];
V_Core Cores[2];

View File

@ -263,7 +263,6 @@ bool VMManager::Internal::InitializeGlobals()
SysLogMachineCaps();
GSinit();
SPU2::Initialize();
USBinit();
return true;
@ -272,7 +271,6 @@ bool VMManager::Internal::InitializeGlobals()
void VMManager::Internal::ReleaseGlobals()
{
USBshutdown();
SPU2::Shutdown();
GSshutdown();
#ifdef _WIN32