19 #include "DepthBuffer.h"
22 //Note: 0xC0 is used by 1080 alot, its an unknown command.
25 extern u32 uc_crc, uc_dcrc;
26 extern char uc_str[256];
29 void gSPCombineMatrices();
31 //#ifdef __TRIBUFFER_OPT
32 void __indexmap_init()
34 memset(OGL.triangles.indexmapinv, 0xFF, VERTBUFF_SIZE*sizeof(u32));
35 for(int i=0;i<INDEXMAP_SIZE;i++)
37 OGL.triangles.indexmap[i] = i;
38 //OGL.triangles.indexmapinv[i] = i;
41 OGL.triangles.indexmap_prev = -1;
42 OGL.triangles.indexmap_nomap = 0;
45 void __indexmap_clear()
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;
52 u32 __indexmap_findunused(u32 num)
55 u32 i = min(OGL.triangles.indexmap_prev+1, VERTBUFF_SIZE-1);
57 while(n < VERTBUFF_SIZE)
59 c = (OGL.triangles.indexmapinv[i] == 0xFFFFFFFF) ? (c+1) : 0;
60 if ((c == num) && (i < (VERTBUFF_SIZE - num)))
65 if (i >= VERTBUFF_SIZE) {i=0; c=0;}
68 return (c == num) ? (i-num+1) : (0xFFFFFFFF);
71 void __indexmap_undomap()
73 SPVertex tmp[INDEXMAP_SIZE];
74 memset(OGL.triangles.indexmapinv, 0xFF, VERTBUFF_SIZE * sizeof(u32));
76 for(int i=0;i<INDEXMAP_SIZE;i++)
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;
84 memcpy(OGL.triangles.vertices, tmp, INDEXMAP_SIZE * sizeof(SPVertex));
85 OGL.triangles.indexmap_nomap = 1;
88 u32 __indexmap_getnew(u32 index, u32 num)
92 //test to see if unmapped
94 for(int i=0;i<num;i++)
96 if (OGL.triangles.indexmap[i]!=0xFFFFFFFF)
110 ind = __indexmap_findunused(num);
112 //no more room in buffer....
113 if (ind > VERTBUFF_SIZE)
116 ind = __indexmap_findunused(num);
118 //OK the indices are spread so sparsely, we cannot find a num element block.
119 if (ind > VERTBUFF_SIZE)
121 __indexmap_undomap();
122 ind = __indexmap_findunused(num);
123 if (ind > VERTBUFF_SIZE)
125 LOG(LOG_ERROR, "Could not allocate %i indices\n", num);
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");
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");
142 for(int i=0;i<num;i++)
144 OGL.triangles.indexmap[index+i] = ind+i;
145 OGL.triangles.indexmapinv[ind+i] = index+i;
148 OGL.triangles.indexmap_prev = ind+num-1;
149 OGL.triangles.indexmap_nomap = 0;
155 void gSPTriangle(s32 v0, s32 v1, s32 v2)
157 if ((v0 < INDEXMAP_SIZE) && (v1 < INDEXMAP_SIZE) && (v2 < INDEXMAP_SIZE))
160 #ifdef __TRIBUFFER_OPT
161 v0 = OGL.triangles.indexmap[v0];
162 v1 = OGL.triangles.indexmap[v1];
163 v2 = OGL.triangles.indexmap[v2];
167 // Don't bother with triangles completely outside clipping frustrum
168 if (config.enableClipping)
170 if (OGL.triangles.vertices[v0].clip & OGL.triangles.vertices[v1].clip & OGL.triangles.vertices[v2].clip)
177 OGL_AddTriangle(v0, v1, v2);
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 ));
186 void gSP1Triangle( const s32 v0, const s32 v1, const s32 v2)
188 gSPTriangle( v0, v1, v2);
192 void 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 )
195 gSPTriangle( v00, v01, v02);
196 gSPTriangle( v10, v11, v12);
200 void 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 )
205 gSPTriangle(v00, v01, v02);
206 gSPTriangle(v10, v11, v12);
207 gSPTriangle(v20, v21, v22);
208 gSPTriangle(v30, v31, v32);
215 f32 identityMatrix[4][4] =
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 }
224 static void gSPTransformVertex4_default(u32 v, float mtx[4][4])
228 for(i = 0; i < 4; i++)
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];
241 void gSPClipVertex4(u32 v)
244 for(i = 0; i < 4; i++){
245 SPVertex *vtx = &OGL.triangles.vertices[v+i];
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;
254 static void gSPTransformNormal4_default(u32 v, float mtx[4][4])
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;
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;
272 OGL.triangles.vertices[v+i].nx /= len;
273 OGL.triangles.vertices[v+i].ny /= len;
274 OGL.triangles.vertices[v+i].nz /= len;
279 static void gSPLightVertex4_default(u32 v)
281 gSPTransformNormal4(v, gSP.matrix.modelView[gSP.matrix.modelViewi]);
282 for(int j = 0; j < 4; j++)
285 r = gSP.lights[gSP.numLights].r;
286 g = gSP.lights[gSP.numLights].g;
287 b = gSP.lights[gSP.numLights].b;
289 for (int i = 0; i < gSP.numLights; i++)
291 f32 intensity = DotProduct( &OGL.triangles.vertices[v+j].nx, &gSP.lights[i].x );
292 if (intensity < 0.0f) intensity = 0.0f;
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;
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;
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);
311 static void gSPBillboardVertex4_default(u32 v)
315 #ifdef __TRIBUFFER_OPT
316 i = OGL.triangles.indexmap[0];
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;
337 void gSPProcessVertex4(u32 v)
339 if (gSP.changed & CHANGED_MATRIX)
340 gSPCombineMatrices();
342 gSPTransformVertex4(v, gSP.matrix.combined );
344 if (config.screen.flipVertical)
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;
352 if (gDP.otherMode.depthSource)
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;
360 if (gSP.matrix.billboard)
361 gSPBillboardVertex4(v);
363 if (!(gSP.geometryMode & G_ZBUFFER))
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;
371 if (gSP.geometryMode & G_LIGHTING)
373 if (config.enableLighting)
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;
393 if (gSP.geometryMode & G_TEXTURE_GEN)
395 gSPTransformNormal4(v, gSP.matrix.projection);
397 if (gSP.geometryMode & G_TEXTURE_GEN_LINEAR)
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;
408 else // G_TEXTURE_GEN
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;
422 if (config.enableClipping) gSPClipVertex4(v);
426 void gSPClipVertex(u32 v)
428 SPVertex *vtx = &OGL.triangles.vertices[v];
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;
437 static void gSPTransformVertex_default(float vtx[4], float mtx[4][4])
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];
451 static void gSPLightVertex_default(u32 v)
453 TransformVectorNormalize( &OGL.triangles.vertices[v].nx, gSP.matrix.modelView[gSP.matrix.modelViewi] );
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++)
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;
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);
472 static void gSPBillboardVertex_default(u32 v, u32 i)
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;
480 void gSPCombineMatrices()
482 MultMatrix(gSP.matrix.projection, gSP.matrix.modelView[gSP.matrix.modelViewi], gSP.matrix.combined);
483 gSP.changed &= ~CHANGED_MATRIX;
486 void gSPProcessVertex( u32 v )
491 if (gSP.changed & CHANGED_MATRIX)
492 gSPCombineMatrices();
494 gSPTransformVertex( &OGL.triangles.vertices[v].x, gSP.matrix.combined );
496 if (config.screen.flipVertical)
498 OGL.triangles.vertices[v].y = -OGL.triangles.vertices[v].y;
501 if (gDP.otherMode.depthSource)
503 OGL.triangles.vertices[v].z = gDP.primDepth.z * OGL.triangles.vertices[v].w;
506 if (gSP.matrix.billboard)
509 #ifdef __TRIBUFFER_OPT
510 i = OGL.triangles.indexmap[0];
513 gSPBillboardVertex(v, i);
516 if (!(gSP.geometryMode & G_ZBUFFER))
518 OGL.triangles.vertices[v].z = -OGL.triangles.vertices[v].w;
521 if (config.enableClipping)
524 if (gSP.geometryMode & G_LIGHTING)
526 if (config.enableLighting)
532 OGL.triangles.vertices[v].r = 1.0f;
533 OGL.triangles.vertices[v].g = 1.0f;
534 OGL.triangles.vertices[v].b = 1.0f;
537 if (gSP.geometryMode & G_TEXTURE_GEN)
539 TransformVectorNormalize(&OGL.triangles.vertices[v].nx, gSP.matrix.projection);
541 if (gSP.geometryMode & G_TEXTURE_GEN_LINEAR)
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;
546 else // G_TEXTURE_GEN
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;
556 void gSPLoadUcodeEx( u32 uc_start, u32 uc_dstart, u16 uc_dsize )
559 gSP.matrix.modelViewi = 0;
560 gSP.changed |= CHANGED_MATRIX;
561 gSP.status[0] = gSP.status[1] = gSP.status[2] = gSP.status[3] = 0;
563 if ((((uc_start & 0x1FFFFFFF) + 4096) > RDRAMSize) || (((uc_dstart & 0x1FFFFFFF) + uc_dsize) > RDRAMSize))
568 MicrocodeInfo *ucode = GBI_DetectMicrocode( uc_start, uc_dstart, uc_dsize );
570 if (ucode->type != 0xFFFFFFFF)
571 last_good_ucode = ucode->type;
573 if (ucode->type != NONE)
575 GBI_MakeCurrent( ucode );
579 LOG(LOG_WARNING, "Unknown Ucode\n");
588 void gSPTriangleUnknown()
590 #ifdef __TRIBUFFER_OPT
595 void gSPMatrix( u32 matrix, u8 param )
597 #ifdef __TRIBUFFER_OPT
602 u32 address = RSP_SegmentToPhysical( matrix );
604 if (address + 64 > RDRAMSize)
609 RSP_LoadMatrix( mtx, address );
611 if (param & G_MTX_PROJECTION)
613 if (param & G_MTX_LOAD)
614 CopyMatrix( gSP.matrix.projection, mtx );
616 MultMatrix2( gSP.matrix.projection, mtx );
620 if ((param & G_MTX_PUSH) && (gSP.matrix.modelViewi < (gSP.matrix.stackSize - 1)))
622 CopyMatrix( gSP.matrix.modelView[gSP.matrix.modelViewi + 1], gSP.matrix.modelView[gSP.matrix.modelViewi] );
623 gSP.matrix.modelViewi++;
625 if (param & G_MTX_LOAD)
626 CopyMatrix( gSP.matrix.modelView[gSP.matrix.modelViewi], mtx );
628 MultMatrix2( gSP.matrix.modelView[gSP.matrix.modelViewi], mtx );
631 gSP.changed |= CHANGED_MATRIX;
634 void gSPDMAMatrix( u32 matrix, u8 index, u8 multiply )
637 u32 address = gSP.DMAOffsets.mtx + RSP_SegmentToPhysical( matrix );
639 if (address + 64 > RDRAMSize)
644 RSP_LoadMatrix( mtx, address );
646 gSP.matrix.modelViewi = index;
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]);
655 CopyMatrix( gSP.matrix.modelView[gSP.matrix.modelViewi], mtx );
657 CopyMatrix( gSP.matrix.projection, identityMatrix );
658 gSP.changed |= CHANGED_MATRIX;
661 void gSPViewport( u32 v )
663 u32 address = RSP_SegmentToPhysical( v );
665 if ((address + 16) > RDRAMSize)
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 );
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];
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]) ;
690 gSP.changed |= CHANGED_VIEWPORT;
693 void gSPForceMatrix( u32 mptr )
695 u32 address = RSP_SegmentToPhysical( mptr );
697 if (address + 64 > RDRAMSize)
702 RSP_LoadMatrix( gSP.matrix.combined, RSP_SegmentToPhysical( mptr ) );
704 gSP.changed &= ~CHANGED_MATRIX;
707 void gSPLight( u32 l, s32 n )
713 u32 address = RSP_SegmentToPhysical( l );
715 if ((address + sizeof( Light )) > RDRAMSize)
720 u8 *addr = &RDRAM[address];
722 if (config.hackZelda && (addr[0] == 0x08) && (addr[4] == 0xFF))
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;
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;
742 Normalize(&gSP.lights[n].x);
745 void gSPLookAt( u32 l )
749 void gSPVertex( u32 v, u32 n, u32 v0 )
751 //flush batched triangles:
752 #ifdef __TRIBUFFER_OPT
756 u32 address = RSP_SegmentToPhysical( v );
758 if ((address + sizeof( Vertex ) * n) > RDRAMSize)
763 Vertex *vertex = (Vertex*)&RDRAM[address];
765 if ((n + v0) <= INDEXMAP_SIZE)
769 for (; i < n - (n%4) + v0; i += 4)
772 #ifdef __TRIBUFFER_OPT
773 v = __indexmap_getnew(v, 4);
775 for(int j = 0; j < 4; j++)
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)
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;
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;
799 gSPProcessVertex4(v);
802 for (; i < n + v0; i++)
805 #ifdef __TRIBUFFER_OPT
806 v = __indexmap_getnew(v, 1);
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)
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;
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;
833 LOG(LOG_ERROR, "Using Vertex outside buffer v0=%i, n=%i\n", v0, n);
838 void gSPCIVertex( u32 v, u32 n, u32 v0 )
841 #ifdef __TRIBUFFER_OPT
845 u32 address = RSP_SegmentToPhysical( v );
847 if ((address + sizeof( PDVertex ) * n) > RDRAMSize)
852 PDVertex *vertex = (PDVertex*)&RDRAM[address];
854 if ((n + v0) <= INDEXMAP_SIZE)
858 for (; i < n - (n%4) + v0; i += 4)
861 #ifdef __TRIBUFFER_OPT
862 v = __indexmap_getnew(v, 4);
864 for(unsigned int j = 0; j < 4; j++)
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)];
873 if (gSP.geometryMode & G_LIGHTING)
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;
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;
889 gSPProcessVertex4(v);
892 for(; i < n + v0; i++)
895 #ifdef __TRIBUFFER_OPT
896 v = __indexmap_getnew(v, 1);
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)];
905 if (gSP.geometryMode & G_LIGHTING)
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;
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;
926 LOG(LOG_ERROR, "Using Vertex outside buffer v0=%i, n=%i\n", v0, n);
931 void gSPDMAVertex( u32 v, u32 n, u32 v0 )
934 u32 address = gSP.DMAOffsets.vtx + RSP_SegmentToPhysical( v );
936 if ((address + 10 * n) > RDRAMSize)
941 if ((n + v0) <= INDEXMAP_SIZE)
945 for (; i < n - (n%4) + v0; i += 4)
948 #ifdef __TRIBUFFER_OPT
949 v = __indexmap_getnew(v, 4);
951 for(int j = 0; j < 4; j++)
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];
957 if (gSP.geometryMode & G_LIGHTING)
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;
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;
973 gSPProcessVertex4(v);
976 for (; i < n + v0; i++)
979 #ifdef __TRIBUFFER_OPT
980 //int ind = OGL.triangles.indexmap[i];
981 v = __indexmap_getnew(v, 1);
983 //if previously mapped copy across s/t.
986 // SPVertex *vtx = &OGL.triangles.vertices[ind];
987 // OGL.triangles.vertices[v].s = vtx->s;
988 // OGL.triangles.vertices[v].t = vtx->s;
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];
997 if (gSP.geometryMode & G_LIGHTING)
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;
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;
1012 gSPProcessVertex(v);
1018 LOG(LOG_ERROR, "Using Vertex outside buffer v0=%i, n=%i\n", v0, n);
1023 void gSPDisplayList( u32 dl )
1025 u32 address = RSP_SegmentToPhysical( dl );
1027 if ((address + 8) > RDRAMSize)
1032 if (RSP.PCi < (GBI.PCStackSize - 1))
1035 DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "\n" );
1036 DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gSPDisplayList( 0x%08X );\n",
1040 RSP.PC[RSP.PCi] = address;
1041 RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[address], 24, 8 );
1047 void gSPDMADisplayList( u32 dl, u32 n )
1049 if ((dl + (n << 3)) > RDRAMSize)
1054 u32 curDL = RSP.PC[RSP.PCi];
1056 RSP.PC[RSP.PCi] = RSP_SegmentToPhysical( dl );
1058 while ((RSP.PC[RSP.PCi] - dl) < (n << 3))
1060 if ((RSP.PC[RSP.PCi] + 8) > RDRAMSize)
1065 u32 w0 = *(u32*)&RDRAM[RSP.PC[RSP.PCi]];
1066 u32 w1 = *(u32*)&RDRAM[RSP.PC[RSP.PCi] + 4];
1068 RSP.PC[RSP.PCi] += 8;
1069 RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[RSP.PC[RSP.PCi]], 24, 8 );
1071 GBI.cmd[_SHIFTR( w0, 24, 8 )]( w0, w1 );
1074 RSP.PC[RSP.PCi] = curDL;
1077 void gSPBranchList( u32 dl )
1079 u32 address = RSP_SegmentToPhysical( dl );
1081 if ((address + 8) > RDRAMSize)
1086 RSP.PC[RSP.PCi] = address;
1087 RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[address], 24, 8 );
1090 void gSPBranchLessZ( u32 branchdl, u32 vtx, f32 zval )
1092 u32 address = RSP_SegmentToPhysical( branchdl );
1094 if ((address + 8) > RDRAMSize)
1099 if (OGL.triangles.vertices[vtx].z <= zval)
1100 RSP.PC[RSP.PCi] = address;
1103 void gSPSetDMAOffsets( u32 mtxoffset, u32 vtxoffset )
1105 gSP.DMAOffsets.mtx = mtxoffset;
1106 gSP.DMAOffsets.vtx = vtxoffset;
1109 void gSPSetVertexColorBase( u32 base )
1111 gSP.vertexColorBase = RSP_SegmentToPhysical( base );
1113 #ifdef __TRIBUFFER_OPT
1114 gSPFlushTriangles();
1118 void gSPSprite2DBase( u32 base )
1122 void gSPCopyVertex( SPVertex *dest, SPVertex *src )
1136 void gSPInterpolateVertex( SPVertex *dest, f32 percent, SPVertex *first, SPVertex *second )
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);
1150 void gSPDMATriangles( u32 tris, u32 n )
1152 u32 address = RSP_SegmentToPhysical( tris );
1154 if (address + sizeof( DKRTriangle ) * n > RDRAMSize)
1159 #ifdef __TRIBUFFER_OPT
1160 __indexmap_undomap();
1163 DKRTriangle *triangles = (DKRTriangle*)&RDRAM[address];
1165 for (u32 i = 0; i < n; i++)
1168 if (!(triangles->flag & 0x40))
1170 if (gSP.viewport.vscale[0] > 0)
1171 mode |= G_CULL_BACK;
1173 mode |= G_CULL_FRONT;
1176 if ((gSP.geometryMode&G_CULL_BOTH) != mode)
1178 // OGL_DrawTriangles();
1179 gSP.geometryMode &= ~G_CULL_BOTH;
1180 gSP.geometryMode |= mode;
1181 gSP.changed |= CHANGED_GEOMETRYMODE;
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);
1198 //#ifdef __TRIBUFFER_OPT
1199 OGL_DrawTriangles();
1203 void gSP1Quadrangle( s32 v0, s32 v1, s32 v2, s32 v3)
1205 gSPTriangle( v0, v1, v2);
1206 gSPTriangle( v0, v2, v3);
1207 gSPFlushTriangles();
1210 bool gSPCullVertices( u32 v0, u32 vn )
1212 if (!config.enableClipping)
1216 #ifdef __TRIBUFFER_OPT
1217 v = OGL.triangles.indexmap[v0];
1220 u32 clip = OGL.triangles.vertices[v].clip;
1224 for (unsigned int i = (v0+1); i <= vn; i++)
1227 #ifdef __TRIBUFFER_OPT
1228 v = OGL.triangles.indexmap[i];
1230 if (OGL.triangles.vertices[v].clip != clip) return FALSE;
1235 void gSPCullDisplayList( u32 v0, u32 vn )
1237 if (gSPCullVertices( v0, vn ))
1248 void gSPPopMatrixN( u32 param, u32 num )
1250 if (gSP.matrix.modelViewi > num - 1)
1252 gSP.matrix.modelViewi -= num;
1254 gSP.changed |= CHANGED_MATRIX;
1258 void gSPPopMatrix( u32 param )
1260 if (gSP.matrix.modelViewi > 0)
1262 gSP.matrix.modelViewi--;
1264 gSP.changed |= CHANGED_MATRIX;
1268 void gSPSegment( s32 seg, s32 base )
1275 if ((unsigned int)base > RDRAMSize - 1)
1280 gSP.segment[seg] = base;
1283 void gSPClipRatio( u32 r )
1287 void gSPInsertMatrix( u32 where, u32 num )
1289 f32 fraction, integer;
1291 if (gSP.changed & CHANGED_MATRIX)
1292 gSPCombineMatrices();
1294 if ((where & 0x3) || (where > 0x3C))
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 );
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 );
1311 fraction = modff( gSP.matrix.combined[0][(where - 0x20) >> 1], &integer );
1312 newValue = integer + _FIXED2FLOAT( _SHIFTR( num, 16, 16 ), 16);
1314 // Make sure the sign isn't lost
1315 if ((integer == 0.0f) && (fraction != 0.0f))
1316 newValue = newValue * (fraction / abs( (int)fraction ));
1318 gSP.matrix.combined[0][(where - 0x20) >> 1] = newValue;
1320 fraction = modff( gSP.matrix.combined[0][((where - 0x20) >> 1) + 1], &integer );
1321 newValue = integer + _FIXED2FLOAT( _SHIFTR( num, 0, 16 ), 16 );
1323 // Make sure the sign isn't lost
1324 if ((integer == 0.0f) && (fraction != 0.0f))
1325 newValue = newValue * (fraction / abs( (int)fraction ));
1327 gSP.matrix.combined[0][((where - 0x20) >> 1) + 1] = newValue;
1331 void gSPModifyVertex( u32 vtx, u32 where, u32 val )
1335 #ifdef __TRIBUFFER_OPT
1336 v = OGL.triangles.indexmap[v];
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;
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 );
1351 case G_MWO_POINT_XYSCREEN:
1353 case G_MWO_POINT_ZSCREEN:
1358 void gSPNumLights( s32 n )
1360 gSP.numLights = (n <= 8) ? n : 0;
1364 void gSPLightColor( u32 lightNum, u32 packedColor )
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;
1376 void gSPFogFactor( s16 fm, s16 fo )
1378 gSP.fog.multiplier = fm;
1379 gSP.fog.offset = fo;
1381 gSP.changed |= CHANGED_FOGPOSITION;
1384 void gSPPerspNormalize( u16 scale )
1388 void gSPTexture( f32 sc, f32 tc, s32 level, s32 tile, s32 on )
1390 gSP.texture.scales = sc;
1391 gSP.texture.scalet = tc;
1393 if (gSP.texture.scales == 0.0f) gSP.texture.scales = 1.0f;
1394 if (gSP.texture.scalet == 0.0f) gSP.texture.scalet = 1.0f;
1396 gSP.texture.level = level;
1397 gSP.texture.on = on;
1399 if (gSP.texture.tile != tile)
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;
1407 gSP.changed |= CHANGED_TEXTURESCALE;
1410 void gSPEndDisplayList()
1419 #ifdef __TRIBUFFER_OPT
1420 RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[RSP.PC[RSP.PCi]], 24, 8 );
1421 gSPFlushTriangles();
1425 void gSPGeometryMode( u32 clear, u32 set )
1427 gSP.geometryMode = (gSP.geometryMode & ~clear) | set;
1428 gSP.changed |= CHANGED_GEOMETRYMODE;
1431 void gSPSetGeometryMode( u32 mode )
1433 gSP.geometryMode |= mode;
1434 gSP.changed |= CHANGED_GEOMETRYMODE;
1437 void gSPClearGeometryMode( u32 mode )
1439 gSP.geometryMode &= ~mode;
1440 gSP.changed |= CHANGED_GEOMETRYMODE;
1443 void gSPLine3D( s32 v0, s32 v1, s32 flag )
1445 OGL_DrawLine(v0, v1, 1.5f );
1448 void gSPLineW3D( s32 v0, s32 v1, s32 wd, s32 flag )
1450 OGL_DrawLine(v0, v1, 1.5f + wd * 0.5f );
1453 void gSPBgRect1Cyc( u32 bg )
1458 u32 addr = RSP_SegmentToPhysical(bg) >> 1;
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
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
1471 //wxUint16 imageFlip = ((u16*)gfx.RDRAM)[(addr+13)^1]; // 13;
1472 //d.flipX = (u8)imageFlip&0x01;
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];
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;
1486 u32 address = RSP_SegmentToPhysical( bg );
1487 uObjScaleBg *objScaleBg = (uObjScaleBg*)&RDRAM[address];
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;
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;
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 );
1510 f32 frameX0 = frameX;
1511 f32 frameY0 = frameY;
1512 f32 frameS0 = imageX;
1513 f32 frameT0 = imageY;
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 );
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 );
1525 if ((frameX1 - frameX0) < frameW)
1527 f32 frameX2 = frameW - (frameX1 - frameX0) + frameX1;
1528 gDPTextureRectangle( frameX1, frameY0, frameX2 - 1, frameY1 - 1, 0, 0, frameT0, scaleW, scaleH );
1531 if ((frameY1 - frameY0) < frameH)
1533 f32 frameY2 = frameH - (frameY1 - frameY0) + frameY1;
1534 gDPTextureRectangle( frameX0, frameY1, frameX1 - 1, frameY2 - 1, 0, frameS0, 0, scaleW, scaleH );
1537 gDPTextureRectangle( 0, 0, 319, 239, 0, 0, 0, scaleW, scaleH );
1540 void gSPBgRectCopy( u32 bg )
1543 u32 address = RSP_SegmentToPhysical( bg );
1544 uObjBg *objBg = (uObjBg*)&RDRAM[address];
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;
1554 u16 imageX = objBg->imageX >> 5;
1555 u16 imageY = objBg->imageY >> 5;
1557 s16 frameX = objBg->frameX / 4;
1558 s16 frameY = objBg->frameY / 4;
1559 u16 frameW = objBg->frameW >> 2;
1560 u16 frameH = objBg->frameH >> 2;
1562 gSPTexture( 1.0f, 1.0f, 0, 0, TRUE );
1564 gDPTextureRectangle( frameX, frameY, frameX + frameW - 1, frameY + frameH - 1, 0, imageX, imageY, 4, 1 );
1567 void gSPObjRectangle( u32 sp )
1569 u32 address = RSP_SegmentToPhysical( sp );
1570 uObjSprite *objSprite = (uObjSprite*)&RDRAM[address];
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;
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 );
1582 void gSPObjLoadTxtr( u32 tx )
1584 u32 address = RSP_SegmentToPhysical( tx );
1585 uObjTxtr *objTxtr = (uObjTxtr*)&RDRAM[address];
1587 if ((gSP.status[objTxtr->block.sid >> 2] & objTxtr->block.mask) != objTxtr->block.flag)
1589 switch (objTxtr->block.type)
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 );
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 );
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 );
1607 gSP.status[objTxtr->block.sid >> 2] = (gSP.status[objTxtr->block.sid >> 2] & ~objTxtr->block.mask) | (objTxtr->block.flag & objTxtr->block.mask);
1611 void gSPObjSprite( u32 sp )
1613 u32 address = RSP_SegmentToPhysical( sp );
1614 uObjSprite *objSprite = (uObjSprite*)&RDRAM[address];
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;
1625 f32 x1 = objX + imageW / scaleW - 1;
1626 f32 y1 = objY + imageH / scaleH - 1;
1628 s32 v0=0,v1=1,v2=2,v3=3;
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];
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;
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 );
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;
1684 OGL_AddTriangle(v0, v1, v2);
1685 OGL_AddTriangle(v0, v2, v3);
1686 OGL_DrawTriangles();
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 ));
1693 void gSPObjLoadTxSprite( u32 txsp )
1695 gSPObjLoadTxtr( txsp );
1696 gSPObjSprite( txsp + sizeof( uObjTxtr ) );
1699 void gSPObjLoadTxRectR( u32 txsp )
1701 gSPObjLoadTxtr( txsp );
1702 // gSPObjRectangleR( txsp + sizeof( uObjTxtr ) );
1705 void gSPObjMatrix( u32 mtx )
1707 u32 address = RSP_SegmentToPhysical( mtx );
1708 uObjMtx *objMtx = (uObjMtx*)&RDRAM[address];
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 );
1720 void gSPObjSubMatrix( u32 mtx )
1726 void (*gSPTransformVertex4)(u32 v, float mtx[4][4]) =
1727 gSPTransformVertex4_default;
1728 void (*gSPTransformNormal4)(u32 v, float mtx[4][4]) =
1729 gSPTransformNormal4_default;
1730 void (*gSPLightVertex4)(u32 v) = gSPLightVertex4_default;
1731 void (*gSPBillboardVertex4)(u32 v) = gSPBillboardVertex4_default;
1733 void (*gSPTransformVertex)(float vtx[4], float mtx[4][4]) =
1734 gSPTransformVertex_default;
1735 void (*gSPLightVertex)(u32 v) = gSPLightVertex_default;
1736 void (*gSPBillboardVertex)(u32 v, u32 i) = gSPBillboardVertex_default;