Rice GLES2 (from mupen64plus-ae) plugin. Compile but doesn't works well on the OpenPa...
[mupen64plus-pandora.git] / source / gles2rice / src / RenderExt.cpp
CommitLineData
292f9317 1/*
2Copyright (C) 2002 Rice1964
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, 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
25extern uObjMtxReal gObjMtxReal;
26extern Matrix g_MtxReal;
27
28//========================================================================
29
30void 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
124void 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
166void 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
222void 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
251void 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
309void 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
385void 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
459void 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
506void 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
615void 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
717void 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
808void 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
864void 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