Rice GLES2 (from mupen64plus-ae) plugin. Compile but doesn't works well on the OpenPa...
[mupen64plus-pandora.git] / source / gles2rice / src / RSP_GBI1.h
1 /*
2 Copyright (C) 2002 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 "Render.h"
21 #include "Timing.h"
22
23 void 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
49 void 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
85 void 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
160 extern XVECTOR4 g_vtxNonTransformed[MAX_VERTS];
161
162 void 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
188 void 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
199 void 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
215 void 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
232 void 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
271 void 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
335 void 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
383 void 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