summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authoriCatButler <i.am.catbutler@gmail.com>2018-12-16 15:24:01 +0000
committeriCatButler <i.am.catbutler@gmail.com>2018-12-16 15:24:01 +0000
commitcd685f7b75b8c7165642bd45044481ec5b27bc04 (patch)
tree0e0e1c0549961e4432ac31b25143476c199d1b0e /plugins
parent808e3feedb672c9a69830e0011a4fc79d16613f6 (diff)
downloadpcsxr-cd685f7b75b8c7165642bd45044481ec5b27bc04.tar.gz
Port various fixes from Beetle renderers
- Use PGXP w values to detect 3D geometry when modifying tex coords for flipped sprites - Replace line rendering algorithm with find/force line hack implementations - Add UI drop box to access this (no longer dependent on tex coord control)
Diffstat (limited to 'plugins')
-rw-r--r--plugins/peopsxgl/externals.h1
-rw-r--r--plugins/peopsxgl/prim.c342
-rw-r--r--plugins/peopsxgl/texture.c1
3 files changed, 193 insertions, 151 deletions
diff --git a/plugins/peopsxgl/externals.h b/plugins/peopsxgl/externals.h
index 1d82bf4f..e7aa013b 100644
--- a/plugins/peopsxgl/externals.h
+++ b/plugins/peopsxgl/externals.h
@@ -353,6 +353,7 @@ extern BOOL bUseFastMdec;
extern BOOL bUse15bitMdec;
extern int iFrameTexType;
extern int iFrameReadType;
+extern int iLineHackMode;
extern int iClampType;
extern int iSortTexCnt;
extern BOOL bFakeFrontBuffer;
diff --git a/plugins/peopsxgl/prim.c b/plugins/peopsxgl/prim.c
index b03d87d7..e9c4a442 100644
--- a/plugins/peopsxgl/prim.c
+++ b/plugins/peopsxgl/prim.c
@@ -3326,167 +3326,194 @@ void primPolyG4(unsigned char * baseAddr)
// cmd: flat shaded Texture3
////////////////////////////////////////////////////////////////////////
-BOOL DoLineCheck(uint32_t *gpuData)
-{
- BOOL bQuad=FALSE;short dx,dy;
-
- if(lx0==lx1)
- {
- dx=lx0-lx2;if(dx<0) dx=-dx;
-
- if(ly1==ly2)
- {
- dy=ly1-ly0;if(dy<0) dy=-dy;
- if(dx<=1)
- {
- vertex[3]=vertex[2];
- vertex[2]=vertex[0];
- vertex[2].x=vertex[3].x;
- }
- else
- if(dy<=1)
- {
- vertex[3]=vertex[2];
- vertex[2].y=vertex[0].y;
- }
- else return FALSE;
-
- bQuad=TRUE;
- }
- else
- if(ly0==ly2)
- {
- dy=ly0-ly1;if(dy<0) dy=-dy;
- if(dx<=1)
- {
- vertex[3]=vertex[1];
- vertex[3].x=vertex[2].x;
- }
- else
- if(dy<=1)
- {
- vertex[3]=vertex[2];
- vertex[3].y=vertex[1].y;
- }
- else return FALSE;
-
- bQuad=TRUE;
- }
- }
-
- if(lx0==lx2)
- {
- dx=lx0-lx1;if(dx<0) dx=-dx;
- if(ly2==ly1)
- {
- dy=ly2-ly0;if(dy<0) dy=-dy;
- if(dx<=1)
- {
- vertex[3]=vertex[1];
- vertex[1]=vertex[0];
- vertex[1].x=vertex[3].x;
- }
- else
- if(dy<=1)
- {
- vertex[3]=vertex[1];
- vertex[1].y=vertex[0].y;
- }
- else return FALSE;
+// 0 = disabled
+// 1 = enabled (default mode)
+// 2 = enabled (aggressive mode)
- bQuad=TRUE;
- }
- else
- if(ly0==ly1)
- {
- dy=ly2-ly0;if(dy<0) dy=-dy;
- if(dx<=1)
- {
- vertex[3]=vertex[2];
- vertex[3].x=vertex[1].x;
- }
- else
- if(dy<=1)
- {
- vertex[3]=vertex[1];
- vertex[3].y=vertex[2].y;
- }
- else return FALSE;
-
- bQuad=TRUE;
- }
- }
-
- if(lx1==lx2)
- {
- dx=lx1-lx0;if(dx<0) dx=-dx;
+typedef struct
+{
+ short x, y;
+ short padding[2];
+}sourceVert;
- if(ly1==ly0)
- {
- dy=ly1-ly2;if(dy<0) dy=-dy;
+// Hack to deal with PS1 games rendering axis aligned lines using 1 pixel wide triangles with UVs that describe a line
+// Suitable for games like Soul Blade, Doom and Hexen
+BOOL Hack_FindLine(uint32_t *gpuData)
+{
+ int pxWidth = 1; // width of a single pixel
+ unsigned short cornerIdx, shortIdx, longIdx;
+
+ sourceVert* pSourceVerts = (sourceVert*)&gpuData[1];
+
+ // reject 3D elements
+ if ((vertex[0].w != vertex[1].w) ||
+ (vertex[1].w != vertex[2].w))
+ return FALSE;
+
+ // find short side of triangle / end of line with 2 vertices (guess which vertex is the right angle)
+ if ((vertex[0].sow == vertex[1].sow) && (vertex[0].tow == vertex[1].tow))
+ cornerIdx = 0;
+ else if ((vertex[1].sow == vertex[2].sow) && (vertex[1].tow == vertex[2].tow))
+ cornerIdx = 1;
+ else if ((vertex[2].sow == vertex[0].sow) && (vertex[2].tow == vertex[0].tow))
+ cornerIdx = 2;
+ else
+ return FALSE;
+
+ // assign other indices to remaining vertices
+ shortIdx = (cornerIdx + 1) % 3;
+ longIdx = (shortIdx + 1) % 3;
+
+ // determine line orientation and check width
+ if ((vertex[cornerIdx].x == vertex[shortIdx].x) && (abs(pSourceVerts[cornerIdx].y - pSourceVerts[shortIdx].y) == pxWidth))
+ {
+ // line is horizontal
+ // determine which is truly the corner by checking against the long side, while making sure it is axis aligned
+ if (vertex[shortIdx].y == vertex[longIdx].y)
+ {
+ unsigned short tempIdx = shortIdx;
+ shortIdx = cornerIdx;
+ cornerIdx = tempIdx;
+ }
+ else if (vertex[cornerIdx].y != vertex[longIdx].y)
+ return FALSE;
+
+ // flip corner index to other side of quad
+ vertex[3] = vertex[longIdx];
+ vertex[3].y = vertex[shortIdx].y;
+ }
+ else if ((vertex[cornerIdx].y == vertex[shortIdx].y) && (abs(pSourceVerts[cornerIdx].x - pSourceVerts[shortIdx].x) == pxWidth))
+ {
+ // line is vertical
+ // determine which is truly the corner by checking against the long side, while making sure it is axis aligned
+ if (vertex[shortIdx].x == vertex[longIdx].x)
+ {
+ unsigned short tempIdx = shortIdx;
+ shortIdx = cornerIdx;
+ cornerIdx = tempIdx;
+ }
+ else if (vertex[cornerIdx].x != vertex[longIdx].x)
+ return FALSE;
+
+ // flip corner index to other side of quad
+ vertex[3] = vertex[longIdx];
+ vertex[3].x = vertex[shortIdx].x;
+ }
+ else
+ return FALSE;
+
+ // Draw Quad
+ PRIMdrawTexturedQuad(&vertex[cornerIdx], &vertex[longIdx], &vertex[3], &vertex[shortIdx]);
+
+ if(bDrawMultiPass)
+ {
+ SetSemiTransMulti(1);
+ PRIMdrawTexturedQuad(&vertex[cornerIdx], &vertex[longIdx], &vertex[3], &vertex[shortIdx]);
+ }
+
+ if(ubOpaqueDraw)
+ {
+ SetZMask4O();
+ if(bUseMultiPass) SetOpaqueColor(gpuData[0]);
+ DEFOPAQUEON
+ PRIMdrawTexturedQuad(&vertex[cornerIdx], &vertex[longIdx], &vertex[3], &vertex[shortIdx]);
+ DEFOPAQUEOFF
+ }
+
+ iDrawnSomething=1;
+
+ return TRUE;
+}
- if(dx<=1)
- {
- vertex[3]=vertex[2];
- vertex[2].x=vertex[0].x;
- }
- else
- if(dy<=1)
- {
- vertex[3]=vertex[2];
- vertex[2]=vertex[0];
- vertex[2].y=vertex[3].y;
- }
- else return FALSE;
- bQuad=TRUE;
- }
- else
- if(ly2==ly0)
- {
- dy=ly2-ly1;if(dy<0) dy=-dy;
+// Hack to deal with PS1 games rendering axis aligned lines using 1 pixel wide triangles and force UVs to describe a line
+// Required for games like Dark Forces and Duke Nukem
+BOOL Hack_ForceLine(uint32_t *gpuData)
+{
+ int pxWidth = 1; // width of a single pixel
+ unsigned short cornerIdx, shortIdx, longIdx;
+
+ sourceVert* pSourceVerts = (sourceVert*)&gpuData[1];
+
+ // reject 3D elements
+ if ((vertex[0].w != vertex[1].w) ||
+ (vertex[1].w != vertex[2].w))
+ return FALSE;
+
+ // find vertical AB
+ unsigned short A, B, C;
+ if (vertex[0].x == vertex[1].x)
+ A = 0;
+ else if (vertex[1].x == vertex[2].x)
+ A = 1;
+ else if (vertex[2].x == vertex[0].x)
+ A = 2;
+ else
+ return FALSE;
+
+ // assign other indices to remaining vertices
+ B = (A + 1) % 3;
+ C = (B + 1) % 3;
+
+ // find horizontal AC or BC
+ if (vertex[A].y == vertex[C].y)
+ cornerIdx = A;
+ else if (vertex[B].y == vertex[C].y)
+ cornerIdx = B;
+ else
+ return FALSE;
+
+ // determine lengths of sides
+ if (abs(pSourceVerts[A].y - pSourceVerts[B].y) == pxWidth)
+ {
+ // is Horizontal
+ shortIdx = (cornerIdx == A) ? B : A;
+ longIdx = C;
- if(dx<=1)
- {
- vertex[3]=vertex[1];
- vertex[1].x=vertex[0].x;
- }
- else
- if(dy<=1)
- {
- vertex[3]=vertex[1];
- vertex[1]=vertex[0];
- vertex[1].y=vertex[3].y;
- }
- else return FALSE;
+ // flip corner index to other side of quad
+ vertex[3] = vertex[longIdx];
+ vertex[3].y = vertex[shortIdx].y;
+ }
+ else if (abs(pSourceVerts[A].x - pSourceVerts[C].x) == pxWidth)
+ {
+ // is Vertical
+ shortIdx = C;
+ longIdx = (cornerIdx == A) ? B : A;
- bQuad=TRUE;
- }
- }
+ // flip corner index to other side of quad
+ vertex[3] = vertex[longIdx];
+ vertex[3].x = vertex[shortIdx].x;
+ }
+ else
+ return FALSE;
- if(!bQuad) return FALSE;
+ // force UVs into a line along the upper or left most edge of the triangle
+ // Otherwise the wrong UVs will be sampled on second triangle and by hardware renderers
+ vertex[shortIdx].sow = vertex[cornerIdx].sow;
+ vertex[shortIdx].tow = vertex[cornerIdx].tow;
- PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]);
+ // Draw Quad
+ PRIMdrawTexturedQuad(&vertex[cornerIdx], &vertex[longIdx], &vertex[3], &vertex[shortIdx]);
- if(bDrawMultiPass)
- {
- SetSemiTransMulti(1);
- PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]);
- }
+ if (bDrawMultiPass)
+ {
+ SetSemiTransMulti(1);
+ PRIMdrawTexturedQuad(&vertex[cornerIdx], &vertex[longIdx], &vertex[3], &vertex[shortIdx]);
+ }
- if(ubOpaqueDraw)
- {
- SetZMask4O();
- if(bUseMultiPass) SetOpaqueColor(gpuData[0]);
- DEFOPAQUEON
- PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]);
- DEFOPAQUEOFF
- }
+ if (ubOpaqueDraw)
+ {
+ SetZMask4O();
+ if (bUseMultiPass) SetOpaqueColor(gpuData[0]);
+ DEFOPAQUEON
+ PRIMdrawTexturedQuad(&vertex[cornerIdx], &vertex[longIdx], &vertex[3], &vertex[shortIdx]);
+ DEFOPAQUEOFF
+ }
- iDrawnSomething=1;
+ iDrawnSomething = 1;
- return TRUE;
+ return TRUE;
}
////////////////////////////////////////////////////////////////////////
@@ -3536,9 +3563,18 @@ void primPolyFT3(unsigned char * baseAddr)
assignTexture3();
- if(!(dwActFixes&0x10))
- {
- if(DoLineCheck(gpuData)) return;
+ switch(iLineHackMode)
+ {
+ case 0:
+ break; // disabled
+ case 1:
+ if (Hack_FindLine(gpuData)) // default mode
+ return;
+ break;
+ case 2:
+ if (Hack_ForceLine(gpuData)) // aggressive mode
+ return;
+ break;
}
PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]);
@@ -3572,6 +3608,10 @@ void RectTexAlign(void)
int UFlipped = FALSE;
int VFlipped = FALSE;
+ // Leverage PGXP to further avoid 3D polygons that just happen to align this way after projection
+ if ((vertex[0].w != vertex[1].w) || (vertex[1].w != vertex[2].w))
+ return;
+
if(gTexName==gTexFrameName) return;
if(ly0==ly1)
diff --git a/plugins/peopsxgl/texture.c b/plugins/peopsxgl/texture.c
index 8d8fb41b..c19bf0ca 100644
--- a/plugins/peopsxgl/texture.c
+++ b/plugins/peopsxgl/texture.c
@@ -139,6 +139,7 @@ BOOL bUseFastMdec=FALSE;
BOOL bUse15bitMdec=FALSE;
int iFrameTexType=0;
int iFrameReadType=0;
+int iLineHackMode=0;
uint32_t (*TCF[2]) (uint32_t);
unsigned short (*PTCF[2]) (unsigned short);