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