GLES2N64 (from mupen64plus-ae) plugin. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / gles2n64 / src / gDP.cpp
CommitLineData
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:
20bool _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
119gDPInfo gDP;
120
121void 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
154void 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
170void 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
180void 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
191void 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
201void 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
211void 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
221void 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
231void 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
241void 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
251void 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
261void 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
271void 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
281void 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
292void 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
303void 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
324void 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
354void 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
440void 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
457void 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
475void 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
490void 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
504void 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
519void 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
536void 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
553void 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
574void 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
598void 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
661void 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
727void 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
768void 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
787void 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
829void 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
840void 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
847void 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
857void 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
921void 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
932void 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
943void gDPTileSync()
944{
945#ifdef DEBUG
946 DebugMsg( DEBUG_HIGH | DEBUG_IGNORED | DEBUG_TEXTURE, "gDPTileSync();\n" );
947#endif
948}
949
950void gDPPipeSync()
951{
952#ifdef DEBUG
953 DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPPipeSync();\n" );
954#endif
955}
956
957void gDPLoadSync()
958{
959#ifdef DEBUG
960 DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPLoadSync();\n" );
961#endif
962}
963
964void gDPNoOp()
965{
966#ifdef DEBUG
967 DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPNoOp();\n" );
968#endif
969}
970