Rice Video Plugin for GLES1.1
[mupen64plus-pandora.git] / source / rice_gles / src / RSP_GBI0.h
CommitLineData
d07c171f 1/*
2Copyright (C) 2002 Rice1964
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18*/
19
20#include <cmath>
21#include "Render.h"
22#include "Timing.h"
23
24void RSP_GBI1_SpNoop(Gfx *gfx)
25{
26 SP_Timing(RSP_GBI1_SpNoop);
27
28 if( (gfx+1)->words.cmd == 0x00 && gRSP.ucode >= 17 )
29 {
30 RSP_RDP_NOIMPL("Double SPNOOP, Skip remain ucodes, PC=%08X, Cmd1=%08X", gDlistStack[gDlistStackPointer].pc, gfx->words.w1);
31 RDP_GFX_PopDL();
32 //if( gRSP.ucode < 17 ) TriggerDPInterrupt();
33 }
34}
35
36void RSP_GBI0_Mtx(Gfx *gfx)
37{
38 SP_Timing(RSP_GBI0_Mtx);
39
40 uint32 addr = RSPSegmentAddr((gfx->gbi0matrix.addr));
41
42 LOG_UCODE(" Command: %s %s %s Length %d Address 0x%08x",
43 gfx->gbi0matrix.projection == 1 ? "Projection" : "ModelView",
44 gfx->gbi0matrix.load == 1 ? "Load" : "Mul",
45 gfx->gbi0matrix.push == 1 ? "Push" : "NoPush",
46 gfx->gbi0matrix.len, addr);
47
48 if (addr + 64 > g_dwRamSize)
49 {
50 TRACE1("Mtx: Address invalid (0x%08x)", addr);
51 return;
52 }
53
54 LoadMatrix(addr);
55
56 if (gfx->gbi0matrix.projection)
57 {
58 CRender::g_pRender->SetProjection(matToLoad, gfx->gbi0matrix.push, gfx->gbi0matrix.load);
59 }
60 else
61 {
62 CRender::g_pRender->SetWorldView(matToLoad, gfx->gbi0matrix.push, gfx->gbi0matrix.load);
63 }
64
65#ifdef DEBUGGER
66 const char *loadstr = gfx->gbi0matrix.load == 1 ? "Load" : "Mul";
67 const char *pushstr = gfx->gbi0matrix.push == 1 ? "Push" : "Nopush";
68 int projlevel = CRender::g_pRender->GetProjectMatrixLevel();
69 int worldlevel = CRender::g_pRender->GetWorldViewMatrixLevel();
70 if( pauseAtNext && eventToPause == NEXT_MATRIX_CMD )
71 {
72 pauseAtNext = false;
73 debuggerPause = true;
74 if (gfx->gbi0matrix.projection)
75 {
76 TRACE3("Pause after %s and %s Matrix: Projection, level=%d\n", loadstr, pushstr, projlevel );
77 }
78 else
79 {
80 TRACE3("Pause after %s and %s Matrix: WorldView level=%d\n", loadstr, pushstr, worldlevel);
81 }
82 }
83 else
84 {
85 if( pauseAtNext && logMatrix )
86 {
87 if (gfx->gbi0matrix.projection)
88 {
89 TRACE3("Matrix: %s and %s Projection level=%d\n", loadstr, pushstr, projlevel);
90 }
91 else
92 {
93 TRACE3("Matrix: %s and %s WorldView\n level=%d", loadstr, pushstr, worldlevel);
94 }
95 }
96 }
97#endif
98}
99
100
101void RSP_GBI1_Reserved(Gfx *gfx)
102{
103 SP_Timing(RSP_GBI1_Reserved);
104 RSP_RDP_NOIMPL("RDP: Reserved (0x%08x 0x%08x)", (gfx->words.w0), (gfx->words.w1));
105}
106
107
108void RSP_GBI1_MoveMem(Gfx *gfx)
109{
110 SP_Timing(RSP_GBI1_MoveMem);
111
112 uint32 type = ((gfx->words.w0)>>16)&0xFF;
113 uint32 dwLength = ((gfx->words.w0))&0xFFFF;
114 uint32 addr = RSPSegmentAddr((gfx->words.w1));
115
116 switch (type)
117 {
118 case RSP_GBI1_MV_MEM_VIEWPORT:
119 {
120 LOG_UCODE(" RSP_GBI1_MV_MEM_VIEWPORT. Address: 0x%08x, Length: 0x%04x", addr, dwLength);
121 RSP_MoveMemViewport(addr);
122 }
123 break;
124 case RSP_GBI1_MV_MEM_LOOKATY:
125 LOG_UCODE(" RSP_GBI1_MV_MEM_LOOKATY");
126 break;
127 case RSP_GBI1_MV_MEM_LOOKATX:
128 LOG_UCODE(" RSP_GBI1_MV_MEM_LOOKATX");
129 break;
130 case RSP_GBI1_MV_MEM_L0:
131 case RSP_GBI1_MV_MEM_L1:
132 case RSP_GBI1_MV_MEM_L2:
133 case RSP_GBI1_MV_MEM_L3:
134 case RSP_GBI1_MV_MEM_L4:
135 case RSP_GBI1_MV_MEM_L5:
136 case RSP_GBI1_MV_MEM_L6:
137 case RSP_GBI1_MV_MEM_L7:
138 {
139 uint32 dwLight = (type-RSP_GBI1_MV_MEM_L0)/2;
140 LOG_UCODE(" RSP_GBI1_MV_MEM_L%d", dwLight);
141 LOG_UCODE(" Light%d: Length:0x%04x, Address: 0x%08x", dwLight, dwLength, addr);
142
143 RSP_MoveMemLight(dwLight, addr);
144 }
145 break;
146 case RSP_GBI1_MV_MEM_TXTATT:
147 LOG_UCODE(" RSP_GBI1_MV_MEM_TXTATT");
148 break;
149 case RSP_GBI1_MV_MEM_MATRIX_1:
150 RSP_GFX_Force_Matrix(addr);
151 break;
152 case RSP_GBI1_MV_MEM_MATRIX_2:
153 break;
154 case RSP_GBI1_MV_MEM_MATRIX_3:
155 break;
156 case RSP_GBI1_MV_MEM_MATRIX_4:
157 break;
158 default:
159 RSP_RDP_NOIMPL("MoveMem: Unknown Move Type, cmd=%08X, %08X", gfx->words.w0, gfx->words.w1);
160 break;
161 }
162}
163
164
165void RSP_GBI0_Vtx(Gfx *gfx)
166{
167 SP_Timing(RSP_GBI0_Vtx);
168
169 int n = gfx->gbi0vtx.n + 1;
170 int v0 = gfx->gbi0vtx.v0;
171 uint32 addr = RSPSegmentAddr((gfx->gbi0vtx.addr));
172
173 LOG_UCODE(" Address 0x%08x, v0: %d, Num: %d, Length: 0x%04x", addr, v0, n, gfx->gbi0vtx.len);
174
175 if ((v0 + n) > 80)
176 {
177 TRACE3("Warning, invalid vertex positions, N=%d, v0=%d, Addr=0x%08X", n, v0, addr);
178 n = 32 - v0;
179 }
180
181 // Check that address is valid...
182 if ((addr + n*16) > g_dwRamSize)
183 {
184 TRACE1("Vertex Data: Address out of range (0x%08x)", addr);
185 }
186 else
187 {
188 ProcessVertexData(addr, v0, n);
189 status.dwNumVertices += n;
190 DisplayVertexInfo(addr, v0, n);
191 }
192}
193
194
195void RSP_GBI0_DL(Gfx *gfx)
196{
197 SP_Timing(RSP_GBI0_DL);
198
199 uint32 addr = RSPSegmentAddr((gfx->gbi0dlist.addr)) & (g_dwRamSize-1);
200
201 LOG_UCODE(" Address=0x%08x Push: 0x%02x", addr, gfx->gbi0dlist.param);
202 if( addr > g_dwRamSize )
203 {
204 RSP_RDP_NOIMPL("Error: DL addr = %08X out of range, PC=%08X", addr, gDlistStack[gDlistStackPointer].pc );
205 addr &= (g_dwRamSize-1);
206 DebuggerPauseCountN( NEXT_DLIST );
207 }
208
209 if( gfx->gbi0dlist.param == RSP_DLIST_PUSH )
210 gDlistStackPointer++;
211
212 gDlistStack[gDlistStackPointer].pc = addr;
213 gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT;
214
215 LOG_UCODE("Level=%d", gDlistStackPointer+1);
216 LOG_UCODE("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
217}
218
219
220void RSP_GBI1_RDPHalf_Cont(Gfx *gfx)
221{
222 SP_Timing(RSP_GBI1_RDPHalf_Cont);
223
224 LOG_UCODE("RDPHalf_Cont: (Ignored)");
225}
226void RSP_GBI1_RDPHalf_2(Gfx *gfx)
227{
228 SP_Timing(RSP_GBI1_RDPHalf_2);
229
230 LOG_UCODE("RDPHalf_2: (Ignored)");
231}
232
233void RSP_GBI1_RDPHalf_1(Gfx *gfx)
234{
235 SP_Timing(RSP_GBI1_RDPHalf_1);
236
237 LOG_UCODE("RDPHalf_1: (Ignored)");
238}
239
240void RSP_GBI1_Line3D(Gfx *gfx)
241{
242 status.primitiveType = PRIM_LINE3D;
243
244 uint32 dwPC = gDlistStack[gDlistStackPointer].pc;
245
246 BOOL bTrisAdded = FALSE;
247
248 if( gfx->ln3dtri2.v3 == 0 )
249 {
250 // Flying Dragon
251 uint32 dwV0 = gfx->ln3dtri2.v0/gRSP.vertexMult;
252 uint32 dwV1 = gfx->ln3dtri2.v1/gRSP.vertexMult;
253 uint32 dwWidth = gfx->ln3dtri2.v2;
254 //uint32 dwFlag = gfx->ln3dtri2.v3/gRSP.vertexMult;
255
256 CRender::g_pRender->SetCombinerAndBlender();
257
258 status.dwNumTrisRendered++;
259
260 CRender::g_pRender->Line3D(dwV0, dwV1, dwWidth);
261 SP_Timing(RSP_GBI1_Line3D);
262 DP_Timing(RSP_GBI1_Line3D);
263 }
264 else
265 {
266 do {
267 uint32 dwV3 = gfx->ln3dtri2.v3/gRSP.vertexMult;
268 uint32 dwV0 = gfx->ln3dtri2.v0/gRSP.vertexMult;
269 uint32 dwV1 = gfx->ln3dtri2.v1/gRSP.vertexMult;
270 uint32 dwV2 = gfx->ln3dtri2.v2/gRSP.vertexMult;
271
272 LOG_UCODE(" Line3D: V0: %d, V1: %d, V2: %d, V3: %d", dwV0, dwV1, dwV2, dwV3);
273
274 // Do first tri
275 if (IsTriangleVisible(dwV0, dwV1, dwV2))
276 {
277 DEBUG_DUMP_VERTEXES("Line3D 1/2", dwV0, dwV1, dwV2);
278 if (!bTrisAdded && CRender::g_pRender->IsTextureEnabled())
279 {
280 PrepareTextures();
281 InitVertexTextureConstants();
282 }
283
284 if( !bTrisAdded )
285 {
286 CRender::g_pRender->SetCombinerAndBlender();
287 }
288
289 bTrisAdded = true;
290 PrepareTriangle(dwV0, dwV1, dwV2);
291 }
292
293 // Do second tri
294 if (IsTriangleVisible(dwV2, dwV3, dwV0))
295 {
296 DEBUG_DUMP_VERTEXES("Line3D 2/2", dwV0, dwV1, dwV2);
297 if (!bTrisAdded && CRender::g_pRender->IsTextureEnabled())
298 {
299 PrepareTextures();
300 InitVertexTextureConstants();
301 }
302
303 if( !bTrisAdded )
304 {
305 CRender::g_pRender->SetCombinerAndBlender();
306 }
307
308 bTrisAdded = true;
309 PrepareTriangle(dwV2, dwV3, dwV0);
310 }
311
312 gfx++;
313 dwPC += 8;
314#ifdef DEBUGGER
315 } while (gfx->words.cmd == (uint8)RSP_LINE3D && !(pauseAtNext && eventToPause==NEXT_FLUSH_TRI));
316#else
317 } while (gfx->words.cmd == (uint8)RSP_LINE3D);
318#endif
319
320 gDlistStack[gDlistStackPointer].pc = dwPC-8;
321
322 if (bTrisAdded)
323 {
324 CRender::g_pRender->DrawTriangles();
325 }
326 }
327}
328
329
330void RSP_GBI1_ClearGeometryMode(Gfx *gfx)
331{
332 SP_Timing(RSP_GBI1_ClearGeometryMode);
333 uint32 dwMask = ((gfx->words.w1));
334
335#ifdef DEBUGGER
336 LOG_UCODE(" Mask=0x%08x", dwMask);
337 if (dwMask & G_ZBUFFER) LOG_UCODE(" Disabling ZBuffer");
338 if (dwMask & G_TEXTURE_ENABLE) LOG_UCODE(" Disabling Texture");
339 if (dwMask & G_SHADE) LOG_UCODE(" Disabling Shade");
340 if (dwMask & G_SHADING_SMOOTH) LOG_UCODE(" Disabling Smooth Shading");
341 if (dwMask & G_CULL_FRONT) LOG_UCODE(" Disabling Front Culling");
342 if (dwMask & G_CULL_BACK) LOG_UCODE(" Disabling Back Culling");
343 if (dwMask & G_FOG) LOG_UCODE(" Disabling Fog");
344 if (dwMask & G_LIGHTING) LOG_UCODE(" Disabling Lighting");
345 if (dwMask & G_TEXTURE_GEN) LOG_UCODE(" Disabling Texture Gen");
346 if (dwMask & G_TEXTURE_GEN_LINEAR) LOG_UCODE(" Disabling Texture Gen Linear");
347 if (dwMask & G_LOD) LOG_UCODE(" Disabling LOD (no impl)");
348#endif
349
350 gRDP.geometryMode &= ~dwMask;
351 RSP_GFX_InitGeometryMode();
352}
353
354
355
356void RSP_GBI1_SetGeometryMode(Gfx *gfx)
357{
358 SP_Timing(RSP_GBI1_SetGeometryMode);
359 uint32 dwMask = ((gfx->words.w1));
360
361#ifdef DEBUGGER
362 LOG_UCODE(" Mask=0x%08x", dwMask);
363 if (dwMask & G_ZBUFFER) LOG_UCODE(" Enabling ZBuffer");
364 if (dwMask & G_TEXTURE_ENABLE) LOG_UCODE(" Enabling Texture");
365 if (dwMask & G_SHADE) LOG_UCODE(" Enabling Shade");
366 if (dwMask & G_SHADING_SMOOTH) LOG_UCODE(" Enabling Smooth Shading");
367 if (dwMask & G_CULL_FRONT) LOG_UCODE(" Enabling Front Culling");
368 if (dwMask & G_CULL_BACK) LOG_UCODE(" Enabling Back Culling");
369 if (dwMask & G_FOG) LOG_UCODE(" Enabling Fog");
370 if (dwMask & G_LIGHTING) LOG_UCODE(" Enabling Lighting");
371 if (dwMask & G_TEXTURE_GEN) LOG_UCODE(" Enabling Texture Gen");
372 if (dwMask & G_TEXTURE_GEN_LINEAR) LOG_UCODE(" Enabling Texture Gen Linear");
373 if (dwMask & G_LOD) LOG_UCODE(" Enabling LOD (no impl)");
374#endif // DEBUGGER
375 gRDP.geometryMode |= dwMask;
376 RSP_GFX_InitGeometryMode();
377}
378
379
380void RSP_GBI1_EndDL(Gfx *gfx)
381{
382 SP_Timing(RSP_GBI1_EndDL);
383 RDP_GFX_PopDL();
384}
385
386
387//static const char * sc_szBlClr[4] = { "In", "Mem", "Bl", "Fog" };
388//static const char * sc_szBlA1[4] = { "AIn", "AFog", "AShade", "0" };
389//static const char * sc_szBlA2[4] = { "1-A", "AMem", "1", "?" };
390
391void RSP_GBI1_SetOtherModeL(Gfx *gfx)
392{
393 SP_Timing(RSP_GBI1_SetOtherModeL);
394
395 uint32 dwShift = ((gfx->words.w0)>>8)&0xFF;
396 uint32 dwLength= ((gfx->words.w0) )&0xFF;
397 uint32 dwData = (gfx->words.w1);
398
399 uint32 dwMask = ((1<<dwLength)-1)<<dwShift;
400
401 uint32 modeL = gRDP.otherModeL;
402 modeL = (modeL&(~dwMask)) | dwData;
403
404 Gfx tempgfx;
405 tempgfx.words.w0 = gRDP.otherModeH;
406 tempgfx.words.w1 = modeL;
407 DLParser_RDPSetOtherMode(&tempgfx);
408}
409
410
411void RSP_GBI1_SetOtherModeH(Gfx *gfx)
412{
413 SP_Timing(RSP_GBI1_SetOtherModeH);
414
415 uint32 dwShift = ((gfx->words.w0)>>8)&0xFF;
416 uint32 dwLength= ((gfx->words.w0) )&0xFF;
417 uint32 dwData = (gfx->words.w1);
418
419 uint32 dwMask = ((1<<dwLength)-1)<<dwShift;
420 uint32 dwModeH = gRDP.otherModeH;
421
422 dwModeH = (dwModeH&(~dwMask)) | dwData;
423 Gfx tempgfx;
424 tempgfx.words.w0 = dwModeH;
425 tempgfx.words.w1 = gRDP.otherModeL;
426 DLParser_RDPSetOtherMode(&tempgfx );
427}
428
429
430void RSP_GBI1_Texture(Gfx *gfx)
431{
432 SP_Timing(RSP_GBI1_Texture);
433
434 float fTextureScaleS = (float)(gfx->texture.scaleS) / (65536.0f * 32.0f);
435 float fTextureScaleT = (float)(gfx->texture.scaleT) / (65536.0f * 32.0f);
436
437 if( (((gfx->words.w1)>>16)&0xFFFF) == 0xFFFF )
438 {
439 fTextureScaleS = 1/32.0f;
440 }
441 else if( (((gfx->words.w1)>>16)&0xFFFF) == 0x8000 )
442 {
443 fTextureScaleS = 1/64.0f;
444 }
445#ifdef DEBUGGER
446 else if( ((gfx->words.w1>>16)&0xFFFF) != 0 )
447 {
448 //DebuggerAppendMsg("Warning, texture scale = %08X is not integer", (word1>>16)&0xFFFF);
449 }
450#endif
451
452 if( (((gfx->words.w1) )&0xFFFF) == 0xFFFF )
453 {
454 fTextureScaleT = 1/32.0f;
455 }
456 else if( (((gfx->words.w1) )&0xFFFF) == 0x8000 )
457 {
458 fTextureScaleT = 1/64.0f;
459 }
460#ifdef DEBUGGER
461 else if( (gfx->words.w1&0xFFFF) != 0 )
462 {
463 //DebuggerAppendMsg("Warning, texture scale = %08X is not integer", (word1)&0xFFFF);
464 }
465#endif
466
467 if( gRSP.ucode == 6 )
468 {
469 if( fTextureScaleS == 0 ) fTextureScaleS = 1.0f/32.0f;
470 if( fTextureScaleT == 0 ) fTextureScaleT = 1.0f/32.0f;
471 }
472
473 CRender::g_pRender->SetTextureEnableAndScale(gfx->texture.tile, gfx->texture.enable_gbi0, fTextureScaleS, fTextureScaleT);
474
475 // What happens if these are 0? Interpret as 1.0f?
476
477 LOG_TEXTURE(
478 {
479 DebuggerAppendMsg("SetTexture: Level: %d Tile: %d %s\n", gfx->texture.level, gfx->texture.tile, gfx->texture.enable_gbi0 ? "enabled":"disabled");
480 DebuggerAppendMsg(" ScaleS: %f, ScaleT: %f\n", fTextureScaleS*32.0f, fTextureScaleT*32.0f);
481 });
482
483 DEBUGGER_PAUSE_COUNT_N(NEXT_SET_TEXTURE);
484 LOG_UCODE(" Level: %d Tile: %d %s", gfx->texture.level, gfx->texture.tile, gfx->texture.enable_gbi0 ? "enabled":"disabled");
485 LOG_UCODE(" ScaleS: %f, ScaleT: %f", fTextureScaleS*32.0f, fTextureScaleT*32.0f);
486}
487
488extern void RSP_RDP_InsertMatrix(uint32 word0, uint32 word1);
489void RSP_GBI1_MoveWord(Gfx *gfx)
490{
491 SP_Timing(RSP_GBI1_MoveWord);
492
493 switch (gfx->gbi0moveword.type)
494 {
495 case RSP_MOVE_WORD_MATRIX:
496 RSP_RDP_InsertMatrix(gfx);
497 break;
498 case RSP_MOVE_WORD_NUMLIGHT:
499 {
500 uint32 dwNumLights = (((gfx->gbi0moveword.value)-0x80000000)/32)-1;
501 LOG_UCODE(" RSP_MOVE_WORD_NUMLIGHT: Val:%d", dwNumLights);
502
503 gRSP.ambientLightIndex = dwNumLights;
504 SetNumLights(dwNumLights);
505 }
506 break;
507 case RSP_MOVE_WORD_CLIP:
508 {
509 switch (gfx->gbi0moveword.offset)
510 {
511 case RSP_MV_WORD_OFFSET_CLIP_RNX:
512 case RSP_MV_WORD_OFFSET_CLIP_RNY:
513 case RSP_MV_WORD_OFFSET_CLIP_RPX:
514 case RSP_MV_WORD_OFFSET_CLIP_RPY:
515 CRender::g_pRender->SetClipRatio(gfx->gbi0moveword.offset, gfx->gbi0moveword.value);
516 break;
517 default:
518 LOG_UCODE(" RSP_MOVE_WORD_CLIP ? : 0x%08x", gfx->words.w1);
519 break;
520 }
521 }
522 break;
523 case RSP_MOVE_WORD_SEGMENT:
524 {
525 uint32 dwSegment = (gfx->gbi0moveword.offset >> 2) & 0xF;
526 uint32 dwBase = (gfx->gbi0moveword.value)&0x00FFFFFF;
527 LOG_UCODE(" RSP_MOVE_WORD_SEGMENT Seg[%d] = 0x%08x", dwSegment, dwBase);
528 if( dwBase > g_dwRamSize )
529 {
530 gRSP.segments[dwSegment] = dwBase;
531#ifdef DEBUGGER
532 if( pauseAtNext )
533 DebuggerAppendMsg("warning: Segment %d addr is %8X", dwSegment, dwBase);
534#endif
535 }
536 else
537 {
538 gRSP.segments[dwSegment] = dwBase;
539 }
540 }
541 break;
542 case RSP_MOVE_WORD_FOG:
543 {
544 uint16 wMult = (uint16)(((gfx->gbi0moveword.value) >> 16) & 0xFFFF);
545 uint16 wOff = (uint16)(((gfx->gbi0moveword.value) ) & 0xFFFF);
546
547 float fMult = (float)(short)wMult;
548 float fOff = (float)(short)wOff;
549
550 float rng = 128000.0f / fMult;
551 float fMin = 500.0f - (fOff*rng/256.0f);
552 float fMax = rng + fMin;
553
554 FOG_DUMP(TRACE4("Set Fog: Min=%f, Max=%f, Mul=%f, Off=%f", fMin, fMax, fMult, fOff));
555 //if( fMult <= 0 || fMin > fMax || fMax < 0 || fMin > 1000 )
556 if( fMult <= 0 || fMax < 0 )
557 {
558 // Hack
559 fMin = 996;
560 fMax = 1000;
561 fMult = 0;
562 fOff = 1;
563 }
564
565 LOG_UCODE(" RSP_MOVE_WORD_FOG/Mul=%d: Off=%d", wMult, wOff);
566 FOG_DUMP(TRACE3("Set Fog: Min=%f, Max=%f, Data=%08X", fMin, fMax, gfx->gbi0moveword.value));
567 SetFogMinMax(fMin, fMax, fMult, fOff);
568 }
569 break;
570 case RSP_MOVE_WORD_LIGHTCOL:
571 {
572 uint32 dwLight = gfx->gbi0moveword.offset / 0x20;
573 uint32 dwField = (gfx->gbi0moveword.offset & 0x7);
574
575 LOG_UCODE(" RSP_MOVE_WORD_LIGHTCOL/0x%08x: 0x%08x", gfx->gbi0moveword.offset, gfx->words.w1);
576
577 switch (dwField)
578 {
579 case 0:
580 if (dwLight == gRSP.ambientLightIndex)
581 {
582 SetAmbientLight( ((gfx->gbi0moveword.value)>>8) );
583 }
584 else
585 {
586 SetLightCol(dwLight, gfx->gbi0moveword.value);
587 }
588 break;
589
590 case 4:
591 break;
592
593 default:
594 TRACE1("RSP_MOVE_WORD_LIGHTCOL with unknown offset 0x%08x", dwField);
595 break;
596 }
597 }
598 break;
599 case RSP_MOVE_WORD_POINTS:
600 {
601 uint32 vtx = gfx->gbi0moveword.offset/40;
602 uint32 where = gfx->gbi0moveword.offset - vtx*40;
603 ModifyVertexInfo(where, vtx, gfx->gbi0moveword.value);
604 }
605 break;
606 case RSP_MOVE_WORD_PERSPNORM:
607 LOG_UCODE(" RSP_MOVE_WORD_PERSPNORM");
608 //if( word1 != 0x1A ) DebuggerAppendMsg("PerspNorm: 0x%04x", (short)word1);
609 break;
610 default:
611 RSP_RDP_NOIMPL("Unknown MoveWord, %08X, %08X", gfx->words.w0, gfx->words.w1);
612 break;
613 }
614
615}
616
617
618void RSP_GBI1_PopMtx(Gfx *gfx)
619{
620 SP_Timing(RSP_GBI1_PopMtx);
621
622 LOG_UCODE(" Command: (%s)", gfx->gbi0popmatrix.projection ? "Projection" : "ModelView");
623
624 // Do any of the other bits do anything?
625 // So far only Extreme-G seems to Push/Pop projection matrices
626
627 if (gfx->gbi0popmatrix.projection)
628 {
629 CRender::g_pRender->PopProjection();
630 }
631 else
632 {
633 CRender::g_pRender->PopWorldView();
634 }
635#ifdef DEBUGGER
636 if( pauseAtNext && eventToPause == NEXT_MATRIX_CMD )
637 {
638 pauseAtNext = false;
639 debuggerPause = true;
640 DebuggerAppendMsg("Pause after Pop Matrix: %s\n", gfx->gbi0popmatrix.projection ? "Proj":"World");
641 }
642 else
643 {
644 if( pauseAtNext && logMatrix )
645 {
646 DebuggerAppendMsg("Pause after Pop Matrix: %s\n", gfx->gbi0popmatrix.projection ? "Proj":"World");
647 }
648 }
649#endif
650}
651
652
653void RSP_GBI1_CullDL(Gfx *gfx)
654{
655 SP_Timing(RSP_GBI1_CullDL);
656
657#ifdef DEBUGGER
658 if( !debuggerEnableCullFace )
659 {
660 return; //Disable Culling
661 }
662#endif
663 if( g_curRomInfo.bDisableCulling )
664 {
665 return; //Disable Culling
666 }
667
668 uint32 dwVFirst = ((gfx->words.w0) & 0xFFF) / gRSP.vertexMult;
669 uint32 dwVLast = (((gfx->words.w1)) & 0xFFF) / gRSP.vertexMult;
670
671 LOG_UCODE(" Culling using verts %d to %d", dwVFirst, dwVLast);
672
673 // Mask into range
674 dwVFirst &= 0x1f;
675 dwVLast &= 0x1f;
676
677 if( dwVLast < dwVFirst ) return;
678 if( !gRSP.bRejectVtx ) return;
679
680 for (uint32 i = dwVFirst; i <= dwVLast; i++)
681 {
682 if (g_clipFlag[i] == 0)
683 {
684 LOG_UCODE(" Vertex %d is visible, continuing with display list processing", i);
685 return;
686 }
687 }
688
689 status.dwNumDListsCulled++;
690
691 LOG_UCODE(" No vertices were visible, culling rest of display list");
692
693 RDP_GFX_PopDL();
694}
695
696
697
698void RSP_GBI1_Tri1(Gfx *gfx)
699{
700 status.primitiveType = PRIM_TRI1;
701 bool bTrisAdded = false;
702 bool bTexturesAreEnabled = CRender::g_pRender->IsTextureEnabled();
703
704 // While the next command pair is Tri1, add vertices
705 uint32 dwPC = gDlistStack[gDlistStackPointer].pc;
706 //uint32 * pCmdBase = (uint32 *)(g_pRDRAMu8 + dwPC);
707
708 do
709 {
710 uint32 dwV0 = gfx->tri1.v0/gRSP.vertexMult;
711 uint32 dwV1 = gfx->tri1.v1/gRSP.vertexMult;
712 uint32 dwV2 = gfx->tri1.v2/gRSP.vertexMult;
713
714 if (IsTriangleVisible(dwV0, dwV1, dwV2))
715 {
716 DEBUG_DUMP_VERTEXES("Tri1", dwV0, dwV1, dwV2);
717 LOG_UCODE(" Tri1: 0x%08x 0x%08x %d,%d,%d", gfx->words.w0, gfx->words.w1, dwV0, dwV1, dwV2);
718
719 if (!bTrisAdded)
720 {
721 if( bTexturesAreEnabled )
722 {
723 PrepareTextures();
724 InitVertexTextureConstants();
725 }
726 CRender::g_pRender->SetCombinerAndBlender();
727 bTrisAdded = true;
728 }
729 PrepareTriangle(dwV0, dwV1, dwV2);
730 }
731
732 gfx++;
733 dwPC += 8;
734
735#ifdef DEBUGGER
736 } while (!(pauseAtNext && eventToPause==NEXT_TRIANGLE) && gfx->words.cmd == (uint8)RSP_TRI1);
737#else
738 } while (gfx->words.cmd == (uint8)RSP_TRI1);
739#endif
740
741 gDlistStack[gDlistStackPointer].pc = dwPC-8;
742
743 if (bTrisAdded)
744 {
745 CRender::g_pRender->DrawTriangles();
746 }
747
748 DEBUG_TRIANGLE(TRACE0("Pause at GBI0 TRI1"));
749}
750
751
752void RSP_GBI0_Tri4(Gfx *gfx)
753{
754 uint32 w0 = gfx->words.w0;
755 uint32 w1 = gfx->words.w1;
756
757 status.primitiveType = PRIM_TRI2;
758
759 // While the next command pair is Tri2, add vertices
760 uint32 dwPC = gDlistStack[gDlistStackPointer].pc;
761
762 BOOL bTrisAdded = FALSE;
763
764 do {
765 uint32 dwFlag = (w0>>16)&0xFF;
766 LOG_UCODE(" PD Tri4: 0x%08x 0x%08x Flag: 0x%02x", gfx->words.w0, gfx->words.w1, dwFlag);
767
768 BOOL bVisible;
769 for( int i=0; i<4; i++)
770 {
771 uint32 v0 = (w1>>(4+(i<<3))) & 0xF;
772 uint32 v1 = (w1>>( (i<<3))) & 0xF;
773 uint32 v2 = (w0>>( (i<<2))) & 0xF;
774 bVisible = IsTriangleVisible(v0, v2, v1);
775 LOG_UCODE(" (%d, %d, %d) %s", v0, v1, v2, bVisible ? "": "(clipped)");
776 if (bVisible)
777 {
778 DEBUG_DUMP_VERTEXES("Tri4_PerfectDark 1/2", v0, v1, v2);
779 if (!bTrisAdded && CRender::g_pRender->IsTextureEnabled())
780 {
781 PrepareTextures();
782 InitVertexTextureConstants();
783 }
784
785 if( !bTrisAdded )
786 {
787 CRender::g_pRender->SetCombinerAndBlender();
788 }
789
790 bTrisAdded = true;
791 PrepareTriangle(v0, v2, v1);
792 }
793 }
794
795 w0 = *(uint32 *)(g_pRDRAMu8 + dwPC+0);
796 w1 = *(uint32 *)(g_pRDRAMu8 + dwPC+4);
797 dwPC += 8;
798
799#ifdef DEBUGGER
800 } while (!(pauseAtNext && eventToPause==NEXT_TRIANGLE) && (w0>>24) == (uint8)RSP_TRI2);
801#else
802 } while (((w0)>>24) == (uint8)RSP_TRI2);
803#endif
804
805
806 gDlistStack[gDlistStackPointer].pc = dwPC-8;
807
808 if (bTrisAdded)
809 {
810 CRender::g_pRender->DrawTriangles();
811 }
812
813 DEBUG_TRIANGLE(TRACE0("Pause at GBI0 TRI4"));
814
815 gRSP.DKRVtxCount=0;
816}
817
818//Nintro64 uses Sprite2d
819
820
821void RSP_RDP_Nothing(Gfx *gfx)
822{
823 SP_Timing(RSP_RDP_Nothing);
824
825#ifdef DEBUGGER
826 if( logWarning )
827 {
828 TRACE0("Stack Trace");
829 for( int i=0; i<gDlistStackPointer; i++ )
830 {
831 DebuggerAppendMsg(" %08X", gDlistStack[i].pc);
832 }
833
834 uint32 dwPC = gDlistStack[gDlistStackPointer].pc-8;
835 DebuggerAppendMsg("PC=%08X",dwPC);
836 DebuggerAppendMsg("Warning, unknown ucode PC=%08X: 0x%08x 0x%08x\n", dwPC, gfx->words.w0, gfx->words.w1);
837 }
838 DEBUGGER_PAUSE_AND_DUMP_COUNT_N(NEXT_UNKNOWN_OP, {TRACE0("Paused at unknown ucode\n");})
839 if( debuggerContinueWithUnknown )
840 {
841 return;
842 }
843#endif
844
845 if( options.bEnableHacks )
846 return;
847
848 gDlistStackPointer=-1;
849}
850
851
852void RSP_RDP_InsertMatrix(Gfx *gfx)
853{
854 float fraction;
855
856 UpdateCombinedMatrix();
857
858 if ((gfx->words.w0) & 0x20)
859 {
860 int x = ((gfx->words.w0) & 0x1F) >> 1;
861 int y = x >> 2;
862 x &= 3;
863
864 fraction = ((gfx->words.w1)>>16)/65536.0f;
865 gRSPworldProject.m[y][x] = (float)(int)gRSPworldProject.m[y][x];
866 gRSPworldProject.m[y][x] += fraction;
867
868 fraction = ((gfx->words.w1)&0xFFFF)/65536.0f;
869 gRSPworldProject.m[y][x+1] = (float)(int)gRSPworldProject.m[y][x+1];
870 gRSPworldProject.m[y][x+1] += fraction;
871 }
872 else
873 {
874 int x = ((gfx->words.w0) & 0x1F) >> 1;
875 int y = x >> 2;
876 x &= 3;
877
878 fraction = (float)fabs(gRSPworldProject.m[y][x] - (int)gRSPworldProject.m[y][x]);
879 gRSPworldProject.m[y][x] = (short)((gfx->words.w1)>>16) + fraction;
880
881 fraction = (float)fabs(gRSPworldProject.m[y][x+1] - (int)gRSPworldProject.m[y][x+1]);
882 gRSPworldProject.m[y][x+1] = (short)((gfx->words.w1)&0xFFFF) + fraction;
883 }
884
885 gRSP.bMatrixIsUpdated = false;
886 gRSP.bCombinedMatrixIsUpdated = true;
887
888#ifdef DEBUGGER
889 if( pauseAtNext && eventToPause == NEXT_MATRIX_CMD )
890 {
891 pauseAtNext = false;
892 debuggerPause = true;
893 DebuggerAppendMsg("Pause after insert matrix: %08X, %08X", gfx->words.w0, gfx->words.w1);
894 }
895 else
896 {
897 if( pauseAtNext && logMatrix )
898 {
899 DebuggerAppendMsg("insert matrix: %08X, %08X", gfx->words.w0, gfx->words.w1);
900 }
901 }
902#endif
903}
904