GLES2N64 (from mupen64plus-ae) plugin. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / gles2n64 / src / gDP.cpp
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