mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-22 22:05:38 +00:00
Hotkeys: Fix toggle CPU PGXP with Interpreter
This commit is contained in:
parent
591a2228d6
commit
e835f118b7
|
@ -40,29 +40,21 @@ enum : u32
|
||||||
|
|
||||||
union psx_value
|
union psx_value
|
||||||
{
|
{
|
||||||
struct
|
u32 d;
|
||||||
{
|
s32 sd;
|
||||||
u8 l, h, h2, h3;
|
|
||||||
} b;
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u16 l, h;
|
u16 l, h;
|
||||||
} w;
|
} w;
|
||||||
struct
|
struct
|
||||||
{
|
|
||||||
s8 l, h, h2, h3;
|
|
||||||
} sb;
|
|
||||||
struct
|
|
||||||
{
|
{
|
||||||
s16 l, h;
|
s16 l, h;
|
||||||
} sw;
|
} sw;
|
||||||
u32 d;
|
|
||||||
s32 sd;
|
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
static void PGXP_CacheVertex(s16 sx, s16 sy, const PGXP_value& vertex);
|
static void CacheVertex(s16 sx, s16 sy, const PGXP_value& vertex);
|
||||||
static PGXP_value* PGXP_GetCachedVertex(short sx, short sy);
|
static PGXP_value* GetCachedVertex(short sx, short sy);
|
||||||
|
|
||||||
static float TruncateVertexPosition(float p);
|
static float TruncateVertexPosition(float p);
|
||||||
static bool IsWithinTolerance(float precise_x, float precise_y, int int_x, int int_y);
|
static bool IsWithinTolerance(float precise_x, float precise_y, int int_x, int int_y);
|
||||||
|
@ -90,8 +82,8 @@ static void WriteMem16(const PGXP_value* src, u32 addr);
|
||||||
static const PGXP_value PGXP_value_invalid = {0.f, 0.f, 0.f, {0}, 0};
|
static const PGXP_value PGXP_value_invalid = {0.f, 0.f, 0.f, {0}, 0};
|
||||||
static const PGXP_value PGXP_value_zero = {0.f, 0.f, 0.f, {VALID_ALL}, 0};
|
static const PGXP_value PGXP_value_zero = {0.f, 0.f, 0.f, {VALID_ALL}, 0};
|
||||||
|
|
||||||
static PGXP_value* Mem = nullptr;
|
static PGXP_value* s_mem = nullptr;
|
||||||
static PGXP_value* vertexCache = nullptr;
|
static PGXP_value* s_vertex_cache = nullptr;
|
||||||
} // namespace CPU::PGXP
|
} // namespace CPU::PGXP
|
||||||
|
|
||||||
void CPU::PGXP::Initialize()
|
void CPU::PGXP::Initialize()
|
||||||
|
@ -101,25 +93,25 @@ void CPU::PGXP::Initialize()
|
||||||
|
|
||||||
std::memset(g_state.pgxp_gte, 0, sizeof(g_state.pgxp_gte));
|
std::memset(g_state.pgxp_gte, 0, sizeof(g_state.pgxp_gte));
|
||||||
|
|
||||||
if (!Mem)
|
if (!s_mem)
|
||||||
{
|
{
|
||||||
Mem = static_cast<PGXP_value*>(std::calloc(PGXP_MEM_SIZE, sizeof(PGXP_value)));
|
s_mem = static_cast<PGXP_value*>(std::calloc(PGXP_MEM_SIZE, sizeof(PGXP_value)));
|
||||||
if (!Mem)
|
if (!s_mem)
|
||||||
Panic("Failed to allocate PGXP memory");
|
Panic("Failed to allocate PGXP memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_settings.gpu_pgxp_vertex_cache && !vertexCache)
|
if (g_settings.gpu_pgxp_vertex_cache && !s_vertex_cache)
|
||||||
{
|
{
|
||||||
vertexCache = static_cast<PGXP_value*>(std::calloc(VERTEX_CACHE_SIZE, sizeof(PGXP_value)));
|
s_vertex_cache = static_cast<PGXP_value*>(std::calloc(VERTEX_CACHE_SIZE, sizeof(PGXP_value)));
|
||||||
if (!vertexCache)
|
if (!s_vertex_cache)
|
||||||
{
|
{
|
||||||
Log_ErrorPrint("Failed to allocate memory for vertex cache, disabling.");
|
Log_ErrorPrint("Failed to allocate memory for vertex cache, disabling.");
|
||||||
g_settings.gpu_pgxp_vertex_cache = false;
|
g_settings.gpu_pgxp_vertex_cache = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vertexCache)
|
if (s_vertex_cache)
|
||||||
std::memset(vertexCache, 0, sizeof(PGXP_value) * VERTEX_CACHE_SIZE);
|
std::memset(s_vertex_cache, 0, sizeof(PGXP_value) * VERTEX_CACHE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::PGXP::Reset()
|
void CPU::PGXP::Reset()
|
||||||
|
@ -128,24 +120,24 @@ void CPU::PGXP::Reset()
|
||||||
std::memset(g_state.pgxp_cop0, 0, sizeof(g_state.pgxp_cop0));
|
std::memset(g_state.pgxp_cop0, 0, sizeof(g_state.pgxp_cop0));
|
||||||
std::memset(g_state.pgxp_gte, 0, sizeof(g_state.pgxp_gte));
|
std::memset(g_state.pgxp_gte, 0, sizeof(g_state.pgxp_gte));
|
||||||
|
|
||||||
if (Mem)
|
if (s_mem)
|
||||||
std::memset(Mem, 0, sizeof(PGXP_value) * PGXP_MEM_SIZE);
|
std::memset(s_mem, 0, sizeof(PGXP_value) * PGXP_MEM_SIZE);
|
||||||
|
|
||||||
if (vertexCache)
|
if (s_vertex_cache)
|
||||||
std::memset(vertexCache, 0, sizeof(PGXP_value) * VERTEX_CACHE_SIZE);
|
std::memset(s_vertex_cache, 0, sizeof(PGXP_value) * VERTEX_CACHE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::PGXP::Shutdown()
|
void CPU::PGXP::Shutdown()
|
||||||
{
|
{
|
||||||
if (vertexCache)
|
if (s_vertex_cache)
|
||||||
{
|
{
|
||||||
std::free(vertexCache);
|
std::free(s_vertex_cache);
|
||||||
vertexCache = nullptr;
|
s_vertex_cache = nullptr;
|
||||||
}
|
}
|
||||||
if (Mem)
|
if (s_mem)
|
||||||
{
|
{
|
||||||
std::free(Mem);
|
std::free(s_mem);
|
||||||
Mem = nullptr;
|
s_mem = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memset(g_state.pgxp_gte, 0, sizeof(g_state.pgxp_gte));
|
std::memset(g_state.pgxp_gte, 0, sizeof(g_state.pgxp_gte));
|
||||||
|
@ -178,25 +170,23 @@ void CPU::PGXP::Shutdown()
|
||||||
|
|
||||||
ALWAYS_INLINE_RELEASE void CPU::PGXP::MakeValid(PGXP_value* pV, u32 psxV)
|
ALWAYS_INLINE_RELEASE void CPU::PGXP::MakeValid(PGXP_value* pV, u32 psxV)
|
||||||
{
|
{
|
||||||
if ((pV->flags & VALID_01) != VALID_01)
|
if ((pV->flags & VALID_01) == VALID_01)
|
||||||
{
|
return;
|
||||||
pV->x = static_cast<float>(static_cast<s16>(Truncate16(psxV)));
|
|
||||||
pV->y = static_cast<float>(static_cast<s16>(Truncate16(psxV >> 16)));
|
pV->x = static_cast<float>(static_cast<s16>(Truncate16(psxV)));
|
||||||
pV->z = 0.f;
|
pV->y = static_cast<float>(static_cast<s16>(Truncate16(psxV >> 16)));
|
||||||
pV->flags = VALID_01;
|
pV->z = 0.0f;
|
||||||
pV->value = psxV;
|
pV->flags = VALID_01;
|
||||||
}
|
pV->value = psxV;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE_RELEASE void CPU::PGXP::Validate(PGXP_value* pV, u32 psxV)
|
ALWAYS_INLINE_RELEASE void CPU::PGXP::Validate(PGXP_value* pV, u32 psxV)
|
||||||
{
|
{
|
||||||
// assume pV is not NULL
|
|
||||||
pV->flags &= (pV->value == psxV) ? ALL : INV_VALID_ALL;
|
pV->flags &= (pV->value == psxV) ? ALL : INV_VALID_ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE_RELEASE void CPU::PGXP::MaskValidate(PGXP_value* pV, u32 psxV, u32 mask, u32 validMask)
|
ALWAYS_INLINE_RELEASE void CPU::PGXP::MaskValidate(PGXP_value* pV, u32 psxV, u32 mask, u32 validMask)
|
||||||
{
|
{
|
||||||
// assume pV is not NULL
|
|
||||||
pV->flags &= ((pV->value & mask) == (psxV & mask)) ? ALL : (ALL ^ (validMask));
|
pV->flags &= ((pV->value & mask) == (psxV & mask)) ? ALL : (ALL ^ (validMask));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,11 +210,11 @@ ALWAYS_INLINE_RELEASE double CPU::PGXP::f16Overflow(double in)
|
||||||
ALWAYS_INLINE_RELEASE CPU::PGXP_value* CPU::PGXP::GetPtr(u32 addr)
|
ALWAYS_INLINE_RELEASE CPU::PGXP_value* CPU::PGXP::GetPtr(u32 addr)
|
||||||
{
|
{
|
||||||
if ((addr & SCRATCHPAD_ADDR_MASK) == SCRATCHPAD_ADDR)
|
if ((addr & SCRATCHPAD_ADDR_MASK) == SCRATCHPAD_ADDR)
|
||||||
return &Mem[PGXP_MEM_SCRATCH_OFFSET + ((addr & SCRATCHPAD_OFFSET_MASK) >> 2)];
|
return &s_mem[PGXP_MEM_SCRATCH_OFFSET + ((addr & SCRATCHPAD_OFFSET_MASK) >> 2)];
|
||||||
|
|
||||||
const u32 paddr = (addr & PHYSICAL_MEMORY_ADDRESS_MASK);
|
const u32 paddr = (addr & PHYSICAL_MEMORY_ADDRESS_MASK);
|
||||||
if (paddr < Bus::RAM_MIRROR_END)
|
if (paddr < Bus::RAM_MIRROR_END)
|
||||||
return &Mem[(paddr & Bus::g_ram_mask) >> 2];
|
return &s_mem[(paddr & Bus::g_ram_mask) >> 2];
|
||||||
else
|
else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -232,67 +222,67 @@ ALWAYS_INLINE_RELEASE CPU::PGXP_value* CPU::PGXP::GetPtr(u32 addr)
|
||||||
ALWAYS_INLINE_RELEASE void CPU::PGXP::ValidateAndCopyMem(PGXP_value* dest, u32 addr, u32 value)
|
ALWAYS_INLINE_RELEASE void CPU::PGXP::ValidateAndCopyMem(PGXP_value* dest, u32 addr, u32 value)
|
||||||
{
|
{
|
||||||
PGXP_value* pMem = GetPtr(addr);
|
PGXP_value* pMem = GetPtr(addr);
|
||||||
if (pMem)
|
if (!pMem)
|
||||||
{
|
{
|
||||||
Validate(pMem, value);
|
*dest = PGXP_value_invalid;
|
||||||
*dest = *pMem;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*dest = PGXP_value_invalid;
|
Validate(pMem, value);
|
||||||
|
*dest = *pMem;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE_RELEASE void CPU::PGXP::ValidateAndCopyMem16(PGXP_value* dest, u32 addr, u32 value, bool sign)
|
ALWAYS_INLINE_RELEASE void CPU::PGXP::ValidateAndCopyMem16(PGXP_value* dest, u32 addr, u32 value, bool sign)
|
||||||
{
|
{
|
||||||
u32 validMask = 0;
|
|
||||||
psx_value val, mask;
|
|
||||||
PGXP_value* pMem = GetPtr(addr);
|
PGXP_value* pMem = GetPtr(addr);
|
||||||
if (pMem)
|
if (!pMem)
|
||||||
{
|
{
|
||||||
mask.d = val.d = 0;
|
*dest = PGXP_value_invalid;
|
||||||
// determine if high or low word
|
|
||||||
if ((addr % 4) == 2)
|
|
||||||
{
|
|
||||||
val.w.h = static_cast<u16>(value);
|
|
||||||
mask.w.h = 0xFFFF;
|
|
||||||
validMask = VALID_1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val.w.l = static_cast<u16>(value);
|
|
||||||
mask.w.l = 0xFFFF;
|
|
||||||
validMask = VALID_0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate and copy whole value
|
|
||||||
MaskValidate(pMem, val.d, mask.d, validMask);
|
|
||||||
*dest = *pMem;
|
|
||||||
|
|
||||||
// if high word then shift
|
|
||||||
if ((addr % 4) == 2)
|
|
||||||
{
|
|
||||||
dest->x = dest->y;
|
|
||||||
dest->compFlags[0] = dest->compFlags[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
// truncate value
|
|
||||||
if (dest->compFlags[0] == VALID)
|
|
||||||
{
|
|
||||||
// only set y as valid if x is also valid.. don't want to make fake values
|
|
||||||
dest->y = (dest->x < 0) ? -1.f * sign : 0.f; // 0.f;
|
|
||||||
dest->compFlags[1] = VALID; // iCB: High word is valid, just 0
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dest->y = 0.0f;
|
|
||||||
dest->compFlags[1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dest->value = value;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*dest = PGXP_value_invalid;
|
psx_value val{0}, mask{0};
|
||||||
|
u32 valid_mask = 0;
|
||||||
|
|
||||||
|
// determine if high or low word
|
||||||
|
const bool hiword = ((addr & 2) != 0);
|
||||||
|
if (hiword)
|
||||||
|
{
|
||||||
|
val.w.h = static_cast<u16>(value);
|
||||||
|
mask.w.h = 0xFFFF;
|
||||||
|
valid_mask = VALID_1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val.w.l = static_cast<u16>(value);
|
||||||
|
mask.w.l = 0xFFFF;
|
||||||
|
valid_mask = VALID_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate and copy whole value
|
||||||
|
MaskValidate(pMem, val.d, mask.d, valid_mask);
|
||||||
|
*dest = *pMem;
|
||||||
|
|
||||||
|
// if high word then shift
|
||||||
|
if (hiword)
|
||||||
|
{
|
||||||
|
dest->x = dest->y;
|
||||||
|
dest->compFlags[0] = dest->compFlags[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// only set y as valid if x is also valid.. don't want to make fake values
|
||||||
|
if (dest->compFlags[0] == VALID)
|
||||||
|
{
|
||||||
|
dest->y = (dest->x < 0) ? -1.f * sign : 0.f;
|
||||||
|
dest->compFlags[1] = VALID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dest->y = 0.0f;
|
||||||
|
dest->compFlags[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest->value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE_RELEASE void CPU::PGXP::WriteMem(const PGXP_value* value, u32 addr)
|
ALWAYS_INLINE_RELEASE void CPU::PGXP::WriteMem(const PGXP_value* value, u32 addr)
|
||||||
|
@ -306,33 +296,29 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::WriteMem(const PGXP_value* value, u32 addr
|
||||||
ALWAYS_INLINE_RELEASE void CPU::PGXP::WriteMem16(const PGXP_value* src, u32 addr)
|
ALWAYS_INLINE_RELEASE void CPU::PGXP::WriteMem16(const PGXP_value* src, u32 addr)
|
||||||
{
|
{
|
||||||
PGXP_value* dest = GetPtr(addr);
|
PGXP_value* dest = GetPtr(addr);
|
||||||
psx_value* pVal = nullptr;
|
if (!dest)
|
||||||
|
return;
|
||||||
|
|
||||||
if (dest)
|
// determine if high or low word
|
||||||
|
const bool hiword = ((addr & 2) != 0);
|
||||||
|
if (hiword)
|
||||||
{
|
{
|
||||||
pVal = (psx_value*)&dest->value;
|
dest->y = src->x;
|
||||||
// determine if high or low word
|
dest->compFlags[1] = src->compFlags[0];
|
||||||
if ((addr % 4) == 2)
|
dest->value = (dest->value & UINT32_C(0x0000FFFF)) | (src->value << 16);
|
||||||
{
|
}
|
||||||
dest->y = src->x;
|
else
|
||||||
dest->compFlags[1] = src->compFlags[0];
|
{
|
||||||
pVal->w.h = (u16)src->value;
|
dest->x = src->x;
|
||||||
}
|
dest->compFlags[0] = src->compFlags[0];
|
||||||
else
|
dest->value = (dest->value & UINT32_C(0xFFFF0000)) | (src->value & UINT32_C(0x0000FFFF));
|
||||||
{
|
}
|
||||||
dest->x = src->x;
|
|
||||||
dest->compFlags[0] = src->compFlags[0];
|
|
||||||
pVal->w.l = (u16)src->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// overwrite z/w if valid
|
// overwrite z/w if valid
|
||||||
if (src->compFlags[2] == VALID)
|
if (src->compFlags[2] == VALID)
|
||||||
{
|
{
|
||||||
dest->z = src->z;
|
dest->z = src->z;
|
||||||
dest->compFlags[2] = src->compFlags[2];
|
dest->compFlags[2] = src->compFlags[2];
|
||||||
}
|
|
||||||
|
|
||||||
// dest->valid = dest->valid && src->valid;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +335,7 @@ void CPU::PGXP::GTE_PushSXYZ2f(float x, float y, float z, u32 v)
|
||||||
SXY2.flags = VALID_ALL;
|
SXY2.flags = VALID_ALL;
|
||||||
|
|
||||||
if (g_settings.gpu_pgxp_vertex_cache)
|
if (g_settings.gpu_pgxp_vertex_cache)
|
||||||
PGXP_CacheVertex(static_cast<s16>(Truncate16(v)), static_cast<s16>(Truncate16(v >> 16)), SXY2);
|
CacheVertex(static_cast<s16>(Truncate16(v)), static_cast<s16>(Truncate16(v >> 16)), SXY2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VX(n) (psxRegs.CP2D.p[n << 1].sw.l)
|
#define VX(n) (psxRegs.CP2D.p[n << 1].sw.l)
|
||||||
|
@ -450,21 +436,21 @@ void CPU::PGXP::CPU_SWC2(u32 instr, u32 addr, u32 rtVal)
|
||||||
WriteMem(&g_state.pgxp_gte[rt(instr)], addr);
|
WriteMem(&g_state.pgxp_gte[rt(instr)], addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE_RELEASE void CPU::PGXP::PGXP_CacheVertex(s16 sx, s16 sy, const PGXP_value& vertex)
|
ALWAYS_INLINE_RELEASE void CPU::PGXP::CacheVertex(s16 sx, s16 sy, const PGXP_value& vertex)
|
||||||
{
|
{
|
||||||
if (sx >= -0x800 && sx <= 0x7ff && sy >= -0x800 && sy <= 0x7ff)
|
if (sx >= -0x800 && sx <= 0x7ff && sy >= -0x800 && sy <= 0x7ff)
|
||||||
{
|
{
|
||||||
// Write vertex into cache
|
// Write vertex into cache
|
||||||
vertexCache[(sy + 0x800) * VERTEX_CACHE_WIDTH + (sx + 0x800)] = vertex;
|
s_vertex_cache[(sy + 0x800) * VERTEX_CACHE_WIDTH + (sx + 0x800)] = vertex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE_RELEASE CPU::PGXP_value* CPU::PGXP::PGXP_GetCachedVertex(short sx, short sy)
|
ALWAYS_INLINE_RELEASE CPU::PGXP_value* CPU::PGXP::GetCachedVertex(short sx, short sy)
|
||||||
{
|
{
|
||||||
if (sx >= -0x800 && sx <= 0x7ff && sy >= -0x800 && sy <= 0x7ff)
|
if (sx >= -0x800 && sx <= 0x7ff && sy >= -0x800 && sy <= 0x7ff)
|
||||||
{
|
{
|
||||||
// Return pointer to cache entry
|
// Return pointer to cache entry
|
||||||
return &vertexCache[(sy + 0x800) * VERTEX_CACHE_WIDTH + (sx + 0x800)];
|
return &s_vertex_cache[(sy + 0x800) * VERTEX_CACHE_WIDTH + (sx + 0x800)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -511,7 +497,7 @@ bool CPU::PGXP::GetPreciseVertex(u32 addr, u32 value, int x, int y, int xOffs, i
|
||||||
const short psx_y = (short)(value >> 16);
|
const short psx_y = (short)(value >> 16);
|
||||||
|
|
||||||
// Look in cache for valid vertex
|
// Look in cache for valid vertex
|
||||||
vert = PGXP_GetCachedVertex(psx_x, psx_y);
|
vert = GetCachedVertex(psx_x, psx_y);
|
||||||
if (vert && (vert->flags & VALID_01) == VALID_01)
|
if (vert && (vert->flags & VALID_01) == VALID_01)
|
||||||
{
|
{
|
||||||
*out_x = TruncateVertexPosition(vert->x) + static_cast<float>(xOffs);
|
*out_x = TruncateVertexPosition(vert->x) + static_cast<float>(xOffs);
|
||||||
|
|
|
@ -438,6 +438,9 @@ DEFINE_HOTKEY("TogglePGXPCPU", TRANSLATE_NOOP("Hotkeys", "Graphics"), TRANSLATE_
|
||||||
|
|
||||||
// we need to recompile all blocks if pgxp is toggled on/off
|
// we need to recompile all blocks if pgxp is toggled on/off
|
||||||
CPU::CodeCache::Reset();
|
CPU::CodeCache::Reset();
|
||||||
|
|
||||||
|
// need to swap interpreters
|
||||||
|
System::InterruptExecution();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue