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 |
25 | extern u32 uc_crc, uc_dcrc; |
26 | extern char uc_str[256]; |
27 | #endif |
28 | |
29 | void gSPCombineMatrices(); |
30 | |
31 | //#ifdef __TRIBUFFER_OPT |
32 | void __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 | |
45 | void __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 | |
52 | u32 __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 | |
71 | void __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 | |
88 | u32 __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 | |
155 | void 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 | |
186 | void gSP1Triangle( const s32 v0, const s32 v1, const s32 v2) |
187 | { |
188 | gSPTriangle( v0, v1, v2); |
189 | gSPFlushTriangles(); |
190 | } |
191 | |
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 ) |
194 | { |
195 | gSPTriangle( v00, v01, v02); |
196 | gSPTriangle( v10, v11, v12); |
197 | gSPFlushTriangles(); |
198 | } |
199 | |
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 ) |
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 | |
213 | gSPInfo gSP; |
214 | |
215 | f32 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 |
224 | static 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 | |
241 | void 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 | |
254 | static 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 | |
279 | static 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 | |
311 | static 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 | |
337 | void 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 | |
426 | void 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 | |
437 | static 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 | |
451 | static 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 | |
472 | static 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 | |
480 | void gSPCombineMatrices() |
481 | { |
482 | MultMatrix(gSP.matrix.projection, gSP.matrix.modelView[gSP.matrix.modelViewi], gSP.matrix.combined); |
483 | gSP.changed &= ~CHANGED_MATRIX; |
484 | } |
485 | |
486 | void 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 | |
556 | void 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 | |
583 | void gSPNoOp() |
584 | { |
585 | gSPFlushTriangles(); |
586 | } |
587 | |
588 | void gSPTriangleUnknown() |
589 | { |
590 | #ifdef __TRIBUFFER_OPT |
591 | gSPFlushTriangles(); |
592 | #endif |
593 | } |
594 | |
595 | void 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 | |
634 | void 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 | |
661 | void 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 | |
693 | void 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 | |
707 | void 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 | |
745 | void gSPLookAt( u32 l ) |
746 | { |
747 | } |
748 | |
749 | void 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 | |
838 | void 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 | |
931 | void 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 | |
1023 | void 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 | |
1047 | void 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 | |
1077 | void 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 | |
1090 | void 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 | |
1103 | void gSPSetDMAOffsets( u32 mtxoffset, u32 vtxoffset ) |
1104 | { |
1105 | gSP.DMAOffsets.mtx = mtxoffset; |
1106 | gSP.DMAOffsets.vtx = vtxoffset; |
1107 | } |
1108 | |
1109 | void gSPSetVertexColorBase( u32 base ) |
1110 | { |
1111 | gSP.vertexColorBase = RSP_SegmentToPhysical( base ); |
1112 | |
1113 | #ifdef __TRIBUFFER_OPT |
1114 | gSPFlushTriangles(); |
1115 | #endif |
1116 | } |
1117 | |
1118 | void gSPSprite2DBase( u32 base ) |
1119 | { |
1120 | } |
1121 | |
1122 | void 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 | |
1136 | void 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 | |
1150 | void 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 | { |
1178 | OGL_DrawTriangles(); |
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 | |
1198 | #ifdef __TRIBUFFER_OPT |
1199 | OGL_DrawTriangles(); |
1200 | #endif |
1201 | } |
1202 | |
1203 | void gSP1Quadrangle( s32 v0, s32 v1, s32 v2, s32 v3) |
1204 | { |
1205 | gSPTriangle( v0, v1, v2); |
1206 | gSPTriangle( v0, v2, v3); |
1207 | gSPFlushTriangles(); |
1208 | } |
1209 | |
1210 | bool 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 | |
1235 | void 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 | |
1248 | void 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 | |
1258 | void gSPPopMatrix( u32 param ) |
1259 | { |
1260 | if (gSP.matrix.modelViewi > 0) |
1261 | { |
1262 | gSP.matrix.modelViewi--; |
1263 | |
1264 | gSP.changed |= CHANGED_MATRIX; |
1265 | } |
1266 | } |
1267 | |
1268 | void 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 | |
1283 | void gSPClipRatio( u32 r ) |
1284 | { |
1285 | } |
1286 | |
1287 | void 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 | |
1331 | void 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 | |
1358 | void gSPNumLights( s32 n ) |
1359 | { |
1360 | gSP.numLights = (n <= 8) ? n : 0; |
1361 | } |
1362 | |
1363 | |
1364 | void 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 | |
1376 | void gSPFogFactor( s16 fm, s16 fo ) |
1377 | { |
1378 | gSP.fog.multiplier = fm; |
1379 | gSP.fog.offset = fo; |
1380 | |
1381 | gSP.changed |= CHANGED_FOGPOSITION; |
1382 | } |
1383 | |
1384 | void gSPPerspNormalize( u16 scale ) |
1385 | { |
1386 | } |
1387 | |
1388 | void 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 | |
1410 | void 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 | |
1425 | void gSPGeometryMode( u32 clear, u32 set ) |
1426 | { |
1427 | gSP.geometryMode = (gSP.geometryMode & ~clear) | set; |
1428 | gSP.changed |= CHANGED_GEOMETRYMODE; |
1429 | } |
1430 | |
1431 | void gSPSetGeometryMode( u32 mode ) |
1432 | { |
1433 | gSP.geometryMode |= mode; |
1434 | gSP.changed |= CHANGED_GEOMETRYMODE; |
1435 | } |
1436 | |
1437 | void gSPClearGeometryMode( u32 mode ) |
1438 | { |
1439 | gSP.geometryMode &= ~mode; |
1440 | gSP.changed |= CHANGED_GEOMETRYMODE; |
1441 | } |
1442 | |
1443 | void gSPLine3D( s32 v0, s32 v1, s32 flag ) |
1444 | { |
1445 | OGL_DrawLine(v0, v1, 1.5f ); |
1446 | } |
1447 | |
1448 | void gSPLineW3D( s32 v0, s32 v1, s32 wd, s32 flag ) |
1449 | { |
1450 | OGL_DrawLine(v0, v1, 1.5f + wd * 0.5f ); |
1451 | } |
1452 | |
1453 | void 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 | |
1540 | void 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 | |
1567 | void 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 | |
1582 | void 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 | |
1611 | void 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 | |
1693 | void gSPObjLoadTxSprite( u32 txsp ) |
1694 | { |
1695 | gSPObjLoadTxtr( txsp ); |
1696 | gSPObjSprite( txsp + sizeof( uObjTxtr ) ); |
1697 | } |
1698 | |
1699 | void gSPObjLoadTxRectR( u32 txsp ) |
1700 | { |
1701 | gSPObjLoadTxtr( txsp ); |
1702 | // gSPObjRectangleR( txsp + sizeof( uObjTxtr ) ); |
1703 | } |
1704 | |
1705 | void 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 | |
1720 | void gSPObjSubMatrix( u32 mtx ) |
1721 | { |
1722 | } |
1723 | |
1724 | |
1725 | #ifdef __VEC4_OPT |
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; |
1732 | #endif |
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; |
1737 | |