292f9317 |
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(>i, 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(>i, 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(>i, 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(>i, 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(>i, 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(>i, 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(>i, false); |
925 | SetCurrentTexture(0,pEntry); |
926 | } |
927 | |