diff options
| author | iCatButler <i.am.catbutler@gmail.com> | 2016-04-27 12:18:13 +0100 |
|---|---|---|
| committer | iCatButler <i.am.catbutler@gmail.com> | 2016-04-27 12:18:13 +0100 |
| commit | 153c8eb4997d21d3b2965cf38d4348f05c29860f (patch) | |
| tree | 994a8995a888c47eacb6d650f8c28c0c631d3c50 /libpcsxcore | |
| parent | 580df75296286b65812afdac64d82054279fb235 (diff) | |
| download | pcsxr-153c8eb4997d21d3b2965cf38d4348f05c29860f.tar.gz | |
Perspective correct texturing
- replace calls to glOrtho with new matrix (z value becomes w)
- store w value for each vertex
- if any vertex does not have a w value set whole polygon to 1.0
- Reset vertex between draw calls to prevent stale w values persisting
- validate PGXP values using stored copy of original (allow greater variance)
- properly convert addresses before passing to plugin
- rework memory to use a single pool with offsets
- Implement floating point RTPS/RTPT transform, currently disabled.
Diffstat (limited to 'libpcsxcore')
| -rwxr-xr-x | libpcsxcore/gpu.c | 2 | ||||
| -rwxr-xr-x | libpcsxcore/gte.c | 8 | ||||
| -rw-r--r-- | libpcsxcore/pgxp_gte.c | 281 | ||||
| -rw-r--r-- | libpcsxcore/pgxp_gte.h | 8 |
4 files changed, 209 insertions, 90 deletions
diff --git a/libpcsxcore/gpu.c b/libpcsxcore/gpu.c index 61a7b3dc..4ab01166 100755 --- a/libpcsxcore/gpu.c +++ b/libpcsxcore/gpu.c @@ -143,7 +143,7 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU #endif break; } - GPU_pgxpMemory(madr, PGXP_GetMem()); + GPU_pgxpMemory(PGXP_ConvertAddress(madr), PGXP_GetMem()); GPU_writeDataMem(ptr, size); #if 0 diff --git a/libpcsxcore/gte.c b/libpcsxcore/gte.c index 04a3968c..2d02032a 100755 --- a/libpcsxcore/gte.c +++ b/libpcsxcore/gte.c @@ -499,7 +499,9 @@ int docop2(int op) { PGXP_pushSXYZ2s(Lm_G1_ia((s64)OFX + (s64)(IR1 * h_over_sz3) * (Config.Widescreen ? 0.75 : 1)), Lm_G2_ia((s64)OFY + (s64)(IR2 * h_over_sz3)), - SZ3); + SZ3, SXY2); + + //PGXP_RTPS(0, SXY2); MAC0 = F((s64) DQB + ((s64) DQA * h_over_sz3)); IR0 = Lm_H(m_mac0, 1); @@ -889,7 +891,9 @@ int docop2(int op) { PGXP_pushSXYZ2s(Lm_G1_ia((s64)OFX + (s64)(IR1 * h_over_sz3) * (Config.Widescreen ? 0.75 : 1)), Lm_G2_ia((s64)OFY + (s64)(IR2 * h_over_sz3)), - SZ3); + SZ3, SXY2); + + //PGXP_RTPS(v, SXY2); } MAC0 = F((s64) DQB + ((s64) DQA * h_over_sz3)); diff --git a/libpcsxcore/pgxp_gte.c b/libpcsxcore/pgxp_gte.c index de3797d6..d5341dc6 100644 --- a/libpcsxcore/pgxp_gte.c +++ b/libpcsxcore/pgxp_gte.c @@ -27,6 +27,7 @@ #include "pgxp_gte.h"
#include "psxmem.h"
+#include "r3000a.h"
typedef struct
{
@@ -35,6 +36,7 @@ typedef struct float z;
unsigned int valid;
unsigned int count;
+ unsigned int value;
} precise_value;
typedef union
@@ -52,8 +54,14 @@ typedef union precise_value GTE_reg[32];
precise_value CPU_reg[32];
-precise_value Mem[2048 * 1024 / 4]; // mirror 2MB in 32-bit words
-precise_value Scratch[2048 * 1024 / 4]; // mirror 2MB in 32-bit words
+precise_value Mem[3 * 2048 * 1024 / 4]; // mirror 2MB in 32-bit words * 3
+const u32 UserMemOffset = 0;
+const u32 ScratchOffset = 2048 * 1024 / 4;
+const u32 RegisterOffset = 2 * 2048 * 1024 / 4;
+const u32 InvalidAddress = 3 * 2048 * 1024 / 4;
+
+//precise_value Scratch[2048 * 1024 / 4]; // mirror 2MB in 32-bit words
+//precise_value Registers[2048 * 1024 / 4]; // mirror 2MB in 32-bit words
void PGXP_Init()
{
@@ -65,94 +73,112 @@ char* PGXP_GetMem() return (char*)(Mem);
}
-#define VRAM 0
-#define SCRATCH 1
+/* Playstation Memory Map (from Playstation doc by Joshua Walker)
+0x0000_0000-0x0000_ffff Kernel (64K)
+0x0001_0000-0x001f_ffff User Memory (1.9 Meg)
-precise_value* ReadMem(u32 addr)
-{
- u32 memType;
- uint32_t paddr = addr;
- int* ip = NULL;
+0x1f00_0000-0x1f00_ffff Parallel Port (64K)
- switch (paddr >> 24)
- {
- case 0x80:
- case 0xa0:
- case 0x00:
- memType = VRAM;
- break;
- default:
- if ((paddr >> 20) == 0x1f8)
- {
- memType = SCRATCH;
- break;
- }
- // if (value.valid) //FAILED @ 0x807FFEE8
- // *ip = 5;
- return NULL;
- }
-
-#ifdef GTE_LOG
- //GTE_LOG("PGXP_Read %x [%x] |", addr, paddr);
-#endif
- if (memType == VRAM)
- {
- // RAM furher mirrored over 8MB
- //paddr = (paddr & 0x1FFFFF) >> 2;
- paddr = ((paddr & 0x7FFFFF) % 0x200000) >> 2;
- return &Mem[paddr];
- }
- else if (memType == SCRATCH)
+0x1f80_0000-0x1f80_03ff Scratch Pad (1024 bytes)
+
+0x1f80_1000-0x1f80_2fff Hardware Registers (8K)
+
+0x1fc0_0000-0x1fc7_ffff BIOS (512K)
+
+0x8000_0000-0x801f_ffff Kernel and User Memory Mirror (2 Meg) Cached
+0x9fc0_0000-0x9fc7_ffff BIOS Mirror (512K) Cached
+
+0xa000_0000-0xa01f_ffff Kernel and User Memory Mirror (2 Meg) Uncached
+0xbfc0_0000-0xbfc7_ffff BIOS Mirror (512K) Uncached
+*/
+void ValidateAddress(u32 addr)
+{
+ int* pi = NULL;
+
+ if ((addr >= 0x00000000) && (addr <= 0x007fffff)) {} // Kernel + User Memory x 8
+ else if ((addr >= 0x1f000000) && (addr <= 0x1f00ffff)) {} // Parallel Port
+ else if ((addr >= 0x1f800000) && (addr <= 0x1f8003ff)) {} // Scratch Pad
+ else if ((addr >= 0x1f801000) && (addr <= 0x1f802fff)) {} // Hardware Registers
+ else if ((addr >= 0x1fc00000) && (addr <= 0x1fc7ffff)) {} // Bios
+ else if ((addr >= 0x80000000) && (addr <= 0x807fffff)) {} // Kernel + User Memory x 8 Cached mirror
+ else if ((addr >= 0x9fc00000) && (addr <= 0x9fc7ffff)) {} // Bios Cached Mirror
+ else if ((addr >= 0xa0000000) && (addr <= 0xa07fffff)) {} // Kernel + User Memory x 8 Uncached mirror
+ else if ((addr >= 0xbfc00000) && (addr <= 0xbfc7ffff)) {} // Bios Uncached Mirror
+ else if (addr == 0xfffe0130) {} // Used for cache flushing
+ else
{
- paddr = (paddr & 0x1FFFFF) >> 2;// (paddr & 0x3FFF) >> 2;
- return &Scratch[paddr];
+ // *pi = 5;
}
- return NULL;
}
-void WriteMem(precise_value value, u32 addr)
+u32 PGXP_ConvertAddress(u32 addr)
{
- u32 memType;
- uint32_t paddr = addr;
- int* ip = NULL;
+ u32 memOffs = 0;
+ u32 paddr = addr;
+
+ ValidateAddress(addr);
switch (paddr >> 24)
{
case 0x80:
case 0xa0:
case 0x00:
- memType = VRAM;
+ // RAM further mirrored over 8MB
+ paddr = ((paddr & 0x7FFFFF) % 0x200000) >> 2;
+ paddr = UserMemOffset + paddr;
break;
default:
if ((paddr >> 20) == 0x1f8)
{
- memType = SCRATCH;
- break;
+ if (paddr >= 0x1f801000)
+ {
+ // paddr = ((paddr & 0xFFFF) - 0x1000);
+ // paddr = (paddr % 0x2000) >> 2;
+ paddr = ((paddr & 0xFFFF) - 0x1000) >> 2;
+ paddr = RegisterOffset + paddr;
+ break;
+ }
+ else
+ {
+ //paddr = ((paddr & 0xFFF) % 0x400) >> 2;
+ paddr = (paddr & 0x3FF) >> 2;
+ paddr = ScratchOffset + paddr;
+ break;
+ }
}
- else
- if (value.valid) //FAILED @ 0x807FFEE8
- *ip = 5;
- return;
+
+ paddr = InvalidAddress;
+ break;
}
#ifdef GTE_LOG
- GTE_LOG("PGXP_Write %x [%x] |", addr, paddr);
+ //GTE_LOG("PGXP_Read %x [%x] |", addr, paddr);
#endif
- // Store to RAM
- if (memType == VRAM)
- {
- // RAM furher mirrored over 8MB
- //paddr = (paddr & 0x1FFFFF) >> 2;
- paddr = ((paddr & 0x7FFFFF) % 0x200000) >> 2;// (paddr & 0x3FFF) >> 2;
- Mem[paddr] = value;
- }
- else if (memType == SCRATCH)
- {
- paddr = (paddr & 0x1FFFFF) >> 2;// (paddr & 0x3FFF) >> 2;
- Scratch[paddr] = value;
- }
+ return paddr;
+}
+
+precise_value* GetPtr(u32 addr)
+{
+ addr = PGXP_ConvertAddress(addr);
+
+ if (addr != InvalidAddress)
+ return &Mem[addr];
+ return NULL;
+}
+
+precise_value* ReadMem(u32 addr)
+{
+ return GetPtr(addr);
+}
+
+void WriteMem(precise_value value, u32 addr)
+{
+ precise_value* pMem = GetPtr(addr);
+
+ if (pMem)
+ *pMem = value;
}
#define SX0 (GTE_reg[ 12 ].x)
@@ -186,7 +212,7 @@ precise_value PGXP_validateXY(precise_value *high, u32 low) if (!high)
return ret;
- high->valid = (high->valid && PGXP_validate(high->x, temp.x) && PGXP_validate(high->y, temp.y));
+ high->valid = (high->valid) && (high->value == low);//(high->valid && PGXP_validate(high->x, temp.x) && PGXP_validate(high->y, temp.y));
// Cheat
//if (!high->valid)
@@ -225,7 +251,7 @@ precise_value PGXP_copyXY(u32 low) return ret;
}
-void PGXP_pushSXYZ2f(float _x, float _y, float _z)
+void PGXP_pushSXYZ2f(float _x, float _y, float _z, unsigned int _v)
{
static unsigned int uCount = 0;
// push values down FIFO
@@ -235,6 +261,7 @@ void PGXP_pushSXYZ2f(float _x, float _y, float _z) SXY2.x = _x;
SXY2.y = _y;
SXY2.z = _z;
+ SXY2.value = _v;
SXY2.valid = 1;
SXY2.count = uCount++;
@@ -243,13 +270,58 @@ void PGXP_pushSXYZ2f(float _x, float _y, float _z) #endif
}
-void PGXP_pushSXYZ2s(s64 _x, s64 _y, s64 _z)
+void PGXP_pushSXYZ2s(s64 _x, s64 _y, s64 _z, u32 v)
{
float fx = (float)(_x) / (float)(1 << 16);
float fy = (float)(_y) / (float)(1 << 16);
float fz = (float)(_z);
- PGXP_pushSXYZ2f(fx, fy, fz);
+ PGXP_pushSXYZ2f(fx, fy, fz, v);
+}
+
+#define VX(n) (psxRegs.CP2D.p[ n << 1 ].sw.l)
+#define VY(n) (psxRegs.CP2D.p[ n << 1 ].sw.h)
+#define VZ(n) (psxRegs.CP2D.p[ (n << 1) + 1 ].sw.l)
+
+void PGXP_RTPS(u32 _n, u32 _v)
+{
+ // Transform
+ float TRX = (s64)psxRegs.CP2C.p[5].sd;
+ float TRY = (s64)psxRegs.CP2C.p[6].sd;
+ float TRZ = (s64)psxRegs.CP2C.p[7].sd;
+
+ // Rotation with 12-bit shift
+ float R11 = (float)psxRegs.CP2C.p[ 0 ].sw.l / (float)(1 << 12);
+ float R12 = (float)psxRegs.CP2C.p[ 0 ].sw.h / (float)(1 << 12);
+ float R13 = (float)psxRegs.CP2C.p[ 1 ].sw.l / (float)(1 << 12);
+ float R21 = (float)psxRegs.CP2C.p[ 1 ].sw.h / (float)(1 << 12);
+ float R22 = (float)psxRegs.CP2C.p[ 2 ].sw.l / (float)(1 << 12);
+ float R23 = (float)psxRegs.CP2C.p[ 2 ].sw.h / (float)(1 << 12);
+ float R31 = (float)psxRegs.CP2C.p[ 3 ].sw.l / (float)(1 << 12);
+ float R32 = (float)psxRegs.CP2C.p[ 3 ].sw.h / (float)(1 << 12);
+ float R33 = (float)psxRegs.CP2C.p[ 4 ].sw.l / (float)(1 << 12);
+
+ // Bring vertex into view space
+ float MAC1 = TRX + (R11 * VX(_n)) + (R12 * VY(_n)) + (R13 * VZ(_n));
+ float MAC2 = TRY + (R21 * VX(_n)) + (R22 * VY(_n)) + (R23 * VZ(_n));
+ float MAC3 = TRZ + (R31 * VX(_n)) + (R32 * VY(_n)) + (R33 * VZ(_n));
+
+ float SZ3 = MAC3;
+ float H = psxRegs.CP2C.p[26].sw.l;
+ float h_over_sz3 = H / SZ3;
+
+ // Offsets with 16-bit shift
+ float OFX = (float)psxRegs.CP2C.p[ 24 ].sd / (float)(1 << 16);
+ float OFY = (float)psxRegs.CP2C.p[ 25 ].sd / (float)(1 << 16);
+
+ // PSX Screen space X,Y,W components
+ float sx = OFX + (MAC1 * h_over_sz3) * (Config.Widescreen ? 0.75 : 1);
+ float sy = OFY + (MAC2 * h_over_sz3);
+ float sw = SZ3;
+
+ PGXP_pushSXYZ2f(sx , sy , sw, _v);
+
+ return;
}
int PGXP_NLCIP_valid()
@@ -261,13 +333,26 @@ int PGXP_NLCIP_valid() float PGXP_NCLIP()
{
- float nclip = ((SX0 * SY1) + (SX1 * SY2) + (SX2 * SY0) - (SX0 * SY2) - (SX1 * SY0) - (SX2 * SY1));
+// float nclip = ((SX0 * SY1) + (SX1 * SY2) + (SX2 * SY0) - (SX0 * SY2) - (SX1 * SY0) - (SX2 * SY1));
// ensure fractional values are not incorrectly rounded to 0
- if (fabs(nclip) < 1.0f)
- nclip += (nclip < 0.f ? -1 : 1);
+ //if ((fabs(nclip) < 1.0f) && (nclip != 0))
+ // nclip += (nclip < 0.f ? -1 : 1);
+
+ float AX = SX1 - SX0;
+ float AY = SY1 - SY0;
+
+ float BX = SX2 - SX0;
+ float BY = SY2 - SY0;
+
+ // normalise A and B
+ float mA = sqrt((AX*AX) + (AY*AY));
+ float mB = sqrt((BX*BX) + (BY*BY));
- return nclip;
+ // calculate AxB to get Z component of C
+ float CZ = ((AX * BY) - (AY * BX)) * (1 << 12);
+
+ return CZ;// nclip;
}
static precise_value PGXP_MFC2_int(u32 reg)
@@ -307,7 +392,7 @@ void PGXP_MFC2(u32 gpr, u32 gtr, u32 value) {
if (!gpr) return;
#ifdef GTE_LOG
- GTE_LOG("PGXP_MFC2 [%x] [%x] %x (%u %u)|", gpr, gtr, value, GTE_reg[gtr].valid, GTE_reg[gtr].count);
+ GTE_LOG("PGXP_MFC2 [%x]<-[%x] %x (%u %u)|", gpr, gtr, value, GTE_reg[gtr].valid, GTE_reg[gtr].count);
#endif
CPU_reg[gpr] = PGXP_validateXY(>E_reg[gtr], value);
@@ -317,7 +402,7 @@ void PGXP_MFC2(u32 gpr, u32 gtr, u32 value) void PGXP_MTC2(u32 gpr, u32 gtr, u32 value)
{
#ifdef GTE_LOG
- GTE_LOG("PGXP_MTC2 [%x] [%x] %x (%u %u)|", gpr, gtr, value, CPU_reg[gtr].valid, CPU_reg[gtr].count);
+ GTE_LOG("PGXP_MTC2 [%x]->[%x] %x (%u %u)|", gpr, gtr, value, CPU_reg[gpr].valid, CPU_reg[gpr].count);
#endif
PGXP_MTC2_int(PGXP_validateXY(&CPU_reg[gpr], value), gtr);
}
@@ -391,7 +476,7 @@ void PGPR_L32(u32 addr, u32 code, u32 value) #endif
}
-// store 16bit word
+// store 32bit word
void PGPR_S32(u32 addr, u32 code, u32 value)
{
u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register
@@ -429,24 +514,50 @@ void PGPR_S32(u32 addr, u32 code, u32 value) }
// invalidate register (invalid 8/16 bit read)
-void PGPR_InvalidLoad(u32 addr, u32 code)
+void PGPR_InvalidLoad(u32 addr, u32 code, u32 value)
{
u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register
+ precise_value* pD = NULL;
precise_value p;
- p.x = p.y = p.valid = p.count = 0;
+ p.x = p.y = -1337; // default values
+
+ //p.valid = 0;
+ //p.count = value;
+ pD = ReadMem(addr);
+
+ if (pD)
+ {
+ p.count = addr;
+ p = *pD;
+ }
+ else
+ {
+ p.count = value;
+ }
+
+ p.valid = 0;
// invalidate register
CPU_reg[reg] = p;
}
// invalidate memory address (invalid 8/16 bit write)
-void PGPR_InvalidStore(u32 addr, u32 code)
+void PGPR_InvalidStore(u32 addr, u32 code, u32 value)
{
u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register
+ precise_value* pD = NULL;
precise_value p;
- p.x = p.y = p.valid = p.count = 0;
+ pD = ReadMem(addr);
+
+ p.x = p.y = -2337;
+
+ if (pD)
+ p = *pD;
+
+ p.valid = 0;
+ p.count = (reg * 1000) + value;
// invalidate memory
WriteMem(p, addr);
@@ -468,25 +579,25 @@ void PGXP_psxMemWrite32Trace(u32 mem, u32 value, u32 code) u16 PGXP_psxMemRead16Trace(u32 mem, u32 code)
{
u16 value = psxMemRead16(mem);
- PGPR_InvalidLoad(mem, code);
+ PGPR_InvalidLoad(mem, code, 116);
return value;
}
void PGXP_psxMemWrite16Trace(u32 mem, u16 value, u32 code)
{
- PGPR_InvalidStore(mem, code);
+ PGPR_InvalidStore(mem, code, 216);
psxMemWrite16(mem, value);
}
u8 PGXP_psxMemRead8Trace(u32 mem, u32 code)
{
u8 value = psxMemRead8(mem);
- PGPR_InvalidLoad(mem, code);
+ PGPR_InvalidLoad(mem, code, 18);
return value;
}
void PGXP_psxMemWrite8Trace(u32 mem, u8 value, u32 code)
{
- PGPR_InvalidStore(mem, code);
+ PGPR_InvalidStore(mem, code, 28);
psxMemWrite8(mem, value);
}
\ No newline at end of file diff --git a/libpcsxcore/pgxp_gte.h b/libpcsxcore/pgxp_gte.h index 50c8859b..d10021c0 100644 --- a/libpcsxcore/pgxp_gte.h +++ b/libpcsxcore/pgxp_gte.h @@ -32,11 +32,15 @@ void PGXP_Init(); // initialise memory
char* PGXP_GetMem(); // return pointer to precision memory
+u32 PGXP_ConvertAddress(u32 addr);
// -- GTE functions
// Transforms
-void PGXP_pushSXYZ2f(float _x, float _y, float _z);
-void PGXP_pushSXYZ2s(s64 _x, s64 _y, s64 _z);
+void PGXP_pushSXYZ2f(float _x, float _y, float _z, unsigned int _v);
+void PGXP_pushSXYZ2s(s64 _x, s64 _y, s64 _z, u32 v);
+
+void PGXP_RTPS(u32 _n, u32 _v);
+
int PGXP_NLCIP_valid();
float PGXP_NCLIP();
|
