1 /*
2 Copyright (C) 2003 Rice1964
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 
18 */
19 
20 #include <stdint.h>
21 #include <math.h>
22 #include <vector>
23 
24 #include <retro_miscellaneous.h>
25 
26 #include "osal_preproc.h"
27 #include "float.h"
28 #include "DeviceBuilder.h"
29 #include "Render.h"
30 #include "Timing.h"
31 
32 #include "../../Graphics/GBI.h"
33 #include "../../Graphics/RDP/gDP_state.h"
34 
35 extern FiddledVtx * g_pVtxBase;
36 
37 #define ENABLE_CLIP_TRI
38 
39 #ifdef ENABLE_CLIP_TRI
40 
RSP_Vtx_Clipping(int i)41 void RSP_Vtx_Clipping(int i)
42 {
43     g_clipFlag[i] = 0;
44     g_clipFlag2[i] = 0;
45     if( g_vecProjected[i].w > 0 )
46     {
47         /*
48         if( gRSP.bRejectVtx )
49         {
50             if( g_vecProjected[i].x > 1 )
51             {
52                 g_clipFlag2[i] |= X_CLIP_MAX;
53                 if( g_vecProjected[i].x > gRSP.real_clip_ratio_posx )
54                     g_clipFlag[i] |= X_CLIP_MAX;
55             }
56 
57             if( g_vecProjected[i].x < -1 )
58             {
59                 g_clipFlag2[i] |= X_CLIP_MIN;
60                 if( g_vecProjected[i].x < gRSP.real_clip_ratio_negx )
61                     g_clipFlag[i] |= X_CLIP_MIN;
62             }
63 
64             if( g_vecProjected[i].y > 1 )
65             {
66                 g_clipFlag2[i] |= Y_CLIP_MAX;
67                 if( g_vecProjected[i].y > gRSP.real_clip_ratio_posy )
68                     g_clipFlag[i] |= Y_CLIP_MAX;
69             }
70 
71             if( g_vecProjected[i].y < -1 )
72             {
73                 g_clipFlag2[i] |= Y_CLIP_MIN;
74                 if( g_vecProjected[i].y < gRSP.real_clip_ratio_negy )
75                     g_clipFlag[i] |= Y_CLIP_MIN;
76             }
77 
78             //if( g_vecProjected[i].z > 1.0f )
79             //{
80             //  g_clipFlag2[i] |= Z_CLIP_MAX;
81             //  g_clipFlag[i] |= Z_CLIP_MAX;
82             //}
83 
84             //if( gRSP.bNearClip && g_vecProjected[i].z < -1.0f )
85             //{
86             //  g_clipFlag2[i] |= Z_CLIP_MIN;
87             //  g_clipFlag[i] |= Z_CLIP_MIN;
88             //}
89         }
90         else
91         */
92         {
93             if( g_vecProjected[i].x > 1 )   g_clipFlag2[i] |= X_CLIP_MAX;
94             if( g_vecProjected[i].x < -1 )  g_clipFlag2[i] |= X_CLIP_MIN;
95             if( g_vecProjected[i].y > 1 )   g_clipFlag2[i] |= Y_CLIP_MAX;
96             if( g_vecProjected[i].y < -1 )  g_clipFlag2[i] |= Y_CLIP_MIN;
97             //if( g_vecProjected[i].z > 1.0f )  g_clipFlag2[i] |= Z_CLIP_MAX;
98             //if( gRSP.bNearClip && g_vecProjected[i].z < -1.0f )   g_clipFlag2[i] |= Z_CLIP_MIN;
99         }
100 
101     }
102 }
103 
104 #else
RSP_Vtx_Clipping(int i)105 inline void RSP_Vtx_Clipping(int i) {}
106 #endif
107 
108 /*
109  *  Global variables
110  */
111 ALIGN(16,RSP_Options gRSP);
112 ALIGN(16,RDP_Options gRDP);
113 
114 ALIGN(16,XVECTOR4 g_normal);
115 //static int norms[3];
116 
117 ALIGN(16,XVECTOR4 g_vtxNonTransformed[MAX_VERTS]);
118 ALIGN(16,XVECTOR4 g_vecProjected[MAX_VERTS]);
119 ALIGN(16,XVECTOR4 g_vtxTransformed[MAX_VERTS]);
120 
121 float       g_vtxProjected5[1000][5];
122 float       g_vtxProjected5Clipped[2000][5];
123 
124 //uint32_t        g_dwVtxFlags[MAX_VERTS];            // Z_POS Z_NEG etc
125 VECTOR2     g_fVtxTxtCoords[MAX_VERTS];
126 uint32_t      g_dwVtxDifColor[MAX_VERTS];
127 uint32_t      g_clipFlag[MAX_VERTS];
128 uint32_t      g_clipFlag2[MAX_VERTS];
129 RenderTexture g_textures[MAX_TEXTURES];
130 float       g_fFogCoord[MAX_VERTS];
131 
132 EXTERNAL_VERTEX g_vtxForExternal[MAX_VERTS];
133 
134 TLITVERTEX          g_vtxBuffer[1000];
135 TLITVERTEX          g_clippedVtxBuffer[2000];
136 uint8_t               g_oglVtxColors[1000][4];
137 int                 g_clippedVtxCount=0;
138 TLITVERTEX          g_texRectTVtx[4];
139 unsigned short      g_vtxIndex[1000];
140 unsigned int        g_minIndex, g_maxIndex;
141 
142 float               gRSPfFogMin;
143 float               gRSPfFogMax;
144 float               gRSPfFogDivider;
145 
146 Light   gRSPlights[16];
147 
148 ALIGN(16,Matrix  gRSPworldProjectTransported);
149 ALIGN(16,Matrix  gRSPworldProject);
150 ALIGN(16,Matrix  gRSPmodelViewTop);
151 ALIGN(16,Matrix  gRSPmodelViewTopTranspose);
152 ALIGN(16,Matrix  dkrMatrixTransposed);
153 
154 N64Light        gRSPn64lights[16];
155 
156 
157 void (*ProcessVertexData)(uint32_t dwAddr, uint32_t dwV0, uint32_t dwNum)=NULL;
158 
159 /* Multiply (x,y,z,0) by matrix m, then normalize */
160 #define Vec3TransformNormal(vec, m) \
161    VECTOR3 temp; \
162    temp.x = (vec.x * m._11) + (vec.y * m._21) + (vec.z * m._31); \
163    temp.y = (vec.x * m._12) + (vec.y * m._22) + (vec.z * m._32); \
164    temp.z = (vec.x * m._13) + (vec.y * m._23) + (vec.z * m._33); \
165    float norm = sqrt(temp.x*temp.x+temp.y*temp.y+temp.z*temp.z); \
166    if (norm == 0.0) { vec.x = 0.0; vec.y = 0.0; vec.z = 0.0;} else \
167    { vec.x = temp.x/norm; vec.y = temp.y/norm; vec.z = temp.z/norm; }
168 
169 float real255 = 255.0f;
170 float real128 = 128.0f;
171 
NormalizeNormalVec()172 void NormalizeNormalVec()
173 {
174     float w = 1/sqrtf(g_normal.x*g_normal.x + g_normal.y*g_normal.y + g_normal.z*g_normal.z);
175     g_normal.x *= w;
176     g_normal.y *= w;
177     g_normal.z *= w;
178 }
179 
180 
InitRenderBase()181 void InitRenderBase()
182 {
183    ProcessVertexData = ProcessVertexDataNoSSE;
184 
185     gRSPfFogMin = gRSPfFogMax = 0.0f;
186     windowSetting.fMultX = windowSetting.fMultY = 2.0f;
187     windowSetting.vpLeftW = windowSetting.vpTopW = 0;
188     windowSetting.vpRightW = windowSetting.vpWidthW = 640;
189     windowSetting.vpBottomW = windowSetting.vpHeightW = 480;
190     gRSP.maxZ = 0;
191     gRSP.nVPLeftN = gRSP.nVPTopN = 0;
192     gRSP.nVPRightN = 640;
193     gRSP.nVPBottomN = 640;
194     gRSP.nVPWidthN = 640;
195     gRSP.nVPHeightN = 640;
196     gRDP.scissor.left=gRDP.scissor.top=0;
197     gRDP.scissor.right=gRDP.scissor.bottom=640;
198 
199     gRSP.bLightingEnable = gRSP.bTextureGen = false;
200     gSP.numLights = 0;
201     gRSP.curTile=gRSP.ambientLightColor=gRSP.ambientLightIndex= 0;
202     gRSP.fAmbientLightR=gRSP.fAmbientLightG=gRSP.fAmbientLightB=0;
203     gRSP.projectionMtxTop = gRSP.modelViewMtxTop = 0;
204     gRDP.fogColor = gRDP.primitiveColor = gRDP.envColor = gRDP.primitiveDepth = gRDP.primLODMin = gRDP.primLODFrac = gRDP.LODFrac = 0;
205     gRDP.fPrimitiveDepth = 0;
206     gRSP.numVertices = 0;
207     gRSP.maxVertexID = 0;
208     gRSP.bCullFront=false;
209     gRSP.bCullBack=true;
210     gRSP.bFogEnabled=gRDP.bFogEnableInBlender=false;
211     gRSP.bZBufferEnabled=true;
212     gRSP.shadeMode=SHADE_SMOOTH;
213     gRDP.keyR=gRDP.keyG=gRDP.keyB=gRDP.keyA=gRDP.keyRGB=gRDP.keyRGBA = 0;
214     gRDP.fKeyA = 0;
215     gRSP.DKRCMatrixIndex = gRSP.dwDKRVtxAddr = gRSP.dwDKRMatrixAddr = 0;
216     gRSP.DKRBillBoard = false;
217 
218     gRSP.fTexScaleX = 1/32.0f;
219     gRSP.fTexScaleY = 1/32.0f;
220     gRSP.bTextureEnabled = false;
221 
222     gRSP.clip_ratio_left = 0;
223     gRSP.clip_ratio_top = 0;
224     gRSP.clip_ratio_right = 640;
225     gRSP.clip_ratio_bottom = 480;
226     gRSP.clip_ratio_negx = 1;
227     gRSP.clip_ratio_negy = 1;
228     gRSP.clip_ratio_posx = 1;
229     gRSP.clip_ratio_posy = 1;
230     gRSP.real_clip_scissor_left = 0;
231     gRSP.real_clip_scissor_top = 0;
232     gRSP.real_clip_scissor_right = 640;
233     gRSP.real_clip_scissor_bottom = 480;
234     windowSetting.clipping.left = 0;
235     windowSetting.clipping.top = 0;
236     windowSetting.clipping.right = 640;
237     windowSetting.clipping.bottom = 480;
238     windowSetting.clipping.width = 640;
239     windowSetting.clipping.height = 480;
240     windowSetting.clipping.needToClip = false;
241     gRSP.real_clip_ratio_negx = 1;
242     gRSP.real_clip_ratio_negy = 1;
243     gRSP.real_clip_ratio_posx = 1;
244     gRSP.real_clip_ratio_posy = 1;
245 
246     gRSP.DKRCMatrixIndex=0;
247     gRSP.DKRVtxCount=0;
248     gRSP.DKRBillBoard = false;
249     gRSP.dwDKRVtxAddr=0;
250     gRSP.dwDKRMatrixAddr=0;
251 
252 
253     gSP.geometryMode    = 0;
254     gDP.otherMode.l     = 0;
255     gDP.otherMode.h     = 0;
256     gRDP.fillColor      = 0xFFFFFFFF;
257     gRDP.originalFillColor  =0;
258 
259     gRSP.ucode      = 1;
260     gRSP.vertexMult = 10;
261     gRSP.bNearClip  = false;
262     gRSP.bRejectVtx = false;
263 
264     gRDP.texturesAreReloaded = false;
265     gRDP.textureIsChanged = false;
266     gRDP.colorsAreReloaded = false;
267 
268     memset(&gRDP.otherMode,0,sizeof(RDP_OtherMode));
269     memset(&gRDP.tilesinfo,0,sizeof(TileAdditionalInfo)*8);
270     memset(&gDP.tiles,0,sizeof(struct gDPTile)*8);
271 
272     for (int i=0; i<MAX_VERTS; i++)
273     {
274         g_clipFlag[i] = 0;
275         g_vtxNonTransformed[i].w = 1;
276     }
277 
278     memset(gRSPn64lights, 0, sizeof(N64Light)*16);
279 }
280 
SetFogMinMax(float fMin,float fMax,float fMul,float fOffset)281 void SetFogMinMax(float fMin, float fMax, float fMul, float fOffset)
282 {
283     if (fMin > fMax)
284     {
285         float temp = fMin;
286         fMin = fMax;
287         fMax = temp;
288     }
289 
290     {
291         gRSPfFogMin = MAX(0,fMin/500-1);
292         gRSPfFogMax = fMax/500-1;
293     }
294 
295     gRSPfFogDivider = 255/(gRSPfFogMax-gRSPfFogMin);
296     CRender::g_pRender->SetFogMinMax(fMin, fMax);
297 }
298 
InitVertexTextureConstants()299 void InitVertexTextureConstants()
300 {
301     RenderTexture &tex0 = g_textures[gRSP.curTile];
302     //CTexture *surf = tex0.m_pCTexture;
303     TileAdditionalInfo *tile0 = &gRDP.tilesinfo[gRSP.curTile];
304 
305     float scaleX = gRSP.fTexScaleX;
306     float scaleY = gRSP.fTexScaleY;
307 
308     gRSP.tex0scaleX = scaleX * tile0->fShiftScaleS/tex0.m_fTexWidth;
309     gRSP.tex0scaleY = scaleY * tile0->fShiftScaleT/tex0.m_fTexHeight;
310 
311     gRSP.tex0OffsetX = tile0->fhilite_sl/tex0.m_fTexWidth;
312     gRSP.tex0OffsetY = tile0->fhilite_tl/tex0.m_fTexHeight;
313 
314     if( CRender::g_pRender->IsTexel1Enable() )
315     {
316         RenderTexture &tex1 = g_textures[(gRSP.curTile+1)&7];
317         //CTexture *surf = tex1.m_pCTexture;
318         TileAdditionalInfo *tile1 = &gRDP.tilesinfo[(gRSP.curTile+1)&7];
319 
320         gRSP.tex1scaleX = scaleX * tile1->fShiftScaleS/tex1.m_fTexWidth;
321         gRSP.tex1scaleY = scaleY * tile1->fShiftScaleT/tex1.m_fTexHeight;
322 
323         gRSP.tex1OffsetX = tile1->fhilite_sl/tex1.m_fTexWidth;
324         gRSP.tex1OffsetY = tile1->fhilite_tl/tex1.m_fTexHeight;
325     }
326 
327     gRSP.texGenXRatio = tile0->fShiftScaleS;
328     gRSP.texGenYRatio = gRSP.fTexScaleX/gRSP.fTexScaleY*tex0.m_fTexWidth/tex0.m_fTexHeight*tile0->fShiftScaleT;
329 }
330 
TexGen(float & s,float & t)331 void TexGen(float &s, float &t)
332 {
333     if (gSP.geometryMode & G_TEXTURE_GEN_LINEAR)
334     {
335         s = acosf(g_normal.x) / 3.14159f;
336         t = acosf(g_normal.y) / 3.14159f;
337     }
338     else
339     {
340         s = 0.5f * ( 1.0f + g_normal.x);
341         t = 0.5f * ( 1.0f - g_normal.y);
342     }
343 }
344 
ComputeLOD(void)345 void ComputeLOD(void)
346 {
347     TLITVERTEX &v0 = g_vtxBuffer[0];
348     TLITVERTEX &v1 = g_vtxBuffer[1];
349     RenderTexture &tex0 = g_textures[gRSP.curTile];
350 
351     float d,dt;
352     float x = g_vtxProjected5[0][0] / g_vtxProjected5[0][4] - g_vtxProjected5[1][0] / g_vtxProjected5[1][4];
353     float y = g_vtxProjected5[0][1] / g_vtxProjected5[0][4] - g_vtxProjected5[1][1] / g_vtxProjected5[1][4];
354 
355     x = windowSetting.vpWidthW*x/windowSetting.fMultX/2;
356     y = windowSetting.vpHeightW*y/windowSetting.fMultY/2;
357     d = sqrtf(x*x+y*y);
358 
359     float s0 = v0.tcord[0].u * tex0.m_fTexWidth;
360     float t0 = v0.tcord[0].v * tex0.m_fTexHeight;
361     float s1 = v1.tcord[0].u * tex0.m_fTexWidth;
362     float t1 = v1.tcord[0].v * tex0.m_fTexHeight;
363 
364     dt = sqrtf((s0-s1)*(s0-s1)+(t0-t1)*(t0-t1));
365 
366     float lod = dt/d;
367     float frac = log10f(lod)/log10f(2.0f);
368     frac = (lod / powf(2.0f,floorf(frac)));
369     frac = frac - floorf(frac);
370     gRDP.LODFrac = (uint32_t)(frac*255);
371     CRender::g_pRender->SetCombinerAndBlender();
372 }
373 
374 bool bHalfTxtScale=false;
375 extern uint32_t lastSetTile;
376 
377 #ifdef _MSC_VER
378 #define noinline __declspec(noinline)
379 #else
380 #define noinline __attribute__((noinline))
381 #endif
382 
InitVertex_scale_hack_check(uint32_t dwV)383 static noinline void InitVertex_scale_hack_check(uint32_t dwV)
384 {
385     // Check for txt scale hack
386     if( gDP.tiles[lastSetTile].size == G_IM_SIZ_32b || gDP.tiles[lastSetTile].size == G_IM_SIZ_4b )
387     {
388         int width = ((gDP.tiles[lastSetTile].uls  - gDP.tiles[lastSetTile].lrs+1)<<1);
389         int height = ((gDP.tiles[lastSetTile].ult - gDP.tiles[lastSetTile].lrt+1)<<1);
390         if( g_fVtxTxtCoords[dwV].x*gRSP.fTexScaleX == width || g_fVtxTxtCoords[dwV].y*gRSP.fTexScaleY == height )
391             bHalfTxtScale=true;
392     }
393 }
394 
InitVertex_notopengl_or_clipper_adjust(TLITVERTEX & v,uint32_t dwV)395 static noinline void InitVertex_notopengl_or_clipper_adjust(TLITVERTEX &v, uint32_t dwV)
396 {
397     v.x = g_vecProjected[dwV].x*gRSP.vtxXMul+gRSP.vtxXAdd;
398     v.y = g_vecProjected[dwV].y*gRSP.vtxYMul+gRSP.vtxYAdd;
399     v.z = (g_vecProjected[dwV].z + 1.0f) * 0.5f;    // DirectX minZ=0, maxZ=1
400     //v.z = g_vecProjected[dwV].z;  // DirectX minZ=0, maxZ=1
401     v.rhw = g_vecProjected[dwV].w;
402 
403     if( gRSP.bProcessSpecularColor )
404     {
405         v.dcSpecular = CRender::g_pRender->PostProcessSpecularColor();
406         if( gRSP.bFogEnabled )
407         {
408             v.dcSpecular &= 0x00FFFFFF;
409             uint32_t  fogFct = 0xFF-(uint8_t)((g_fFogCoord[dwV]-gRSPfFogMin)*gRSPfFogDivider);
410             v.dcSpecular |= (fogFct<<24);
411         }
412     }
413     else if( gRSP.bFogEnabled )
414     {
415         uint32_t  fogFct = 0xFF-(uint8_t)((g_fFogCoord[dwV]-gRSPfFogMin)*gRSPfFogDivider);
416         v.dcSpecular = (fogFct<<24);
417     }
418 }
419 
InitVertex_texgen_correct(TLITVERTEX & v,uint32_t dwV)420 static noinline void InitVertex_texgen_correct(TLITVERTEX &v, uint32_t dwV)
421 {
422     // Correction for texGen result
423     float u0,u1,v0,v1;
424     RenderTexture &tex0 = g_textures[gRSP.curTile];
425     u0 = g_fVtxTxtCoords[dwV].x * 32 * 1024 * gRSP.fTexScaleX / tex0.m_fTexWidth;
426     v0 = g_fVtxTxtCoords[dwV].y * 32 * 1024 * gRSP.fTexScaleY / tex0.m_fTexHeight;
427     u0 *= (gRDP.tilesinfo[gRSP.curTile].fShiftScaleS);
428     v0 *= (gRDP.tilesinfo[gRSP.curTile].fShiftScaleT);
429 
430     if( CRender::g_pRender->IsTexel1Enable() )
431     {
432         RenderTexture &tex1 = g_textures[(gRSP.curTile+1)&7];
433         u1 = g_fVtxTxtCoords[dwV].x * 32 * 1024 * gRSP.fTexScaleX / tex1.m_fTexWidth;
434         v1 = g_fVtxTxtCoords[dwV].y * 32 * 1024 * gRSP.fTexScaleY / tex1.m_fTexHeight;
435         u1 *= gRDP.tilesinfo[(gRSP.curTile+1)&7].fShiftScaleS;
436         v1 *= gRDP.tilesinfo[(gRSP.curTile+1)&7].fShiftScaleT;
437         CRender::g_pRender->SetVertexTextureUVCoord(v, u0, v0, u1, v1);
438     }
439     else
440     {
441         CRender::g_pRender->SetVertexTextureUVCoord(v, u0, v0);
442     }
443 }
444 
multiply_subtract2(float * d,const float * m1,const float * m2,const float * s)445 static void multiply_subtract2(float *d, const float *m1, const float *m2, const float *s)
446 {
447     int i;
448     for (i = 0; i < 2; i++)
449         d[i] = m1[i] * m2[i] - s[i];
450 }
451 
InitVertex(uint32_t dwV,uint32_t vtxIndex,bool bTexture)452 void InitVertex(uint32_t dwV, uint32_t vtxIndex, bool bTexture)
453 {
454     TLITVERTEX &v = g_vtxBuffer[vtxIndex];
455     g_vtxProjected5[vtxIndex][0] = g_vtxTransformed[dwV].x;
456     g_vtxProjected5[vtxIndex][1] = g_vtxTransformed[dwV].y;
457     g_vtxProjected5[vtxIndex][2] = g_vtxTransformed[dwV].z;
458     g_vtxProjected5[vtxIndex][3] = g_vtxTransformed[dwV].w;
459     g_vtxProjected5[vtxIndex][4] = g_fFogCoord[dwV];
460 
461     g_vtxIndex[vtxIndex] = vtxIndex;
462 
463     if( options.bOGLVertexClipper == true )
464     {
465         InitVertex_notopengl_or_clipper_adjust(v, dwV);
466     }
467 
468     v.dcDiffuse = g_dwVtxDifColor[dwV];
469     if( gRDP.otherMode.key_en )
470     {
471         v.dcDiffuse &= 0x00FFFFFF;
472         v.dcDiffuse |= (gRDP.keyA<<24);
473     }
474     else if( gRDP.otherMode.aa_en && gRDP.otherMode.clr_on_cvg==0 )
475     {
476         v.dcDiffuse |= 0xFF000000;
477     }
478 
479     if( gRSP.bProcessDiffuseColor )
480     {
481         v.dcDiffuse = CRender::g_pRender->PostProcessDiffuseColor(v.dcDiffuse);
482     }
483     if( options.bWinFrameMode )
484     {
485         v.dcDiffuse = g_dwVtxDifColor[dwV];
486     }
487 
488     g_oglVtxColors[vtxIndex][0] = v.r;
489     g_oglVtxColors[vtxIndex][1] = v.g;
490     g_oglVtxColors[vtxIndex][2] = v.b;
491     g_oglVtxColors[vtxIndex][3] = v.a;
492 
493     if( bTexture )
494     {
495         // If the vert is already lit, then there is no normal (and hence we can't generate tex coord)
496         // Only scale if not generated automatically
497         if (gRSP.bTextureGen && gRSP.bLightingEnable)
498             InitVertex_texgen_correct(v, dwV);
499         else
500         {
501             TexCord tex0;
502             multiply_subtract2(&tex0.u, &g_fVtxTxtCoords[dwV].x, &gRSP.tex0scaleX, &gRSP.tex0OffsetX);
503 
504             if( CRender::g_pRender->IsTexel1Enable() )
505             {
506                 TexCord tex1;
507                 multiply_subtract2(&tex1.u, &g_fVtxTxtCoords[dwV].x, &gRSP.tex1scaleX, &gRSP.tex1OffsetX);
508 
509                 CRender::g_pRender->SetVertexTextureUVCoord(v, tex0, tex1);
510             }
511             else
512                 CRender::g_pRender->SetVertexTextureUVCoord(v, tex0);
513         }
514 
515         if(g_curRomInfo.bTextureScaleHack && !bHalfTxtScale)
516             InitVertex_scale_hack_check(dwV);
517     }
518 }
519 
LightVert(XVECTOR4 & norm,int vidx)520 uint32_t LightVert(XVECTOR4 & norm, int vidx)
521 {
522     float fCosT;
523     /* Do ambient */
524     float r = gRSP.fAmbientLightR;
525     float g = gRSP.fAmbientLightG;
526     float b = gRSP.fAmbientLightB;
527 
528     if( options.enableHackForGames != HACK_FOR_ZELDA_MM )
529     {
530         for (unsigned int l=0; l < gSP.numLights; l++)
531         {
532             fCosT = norm.x*gRSPlights[l].x + norm.y*gRSPlights[l].y + norm.z*gRSPlights[l].z;
533 
534             if (fCosT > 0 )
535             {
536                 r += gRSPlights[l].fr * fCosT;
537                 g += gRSPlights[l].fg * fCosT;
538                 b += gRSPlights[l].fb * fCosT;
539             }
540         }
541     }
542     else
543     {
544         XVECTOR4 v;
545         unsigned int l;
546         bool transformed = false;
547 
548         for (l=0; l < gSP.numLights; l++)
549         {
550             if( gRSPlights[l].range == 0 )
551             {
552                 // Regular directional light
553                 fCosT = norm.x*gRSPlights[l].x + norm.y*gRSPlights[l].y + norm.z*gRSPlights[l].z;
554 
555                 if (fCosT > 0 )
556                 {
557                     r += gRSPlights[l].fr * fCosT;
558                     g += gRSPlights[l].fg * fCosT;
559                     b += gRSPlights[l].fb * fCosT;
560                 }
561             }
562             else //if( (gRSPlights[l].col&0x00FFFFFF) != 0x00FFFFFF )
563             {
564                 // Point light
565                 if( !transformed )
566                 {
567                     Vec3Transform(&v, (XVECTOR3*)&g_vtxNonTransformed[vidx], &gRSPmodelViewTop);    // Convert to w=1
568                     transformed = true;
569                 }
570 
571                 XVECTOR3 dir(gRSPlights[l].x - v.x, gRSPlights[l].y - v.y, gRSPlights[l].z - v.z);
572                 //XVECTOR3 dir(v.x-gRSPlights[l].x, v.y-gRSPlights[l].y, v.z-gRSPlights[l].z);
573                 float d2 = sqrtf(dir.x*dir.x+dir.y*dir.y+dir.z*dir.z);
574                 dir.x /= d2;
575                 dir.y /= d2;
576                 dir.z /= d2;
577 
578                 fCosT = norm.x*dir.x + norm.y*dir.y + norm.z*dir.z;
579 
580                 if (fCosT > 0 )
581                 {
582                     //float f = d2/gRSPlights[l].range*50;
583                     float f = d2/15000*50;
584                     f = 1 - MIN(f,1);
585                     fCosT *= f*f;
586 
587                     r += gRSPlights[l].fr * fCosT;
588                     g += gRSPlights[l].fg * fCosT;
589                     b += gRSPlights[l].fb * fCosT;
590                 }
591             }
592         }
593     }
594 
595     if (r > 255) r = 255;
596     if (g > 255) g = 255;
597     if (b > 255) b = 255;
598     return ((0xff000000)|(((uint32_t)r)<<16)|(((uint32_t)g)<<8)|((uint32_t)b));
599 }
600 
LightVertNew(XVECTOR4 & norm)601 uint32_t LightVertNew(XVECTOR4 & norm)
602 {
603     unsigned int l;
604     /* Do ambient */
605     float r = gRSP.fAmbientLightR;
606     float g = gRSP.fAmbientLightG;
607     float b = gRSP.fAmbientLightB;
608 
609 
610     for (l=0; l < gSP.numLights; l++)
611     {
612         float fCosT = norm.x*gRSPlights[l].tx + norm.y*gRSPlights[l].ty + norm.z*gRSPlights[l].tz;
613 
614         if (fCosT > 0 )
615         {
616             r += gRSPlights[l].fr * fCosT;
617             g += gRSPlights[l].fg * fCosT;
618             b += gRSPlights[l].fb * fCosT;
619         }
620     }
621 
622     if (r > 255) r = 255;
623     if (g > 255) g = 255;
624     if (b > 255) b = 255;
625     return ((0xff000000)|(((uint32_t)r)<<16)|(((uint32_t)g)<<8)|((uint32_t)b));
626 }
627 
628 
629 float zero = 0.0f;
630 float onef = 1.0f;
631 float fcosT;
632 
ReplaceAlphaWithFogFactor(int i)633 void ReplaceAlphaWithFogFactor(int i)
634 {
635     if( gSP.geometryMode & G_FOG )
636     {
637         // Use fog factor to replace vertex alpha
638         if( g_vecProjected[i].z > 1 )
639             *(((uint8_t*)&(g_dwVtxDifColor[i]))+3) = 0xFF;
640         if( g_vecProjected[i].z < 0 )
641             *(((uint8_t*)&(g_dwVtxDifColor[i]))+3) = 0;
642         else
643             *(((uint8_t*)&(g_dwVtxDifColor[i]))+3) = (uint8_t)(g_vecProjected[i].z*255);
644     }
645 }
646 
647 
648 // Bits
649 // +-+-+-
650 // xxyyzz
651 #define Z_NEG  0x01
652 #define Z_POS  0x02
653 #define Y_NEG  0x04
654 #define Y_POS  0x08
655 #define X_NEG  0x10
656 #define X_POS  0x20
657 
658 // Assumes dwAddr has already been checked!
659 // Don't inline - it's too big with the transform macros
660 
ProcessVertexDataNoSSE(uint32_t dwAddr,uint32_t dwV0,uint32_t dwNum)661 void ProcessVertexDataNoSSE(uint32_t dwAddr, uint32_t dwV0, uint32_t dwNum)
662 {
663 
664     UpdateCombinedMatrix();
665 
666     // This function is called upon SPvertex
667     // - do vertex matrix transform
668     // - do vertex lighting
669     // - do texture coordinate transform if needed
670     // - calculate normal vector
671 
672     // Output:  - g_vecProjected[i]             -> transformed vertex x,y,z
673     //          - g_vecProjected[i].w           -> saved vertex 1/w
674     //          - g_dwVtxFlags[i]               -> flags
675     //          - g_dwVtxDifColor[i]            -> vertex color
676     //          - g_fVtxTxtCoords[i]            -> vertex texture coordinates
677 
678     uint8_t *rdram_u8 = (uint8_t*)gfx_info.RDRAM;
679     FiddledVtx * pVtxBase = (FiddledVtx*)(rdram_u8 + dwAddr);
680     g_pVtxBase = pVtxBase;
681 
682     for (uint32_t i = dwV0; i < dwV0 + dwNum; i++)
683     {
684         SP_Timing(RSP_GBI0_Vtx);
685 
686         FiddledVtx & vert = pVtxBase[i - dwV0];
687 
688         g_vtxNonTransformed[i].x = (float)vert.x;
689         g_vtxNonTransformed[i].y = (float)vert.y;
690         g_vtxNonTransformed[i].z = (float)vert.z;
691 
692         Vec3Transform(&g_vtxTransformed[i], (XVECTOR3*)&g_vtxNonTransformed[i], &gRSPworldProject); // Convert to w=1
693 
694         g_vecProjected[i].w = 1.0f / g_vtxTransformed[i].w;
695         g_vecProjected[i].x = g_vtxTransformed[i].x * g_vecProjected[i].w;
696         g_vecProjected[i].y = g_vtxTransformed[i].y * g_vecProjected[i].w;
697         if ((g_curRomInfo.bPrimaryDepthHack || options.enableHackForGames == HACK_FOR_NASCAR ) && gRDP.otherMode.depth_source )
698         {
699             g_vecProjected[i].z = gRDP.fPrimitiveDepth;
700             g_vtxTransformed[i].z = gRDP.fPrimitiveDepth*g_vtxTransformed[i].w;
701         }
702         else
703         {
704             g_vecProjected[i].z = g_vtxTransformed[i].z * g_vecProjected[i].w;
705         }
706 
707         if( gRSP.bFogEnabled )
708         {
709             g_fFogCoord[i] = g_vecProjected[i].z;
710             if( g_vecProjected[i].w < 0 || g_vecProjected[i].z < 0 || g_fFogCoord[i] < gRSPfFogMin )
711                 g_fFogCoord[i] = gRSPfFogMin;
712         }
713 
714         RSP_Vtx_Clipping(i);
715 
716         if( gRSP.bLightingEnable )
717         {
718             g_normal.x = (float)vert.norma.nx;
719             g_normal.y = (float)vert.norma.ny;
720             g_normal.z = (float)vert.norma.nz;
721 
722             Vec3TransformNormal(g_normal, gRSPmodelViewTop);
723             g_dwVtxDifColor[i] = LightVert(g_normal, i);
724             *(((uint8_t*)&(g_dwVtxDifColor[i]))+3) = vert.rgba.a; // still use alpha from the vertex
725         }
726         else
727         {
728             if( (gSP.geometryMode & G_SHADE) == 0 && gRSP.ucode < 5 )  //Shade is disabled
729             {
730                 //FLAT shade
731                 g_dwVtxDifColor[i] = gRDP.primitiveColor;
732             }
733             else
734             {
735                 IColor &color = *(IColor*)&g_dwVtxDifColor[i];
736                 color.b = vert.rgba.r;
737                 color.g = vert.rgba.g;
738                 color.r = vert.rgba.b;
739                 color.a = vert.rgba.a;
740             }
741         }
742 
743         if( options.bWinFrameMode )
744         {
745             g_dwVtxDifColor[i] = COLOR_RGBA(vert.rgba.r, vert.rgba.g, vert.rgba.b, vert.rgba.a);
746         }
747 
748         ReplaceAlphaWithFogFactor(i);
749 
750         // Update texture coords n.b. need to divide tu/tv by bogus scale on addition to buffer
751 
752         // If the vertex is already lit, then there is no normal (and hence we
753         // can't generate tex coord)
754         if (gRSP.bTextureGen && gRSP.bLightingEnable )
755         {
756             TexGen(g_fVtxTxtCoords[i].x, g_fVtxTxtCoords[i].y);
757         }
758         else
759         {
760             g_fVtxTxtCoords[i].x = (float)vert.tu;
761             g_fVtxTxtCoords[i].y = (float)vert.tv;
762         }
763     }
764 }
765 
PrepareTriangle(uint32_t dwV0,uint32_t dwV1,uint32_t dwV2)766 bool PrepareTriangle(uint32_t dwV0, uint32_t dwV1, uint32_t dwV2)
767 {
768    SP_Timing(SP_Each_Triangle);
769 
770    bool textureFlag = (CRender::g_pRender->IsTextureEnabled() || gRSP.ucode == 6 );
771 
772    InitVertex(dwV0, gRSP.numVertices, textureFlag);
773    InitVertex(dwV1, gRSP.numVertices+1, textureFlag);
774    InitVertex(dwV2, gRSP.numVertices+2, textureFlag);
775 
776         if(gRSP.numVertices == 0 && g_curRomInfo.bEnableTxtLOD && gRDP.otherMode.text_lod)
777         {
778             if( CRender::g_pRender->IsTexel1Enable() && CRender::g_pRender->m_pColorCombiner->m_pDecodedMux->IsUsed(MUX_LODFRAC, MUX_MASK) )
779             {
780                 ComputeLOD();
781             }
782             else
783             {
784                 gRDP.LODFrac = 0;
785             }
786         }
787 
788    gRSP.numVertices += 3;
789    status.dwNumTrisRendered++;
790 
791    return true;
792 }
793 
794 
795 
796 // Returns true if it thinks the triangle is visible
797 // Returns false if it is clipped
IsTriangleVisible(uint32_t dwV0,uint32_t dwV1,uint32_t dwV2)798 bool IsTriangleVisible(uint32_t dwV0, uint32_t dwV1, uint32_t dwV2)
799 {
800     //return true;  //fix me
801 
802     // Here we AND all the flags. If any of the bits is set for all
803     // 3 vertices, it means that all three x, y or z lie outside of
804     // the current viewing volume.
805     // Currently disabled - still seems a bit dodgy
806     if ((gRSP.bCullFront || gRSP.bCullBack) && gRDP.otherMode.zmode != 3)
807     {
808         XVECTOR4 & v0 = g_vecProjected[dwV0];
809         XVECTOR4 & v1 = g_vecProjected[dwV1];
810         XVECTOR4 & v2 = g_vecProjected[dwV2];
811 
812         // Only try to clip if the tri is onscreen. For some reason, this
813         // method doesn't work well when the z value is outside of screenspace
814         //if (v0.z < 1 && v1.z < 1 && v2.z < 1)
815         {
816            float V1 = v2.x - v0.x;
817            float V2 = v2.y - v0.y;
818 
819            float W1 = v2.x - v1.x;
820            float W2 = v2.y - v1.y;
821 
822            float fDirection = ((V1 * W2) - (V2 * W1)) * v1.w * v2.w * v0.w;
823 
824            if (fDirection < 0 && gRSP.bCullBack)
825            {
826               status.dwNumTrisClipped++;
827               return false;
828            }
829            else if (fDirection > 0 && gRSP.bCullFront)
830            {
831               status.dwNumTrisClipped++;
832               return false;
833            }
834         }
835     }
836 
837 #ifdef ENABLE_CLIP_TRI
838     //if( gRSP.bRejectVtx && (g_clipFlag[dwV0]|g_clipFlag[dwV1]|g_clipFlag[dwV2]) )
839     //  return;
840     if( g_clipFlag2[dwV0]&g_clipFlag2[dwV1]&g_clipFlag2[dwV2] )
841     {
842         //DebuggerAppendMsg("Clipped");
843         return false;
844     }
845 #endif
846 
847     return true;
848 }
849 
850 
SetPrimitiveColor(uint32_t dwCol,uint32_t LODMin,uint32_t LODFrac)851 void SetPrimitiveColor(uint32_t dwCol, uint32_t LODMin, uint32_t LODFrac)
852 {
853     gRDP.colorsAreReloaded = true;
854     gRDP.primitiveColor = dwCol;
855     gRDP.primLODMin = LODMin;
856     gRDP.primLODFrac = LODFrac;
857     if( gRDP.primLODFrac < gRDP.primLODMin )
858     {
859         gRDP.primLODFrac = gRDP.primLODMin;
860     }
861 
862     gRDP.fvPrimitiveColor[0] = ((dwCol>>16)&0xFF)/255.0f;  // R
863     gRDP.fvPrimitiveColor[1] = ((dwCol>>8)&0xFF)/255.0f;   // G
864     gRDP.fvPrimitiveColor[2] = ((dwCol)&0xFF)/255.0f;      // B
865     gRDP.fvPrimitiveColor[3] = ((dwCol>>24)&0xFF)/255.0f;  // A
866 }
867 
SetPrimitiveDepth(uint32_t z,uint32_t dwDZ)868 void SetPrimitiveDepth(uint32_t z, uint32_t dwDZ)
869 {
870     gRDP.primitiveDepth = z & 0x7FFF;
871     gRDP.fPrimitiveDepth = (float)(gRDP.primitiveDepth)/(float)0x8000;
872 
873     //gRDP.fPrimitiveDepth = gRDP.fPrimitiveDepth*2-1;
874     /*
875     z=0xFFFF    ->   1  the farthest
876     z=0         ->  -1  the nearest
877     */
878 
879     // TODO: How to use dwDZ?
880 }
881 
SetVertexXYZ(uint32_t vertex,float x,float y,float z)882 void SetVertexXYZ(uint32_t vertex, float x, float y, float z)
883 {
884     g_vecProjected[vertex].x = x;
885     g_vecProjected[vertex].y = y;
886     g_vecProjected[vertex].z = z;
887 
888     g_vtxTransformed[vertex].x = x*g_vtxTransformed[vertex].w;
889     g_vtxTransformed[vertex].y = y*g_vtxTransformed[vertex].w;
890     g_vtxTransformed[vertex].z = z*g_vtxTransformed[vertex].w;
891 }
892 
ProcessVertexDataDKR(uint32_t dwAddr,uint32_t dwV0,uint32_t dwNum)893 void ProcessVertexDataDKR(uint32_t dwAddr, uint32_t dwV0, uint32_t dwNum)
894 {
895     UpdateCombinedMatrix();
896 
897     uint8_t *rdram_u8 = (uint8_t*)gfx_info.RDRAM;
898     long long pVtxBase = (long long) (rdram_u8 + dwAddr);
899     g_pVtxBase = (FiddledVtx*)pVtxBase;
900 
901     Matrix &matWorldProject = gRSP.DKRMatrixes[gRSP.DKRCMatrixIndex];
902 
903     bool addbase=false;
904     if ((!gRSP.DKRBillBoard) || (gRSP.DKRCMatrixIndex != 2) )
905         addbase = false;
906     else
907         addbase = true;
908 
909     if( addbase && gRSP.DKRVtxCount == 0 && dwNum > 1 )
910         gRSP.DKRVtxCount++;
911 
912     int nOff = 0;
913     uint32_t end = dwV0 + dwNum;
914     for (uint32_t i = dwV0; i < end; i++)
915     {
916         XVECTOR3 w;
917 
918         g_vtxNonTransformed[i].x = (float)*(short*)((pVtxBase+nOff + 0) ^ 2);
919         g_vtxNonTransformed[i].y = (float)*(short*)((pVtxBase+nOff + 2) ^ 2);
920         g_vtxNonTransformed[i].z = (float)*(short*)((pVtxBase+nOff + 4) ^ 2);
921 
922         Vec3Transform(&g_vtxTransformed[i], (XVECTOR3*)&g_vtxNonTransformed[i], &matWorldProject);  // Convert to w=1
923 
924         if( gRSP.DKRVtxCount == 0 && dwNum==1 )
925         {
926             gRSP.DKRBaseVec.x = g_vtxTransformed[i].x;
927             gRSP.DKRBaseVec.y = g_vtxTransformed[i].y;
928             gRSP.DKRBaseVec.z = g_vtxTransformed[i].z;
929             gRSP.DKRBaseVec.w = g_vtxTransformed[i].w;
930         }
931         else if( addbase )
932         {
933             g_vtxTransformed[i].x += gRSP.DKRBaseVec.x;
934             g_vtxTransformed[i].y += gRSP.DKRBaseVec.y;
935             g_vtxTransformed[i].z += gRSP.DKRBaseVec.z;
936             g_vtxTransformed[i].w  = gRSP.DKRBaseVec.w;
937         }
938 
939         g_vecProjected[i].w = 1.0f / g_vtxTransformed[i].w;
940         g_vecProjected[i].x = g_vtxTransformed[i].x * g_vecProjected[i].w;
941         g_vecProjected[i].y = g_vtxTransformed[i].y * g_vecProjected[i].w;
942         g_vecProjected[i].z = g_vtxTransformed[i].z * g_vecProjected[i].w;
943 
944         gRSP.DKRVtxCount++;
945 
946         if( gRSP.bFogEnabled )
947         {
948             g_fFogCoord[i] = g_vecProjected[i].z;
949             if( g_vecProjected[i].w < 0 || g_vecProjected[i].z < 0 || g_fFogCoord[i] < gRSPfFogMin )
950                 g_fFogCoord[i] = gRSPfFogMin;
951         }
952 
953         RSP_Vtx_Clipping(i);
954 
955         short wA = *(short*)((pVtxBase+nOff + 6) ^ 2);
956         short wB = *(short*)((pVtxBase+nOff + 8) ^ 2);
957 
958         int8_t r = (int8_t)(wA >> 8);
959         int8_t g = (int8_t)(wA);
960         int8_t b = (int8_t)(wB >> 8);
961         int8_t a = (int8_t)(wB);
962 
963         if (gRSP.bLightingEnable)
964         {
965             g_normal.x = (char)r; //norma.nx;
966             g_normal.y = (char)g; //norma.ny;
967             g_normal.z = (char)b; //norma.nz;
968 
969             Vec3TransformNormal(g_normal, matWorldProject)
970                 g_dwVtxDifColor[i] = LightVert(g_normal, i);
971         }
972         else   // Assign true vert colour after lighting/fogging
973             g_dwVtxDifColor[i] = COLOR_RGBA(r, g, b, a);
974 
975         ReplaceAlphaWithFogFactor(i);
976 
977         g_fVtxTxtCoords[i].x = g_fVtxTxtCoords[i].y = 1;
978 
979         nOff += 10;
980     }
981 }
982 
983 extern uint32_t dwPDCIAddr;
984 extern uint32_t dwConkerVtxZAddr;
985 
ProcessVertexDataConker(uint32_t dwAddr,uint32_t dwV0,uint32_t dwNum)986 void ProcessVertexDataConker(uint32_t dwAddr, uint32_t dwV0, uint32_t dwNum)
987 {
988     UpdateCombinedMatrix();
989 
990     uint8_t *rdram_u8 = (uint8_t*)gfx_info.RDRAM;
991     FiddledVtx * pVtxBase = (FiddledVtx*)(rdram_u8 + dwAddr);
992     g_pVtxBase = pVtxBase;
993 
994     for (uint32_t i = dwV0; i < dwV0 + dwNum; i++)
995     {
996         SP_Timing(RSP_GBI0_Vtx);
997 
998         FiddledVtx & vert = pVtxBase[i - dwV0];
999 
1000         g_vtxNonTransformed[i].x = (float)vert.x;
1001         g_vtxNonTransformed[i].y = (float)vert.y;
1002         g_vtxNonTransformed[i].z = (float)vert.z;
1003 
1004         {
1005             Vec3Transform(&g_vtxTransformed[i], (XVECTOR3*)&g_vtxNonTransformed[i], &gRSPworldProject); // Convert to w=1
1006             g_vecProjected[i].w = 1.0f / g_vtxTransformed[i].w;
1007             g_vecProjected[i].x = g_vtxTransformed[i].x * g_vecProjected[i].w;
1008             g_vecProjected[i].y = g_vtxTransformed[i].y * g_vecProjected[i].w;
1009             g_vecProjected[i].z = g_vtxTransformed[i].z * g_vecProjected[i].w;
1010         }
1011 
1012         g_fFogCoord[i] = g_vecProjected[i].z;
1013         if( g_vecProjected[i].w < 0 || g_vecProjected[i].z < 0 || g_fFogCoord[i] < gRSPfFogMin )
1014             g_fFogCoord[i] = gRSPfFogMin;
1015 
1016         RSP_Vtx_Clipping(i);
1017 
1018         if( gRSP.bLightingEnable )
1019         {
1020             {
1021                 uint32_t r= ((gRSP.ambientLightColor>>16)&0xFF);
1022                 uint32_t g= ((gRSP.ambientLightColor>> 8)&0xFF);
1023                 uint32_t b= ((gRSP.ambientLightColor    )&0xFF);
1024                 for( uint32_t k=1; k<= gSP.numLights; k++)
1025                 {
1026                     r += gRSPlights[k].r;
1027                     g += gRSPlights[k].g;
1028                     b += gRSPlights[k].b;
1029                 }
1030                 if( r>255 ) r=255;
1031                 if( g>255 ) g=255;
1032                 if( b>255 ) b=255;
1033                 r *= vert.rgba.r ;
1034                 g *= vert.rgba.g ;
1035                 b *= vert.rgba.b ;
1036                 r >>= 8;
1037                 g >>= 8;
1038                 b >>= 8;
1039                 g_dwVtxDifColor[i] = 0xFF000000;
1040                 g_dwVtxDifColor[i] |= (r<<16);
1041                 g_dwVtxDifColor[i] |= (g<< 8);
1042                 g_dwVtxDifColor[i] |= (b    );
1043             }
1044 
1045             *(((uint8_t*)&(g_dwVtxDifColor[i]))+3) = vert.rgba.a; // still use alpha from the vertex
1046         }
1047         else
1048         {
1049             if( (gSP.geometryMode & G_SHADE) == 0 && gRSP.ucode < 5 )  //Shade is disabled
1050                 g_dwVtxDifColor[i] = gRDP.primitiveColor;
1051             else    //FLAT shade
1052                 g_dwVtxDifColor[i] = COLOR_RGBA(vert.rgba.r, vert.rgba.g, vert.rgba.b, vert.rgba.a);
1053         }
1054 
1055         if( options.bWinFrameMode )
1056         {
1057             //g_vecProjected[i].z = 0;
1058             g_dwVtxDifColor[i] = COLOR_RGBA(vert.rgba.r, vert.rgba.g, vert.rgba.b, vert.rgba.a);
1059         }
1060 
1061         ReplaceAlphaWithFogFactor(i);
1062 
1063         // Update texture coords n.b. need to divide tu/tv by bogus scale on addition to buffer
1064         //VECTOR2 & t = g_fVtxTxtCoords[i];
1065 
1066         // If the vert is already lit, then there is no normal (and hence we
1067         // can't generate tex coord)
1068         if (gRSP.bTextureGen && gRSP.bLightingEnable )
1069         {
1070                 g_normal.x = (float)*(int8_t*)(rdram_u8 + (((i<<1)+0)^3)+dwConkerVtxZAddr);
1071                 g_normal.y = (float)*(int8_t*)(rdram_u8 + (((i<<1)+1)^3)+dwConkerVtxZAddr);
1072                 g_normal.z = (float)*(int8_t*)(rdram_u8 + (((i<<1)+2)^3)+dwConkerVtxZAddr);
1073                 Vec3TransformNormal(g_normal, gRSPmodelViewTop);
1074                 TexGen(g_fVtxTxtCoords[i].x, g_fVtxTxtCoords[i].y);
1075         }
1076         else
1077         {
1078             g_fVtxTxtCoords[i].x = (float)vert.tu;
1079             g_fVtxTxtCoords[i].y = (float)vert.tv;
1080         }
1081     }
1082 }
1083 
1084 
1085 typedef struct
1086 {
1087     short y;
1088     short x;
1089     short flag;
1090     short z;
1091 } RS_Vtx_XYZ;
1092 
1093 typedef union
1094 {
1095     struct
1096     {
1097         uint8_t a;
1098         uint8_t b;
1099         uint8_t g;
1100         uint8_t r;
1101     };
1102 
1103     struct
1104     {
1105         char na;    // A
1106         char nz;    // B
1107         char ny;    // G
1108         char nx;    // R
1109     };
1110 } RS_Vtx_Color;
1111 
1112 
ProcessVertexData_Rogue_Squadron(uint32_t dwXYZAddr,uint32_t dwColorAddr,uint32_t dwXYZCmd,uint32_t dwColorCmd)1113 void ProcessVertexData_Rogue_Squadron(uint32_t dwXYZAddr, uint32_t dwColorAddr, uint32_t dwXYZCmd, uint32_t dwColorCmd)
1114 {
1115     UpdateCombinedMatrix();
1116 
1117     uint8_t *rdram_u8 = (uint8_t*)gfx_info.RDRAM;
1118     uint32_t dwV0 = 0;
1119     uint32_t dwNum = (dwXYZCmd&0xFF00)>>10;
1120 
1121     RS_Vtx_XYZ * pVtxXYZBase = (RS_Vtx_XYZ*)(rdram_u8 + dwXYZAddr);
1122     RS_Vtx_Color * pVtxColorBase = (RS_Vtx_Color*)(rdram_u8 + dwColorAddr);
1123 
1124     for (uint32_t i = dwV0; i < dwV0 + dwNum; i++)
1125     {
1126         RS_Vtx_XYZ & vertxyz = pVtxXYZBase[i - dwV0];
1127         RS_Vtx_Color & vertcolors = pVtxColorBase[i - dwV0];
1128 
1129         g_vtxNonTransformed[i].x = (float)vertxyz.x;
1130         g_vtxNonTransformed[i].y = (float)vertxyz.y;
1131         g_vtxNonTransformed[i].z = (float)vertxyz.z;
1132 
1133         {
1134             Vec3Transform(&g_vtxTransformed[i], (XVECTOR3*)&g_vtxNonTransformed[i], &gRSPworldProject); // Convert to w=1
1135             g_vecProjected[i].w = 1.0f / g_vtxTransformed[i].w;
1136             g_vecProjected[i].x = g_vtxTransformed[i].x * g_vecProjected[i].w;
1137             g_vecProjected[i].y = g_vtxTransformed[i].y * g_vecProjected[i].w;
1138             g_vecProjected[i].z = g_vtxTransformed[i].z * g_vecProjected[i].w;
1139         }
1140 
1141         g_fFogCoord[i] = g_vecProjected[i].z;
1142         if( g_vecProjected[i].w < 0 || g_vecProjected[i].z < 0 || g_fFogCoord[i] < gRSPfFogMin )
1143             g_fFogCoord[i] = gRSPfFogMin;
1144 
1145         RSP_Vtx_Clipping(i);
1146 
1147         if( gRSP.bLightingEnable )
1148         {
1149             g_normal.x = (float)vertcolors.nx;
1150             g_normal.y = (float)vertcolors.ny;
1151             g_normal.z = (float)vertcolors.nz;
1152 
1153             {
1154                 Vec3TransformNormal(g_normal, gRSPmodelViewTop);
1155                 g_dwVtxDifColor[i] = LightVert(g_normal, i);
1156             }
1157             *(((uint8_t*)&(g_dwVtxDifColor[i]))+3) = vertcolors.a;    // still use alpha from the vertex
1158         }
1159         else
1160         {
1161             if( (gSP.geometryMode & G_SHADE) == 0 && gRSP.ucode < 5 )  //Shade is disabled
1162             {
1163                 g_dwVtxDifColor[i] = gRDP.primitiveColor;
1164             }
1165             else    //FLAT shade
1166             {
1167                 g_dwVtxDifColor[i] = COLOR_RGBA(vertcolors.r, vertcolors.g, vertcolors.b, vertcolors.a);
1168             }
1169         }
1170 
1171         if( options.bWinFrameMode )
1172         {
1173             g_dwVtxDifColor[i] = COLOR_RGBA(vertcolors.r, vertcolors.g, vertcolors.b, vertcolors.a);
1174         }
1175 
1176         ReplaceAlphaWithFogFactor(i);
1177 
1178         /*
1179         // Update texture coords n.b. need to divide tu/tv by bogus scale on addition to buffer
1180         VECTOR2 & t = g_fVtxTxtCoords[i];
1181 
1182         // If the vert is already lit, then there is no normal (and hence we
1183         // can't generate tex coord)
1184         if (gRSP.bTextureGen && gRSP.bLightingEnable && g_textures[gRSP.curTile].m_bTextureEnable )
1185         {
1186             TexGen(g_fVtxTxtCoords[i].x, g_fVtxTxtCoords[i].y);
1187         }
1188         else
1189         {
1190             t.x = (float)vert.tu;
1191             t.y = (float)vert.tv;
1192         }
1193         */
1194     }
1195 }
1196 
SetLightDirection(uint32_t dwLight,float x,float y,float z,float range)1197 void SetLightDirection(uint32_t dwLight, float x, float y, float z, float range)
1198 {
1199     float w = 1;
1200     //gRSP.bLightIsUpdated = true;
1201 
1202     //gRSPlights[dwLight].ox = x;
1203     //gRSPlights[dwLight].oy = y;
1204     //gRSPlights[dwLight].oz = z;
1205 
1206     if (range == 0)
1207        w = (float)sqrt(x*x+y*y+z*z);
1208 
1209     gRSPlights[dwLight].x = x/w;
1210     gRSPlights[dwLight].y = y/w;
1211     gRSPlights[dwLight].z = z/w;
1212     gRSPlights[dwLight].range = range;
1213 }
1214 
1215 static float maxS0, maxT0;
1216 static float maxS1, maxT1;
1217 static bool validS0, validT0;
1218 static bool validS1, validT1;
1219 
LogTextureCoords(float fTex0S,float fTex0T,float fTex1S,float fTex1T)1220 void LogTextureCoords(float fTex0S, float fTex0T, float fTex1S, float fTex1T)
1221 {
1222     if( validS0 )
1223     {
1224         if( fTex0S<0 || fTex0S>maxS0 )  validS0 = false;
1225     }
1226     if( validT0 )
1227     {
1228         if( fTex0T<0 || fTex0T>maxT0 )  validT0 = false;
1229     }
1230     if( validS1 )
1231     {
1232         if( fTex1S<0 || fTex1S>maxS1 )  validS1 = false;
1233     }
1234     if( validT1 )
1235     {
1236         if( fTex1T<0 || fTex1T>maxT1 )  validT1 = false;
1237     }
1238 }
1239 
CheckTextureCoords(int tex)1240 bool CheckTextureCoords(int tex)
1241 {
1242     if( tex==0 )
1243         return validS0&&validT0;
1244 
1245     return validS1&&validT1;
1246 }
1247 
ResetTextureCoordsLog(float maxs0,float maxt0,float maxs1,float maxt1)1248 void ResetTextureCoordsLog(float maxs0, float maxt0, float maxs1, float maxt1)
1249 {
1250     maxS0 = maxs0;
1251     maxT0 = maxt0;
1252     maxS1 = maxs1;
1253     maxT1 = maxt1;
1254     validS0 = validT0 = true;
1255     validS1 = validT1 = true;
1256 }
1257 
ForceMainTextureIndex(int dwTile)1258 void ForceMainTextureIndex(int dwTile)
1259 {
1260    // Hack
1261    if( dwTile == 1 && !(CRender::g_pRender->IsTexel0Enable()) && CRender::g_pRender->IsTexel1Enable() )
1262       gRSP.curTile = 0;
1263    else
1264       gRSP.curTile = dwTile;
1265 }
1266 
HackZ2(float z)1267 float HackZ2(float z)
1268 {
1269     z = (z+9)/10;
1270     return z;
1271 }
1272 
HackZ(float z)1273 float HackZ(float z)
1274 {
1275    /* TODO - investigate
1276     * should we just do this instead?
1277     * z = HackZ2(z);
1278     */
1279     return HackZ2(z);
1280 
1281     if( z < 0.1 && z >= 0 )
1282         z = (.1f+z)/2;
1283     else if( z < 0 )
1284         //return (10+z)/100;
1285         z = (expf(z)/20);
1286     return z;
1287 }
1288 
HackZ(std::vector<XVECTOR3> & points)1289 void HackZ(std::vector<XVECTOR3>& points)
1290 {
1291     int size = points.size();
1292     for( int i=0; i<size; i++)
1293     {
1294         XVECTOR3 &v = points[i];
1295         v.z = (float)HackZ(v.z);
1296     }
1297 }
1298 
HackZAll()1299 void HackZAll()
1300 {
1301     if( CDeviceBuilder::m_deviceGeneralType == DIRECTX_DEVICE )
1302     {
1303         for( uint32_t i=0; i<gRSP.numVertices; i++)
1304             g_vtxBuffer[i].z = HackZ(g_vtxBuffer[i].z);
1305     }
1306     else
1307     {
1308         for( uint32_t i=0; i<gRSP.numVertices; i++)
1309         {
1310             float w = g_vtxProjected5[i][3];
1311             g_vtxProjected5[i][2] = HackZ(g_vtxProjected5[i][2]/w)*w;
1312         }
1313     }
1314 }
1315 
1316 
1317 extern XMATRIX reverseXY;
1318 extern XMATRIX reverseY;
1319 
UpdateCombinedMatrix()1320 void UpdateCombinedMatrix()
1321 {
1322     if( gRSP.bMatrixIsUpdated )
1323     {
1324         gRSPworldProject = gRSP.modelviewMtxs[gRSP.modelViewMtxTop] * gRSP.projectionMtxs[gRSP.projectionMtxTop];
1325         gRSP.bMatrixIsUpdated = false;
1326         gRSP.bCombinedMatrixIsUpdated = true;
1327     }
1328 
1329     if( gRSP.bCombinedMatrixIsUpdated )
1330     {
1331         if( options.enableHackForGames == HACK_REVERSE_XY_COOR )
1332             gRSPworldProject = gRSPworldProject * reverseXY;
1333         if( options.enableHackForGames == HACK_REVERSE_Y_COOR )
1334             gRSPworldProject = gRSPworldProject * reverseY;
1335         gRSP.bCombinedMatrixIsUpdated = false;
1336     }
1337 
1338     //if( gRSP.bWorldMatrixIsUpdated || gRSP.bLightIsUpdated )
1339     //{
1340     //  // Update lights with transported world matrix
1341     //  for( unsigned int l=0; l< gSP.numLights; l++)
1342     //  {
1343     //      Vec3TransformCoord(&gRSPlights[l].td, &gRSPlights[l].od, &gRSPmodelViewTopTranspose);
1344     //      Vec3Normalize(&gRSPlights[l].td,&gRSPlights[l].td);
1345     //  }
1346 
1347     //  gRSP.bWorldMatrixIsUpdated = false;
1348     //  gRSP.bLightIsUpdated = false;
1349     //}
1350 }
1351 
1352