Rice Video Plugin for GLES1.1
[mupen64plus-pandora.git] / source / rice_gles / src / RSP_GBI1.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_GBI1_Vtx(Gfx *gfx)
24{
25 uint32 addr = RSPSegmentAddr((gfx->gbi1vtx.addr));
26 uint32 v0 = gfx->gbi1vtx.v0;
27 uint32 n = gfx->gbi1vtx.n;
28
29 LOG_UCODE(" Address 0x%08x, v0: %d, Num: %d, Length: 0x%04x", addr, v0, n, gfx->gbi1vtx.len);
30
31 if (addr > g_dwRamSize)
32 {
33 TRACE0(" Address out of range - ignoring load");
34 return;
35 }
36
37 if ((v0 + n) > 80)
38 {
39 TRACE5("Warning, invalid vertex positions, N=%d, v0=%d, Addr=0x%08X, Cmd=%08X-%08X",
40 n, v0, addr, gfx->words.w0, gfx->words.w1);
41 return;
42 }
43
44 ProcessVertexData(addr, v0, n);
45 status.dwNumVertices += n;
46 DisplayVertexInfo(addr, v0, n);
47}
48
49void RSP_GBI1_ModifyVtx(Gfx *gfx)
50{
51 SP_Timing(RSP_GBI1_ModifyVtx);
52
53 if( gRSP.ucode == 5 && ((gfx->words.w0)&0x00FFFFFF) == 0 && ((gfx->words.w1)&0xFF000000) == 0x80000000 )
54 {
55 DLParser_Bomberman2TextRect(gfx);
56 }
57 else
58 {
59 uint32 dwWhere = ((gfx->words.w0) >> 16) & 0xFF;
60 uint32 dwVert = (((gfx->words.w0) ) & 0xFFFF) / 2;
61 uint32 dwValue = (gfx->words.w1);
62
63 if( dwVert > 80 )
64 {
65 RSP_RDP_NOIMPL("RSP_GBI1_ModifyVtx: Invalid vertex number: %d", dwVert, 0);
66 return;
67 }
68
69 // Data for other commands?
70 switch (dwWhere)
71 {
72 case RSP_MV_WORD_OFFSET_POINT_RGBA: // Modify RGBA
73 case RSP_MV_WORD_OFFSET_POINT_XYSCREEN: // Modify X,Y
74 case RSP_MV_WORD_OFFSET_POINT_ZSCREEN: // Modify C
75 case RSP_MV_WORD_OFFSET_POINT_ST: // Texture
76 ModifyVertexInfo(dwWhere, dwVert, dwValue);
77 break;
78 default:
79 RSP_RDP_NOIMPL("RSP_GBI1_ModifyVtx: Setting unk value: 0x%02x, 0x%08x", dwWhere, dwValue);
80 break;
81 }
82 }
83}
84
85void RSP_GBI1_Tri2(Gfx *gfx)
86{
87 status.primitiveType = PRIM_TRI2;
88 bool bTrisAdded = false;
89 bool bTexturesAreEnabled = CRender::g_pRender->IsTextureEnabled();
90
91 // While the next command pair is Tri2, add vertices
92 uint32 dwPC = gDlistStack[gDlistStackPointer].pc;
93
94 do {
95 // Vertex indices are multiplied by 10 for Mario64, by 2 for MarioKart
96 uint32 dwV0 = gfx->gbi1tri2.v0/gRSP.vertexMult;
97 uint32 dwV1 = gfx->gbi1tri2.v1/gRSP.vertexMult;
98 uint32 dwV2 = gfx->gbi1tri2.v2/gRSP.vertexMult;
99
100 uint32 dwV3 = gfx->gbi1tri2.v3/gRSP.vertexMult;
101 uint32 dwV4 = gfx->gbi1tri2.v4/gRSP.vertexMult;
102 uint32 dwV5 = gfx->gbi1tri2.v5/gRSP.vertexMult;
103
104 // Do first tri
105 if (IsTriangleVisible(dwV0, dwV1, dwV2))
106 {
107 DEBUG_DUMP_VERTEXES("Tri2 1/2", dwV0, dwV1, dwV2);
108 if (!bTrisAdded)
109 {
110 if( bTexturesAreEnabled )
111 {
112 PrepareTextures();
113 InitVertexTextureConstants();
114 }
115
116 CRender::g_pRender->SetCombinerAndBlender();
117 bTrisAdded = true;
118 }
119 PrepareTriangle(dwV0, dwV1, dwV2);
120 }
121
122 // Do second tri
123 if (IsTriangleVisible(dwV3, dwV4, dwV5))
124 {
125 DEBUG_DUMP_VERTEXES("Tri2 2/2", dwV3, dwV4, dwV5);
126 if (!bTrisAdded)
127 {
128 if( bTexturesAreEnabled )
129 {
130 PrepareTextures();
131 InitVertexTextureConstants();
132 }
133
134 CRender::g_pRender->SetCombinerAndBlender();
135 bTrisAdded = true;
136 }
137 PrepareTriangle(dwV3, dwV4, dwV5);
138 }
139
140 gfx++;
141 dwPC += 8;
142#ifdef DEBUGGER
143 } while (!(pauseAtNext && eventToPause==NEXT_TRIANGLE) && gfx->words.cmd == (uint8)RSP_TRI2);
144#else
145 } while( gfx->words.cmd == (uint8)RSP_TRI2);
146#endif
147
148
149 gDlistStack[gDlistStackPointer].pc = dwPC-8;
150
151
152 if (bTrisAdded)
153 {
154 CRender::g_pRender->DrawTriangles();
155 }
156
157 DEBUG_TRIANGLE(TRACE0("Pause at GBI1 TRI1"));
158}
159
160extern XVECTOR4 g_vtxNonTransformed[MAX_VERTS];
161
162void RSP_GBI1_BranchZ(Gfx *gfx)
163{
164 SP_Timing(RSP_GBI1_BranchZ);
165
166 uint32 vtx = ((gfx->words.w0)&0xFFF)>>1;
167 float vtxdepth = g_vecProjected[vtx].z/g_vecProjected[vtx].w;
168
169#ifdef DEBUGGER
170 if( debuggerEnableZBuffer==FALSE || vtxdepth <= (s32)gfx->words.w1 || g_curRomInfo.bForceDepthBuffer )
171#else
172 if( vtxdepth <= (s32)(gfx->words.w1) || g_curRomInfo.bForceDepthBuffer )
173#endif
174 {
175 uint32 dwPC = gDlistStack[gDlistStackPointer].pc; // This points to the next instruction
176 uint32 dwDL = *(uint32 *)(g_pRDRAMu8 + dwPC-12);
177 uint32 dwAddr = RSPSegmentAddr(dwDL);
178
179 dwAddr = RSPSegmentAddr(dwDL);;
180
181 LOG_UCODE("BranchZ to DisplayList 0x%08x", dwAddr);
182 gDlistStack[gDlistStackPointer].pc = dwAddr;
183 gDlistStack[gDlistStackPointer].countdown = MAX_DL_COUNT;
184 }
185}
186
187#ifdef DEBUGGER
188void DumpUcodeInfo(UcodeInfo &info)
189{
190 DebuggerAppendMsg("Loading Unknown Ucode:\n%08X-%08X-%08X-%08X, Size=0x%X, CRC=0x%08X\nCode:\n",
191 info.ucDWORD1, info.ucDWORD2, info.ucDWORD3, info.ucDWORD4,
192 info.ucSize, info.ucCRC);
193 DumpHex(info.ucStart,20);
194 TRACE0("Data:\n");
195 DumpHex(info.ucDStart,20);
196}
197#endif
198
199void RSP_GBI1_LoadUCode(Gfx *gfx)
200{
201 SP_Timing(RSP_GBI1_LoadUCode);
202
203 //TRACE0("Load ucode");
204 uint32 dwPC = gDlistStack[gDlistStackPointer].pc;
205 uint32 dwUcStart = RSPSegmentAddr((gfx->words.w1));
206 uint32 dwSize = ((gfx->words.w0)&0xFFFF)+1;
207 uint32 dwUcDStart = RSPSegmentAddr(*(uint32 *)(g_pRDRAMu8 + dwPC-12));
208
209 uint32 ucode = DLParser_CheckUcode(dwUcStart, dwUcDStart, dwSize, 8);
210 RSP_SetUcode(ucode, dwUcStart, dwUcDStart, dwSize);
211
212 DEBUGGER_PAUSE_AND_DUMP(NEXT_SWITCH_UCODE,{DebuggerAppendMsg("Pause at loading ucode");});
213}
214
215void RSP_GFX_Force_Matrix(uint32 dwAddr)
216{
217 if (dwAddr + 64 > g_dwRamSize)
218 {
219 DebuggerAppendMsg("ForceMtx: Address invalid (0x%08x)", dwAddr);
220 return;
221 }
222
223 // Load matrix from dwAddr
224 LoadMatrix(dwAddr);
225
226 CRender::g_pRender->SetWorldProjectMatrix(matToLoad);
227
228 DEBUGGER_PAUSE_AND_DUMP(NEXT_MATRIX_CMD,{TRACE0("Paused at ModMatrix Cmd");});
229}
230
231
232void DisplayVertexInfo(uint32 dwAddr, uint32 dwV0, uint32 dwN)
233{
234#ifdef DEBUGGER
235 s8 *pcSrc = (s8 *)(g_pRDRAMu8 + dwAddr);
236 short *psSrc = (short *)(g_pRDRAMu8 + dwAddr);
237
238 for (uint32 dwV = dwV0; dwV < dwV0 + dwN; dwV++)
239 {
240 float x = (float)psSrc[0^0x1];
241 float y = (float)psSrc[1^0x1];
242 float z = (float)psSrc[2^0x1];
243
244 //uint32 wFlags = g_dwVtxFlags[dwV]; //(uint16)psSrc[3^0x1];
245 uint32 wFlags = 0;
246
247 uint8 a = pcSrc[12^0x3];
248 uint8 b = pcSrc[13^0x3];
249 uint8 c = pcSrc[14^0x3];
250 uint8 d = pcSrc[15^0x3];
251
252 //int nTU = (int)(short)(psSrc[4^0x1]<<4);
253 //int nTV = (int)(short)(psSrc[5^0x1]<<4);
254
255 //float tu = (float)(nTU>>4);
256 //float tv = (float)(nTV>>4);
257 float tu = (float)(short)(psSrc[4^0x1]);
258 float tv = (float)(short)(psSrc[5^0x1]);
259
260 XVECTOR4 & t = g_vecProjected[dwV];
261
262 psSrc += 8; // Increase by 16 bytes
263 pcSrc += 16;
264
265 LOG_UCODE(" #%02d Flags: 0x%04x Pos: {% 6f,% 6f,% 6f} Tex: {%+7.2f,%+7.2f}, Extra: %02x %02x %02x %02x (transf: {% 6f,% 6f,% 6f})",
266 dwV, wFlags, x, y, z, tu, tv, a, b, c, d, t.x, t.y, t.z );
267 }
268#endif
269}
270
271void RSP_MoveMemLight(uint32 dwLight, uint32 dwAddr)
272{
273 if( dwLight >= 16 )
274 {
275 DebuggerAppendMsg("Warning: invalid light # = %d", dwLight);
276 return;
277 }
278
279 s8 * pcBase = g_pRDRAMs8 + dwAddr;
280 uint32 * pdwBase = (uint32 *)pcBase;
281
282
283 float range = 0, x, y, z;
284 if( options.enableHackForGames == HACK_FOR_ZELDA_MM && (pdwBase[0]&0xFF) == 0x08 && (pdwBase[1]&0xFF) == 0xFF )
285 {
286 gRSPn64lights[dwLight].dwRGBA = pdwBase[0];
287 gRSPn64lights[dwLight].dwRGBACopy = pdwBase[1];
288 short* pdwBase16 = (short*)pcBase;
289 x = pdwBase16[5];
290 y = pdwBase16[4];
291 z = pdwBase16[7];
292 range = pdwBase16[6];
293 }
294 else
295 {
296 gRSPn64lights[dwLight].dwRGBA = pdwBase[0];
297 gRSPn64lights[dwLight].dwRGBACopy = pdwBase[1];
298 x = pcBase[8 ^ 0x3];
299 y = pcBase[9 ^ 0x3];
300 z = pcBase[10 ^ 0x3];
301 }
302
303
304 LOG_UCODE(" RGBA: 0x%08x, RGBACopy: 0x%08x, x: %d, y: %d, z: %d",
305 gRSPn64lights[dwLight].dwRGBA,
306 gRSPn64lights[dwLight].dwRGBACopy,
307 x, y, z);
308
309 LIGHT_DUMP(TRACE3("Move Light: %08X, %08X, %08X", pdwBase[0], pdwBase[1], pdwBase[2]));
310
311
312 if (dwLight == gRSP.ambientLightIndex)
313 {
314 LOG_UCODE(" (Ambient Light)");
315
316 uint32 dwCol = COLOR_RGBA( (gRSPn64lights[dwLight].dwRGBA >> 24)&0xFF,
317 (gRSPn64lights[dwLight].dwRGBA >> 16)&0xFF,
318 (gRSPn64lights[dwLight].dwRGBA >> 8)&0xFF, 0xff);
319
320 SetAmbientLight( dwCol );
321 }
322 else
323 {
324 LOG_UCODE(" (Normal Light)");
325
326 SetLightCol(dwLight, gRSPn64lights[dwLight].dwRGBA);
327 if (pdwBase[2] == 0) // Direction is 0!
328 {
329 LOG_UCODE(" Light is invalid");
330 }
331 SetLightDirection(dwLight, x, y, z, range);
332 }
333}
334
335void RSP_MoveMemViewport(uint32 dwAddr)
336{
337 if( dwAddr+16 >= g_dwRamSize )
338 {
339 TRACE0("MoveMem Viewport, invalid memory");
340 return;
341 }
342
343 short scale[4];
344 short trans[4];
345
346 // dwAddr is offset into RD_RAM of 8 x 16bits of data...
347 scale[0] = *(short *)(g_pRDRAMu8 + ((dwAddr+(0*2))^0x2));
348 scale[1] = *(short *)(g_pRDRAMu8 + ((dwAddr+(1*2))^0x2));
349 scale[2] = *(short *)(g_pRDRAMu8 + ((dwAddr+(2*2))^0x2));
350 scale[3] = *(short *)(g_pRDRAMu8 + ((dwAddr+(3*2))^0x2));
351
352 trans[0] = *(short *)(g_pRDRAMu8 + ((dwAddr+(4*2))^0x2));
353 trans[1] = *(short *)(g_pRDRAMu8 + ((dwAddr+(5*2))^0x2));
354 trans[2] = *(short *)(g_pRDRAMu8 + ((dwAddr+(6*2))^0x2));
355 trans[3] = *(short *)(g_pRDRAMu8 + ((dwAddr+(7*2))^0x2));
356
357
358 int nCenterX = trans[0]/4;
359 int nCenterY = trans[1]/4;
360 int nWidth = scale[0]/4;
361 int nHeight = scale[1]/4;
362
363 // Check for some strange games
364 if( nWidth < 0 ) nWidth = -nWidth;
365 if( nHeight < 0 ) nHeight = -nHeight;
366
367 int nLeft = nCenterX - nWidth;
368 int nTop = nCenterY - nHeight;
369 int nRight= nCenterX + nWidth;
370 int nBottom= nCenterY + nHeight;
371
372 //int maxZ = scale[2];
373 int maxZ = 0x3FF;
374
375 CRender::g_pRender->SetViewport(nLeft, nTop, nRight, nBottom, maxZ);
376
377 LOG_UCODE(" Scale: %d %d %d %d = %d,%d", scale[0], scale[1], scale[2], scale[3], nWidth, nHeight);
378 LOG_UCODE(" Trans: %d %d %d %d = %d,%d", trans[0], trans[1], trans[2], trans[3], nCenterX, nCenterY);
379}
380
381
382// S2DEX uses this - 0xc1
383void RSP_S2DEX_SPObjLoadTxtr_Ucode1(Gfx *gfx)
384{
385 SP_Timing(RSP_S2DEX_SPObjLoadTxtr_Ucode1);
386
387 // Add S2DEX ucode supporting to F3DEX, see game DT and others
388 status.bUseModifiedUcodeMap = true;
389 RSP_SetUcode(1);
390 memcpy( &LoadedUcodeMap, &ucodeMap1, sizeof(UcodeMap));
391
392 LoadedUcodeMap[S2DEX_OBJ_MOVEMEM] = &RSP_S2DEX_OBJ_MOVEMEM;
393 LoadedUcodeMap[S2DEX_OBJ_LOADTXTR] = &RSP_S2DEX_SPObjLoadTxtr;
394 LoadedUcodeMap[S2DEX_OBJ_LDTX_SPRITE] = &RSP_S2DEX_SPObjLoadTxSprite;
395 LoadedUcodeMap[S2DEX_OBJ_LDTX_RECT] = &RSP_S2DEX_SPObjLoadTxRect;
396 LoadedUcodeMap[S2DEX_OBJ_LDTX_RECT_R] = &RSP_S2DEX_SPObjLoadTxRectR;
397
398 RSP_S2DEX_SPObjLoadTxtr(gfx);
399}
400