34cf4058 |
1 | #include <stdlib.h> |
2 | |
3 | #include "gles2N64.h" |
4 | #include "N64.h" |
5 | #include "GBI.h" |
6 | #include "RSP.h" |
7 | #include "gDP.h" |
8 | #include "gSP.h" |
9 | #include "Types.h" |
10 | #include "Debug.h" |
11 | #include "convert.h" |
12 | #include "OpenGL.h" |
13 | #include "CRC.h" |
14 | #include "DepthBuffer.h" |
15 | #include "VI.h" |
16 | #include "Config.h" |
17 | |
18 | |
19 | //thank rice_video for this: |
20 | bool _IsRenderTexture() |
21 | { |
22 | bool foundSetScissor=false; |
23 | bool foundFillRect=false; |
24 | bool foundSetFillColor=false; |
25 | bool foundSetCImg=false; |
26 | bool foundTxtRect=false; |
27 | int height; |
28 | unsigned int newFillColor = 0; |
29 | unsigned int dwPC = RSP.PC[RSP.PCi]; // This points to the next instruction |
30 | |
31 | for(int i=0; i<10; i++ ) |
32 | { |
33 | unsigned int w0 = *(unsigned int *)(RDRAM + dwPC + i*8); |
34 | unsigned int w1 = *(unsigned int *)(RDRAM + dwPC + 4 + i*8); |
35 | |
36 | if ((w0>>24) == G_SETSCISSOR) |
37 | { |
38 | height = ((w1>>0 )&0xFFF)/4; |
39 | foundSetScissor = true; |
40 | continue; |
41 | } |
42 | |
43 | if ((w0>>24) == G_SETFILLCOLOR) |
44 | { |
45 | height = ((w1>>0 )&0xFFF)/4; |
46 | foundSetFillColor = true; |
47 | newFillColor = w1; |
48 | continue; |
49 | } |
50 | |
51 | if ((w0>>24) == G_FILLRECT) |
52 | { |
53 | unsigned int x0 = ((w1>>12)&0xFFF)/4; |
54 | unsigned int y0 = ((w1>>0 )&0xFFF)/4; |
55 | unsigned int x1 = ((w0>>12)&0xFFF)/4; |
56 | unsigned int y1 = ((w0>>0 )&0xFFF)/4; |
57 | |
58 | if (x0 == 0 && y0 == 0) |
59 | { |
60 | if( x1 == gDP.colorImage.width) |
61 | { |
62 | height = y1; |
63 | foundFillRect = true; |
64 | continue; |
65 | } |
66 | |
67 | if(x1 == (unsigned int)(gDP.colorImage.width-1)) |
68 | { |
69 | height = y1+1; |
70 | foundFillRect = true; |
71 | continue; |
72 | } |
73 | } |
74 | } |
75 | |
76 | if ((w0>>24) == G_TEXRECT) |
77 | { |
78 | foundTxtRect = true; |
79 | break; |
80 | } |
81 | |
82 | if ((w0>>24) == G_SETCIMG) |
83 | { |
84 | foundSetCImg = true; |
85 | break; |
86 | } |
87 | } |
88 | |
89 | if (foundFillRect ) |
90 | { |
91 | if (foundSetFillColor) |
92 | { |
93 | if (newFillColor != 0xFFFCFFFC) |
94 | return true; // this is a render_texture |
95 | else |
96 | return false; |
97 | } |
98 | |
99 | if (gDP.fillColor.i == 0x00FFFFF7) |
100 | return true; // this is a render_texture |
101 | else |
102 | return false; // this is a normal ZImg |
103 | } |
104 | else if (foundSetFillColor && newFillColor == 0xFFFCFFFC && foundSetCImg ) |
105 | { |
106 | return false; |
107 | } |
108 | else |
109 | return true; |
110 | |
111 | |
112 | if (!foundSetCImg) return true; |
113 | |
114 | if (foundSetScissor ) return true; |
115 | |
116 | return false; |
117 | } |
118 | |
119 | gDPInfo gDP; |
120 | |
121 | void gDPSetOtherMode( u32 mode0, u32 mode1 ) |
122 | { |
123 | gDP.otherMode.h = mode0; |
124 | gDP.otherMode.l = mode1; |
125 | gDP.changed |= CHANGED_RENDERMODE | CHANGED_CYCLETYPE | CHANGED_ALPHACOMPARE; |
126 | |
127 | #ifdef DEBUG |
128 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetOtherMode( %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s, %s | %s | %s%s%s%s%s | %s | %s%s%s );\n", |
129 | AlphaDitherText[gDP.otherMode.alphaDither], |
130 | ColorDitherText[gDP.otherMode.colorDither], |
131 | CombineKeyText[gDP.otherMode.combineKey], |
132 | TextureConvertText[gDP.otherMode.textureConvert], |
133 | TextureFilterText[gDP.otherMode.textureFilter], |
134 | TextureLUTText[gDP.otherMode.textureLUT], |
135 | TextureLODText[gDP.otherMode.textureLOD], |
136 | TextureDetailText[gDP.otherMode.textureDetail], |
137 | TexturePerspText[gDP.otherMode.texturePersp], |
138 | CycleTypeText[gDP.otherMode.cycleType], |
139 | PipelineModeText[gDP.otherMode.pipelineMode], |
140 | AlphaCompareText[gDP.otherMode.alphaCompare], |
141 | DepthSourceText[gDP.otherMode.depthSource], |
142 | gDP.otherMode.AAEnable ? "AA_EN | " : "", |
143 | gDP.otherMode.depthCompare ? "Z_CMP | " : "", |
144 | gDP.otherMode.depthUpdate ? "Z_UPD | " : "", |
145 | gDP.otherMode.imageRead ? "IM_RD | " : "", |
146 | CvgDestText[gDP.otherMode.cvgDest], |
147 | DepthModeText[gDP.otherMode.depthMode], |
148 | gDP.otherMode.cvgXAlpha ? "CVG_X_ALPHA | " : "", |
149 | gDP.otherMode.alphaCvgSel ? "ALPHA_CVG_SEL | " : "", |
150 | gDP.otherMode.forceBlender ? "FORCE_BL" : "" ); |
151 | #endif |
152 | } |
153 | |
154 | void gDPSetPrimDepth( u16 z, u16 dz ) |
155 | { |
156 | z = z&0x7FFF; |
157 | |
158 | //gDP.primDepth.z = (_FIXED2FLOAT( z, 15 ) - gSP.viewport.vtrans[2]) / gSP.viewport.vscale[2] ; |
159 | gDP.primDepth.z = (z - gSP.viewport.vtrans[2]) / gSP.viewport.vscale[2] ; |
160 | gDP.primDepth.deltaZ = dz; |
161 | gDP.changed |= CHANGED_PRIMITIVEZ; |
162 | |
163 | #ifdef DEBUG |
164 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetPrimDepth( %f, %f );\n", |
165 | gDP.primDepth.z, |
166 | gDP.primDepth.deltaZ); |
167 | #endif |
168 | } |
169 | |
170 | void gDPPipelineMode( u32 mode ) |
171 | { |
172 | gDP.otherMode.pipelineMode = mode; |
173 | |
174 | #ifdef DEBUG |
175 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPPipelineMode( %s );\n", |
176 | PipelineModeText[gDP.otherMode.pipelineMode] ); |
177 | #endif |
178 | } |
179 | |
180 | void gDPSetCycleType( u32 type ) |
181 | { |
182 | gDP.otherMode.cycleType = type; |
183 | gDP.changed |= CHANGED_CYCLETYPE; |
184 | |
185 | #ifdef DEBUG |
186 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetCycleType( %s );\n", |
187 | CycleTypeText[gDP.otherMode.cycleType] ); |
188 | #endif |
189 | } |
190 | |
191 | void gDPSetTexturePersp( u32 enable ) |
192 | { |
193 | gDP.otherMode.texturePersp = enable; |
194 | |
195 | #ifdef DEBUG |
196 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTexturePersp( %s );\n", |
197 | TexturePerspText[gDP.otherMode.texturePersp] ); |
198 | #endif |
199 | } |
200 | |
201 | void gDPSetTextureDetail( u32 type ) |
202 | { |
203 | gDP.otherMode.textureDetail = type; |
204 | |
205 | #ifdef DEBUG |
206 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureDetail( %s );\n", |
207 | TextureDetailText[gDP.otherMode.textureDetail] ); |
208 | #endif |
209 | } |
210 | |
211 | void gDPSetTextureLOD( u32 mode ) |
212 | { |
213 | gDP.otherMode.textureLOD = mode; |
214 | |
215 | #ifdef DEBUG |
216 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureLOD( %s );\n", |
217 | TextureLODText[gDP.otherMode.textureLOD] ); |
218 | #endif |
219 | } |
220 | |
221 | void gDPSetTextureLUT( u32 mode ) |
222 | { |
223 | gDP.otherMode.textureLUT = mode; |
224 | |
225 | #ifdef DEBUG |
226 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureLUT( %s );\n", |
227 | TextureLUTText[gDP.otherMode.textureLUT] ); |
228 | #endif |
229 | } |
230 | |
231 | void gDPSetTextureFilter( u32 type ) |
232 | { |
233 | gDP.otherMode.textureFilter = type; |
234 | |
235 | #ifdef DEBUG |
236 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureFilter( %s );\n", |
237 | TextureFilterText[gDP.otherMode.textureFilter] ); |
238 | #endif |
239 | } |
240 | |
241 | void gDPSetTextureConvert( u32 type ) |
242 | { |
243 | gDP.otherMode.textureConvert = type; |
244 | |
245 | #ifdef DEBUG |
246 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureConvert( %s );\n", |
247 | TextureConvertText[gDP.otherMode.textureConvert] ); |
248 | #endif |
249 | } |
250 | |
251 | void gDPSetCombineKey( u32 type ) |
252 | { |
253 | gDP.otherMode.combineKey = type; |
254 | |
255 | #ifdef DEBUG |
256 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, "gDPSetCombineKey( %s );\n", |
257 | CombineKeyText[gDP.otherMode.combineKey] ); |
258 | #endif |
259 | } |
260 | |
261 | void gDPSetColorDither( u32 type ) |
262 | { |
263 | gDP.otherMode.colorDither = type; |
264 | |
265 | #ifdef DEBUG |
266 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetColorDither( %s );\n", |
267 | ColorDitherText[gDP.otherMode.colorDither] ); |
268 | #endif |
269 | } |
270 | |
271 | void gDPSetAlphaDither( u32 type ) |
272 | { |
273 | gDP.otherMode.alphaDither = type; |
274 | |
275 | #ifdef DEBUG |
276 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetAlphaDither( %s );\n", |
277 | AlphaDitherText[gDP.otherMode.alphaDither] ); |
278 | #endif |
279 | } |
280 | |
281 | void gDPSetAlphaCompare( u32 mode ) |
282 | { |
283 | gDP.otherMode.alphaCompare = mode; |
284 | gDP.changed |= CHANGED_ALPHACOMPARE; |
285 | |
286 | #ifdef DEBUG |
287 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetAlphaCompare( %s );\n", |
288 | AlphaCompareText[gDP.otherMode.alphaCompare] ); |
289 | #endif |
290 | } |
291 | |
292 | void gDPSetDepthSource( u32 source ) |
293 | { |
294 | gDP.otherMode.depthSource = source; |
295 | gDP.changed |= CHANGED_DEPTHSOURCE; |
296 | |
297 | #ifdef DEBUG |
298 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetDepthSource( %s );\n", |
299 | DepthSourceText[gDP.otherMode.depthSource] ); |
300 | #endif |
301 | } |
302 | |
303 | void gDPSetRenderMode( u32 mode1, u32 mode2 ) |
304 | { |
305 | gDP.otherMode.l &= 0x00000007; |
306 | gDP.otherMode.l |= mode1 | mode2; |
307 | gDP.changed |= CHANGED_RENDERMODE; |
308 | |
309 | #ifdef DEBUG |
310 | // THIS IS INCOMPLETE!!! |
311 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetRenderMode( %s%s%s%s%s | %s | %s%s%s );\n", |
312 | gDP.otherMode.AAEnable ? "AA_EN | " : "", |
313 | gDP.otherMode.depthCompare ? "Z_CMP | " : "", |
314 | gDP.otherMode.depthUpdate ? "Z_UPD | " : "", |
315 | gDP.otherMode.imageRead ? "IM_RD | " : "", |
316 | CvgDestText[gDP.otherMode.cvgDest], |
317 | DepthModeText[gDP.otherMode.depthMode], |
318 | gDP.otherMode.cvgXAlpha ? "CVG_X_ALPHA | " : "", |
319 | gDP.otherMode.alphaCvgSel ? "ALPHA_CVG_SEL | " : "", |
320 | gDP.otherMode.forceBlender ? "FORCE_BL" : "" ); |
321 | #endif |
322 | } |
323 | |
324 | void gDPSetCombine( s32 muxs0, s32 muxs1 ) |
325 | { |
326 | gDP.combine.muxs0 = muxs0; |
327 | gDP.combine.muxs1 = muxs1; |
328 | gDP.changed |= CHANGED_COMBINE; |
329 | |
330 | #ifdef DEBUG |
331 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, "gDPSetCombine( %s, %s, %s, %s, %s, %s, %s, %s,\n", |
332 | saRGBText[gDP.combine.saRGB0], |
333 | sbRGBText[gDP.combine.sbRGB0], |
334 | mRGBText[gDP.combine.mRGB0], |
335 | aRGBText[gDP.combine.aRGB0], |
336 | saAText[gDP.combine.saA0], |
337 | sbAText[gDP.combine.sbA0], |
338 | mAText[gDP.combine.mA0], |
339 | aAText[gDP.combine.aA0] ); |
340 | |
341 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, " %s, %s, %s, %s, %s, %s, %s, %s );\n", |
342 | saRGBText[gDP.combine.saRGB1], |
343 | sbRGBText[gDP.combine.sbRGB1], |
344 | mRGBText[gDP.combine.mRGB1], |
345 | aRGBText[gDP.combine.aRGB1], |
346 | saAText[gDP.combine.saA1], |
347 | sbAText[gDP.combine.sbA1], |
348 | mAText[gDP.combine.mA1], |
349 | aAText[gDP.combine.aA1] ); |
350 | |
351 | #endif |
352 | } |
353 | |
354 | void gDPSetColorImage( u32 format, u32 size, u32 width, u32 address ) |
355 | { |
356 | if (config.updateMode == SCREEN_UPDATE_AT_CI_CHANGE) |
357 | OGL_SwapBuffers(); |
358 | |
359 | if (config.updateMode == SCREEN_UPDATE_AT_1ST_CI_CHANGE && OGL.screenUpdate) |
360 | OGL_SwapBuffers(); |
361 | |
362 | u32 addr = RSP_SegmentToPhysical( address ); |
363 | |
364 | if (gDP.colorImage.address != addr) |
365 | { |
366 | gDP.colorImage.changed = FALSE; |
367 | if (width == VI.width) |
368 | gDP.colorImage.height = VI.height; |
369 | else |
370 | gDP.colorImage.height = 1; |
371 | } |
372 | |
373 | gDP.colorImage.format = format; |
374 | gDP.colorImage.size = size; |
375 | gDP.colorImage.width = width; |
376 | gDP.colorImage.address = addr; |
377 | |
378 | if (config.ignoreOffscreenRendering) |
379 | { |
380 | int i; |
381 | |
382 | //colorimage byte size: |
383 | //color image height is not the best thing to base this on, its normally set |
384 | //later on in the code |
385 | |
386 | if (gDP.colorImage.address == gDP.depthImageAddress) |
387 | { |
388 | OGL.renderingToTexture = false; |
389 | } |
390 | else if (size == G_IM_SIZ_16b && format == G_IM_FMT_RGBA) |
391 | { |
392 | int s = 0; |
393 | switch(size) |
394 | { |
395 | case G_IM_SIZ_4b: s = (gDP.colorImage.width * gDP.colorImage.height) / 2; break; |
396 | case G_IM_SIZ_8b: s = (gDP.colorImage.width * gDP.colorImage.height); break; |
397 | case G_IM_SIZ_16b: s = (gDP.colorImage.width * gDP.colorImage.height) * 2; break; |
398 | case G_IM_SIZ_32b: s = (gDP.colorImage.width * gDP.colorImage.height) * 4; break; |
399 | } |
400 | u32 start = addr & 0x00FFFFFF; |
401 | u32 end = min(start + s, RDRAMSize); |
402 | for(i = 0; i < VI.displayNum; i++) |
403 | { |
404 | if (VI.display[i].start <= end && VI.display[i].start >= start) break; |
405 | if (start <= VI.display[i].end && start >= VI.display[i].start) break; |
406 | } |
407 | |
408 | OGL.renderingToTexture = (i == VI.displayNum); |
409 | } |
410 | else |
411 | { |
412 | OGL.renderingToTexture = true; |
413 | } |
414 | |
415 | #if 0 |
416 | if (OGL.renderingToTexture) |
417 | { |
418 | printf("start=%i end=%i\n", start, end); |
419 | printf("display="); |
420 | for(int i=0; i< VI.displayNum; i++) printf("%i,%i:", VI.display[i].start, VI.display[i].end); |
421 | printf("\n"); |
422 | } |
423 | #endif |
424 | } |
425 | else |
426 | { |
427 | OGL.renderingToTexture = false; |
428 | } |
429 | |
430 | |
431 | #ifdef DEBUG |
432 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetColorImage( %s, %s, %i, 0x%08X );\n", |
433 | ImageFormatText[gDP.colorImage.format], |
434 | ImageSizeText[gDP.colorImage.size], |
435 | gDP.colorImage.width, |
436 | gDP.colorImage.address ); |
437 | #endif |
438 | } |
439 | |
440 | void gDPSetTextureImage( u32 format, u32 size, u32 width, u32 address ) |
441 | { |
442 | gDP.textureImage.format = format; |
443 | gDP.textureImage.size = size; |
444 | gDP.textureImage.width = width; |
445 | gDP.textureImage.address = RSP_SegmentToPhysical( address ); |
446 | gDP.textureImage.bpl = gDP.textureImage.width << gDP.textureImage.size >> 1; |
447 | |
448 | #ifdef DEBUG |
449 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureImage( %s, %s, %i, 0x%08X );\n", |
450 | ImageFormatText[gDP.textureImage.format], |
451 | ImageSizeText[gDP.textureImage.size], |
452 | gDP.textureImage.width, |
453 | gDP.textureImage.address ); |
454 | #endif |
455 | } |
456 | |
457 | void gDPSetDepthImage( u32 address ) |
458 | { |
459 | // if (address != gDP.depthImageAddress) |
460 | // OGL_ClearDepthBuffer(); |
461 | |
462 | u32 addr = RSP_SegmentToPhysical(address); |
463 | DepthBuffer_SetBuffer(addr); |
464 | |
465 | if (depthBuffer.current->cleared) |
466 | OGL_ClearDepthBuffer(); |
467 | |
468 | gDP.depthImageAddress = addr; |
469 | |
470 | #ifdef DEBUG |
471 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetDepthImage( 0x%08X );\n", gDP.depthImageAddress ); |
472 | #endif |
473 | } |
474 | |
475 | void gDPSetEnvColor( u32 r, u32 g, u32 b, u32 a ) |
476 | { |
477 | gDP.envColor.r = r * 0.0039215689f; |
478 | gDP.envColor.g = g * 0.0039215689f; |
479 | gDP.envColor.b = b * 0.0039215689f; |
480 | gDP.envColor.a = a * 0.0039215689f; |
481 | |
482 | gDP.changed |= CHANGED_ENV_COLOR; |
483 | |
484 | #ifdef DEBUG |
485 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, "gDPSetEnvColor( %u, %u, %u, %u );\n", |
486 | r, g, b, a ); |
487 | #endif |
488 | } |
489 | |
490 | void gDPSetBlendColor( u32 r, u32 g, u32 b, u32 a ) |
491 | { |
492 | gDP.blendColor.r = r * 0.0039215689f; |
493 | gDP.blendColor.g = g * 0.0039215689f; |
494 | gDP.blendColor.b = b * 0.0039215689f; |
495 | gDP.blendColor.a = a * 0.0039215689f; |
496 | gDP.changed |= CHANGED_BLENDCOLOR; |
497 | |
498 | #ifdef DEBUG |
499 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetBlendColor( %u, %u, %u, %u );\n", |
500 | r, g, b, a ); |
501 | #endif |
502 | } |
503 | |
504 | void gDPSetFogColor( u32 r, u32 g, u32 b, u32 a ) |
505 | { |
506 | gDP.fogColor.r = r * 0.0039215689f; |
507 | gDP.fogColor.g = g * 0.0039215689f; |
508 | gDP.fogColor.b = b * 0.0039215689f; |
509 | gDP.fogColor.a = a * 0.0039215689f; |
510 | |
511 | gDP.changed |= CHANGED_FOGCOLOR; |
512 | |
513 | #ifdef DEBUG |
514 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetFogColor( %u, %u, %u, %u );\n", |
515 | r, g, b, a ); |
516 | #endif |
517 | } |
518 | |
519 | void gDPSetFillColor( u32 c ) |
520 | { |
521 | |
522 | gDP.fillColor.i = c; |
523 | gDP.fillColor.r = _SHIFTR( c, 11, 5 ) * 0.032258064f; |
524 | gDP.fillColor.g = _SHIFTR( c, 6, 5 ) * 0.032258064f; |
525 | gDP.fillColor.b = _SHIFTR( c, 1, 5 ) * 0.032258064f; |
526 | gDP.fillColor.a = _SHIFTR( c, 0, 1 ); |
527 | |
528 | gDP.fillColor.z = _SHIFTR( c, 2, 14 ); |
529 | gDP.fillColor.dz = _SHIFTR( c, 0, 2 ); |
530 | |
531 | #ifdef DEBUG |
532 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetFillColor( 0x%08X );\n", c ); |
533 | #endif |
534 | } |
535 | |
536 | void gDPSetPrimColor( u32 m, u32 l, u32 r, u32 g, u32 b, u32 a ) |
537 | { |
538 | gDP.primColor.m = m; |
539 | gDP.primColor.l = l * 0.0039215689f; |
540 | gDP.primColor.r = r * 0.0039215689f; |
541 | gDP.primColor.g = g * 0.0039215689f; |
542 | gDP.primColor.b = b * 0.0039215689f; |
543 | gDP.primColor.a = a * 0.0039215689f; |
544 | |
545 | gDP.changed |= CHANGED_PRIM_COLOR; |
546 | |
547 | #ifdef DEBUG |
548 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, "gDPSetPrimColor( %u, %u, %u, %u, %u, %u );\n", |
549 | m, l, r, g, b, a ); |
550 | #endif |
551 | } |
552 | |
553 | void gDPSetTile( u32 format, u32 size, u32 line, u32 tmem, u32 tile, u32 palette, u32 cmt, u32 cms, u32 maskt, u32 masks, u32 shiftt, u32 shifts ) |
554 | { |
555 | if (((size == G_IM_SIZ_4b) || (size == G_IM_SIZ_8b)) && (format == G_IM_FMT_RGBA)) |
556 | format = G_IM_FMT_CI; |
557 | |
558 | gDP.tiles[tile].format = format; |
559 | gDP.tiles[tile].size = size; |
560 | gDP.tiles[tile].line = line; |
561 | gDP.tiles[tile].tmem = tmem; |
562 | gDP.tiles[tile].palette = palette; |
563 | gDP.tiles[tile].cmt = cmt; |
564 | gDP.tiles[tile].cms = cms; |
565 | gDP.tiles[tile].maskt = maskt; |
566 | gDP.tiles[tile].masks = masks; |
567 | gDP.tiles[tile].shiftt = shiftt; |
568 | gDP.tiles[tile].shifts = shifts; |
569 | |
570 | if (!gDP.tiles[tile].masks) gDP.tiles[tile].clamps = 1; |
571 | if (!gDP.tiles[tile].maskt) gDP.tiles[tile].clampt = 1; |
572 | } |
573 | |
574 | void gDPSetTileSize( u32 tile, u32 uls, u32 ult, u32 lrs, u32 lrt ) |
575 | { |
576 | gDP.tiles[tile].uls = _SHIFTR( uls, 2, 10 ); |
577 | gDP.tiles[tile].ult = _SHIFTR( ult, 2, 10 ); |
578 | gDP.tiles[tile].lrs = _SHIFTR( lrs, 2, 10 ); |
579 | gDP.tiles[tile].lrt = _SHIFTR( lrt, 2, 10 ); |
580 | |
581 | gDP.tiles[tile].fuls = _FIXED2FLOAT( uls, 2 ); |
582 | gDP.tiles[tile].fult = _FIXED2FLOAT( ult, 2 ); |
583 | gDP.tiles[tile].flrs = _FIXED2FLOAT( lrs, 2 ); |
584 | gDP.tiles[tile].flrt = _FIXED2FLOAT( lrt, 2 ); |
585 | |
586 | gDP.changed |= CHANGED_TILE; |
587 | |
588 | #ifdef DEBUG |
589 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTileSize( %u, %.2f, %.2f, %.2f, %.2f );\n", |
590 | tile, |
591 | gDP.tiles[tile].fuls, |
592 | gDP.tiles[tile].fult, |
593 | gDP.tiles[tile].flrs, |
594 | gDP.tiles[tile].flrt ); |
595 | #endif |
596 | } |
597 | |
598 | void gDPLoadTile( u32 tile, u32 uls, u32 ult, u32 lrs, u32 lrt ) |
599 | { |
600 | void (*Interleave)( void *mem, u32 numDWords ); |
601 | |
602 | u32 address, height, bpl, line, y; |
603 | u64 *dest; |
604 | u8 *src; |
605 | |
606 | gDPSetTileSize( tile, uls, ult, lrs, lrt ); |
607 | gDP.loadTile = &gDP.tiles[tile]; |
608 | |
609 | if (gDP.loadTile->line == 0) |
610 | return; |
611 | |
612 | address = gDP.textureImage.address + gDP.loadTile->ult * gDP.textureImage.bpl + (gDP.loadTile->uls << gDP.textureImage.size >> 1); |
613 | dest = &TMEM[gDP.loadTile->tmem]; |
614 | bpl = (gDP.loadTile->lrs - gDP.loadTile->uls + 1) << gDP.loadTile->size >> 1; |
615 | height = gDP.loadTile->lrt - gDP.loadTile->ult + 1; |
616 | src = &RDRAM[address]; |
617 | |
618 | if (((address + height * bpl) > RDRAMSize) || |
619 | (((gDP.loadTile->tmem << 3) + bpl * height) > 4096)) // Stay within TMEM |
620 | { |
621 | #ifdef DEBUG |
622 | DebugMsg( DEBUG_HIGH | DEBUG_ERROR | DEBUG_TEXTURE, "// Attempting to load texture tile out of range\n" ); |
623 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadTile( %u, %i, %i, %i, %i );\n", |
624 | tile, gDP.loadTile->uls, gDP.loadTile->ult, gDP.loadTile->lrs, gDP.loadTile->lrt ); |
625 | #endif |
626 | return; |
627 | } |
628 | |
629 | // Line given for 32-bit is half what it seems it should since they split the |
630 | // high and low words. I'm cheating by putting them together. |
631 | if (gDP.loadTile->size == G_IM_SIZ_32b) |
632 | { |
633 | line = gDP.loadTile->line << 1; |
634 | Interleave = QWordInterleave; |
635 | } |
636 | else |
637 | { |
638 | line = gDP.loadTile->line; |
639 | Interleave = DWordInterleave; |
640 | } |
641 | |
642 | for (y = 0; y < height; y++) |
643 | { |
644 | UnswapCopy( src, dest, bpl ); |
645 | if (y & 1) Interleave( dest, line ); |
646 | |
647 | src += gDP.textureImage.bpl; |
648 | dest += line; |
649 | } |
650 | |
651 | gDP.textureMode = TEXTUREMODE_NORMAL; |
652 | gDP.loadType = LOADTYPE_TILE; |
653 | gDP.changed |= CHANGED_TMEM; |
654 | |
655 | #ifdef DEBUG |
656 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadTile( %u, %i, %i, %i, %i );\n", |
657 | tile, gDP.loadTile->uls, gDP.loadTile->ult, gDP.loadTile->lrs, gDP.loadTile->lrt ); |
658 | #endif |
659 | } |
660 | |
661 | void gDPLoadBlock( u32 tile, u32 uls, u32 ult, u32 lrs, u32 dxt ) |
662 | { |
663 | gDPSetTileSize( tile, uls, ult, lrs, dxt ); |
664 | gDP.loadTile = &gDP.tiles[tile]; |
665 | |
666 | u32 bytes = (lrs + 1) << gDP.loadTile->size >> 1; |
667 | u32 address = gDP.textureImage.address + ult * gDP.textureImage.bpl + (uls << gDP.textureImage.size >> 1); |
668 | |
669 | if ((bytes == 0) || |
670 | ((address + bytes) > RDRAMSize) || |
671 | (((gDP.loadTile->tmem << 3) + bytes) > 4096)) |
672 | { |
673 | #ifdef DEBUG |
674 | DebugMsg( DEBUG_HIGH | DEBUG_ERROR | DEBUG_TEXTURE, "// Attempting to load texture block out of range\n" ); |
675 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadBlock( %u, %u, %u, %u, %u );\n", |
676 | tile, uls, ult, lrs, dxt ); |
677 | #endif |
678 | // bytes = min( bytes, min( RDRAMSize - gDP.textureImage.address, 4096 - (gDP.loadTile->tmem << 3) ) ); |
679 | return; |
680 | } |
681 | |
682 | u64* src = (u64*)&RDRAM[address]; |
683 | u64* dest = &TMEM[gDP.loadTile->tmem]; |
684 | |
685 | if (dxt > 0) |
686 | { |
687 | u32 line = (2047 + dxt) / dxt; |
688 | u32 bpl = line << 3; |
689 | u32 height = bytes / bpl; |
690 | |
691 | if (gDP.loadTile->size == G_IM_SIZ_32b) |
692 | { |
693 | for (u32 y = 0; y < height; y++) |
694 | { |
695 | UnswapCopy( src, dest, bpl ); |
696 | if (y & 1) QWordInterleave( dest, line ); |
697 | src += line; |
698 | dest += line; |
699 | } |
700 | } |
701 | else |
702 | { |
703 | for (u32 y = 0; y < height; y++) |
704 | { |
705 | UnswapCopy( src, dest, bpl ); |
706 | if (y & 1) DWordInterleave( dest, line ); |
707 | src += line; |
708 | dest += line; |
709 | } |
710 | |
711 | } |
712 | |
713 | } |
714 | else |
715 | UnswapCopy( src, dest, bytes ); |
716 | |
717 | gDP.textureMode = TEXTUREMODE_NORMAL; |
718 | gDP.loadType = LOADTYPE_BLOCK; |
719 | gDP.changed |= CHANGED_TMEM; |
720 | |
721 | #ifdef DEBUG |
722 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadBlock( %u, %u, %u, %u, %u );\n", |
723 | tile, uls, ult, lrs, dxt ); |
724 | #endif |
725 | } |
726 | |
727 | void gDPLoadTLUT( u32 tile, u32 uls, u32 ult, u32 lrs, u32 lrt ) |
728 | { |
729 | gDPSetTileSize( tile, uls, ult, lrs, lrt ); |
730 | |
731 | u16 count = (gDP.tiles[tile].lrs - gDP.tiles[tile].uls + 1) * (gDP.tiles[tile].lrt - gDP.tiles[tile].ult + 1); |
732 | u32 address = gDP.textureImage.address + gDP.tiles[tile].ult * gDP.textureImage.bpl + (gDP.tiles[tile].uls << gDP.textureImage.size >> 1); |
733 | |
734 | u16 *dest = (u16*)&TMEM[gDP.tiles[tile].tmem]; |
735 | u16 *src = (u16*)&RDRAM[address]; |
736 | |
737 | u16 pal = (gDP.tiles[tile].tmem - 256) >> 4; |
738 | |
739 | int i = 0; |
740 | while (i < count) |
741 | { |
742 | for (u16 j = 0; (j < 16) && (i < count); j++, i++) |
743 | { |
744 | u16 color = swapword( src[i^1] ); |
745 | |
746 | *dest = color; |
747 | //dest[1] = color; |
748 | //dest[2] = color; |
749 | //dest[3] = color; |
750 | |
751 | dest += 4; |
752 | } |
753 | |
754 | gDP.paletteCRC16[pal] = CRC_CalculatePalette( 0xFFFFFFFF, &TMEM[256 + (pal << 4)], 16 ); |
755 | pal++; |
756 | } |
757 | |
758 | gDP.paletteCRC256 = CRC_Calculate( 0xFFFFFFFF, gDP.paletteCRC16, 64 ); |
759 | |
760 | gDP.changed |= CHANGED_TMEM; |
761 | |
762 | #ifdef DEBUG |
763 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadTLUT( %u, %i, %i, %i, %i );\n", |
764 | tile, gDP.tiles[tile].uls, gDP.tiles[tile].ult, gDP.tiles[tile].lrs, gDP.tiles[tile].lrt ); |
765 | #endif |
766 | } |
767 | |
768 | void gDPSetScissor( u32 mode, f32 ulx, f32 uly, f32 lrx, f32 lry ) |
769 | { |
770 | gDP.scissor.mode = mode; |
771 | gDP.scissor.ulx = ulx; |
772 | gDP.scissor.uly = uly; |
773 | gDP.scissor.lrx = lrx; |
774 | gDP.scissor.lry = lry; |
775 | gDP.changed |= CHANGED_SCISSOR; |
776 | |
777 | #ifdef DEBUG |
778 | DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPSetScissor( %s, %.2f, %.2f, %.2f, %.2f );\n", |
779 | ScissorModeText[gDP.scissor.mode], |
780 | gDP.scissor.ulx, |
781 | gDP.scissor.uly, |
782 | gDP.scissor.lrx, |
783 | gDP.scissor.lry ); |
784 | #endif |
785 | } |
786 | |
787 | void gDPFillRectangle( s32 ulx, s32 uly, s32 lrx, s32 lry ) |
788 | { |
789 | DepthBuffer *buffer = DepthBuffer_FindBuffer( gDP.colorImage.address ); |
790 | |
791 | if (buffer) |
792 | buffer->cleared = TRUE; |
793 | |
794 | if (gDP.depthImageAddress == gDP.colorImage.address) |
795 | { |
796 | OGL_ClearDepthBuffer(); |
797 | return; |
798 | } |
799 | |
800 | if (gDP.otherMode.cycleType == G_CYC_FILL) |
801 | { |
802 | lrx++; |
803 | lry++; |
804 | |
805 | if ((ulx == 0) && (uly == 0) && ((unsigned int)lrx == VI.width) && ((unsigned int)lry == VI.height)) |
806 | { |
807 | OGL_ClearColorBuffer( &gDP.fillColor.r ); |
808 | return; |
809 | } |
810 | } |
811 | |
812 | //shouldn't this be primitive color? |
813 | //OGL_DrawRect( ulx, uly, lrx, lry, (gDP.otherMode.cycleType == G_CYC_FILL) ? &gDP.fillColor.r : &gDP.blendColor.r ); |
814 | //OGL_DrawRect( ulx, uly, lrx, lry, (gDP.otherMode.cycleType == G_CYC_FILL) ? &gDP.fillColor.r : &gDP.primColor.r); |
815 | |
816 | float black[] = {0,0,0,0}; |
817 | OGL_DrawRect( ulx, uly, lrx, lry, (gDP.otherMode.cycleType == G_CYC_FILL) ? &gDP.fillColor.r : black); |
818 | |
819 | if (depthBuffer.current) depthBuffer.current->cleared = FALSE; |
820 | gDP.colorImage.changed = TRUE; |
821 | gDP.colorImage.height = max( gDP.colorImage.height, (unsigned int)lry ); |
822 | |
823 | #ifdef DEBUG |
824 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPFillRectangle( %i, %i, %i, %i );\n", |
825 | ulx, uly, lrx, lry ); |
826 | #endif |
827 | } |
828 | |
829 | void gDPSetConvert( s32 k0, s32 k1, s32 k2, s32 k3, s32 k4, s32 k5 ) |
830 | { |
831 | gDP.convert.k0 = k0 * 0.0039215689f; |
832 | gDP.convert.k1 = k1 * 0.0039215689f; |
833 | gDP.convert.k2 = k2 * 0.0039215689f; |
834 | gDP.convert.k3 = k3 * 0.0039215689f; |
835 | gDP.convert.k4 = k4 * 0.0039215689f; |
836 | gDP.convert.k5 = k5 * 0.0039215689f; |
837 | gDP.changed |= CHANGED_CONVERT; |
838 | } |
839 | |
840 | void gDPSetKeyR( u32 cR, u32 sR, u32 wR ) |
841 | { |
842 | gDP.key.center.r = cR * 0.0039215689f;; |
843 | gDP.key.scale.r = sR * 0.0039215689f;; |
844 | gDP.key.width.r = wR * 0.0039215689f;; |
845 | } |
846 | |
847 | void gDPSetKeyGB(u32 cG, u32 sG, u32 wG, u32 cB, u32 sB, u32 wB ) |
848 | { |
849 | gDP.key.center.g = cG * 0.0039215689f;; |
850 | gDP.key.scale.g = sG * 0.0039215689f;; |
851 | gDP.key.width.g = wG * 0.0039215689f;; |
852 | gDP.key.center.b = cB * 0.0039215689f;; |
853 | gDP.key.scale.b = sB * 0.0039215689f;; |
854 | gDP.key.width.b = wB * 0.0039215689f;; |
855 | } |
856 | |
857 | void gDPTextureRectangle( f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, f32 s, f32 t, f32 dsdx, f32 dtdy ) |
858 | { |
859 | if (gDP.colorImage.address == gDP.depthImageAddress) |
860 | { |
861 | return; |
862 | } |
863 | |
864 | if (gDP.otherMode.cycleType == G_CYC_COPY) |
865 | { |
866 | dsdx = 1.0f; |
867 | lrx += 1.0f; |
868 | lry += 1.0f; |
869 | } |
870 | |
871 | gSP.textureTile[0] = &gDP.tiles[tile]; |
872 | gSP.textureTile[1] = &gDP.tiles[(tile < 7) ? (tile + 1) : tile]; |
873 | |
874 | |
875 | f32 lrs; |
876 | f32 lrt; |
877 | if (RSP.cmd == G_TEXRECTFLIP) |
878 | { |
879 | lrs = s + (lry - uly - 1) * dtdy; |
880 | lrt = t + (lrx - ulx - 1) * dsdx; |
881 | } |
882 | else |
883 | { |
884 | lrs = s + (lrx - ulx - 1) * dsdx; |
885 | lrt = t + (lry - uly - 1) * dtdy; |
886 | } |
887 | |
888 | if (gDP.textureMode == TEXTUREMODE_NORMAL) |
889 | gDP.textureMode = TEXTUREMODE_TEXRECT; |
890 | |
891 | gDP.texRect.width = (unsigned int)(max( lrs, s ) + dsdx); |
892 | gDP.texRect.height = (unsigned int)(max( lrt, t ) + dtdy); |
893 | |
894 | float tmp; |
895 | if (lrs < s) |
896 | { |
897 | tmp = ulx; ulx = lrx; lrx = tmp; |
898 | tmp = s; s = lrs; lrs = tmp; |
899 | } |
900 | if (lrt < t) |
901 | { |
902 | tmp = uly; uly = lry; lry = tmp; |
903 | tmp = t; t = lrt; lrt = tmp; |
904 | } |
905 | |
906 | OGL_DrawTexturedRect( ulx, uly, lrx, lry, s, t, lrs, lrt, (RSP.cmd == G_TEXRECTFLIP)); |
907 | |
908 | gSP.textureTile[0] = &gDP.tiles[gSP.texture.tile]; |
909 | gSP.textureTile[1] = &gDP.tiles[(gSP.texture.tile < 7) ? (gSP.texture.tile + 1) : gSP.texture.tile]; |
910 | |
911 | if (depthBuffer.current) depthBuffer.current->cleared = FALSE; |
912 | gDP.colorImage.changed = TRUE; |
913 | gDP.colorImage.height = (unsigned int)(max( gDP.colorImage.height, gDP.scissor.lry )); |
914 | |
915 | #ifdef DEBUG |
916 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPTextureRectangle( %f, %f, %f, %f, %i, %f, %f, %f, %f );\n", |
917 | ulx, uly, lrx, lry, tile, s, t, dsdx, dtdy ); |
918 | #endif |
919 | } |
920 | |
921 | void gDPTextureRectangleFlip( f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, f32 s, f32 t, f32 dsdx, f32 dtdy ) |
922 | { |
923 | //gDPTextureRectangle( ulx, uly, lrx, lry, tile, s + (lrx - ulx) * dsdx, t + (lry - uly) * dtdy, -dsdx, -dtdy ); |
924 | |
925 | gDPTextureRectangle( ulx, uly, lrx, lry, tile, s, t, dsdx, dtdy ); |
926 | #ifdef DEBUG |
927 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPTextureRectangleFlip( %f, %f, %f, %f, %i, %f, %f, %f, %f);\n", |
928 | ulx, uly, lrx, lry, tile, s, t, dsdx, dtdy ); |
929 | #endif |
930 | } |
931 | |
932 | void gDPFullSync() |
933 | { |
934 | *REG.MI_INTR |= MI_INTR_DP; |
935 | |
936 | CheckInterrupts(); |
937 | |
938 | #ifdef DEBUG |
939 | DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPFullSync();\n" ); |
940 | #endif |
941 | } |
942 | |
943 | void gDPTileSync() |
944 | { |
945 | #ifdef DEBUG |
946 | DebugMsg( DEBUG_HIGH | DEBUG_IGNORED | DEBUG_TEXTURE, "gDPTileSync();\n" ); |
947 | #endif |
948 | } |
949 | |
950 | void gDPPipeSync() |
951 | { |
952 | #ifdef DEBUG |
953 | DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPPipeSync();\n" ); |
954 | #endif |
955 | } |
956 | |
957 | void gDPLoadSync() |
958 | { |
959 | #ifdef DEBUG |
960 | DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPLoadSync();\n" ); |
961 | #endif |
962 | } |
963 | |
964 | void gDPNoOp() |
965 | { |
966 | #ifdef DEBUG |
967 | DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPNoOp();\n" ); |
968 | #endif |
969 | } |
970 | |