mirror of https://github.com/PCSX2/pcsx2.git
SPU2: Get rid of dynamic allocations
This commit is contained in:
parent
191ea50663
commit
6426f4432e
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue