GLES2N64: Some fixes from mupen64plus-ae team
[mupen64plus-pandora.git] / source / gles2n64 / src / gSP.cpp
CommitLineData
34cf4058 1#include <math.h>
2#include <stdlib.h>
3
4#include "Common.h"
5#include "gles2N64.h"
6#include "Debug.h"
7#include "Types.h"
8#include "RSP.h"
9#include "GBI.h"
10#include "gSP.h"
11#include "gDP.h"
12#include "3DMath.h"
13#include "OpenGL.h"
14#include "CRC.h"
15#include <string.h>
16#include "convert.h"
17#include "S2DEX.h"
18#include "VI.h"
19#include "DepthBuffer.h"
20#include "Config.h"
21
22//Note: 0xC0 is used by 1080 alot, its an unknown command.
23
24#ifdef DEBUG
25extern u32 uc_crc, uc_dcrc;
26extern char uc_str[256];
27#endif
28
29void gSPCombineMatrices();
30
31//#ifdef __TRIBUFFER_OPT
32void __indexmap_init()
33{
34 memset(OGL.triangles.indexmapinv, 0xFF, VERTBUFF_SIZE*sizeof(u32));
35 for(int i=0;i<INDEXMAP_SIZE;i++)
36 {
37 OGL.triangles.indexmap[i] = i;
38 //OGL.triangles.indexmapinv[i] = i;
39 }
40
41 OGL.triangles.indexmap_prev = -1;
42 OGL.triangles.indexmap_nomap = 0;
43}
44
45void __indexmap_clear()
46{
47 memset(OGL.triangles.indexmapinv, 0xFF, VERTBUFF_SIZE * sizeof(u32));
48 for(int i=0;i<INDEXMAP_SIZE;i++)
49 OGL.triangles.indexmapinv[OGL.triangles.indexmap[i]] = i;
50}
51
52u32 __indexmap_findunused(u32 num)
53{
54 u32 c = 0;
55 u32 i = min(OGL.triangles.indexmap_prev+1, VERTBUFF_SIZE-1);
56 u32 n = 0;
57 while(n < VERTBUFF_SIZE)
58 {
59 c = (OGL.triangles.indexmapinv[i] == 0xFFFFFFFF) ? (c+1) : 0;
60 if ((c == num) && (i < (VERTBUFF_SIZE - num)))
61 {
62 break;
63 }
64 i=i+1;
65 if (i >= VERTBUFF_SIZE) {i=0; c=0;}
66 n++;
67 }
68 return (c == num) ? (i-num+1) : (0xFFFFFFFF);
69}
70
71void __indexmap_undomap()
72{
73 SPVertex tmp[INDEXMAP_SIZE];
74 memset(OGL.triangles.indexmapinv, 0xFF, VERTBUFF_SIZE * sizeof(u32));
75
76 for(int i=0;i<INDEXMAP_SIZE;i++)
77 {
78 u32 ind = OGL.triangles.indexmap[i];
79 tmp[i] = OGL.triangles.vertices[ind];
80 OGL.triangles.indexmap[i] = i;
81 OGL.triangles.indexmapinv[i] = i;
82 }
83
84 memcpy(OGL.triangles.vertices, tmp, INDEXMAP_SIZE * sizeof(SPVertex));
85 OGL.triangles.indexmap_nomap = 1;
86}
87
88u32 __indexmap_getnew(u32 index, u32 num)
89{
90 u32 ind;
91
92 //test to see if unmapped
93 u32 unmapped = 1;
94 for(int i=0;i<num;i++)
95 {
96 if (OGL.triangles.indexmap[i]!=0xFFFFFFFF)
97 {
98 unmapped = 0;
99 break;
100 }
101
102 }
103
104 if (unmapped)
105 {
106 ind = index;
107 }
108 else
109 {
110 ind = __indexmap_findunused(num);
111
112 //no more room in buffer....
113 if (ind > VERTBUFF_SIZE)
114 {
115 OGL_DrawTriangles();
116 ind = __indexmap_findunused(num);
117
118 //OK the indices are spread so sparsely, we cannot find a num element block.
119 if (ind > VERTBUFF_SIZE)
120 {
121 __indexmap_undomap();
122 ind = __indexmap_findunused(num);
123 if (ind > VERTBUFF_SIZE)
124 {
125 LOG(LOG_ERROR, "Could not allocate %i indices\n", num);
126
127 LOG(LOG_VERBOSE, "indexmap=[");
128 for(int i=0;i<INDEXMAP_SIZE;i++)
129 LOG(LOG_VERBOSE, "%i,", OGL.triangles.indexmap[i]);
130 LOG(LOG_VERBOSE, "]\n");
131
132 LOG(LOG_VERBOSE, "indexmapinv=[");
133 for(int i=0;i<VERTBUFF_SIZE;i++)
134 LOG(LOG_VERBOSE, "%i,", OGL.triangles.indexmapinv[i]);
135 LOG(LOG_VERBOSE, "]\n");
136 }
137 return ind;
138 }
139 }
140 }
141
142 for(int i=0;i<num;i++)
143 {
144 OGL.triangles.indexmap[index+i] = ind+i;
145 OGL.triangles.indexmapinv[ind+i] = index+i;
146 }
147
148 OGL.triangles.indexmap_prev = ind+num-1;
149 OGL.triangles.indexmap_nomap = 0;
150
151 return ind;
152}
153//#endif
154
155void gSPTriangle(s32 v0, s32 v1, s32 v2)
156{
157 if ((v0 < INDEXMAP_SIZE) && (v1 < INDEXMAP_SIZE) && (v2 < INDEXMAP_SIZE))
158 {
159
160#ifdef __TRIBUFFER_OPT
161 v0 = OGL.triangles.indexmap[v0];
162 v1 = OGL.triangles.indexmap[v1];
163 v2 = OGL.triangles.indexmap[v2];
164#endif
165
166#if 0
167 // Don't bother with triangles completely outside clipping frustrum
168 if (config.enableClipping)
169 {
170 if (OGL.triangles.vertices[v0].clip & OGL.triangles.vertices[v1].clip & OGL.triangles.vertices[v2].clip)
171 {
172 return;
173 }
174 }
175#endif
176
177 OGL_AddTriangle(v0, v1, v2);
178
179 }
180
181 if (depthBuffer.current) depthBuffer.current->cleared = FALSE;
182 gDP.colorImage.changed = TRUE;
183 gDP.colorImage.height = (unsigned int)(max( gDP.colorImage.height, gDP.scissor.lry ));
184}
185
186void gSP1Triangle( const s32 v0, const s32 v1, const s32 v2)
187{
188 gSPTriangle( v0, v1, v2);
189 gSPFlushTriangles();
190}
191
192void gSP2Triangles(const s32 v00, const s32 v01, const s32 v02, const s32 flag0,
193 const s32 v10, const s32 v11, const s32 v12, const s32 flag1 )
194{
195 gSPTriangle( v00, v01, v02);
196 gSPTriangle( v10, v11, v12);
197 gSPFlushTriangles();
198}
199
200void gSP4Triangles(const s32 v00, const s32 v01, const s32 v02,
201 const s32 v10, const s32 v11, const s32 v12,
202 const s32 v20, const s32 v21, const s32 v22,
203 const s32 v30, const s32 v31, const s32 v32 )
204{
205 gSPTriangle(v00, v01, v02);
206 gSPTriangle(v10, v11, v12);
207 gSPTriangle(v20, v21, v22);
208 gSPTriangle(v30, v31, v32);
209 gSPFlushTriangles();
210}
211
212
213gSPInfo gSP;
214
215f32 identityMatrix[4][4] =
216{
217 { 1.0f, 0.0f, 0.0f, 0.0f },
218 { 0.0f, 1.0f, 0.0f, 0.0f },
219 { 0.0f, 0.0f, 1.0f, 0.0f },
220 { 0.0f, 0.0f, 0.0f, 1.0f }
221};
222
223#ifdef __VEC4_OPT
224static void gSPTransformVertex4_default(u32 v, float mtx[4][4])
225{
226 float x, y, z, w;
227 int i;
228 for(i = 0; i < 4; i++)
229 {
230 x = OGL.triangles.vertices[v+i].x;
231 y = OGL.triangles.vertices[v+i].y;
232 z = OGL.triangles.vertices[v+i].z;
233 w = OGL.triangles.vertices[v+i].w;
234 OGL.triangles.vertices[v+i].x = x * mtx[0][0] + y * mtx[1][0] + z * mtx[2][0] + mtx[3][0];
235 OGL.triangles.vertices[v+i].y = x * mtx[0][1] + y * mtx[1][1] + z * mtx[2][1] + mtx[3][1];
236 OGL.triangles.vertices[v+i].z = x * mtx[0][2] + y * mtx[1][2] + z * mtx[2][2] + mtx[3][2];
237 OGL.triangles.vertices[v+i].w = x * mtx[0][3] + y * mtx[1][3] + z * mtx[2][3] + mtx[3][3];
238 }
239}
240
241void gSPClipVertex4(u32 v)
242{
243 int i;
244 for(i = 0; i < 4; i++){
245 SPVertex *vtx = &OGL.triangles.vertices[v+i];
246 vtx->clip = 0;
247 if (vtx->x > +vtx->w) vtx->clip |= CLIP_POSX;
248 if (vtx->x < -vtx->w) vtx->clip |= CLIP_NEGX;
249 if (vtx->y > +vtx->w) vtx->clip |= CLIP_POSY;
250 if (vtx->y < -vtx->w) vtx->clip |= CLIP_NEGY;
251 }
252}
253
254static void gSPTransformNormal4_default(u32 v, float mtx[4][4])
255{
256 float len, x, y, z;
257 int i;
258 for(i = 0; i < 4; i++){
259 x = OGL.triangles.vertices[v+i].nx;
260 y = OGL.triangles.vertices[v+i].ny;
261 z = OGL.triangles.vertices[v+i].nz;
262
263 OGL.triangles.vertices[v+i].nx = mtx[0][0]*x + mtx[1][0]*y + mtx[2][0]*z;
264 OGL.triangles.vertices[v+i].ny = mtx[0][1]*x + mtx[1][1]*y + mtx[2][1]*z;
265 OGL.triangles.vertices[v+i].nz = mtx[0][2]*x + mtx[1][2]*y + mtx[2][2]*z;
266 len = OGL.triangles.vertices[v+i].nx*OGL.triangles.vertices[v+i].nx +
267 OGL.triangles.vertices[v+i].ny*OGL.triangles.vertices[v+i].ny +
268 OGL.triangles.vertices[v+i].nz*OGL.triangles.vertices[v+i].nz;
269 if (len != 0.0)
270 {
271 len = sqrtf(len);
272 OGL.triangles.vertices[v+i].nx /= len;
273 OGL.triangles.vertices[v+i].ny /= len;
274 OGL.triangles.vertices[v+i].nz /= len;
275 }
276 }
277}
278
279static void gSPLightVertex4_default(u32 v)
280{
281 gSPTransformNormal4(v, gSP.matrix.modelView[gSP.matrix.modelViewi]);
282 for(int j = 0; j < 4; j++)
283 {
284 f32 r,g,b;
285 r = gSP.lights[gSP.numLights].r;
286 g = gSP.lights[gSP.numLights].g;
287 b = gSP.lights[gSP.numLights].b;
288
289 for (int i = 0; i < gSP.numLights; i++)
290 {
291 f32 intensity = DotProduct( &OGL.triangles.vertices[v+j].nx, &gSP.lights[i].x );
292 if (intensity < 0.0f) intensity = 0.0f;
293/*
294// paulscode, cause of the shader bug (not applying intensity to correct varriables)
295 OGL.triangles.vertices[v+j].r += gSP.lights[i].r * intensity;
296 OGL.triangles.vertices[v+j].g += gSP.lights[i].g * intensity;
297 OGL.triangles.vertices[v+j].b += gSP.lights[i].b * intensity;
298*/
299//// paulscode, shader bug-fix:
300 r += gSP.lights[i].r * intensity;
301 g += gSP.lights[i].g * intensity;
302 b += gSP.lights[i].b * intensity;
303////
304 }
305 OGL.triangles.vertices[v+j].r = min(1.0f, r);
306 OGL.triangles.vertices[v+j].g = min(1.0f, g);
307 OGL.triangles.vertices[v+j].b = min(1.0f, b);
308 }
309}
310
311static void gSPBillboardVertex4_default(u32 v)
312{
313
314 int i = 0;
315#ifdef __TRIBUFFER_OPT
316 i = OGL.triangles.indexmap[0];
317#endif
318
319 OGL.triangles.vertices[v].x += OGL.triangles.vertices[i].x;
320 OGL.triangles.vertices[v].y += OGL.triangles.vertices[i].y;
321 OGL.triangles.vertices[v].z += OGL.triangles.vertices[i].z;
322 OGL.triangles.vertices[v].w += OGL.triangles.vertices[i].w;
323 OGL.triangles.vertices[v+1].x += OGL.triangles.vertices[i].x;
324 OGL.triangles.vertices[v+1].y += OGL.triangles.vertices[i].y;
325 OGL.triangles.vertices[v+1].z += OGL.triangles.vertices[i].z;
326 OGL.triangles.vertices[v+1].w += OGL.triangles.vertices[i].w;
327 OGL.triangles.vertices[v+2].x += OGL.triangles.vertices[i].x;
328 OGL.triangles.vertices[v+2].y += OGL.triangles.vertices[i].y;
329 OGL.triangles.vertices[v+2].z += OGL.triangles.vertices[i].z;
330 OGL.triangles.vertices[v+2].w += OGL.triangles.vertices[i].w;
331 OGL.triangles.vertices[v+3].x += OGL.triangles.vertices[i].x;
332 OGL.triangles.vertices[v+3].y += OGL.triangles.vertices[i].y;
333 OGL.triangles.vertices[v+3].z += OGL.triangles.vertices[i].z;
334 OGL.triangles.vertices[v+3].w += OGL.triangles.vertices[i].w;
335}
336
337void gSPProcessVertex4(u32 v)
338{
339 if (gSP.changed & CHANGED_MATRIX)
340 gSPCombineMatrices();
341
342 gSPTransformVertex4(v, gSP.matrix.combined );
343
344 if (config.screen.flipVertical)
345 {
346 OGL.triangles.vertices[v+0].y = -OGL.triangles.vertices[v+0].y;
347 OGL.triangles.vertices[v+1].y = -OGL.triangles.vertices[v+1].y;
348 OGL.triangles.vertices[v+2].y = -OGL.triangles.vertices[v+2].y;
349 OGL.triangles.vertices[v+3].y = -OGL.triangles.vertices[v+3].y;
350 }
351
352 if (gDP.otherMode.depthSource)
353 {
354 OGL.triangles.vertices[v+0].z = gDP.primDepth.z * OGL.triangles.vertices[v+0].w;
355 OGL.triangles.vertices[v+1].z = gDP.primDepth.z * OGL.triangles.vertices[v+1].w;
356 OGL.triangles.vertices[v+2].z = gDP.primDepth.z * OGL.triangles.vertices[v+2].w;
357 OGL.triangles.vertices[v+3].z = gDP.primDepth.z * OGL.triangles.vertices[v+3].w;
358 }
359
360 if (gSP.matrix.billboard)
361 gSPBillboardVertex4(v);
362
363 if (!(gSP.geometryMode & G_ZBUFFER))
364 {
365 OGL.triangles.vertices[v].z = -OGL.triangles.vertices[v].w;
366 OGL.triangles.vertices[v+1].z = -OGL.triangles.vertices[v+1].w;
367 OGL.triangles.vertices[v+2].z = -OGL.triangles.vertices[v+2].w;
368 OGL.triangles.vertices[v+3].z = -OGL.triangles.vertices[v+3].w;
369 }
370
371 if (gSP.geometryMode & G_LIGHTING)
372 {
373 if (config.enableLighting)
374 {
375 gSPLightVertex4(v);
376 }
377 else
378 {
379 OGL.triangles.vertices[v].r = 1.0f;
380 OGL.triangles.vertices[v].g = 1.0f;
381 OGL.triangles.vertices[v].b = 1.0f;
382 OGL.triangles.vertices[v+1].r = 1.0f;
383 OGL.triangles.vertices[v+1].g = 1.0f;
384 OGL.triangles.vertices[v+1].b = 1.0f;
385 OGL.triangles.vertices[v+2].r = 1.0f;
386 OGL.triangles.vertices[v+2].g = 1.0f;
387 OGL.triangles.vertices[v+2].b = 1.0f;
388 OGL.triangles.vertices[v+3].r = 1.0f;
389 OGL.triangles.vertices[v+3].g = 1.0f;
390 OGL.triangles.vertices[v+3].b = 1.0f;
391 }
392
393 if (gSP.geometryMode & G_TEXTURE_GEN)
394 {
395 gSPTransformNormal4(v, gSP.matrix.projection);
396
397 if (gSP.geometryMode & G_TEXTURE_GEN_LINEAR)
398 {
399 OGL.triangles.vertices[v].s = acosf(OGL.triangles.vertices[v].nx) * 325.94931f;
400 OGL.triangles.vertices[v].t = acosf(OGL.triangles.vertices[v].ny) * 325.94931f;
401 OGL.triangles.vertices[v+1].s = acosf(OGL.triangles.vertices[v+1].nx) * 325.94931f;
402 OGL.triangles.vertices[v+1].t = acosf(OGL.triangles.vertices[v+1].ny) * 325.94931f;
403 OGL.triangles.vertices[v+2].s = acosf(OGL.triangles.vertices[v+2].nx) * 325.94931f;
404 OGL.triangles.vertices[v+2].t = acosf(OGL.triangles.vertices[v+2].ny) * 325.94931f;
405 OGL.triangles.vertices[v+3].s = acosf(OGL.triangles.vertices[v+3].nx) * 325.94931f;
406 OGL.triangles.vertices[v+3].t = acosf(OGL.triangles.vertices[v+3].ny) * 325.94931f;
407 }
408 else // G_TEXTURE_GEN
409 {
410 OGL.triangles.vertices[v].s = (OGL.triangles.vertices[v].nx + 1.0f) * 512.0f;
411 OGL.triangles.vertices[v].t = (OGL.triangles.vertices[v].ny + 1.0f) * 512.0f;
412 OGL.triangles.vertices[v+1].s = (OGL.triangles.vertices[v+1].nx + 1.0f) * 512.0f;
413 OGL.triangles.vertices[v+1].t = (OGL.triangles.vertices[v+1].ny + 1.0f) * 512.0f;
414 OGL.triangles.vertices[v+2].s = (OGL.triangles.vertices[v+2].nx + 1.0f) * 512.0f;
415 OGL.triangles.vertices[v+2].t = (OGL.triangles.vertices[v+2].ny + 1.0f) * 512.0f;
416 OGL.triangles.vertices[v+3].s = (OGL.triangles.vertices[v+3].nx + 1.0f) * 512.0f;
417 OGL.triangles.vertices[v+3].t = (OGL.triangles.vertices[v+3].ny + 1.0f) * 512.0f;
418 }
419 }
420 }
421
422 if (config.enableClipping) gSPClipVertex4(v);
423}
424#endif
425
426void gSPClipVertex(u32 v)
427{
428 SPVertex *vtx = &OGL.triangles.vertices[v];
429 vtx->clip = 0;
430 if (vtx->x > +vtx->w) vtx->clip |= CLIP_POSX;
431 if (vtx->x < -vtx->w) vtx->clip |= CLIP_NEGX;
432 if (vtx->y > +vtx->w) vtx->clip |= CLIP_POSY;
433 if (vtx->y < -vtx->w) vtx->clip |= CLIP_NEGY;
434 //if (vtx->w < 0.1f) vtx->clip |= CLIP_NEGW;
435}
436
437static void gSPTransformVertex_default(float vtx[4], float mtx[4][4])
438{
439 float x, y, z, w;
440 x = vtx[0];
441 y = vtx[1];
442 z = vtx[2];
443 w = vtx[3];
444
445 vtx[0] = x * mtx[0][0] + y * mtx[1][0] + z * mtx[2][0] + mtx[3][0];
446 vtx[1] = x * mtx[0][1] + y * mtx[1][1] + z * mtx[2][1] + mtx[3][1];
447 vtx[2] = x * mtx[0][2] + y * mtx[1][2] + z * mtx[2][2] + mtx[3][2];
448 vtx[3] = x * mtx[0][3] + y * mtx[1][3] + z * mtx[2][3] + mtx[3][3];
449}
450
451static void gSPLightVertex_default(u32 v)
452{
453 TransformVectorNormalize( &OGL.triangles.vertices[v].nx, gSP.matrix.modelView[gSP.matrix.modelViewi] );
454
455 f32 r, g, b;
456 r = gSP.lights[gSP.numLights].r;
457 g = gSP.lights[gSP.numLights].g;
458 b = gSP.lights[gSP.numLights].b;
459 for (int i = 0; i < gSP.numLights; i++)
460 {
461 f32 intensity = DotProduct( &OGL.triangles.vertices[v].nx, &gSP.lights[i].x );
462 if (intensity < 0.0f) intensity = 0.0f;
463 r += gSP.lights[i].r * intensity;
464 g += gSP.lights[i].g * intensity;
465 b += gSP.lights[i].b * intensity;
466 }
467 OGL.triangles.vertices[v].r = min(1.0, r);
468 OGL.triangles.vertices[v].g = min(1.0, g);
469 OGL.triangles.vertices[v].b = min(1.0, b);
470}
471
472static void gSPBillboardVertex_default(u32 v, u32 i)
473{
474 OGL.triangles.vertices[v].x += OGL.triangles.vertices[i].x;
475 OGL.triangles.vertices[v].y += OGL.triangles.vertices[i].y;
476 OGL.triangles.vertices[v].z += OGL.triangles.vertices[i].z;
477 OGL.triangles.vertices[v].w += OGL.triangles.vertices[i].w;
478}
479
480void gSPCombineMatrices()
481{
482 MultMatrix(gSP.matrix.projection, gSP.matrix.modelView[gSP.matrix.modelViewi], gSP.matrix.combined);
483 gSP.changed &= ~CHANGED_MATRIX;
484}
485
486void gSPProcessVertex( u32 v )
487{
488 f32 intensity;
489 f32 r, g, b;
490
491 if (gSP.changed & CHANGED_MATRIX)
492 gSPCombineMatrices();
493
494 gSPTransformVertex( &OGL.triangles.vertices[v].x, gSP.matrix.combined );
495
496 if (config.screen.flipVertical)
497 {
498 OGL.triangles.vertices[v].y = -OGL.triangles.vertices[v].y;
499 }
500
501 if (gDP.otherMode.depthSource)
502 {
503 OGL.triangles.vertices[v].z = gDP.primDepth.z * OGL.triangles.vertices[v].w;
504 }
505
506 if (gSP.matrix.billboard)
507 {
508 int i = 0;
509#ifdef __TRIBUFFER_OPT
510 i = OGL.triangles.indexmap[0];
511#endif
512
513 gSPBillboardVertex(v, i);
514 }
515
516 if (!(gSP.geometryMode & G_ZBUFFER))
517 {
518 OGL.triangles.vertices[v].z = -OGL.triangles.vertices[v].w;
519 }
520
521 if (config.enableClipping)
522 gSPClipVertex(v);
523
524 if (gSP.geometryMode & G_LIGHTING)
525 {
526 if (config.enableLighting)
527 {
528 gSPLightVertex(v);
529 }
530 else
531 {
532 OGL.triangles.vertices[v].r = 1.0f;
533 OGL.triangles.vertices[v].g = 1.0f;
534 OGL.triangles.vertices[v].b = 1.0f;
535 }
536
537 if (gSP.geometryMode & G_TEXTURE_GEN)
538 {
539 TransformVectorNormalize(&OGL.triangles.vertices[v].nx, gSP.matrix.projection);
540
541 if (gSP.geometryMode & G_TEXTURE_GEN_LINEAR)
542 {
543 OGL.triangles.vertices[v].s = acosf(OGL.triangles.vertices[v].nx) * 325.94931f;
544 OGL.triangles.vertices[v].t = acosf(OGL.triangles.vertices[v].ny) * 325.94931f;
545 }
546 else // G_TEXTURE_GEN
547 {
548 OGL.triangles.vertices[v].s = (OGL.triangles.vertices[v].nx + 1.0f) * 512.0f;
549 OGL.triangles.vertices[v].t = (OGL.triangles.vertices[v].ny + 1.0f) * 512.0f;
550 }
551 }
552 }
553}
554
555
556void gSPLoadUcodeEx( u32 uc_start, u32 uc_dstart, u16 uc_dsize )
557{
558 RSP.PCi = 0;
559 gSP.matrix.modelViewi = 0;
560 gSP.changed |= CHANGED_MATRIX;
561 gSP.status[0] = gSP.status[1] = gSP.status[2] = gSP.status[3] = 0;
562
563 if ((((uc_start & 0x1FFFFFFF) + 4096) > RDRAMSize) || (((uc_dstart & 0x1FFFFFFF) + uc_dsize) > RDRAMSize))
564 {
565 return;
566 }
567
568 MicrocodeInfo *ucode = GBI_DetectMicrocode( uc_start, uc_dstart, uc_dsize );
569
570 if (ucode->type != 0xFFFFFFFF)
571 last_good_ucode = ucode->type;
572
573 if (ucode->type != NONE)
574 {
575 GBI_MakeCurrent( ucode );
576 }
577 else
578 {
579 LOG(LOG_WARNING, "Unknown Ucode\n");
580 }
581}
582
583void gSPNoOp()
584{
585 gSPFlushTriangles();
586}
587
588void gSPTriangleUnknown()
589{
590#ifdef __TRIBUFFER_OPT
591 gSPFlushTriangles();
592#endif
593}
594
595void gSPMatrix( u32 matrix, u8 param )
596{
597#ifdef __TRIBUFFER_OPT
598 gSPFlushTriangles();
599#endif
600
601 f32 mtx[4][4];
602 u32 address = RSP_SegmentToPhysical( matrix );
603
604 if (address + 64 > RDRAMSize)
605 {
606 return;
607 }
608
609 RSP_LoadMatrix( mtx, address );
610
611 if (param & G_MTX_PROJECTION)
612 {
613 if (param & G_MTX_LOAD)
614 CopyMatrix( gSP.matrix.projection, mtx );
615 else
616 MultMatrix2( gSP.matrix.projection, mtx );
617 }
618 else
619 {
620 if ((param & G_MTX_PUSH) && (gSP.matrix.modelViewi < (gSP.matrix.stackSize - 1)))
621 {
622 CopyMatrix( gSP.matrix.modelView[gSP.matrix.modelViewi + 1], gSP.matrix.modelView[gSP.matrix.modelViewi] );
623 gSP.matrix.modelViewi++;
624 }
625 if (param & G_MTX_LOAD)
626 CopyMatrix( gSP.matrix.modelView[gSP.matrix.modelViewi], mtx );
627 else
628 MultMatrix2( gSP.matrix.modelView[gSP.matrix.modelViewi], mtx );
629 }
630
631 gSP.changed |= CHANGED_MATRIX;
632}
633
634void gSPDMAMatrix( u32 matrix, u8 index, u8 multiply )
635{
636 f32 mtx[4][4];
637 u32 address = gSP.DMAOffsets.mtx + RSP_SegmentToPhysical( matrix );
638
639 if (address + 64 > RDRAMSize)
640 {
641 return;
642 }
643
644 RSP_LoadMatrix( mtx, address );
645
646 gSP.matrix.modelViewi = index;
647
648 if (multiply)
649 {
650 //CopyMatrix( gSP.matrix.modelView[gSP.matrix.modelViewi], gSP.matrix.modelView[0] );
651 //MultMatrix( gSP.matrix.modelView[gSP.matrix.modelViewi], mtx );
652 MultMatrix(gSP.matrix.modelView[0], mtx, gSP.matrix.modelView[gSP.matrix.modelViewi]);
653 }
654 else
655 CopyMatrix( gSP.matrix.modelView[gSP.matrix.modelViewi], mtx );
656
657 CopyMatrix( gSP.matrix.projection, identityMatrix );
658 gSP.changed |= CHANGED_MATRIX;
659}
660
661void gSPViewport( u32 v )
662{
663 u32 address = RSP_SegmentToPhysical( v );
664
665 if ((address + 16) > RDRAMSize)
666 {
667#ifdef DEBUG
668 DebugMsg( DEBUG_HIGH | DEBUG_ERROR, "// Attempting to load viewport from invalid address\n" );
669 DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gSPViewport( 0x%08X );\n", v );
670#endif
671 return;
672 }
673
674 gSP.viewport.vscale[0] = _FIXED2FLOAT( *(s16*)&RDRAM[address + 2], 2 );
675 gSP.viewport.vscale[1] = _FIXED2FLOAT( *(s16*)&RDRAM[address ], 2 );
676 gSP.viewport.vscale[2] = _FIXED2FLOAT( *(s16*)&RDRAM[address + 6], 10 );// * 0.00097847357f;
677 gSP.viewport.vscale[3] = *(s16*)&RDRAM[address + 4];
678 gSP.viewport.vtrans[0] = _FIXED2FLOAT( *(s16*)&RDRAM[address + 10], 2 );
679 gSP.viewport.vtrans[1] = _FIXED2FLOAT( *(s16*)&RDRAM[address + 8], 2 );
680 gSP.viewport.vtrans[2] = _FIXED2FLOAT( *(s16*)&RDRAM[address + 14], 10 );// * 0.00097847357f;
681 gSP.viewport.vtrans[3] = *(s16*)&RDRAM[address + 12];
682
683 gSP.viewport.x = gSP.viewport.vtrans[0] - gSP.viewport.vscale[0];
684 gSP.viewport.y = gSP.viewport.vtrans[1] - gSP.viewport.vscale[1];
685 gSP.viewport.width = gSP.viewport.vscale[0] * 2;
686 gSP.viewport.height = gSP.viewport.vscale[1] * 2;
687 gSP.viewport.nearz = gSP.viewport.vtrans[2] - gSP.viewport.vscale[2];
688 gSP.viewport.farz = (gSP.viewport.vtrans[2] + gSP.viewport.vscale[2]) ;
689
690 gSP.changed |= CHANGED_VIEWPORT;
691}
692
693void gSPForceMatrix( u32 mptr )
694{
695 u32 address = RSP_SegmentToPhysical( mptr );
696
697 if (address + 64 > RDRAMSize)
698 {
699 return;
700 }
701
702 RSP_LoadMatrix( gSP.matrix.combined, RSP_SegmentToPhysical( mptr ) );
703
704 gSP.changed &= ~CHANGED_MATRIX;
705}
706
707void gSPLight( u32 l, s32 n )
708{
709 n--;
710 if (n >= 8)
711 return;
712
713 u32 address = RSP_SegmentToPhysical( l );
714
715 if ((address + sizeof( Light )) > RDRAMSize)
716 {
717 return;
718 }
719
720 u8 *addr = &RDRAM[address];
721
722 if (config.hackZelda && (addr[0] == 0x08) && (addr[4] == 0xFF))
723 {
724 LightMM *light = (LightMM*)addr;
725 gSP.lights[n].r = light->r * 0.0039215689f;
726 gSP.lights[n].g = light->g * 0.0039215689f;
727 gSP.lights[n].b = light->b * 0.0039215689f;
728 gSP.lights[n].x = light->x;
729 gSP.lights[n].y = light->y;
730 gSP.lights[n].z = light->z;
731 }
732 else
733 {
734 Light *light = (Light*)addr;
735 gSP.lights[n].r = light->r * 0.0039215689f;
736 gSP.lights[n].g = light->g * 0.0039215689f;
737 gSP.lights[n].b = light->b * 0.0039215689f;
738 gSP.lights[n].x = light->x;
739 gSP.lights[n].y = light->y;
740 gSP.lights[n].z = light->z;
741 }
742 Normalize(&gSP.lights[n].x);
743}
744
745void gSPLookAt( u32 l )
746{
747}
748
749void gSPVertex( u32 v, u32 n, u32 v0 )
750{
751 //flush batched triangles:
752#ifdef __TRIBUFFER_OPT
753 gSPFlushTriangles();
754#endif
755
756 u32 address = RSP_SegmentToPhysical( v );
757
758 if ((address + sizeof( Vertex ) * n) > RDRAMSize)
759 {
760 return;
761 }
762
763 Vertex *vertex = (Vertex*)&RDRAM[address];
764
765 if ((n + v0) <= INDEXMAP_SIZE)
766 {
767 unsigned int i = v0;
768#ifdef __VEC4_OPT
769 for (; i < n - (n%4) + v0; i += 4)
770 {
771 u32 v = i;
772#ifdef __TRIBUFFER_OPT
773 v = __indexmap_getnew(v, 4);
774#endif
775 for(int j = 0; j < 4; j++)
776 {
777 OGL.triangles.vertices[v+j].x = vertex->x;
778 OGL.triangles.vertices[v+j].y = vertex->y;
779 OGL.triangles.vertices[v+j].z = vertex->z;
780 //OGL.triangles.vertices[i+j].flag = vertex->flag;
781 OGL.triangles.vertices[v+j].s = _FIXED2FLOAT( vertex->s, 5 );
782 OGL.triangles.vertices[v+j].t = _FIXED2FLOAT( vertex->t, 5 );
783 if (gSP.geometryMode & G_LIGHTING)
784 {
785 OGL.triangles.vertices[v+j].nx = vertex->normal.x;
786 OGL.triangles.vertices[v+j].ny = vertex->normal.y;
787 OGL.triangles.vertices[v+j].nz = vertex->normal.z;
788 OGL.triangles.vertices[v+j].a = vertex->color.a * 0.0039215689f;
789 }
790 else
791 {
792 OGL.triangles.vertices[v+j].r = vertex->color.r * 0.0039215689f;
793 OGL.triangles.vertices[v+j].g = vertex->color.g * 0.0039215689f;
794 OGL.triangles.vertices[v+j].b = vertex->color.b * 0.0039215689f;
795 OGL.triangles.vertices[v+j].a = vertex->color.a * 0.0039215689f;
796 }
797 vertex++;
798 }
799 gSPProcessVertex4(v);
800 }
801#endif
802 for (; i < n + v0; i++)
803 {
804 u32 v = i;
805#ifdef __TRIBUFFER_OPT
806 v = __indexmap_getnew(v, 1);
807#endif
808 OGL.triangles.vertices[v].x = vertex->x;
809 OGL.triangles.vertices[v].y = vertex->y;
810 OGL.triangles.vertices[v].z = vertex->z;
811 OGL.triangles.vertices[v].s = _FIXED2FLOAT( vertex->s, 5 );
812 OGL.triangles.vertices[v].t = _FIXED2FLOAT( vertex->t, 5 );
813 if (gSP.geometryMode & G_LIGHTING)
814 {
815 OGL.triangles.vertices[v].nx = vertex->normal.x;
816 OGL.triangles.vertices[v].ny = vertex->normal.y;
817 OGL.triangles.vertices[v].nz = vertex->normal.z;
818 OGL.triangles.vertices[v].a = vertex->color.a * 0.0039215689f;
819 }
820 else
821 {
822 OGL.triangles.vertices[v].r = vertex->color.r * 0.0039215689f;
823 OGL.triangles.vertices[v].g = vertex->color.g * 0.0039215689f;
824 OGL.triangles.vertices[v].b = vertex->color.b * 0.0039215689f;
825 OGL.triangles.vertices[v].a = vertex->color.a * 0.0039215689f;
826 }
827 gSPProcessVertex(v);
828 vertex++;
829 }
830 }
831 else
832 {
833 LOG(LOG_ERROR, "Using Vertex outside buffer v0=%i, n=%i\n", v0, n);
834 }
835
836}
837
838void gSPCIVertex( u32 v, u32 n, u32 v0 )
839{
840
841#ifdef __TRIBUFFER_OPT
842 gSPFlushTriangles();
843#endif
844
845 u32 address = RSP_SegmentToPhysical( v );
846
847 if ((address + sizeof( PDVertex ) * n) > RDRAMSize)
848 {
849 return;
850 }
851
852 PDVertex *vertex = (PDVertex*)&RDRAM[address];
853
854 if ((n + v0) <= INDEXMAP_SIZE)
855 {
856 unsigned int i = v0;
857#ifdef __VEC4_OPT
858 for (; i < n - (n%4) + v0; i += 4)
859 {
860 u32 v = i;
861#ifdef __TRIBUFFER_OPT
862 v = __indexmap_getnew(v, 4);
863#endif
864 for(unsigned int j = 0; j < 4; j++)
865 {
866 OGL.triangles.vertices[v+j].x = vertex->x;
867 OGL.triangles.vertices[v+j].y = vertex->y;
868 OGL.triangles.vertices[v+j].z = vertex->z;
869 OGL.triangles.vertices[v+j].s = _FIXED2FLOAT( vertex->s, 5 );
870 OGL.triangles.vertices[v+j].t = _FIXED2FLOAT( vertex->t, 5 );
871 u8 *color = &RDRAM[gSP.vertexColorBase + (vertex->ci & 0xff)];
872
873 if (gSP.geometryMode & G_LIGHTING)
874 {
875 OGL.triangles.vertices[v+j].nx = (s8)color[3];
876 OGL.triangles.vertices[v+j].ny = (s8)color[2];
877 OGL.triangles.vertices[v+j].nz = (s8)color[1];
878 OGL.triangles.vertices[v+j].a = color[0] * 0.0039215689f;
879 }
880 else
881 {
882 OGL.triangles.vertices[v+j].r = color[3] * 0.0039215689f;
883 OGL.triangles.vertices[v+j].g = color[2] * 0.0039215689f;
884 OGL.triangles.vertices[v+j].b = color[1] * 0.0039215689f;
885 OGL.triangles.vertices[v+j].a = color[0] * 0.0039215689f;
886 }
887 vertex++;
888 }
889 gSPProcessVertex4(v);
890 }
891#endif
892 for(; i < n + v0; i++)
893 {
894 u32 v = i;
895#ifdef __TRIBUFFER_OPT
896 v = __indexmap_getnew(v, 1);
897#endif
898 OGL.triangles.vertices[v].x = vertex->x;
899 OGL.triangles.vertices[v].y = vertex->y;
900 OGL.triangles.vertices[v].z = vertex->z;
901 OGL.triangles.vertices[v].s = _FIXED2FLOAT( vertex->s, 5 );
902 OGL.triangles.vertices[v].t = _FIXED2FLOAT( vertex->t, 5 );
903 u8 *color = &RDRAM[gSP.vertexColorBase + (vertex->ci & 0xff)];
904
905 if (gSP.geometryMode & G_LIGHTING)
906 {
907 OGL.triangles.vertices[v].nx = (s8)color[3];
908 OGL.triangles.vertices[v].ny = (s8)color[2];
909 OGL.triangles.vertices[v].nz = (s8)color[1];
910 OGL.triangles.vertices[v].a = color[0] * 0.0039215689f;
911 }
912 else
913 {
914 OGL.triangles.vertices[v].r = color[3] * 0.0039215689f;
915 OGL.triangles.vertices[v].g = color[2] * 0.0039215689f;
916 OGL.triangles.vertices[v].b = color[1] * 0.0039215689f;
917 OGL.triangles.vertices[v].a = color[0] * 0.0039215689f;
918 }
919
920 gSPProcessVertex(v);
921 vertex++;
922 }
923 }
924 else
925 {
926 LOG(LOG_ERROR, "Using Vertex outside buffer v0=%i, n=%i\n", v0, n);
927 }
928
929}
930
931void gSPDMAVertex( u32 v, u32 n, u32 v0 )
932{
933
934 u32 address = gSP.DMAOffsets.vtx + RSP_SegmentToPhysical( v );
935
936 if ((address + 10 * n) > RDRAMSize)
937 {
938 return;
939 }
940
941 if ((n + v0) <= INDEXMAP_SIZE)
942 {
943 u32 i = v0;
944#ifdef __VEC4_OPT
945 for (; i < n - (n%4) + v0; i += 4)
946 {
947 u32 v = i;
948#ifdef __TRIBUFFER_OPT
949 v = __indexmap_getnew(v, 4);
950#endif
951 for(int j = 0; j < 4; j++)
952 {
953 OGL.triangles.vertices[v+j].x = *(s16*)&RDRAM[address ^ 2];
954 OGL.triangles.vertices[v+j].y = *(s16*)&RDRAM[(address + 2) ^ 2];
955 OGL.triangles.vertices[v+j].z = *(s16*)&RDRAM[(address + 4) ^ 2];
956
957 if (gSP.geometryMode & G_LIGHTING)
958 {
959 OGL.triangles.vertices[v+j].nx = *(s8*)&RDRAM[(address + 6) ^ 3];
960 OGL.triangles.vertices[v+j].ny = *(s8*)&RDRAM[(address + 7) ^ 3];
961 OGL.triangles.vertices[v+j].nz = *(s8*)&RDRAM[(address + 8) ^ 3];
962 OGL.triangles.vertices[v+j].a = *(u8*)&RDRAM[(address + 9) ^ 3] * 0.0039215689f;
963 }
964 else
965 {
966 OGL.triangles.vertices[v+j].r = *(u8*)&RDRAM[(address + 6) ^ 3] * 0.0039215689f;
967 OGL.triangles.vertices[v+j].g = *(u8*)&RDRAM[(address + 7) ^ 3] * 0.0039215689f;
968 OGL.triangles.vertices[v+j].b = *(u8*)&RDRAM[(address + 8) ^ 3] * 0.0039215689f;
969 OGL.triangles.vertices[v+j].a = *(u8*)&RDRAM[(address + 9) ^ 3] * 0.0039215689f;
970 }
971 address += 10;
972 }
973 gSPProcessVertex4(v);
974 }
975#endif
976 for (; i < n + v0; i++)
977 {
978 u32 v = i;
979#ifdef __TRIBUFFER_OPT
980 //int ind = OGL.triangles.indexmap[i];
981 v = __indexmap_getnew(v, 1);
982
983 //if previously mapped copy across s/t.
984 //if (ind != -1)
985 //{
986 // SPVertex *vtx = &OGL.triangles.vertices[ind];
987 // OGL.triangles.vertices[v].s = vtx->s;
988 // OGL.triangles.vertices[v].t = vtx->s;
989 //}
990#else
991 v = i;
992#endif
993 OGL.triangles.vertices[v].x = *(s16*)&RDRAM[address ^ 2];
994 OGL.triangles.vertices[v].y = *(s16*)&RDRAM[(address + 2) ^ 2];
995 OGL.triangles.vertices[v].z = *(s16*)&RDRAM[(address + 4) ^ 2];
996
997 if (gSP.geometryMode & G_LIGHTING)
998 {
999 OGL.triangles.vertices[v].nx = *(s8*)&RDRAM[(address + 6) ^ 3];
1000 OGL.triangles.vertices[v].ny = *(s8*)&RDRAM[(address + 7) ^ 3];
1001 OGL.triangles.vertices[v].nz = *(s8*)&RDRAM[(address + 8) ^ 3];
1002 OGL.triangles.vertices[v].a = *(u8*)&RDRAM[(address + 9) ^ 3] * 0.0039215689f;
1003 }
1004 else
1005 {
1006 OGL.triangles.vertices[v].r = *(u8*)&RDRAM[(address + 6) ^ 3] * 0.0039215689f;
1007 OGL.triangles.vertices[v].g = *(u8*)&RDRAM[(address + 7) ^ 3] * 0.0039215689f;
1008 OGL.triangles.vertices[v].b = *(u8*)&RDRAM[(address + 8) ^ 3] * 0.0039215689f;
1009 OGL.triangles.vertices[v].a = *(u8*)&RDRAM[(address + 9) ^ 3] * 0.0039215689f;
1010 }
1011
1012 gSPProcessVertex(v);
1013 address += 10;
1014 }
1015 }
1016 else
1017 {
1018 LOG(LOG_ERROR, "Using Vertex outside buffer v0=%i, n=%i\n", v0, n);
1019 }
1020
1021}
1022
1023void gSPDisplayList( u32 dl )
1024{
1025 u32 address = RSP_SegmentToPhysical( dl );
1026
1027 if ((address + 8) > RDRAMSize)
1028 {
1029 return;
1030 }
1031
1032 if (RSP.PCi < (GBI.PCStackSize - 1))
1033 {
1034#ifdef DEBUG
1035 DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "\n" );
1036 DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gSPDisplayList( 0x%08X );\n",
1037 dl );
1038#endif
1039 RSP.PCi++;
1040 RSP.PC[RSP.PCi] = address;
1041 RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[address], 24, 8 );
1042 }
1043
1044
1045}
1046
1047void gSPDMADisplayList( u32 dl, u32 n )
1048{
1049 if ((dl + (n << 3)) > RDRAMSize)
1050 {
1051 return;
1052 }
1053
1054 u32 curDL = RSP.PC[RSP.PCi];
1055
1056 RSP.PC[RSP.PCi] = RSP_SegmentToPhysical( dl );
1057
1058 while ((RSP.PC[RSP.PCi] - dl) < (n << 3))
1059 {
1060 if ((RSP.PC[RSP.PCi] + 8) > RDRAMSize)
1061 {
1062 break;
1063 }
1064
1065 u32 w0 = *(u32*)&RDRAM[RSP.PC[RSP.PCi]];
1066 u32 w1 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4];
1067
1068 RSP.PC[RSP.PCi] += 8;
1069 RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[RSP.PC[RSP.PCi]], 24, 8 );
1070
1071 GBI.cmd[_SHIFTR( w0, 24, 8 )]( w0, w1 );
1072 }
1073
1074 RSP.PC[RSP.PCi] = curDL;
1075}
1076
1077void gSPBranchList( u32 dl )
1078{
1079 u32 address = RSP_SegmentToPhysical( dl );
1080
1081 if ((address + 8) > RDRAMSize)
1082 {
1083 return;
1084 }
1085
1086 RSP.PC[RSP.PCi] = address;
1087 RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[address], 24, 8 );
1088}
1089
1090void gSPBranchLessZ( u32 branchdl, u32 vtx, f32 zval )
1091{
1092 u32 address = RSP_SegmentToPhysical( branchdl );
1093
1094 if ((address + 8) > RDRAMSize)
1095 {
1096 return;
1097 }
1098
1099 if (OGL.triangles.vertices[vtx].z <= zval)
1100 RSP.PC[RSP.PCi] = address;
1101}
1102
1103void gSPSetDMAOffsets( u32 mtxoffset, u32 vtxoffset )
1104{
1105 gSP.DMAOffsets.mtx = mtxoffset;
1106 gSP.DMAOffsets.vtx = vtxoffset;
1107}
1108
1109void gSPSetVertexColorBase( u32 base )
1110{
1111 gSP.vertexColorBase = RSP_SegmentToPhysical( base );
1112
1113#ifdef __TRIBUFFER_OPT
1114 gSPFlushTriangles();
1115#endif
1116}
1117
1118void gSPSprite2DBase( u32 base )
1119{
1120}
1121
1122void gSPCopyVertex( SPVertex *dest, SPVertex *src )
1123{
1124 dest->x = src->x;
1125 dest->y = src->y;
1126 dest->z = src->z;
1127 dest->w = src->w;
1128 dest->r = src->r;
1129 dest->g = src->g;
1130 dest->b = src->b;
1131 dest->a = src->a;
1132 dest->s = src->s;
1133 dest->t = src->t;
1134}
1135
1136void gSPInterpolateVertex( SPVertex *dest, f32 percent, SPVertex *first, SPVertex *second )
1137{
1138 dest->x = first->x + percent * (second->x - first->x);
1139 dest->y = first->y + percent * (second->y - first->y);
1140 dest->z = first->z + percent * (second->z - first->z);
1141 dest->w = first->w + percent * (second->w - first->w);
1142 dest->r = first->r + percent * (second->r - first->r);
1143 dest->g = first->g + percent * (second->g - first->g);
1144 dest->b = first->b + percent * (second->b - first->b);
1145 dest->a = first->a + percent * (second->a - first->a);
1146 dest->s = first->s + percent * (second->s - first->s);
1147 dest->t = first->t + percent * (second->t - first->t);
1148}
1149
1150void gSPDMATriangles( u32 tris, u32 n )
1151{
1152 u32 address = RSP_SegmentToPhysical( tris );
1153
1154 if (address + sizeof( DKRTriangle ) * n > RDRAMSize)
1155 {
1156 return;
1157 }
1158
1159#ifdef __TRIBUFFER_OPT
1160 __indexmap_undomap();
1161#endif
1162
1163 DKRTriangle *triangles = (DKRTriangle*)&RDRAM[address];
1164
1165 for (u32 i = 0; i < n; i++)
1166 {
1167 int mode = 0;
1168 if (!(triangles->flag & 0x40))
1169 {
1170 if (gSP.viewport.vscale[0] > 0)
1171 mode |= G_CULL_BACK;
1172 else
1173 mode |= G_CULL_FRONT;
1174 }
1175
1176 if ((gSP.geometryMode&G_CULL_BOTH) != mode)
1177 {
c4fb3d4c 1178// OGL_DrawTriangles();
34cf4058 1179 gSP.geometryMode &= ~G_CULL_BOTH;
1180 gSP.geometryMode |= mode;
1181 gSP.changed |= CHANGED_GEOMETRYMODE;
1182 }
1183
1184
1185 s32 v0 = triangles->v0;
1186 s32 v1 = triangles->v1;
1187 s32 v2 = triangles->v2;
1188 OGL.triangles.vertices[v0].s = _FIXED2FLOAT( triangles->s0, 5 );
1189 OGL.triangles.vertices[v0].t = _FIXED2FLOAT( triangles->t0, 5 );
1190 OGL.triangles.vertices[v1].s = _FIXED2FLOAT( triangles->s1, 5 );
1191 OGL.triangles.vertices[v1].t = _FIXED2FLOAT( triangles->t1, 5 );
1192 OGL.triangles.vertices[v2].s = _FIXED2FLOAT( triangles->s2, 5 );
1193 OGL.triangles.vertices[v2].t = _FIXED2FLOAT( triangles->t2, 5 );
1194 gSPTriangle(triangles->v0, triangles->v1, triangles->v2);
1195 triangles++;
1196 }
1197
c4fb3d4c 1198//#ifdef __TRIBUFFER_OPT
34cf4058 1199 OGL_DrawTriangles();
c4fb3d4c 1200//#endif
34cf4058 1201}
1202
1203void gSP1Quadrangle( s32 v0, s32 v1, s32 v2, s32 v3)
1204{
1205 gSPTriangle( v0, v1, v2);
1206 gSPTriangle( v0, v2, v3);
1207 gSPFlushTriangles();
1208}
1209
1210bool gSPCullVertices( u32 v0, u32 vn )
1211{
1212 if (!config.enableClipping)
1213 return FALSE;
1214
1215 s32 v = v0;
1216#ifdef __TRIBUFFER_OPT
1217 v = OGL.triangles.indexmap[v0];
1218#endif
1219
1220 u32 clip = OGL.triangles.vertices[v].clip;
1221 if (clip == 0)
1222 return FALSE;
1223
1224 for (unsigned int i = (v0+1); i <= vn; i++)
1225 {
1226 v = i;
1227#ifdef __TRIBUFFER_OPT
1228 v = OGL.triangles.indexmap[i];
1229#endif
1230 if (OGL.triangles.vertices[v].clip != clip) return FALSE;
1231 }
1232 return TRUE;
1233}
1234
1235void gSPCullDisplayList( u32 v0, u32 vn )
1236{
1237 if (gSPCullVertices( v0, vn ))
1238 {
1239 if (RSP.PCi > 0)
1240 RSP.PCi--;
1241 else
1242 {
1243 RSP.halt = TRUE;
1244 }
1245 }
1246}
1247
1248void gSPPopMatrixN( u32 param, u32 num )
1249{
1250 if (gSP.matrix.modelViewi > num - 1)
1251 {
1252 gSP.matrix.modelViewi -= num;
1253
1254 gSP.changed |= CHANGED_MATRIX;
1255 }
1256}
1257
1258void gSPPopMatrix( u32 param )
1259{
1260 if (gSP.matrix.modelViewi > 0)
1261 {
1262 gSP.matrix.modelViewi--;
1263
1264 gSP.changed |= CHANGED_MATRIX;
1265 }
1266}
1267
1268void gSPSegment( s32 seg, s32 base )
1269{
1270 if (seg > 0xF)
1271 {
1272 return;
1273 }
1274
1275 if ((unsigned int)base > RDRAMSize - 1)
1276 {
1277 return;
1278 }
1279
1280 gSP.segment[seg] = base;
1281}
1282
1283void gSPClipRatio( u32 r )
1284{
1285}
1286
1287void gSPInsertMatrix( u32 where, u32 num )
1288{
1289 f32 fraction, integer;
1290
1291 if (gSP.changed & CHANGED_MATRIX)
1292 gSPCombineMatrices();
1293
1294 if ((where & 0x3) || (where > 0x3C))
1295 {
1296 return;
1297 }
1298
1299 if (where < 0x20)
1300 {
1301 fraction = modff( gSP.matrix.combined[0][where >> 1], &integer );
1302 gSP.matrix.combined[0][where >> 1] = (s16)_SHIFTR( num, 16, 16 ) + abs( (int)fraction );
1303
1304 fraction = modff( gSP.matrix.combined[0][(where >> 1) + 1], &integer );
1305 gSP.matrix.combined[0][(where >> 1) + 1] = (s16)_SHIFTR( num, 0, 16 ) + abs( (int)fraction );
1306 }
1307 else
1308 {
1309 f32 newValue;
1310
1311 fraction = modff( gSP.matrix.combined[0][(where - 0x20) >> 1], &integer );
1312 newValue = integer + _FIXED2FLOAT( _SHIFTR( num, 16, 16 ), 16);
1313
1314 // Make sure the sign isn't lost
1315 if ((integer == 0.0f) && (fraction != 0.0f))
1316 newValue = newValue * (fraction / abs( (int)fraction ));
1317
1318 gSP.matrix.combined[0][(where - 0x20) >> 1] = newValue;
1319
1320 fraction = modff( gSP.matrix.combined[0][((where - 0x20) >> 1) + 1], &integer );
1321 newValue = integer + _FIXED2FLOAT( _SHIFTR( num, 0, 16 ), 16 );
1322
1323 // Make sure the sign isn't lost
1324 if ((integer == 0.0f) && (fraction != 0.0f))
1325 newValue = newValue * (fraction / abs( (int)fraction ));
1326
1327 gSP.matrix.combined[0][((where - 0x20) >> 1) + 1] = newValue;
1328 }
1329}
1330
1331void gSPModifyVertex( u32 vtx, u32 where, u32 val )
1332{
1333 s32 v = vtx;
1334
1335#ifdef __TRIBUFFER_OPT
1336 v = OGL.triangles.indexmap[v];
1337#endif
1338
1339 switch (where)
1340 {
1341 case G_MWO_POINT_RGBA:
1342 OGL.triangles.vertices[v].r = _SHIFTR( val, 24, 8 ) * 0.0039215689f;
1343 OGL.triangles.vertices[v].g = _SHIFTR( val, 16, 8 ) * 0.0039215689f;
1344 OGL.triangles.vertices[v].b = _SHIFTR( val, 8, 8 ) * 0.0039215689f;
1345 OGL.triangles.vertices[v].a = _SHIFTR( val, 0, 8 ) * 0.0039215689f;
1346 break;
1347 case G_MWO_POINT_ST:
1348 OGL.triangles.vertices[v].s = _FIXED2FLOAT( (s16)_SHIFTR( val, 16, 16 ), 5 );
1349 OGL.triangles.vertices[v].t = _FIXED2FLOAT( (s16)_SHIFTR( val, 0, 16 ), 5 );
1350 break;
1351 case G_MWO_POINT_XYSCREEN:
1352 break;
1353 case G_MWO_POINT_ZSCREEN:
1354 break;
1355 }
1356}
1357
1358void gSPNumLights( s32 n )
1359{
1360 gSP.numLights = (n <= 8) ? n : 0;
1361}
1362
1363
1364void gSPLightColor( u32 lightNum, u32 packedColor )
1365{
1366 lightNum--;
1367
1368 if (lightNum < 8)
1369 {
1370 gSP.lights[lightNum].r = _SHIFTR( packedColor, 24, 8 ) * 0.0039215689f;
1371 gSP.lights[lightNum].g = _SHIFTR( packedColor, 16, 8 ) * 0.0039215689f;
1372 gSP.lights[lightNum].b = _SHIFTR( packedColor, 8, 8 ) * 0.0039215689f;
1373 }
1374}
1375
1376void gSPFogFactor( s16 fm, s16 fo )
1377{
1378 gSP.fog.multiplier = fm;
1379 gSP.fog.offset = fo;
1380
1381 gSP.changed |= CHANGED_FOGPOSITION;
1382}
1383
1384void gSPPerspNormalize( u16 scale )
1385{
1386}
1387
1388void gSPTexture( f32 sc, f32 tc, s32 level, s32 tile, s32 on )
1389{
1390 gSP.texture.scales = sc;
1391 gSP.texture.scalet = tc;
1392
1393 if (gSP.texture.scales == 0.0f) gSP.texture.scales = 1.0f;
1394 if (gSP.texture.scalet == 0.0f) gSP.texture.scalet = 1.0f;
1395
1396 gSP.texture.level = level;
1397 gSP.texture.on = on;
1398
1399 if (gSP.texture.tile != tile)
1400 {
1401 gSP.texture.tile = tile;
1402 gSP.textureTile[0] = &gDP.tiles[tile];
1403 gSP.textureTile[1] = &gDP.tiles[(tile < 7) ? (tile + 1) : tile];
1404 gSP.changed |= CHANGED_TEXTURE;
1405 }
1406
1407 gSP.changed |= CHANGED_TEXTURESCALE;
1408}
1409
1410void gSPEndDisplayList()
1411{
1412 if (RSP.PCi > 0)
1413 RSP.PCi--;
1414 else
1415 {
1416 RSP.halt = TRUE;
1417 }
1418
1419#ifdef __TRIBUFFER_OPT
1420 RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[RSP.PC[RSP.PCi]], 24, 8 );
1421 gSPFlushTriangles();
1422#endif
1423}
1424
1425void gSPGeometryMode( u32 clear, u32 set )
1426{
1427 gSP.geometryMode = (gSP.geometryMode & ~clear) | set;
1428 gSP.changed |= CHANGED_GEOMETRYMODE;
1429}
1430
1431void gSPSetGeometryMode( u32 mode )
1432{
1433 gSP.geometryMode |= mode;
1434 gSP.changed |= CHANGED_GEOMETRYMODE;
1435}
1436
1437void gSPClearGeometryMode( u32 mode )
1438{
1439 gSP.geometryMode &= ~mode;
1440 gSP.changed |= CHANGED_GEOMETRYMODE;
1441}
1442
1443void gSPLine3D( s32 v0, s32 v1, s32 flag )
1444{
1445 OGL_DrawLine(v0, v1, 1.5f );
1446}
1447
1448void gSPLineW3D( s32 v0, s32 v1, s32 wd, s32 flag )
1449{
1450 OGL_DrawLine(v0, v1, 1.5f + wd * 0.5f );
1451}
1452
1453void gSPBgRect1Cyc( u32 bg )
1454{
1455
1456#if 1
1457
1458 u32 addr = RSP_SegmentToPhysical(bg) >> 1;
1459
1460 f32 imageX = (((u16*)RDRAM)[(addr+0)^1] >> 5); // 0
1461 f32 imageY = (((u16*)RDRAM)[(addr+4)^1] >> 5); // 4
1462 f32 imageW = (((u16*)RDRAM)[(addr+1)^1] >> 2); // 1
1463 f32 imageH = (((u16*)RDRAM)[(addr+5)^1] >> 2); // 5
1464
1465 f32 frameX = ((s16*)RDRAM)[(addr+2)^1] / 4.0f; // 2
1466 f32 frameY = ((s16*)RDRAM)[(addr+6)^1] / 4.0f; // 6
1467 f32 frameW = ((u16*)RDRAM)[(addr+3)^1] >> 2; // 3
1468 f32 frameH = ((u16*)RDRAM)[(addr+7)^1] >> 2; // 7
1469
1470
1471 //wxUint16 imageFlip = ((u16*)gfx.RDRAM)[(addr+13)^1]; // 13;
1472 //d.flipX = (u8)imageFlip&0x01;
1473
1474 gSP.bgImage.address = RSP_SegmentToPhysical(((u32*)RDRAM)[(addr+8)>>1]); // 8,9
1475 gSP.bgImage.width = imageW;
1476 gSP.bgImage.height = imageH;
1477 gSP.bgImage.format = ((u8*)RDRAM)[(((addr+11)<<1)+0)^3];
1478 gSP.bgImage.size = ((u8*)RDRAM)[(((addr+11)<<1)+1)^3];
1479 gSP.bgImage.palette = ((u16*)RDRAM)[(addr+12)^1];
1480
1481 f32 scaleW = ((s16*)RDRAM)[(addr+14)^1] / 1024.0f; // 14
1482 f32 scaleH = ((s16*)RDRAM)[(addr+15)^1] / 1024.0f; // 15
1483 gDP.textureMode = TEXTUREMODE_BGIMAGE;
1484
1485#else
1486 u32 address = RSP_SegmentToPhysical( bg );
1487 uObjScaleBg *objScaleBg = (uObjScaleBg*)&RDRAM[address];
1488
1489 gSP.bgImage.address = RSP_SegmentToPhysical( objScaleBg->imagePtr );
1490 gSP.bgImage.width = objScaleBg->imageW >> 2;
1491 gSP.bgImage.height = objScaleBg->imageH >> 2;
1492 gSP.bgImage.format = objScaleBg->imageFmt;
1493 gSP.bgImage.size = objScaleBg->imageSiz;
1494 gSP.bgImage.palette = objScaleBg->imagePal;
1495 gDP.textureMode = TEXTUREMODE_BGIMAGE;
1496
1497 f32 imageX = _FIXED2FLOAT( objScaleBg->imageX, 5 );
1498 f32 imageY = _FIXED2FLOAT( objScaleBg->imageY, 5 );
1499 f32 imageW = objScaleBg->imageW >> 2;
1500 f32 imageH = objScaleBg->imageH >> 2;
1501
1502 f32 frameX = _FIXED2FLOAT( objScaleBg->frameX, 2 );
1503 f32 frameY = _FIXED2FLOAT( objScaleBg->frameY, 2 );
1504 f32 frameW = _FIXED2FLOAT( objScaleBg->frameW, 2 );
1505 f32 frameH = _FIXED2FLOAT( objScaleBg->frameH, 2 );
1506 f32 scaleW = _FIXED2FLOAT( objScaleBg->scaleW, 10 );
1507 f32 scaleH = _FIXED2FLOAT( objScaleBg->scaleH, 10 );
1508#endif
1509
1510 f32 frameX0 = frameX;
1511 f32 frameY0 = frameY;
1512 f32 frameS0 = imageX;
1513 f32 frameT0 = imageY;
1514
1515 f32 frameX1 = frameX + min( (imageW - imageX) / scaleW, frameW );
1516 f32 frameY1 = frameY + min( (imageH - imageY) / scaleH, frameH );
1517 //f32 frameS1 = imageX + min( (imageW - imageX) * scaleW, frameW * scaleW );
1518 //f32 frameT1 = imageY + min( (imageH - imageY) * scaleH, frameH * scaleH );
1519
1520 gDP.otherMode.cycleType = G_CYC_1CYCLE;
1521 gDP.changed |= CHANGED_CYCLETYPE;
1522 gSPTexture( 1.0f, 1.0f, 0, 0, TRUE );
1523 gDPTextureRectangle( frameX0, frameY0, frameX1 - 1, frameY1 - 1, 0, frameS0 - 1, frameT0 - 1, scaleW, scaleH );
1524
1525 if ((frameX1 - frameX0) < frameW)
1526 {
1527 f32 frameX2 = frameW - (frameX1 - frameX0) + frameX1;
1528 gDPTextureRectangle( frameX1, frameY0, frameX2 - 1, frameY1 - 1, 0, 0, frameT0, scaleW, scaleH );
1529 }
1530
1531 if ((frameY1 - frameY0) < frameH)
1532 {
1533 f32 frameY2 = frameH - (frameY1 - frameY0) + frameY1;
1534 gDPTextureRectangle( frameX0, frameY1, frameX1 - 1, frameY2 - 1, 0, frameS0, 0, scaleW, scaleH );
1535 }
1536
1537 gDPTextureRectangle( 0, 0, 319, 239, 0, 0, 0, scaleW, scaleH );
1538}
1539
1540void gSPBgRectCopy( u32 bg )
1541{
1542
34cf4058 1543 u32 address = RSP_SegmentToPhysical( bg );
1544 uObjBg *objBg = (uObjBg*)&RDRAM[address];
1545
1546 gSP.bgImage.address = RSP_SegmentToPhysical( objBg->imagePtr );
1547 gSP.bgImage.width = objBg->imageW >> 2;
1548 gSP.bgImage.height = objBg->imageH >> 2;
1549 gSP.bgImage.format = objBg->imageFmt;
1550 gSP.bgImage.size = objBg->imageSiz;
1551 gSP.bgImage.palette = objBg->imagePal;
1552 gDP.textureMode = TEXTUREMODE_BGIMAGE;
1553
1554 u16 imageX = objBg->imageX >> 5;
1555 u16 imageY = objBg->imageY >> 5;
1556
1557 s16 frameX = objBg->frameX / 4;
1558 s16 frameY = objBg->frameY / 4;
1559 u16 frameW = objBg->frameW >> 2;
1560 u16 frameH = objBg->frameH >> 2;
1561
1562 gSPTexture( 1.0f, 1.0f, 0, 0, TRUE );
1563
1564 gDPTextureRectangle( frameX, frameY, frameX + frameW - 1, frameY + frameH - 1, 0, imageX, imageY, 4, 1 );
1565}
1566
1567void gSPObjRectangle( u32 sp )
1568{
1569 u32 address = RSP_SegmentToPhysical( sp );
1570 uObjSprite *objSprite = (uObjSprite*)&RDRAM[address];
1571
1572 f32 scaleW = _FIXED2FLOAT( objSprite->scaleW, 10 );
1573 f32 scaleH = _FIXED2FLOAT( objSprite->scaleH, 10 );
1574 f32 objX = _FIXED2FLOAT( objSprite->objX, 2 );
1575 f32 objY = _FIXED2FLOAT( objSprite->objY, 2 );
1576 u32 imageW = objSprite->imageW >> 2;
1577 u32 imageH = objSprite->imageH >> 2;
1578
1579 gDPTextureRectangle( objX, objY, objX + imageW / scaleW - 1, objY + imageH / scaleH - 1, 0, 0.0f, 0.0f, scaleW * (gDP.otherMode.cycleType == G_CYC_COPY ? 4.0f : 1.0f), scaleH );
1580}
1581
1582void gSPObjLoadTxtr( u32 tx )
1583{
1584 u32 address = RSP_SegmentToPhysical( tx );
1585 uObjTxtr *objTxtr = (uObjTxtr*)&RDRAM[address];
1586
1587 if ((gSP.status[objTxtr->block.sid >> 2] & objTxtr->block.mask) != objTxtr->block.flag)
1588 {
1589 switch (objTxtr->block.type)
1590 {
1591 case G_OBJLT_TXTRBLOCK:
1592 gDPSetTextureImage( 0, 1, 0, objTxtr->block.image );
1593 gDPSetTile( 0, 1, 0, objTxtr->block.tmem, 7, 0, 0, 0, 0, 0, 0, 0 );
1594 gDPLoadBlock( 7, 0, 0, ((objTxtr->block.tsize + 1) << 3) - 1, objTxtr->block.tline );
1595 break;
1596 case G_OBJLT_TXTRTILE:
1597 gDPSetTextureImage( 0, 1, (objTxtr->tile.twidth + 1) << 1, objTxtr->tile.image );
1598 gDPSetTile( 0, 1, (objTxtr->tile.twidth + 1) >> 2, objTxtr->tile.tmem, 7, 0, 0, 0, 0, 0, 0, 0 );
1599 gDPLoadTile( 7, 0, 0, (((objTxtr->tile.twidth + 1) << 1) - 1) << 2, (((objTxtr->tile.theight + 1) >> 2) - 1) << 2 );
1600 break;
1601 case G_OBJLT_TLUT:
1602 gDPSetTextureImage( 0, 2, 1, objTxtr->tlut.image );
1603 gDPSetTile( 0, 2, 0, objTxtr->tlut.phead, 7, 0, 0, 0, 0, 0, 0, 0 );
1604 gDPLoadTLUT( 7, 0, 0, objTxtr->tlut.pnum << 2, 0 );
1605 break;
1606 }
1607 gSP.status[objTxtr->block.sid >> 2] = (gSP.status[objTxtr->block.sid >> 2] & ~objTxtr->block.mask) | (objTxtr->block.flag & objTxtr->block.mask);
1608 }
1609}
1610
1611void gSPObjSprite( u32 sp )
1612{
1613 u32 address = RSP_SegmentToPhysical( sp );
1614 uObjSprite *objSprite = (uObjSprite*)&RDRAM[address];
1615
1616 f32 scaleW = _FIXED2FLOAT( objSprite->scaleW, 10 );
1617 f32 scaleH = _FIXED2FLOAT( objSprite->scaleH, 10 );
1618 f32 objX = _FIXED2FLOAT( objSprite->objX, 2 );
1619 f32 objY = _FIXED2FLOAT( objSprite->objY, 2 );
1620 u32 imageW = objSprite->imageW >> 5;
1621 u32 imageH = objSprite->imageH >> 5;
1622
1623 f32 x0 = objX;
1624 f32 y0 = objY;
1625 f32 x1 = objX + imageW / scaleW - 1;
1626 f32 y1 = objY + imageH / scaleH - 1;
1627
1628 s32 v0=0,v1=1,v2=2,v3=3;
1629
1630#ifdef __TRIBUFFER_OPT
1631 v0 = OGL.triangles.indexmap[v0];
1632 v1 = OGL.triangles.indexmap[v1];
1633 v2 = OGL.triangles.indexmap[v2];
1634 v3 = OGL.triangles.indexmap[v3];
1635#endif
1636
1637 OGL.triangles.vertices[v0].x = gSP.objMatrix.A * x0 + gSP.objMatrix.B * y0 + gSP.objMatrix.X;
1638 OGL.triangles.vertices[v0].y = gSP.objMatrix.C * x0 + gSP.objMatrix.D * y0 + gSP.objMatrix.Y;
1639 OGL.triangles.vertices[v0].z = 0.0f;
1640 OGL.triangles.vertices[v0].w = 1.0f;
1641 OGL.triangles.vertices[v0].s = 0.0f;
1642 OGL.triangles.vertices[v0].t = 0.0f;
1643 OGL.triangles.vertices[v1].x = gSP.objMatrix.A * x1 + gSP.objMatrix.B * y0 + gSP.objMatrix.X;
1644 OGL.triangles.vertices[v1].y = gSP.objMatrix.C * x1 + gSP.objMatrix.D * y0 + gSP.objMatrix.Y;
1645 OGL.triangles.vertices[v1].z = 0.0f;
1646 OGL.triangles.vertices[v1].w = 1.0f;
1647 OGL.triangles.vertices[v1].s = imageW - 1;
1648 OGL.triangles.vertices[v1].t = 0.0f;
1649 OGL.triangles.vertices[v2].x = gSP.objMatrix.A * x1 + gSP.objMatrix.B * y1 + gSP.objMatrix.X;
1650 OGL.triangles.vertices[v2].y = gSP.objMatrix.C * x1 + gSP.objMatrix.D * y1 + gSP.objMatrix.Y;
1651 OGL.triangles.vertices[v2].z = 0.0f;
1652 OGL.triangles.vertices[v2].w = 1.0f;
1653 OGL.triangles.vertices[v2].s = imageW - 1;
1654 OGL.triangles.vertices[v2].t = imageH - 1;
1655 OGL.triangles.vertices[v3].x = gSP.objMatrix.A * x0 + gSP.objMatrix.B * y1 + gSP.objMatrix.X;
1656 OGL.triangles.vertices[v3].y = gSP.objMatrix.C * x0 + gSP.objMatrix.D * y1 + gSP.objMatrix.Y;
1657 OGL.triangles.vertices[v3].z = 0.0f;
1658 OGL.triangles.vertices[v3].w = 1.0f;
1659 OGL.triangles.vertices[v3].s = 0;
1660 OGL.triangles.vertices[v3].t = imageH - 1;
1661
1662 gDPSetTile( objSprite->imageFmt, objSprite->imageSiz, objSprite->imageStride, objSprite->imageAdrs, 0, objSprite->imagePal, G_TX_CLAMP, G_TX_CLAMP, 0, 0, 0, 0 );
1663 gDPSetTileSize( 0, 0, 0, (imageW - 1) << 2, (imageH - 1) << 2 );
1664 gSPTexture( 1.0f, 1.0f, 0, 0, TRUE );
1665
1666 //glOrtho( 0, VI.width, VI.height, 0, 0.0f, 32767.0f );
1667 OGL.triangles.vertices[v0].x = 2.0f * VI.rwidth * OGL.triangles.vertices[v0].x - 1.0f;
1668 OGL.triangles.vertices[v0].y = -2.0f * VI.rheight * OGL.triangles.vertices[v0].y + 1.0f;
1669 OGL.triangles.vertices[v0].z = -1.0f;
1670 OGL.triangles.vertices[v0].w = 1.0f;
1671 OGL.triangles.vertices[v1].x = 2.0f * VI.rwidth * OGL.triangles.vertices[v0].x - 1.0f;
1672 OGL.triangles.vertices[v1].y = -2.0f * VI.rheight * OGL.triangles.vertices[v0].y + 1.0f;
1673 OGL.triangles.vertices[v1].z = -1.0f;
1674 OGL.triangles.vertices[v1].w = 1.0f;
1675 OGL.triangles.vertices[v2].x = 2.0f * VI.rwidth * OGL.triangles.vertices[v0].x - 1.0f;
1676 OGL.triangles.vertices[v2].y = -2.0f * VI.rheight * OGL.triangles.vertices[v0].y + 1.0f;
1677 OGL.triangles.vertices[v2].z = -1.0f;
1678 OGL.triangles.vertices[v2].w = 1.0f;
1679 OGL.triangles.vertices[v3].x = 2.0f * VI.rwidth * OGL.triangles.vertices[v0].x - 1.0f;
1680 OGL.triangles.vertices[v3].y = -2.0f * VI.rheight * OGL.triangles.vertices[v0].y + 1.0f;
1681 OGL.triangles.vertices[v3].z = -1.0f;
1682 OGL.triangles.vertices[v3].w = 1.0f;
1683
1684 OGL_AddTriangle(v0, v1, v2);
1685 OGL_AddTriangle(v0, v2, v3);
1686 OGL_DrawTriangles();
1687
1688 if (depthBuffer.current) depthBuffer.current->cleared = FALSE;
1689 gDP.colorImage.changed = TRUE;
1690 gDP.colorImage.height = (unsigned int)(max( gDP.colorImage.height, gDP.scissor.lry ));
1691}
1692
1693void gSPObjLoadTxSprite( u32 txsp )
1694{
1695 gSPObjLoadTxtr( txsp );
1696 gSPObjSprite( txsp + sizeof( uObjTxtr ) );
1697}
1698
1699void gSPObjLoadTxRectR( u32 txsp )
1700{
1701 gSPObjLoadTxtr( txsp );
1702// gSPObjRectangleR( txsp + sizeof( uObjTxtr ) );
1703}
1704
1705void gSPObjMatrix( u32 mtx )
1706{
1707 u32 address = RSP_SegmentToPhysical( mtx );
1708 uObjMtx *objMtx = (uObjMtx*)&RDRAM[address];
1709
1710 gSP.objMatrix.A = _FIXED2FLOAT( objMtx->A, 16 );
1711 gSP.objMatrix.B = _FIXED2FLOAT( objMtx->B, 16 );
1712 gSP.objMatrix.C = _FIXED2FLOAT( objMtx->C, 16 );
1713 gSP.objMatrix.D = _FIXED2FLOAT( objMtx->D, 16 );
1714 gSP.objMatrix.X = _FIXED2FLOAT( objMtx->X, 2 );
1715 gSP.objMatrix.Y = _FIXED2FLOAT( objMtx->Y, 2 );
1716 gSP.objMatrix.baseScaleX = _FIXED2FLOAT( objMtx->BaseScaleX, 10 );
1717 gSP.objMatrix.baseScaleY = _FIXED2FLOAT( objMtx->BaseScaleY, 10 );
1718}
1719
1720void gSPObjSubMatrix( u32 mtx )
1721{
1722}
1723
1724
1725#ifdef __VEC4_OPT
1726void (*gSPTransformVertex4)(u32 v, float mtx[4][4]) =
1727 gSPTransformVertex4_default;
1728void (*gSPTransformNormal4)(u32 v, float mtx[4][4]) =
1729 gSPTransformNormal4_default;
1730void (*gSPLightVertex4)(u32 v) = gSPLightVertex4_default;
1731void (*gSPBillboardVertex4)(u32 v) = gSPBillboardVertex4_default;
1732#endif
1733void (*gSPTransformVertex)(float vtx[4], float mtx[4][4]) =
1734 gSPTransformVertex_default;
1735void (*gSPLightVertex)(u32 v) = gSPLightVertex_default;
1736void (*gSPBillboardVertex)(u32 v, u32 i) = gSPBillboardVertex_default;
1737