Rice Video Plugin for GLES1.1
[mupen64plus-pandora.git] / source / rice_gles / src / RSP_GBI2.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 "Render.h"
21#include "Timing.h"
22
23void RSP_GBI2_Vtx(Gfx *gfx)
24{
25 uint32 addr = RSPSegmentAddr((gfx->gbi2vtx.addr));
26 int vend = gfx->gbi2vtx.vend/2;
27 int n = gfx->gbi2vtx.n;
28 int v0 = vend - n;
29
30 LOG_UCODE(" Vtx: Address 0x%08x, vEnd: %d, v0: %d, Num: %d", addr, vend, v0, n);
31
32 if( vend > 64 )
33 {
34 DebuggerAppendMsg("Warning, attempting to load into invalid vertex positions, v0=%d, n=%d", v0, n);
35 return;
36 }
37
38 if ((addr + (n*16)) > g_dwRamSize)
39 {
40 DebuggerAppendMsg("ProcessVertexData: Address out of range (0x%08x)", addr);
41 }
42 else
43 {
44 ProcessVertexData(addr, v0, n);
45 status.dwNumVertices += n;
46 DisplayVertexInfo(addr, v0, n);
47 }
48}
49
50void RSP_GBI2_EndDL(Gfx *gfx)
51{
52 SP_Timing(RSP_GBI1_EndDL);
53
54 RDP_GFX_PopDL();
55}
56
57void RSP_GBI2_CullDL(Gfx *gfx)
58{
59 SP_Timing(RSP_GBI1_CullDL);
60
61#ifdef DEBUGGER
62 if( !debuggerEnableCullFace )
63 {
64 return; //Disable Culling
65 }
66#endif
67 if( g_curRomInfo.bDisableCulling )
68 {
69 return; //Disable Culling
70 }
71
72 uint32 dwVFirst = (((gfx->words.w0)) & 0xfff) / gRSP.vertexMult;
73 uint32 dwVLast = (((gfx->words.w1)) & 0xfff) / gRSP.vertexMult;
74
75 LOG_UCODE(" Culling using verts %d to %d", dwVFirst, dwVLast);
76
77 // Mask into range
78 dwVFirst &= 0x1f;
79 dwVLast &= 0x1f;
80
81 if( dwVLast < dwVFirst ) return;
82 if( !gRSP.bRejectVtx ) return;
83
84 for (uint32 i = dwVFirst; i <= dwVLast; i++)
85 {
86 //if (g_dwVtxFlags[i] == 0)
87 if (g_clipFlag[i] == 0)
88 {
89 LOG_UCODE(" Vertex %d is visible, returning", i);
90 return;
91 }
92 }
93
94 status.dwNumDListsCulled++;
95
96 LOG_UCODE(" No vertices were visible, culling");
97
98 RDP_GFX_PopDL();
99}
100
101void RSP_GBI2_MoveWord(Gfx *gfx)
102{
103 SP_Timing(RSP_GBI1_MoveWord);
104
105 switch (gfx->gbi2moveword.type)
106 {
107 case RSP_MOVE_WORD_MATRIX:
108 RSP_RDP_InsertMatrix(gfx);
109 break;
110 case RSP_MOVE_WORD_NUMLIGHT:
111 {
112 uint32 dwNumLights = gfx->gbi2moveword.value/24;
113 gRSP.ambientLightIndex = dwNumLights;
114 SetNumLights(dwNumLights);
115 }
116 break;
117
118 case RSP_MOVE_WORD_CLIP:
119 {
120 switch (gfx->gbi2moveword.offset)
121 {
122 case RSP_MV_WORD_OFFSET_CLIP_RNX:
123 case RSP_MV_WORD_OFFSET_CLIP_RNY:
124 case RSP_MV_WORD_OFFSET_CLIP_RPX:
125 case RSP_MV_WORD_OFFSET_CLIP_RPY:
126 CRender::g_pRender->SetClipRatio(gfx->gbi2moveword.offset, gfx->gbi2moveword.value);
127 default:
128 LOG_UCODE(" RSP_MOVE_WORD_CLIP ? : 0x%08x", gfx->words.w1);
129 break;
130 }
131 }
132 break;
133
134 case RSP_MOVE_WORD_SEGMENT:
135 {
136 uint32 dwSeg = gfx->gbi2moveword.offset / 4;
137 uint32 dwAddr = gfx->gbi2moveword.value & 0x00FFFFFF; // Hack - convert to physical
138
139 LOG_UCODE(" RSP_MOVE_WORD_SEGMENT Segment[%d] = 0x%08x", dwSeg, dwAddr);
140 if( dwAddr > g_dwRamSize )
141 {
142 gRSP.segments[dwSeg] = dwAddr;
143#ifdef DEBUGGER
144 if( pauseAtNext )
145 DebuggerAppendMsg("warning: Segment %d addr is %8X", dwSeg, dwAddr);
146#endif
147 }
148 else
149 {
150 gRSP.segments[dwSeg] = dwAddr;
151 }
152 }
153 break;
154 case RSP_MOVE_WORD_FOG:
155 {
156 uint16 wMult = (uint16)((gfx->gbi2moveword.value >> 16) & 0xFFFF);
157 uint16 wOff = (uint16)((gfx->gbi2moveword.value ) & 0xFFFF);
158
159 float fMult = (float)(short)wMult;
160 float fOff = (float)(short)wOff;
161
162 float rng = 128000.0f / fMult;
163 float fMin = 500.0f - (fOff*rng/256.0f);
164 float fMax = rng + fMin;
165
166 FOG_DUMP(TRACE4("Set Fog: Min=%f, Max=%f, Mul=%f, Off=%f", fMin, fMax, fMult, fOff));
167 //if( fMult <= 0 || fMin > fMax || fMax < 0 || fMin > 1000 )
168 if( fMult <= 0 || fMax < 0 )
169 {
170 // Hack
171 fMin = 996;
172 fMax = 1000;
173 fMult = 0;
174 fOff = 1;
175 }
176
177 SetFogMinMax(fMin, fMax, fMult, fOff);
178 FOG_DUMP(TRACE3("Set Fog: Min=%f, Max=%f, Data=0x%08X", fMin, fMax, gfx->gbi2moveword.value));
179 }
180 break;
181 case RSP_MOVE_WORD_LIGHTCOL:
182 {
183 uint32 dwLight = gfx->gbi2moveword.offset / 0x18;
184 uint32 dwField = (gfx->gbi2moveword.offset & 0x7);
185
186 switch (dwField)
187 {
188 case 0:
189 if (dwLight == gRSP.ambientLightIndex)
190 {
191 SetAmbientLight( (gfx->gbi2moveword.value>>8) );
192 }
193 else
194 {
195 SetLightCol(dwLight, gfx->gbi2moveword.value);
196 }
197 break;
198
199 case 4:
200 break;
201
202 default:
203 DebuggerAppendMsg("RSP_MOVE_WORD_LIGHTCOL with unknown offset 0x%08x", dwField);
204 break;
205 }
206
207
208 }
209 break;
210
211 case RSP_MOVE_WORD_PERSPNORM:
212 LOG_UCODE(" RSP_MOVE_WORD_PERSPNORM 0x%04x", (short)gfx->words.w1);
213 break;
214
215 case RSP_MOVE_WORD_POINTS:
216 LOG_UCODE(" 2nd cmd of Force Matrix");
217 break;
218
219 default:
220 {
221 LOG_UCODE(" Ignored!!");
222
223 }
224 break;
225 }
226}
227
228void RSP_GBI2_Tri1(Gfx *gfx)
229{
230 if( gfx->words.w0 == 0x05000017 && gfx->gbi2tri1.flag == 0x80 )
231 {
232 // The ObjLoadTxtr / Tlut cmd for Evangelion.v64
233 RSP_S2DEX_SPObjLoadTxtr(gfx);
234 DebuggerAppendMsg("Fix me, SPObjLoadTxtr as RSP_GBI2_Tri2");
235 }
236 else
237 {
238 status.primitiveType = PRIM_TRI1;
239 bool bTrisAdded = false;
240 bool bTexturesAreEnabled = CRender::g_pRender->IsTextureEnabled();
241
242 // While the next command pair is Tri1, add vertices
243 uint32 dwPC = gDlistStack[gDlistStackPointer].pc;
244 //uint32 * pCmdBase = (uint32 *)(g_pRDRAMu8 + dwPC);
245
246 do
247 {
248 uint32 dwV2 = gfx->gbi2tri1.v2/gRSP.vertexMult;
249 uint32 dwV1 = gfx->gbi2tri1.v1/gRSP.vertexMult;
250 uint32 dwV0 = gfx->gbi2tri1.v0/gRSP.vertexMult;
251
252 if (IsTriangleVisible(dwV0, dwV1, dwV2))
253 {
254 DEBUG_DUMP_VERTEXES("ZeldaTri1", dwV0, dwV1, dwV2);
255 LOG_UCODE(" ZeldaTri1: 0x%08x 0x%08x %d,%d,%d", gfx->words.w0, gfx->words.w1, dwV0, dwV1, dwV2);
256 if (!bTrisAdded)
257 {
258 if( bTexturesAreEnabled )
259 {
260 PrepareTextures();
261 InitVertexTextureConstants();
262 }
263
264 CRender::g_pRender->SetCombinerAndBlender();
265 bTrisAdded = true;
266 }
267 PrepareTriangle(dwV0, dwV1, dwV2);
268 }
269
270 gfx++;
271 dwPC += 8;
272
273#ifdef DEBUGGER
274 } while (!(pauseAtNext && eventToPause==NEXT_TRIANGLE) && gfx->words.cmd == (uint8)RSP_ZELDATRI1);
275#else
276 } while( gfx->words.cmd == (uint8)RSP_ZELDATRI1);
277#endif
278
279 gDlistStack[gDlistStackPointer].pc = dwPC-8;
280
281 if (bTrisAdded)
282 {
283 CRender::g_pRender->DrawTriangles();
284 }
285
286 DEBUG_TRIANGLE(TRACE0("Pause at GBI2 TRI1"));
287 }
288}
289
290void RSP_GBI2_Tri2(Gfx *gfx)
291{
292 if( gfx->words.w0 == 0x0600002f && gfx->gbi2tri2.flag == 0x80 )
293 {
294 // The ObjTxSprite cmd for Evangelion.v64
295 RSP_S2DEX_SPObjLoadTxSprite(gfx);
296 DebuggerAppendMsg("Fix me, SPObjLoadTxSprite as RSP_GBI2_Tri2");
297 }
298 else
299 {
300 status.primitiveType = PRIM_TRI2;
301 BOOL bTrisAdded = FALSE;
302
303 // While the next command pair is Tri2, add vertices
304 uint32 dwPC = gDlistStack[gDlistStackPointer].pc;
305 bool bTexturesAreEnabled = CRender::g_pRender->IsTextureEnabled();
306
307 do {
308 uint32 dwV2 = gfx->gbi2tri2.v2;
309 uint32 dwV1 = gfx->gbi2tri2.v1;
310 uint32 dwV0 = gfx->gbi2tri2.v0;
311
312 uint32 dwV5 = gfx->gbi2tri2.v5;
313 uint32 dwV4 = gfx->gbi2tri2.v4;
314 uint32 dwV3 = gfx->gbi2tri2.v3;
315
316 LOG_UCODE(" ZeldaTri2: 0x%08x 0x%08x", gfx->words.w0, gfx->words.w1);
317 LOG_UCODE(" V0: %d, V1: %d, V2: %d", dwV0, dwV1, dwV2);
318 LOG_UCODE(" V3: %d, V4: %d, V5: %d", dwV3, dwV4, dwV5);
319
320 // Do first tri
321 if (IsTriangleVisible(dwV0, dwV1, dwV2))
322 {
323 DEBUG_DUMP_VERTEXES("ZeldaTri2 1/2", dwV0, dwV1, dwV2);
324 if (!bTrisAdded)
325 {
326 if( bTexturesAreEnabled )
327 {
328 PrepareTextures();
329 InitVertexTextureConstants();
330 }
331
332 CRender::g_pRender->SetCombinerAndBlender();
333 bTrisAdded = true;
334 }
335
336 PrepareTriangle(dwV0, dwV1, dwV2);
337 }
338
339 // Do second tri
340 if (IsTriangleVisible(dwV3, dwV4, dwV5))
341 {
342 DEBUG_DUMP_VERTEXES("ZeldaTri2 2/2", dwV3, dwV4, dwV5);
343 if (!bTrisAdded)
344 {
345 if( bTexturesAreEnabled )
346 {
347 PrepareTextures();
348 InitVertexTextureConstants();
349 }
350
351 CRender::g_pRender->SetCombinerAndBlender();
352 bTrisAdded = true;
353 }
354
355 PrepareTriangle(dwV3, dwV4, dwV5);
356 }
357
358 gfx++;
359 dwPC += 8;
360
361#ifdef DEBUGGER
362 } while (!(pauseAtNext && eventToPause==NEXT_TRIANGLE) && gfx->words.cmd == (uint8)RSP_ZELDATRI2);
363#else
364 } while ( gfx->words.cmd == (uint8)RSP_ZELDATRI2 );//&& status.dwNumTrisRendered < 50);
365#endif
366
367
368 gDlistStack[gDlistStackPointer].pc = dwPC-8;
369
370 if (bTrisAdded)
371 {
372 CRender::g_pRender->DrawTriangles();
373 }
374
375 DEBUG_TRIANGLE(TRACE0("Pause at GBI2 TRI2"));
376 }
377}
378
379void RSP_GBI2_Line3D(Gfx *gfx)
380{
381 if( gfx->words.w0 == 0x0700002f && (gfx->words.w1>>24) == 0x80 )
382 {
383 // The ObjTxSprite cmd for Evangelion.v64
384 RSP_S2DEX_SPObjLoadTxRect(gfx);
385 }
386 else
387 {
388 status.primitiveType = PRIM_TRI3;
389
390 uint32 dwPC = gDlistStack[gDlistStackPointer].pc;
391
392 BOOL bTrisAdded = FALSE;
393
394 do {
395 uint32 dwV0 = gfx->gbi2line3d.v0/gRSP.vertexMult;
396 uint32 dwV1 = gfx->gbi2line3d.v1/gRSP.vertexMult;
397 uint32 dwV2 = gfx->gbi2line3d.v2/gRSP.vertexMult;
398
399 uint32 dwV3 = gfx->gbi2line3d.v3/gRSP.vertexMult;
400 uint32 dwV4 = gfx->gbi2line3d.v4/gRSP.vertexMult;
401 uint32 dwV5 = gfx->gbi2line3d.v5/gRSP.vertexMult;
402
403 LOG_UCODE(" ZeldaTri3: 0x%08x 0x%08x", gfx->words.w0, gfx->words.w1);
404 LOG_UCODE(" V0: %d, V1: %d, V2: %d", dwV0, dwV1, dwV2);
405 LOG_UCODE(" V3: %d, V4: %d, V5: %d", dwV3, dwV4, dwV5);
406
407 // Do first tri
408 if (IsTriangleVisible(dwV0, dwV1, dwV2))
409 {
410 DEBUG_DUMP_VERTEXES("ZeldaTri3 1/2", dwV0, dwV1, dwV2);
411 if (!bTrisAdded && CRender::g_pRender->IsTextureEnabled())
412 {
413 PrepareTextures();
414 InitVertexTextureConstants();
415 }
416
417 if( !bTrisAdded )
418 {
419 CRender::g_pRender->SetCombinerAndBlender();
420 }
421
422 bTrisAdded = true;
423 PrepareTriangle(dwV0, dwV1, dwV2);
424 }
425
426 // Do second tri
427 if (IsTriangleVisible(dwV3, dwV4, dwV5))
428 {
429 DEBUG_DUMP_VERTEXES("ZeldaTri3 2/2", dwV3, dwV4, dwV5);
430 if (!bTrisAdded && CRender::g_pRender->IsTextureEnabled())
431 {
432 PrepareTextures();
433 InitVertexTextureConstants();
434 }
435
436 if( !bTrisAdded )
437 {
438 CRender::g_pRender->SetCombinerAndBlender();
439 }
440
441 bTrisAdded = true;
442 PrepareTriangle(dwV3, dwV4, dwV5);
443 }
444
445 gfx++;
446 dwPC += 8;
447
448#ifdef DEBUGGER
449 } while (!(pauseAtNext && eventToPause==NEXT_TRIANGLE) && gfx->words.cmd == (uint8)RSP_LINE3D);
450#else
451 } while ( gfx->words.cmd == (uint8)RSP_LINE3D);
452#endif
453
454 gDlistStack[gDlistStackPointer].pc = dwPC-8;
455
456
457 if (bTrisAdded)
458 {
459 CRender::g_pRender->DrawTriangles();
460 }
461
462 DEBUG_TRIANGLE(TRACE0("Pause at GBI2 Line3D"));
463 }
464}
465
466void RSP_GBI2_Texture(Gfx *gfx)
467{
468 SP_Timing(RSP_GBI1_Texture);
469
470 float fTextureScaleS = (float)(gfx->texture.scaleS) / (65536.0f * 32.0f);
471 float fTextureScaleT = (float)(gfx->texture.scaleT) / (65536.0f * 32.0f);
472
473 if( (((gfx->words.w1)>>16)&0xFFFF) == 0xFFFF )
474 {
475 fTextureScaleS = 1/32.0f;
476 }
477 else if( (((gfx->words.w1)>>16)&0xFFFF) == 0x8000 )
478 {
479 fTextureScaleS = 1/64.0f;
480 }
481 if( (((gfx->words.w1) )&0xFFFF) == 0xFFFF )
482 {
483 fTextureScaleT = 1/32.0f;
484 }
485 else if( (((gfx->words.w1) )&0xFFFF) == 0x8000 )
486 {
487 fTextureScaleT = 1/64.0f;
488 }
489
490 CRender::g_pRender->SetTextureEnableAndScale(gfx->texture.tile, gfx->texture.enable_gbi2, fTextureScaleS, fTextureScaleT);
491
492 /*
493 if( g_curRomInfo.bTextureScaleHack )
494 {
495 // Hack, need to verify, refer to N64 programming manual
496 // that if scale = 0.5 (1/64), vtx s,t are also doubled
497
498 if( ((word1>>16)&0xFFFF) == 0x8000 )
499 {
500 fTextureScaleS = 1/128.0f;
501 if( ((word1)&0xFFFF) == 0xFFFF )
502 {
503 fTextureScaleT = 1/64.0f;
504 }
505 }
506
507 if( ((word1 )&0xFFFF) == 0x8000 )
508 {
509 fTextureScaleT = 1/128.0f;
510 if( ((word1>>16)&0xFFFF) == 0xFFFF )
511 {
512 fTextureScaleS = 1/64.0f;
513 }
514 }
515 }
516 */
517
518 CRender::g_pRender->SetTextureEnableAndScale(gfx->texture.tile, gfx->texture.enable_gbi2, fTextureScaleS, fTextureScaleT);
519
520 LOG_TEXTURE(
521 {
522 DebuggerAppendMsg("SetTexture: Level: %d Tile: %d %s\n", gfx->texture.level, gfx->texture.tile, gfx->texture.enable_gbi2 ? "enabled":"disabled");
523 DebuggerAppendMsg(" ScaleS: %f, ScaleT: %f\n", fTextureScaleS*32.0f, fTextureScaleT*32.0f);
524 });
525
526 DEBUGGER_PAUSE_COUNT_N(NEXT_SET_TEXTURE);
527
528 LOG_UCODE(" Level: %d Tile: %d %s", gfx->texture.level, gfx->texture.tile, gfx->texture.enable_gbi2 ? "enabled":"disabled");
529 LOG_UCODE(" ScaleS: %f, ScaleT: %f", fTextureScaleS*32.0f, fTextureScaleT*32.0f);
530}
531
532
533
534void RSP_GBI2_PopMtx(Gfx *gfx)
535{
536 SP_Timing(RSP_GBI1_PopMtx);
537
538 uint8 nCommand = (uint8)(gfx->words.w0 & 0xFF);
539
540 LOG_UCODE(" PopMtx: 0x%02x (%s)",
541 nCommand,
542 (nCommand & RSP_ZELDA_MTX_PROJECTION) ? "Projection" : "ModelView");
543
544
545/* if (nCommand & RSP_ZELDA_MTX_PROJECTION)
546 {
547 CRender::g_pRender->PopProjection();
548 }
549 else*/
550 {
551 CRender::g_pRender->PopWorldView();
552 }
553#ifdef DEBUGGER
554 if( pauseAtNext && eventToPause == NEXT_MATRIX_CMD )
555 {
556 pauseAtNext = false;
557 debuggerPause = true;
558 TRACE0("Pause after Pop GBI2_PopMtx:");
559 }
560 else
561 {
562 if( pauseAtNext && logMatrix )
563 {
564 TRACE0("Pause after Pop GBI2_PopMtx:");
565 }
566 }
567#endif
568
569}
570
571
572#define RSP_ZELDA_ZBUFFER 0x00000001 // Guess
573#define RSP_ZELDA_CULL_BACK 0x00000200
574#define RSP_ZELDA_CULL_FRONT 0x00000400
575#define RSP_ZELDA_FOG 0x00010000
576#define RSP_ZELDA_LIGHTING 0x00020000
577#define RSP_ZELDA_TEXTURE_GEN 0x00040000
578#define RSP_ZELDA_TEXTURE_GEN_LINEAR 0x00080000
579#define RSP_ZELDA_SHADING_SMOOTH 0x00200000
580
581void RSP_GBI2_GeometryMode(Gfx *gfx)
582{
583 SP_Timing(RSP_GBI2_GeometryMode);
584
585 uint32 dwAnd = ((gfx->words.w0)) & 0x00FFFFFF;
586 uint32 dwOr = ((gfx->words.w1)) & 0x00FFFFFF;
587
588#ifdef DEBUGGER
589 LOG_UCODE(" 0x%08x 0x%08x =(x & 0x%08x) | 0x%08x", gfx->words.w0, gfx->words.w1, dwAnd, dwOr);
590
591 if ((~dwAnd) & RSP_ZELDA_ZBUFFER) LOG_UCODE(" Disabling ZBuffer");
592 //if ((~dwAnd) & RSP_ZELDA_TEXTURE_ENABLE) LOG_UCODE(" Disabling Texture");
593 //if ((~dwAnd) & RSP_ZELDA_SHADE) LOG_UCODE(" Disabling Shade");
594 if ((~dwAnd) & RSP_ZELDA_SHADING_SMOOTH) LOG_UCODE(" Disabling Flat Shading");
595 if ((~dwAnd) & RSP_ZELDA_CULL_FRONT) LOG_UCODE(" Disabling Front Culling");
596 if ((~dwAnd) & RSP_ZELDA_CULL_BACK) LOG_UCODE(" Disabling Back Culling");
597 if ((~dwAnd) & RSP_ZELDA_FOG) LOG_UCODE(" Disabling Fog");
598 if ((~dwAnd) & RSP_ZELDA_LIGHTING) LOG_UCODE(" Disabling Lighting");
599 if ((~dwAnd) & RSP_ZELDA_TEXTURE_GEN) LOG_UCODE(" Disabling Texture Gen");
600 if ((~dwAnd) & RSP_ZELDA_TEXTURE_GEN_LINEAR) LOG_UCODE(" Disabling Texture Gen Linear");
601 // if ((~dwAnd) & RSP_ZELDA_LOD) LOG_UCODE(" Disabling LOD (no impl)");
602
603 if (dwOr & RSP_ZELDA_ZBUFFER) LOG_UCODE(" Enabling ZBuffer");
604 //if (dwOr & RSP_ZELDA_TEXTURE_ENABLE) LOG_UCODE(" Enabling Texture");
605 //if (dwOr & RSP_ZELDA_SHADE) LOG_UCODE(" Enabling Shade");
606 if (dwOr & RSP_ZELDA_SHADING_SMOOTH) LOG_UCODE(" Enabling Flat Shading");
607 if (dwOr & RSP_ZELDA_CULL_FRONT) LOG_UCODE(" Enabling Front Culling");
608 if (dwOr & RSP_ZELDA_CULL_BACK) LOG_UCODE(" Enabling Back Culling");
609 if (dwOr & RSP_ZELDA_FOG) LOG_UCODE(" Enabling Fog");
610 if (dwOr & RSP_ZELDA_LIGHTING) LOG_UCODE(" Enabling Lighting");
611 if (dwOr & RSP_ZELDA_TEXTURE_GEN) LOG_UCODE(" Enabling Texture Gen");
612 if (dwOr & RSP_ZELDA_TEXTURE_GEN_LINEAR) LOG_UCODE(" Enabling Texture Gen Linear");
613 ///if (dwOr & RSP_ZELDA_LOD) LOG_UCODE(" Enabling LOD (no impl)");
614#endif // DEBUGGER
615
616 gRDP.geometryMode &= dwAnd;
617 gRDP.geometryMode |= dwOr;
618
619
620 bool bCullFront = (gRDP.geometryMode & RSP_ZELDA_CULL_FRONT) ? true : false;
621 bool bCullBack = (gRDP.geometryMode & RSP_ZELDA_CULL_BACK) ? true : false;
622
623 //BOOL bShade = (gRDP.geometryMode & G_SHADE) ? TRUE : FALSE;
624 //BOOL bFlatShade = (gRDP.geometryMode & RSP_ZELDA_SHADING_SMOOTH) ? TRUE : FALSE;
625 BOOL bFlatShade = (gRDP.geometryMode & RSP_ZELDA_TEXTURE_GEN_LINEAR) ? TRUE : FALSE;
626 if( options.enableHackForGames == HACK_FOR_TIGER_HONEY_HUNT )
627 bFlatShade = FALSE;
628
629 bool bFog = (gRDP.geometryMode & RSP_ZELDA_FOG) ? true : false;
630 bool bTextureGen = (gRDP.geometryMode & RSP_ZELDA_TEXTURE_GEN) ? true : false;
631
632 bool bLighting = (gRDP.geometryMode & RSP_ZELDA_LIGHTING) ? true : false;
633 BOOL bZBuffer = (gRDP.geometryMode & RSP_ZELDA_ZBUFFER) ? TRUE : FALSE;
634
635 CRender::g_pRender->SetCullMode(bCullFront, bCullBack);
636
637 //if (bFlatShade||!bShade) CRender::g_pRender->SetShadeMode( SHADE_FLAT );
638 if (bFlatShade) CRender::g_pRender->SetShadeMode( SHADE_FLAT );
639 else CRender::g_pRender->SetShadeMode( SHADE_SMOOTH );
640
641 SetTextureGen(bTextureGen);
642
643 SetLighting( bLighting );
644 CRender::g_pRender->ZBufferEnable( bZBuffer );
645 CRender::g_pRender->SetFogEnable( bFog );
646}
647
648
649int dlistMtxCount=0;
650extern uint32 dwConkerVtxZAddr;
651
652void RSP_GBI2_Mtx(Gfx *gfx)
653{
654 SP_Timing(RSP_GBI0_Mtx);
655 dwConkerVtxZAddr = 0; // For Conker BFD
656
657 uint32 addr = RSPSegmentAddr((gfx->gbi2matrix.addr));
658
659 if( gfx->gbi2matrix.param == 0 && gfx->gbi2matrix.len == 0 )
660 {
661 DLParser_Bomberman2TextRect(gfx);
662 return;
663 }
664
665 LOG_UCODE(" Mtx: %s %s %s Length %d Address 0x%08x",
666 gfx->gbi2matrix.projection ? "Projection" : "ModelView",
667 gfx->gbi2matrix.load ? "Load" : "Mul",
668 gfx->gbi2matrix.nopush==0 ? "Push" : "No Push",
669 gfx->gbi2matrix.len, addr);
670
671 if (addr + 64 > g_dwRamSize)
672 {
673 DebuggerAppendMsg("ZeldaMtx: Address invalid (0x%08x)", addr);
674 return;
675 }
676
677 LoadMatrix(addr);
678
679 if (gfx->gbi2matrix.projection)
680 {
681 // So far only Extreme-G seems to Push/Pop projection matrices
682 CRender::g_pRender->SetProjection(matToLoad, gfx->gbi2matrix.nopush==0, gfx->gbi2matrix.load);
683 }
684 else
685 {
686 CRender::g_pRender->SetWorldView(matToLoad, gfx->gbi2matrix.nopush==0, gfx->gbi2matrix.load);
687
688 if( options.enableHackForGames == HACK_FOR_SOUTH_PARK_RALLY )
689 {
690 dlistMtxCount++;
691 if( dlistMtxCount == 2 )
692 {
693 CRender::g_pRender->ClearZBuffer(1.0f);
694 }
695 }
696 }
697
698#ifdef DEBUGGER
699 const char *loadstr = gfx->gbi2matrix.load?"Load":"Mul";
700 const char *pushstr = gfx->gbi2matrix.nopush==0?"Push":"Nopush";
701 int projlevel = CRender::g_pRender->GetProjectMatrixLevel();
702 int worldlevel = CRender::g_pRender->GetWorldViewMatrixLevel();
703 if( pauseAtNext && eventToPause == NEXT_MATRIX_CMD )
704 {
705 pauseAtNext = false;
706 debuggerPause = true;
707 if (gfx->gbi2matrix.projection)
708 {
709 DebuggerAppendMsg("Pause after %s and %s Matrix: Projection, level=%d\n", loadstr, pushstr, projlevel );
710 }
711 else
712 {
713 DebuggerAppendMsg("Pause after %s and %s Matrix: WorldView level=%d\n", loadstr, pushstr, worldlevel);
714 }
715 }
716 else
717 {
718 if( pauseAtNext && logMatrix )
719 {
720 if (gfx->gbi2matrix.projection)
721 {
722 DebuggerAppendMsg("Matrix: %s and %s Projection level=%d\n", loadstr, pushstr, projlevel);
723 }
724 else
725 {
726 DebuggerAppendMsg("Matrix: %s and %s WorldView\n level=%d", loadstr, pushstr, worldlevel);
727 }
728 }
729 }
730#endif
731}
732
733void RSP_GBI2_MoveMem(Gfx *gfx)
734{
735 SP_Timing(RSP_GBI1_MoveMem);
736
737 uint32 addr = RSPSegmentAddr((gfx->words.w1));
738 uint32 type = ((gfx->words.w0) ) & 0xFE;
739
740 //uint32 dwLen = ((gfx->words.w0) >> 16) & 0xFF;
741 //uint32 dwOffset = ((gfx->words.w0) >> 8) & 0xFFFF;
742
743 switch (type)
744 {
745 case RSP_GBI2_MV_MEM__VIEWPORT:
746 {
747 RSP_MoveMemViewport(addr);
748 }
749 break;
750 case RSP_GBI2_MV_MEM__LIGHT:
751 {
752 uint32 dwOffset2 = ((gfx->words.w0) >> 5) & 0x3FFF;
753 switch (dwOffset2)
754 {
755 case 0x00:
756 {
757 s8 * pcBase = g_pRDRAMs8 + addr;
758 LOG_UCODE(" RSP_GBI1_MV_MEM_LOOKATX %f %f %f",
759 (float)pcBase[8 ^ 0x3],
760 (float)pcBase[9 ^ 0x3],
761 (float)pcBase[10 ^ 0x3]);
762
763 }
764 break;
765 case 0x18:
766 {
767 s8 * pcBase = g_pRDRAMs8 + addr;
768 LOG_UCODE(" RSP_GBI1_MV_MEM_LOOKATY %f %f %f",
769 (float)pcBase[8 ^ 0x3],
770 (float)pcBase[9 ^ 0x3],
771 (float)pcBase[10 ^ 0x3]);
772 }
773 break;
774 default: //0x30/48/60
775 {
776 uint32 dwLight = (dwOffset2 - 0x30)/0x18;
777 LOG_UCODE(" Light %d:", dwLight);
778 RSP_MoveMemLight(dwLight, addr);
779 }
780 break;
781 }
782 break;
783
784 }
785 case RSP_GBI2_MV_MEM__MATRIX:
786 LOG_UCODE("Force Matrix: addr=%08X", addr);
787 RSP_GFX_Force_Matrix(addr);
788 break;
789 case RSP_GBI2_MV_MEM_O_L0:
790 case RSP_GBI2_MV_MEM_O_L1:
791 case RSP_GBI2_MV_MEM_O_L2:
792 case RSP_GBI2_MV_MEM_O_L3:
793 case RSP_GBI2_MV_MEM_O_L4:
794 case RSP_GBI2_MV_MEM_O_L5:
795 case RSP_GBI2_MV_MEM_O_L6:
796 case RSP_GBI2_MV_MEM_O_L7:
797 LOG_UCODE("Zelda Move Light");
798 RDP_NOIMPL_WARN("Zelda Move Light");
799 break;
800
801 case RSP_GBI2_MV_MEM__POINT:
802 LOG_UCODE("Zelda Move Point");
803 void RDP_NOIMPL_WARN(const char* op);
804 RDP_NOIMPL_WARN("Zelda Move Point");
805 break;
806
807 case RSP_GBI2_MV_MEM_O_LOOKATX:
808 if( (gfx->words.w0) == 0xDC170000 && ((gfx->words.w1)&0xFF000000) == 0x80000000 )
809 {
810 // Ucode for Evangelion.v64, the ObjMatrix cmd
811 RSP_S2DEX_OBJ_MOVEMEM(gfx);
812 }
813 break;
814 case RSP_GBI2_MV_MEM_O_LOOKATY:
815 RSP_RDP_NOIMPL("Not implemented ZeldaMoveMem LOOKATY, Cmd0=0x%08X, Cmd1=0x%08X", gfx->words.w0, gfx->words.w1);
816 break;
817 case 0x02:
818 if( (gfx->words.w0) == 0xDC070002 && ((gfx->words.w1)&0xFF000000) == 0x80000000 )
819 {
820 RSP_S2DEX_OBJ_MOVEMEM(gfx);
821 break;
822 }
823 default:
824 LOG_UCODE("ZeldaMoveMem Type: Unknown");
825 RSP_RDP_NOIMPL("Unknown ZeldaMoveMem Type, type=0x%X, Addr=%08X", type, addr);
826 break;
827 }
828}
829
830
831
832void RSP_GBI2_DL(Gfx *gfx)
833{
834 SP_Timing(RSP_GBI0_DL);
835
836 uint32 dwPush = ((gfx->words.w0) >> 16) & 0xFF;
837 uint32 dwAddr = RSPSegmentAddr((gfx->words.w1));
838
839 if( dwAddr > g_dwRamSize )
840 {
841 RSP_RDP_NOIMPL("Error: DL addr = %08X out of range, PC=%08X", dwAddr, gDlistStack[gDlistStackPointer].pc );
842 dwAddr &= (g_dwRamSize-1);
843 DebuggerPauseCountN( NEXT_DLIST );
844 }
845
846 LOG_UCODE(" DL: Push:0x%02x Addr: 0x%08x", dwPush, dwAddr);
847
848 switch (dwPush)
849 {
850 case RSP_DLIST_PUSH:
851 LOG_UCODE(" Pushing ZeldaDisplayList 0x%08x", dwAddr);
852 gDlistStackPointer++;
853 gDlistStack[gDlistStackPointer].pc = dwAddr;
854 gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT;
855
856 break;
857 case RSP_DLIST_NOPUSH:
858 LOG_UCODE(" Jumping to ZeldaDisplayList 0x%08x", dwAddr);
859 if( gDlistStack[gDlistStackPointer].pc == dwAddr+8 ) //Is this a loop
860 {
861 //Hack for Gauntlet Legends
862 gDlistStack[gDlistStackPointer].pc = dwAddr+8;
863 }
864 else
865 gDlistStack[gDlistStackPointer].pc = dwAddr;
866 gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT;
867 break;
868 }
869
870 LOG_UCODE("");
871 LOG_UCODE("\\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/");
872 LOG_UCODE("#############################################");
873}
874
875
876void RSP_GBI2_SetOtherModeL(Gfx *gfx)
877{
878 SP_Timing(RSP_GBI1_SetOtherModeL);
879
880 uint32 dwShift = ((gfx->words.w0)>>8)&0xFF;
881 uint32 dwLength= ((gfx->words.w0) )&0xFF;
882 uint32 dwData = (gfx->words.w1);
883
884 // Mask is constructed slightly differently
885 uint32 dwMask = (uint32)((s32)(0x80000000)>>dwLength)>>dwShift;
886 dwData &= dwMask;
887
888 uint32 modeL = gRDP.otherModeL;
889 modeL = (modeL&(~dwMask)) | dwData;
890
891 Gfx tempgfx;
892 tempgfx.words.w0 = gRDP.otherModeH;
893 tempgfx.words.w1 = modeL;
894 DLParser_RDPSetOtherMode(&tempgfx );
895}
896
897
898void RSP_GBI2_SetOtherModeH(Gfx *gfx)
899{
900 SP_Timing(RSP_GBI1_SetOtherModeH);
901
902 uint32 dwLength= (((gfx->words.w0))&0xFF)+1;
903 uint32 dwShift = 32 - (((gfx->words.w0)>>8)&0xFF) - dwLength;
904 uint32 dwData = (gfx->words.w1);
905
906 uint32 dwMask2 = ((1<<dwLength)-1)<<dwShift;
907 uint32 dwModeH = gRDP.otherModeH;
908 dwModeH = (dwModeH&(~dwMask2)) | dwData;
909
910 Gfx tempgfx;
911 tempgfx.words.w0 = dwModeH;
912 tempgfx.words.w1 = gRDP.otherModeL;
913 DLParser_RDPSetOtherMode(&tempgfx );
914}
915
916
917void RSP_GBI2_SubModule(Gfx *gfx)
918{
919 SP_Timing(RSP_GBI2_SubModule);
920
921 RSP_RDP_NOIMPL("RDP: RSP_GBI2_SubModule (0x%08x 0x%08x)", (gfx->words.w0), (gfx->words.w1));
922}
923