Rice GLES2 (from mupen64plus-ae) plugin. Compile but doesn't works well on the OpenPa...
[mupen64plus-pandora.git] / source / gles2rice / src / RenderExt.cpp
1 /*
2 Copyright (C) 2002 Rice1964
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18 */
19
20 #include "osal_opengl.h"
21 #include "OGLDebug.h"
22 #include "FrameBuffer.h"
23 #include "Render.h"
24
25 extern uObjMtxReal gObjMtxReal;
26 extern Matrix g_MtxReal;
27
28 //========================================================================
29
30 void CRender::LoadFrameBuffer(bool useVIreg, uint32 left, uint32 top, uint32 width, uint32 height)
31 {
32     uint32 VIwidth = *g_GraphicsInfo.VI_WIDTH_REG;
33
34     TxtrInfo gti;
35
36     gti.clampS = gti.clampT = 0;
37     gti.maskS = gti.maskT = gti.mirrorS = gti.mirrorT = 0;
38     gti.TLutFmt = TLUT_FMT_RGBA16;  //RGBA16
39     gti.bSwapped    = FALSE;
40     gti.Palette = 0;
41
42     if( useVIreg && *g_GraphicsInfo.VI_ORIGIN_REG > VIwidth*2 )
43     {
44         gti.Format  = 0;
45         gti.Size    = 2;
46
47         gti.Address = (*g_GraphicsInfo.VI_ORIGIN_REG & (g_dwRamSize-1) ) - VIwidth*2;
48         gti.LeftToLoad  = 0;
49         gti.TopToLoad   = 0;
50
51         gti.PalAddress = (uchar *) &g_wRDPTlut[0];
52
53         gti.WidthToCreate   = windowSetting.uViWidth;;
54         gti.HeightToCreate  = windowSetting.uViHeight;
55
56         if( gti.WidthToCreate == 0 || gti.HeightToCreate == 0 )
57         {
58             TRACE0("Loading frame buffer: size = 0 x 0");
59             return;
60         }
61
62         gti.Pitch   = VIwidth << gti.Size >> 1;
63     }
64     else
65     {
66         gti.Format  = g_CI.dwFormat;
67         gti.Size    = g_CI.dwSize;
68         gti.PalAddress = (uchar *) &g_wRDPTlut[0];
69
70         gti.Address = RSPSegmentAddr(g_CI.dwAddr);
71
72         if( width == 0 || height == 0 )
73         {
74             gti.LeftToLoad      = 0;
75             gti.TopToLoad       = 0;
76
77             gti.WidthToCreate       = g_CI.dwWidth;
78             gti.HeightToCreate      = g_CI.dwWidth*3/4;
79         }
80         else
81         {
82             gti.LeftToLoad      = left;
83             gti.TopToLoad       = top;
84
85             gti.WidthToCreate   = width;
86             gti.HeightToCreate  = height;
87         }
88
89         if( gti.Size == TXT_SIZE_4b )
90         {
91             gti.Pitch = g_CI.dwWidth >> 1;
92         }
93         else
94         {
95             gti.Pitch = g_CI.dwWidth << (gti.Size-1);
96         }
97     }
98
99
100     if( gti.Address + gti.Pitch*gti.HeightToCreate > g_dwRamSize )
101     {
102         TRACE0("Skip frame buffer loading, memory out of bound");
103         return;
104     }
105
106 #ifdef DEBUGGER
107     if( pauseAtNext )
108     {
109         DebuggerAppendMsg("Load Frame Buffer Imag at: %08X, (%d, %d) - (%d, %d)", gti.Address,
110             gti.LeftToLoad, gti.TopToLoad, gti.WidthToCreate, gti.HeightToCreate );
111     }
112 #endif
113
114
115     gti.HeightToLoad = gti.HeightToCreate;
116     gti.WidthToLoad = gti.WidthToCreate;
117
118     gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address;
119     gti.tileNo = -1;
120     TxtrCacheEntry *pEntry = gTextureManager.GetTexture(&gti, false, true, false);
121     if( pEntry ) SetCurrentTexture( 0, pEntry->pTexture, pEntry->ti.WidthToCreate, pEntry->ti.HeightToCreate, pEntry);
122 }
123
124 void CRender::LoadTextureFromMemory(void *buf, uint32 left, uint32 top, uint32 width, uint32 height, uint32 pitch, uint32 format)
125 {
126     TxtrInfo gti;
127     gti.Format  = g_CI.dwFormat;
128     gti.Size    = g_CI.dwSize;
129     gti.Palette = 0;
130     gti.TLutFmt = TLUT_FMT_RGBA16;  //RGBA16
131     gti.PalAddress = 0;
132     gti.bSwapped = FALSE;
133     gti.Address = 0;
134     gti.LeftToLoad = 0;
135     gti.TopToLoad = 0;
136     gti.WidthToCreate = width;
137     gti.HeightToCreate = height;
138
139     gti.Pitch   = pitch;
140
141     gti.HeightToLoad = height;
142     gti.WidthToLoad = width;
143     gti.pPhysicalAddress = (uint8*)buf;
144
145     gti.tileNo = -1;
146     TxtrCacheEntry *pEntry = gTextureManager.GetTexture(&gti, false);
147     //Upto here, the texture is loaded wrong because the format is wrong
148
149     DrawInfo info;  
150     if( pEntry->pTexture->StartUpdate(&info) )
151     {
152         for( uint32 i=0; i<height; i++)
153         {
154             uint32 *psrc = (uint32*)((uint8*)buf+pitch*(i+top))+left;
155             uint32 *pdst = (uint32*)((uint8*)info.lpSurface+i*info.lPitch);
156             for( uint32 j=0; j<width; j++)
157             {
158                 pdst[j]=psrc[j];
159             }
160         }
161         pEntry->pTexture->EndUpdate(&info);
162     }
163     SetCurrentTexture( 0, pEntry->pTexture, width, height, pEntry);
164 }
165
166 void CRender::LoadObjBGCopy(uObjBg &info)
167 {
168     TxtrInfo gti;
169     gti.Format      = info.imageFmt;
170     gti.Size        = info.imageSiz;
171     gti.Address     = RSPSegmentAddr(info.imagePtr);
172     gti.LeftToLoad  = 0;
173     gti.TopToLoad   = 0;
174     gti.Palette     = info.imagePal;
175
176     gti.PalAddress  = (uchar *) &g_wRDPTlut[0];
177     gti.bSwapped    = FALSE;
178     gti.TLutFmt     = TLUT_FMT_RGBA16;  //RGBA16
179
180     gti.WidthToCreate   = info.imageW/4;
181     gti.HeightToCreate  = info.imageH/4;
182
183     if( options.bEnableHacks )
184     {
185         if( g_CI.dwWidth == 0x200 && gti.Format == g_CI.dwFormat && gti.Size == g_CI.dwSize &&
186             gti.WidthToCreate == 0x200 )
187         {
188             // Hack for RE2
189             uint32 w = *g_GraphicsInfo.VI_WIDTH_REG & 0xFFF;
190             gti.HeightToCreate = (gti.WidthToCreate*gti.HeightToCreate)/w;
191             gti.WidthToCreate = w;
192         }
193     }
194
195     gti.Pitch   = gti.WidthToCreate << gti.Size >> 1;
196     gti.Pitch   = (gti.Pitch>>3)<<3;    // Align to 8 bytes
197
198     if( gti.Address + gti.Pitch*gti.HeightToCreate > g_dwRamSize )
199     {
200         TRACE0("Skip BG copy loading, memory out of bound");
201         return;
202     }
203
204     gti.HeightToLoad = gti.HeightToCreate;
205     gti.WidthToLoad = gti.WidthToCreate;
206     gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address;
207     gti.tileNo = -1;
208     TxtrCacheEntry *pEntry = gTextureManager.GetTexture(&gti, false);
209     SetCurrentTexture(0,pEntry);
210
211     DEBUGGER_IF_DUMP((pauseAtNext && (eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI||eventToPause == NEXT_OBJ_BG)),
212     {
213         TRACE0("Load Obj BG Copy:\n");
214         DebuggerAppendMsg("Addr=0x%08X, W=%d, H=%d, Left=%d, Top=%d\n", 
215             gti.Address, gti.WidthToCreate, gti.HeightToCreate, gti.LeftToLoad, gti.TopToLoad);
216         DebuggerAppendMsg("Fmt=%s-%db, Pal=%d\n",
217             pszImgFormat[gti.Format], pnImgSize[gti.Size], gti.Palette);
218     }
219     );
220 }
221
222 void CRender::LoadTxtrBufIntoTexture(void)
223 {
224     TxtrInfo gti;
225
226     gti.Format  = g_pRenderTextureInfo->CI_Info.dwFormat;
227     gti.Size    = g_pRenderTextureInfo->CI_Info.dwSize;
228
229     gti.Address = RSPSegmentAddr(g_pRenderTextureInfo->CI_Info.dwAddr);
230     gti.LeftToLoad      = 0;
231     gti.TopToLoad       = 0;
232     gti.Palette = 0;
233
234     gti.PalAddress = (uchar *) &g_wRDPTlut[0];
235     gti.bSwapped    = FALSE;
236
237     gti.WidthToCreate       = g_pRenderTextureInfo->N64Width;
238     gti.HeightToCreate      = g_pRenderTextureInfo->N64Height;
239     gti.TLutFmt = TLUT_FMT_RGBA16;  //RGBA16
240
241     gti.Pitch   = gti.WidthToCreate << (gti.Size-1);
242
243     gti.HeightToLoad = gti.HeightToCreate;
244     gti.WidthToLoad = gti.WidthToCreate;
245     gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address;
246     gti.tileNo = -1;
247     TxtrCacheEntry *pEntry = gTextureManager.GetTexture(&gti, false);
248     SetCurrentTexture(0,pEntry);
249 }
250
251 void CRender::LoadSprite2D(Sprite2DInfo &info, uint32 ucode)
252 {
253     TxtrInfo gti;
254
255     gti.Format  = info.spritePtr->SourceImageType;
256     gti.Size    = info.spritePtr->SourceImageBitSize;
257
258     gti.Address = RSPSegmentAddr(info.spritePtr->SourceImagePointer);
259     gti.Palette = 0;
260     gti.PalAddress = (uchar *) (g_pRDRAMu8 + RSPSegmentAddr(info.spritePtr->TlutPointer));
261
262     if( options.enableHackForGames == HACK_FOR_NITRO )
263     {
264         gti.WidthToCreate   = (uint32)(info.spritePtr->SubImageWidth/info.scaleX);
265         gti.HeightToCreate  = (uint32)(info.spritePtr->SubImageHeight/info.scaleY);
266         gti.LeftToLoad      = (uint32)(info.spritePtr->SourceImageOffsetS/info.scaleX);
267         gti.TopToLoad       = (uint32)(info.spritePtr->SourceImageOffsetT/info.scaleY);
268         gti.Pitch   = info.spritePtr->Stride << gti.Size >> 1;
269         gti.Pitch   = (uint32)(gti.Pitch*info.scaleY);
270     }
271     else
272     {
273         gti.WidthToCreate   = info.spritePtr->SubImageWidth;
274         gti.HeightToCreate  = info.spritePtr->SubImageHeight;
275         gti.LeftToLoad      = info.spritePtr->SourceImageOffsetS;
276         gti.TopToLoad       = info.spritePtr->SourceImageOffsetT;
277         gti.Pitch   = info.spritePtr->Stride << gti.Size >> 1;
278     }
279
280     if( gti.Address + gti.Pitch*gti.HeightToCreate > g_dwRamSize )
281     {
282         TRACE0("Skip Sprite image decompress, memory out of bound");
283         return;
284     }
285
286     gti.HeightToLoad = gti.HeightToCreate;
287     gti.WidthToLoad = gti.WidthToCreate;
288
289     gti.TLutFmt     = TLUT_FMT_RGBA16;  //RGBA16
290     gti.bSwapped    = FALSE;
291
292     gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address;
293     gti.tileNo = -1;
294     TxtrCacheEntry *pEntry = gTextureManager.GetTexture(&gti, false);
295     SetCurrentTexture(0,pEntry);
296
297     DEBUGGER_IF_DUMP((pauseAtNext && (eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI||eventToPause == NEXT_SPRITE_2D)),
298     {
299         TRACE0("Load Sprite 2D\n");
300         DebuggerAppendMsg("Addr=0x%08X, W=%d, H=%d, Left=%d, Top=%d\n", 
301             gti.Address, gti.WidthToCreate, gti.HeightToCreate, gti.LeftToLoad, gti.TopToLoad);
302         DebuggerAppendMsg("Fmt=%s-%db, Pal=%d, Pitch=%d\n",
303             pszImgFormat[gti.Format], pnImgSize[gti.Size], gti.Palette, gti.Pitch);
304     }
305     );
306 }
307
308
309 void CRender::DrawSprite2D(Sprite2DInfo &info, uint32 ucode)
310 {
311     if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer();
312
313     if( status.bHandleN64RenderTexture )
314     {
315         g_pRenderTextureInfo->maxUsedHeight = g_pRenderTextureInfo->N64Height;
316         if( !status.bDirectWriteIntoRDRAM ) 
317         {
318             status.bFrameBufferIsDrawn = true;
319             status.bFrameBufferDrawnByTriangles = true;
320         }
321     }
322     LoadSprite2D(info, ucode);
323
324     info.scaleX = 1/info.scaleX;
325     info.scaleY = 1/info.scaleY;
326
327     int x0, y0, x1, y1;
328     float t0, s0, t1, s1;
329
330     if( info.flipX )
331     {
332         //x0 = info.px*info.scaleX + info.spritePtr->SubImageWidth*info.scaleX;
333         //x1 = info.px*info.scaleX;
334         x0 = info.px + int(info.spritePtr->SubImageWidth*info.scaleX);
335         x1 = info.px;
336     }
337     else
338     {
339         //x0 = info.px*info.scaleX;
340         //x1 = info.px*info.scaleX + info.spritePtr->SubImageWidth*info.scaleX;
341         x0 = info.px;
342         x1 = info.px + int(info.spritePtr->SubImageWidth*info.scaleX);
343     }
344
345     if( info.flipY )
346     {
347         //y0 = info.py*info.scaleY + info.spritePtr->SubImageHeight*info.scaleY;
348         //y1 = info.py*info.scaleY;
349         y0 = info.py + int(info.spritePtr->SubImageHeight*info.scaleY);
350         y1 = info.py;
351     }
352     else
353     {
354         //y0 = info.py*info.scaleY;
355         //y1 = info.py*info.scaleY + info.spritePtr->SubImageHeight*info.scaleY;
356         y0 = info.py;
357         y1 = info.py + int(info.spritePtr->SubImageHeight*info.scaleY);
358     }
359
360     t0 = s0 = 0;
361     if( options.enableHackForGames == HACK_FOR_NITRO )
362     {
363         t1 = info.spritePtr->SubImageWidth*info.scaleX/g_textures[0].m_fTexWidth;
364         s1 = info.spritePtr->SubImageHeight*info.scaleY/g_textures[0].m_fTexHeight;
365     }
366     else
367     {
368         t1 = info.spritePtr->SubImageWidth/g_textures[0].m_fTexWidth;
369         s1 = info.spritePtr->SubImageHeight/g_textures[0].m_fTexHeight;
370     }
371
372     //InitCombinerBlenderForSimpleTextureDraw();
373     SetCombinerAndBlender();
374     SetAddressUAllStages( 0, TEXTURE_UV_FLAG_CLAMP );
375     SetAddressVAllStages( 0, TEXTURE_UV_FLAG_CLAMP );
376
377     COLOR speColor = PostProcessSpecularColor();
378     COLOR difColor = PostProcessDiffuseColor(0xffffffff);
379
380     float depth = ( gRDP.otherMode.depth_source == 1 ) ? gRDP.fPrimitiveDepth : 0;
381     DrawSimple2DTexture((float)x0, (float)y0, (float)x1, (float)y1, t0, s0, t1, s1, speColor, difColor, depth, 1.0f);
382 }
383
384
385 void CRender::DrawSpriteR(uObjTxSprite &sprite, bool initCombiner, uint32 tile, uint32 left, uint32 top, uint32 width, uint32 height)   // With Rotation
386 {
387     if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer();
388
389     if( status.bHandleN64RenderTexture )
390     {
391         g_pRenderTextureInfo->maxUsedHeight = g_pRenderTextureInfo->N64Height;
392         if( !status.bDirectWriteIntoRDRAM ) 
393         {
394             status.bFrameBufferIsDrawn = true;
395             status.bFrameBufferDrawnByTriangles = true;
396         }
397     }
398     SetCombinerAndBlender();
399
400     float scaleX = sprite.sprite.scaleW/1024.0f;
401     float scaleY = sprite.sprite.scaleH/1024.0f;
402
403     if( width == 0 || height == 0 )
404     {
405         width = g_textures[tile].m_dwTileWidth;
406         height = g_textures[tile].m_dwTileHeight;
407     }
408
409     //RECT src = {left,top,width, height};
410     float depth = 0.0;
411     if (gRDP.otherMode.depth_source==1) 
412         depth = gRDP.fPrimitiveDepth;
413
414     float x0 = sprite.sprite.objX/4.0f;
415     float y0 = sprite.sprite.objY/4.0f;
416     float x1 = sprite.sprite.imageW / 32.0f / scaleX + x0;
417     float y1 = sprite.sprite.imageH / 32.0f / scaleY + y0;
418
419     if( sprite.sprite.imageFlags&1 ) { float temp = x0; x0 = x1; x1 = temp; } // flip X 
420     if( sprite.sprite.imageFlags&0x10 ) { float temp = y0; y0 = y1; y1 = temp; } // flip Y
421
422     g_texRectTVtx[0].x = (gObjMtxReal.A*x0 + gObjMtxReal.B*y0 + gObjMtxReal.X)*windowSetting.fMultX;
423     g_texRectTVtx[0].y = (gObjMtxReal.C*x0 + gObjMtxReal.D*y0 + gObjMtxReal.Y)*windowSetting.fMultY;
424     g_texRectTVtx[0].z = depth;
425     g_texRectTVtx[0].rhw = 1;
426     g_texRectTVtx[1].x = (gObjMtxReal.A*x1 + gObjMtxReal.B*y0 + gObjMtxReal.X)*windowSetting.fMultX;
427     g_texRectTVtx[1].y = (gObjMtxReal.C*x1 + gObjMtxReal.D*y0 + gObjMtxReal.Y)*windowSetting.fMultY;
428     g_texRectTVtx[1].z = depth;
429     g_texRectTVtx[1].rhw = 1;
430     g_texRectTVtx[2].x = (gObjMtxReal.A*x1 + gObjMtxReal.B*y1 + gObjMtxReal.X)*windowSetting.fMultX;
431     g_texRectTVtx[2].y = (gObjMtxReal.C*x1 + gObjMtxReal.D*y1 + gObjMtxReal.Y)*windowSetting.fMultY;
432     g_texRectTVtx[2].z = depth;
433     g_texRectTVtx[2].rhw = 1;
434     g_texRectTVtx[3].x = (gObjMtxReal.A*x0 + gObjMtxReal.B*y1 + gObjMtxReal.X)*windowSetting.fMultX;
435     g_texRectTVtx[3].y = (gObjMtxReal.C*x0 + gObjMtxReal.D*y1 + gObjMtxReal.Y)*windowSetting.fMultY;
436     g_texRectTVtx[3].z = depth;
437     g_texRectTVtx[3].rhw = 1;
438
439     g_texRectTVtx[0].tcord[0].u = left/g_textures[tile].m_fTexWidth;
440     g_texRectTVtx[0].tcord[0].v = top/g_textures[tile].m_fTexHeight;
441     g_texRectTVtx[1].tcord[0].u = (left+width)/g_textures[tile].m_fTexWidth;
442     g_texRectTVtx[1].tcord[0].v = top/g_textures[tile].m_fTexHeight;
443     g_texRectTVtx[2].tcord[0].u = (left+width)/g_textures[tile].m_fTexWidth;
444     g_texRectTVtx[2].tcord[0].v = (top+height)/g_textures[tile].m_fTexHeight;
445     g_texRectTVtx[3].tcord[0].u = left/g_textures[tile].m_fTexWidth;
446     g_texRectTVtx[3].tcord[0].v = (top+height)/g_textures[tile].m_fTexHeight;
447
448     //COLOR speColor = PostProcessSpecularColor();
449     COLOR difColor = PostProcessDiffuseColor(0xffffffff);
450
451     g_texRectTVtx[0].dcDiffuse = g_texRectTVtx[1].dcDiffuse 
452         = g_texRectTVtx[2].dcDiffuse = g_texRectTVtx[3].dcDiffuse = difColor;
453     g_texRectTVtx[0].dcSpecular = g_texRectTVtx[1].dcSpecular 
454         = g_texRectTVtx[2].dcSpecular = g_texRectTVtx[3].dcSpecular = difColor;
455
456     DrawSpriteR_Render();
457 }
458
459 void CRender::DrawFrameBuffer(bool useVIreg, uint32 left, uint32 top, uint32 width, uint32 height)
460 {
461     BeginRendering();
462
463     LoadFrameBuffer(useVIreg, left, top, width, height);
464
465     m_pColorCombiner->InitCombinerBlenderForSimpleTextureDraw(0);
466
467     ZBufferEnable(FALSE);
468     SetZUpdate(FALSE);
469     if( left == 0 )
470         SetAlphaTestEnable(FALSE);
471     else
472         SetAlphaTestEnable(TRUE);   // use Alpha Test for partial frame buffer draw, for Dr. Mario 64
473
474     m_pAlphaBlender->Disable();
475
476     CTexture *pTexture = g_textures[0].m_pCTexture;
477     if( pTexture )
478     {
479         if( useVIreg )
480         {
481             // Draw the whole frame buffer
482             DrawSimple2DTexture(0, 0, windowSetting.uViWidth, windowSetting.uViHeight, 
483                 0, 0, 1/pTexture->m_fXScale, 1/pTexture->m_fYScale, 0xFFFFFFFF, 0xFFFFFFFF, 0, 1);
484         }
485         else
486         {
487             // Draw a small texture in frame buffer
488             DrawSimple2DTexture((float)left, (float)top, (float)(left+width), (float)(top+height), 
489                 0, 0, 1/pTexture->m_fXScale, 1/pTexture->m_fYScale, 0xFFFFFFFF, 0xFFFFFFFF, 0, 1);
490         }
491     }
492
493     TXTRBUF_OR_CI_DUMP(TRACE0("Draw Frame Buffer Img"));
494 #ifdef DEBUGGER
495     if( pauseAtNext && ( eventToPause == NEXT_FRAME || eventToPause == NEXT_FLUSH_TRI ) )
496     {
497         TRACE0("Draw Frame Buffer Img");
498         debuggerPause = true;
499         DebuggerPause();
500     }
501 #endif
502
503     EndRendering();
504 }
505
506 void CRender::DrawObjBGCopy(uObjBg &info)
507 {
508     if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer();
509
510     if( status.bHandleN64RenderTexture )
511     {
512         g_pRenderTextureInfo->maxUsedHeight = g_pRenderTextureInfo->N64Height;
513         if( !status.bDirectWriteIntoRDRAM ) 
514         {
515             status.bFrameBufferIsDrawn = true;
516             status.bFrameBufferDrawnByTriangles = true;
517         }
518     }
519     SetCombinerAndBlender();
520
521     uint32 frameH = info.frameH;
522     uint32 frameW = info.frameW;
523     uint32 imageH = info.imageH;
524     uint32 imageW = info.imageW;
525
526     if( options.bEnableHacks )
527     {
528         if( g_CI.dwWidth == 0x200 && info.imageFmt == g_CI.dwFormat && info.imageSiz == g_CI.dwSize &&
529             frameW == 0x800 )
530         {
531             // Hack for RE2
532             uint32 width = *g_GraphicsInfo.VI_WIDTH_REG & 0xFFF;
533             imageH = frameH = (frameW/4*frameH/4)/width*4;
534             imageW = frameW = width*4;
535         }
536     }
537
538     float x0 = info.frameX / 4.0f;
539     float y0 = info.frameY / 4.0f;
540     float x1 = frameW / 4.0f + x0;
541     float y1 = frameH / 4.0f + y0;
542
543     float s0 = info.imageX / 32.0f;
544     float t0 = info.imageY / 32.0f;
545
546     float texwidth = imageW/4.0f;
547     float texheight = imageH/4.0f;
548
549     float u0 = s0/g_textures[0].m_fTexWidth;
550     float v0 = t0/g_textures[0].m_fTexHeight;
551     float maxu = texwidth/g_textures[0].m_fTexWidth;
552     float maxv = texheight/g_textures[0].m_fTexHeight;
553
554     float x2 = x0 + (texwidth-s0);
555     float y2 = y0 + (texheight-t0);
556     float u1 = (x1-x2)/g_textures[0].m_fTexWidth;
557     float v1 = (y1-y2)/g_textures[0].m_fTexHeight;
558
559     float depth = (gRDP.otherMode.depth_source == 1 ? gRDP.fPrimitiveDepth : 0.0f);
560
561     COLOR speColor = PostProcessSpecularColor();
562     COLOR difColor = PostProcessDiffuseColor(0xffffffff);
563
564     if( options.enableHackForGames == HACK_FOR_COMMANDCONQUER )
565     {
566         float s1 = (x1-x0) + s0;
567         float t1 = (y1-y0) + t0;
568         DrawSimple2DTexture(x0, y0, x1, y1, u0, v0, 
569             s1/g_textures[0].m_fTexWidth, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1);
570     }
571     else if( x2 >= x1 )
572     {
573         float s1 = (x1-x0) + s0;
574         if( y2 >= y1 )
575         {
576             float t1 = (y1-y0) + t0;
577             DrawSimple2DTexture(x0, y0, x1, y1, u0, v0, 
578                 s1/g_textures[0].m_fTexWidth, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1);
579         }
580         else
581         {
582             DrawSimple2DTexture(x0, y0, x1, y2, u0, v0, 
583                 s1/g_textures[0].m_fTexWidth, maxv, difColor, speColor, depth, 1);
584             DrawSimple2DTexture(x0, y2, x1, y1, u0, 0, 
585                 s1/g_textures[0].m_fTexWidth, v1, difColor, speColor, depth, 1);
586         }
587     }
588     else
589     {
590         if( y2 >= y1 )
591         {
592             float t1 = (y1-y0) + t0;
593             DrawSimple2DTexture(x0, y0, x2, y1, u0, v0, 
594                 maxu, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1);
595             DrawSimple2DTexture(x2, y0, x1, y1, 0, v0, 
596                 u1, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1);
597         }
598         else
599         {
600             DrawSimple2DTexture(x0, y0, x2, y2, u0, v0, maxu, maxv, difColor, speColor, depth, 1);
601             DrawSimple2DTexture(x2, y0, x1, y2, 0, v0, u1, maxv, difColor, speColor, depth, 1);
602             DrawSimple2DTexture(x0, y2, x2, y1, u0, 0, maxu, v1, difColor, speColor, depth, 1);
603             DrawSimple2DTexture(x2, y2, x1, y1, 0, 0, u1, v1, difColor, speColor, depth, 1);
604         }
605     }
606
607     DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N(
608         (pauseAtNext&&(eventToPause==NEXT_OBJ_BG||eventToPause==NEXT_FLUSH_TRI||eventToPause==NEXT_OBJ_TXT_CMD)),
609         {
610             TRACE0("Pause ObjBG Copy");
611         }
612     );
613 }
614
615 void CRender::DrawObjBG1CYC(uObjScaleBg &bg, bool scaled)   //Without Ratation
616 {
617     if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer();
618
619     if( g_curRomInfo.bDisableObjBG )
620         return;
621
622     if( status.bHandleN64RenderTexture )
623     {
624         g_pRenderTextureInfo->maxUsedHeight = g_pRenderTextureInfo->N64Height;
625         if( !status.bDirectWriteIntoRDRAM ) 
626         {
627             status.bFrameBufferIsDrawn = true;
628             status.bFrameBufferDrawnByTriangles = true;
629         }
630     }
631
632     SetCombinerAndBlender();
633
634     float depth = (gRDP.otherMode.depth_source == 1 ? gRDP.fPrimitiveDepth : 0.0f);
635
636     float x0 = bg.frameX / 4.0f;
637     float y0 = bg.frameY / 4.0f;
638     float x1 = bg.frameW / 4.0f + x0;
639     float y1 = bg.frameH / 4.0f + y0;
640
641     float s0 = bg.imageX / 32.0f;
642     float t0 = bg.imageY / 32.0f;
643
644     float scaleX = bg.scaleW/1024.0f;
645     float scaleY = bg.scaleH/1024.0f;
646
647     float texwidth = bg.imageW/4.0f;
648     float texheight = bg.imageH/4.0f;
649
650     float u0 = s0/g_textures[0].m_fTexWidth;
651     float v0 = t0/g_textures[0].m_fTexHeight;
652     float maxu = texwidth/g_textures[0].m_fTexWidth;
653     float maxv = texheight/g_textures[0].m_fTexHeight;
654
655     float x2 = x0 + (texwidth-s0)/scaleX;
656     float y2 = y0 + (texheight-t0)/scaleY;
657     float u1 = (x1-x2)*scaleX/g_textures[0].m_fTexWidth;
658     float v1 = (y1-y2)*scaleY/g_textures[0].m_fTexHeight;
659
660     COLOR speColor = PostProcessSpecularColor();
661     COLOR difColor = PostProcessDiffuseColor(0xffffffff);
662
663     SetAlphaTestEnable(FALSE);
664
665     if( options.enableHackForGames != HACK_FOR_YOSHI )
666     {
667         float s1 = (x1-x0)*scaleX + s0;
668         float t1 = (y1-y0)*scaleY + t0;
669         DrawSimple2DTexture(x0, y0, x1, y1, u0, v0, 
670             s1/g_textures[0].m_fTexWidth, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1);
671     }
672     else if( x2 >= x1 )
673     {
674         float s1 = (x1-x0)*scaleX + s0;
675         if( y2 >= y1 )
676         {
677             float t1 = (y1-y0)*scaleY + t0;
678             DrawSimple2DTexture(x0, y0, x1, y1, u0, v0, 
679                 s1/g_textures[0].m_fTexWidth, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1);
680         }
681         else
682         {
683             DrawSimple2DTexture(x0, y0, x1, y2, u0, v0, 
684                 s1/g_textures[0].m_fTexWidth, maxv, difColor, speColor, depth, 1);
685             DrawSimple2DTexture(x0, y2, x1, y1, u0, 0, 
686                 s1/g_textures[0].m_fTexWidth, v1, difColor, speColor, depth, 1);
687         }
688     }
689     else
690     {
691         if( y2 >= y1 )
692         {
693             float t1 = (y1-y0)*scaleY + t0;
694             DrawSimple2DTexture(x0, y0, x2, y1, u0, v0, 
695                 maxu, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1);
696             DrawSimple2DTexture(x2, y0, x1, y1, 0, v0, 
697                 u1, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1);
698         }
699         else
700         {
701             DrawSimple2DTexture(x0, y0, x2, y2, u0, v0, maxu, maxv, difColor, speColor, depth, 1);
702             DrawSimple2DTexture(x2, y0, x1, y2, 0, v0, u1, maxv, difColor, speColor, depth, 1);
703             DrawSimple2DTexture(x0, y2, x2, y1, u0, 0, maxu, v1, difColor, speColor, depth, 1);
704             DrawSimple2DTexture(x2, y2, x1, y1, 0, 0, u1, v1, difColor, speColor, depth, 1);
705         }
706     }
707
708     DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N(
709         (pauseAtNext&&(eventToPause==NEXT_OBJ_BG||eventToPause==NEXT_FLUSH_TRI||eventToPause==NEXT_OBJ_TXT_CMD)),
710         {
711             DebuggerAppendMsg("Pause BG 1CYC: (%.0f,%.0f - %.0f,%.0f), \ntex (%.2f,%.2f), scale (%.2f,%.2f)",x0,y0,x1,y1,s0,t0,scaleX,scaleY);
712         }
713     );
714 }
715
716
717 void CRender::DrawSprite(uObjTxSprite &sprite, bool rectR)  //Without Ratation
718 {
719     if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer();
720
721     if( status.bHandleN64RenderTexture )
722     {
723         g_pRenderTextureInfo->maxUsedHeight = g_pRenderTextureInfo->N64Height;
724         if( !status.bDirectWriteIntoRDRAM ) 
725         {
726             status.bFrameBufferIsDrawn = true;
727             status.bFrameBufferDrawnByTriangles = true;
728         }
729     }
730     SetCombinerAndBlender();
731     COLOR speColor = PostProcessSpecularColor();
732     COLOR difColor = PostProcessDiffuseColor(0xffffffff);
733
734
735     float objX = sprite.sprite.objX/4.0f;
736     float objY = sprite.sprite.objY/4.0f;
737     float width = sprite.sprite.imageW / 32.0f;
738     float high = sprite.sprite.imageH / 32.0f;
739     float scaleW = sprite.sprite.scaleW/1024.0f;
740     float scaleH = sprite.sprite.scaleH/1024.0f;
741
742     if( g_curRomInfo.bIncTexRectEdge )
743     {
744         width++;
745         high++;
746     }
747
748     float x0, y0, x1, y1;
749     if( rectR )
750     {
751         // Upper-left coordinate
752         // ( X + objX / BaseScaleX, Y+objY/BaseScaleY )
753         // Lower-right coordinate
754         // ( X + (objX + imageW / scaleW) / BaseScaleX - 1, Y + (objY + imageH / scaleH) / BaseScaleY - 1 )
755
756         x0 = gObjMtxReal.X + objX/gObjMtxReal.BaseScaleX;
757         y0 = gObjMtxReal.Y + objY/gObjMtxReal.BaseScaleY;
758         x1 = gObjMtxReal.X + (objX + width / scaleW) / gObjMtxReal.BaseScaleX;
759         y1 = gObjMtxReal.Y + (objY + high / scaleH) / gObjMtxReal.BaseScaleY;
760     }
761     else
762     {
763         // (objX, objY) - ( objX+imageW/scaleW-1, objY+imageH/scaleH-1)
764         x0 = objX;
765         y0 = objY;
766         x1 = objX + width / scaleW;
767         y1 = objY + high / scaleH;
768
769         if( (sprite.sprite.imageFlags&1) ) // flipX
770         {
771             float temp = x0;
772             x0 = x1;
773             x1 = temp;
774         }
775
776         if( (sprite.sprite.imageFlags&0x10) ) // flipY
777         {
778             float temp = y0;
779             y0 = y1;
780             y1 = temp;
781         }
782     }
783
784     // save the current clamp type
785     GLint iClampS, iClampT;
786     glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, &iClampS);
787     OPENGL_CHECK_ERRORS;
788     glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, &iClampT);
789     OPENGL_CHECK_ERRORS;
790     // force clamp type to CLAMP_EDGE (experiments show sometimes this is set to hex 0x2901 - invalid value)
791     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
792     OPENGL_CHECK_ERRORS;
793     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
794     OPENGL_CHECK_ERRORS;
795     // draw the 2D sprite as 2 triangles
796     float depth = (gRDP.otherMode.depth_source == 1 ? gRDP.fPrimitiveDepth : 0.0f);
797     CTexture *pTexture = g_textures[0].m_pCTexture;
798     DrawSimple2DTexture(x0, y0, x1, y1, 0, 0, 1/pTexture->m_fXScale, 1/pTexture->m_fYScale, 
799         difColor, speColor, depth, 1);
800     // return clamp type to original setting
801     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampS);
802     OPENGL_CHECK_ERRORS;
803     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampT);
804     OPENGL_CHECK_ERRORS;
805 }
806
807
808 void CRender::LoadObjBG1CYC(uObjScaleBg &bg)
809 {
810     uint32 imageWidth = bg.imageW/4;
811     uint32 imageHeight = bg.imageH/4;
812
813     TxtrInfo gti;
814     gti.Format  = bg.imageFmt;
815     gti.Size        = bg.imageSiz;
816
817     //uint8* img = (uint8*)(g_pRDRAMu8+RSPSegmentAddr(bg.imagePtr));
818     
819     uchar *palAddr = (uchar *) &g_wRDPTlut[0];
820     gti.Address = RSPSegmentAddr(bg.imagePtr);
821
822     gti.LeftToLoad      = 0;
823     gti.TopToLoad       = 0;
824
825     gti.WidthToCreate       = imageWidth;
826     gti.HeightToCreate      = imageHeight;
827
828     gti.clampS = gti.clampT = 1;
829     gti.maskS = gti.maskT = 0;
830
831     gti.Palette     = bg.imagePal;
832     gti.PalAddress  = palAddr;
833
834     gti.Pitch   = imageWidth << gti.Size >> 1;
835     gti.Pitch   = (gti.Pitch>>3)<<3;    // Align to 8 bytes
836
837     if( gti.Address + gti.Pitch*gti.HeightToCreate > g_dwRamSize )
838     {
839         TRACE0("Skip BG 1CYC loading, memory out of bound");
840         return;
841     }
842
843     gti.TLutFmt = TLUT_FMT_RGBA16;  //RGBA16
844     gti.bSwapped    = FALSE;
845
846     gti.HeightToLoad = gti.HeightToCreate;
847     gti.WidthToLoad = gti.WidthToCreate;
848     gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address;
849     gti.tileNo = -1;
850     TxtrCacheEntry *pEntry = gTextureManager.GetTexture(&gti, false,true,false);
851     SetCurrentTexture(0,pEntry);
852
853     DEBUGGER_IF_DUMP((pauseAtNext && (eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI||eventToPause == NEXT_OBJ_BG)),
854         {
855             TRACE0("Load Obj BG 1CYC:\n");
856             DebuggerAppendMsg("Addr=0x%08X, W=%d, H=%d, Left=%d, Top=%d\n", 
857                 gti.Address, gti.WidthToCreate, gti.HeightToCreate, gti.LeftToLoad, gti.TopToLoad);
858             DebuggerAppendMsg("Fmt=%s-%db, Pal=%d\n",
859                 pszImgFormat[gti.Format], pnImgSize[gti.Size], gti.Palette);
860         }
861     );
862 }
863
864 void CRender::LoadObjSprite(uObjTxSprite &sprite, bool useTIAddr)
865 {
866     TxtrInfo gti;
867     gti.Format  = sprite.sprite.imageFmt;
868     gti.Size    = sprite.sprite.imageSiz;
869
870     uchar *palAddr = (uchar *) &g_wRDPTlut[0];
871
872     gti.Address = RSPSegmentAddr(sprite.txtr.block.image);
873     gti.Address += sprite.sprite.imageAdrs<<3;
874     gti.LeftToLoad      = 0;
875     gti.TopToLoad       = 0;
876     gti.Palette = sprite.sprite.imagePal;
877     gti.PalAddress = palAddr;
878
879     if( sprite.txtr.block.type == S2DEX_OBJLT_TXTRBLOCK )
880     {
881         gti.WidthToCreate       = sprite.sprite.imageW/32;
882         if( sprite.sprite.imageW >= 0x8000 )
883         {
884             gti.WidthToCreate = (0x10000-sprite.sprite.imageW)/32;
885         }
886         gti.HeightToCreate  = sprite.sprite.imageH/32;
887         if( sprite.sprite.imageH >= 0x8000 )
888         {
889             gti.HeightToCreate  = (0x10000-sprite.sprite.imageH)/32;
890         }
891         gti.Pitch       = (2047/(sprite.txtr.block.tline-1)) << 3;
892     }
893     else if( sprite.txtr.block.type == S2DEX_OBJLT_TXTRTILE )
894     {
895 //#define   GS_PIX2TMEM(pix, siz)   ((pix)>>(4-(siz)))
896 //#define   GS_TT_TWIDTH(pix,siz)   ((GS_PIX2TMEM((pix), (siz))<<2)-1)
897 //#define   GS_TT_THEIGHT(pix,siz)  (((pix)<<2)-1)
898
899         gti.WidthToCreate       = ((sprite.txtr.tile.twidth+1)>>2)<<(4-gti.Size);
900         gti.HeightToCreate  = (sprite.txtr.tile.theight+1)>>2;
901
902         if( gti.Size == TXT_SIZE_4b )
903         {
904             gti.Pitch = gti.WidthToCreate >> 1;
905         }
906         else
907             //gti.Pitch     = (sprite.txtr.tile.twidth+1) << 3;
908             gti.Pitch       = gti.WidthToCreate << (gti.Size-1);
909     }
910
911     if( gti.Address + gti.Pitch*gti.HeightToCreate > g_dwRamSize )
912     {
913         TRACE0("Skip Obj sprite loading, memory out of bound");
914         return;
915     }
916
917     gti.TLutFmt = TLUT_FMT_RGBA16;  //RGBA16
918     gti.bSwapped    = FALSE;
919
920     gti.HeightToLoad = gti.HeightToCreate;
921     gti.WidthToLoad = gti.WidthToCreate;
922     gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address;
923     gti.tileNo = -1;
924     TxtrCacheEntry *pEntry = gTextureManager.GetTexture(&gti, false);
925     SetCurrentTexture(0,pEntry);
926 }
927