X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=source%2Frice_gles%2Fsrc%2FRenderExt.cpp;fp=source%2Frice_gles%2Fsrc%2FRenderExt.cpp;h=564f49ae8e43dc3103fdbab54b73309d097deb1f;hb=d07c171fa694cae985ad7045f9ce2b2f1a5699b4;hp=0000000000000000000000000000000000000000;hpb=ca22e7b76883b946060a6b40bb8709c1981e1cf6;p=mupen64plus-pandora.git diff --git a/source/rice_gles/src/RenderExt.cpp b/source/rice_gles/src/RenderExt.cpp new file mode 100644 index 0000000..564f49a --- /dev/null +++ b/source/rice_gles/src/RenderExt.cpp @@ -0,0 +1,927 @@ +/* +Copyright (C) 2002 Rice1964 + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "osal_opengl.h" +#include "OGLDebug.h" +#include "FrameBuffer.h" +#include "Render.h" + +extern uObjMtxReal gObjMtxReal; +extern Matrix g_MtxReal; + +//======================================================================== + +void CRender::LoadFrameBuffer(bool useVIreg, uint32 left, uint32 top, uint32 width, uint32 height) +{ + uint32 VIwidth = *g_GraphicsInfo.VI_WIDTH_REG; + + TxtrInfo gti; + + gti.clampS = gti.clampT = 0; + gti.maskS = gti.maskT = gti.mirrorS = gti.mirrorT = 0; + gti.TLutFmt = TLUT_FMT_RGBA16; //RGBA16 + gti.bSwapped = FALSE; + gti.Palette = 0; + + if( useVIreg && *g_GraphicsInfo.VI_ORIGIN_REG > VIwidth*2 ) + { + gti.Format = 0; + gti.Size = 2; + + gti.Address = (*g_GraphicsInfo.VI_ORIGIN_REG & (g_dwRamSize-1) ) - VIwidth*2; + gti.LeftToLoad = 0; + gti.TopToLoad = 0; + + gti.PalAddress = (uchar *) &g_wRDPTlut[0]; + + gti.WidthToCreate = windowSetting.uViWidth;; + gti.HeightToCreate = windowSetting.uViHeight; + + if( gti.WidthToCreate == 0 || gti.HeightToCreate == 0 ) + { + TRACE0("Loading frame buffer: size = 0 x 0"); + return; + } + + gti.Pitch = VIwidth << gti.Size >> 1; + } + else + { + gti.Format = g_CI.dwFormat; + gti.Size = g_CI.dwSize; + gti.PalAddress = (uchar *) &g_wRDPTlut[0]; + + gti.Address = RSPSegmentAddr(g_CI.dwAddr); + + if( width == 0 || height == 0 ) + { + gti.LeftToLoad = 0; + gti.TopToLoad = 0; + + gti.WidthToCreate = g_CI.dwWidth; + gti.HeightToCreate = g_CI.dwWidth*3/4; + } + else + { + gti.LeftToLoad = left; + gti.TopToLoad = top; + + gti.WidthToCreate = width; + gti.HeightToCreate = height; + } + + if( gti.Size == TXT_SIZE_4b ) + { + gti.Pitch = g_CI.dwWidth >> 1; + } + else + { + gti.Pitch = g_CI.dwWidth << (gti.Size-1); + } + } + + + if( gti.Address + gti.Pitch*gti.HeightToCreate > g_dwRamSize ) + { + TRACE0("Skip frame buffer loading, memory out of bound"); + return; + } + +#ifdef DEBUGGER + if( pauseAtNext ) + { + DebuggerAppendMsg("Load Frame Buffer Imag at: %08X, (%d, %d) - (%d, %d)", gti.Address, + gti.LeftToLoad, gti.TopToLoad, gti.WidthToCreate, gti.HeightToCreate ); + } +#endif + + + gti.HeightToLoad = gti.HeightToCreate; + gti.WidthToLoad = gti.WidthToCreate; + + gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address; + gti.tileNo = -1; + TxtrCacheEntry *pEntry = gTextureManager.GetTexture(>i, false, true, false); + if( pEntry ) SetCurrentTexture( 0, pEntry->pTexture, pEntry->ti.WidthToCreate, pEntry->ti.HeightToCreate, pEntry); +} + +void CRender::LoadTextureFromMemory(void *buf, uint32 left, uint32 top, uint32 width, uint32 height, uint32 pitch, uint32 format) +{ + TxtrInfo gti; + gti.Format = g_CI.dwFormat; + gti.Size = g_CI.dwSize; + gti.Palette = 0; + gti.TLutFmt = TLUT_FMT_RGBA16; //RGBA16 + gti.PalAddress = 0; + gti.bSwapped = FALSE; + gti.Address = 0; + gti.LeftToLoad = 0; + gti.TopToLoad = 0; + gti.WidthToCreate = width; + gti.HeightToCreate = height; + + gti.Pitch = pitch; + + gti.HeightToLoad = height; + gti.WidthToLoad = width; + gti.pPhysicalAddress = (uint8*)buf; + + gti.tileNo = -1; + TxtrCacheEntry *pEntry = gTextureManager.GetTexture(>i, false); + //Upto here, the texture is loaded wrong because the format is wrong + + DrawInfo info; + if( pEntry->pTexture->StartUpdate(&info) ) + { + for( uint32 i=0; ipTexture->EndUpdate(&info); + } + SetCurrentTexture( 0, pEntry->pTexture, width, height, pEntry); +} + +void CRender::LoadObjBGCopy(uObjBg &info) +{ + TxtrInfo gti; + gti.Format = info.imageFmt; + gti.Size = info.imageSiz; + gti.Address = RSPSegmentAddr(info.imagePtr); + gti.LeftToLoad = 0; + gti.TopToLoad = 0; + gti.Palette = info.imagePal; + + gti.PalAddress = (uchar *) &g_wRDPTlut[0]; + gti.bSwapped = FALSE; + gti.TLutFmt = TLUT_FMT_RGBA16; //RGBA16 + + gti.WidthToCreate = info.imageW/4; + gti.HeightToCreate = info.imageH/4; + + if( options.bEnableHacks ) + { + if( g_CI.dwWidth == 0x200 && gti.Format == g_CI.dwFormat && gti.Size == g_CI.dwSize && + gti.WidthToCreate == 0x200 ) + { + // Hack for RE2 + uint32 w = *g_GraphicsInfo.VI_WIDTH_REG & 0xFFF; + gti.HeightToCreate = (gti.WidthToCreate*gti.HeightToCreate)/w; + gti.WidthToCreate = w; + } + } + + gti.Pitch = gti.WidthToCreate << gti.Size >> 1; + gti.Pitch = (gti.Pitch>>3)<<3; // Align to 8 bytes + + if( gti.Address + gti.Pitch*gti.HeightToCreate > g_dwRamSize ) + { + TRACE0("Skip BG copy loading, memory out of bound"); + return; + } + + gti.HeightToLoad = gti.HeightToCreate; + gti.WidthToLoad = gti.WidthToCreate; + gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address; + gti.tileNo = -1; + TxtrCacheEntry *pEntry = gTextureManager.GetTexture(>i, false); + SetCurrentTexture(0,pEntry); + + DEBUGGER_IF_DUMP((pauseAtNext && (eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI||eventToPause == NEXT_OBJ_BG)), + { + TRACE0("Load Obj BG Copy:\n"); + DebuggerAppendMsg("Addr=0x%08X, W=%d, H=%d, Left=%d, Top=%d\n", + gti.Address, gti.WidthToCreate, gti.HeightToCreate, gti.LeftToLoad, gti.TopToLoad); + DebuggerAppendMsg("Fmt=%s-%db, Pal=%d\n", + pszImgFormat[gti.Format], pnImgSize[gti.Size], gti.Palette); + } + ); +} + +void CRender::LoadTxtrBufIntoTexture(void) +{ + TxtrInfo gti; + + gti.Format = g_pRenderTextureInfo->CI_Info.dwFormat; + gti.Size = g_pRenderTextureInfo->CI_Info.dwSize; + + gti.Address = RSPSegmentAddr(g_pRenderTextureInfo->CI_Info.dwAddr); + gti.LeftToLoad = 0; + gti.TopToLoad = 0; + gti.Palette = 0; + + gti.PalAddress = (uchar *) &g_wRDPTlut[0]; + gti.bSwapped = FALSE; + + gti.WidthToCreate = g_pRenderTextureInfo->N64Width; + gti.HeightToCreate = g_pRenderTextureInfo->N64Height; + gti.TLutFmt = TLUT_FMT_RGBA16; //RGBA16 + + gti.Pitch = gti.WidthToCreate << (gti.Size-1); + + gti.HeightToLoad = gti.HeightToCreate; + gti.WidthToLoad = gti.WidthToCreate; + gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address; + gti.tileNo = -1; + TxtrCacheEntry *pEntry = gTextureManager.GetTexture(>i, false); + SetCurrentTexture(0,pEntry); +} + +void CRender::LoadSprite2D(Sprite2DInfo &info, uint32 ucode) +{ + TxtrInfo gti; + + gti.Format = info.spritePtr->SourceImageType; + gti.Size = info.spritePtr->SourceImageBitSize; + + gti.Address = RSPSegmentAddr(info.spritePtr->SourceImagePointer); + gti.Palette = 0; + gti.PalAddress = (uchar *) (g_pRDRAMu8 + RSPSegmentAddr(info.spritePtr->TlutPointer)); + + if( options.enableHackForGames == HACK_FOR_NITRO ) + { + gti.WidthToCreate = (uint32)(info.spritePtr->SubImageWidth/info.scaleX); + gti.HeightToCreate = (uint32)(info.spritePtr->SubImageHeight/info.scaleY); + gti.LeftToLoad = (uint32)(info.spritePtr->SourceImageOffsetS/info.scaleX); + gti.TopToLoad = (uint32)(info.spritePtr->SourceImageOffsetT/info.scaleY); + gti.Pitch = info.spritePtr->Stride << gti.Size >> 1; + gti.Pitch = (uint32)(gti.Pitch*info.scaleY); + } + else + { + gti.WidthToCreate = info.spritePtr->SubImageWidth; + gti.HeightToCreate = info.spritePtr->SubImageHeight; + gti.LeftToLoad = info.spritePtr->SourceImageOffsetS; + gti.TopToLoad = info.spritePtr->SourceImageOffsetT; + gti.Pitch = info.spritePtr->Stride << gti.Size >> 1; + } + + if( gti.Address + gti.Pitch*gti.HeightToCreate > g_dwRamSize ) + { + TRACE0("Skip Sprite image decompress, memory out of bound"); + return; + } + + gti.HeightToLoad = gti.HeightToCreate; + gti.WidthToLoad = gti.WidthToCreate; + + gti.TLutFmt = TLUT_FMT_RGBA16; //RGBA16 + gti.bSwapped = FALSE; + + gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address; + gti.tileNo = -1; + TxtrCacheEntry *pEntry = gTextureManager.GetTexture(>i, false); + SetCurrentTexture(0,pEntry); + + DEBUGGER_IF_DUMP((pauseAtNext && (eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI||eventToPause == NEXT_SPRITE_2D)), + { + TRACE0("Load Sprite 2D\n"); + DebuggerAppendMsg("Addr=0x%08X, W=%d, H=%d, Left=%d, Top=%d\n", + gti.Address, gti.WidthToCreate, gti.HeightToCreate, gti.LeftToLoad, gti.TopToLoad); + DebuggerAppendMsg("Fmt=%s-%db, Pal=%d, Pitch=%d\n", + pszImgFormat[gti.Format], pnImgSize[gti.Size], gti.Palette, gti.Pitch); + } + ); +} + + +void CRender::DrawSprite2D(Sprite2DInfo &info, uint32 ucode) +{ + if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer(); + + if( status.bHandleN64RenderTexture ) + { + g_pRenderTextureInfo->maxUsedHeight = g_pRenderTextureInfo->N64Height; + if( !status.bDirectWriteIntoRDRAM ) + { + status.bFrameBufferIsDrawn = true; + status.bFrameBufferDrawnByTriangles = true; + } + } + LoadSprite2D(info, ucode); + + info.scaleX = 1/info.scaleX; + info.scaleY = 1/info.scaleY; + + int x0, y0, x1, y1; + float t0, s0, t1, s1; + + if( info.flipX ) + { + //x0 = info.px*info.scaleX + info.spritePtr->SubImageWidth*info.scaleX; + //x1 = info.px*info.scaleX; + x0 = info.px + int(info.spritePtr->SubImageWidth*info.scaleX); + x1 = info.px; + } + else + { + //x0 = info.px*info.scaleX; + //x1 = info.px*info.scaleX + info.spritePtr->SubImageWidth*info.scaleX; + x0 = info.px; + x1 = info.px + int(info.spritePtr->SubImageWidth*info.scaleX); + } + + if( info.flipY ) + { + //y0 = info.py*info.scaleY + info.spritePtr->SubImageHeight*info.scaleY; + //y1 = info.py*info.scaleY; + y0 = info.py + int(info.spritePtr->SubImageHeight*info.scaleY); + y1 = info.py; + } + else + { + //y0 = info.py*info.scaleY; + //y1 = info.py*info.scaleY + info.spritePtr->SubImageHeight*info.scaleY; + y0 = info.py; + y1 = info.py + int(info.spritePtr->SubImageHeight*info.scaleY); + } + + t0 = s0 = 0; + if( options.enableHackForGames == HACK_FOR_NITRO ) + { + t1 = info.spritePtr->SubImageWidth*info.scaleX/g_textures[0].m_fTexWidth; + s1 = info.spritePtr->SubImageHeight*info.scaleY/g_textures[0].m_fTexHeight; + } + else + { + t1 = info.spritePtr->SubImageWidth/g_textures[0].m_fTexWidth; + s1 = info.spritePtr->SubImageHeight/g_textures[0].m_fTexHeight; + } + + //InitCombinerBlenderForSimpleTextureDraw(); + SetCombinerAndBlender(); + SetAddressUAllStages( 0, TEXTURE_UV_FLAG_CLAMP ); + SetAddressVAllStages( 0, TEXTURE_UV_FLAG_CLAMP ); + + COLOR speColor = PostProcessSpecularColor(); + COLOR difColor = PostProcessDiffuseColor(0xffffffff); + + float depth = ( gRDP.otherMode.depth_source == 1 ) ? gRDP.fPrimitiveDepth : 0; + DrawSimple2DTexture((float)x0, (float)y0, (float)x1, (float)y1, t0, s0, t1, s1, speColor, difColor, depth, 1.0f); +} + + +void CRender::DrawSpriteR(uObjTxSprite &sprite, bool initCombiner, uint32 tile, uint32 left, uint32 top, uint32 width, uint32 height) // With Rotation +{ + if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer(); + + if( status.bHandleN64RenderTexture ) + { + g_pRenderTextureInfo->maxUsedHeight = g_pRenderTextureInfo->N64Height; + if( !status.bDirectWriteIntoRDRAM ) + { + status.bFrameBufferIsDrawn = true; + status.bFrameBufferDrawnByTriangles = true; + } + } + SetCombinerAndBlender(); + + float scaleX = sprite.sprite.scaleW/1024.0f; + float scaleY = sprite.sprite.scaleH/1024.0f; + + if( width == 0 || height == 0 ) + { + width = g_textures[tile].m_dwTileWidth; + height = g_textures[tile].m_dwTileHeight; + } + + //RECT src = {left,top,width, height}; + float depth = 0.0; + if (gRDP.otherMode.depth_source==1) + depth = gRDP.fPrimitiveDepth; + + float x0 = sprite.sprite.objX/4.0f; + float y0 = sprite.sprite.objY/4.0f; + float x1 = sprite.sprite.imageW / 32.0f / scaleX + x0; + float y1 = sprite.sprite.imageH / 32.0f / scaleY + y0; + + if( sprite.sprite.imageFlags&1 ) { float temp = x0; x0 = x1; x1 = temp; } // flip X + if( sprite.sprite.imageFlags&0x10 ) { float temp = y0; y0 = y1; y1 = temp; } // flip Y + + g_texRectTVtx[0].x = (gObjMtxReal.A*x0 + gObjMtxReal.B*y0 + gObjMtxReal.X)*windowSetting.fMultX; + g_texRectTVtx[0].y = (gObjMtxReal.C*x0 + gObjMtxReal.D*y0 + gObjMtxReal.Y)*windowSetting.fMultY; + g_texRectTVtx[0].z = depth; + g_texRectTVtx[0].rhw = 1; + g_texRectTVtx[1].x = (gObjMtxReal.A*x1 + gObjMtxReal.B*y0 + gObjMtxReal.X)*windowSetting.fMultX; + g_texRectTVtx[1].y = (gObjMtxReal.C*x1 + gObjMtxReal.D*y0 + gObjMtxReal.Y)*windowSetting.fMultY; + g_texRectTVtx[1].z = depth; + g_texRectTVtx[1].rhw = 1; + g_texRectTVtx[2].x = (gObjMtxReal.A*x1 + gObjMtxReal.B*y1 + gObjMtxReal.X)*windowSetting.fMultX; + g_texRectTVtx[2].y = (gObjMtxReal.C*x1 + gObjMtxReal.D*y1 + gObjMtxReal.Y)*windowSetting.fMultY; + g_texRectTVtx[2].z = depth; + g_texRectTVtx[2].rhw = 1; + g_texRectTVtx[3].x = (gObjMtxReal.A*x0 + gObjMtxReal.B*y1 + gObjMtxReal.X)*windowSetting.fMultX; + g_texRectTVtx[3].y = (gObjMtxReal.C*x0 + gObjMtxReal.D*y1 + gObjMtxReal.Y)*windowSetting.fMultY; + g_texRectTVtx[3].z = depth; + g_texRectTVtx[3].rhw = 1; + + g_texRectTVtx[0].tcord[0].u = left/g_textures[tile].m_fTexWidth; + g_texRectTVtx[0].tcord[0].v = top/g_textures[tile].m_fTexHeight; + g_texRectTVtx[1].tcord[0].u = (left+width)/g_textures[tile].m_fTexWidth; + g_texRectTVtx[1].tcord[0].v = top/g_textures[tile].m_fTexHeight; + g_texRectTVtx[2].tcord[0].u = (left+width)/g_textures[tile].m_fTexWidth; + g_texRectTVtx[2].tcord[0].v = (top+height)/g_textures[tile].m_fTexHeight; + g_texRectTVtx[3].tcord[0].u = left/g_textures[tile].m_fTexWidth; + g_texRectTVtx[3].tcord[0].v = (top+height)/g_textures[tile].m_fTexHeight; + + //COLOR speColor = PostProcessSpecularColor(); + COLOR difColor = PostProcessDiffuseColor(0xffffffff); + + g_texRectTVtx[0].dcDiffuse = g_texRectTVtx[1].dcDiffuse + = g_texRectTVtx[2].dcDiffuse = g_texRectTVtx[3].dcDiffuse = difColor; + g_texRectTVtx[0].dcSpecular = g_texRectTVtx[1].dcSpecular + = g_texRectTVtx[2].dcSpecular = g_texRectTVtx[3].dcSpecular = difColor; + + DrawSpriteR_Render(); +} + +void CRender::DrawFrameBuffer(bool useVIreg, uint32 left, uint32 top, uint32 width, uint32 height) +{ + BeginRendering(); + + LoadFrameBuffer(useVIreg, left, top, width, height); + + m_pColorCombiner->InitCombinerBlenderForSimpleTextureDraw(0); + + ZBufferEnable(FALSE); + SetZUpdate(FALSE); + if( left == 0 ) + SetAlphaTestEnable(FALSE); + else + SetAlphaTestEnable(TRUE); // use Alpha Test for partial frame buffer draw, for Dr. Mario 64 + + m_pAlphaBlender->Disable(); + + CTexture *pTexture = g_textures[0].m_pCTexture; + if( pTexture ) + { + if( useVIreg ) + { + // Draw the whole frame buffer + DrawSimple2DTexture(0, 0, windowSetting.uViWidth, windowSetting.uViHeight, + 0, 0, 1/pTexture->m_fXScale, 1/pTexture->m_fYScale, 0xFFFFFFFF, 0xFFFFFFFF, 0, 1); + } + else + { + // Draw a small texture in frame buffer + DrawSimple2DTexture((float)left, (float)top, (float)(left+width), (float)(top+height), + 0, 0, 1/pTexture->m_fXScale, 1/pTexture->m_fYScale, 0xFFFFFFFF, 0xFFFFFFFF, 0, 1); + } + } + + TXTRBUF_OR_CI_DUMP(TRACE0("Draw Frame Buffer Img")); +#ifdef DEBUGGER + if( pauseAtNext && ( eventToPause == NEXT_FRAME || eventToPause == NEXT_FLUSH_TRI ) ) + { + TRACE0("Draw Frame Buffer Img"); + debuggerPause = true; + DebuggerPause(); + } +#endif + + EndRendering(); +} + +void CRender::DrawObjBGCopy(uObjBg &info) +{ + if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer(); + + if( status.bHandleN64RenderTexture ) + { + g_pRenderTextureInfo->maxUsedHeight = g_pRenderTextureInfo->N64Height; + if( !status.bDirectWriteIntoRDRAM ) + { + status.bFrameBufferIsDrawn = true; + status.bFrameBufferDrawnByTriangles = true; + } + } + SetCombinerAndBlender(); + + uint32 frameH = info.frameH; + uint32 frameW = info.frameW; + uint32 imageH = info.imageH; + uint32 imageW = info.imageW; + + if( options.bEnableHacks ) + { + if( g_CI.dwWidth == 0x200 && info.imageFmt == g_CI.dwFormat && info.imageSiz == g_CI.dwSize && + frameW == 0x800 ) + { + // Hack for RE2 + uint32 width = *g_GraphicsInfo.VI_WIDTH_REG & 0xFFF; + imageH = frameH = (frameW/4*frameH/4)/width*4; + imageW = frameW = width*4; + } + } + + float x0 = info.frameX / 4.0f; + float y0 = info.frameY / 4.0f; + float x1 = frameW / 4.0f + x0; + float y1 = frameH / 4.0f + y0; + + float s0 = info.imageX / 32.0f; + float t0 = info.imageY / 32.0f; + + float texwidth = imageW/4.0f; + float texheight = imageH/4.0f; + + float u0 = s0/g_textures[0].m_fTexWidth; + float v0 = t0/g_textures[0].m_fTexHeight; + float maxu = texwidth/g_textures[0].m_fTexWidth; + float maxv = texheight/g_textures[0].m_fTexHeight; + + float x2 = x0 + (texwidth-s0); + float y2 = y0 + (texheight-t0); + float u1 = (x1-x2)/g_textures[0].m_fTexWidth; + float v1 = (y1-y2)/g_textures[0].m_fTexHeight; + + float depth = (gRDP.otherMode.depth_source == 1 ? gRDP.fPrimitiveDepth : 0.0f); + + COLOR speColor = PostProcessSpecularColor(); + COLOR difColor = PostProcessDiffuseColor(0xffffffff); + + if( options.enableHackForGames == HACK_FOR_COMMANDCONQUER ) + { + float s1 = (x1-x0) + s0; + float t1 = (y1-y0) + t0; + DrawSimple2DTexture(x0, y0, x1, y1, u0, v0, + s1/g_textures[0].m_fTexWidth, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1); + } + else if( x2 >= x1 ) + { + float s1 = (x1-x0) + s0; + if( y2 >= y1 ) + { + float t1 = (y1-y0) + t0; + DrawSimple2DTexture(x0, y0, x1, y1, u0, v0, + s1/g_textures[0].m_fTexWidth, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1); + } + else + { + DrawSimple2DTexture(x0, y0, x1, y2, u0, v0, + s1/g_textures[0].m_fTexWidth, maxv, difColor, speColor, depth, 1); + DrawSimple2DTexture(x0, y2, x1, y1, u0, 0, + s1/g_textures[0].m_fTexWidth, v1, difColor, speColor, depth, 1); + } + } + else + { + if( y2 >= y1 ) + { + float t1 = (y1-y0) + t0; + DrawSimple2DTexture(x0, y0, x2, y1, u0, v0, + maxu, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1); + DrawSimple2DTexture(x2, y0, x1, y1, 0, v0, + u1, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1); + } + else + { + DrawSimple2DTexture(x0, y0, x2, y2, u0, v0, maxu, maxv, difColor, speColor, depth, 1); + DrawSimple2DTexture(x2, y0, x1, y2, 0, v0, u1, maxv, difColor, speColor, depth, 1); + DrawSimple2DTexture(x0, y2, x2, y1, u0, 0, maxu, v1, difColor, speColor, depth, 1); + DrawSimple2DTexture(x2, y2, x1, y1, 0, 0, u1, v1, difColor, speColor, depth, 1); + } + } + + DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N( + (pauseAtNext&&(eventToPause==NEXT_OBJ_BG||eventToPause==NEXT_FLUSH_TRI||eventToPause==NEXT_OBJ_TXT_CMD)), + { + TRACE0("Pause ObjBG Copy"); + } + ); +} + +void CRender::DrawObjBG1CYC(uObjScaleBg &bg, bool scaled) //Without Ratation +{ + if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer(); + + if( g_curRomInfo.bDisableObjBG ) + return; + + if( status.bHandleN64RenderTexture ) + { + g_pRenderTextureInfo->maxUsedHeight = g_pRenderTextureInfo->N64Height; + if( !status.bDirectWriteIntoRDRAM ) + { + status.bFrameBufferIsDrawn = true; + status.bFrameBufferDrawnByTriangles = true; + } + } + + SetCombinerAndBlender(); + + float depth = (gRDP.otherMode.depth_source == 1 ? gRDP.fPrimitiveDepth : 0.0f); + + float x0 = bg.frameX / 4.0f; + float y0 = bg.frameY / 4.0f; + float x1 = bg.frameW / 4.0f + x0; + float y1 = bg.frameH / 4.0f + y0; + + float s0 = bg.imageX / 32.0f; + float t0 = bg.imageY / 32.0f; + + float scaleX = bg.scaleW/1024.0f; + float scaleY = bg.scaleH/1024.0f; + + float texwidth = bg.imageW/4.0f; + float texheight = bg.imageH/4.0f; + + float u0 = s0/g_textures[0].m_fTexWidth; + float v0 = t0/g_textures[0].m_fTexHeight; + float maxu = texwidth/g_textures[0].m_fTexWidth; + float maxv = texheight/g_textures[0].m_fTexHeight; + + float x2 = x0 + (texwidth-s0)/scaleX; + float y2 = y0 + (texheight-t0)/scaleY; + float u1 = (x1-x2)*scaleX/g_textures[0].m_fTexWidth; + float v1 = (y1-y2)*scaleY/g_textures[0].m_fTexHeight; + + COLOR speColor = PostProcessSpecularColor(); + COLOR difColor = PostProcessDiffuseColor(0xffffffff); + + SetAlphaTestEnable(FALSE); + + if( options.enableHackForGames != HACK_FOR_YOSHI ) + { + float s1 = (x1-x0)*scaleX + s0; + float t1 = (y1-y0)*scaleY + t0; + DrawSimple2DTexture(x0, y0, x1, y1, u0, v0, + s1/g_textures[0].m_fTexWidth, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1); + } + else if( x2 >= x1 ) + { + float s1 = (x1-x0)*scaleX + s0; + if( y2 >= y1 ) + { + float t1 = (y1-y0)*scaleY + t0; + DrawSimple2DTexture(x0, y0, x1, y1, u0, v0, + s1/g_textures[0].m_fTexWidth, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1); + } + else + { + DrawSimple2DTexture(x0, y0, x1, y2, u0, v0, + s1/g_textures[0].m_fTexWidth, maxv, difColor, speColor, depth, 1); + DrawSimple2DTexture(x0, y2, x1, y1, u0, 0, + s1/g_textures[0].m_fTexWidth, v1, difColor, speColor, depth, 1); + } + } + else + { + if( y2 >= y1 ) + { + float t1 = (y1-y0)*scaleY + t0; + DrawSimple2DTexture(x0, y0, x2, y1, u0, v0, + maxu, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1); + DrawSimple2DTexture(x2, y0, x1, y1, 0, v0, + u1, t1/g_textures[0].m_fTexHeight, difColor, speColor, depth, 1); + } + else + { + DrawSimple2DTexture(x0, y0, x2, y2, u0, v0, maxu, maxv, difColor, speColor, depth, 1); + DrawSimple2DTexture(x2, y0, x1, y2, 0, v0, u1, maxv, difColor, speColor, depth, 1); + DrawSimple2DTexture(x0, y2, x2, y1, u0, 0, maxu, v1, difColor, speColor, depth, 1); + DrawSimple2DTexture(x2, y2, x1, y1, 0, 0, u1, v1, difColor, speColor, depth, 1); + } + } + + DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N( + (pauseAtNext&&(eventToPause==NEXT_OBJ_BG||eventToPause==NEXT_FLUSH_TRI||eventToPause==NEXT_OBJ_TXT_CMD)), + { + DebuggerAppendMsg("Pause BG 1CYC: (%.0f,%.0f - %.0f,%.0f), \ntex (%.2f,%.2f), scale (%.2f,%.2f)",x0,y0,x1,y1,s0,t0,scaleX,scaleY); + } + ); +} + + +void CRender::DrawSprite(uObjTxSprite &sprite, bool rectR) //Without Ratation +{ + if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer(); + + if( status.bHandleN64RenderTexture ) + { + g_pRenderTextureInfo->maxUsedHeight = g_pRenderTextureInfo->N64Height; + if( !status.bDirectWriteIntoRDRAM ) + { + status.bFrameBufferIsDrawn = true; + status.bFrameBufferDrawnByTriangles = true; + } + } + SetCombinerAndBlender(); + COLOR speColor = PostProcessSpecularColor(); + COLOR difColor = PostProcessDiffuseColor(0xffffffff); + + + float objX = sprite.sprite.objX/4.0f; + float objY = sprite.sprite.objY/4.0f; + float width = sprite.sprite.imageW / 32.0f; + float high = sprite.sprite.imageH / 32.0f; + float scaleW = sprite.sprite.scaleW/1024.0f; + float scaleH = sprite.sprite.scaleH/1024.0f; + + if( g_curRomInfo.bIncTexRectEdge ) + { + width++; + high++; + } + + float x0, y0, x1, y1; + if( rectR ) + { + // Upper-left coordinate + // ( X + objX / BaseScaleX, Y+objY/BaseScaleY ) + // Lower-right coordinate + // ( X + (objX + imageW / scaleW) / BaseScaleX - 1, Y + (objY + imageH / scaleH) / BaseScaleY - 1 ) + + x0 = gObjMtxReal.X + objX/gObjMtxReal.BaseScaleX; + y0 = gObjMtxReal.Y + objY/gObjMtxReal.BaseScaleY; + x1 = gObjMtxReal.X + (objX + width / scaleW) / gObjMtxReal.BaseScaleX; + y1 = gObjMtxReal.Y + (objY + high / scaleH) / gObjMtxReal.BaseScaleY; + } + else + { + // (objX, objY) - ( objX+imageW/scaleW-1, objY+imageH/scaleH-1) + x0 = objX; + y0 = objY; + x1 = objX + width / scaleW; + y1 = objY + high / scaleH; + + if( (sprite.sprite.imageFlags&1) ) // flipX + { + float temp = x0; + x0 = x1; + x1 = temp; + } + + if( (sprite.sprite.imageFlags&0x10) ) // flipY + { + float temp = y0; + y0 = y1; + y1 = temp; + } + } + + // save the current clamp type + GLint iClampS, iClampT; + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, &iClampS); + OPENGL_CHECK_ERRORS; + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, &iClampT); + OPENGL_CHECK_ERRORS; + // force clamp type to CLAMP_EDGE (experiments show sometimes this is set to hex 0x2901 - invalid value) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + OPENGL_CHECK_ERRORS; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + OPENGL_CHECK_ERRORS; + // draw the 2D sprite as 2 triangles + float depth = (gRDP.otherMode.depth_source == 1 ? gRDP.fPrimitiveDepth : 0.0f); + CTexture *pTexture = g_textures[0].m_pCTexture; + DrawSimple2DTexture(x0, y0, x1, y1, 0, 0, 1/pTexture->m_fXScale, 1/pTexture->m_fYScale, + difColor, speColor, depth, 1); + // return clamp type to original setting + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampS); + OPENGL_CHECK_ERRORS; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampT); + OPENGL_CHECK_ERRORS; +} + + +void CRender::LoadObjBG1CYC(uObjScaleBg &bg) +{ + uint32 imageWidth = bg.imageW/4; + uint32 imageHeight = bg.imageH/4; + + TxtrInfo gti; + gti.Format = bg.imageFmt; + gti.Size = bg.imageSiz; + + //uint8* img = (uint8*)(g_pRDRAMu8+RSPSegmentAddr(bg.imagePtr)); + + uchar *palAddr = (uchar *) &g_wRDPTlut[0]; + gti.Address = RSPSegmentAddr(bg.imagePtr); + + gti.LeftToLoad = 0; + gti.TopToLoad = 0; + + gti.WidthToCreate = imageWidth; + gti.HeightToCreate = imageHeight; + + gti.clampS = gti.clampT = 1; + gti.maskS = gti.maskT = 0; + + gti.Palette = bg.imagePal; + gti.PalAddress = palAddr; + + gti.Pitch = imageWidth << gti.Size >> 1; + gti.Pitch = (gti.Pitch>>3)<<3; // Align to 8 bytes + + if( gti.Address + gti.Pitch*gti.HeightToCreate > g_dwRamSize ) + { + TRACE0("Skip BG 1CYC loading, memory out of bound"); + return; + } + + gti.TLutFmt = TLUT_FMT_RGBA16; //RGBA16 + gti.bSwapped = FALSE; + + gti.HeightToLoad = gti.HeightToCreate; + gti.WidthToLoad = gti.WidthToCreate; + gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address; + gti.tileNo = -1; + TxtrCacheEntry *pEntry = gTextureManager.GetTexture(>i, false,true,false); + SetCurrentTexture(0,pEntry); + + DEBUGGER_IF_DUMP((pauseAtNext && (eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI||eventToPause == NEXT_OBJ_BG)), + { + TRACE0("Load Obj BG 1CYC:\n"); + DebuggerAppendMsg("Addr=0x%08X, W=%d, H=%d, Left=%d, Top=%d\n", + gti.Address, gti.WidthToCreate, gti.HeightToCreate, gti.LeftToLoad, gti.TopToLoad); + DebuggerAppendMsg("Fmt=%s-%db, Pal=%d\n", + pszImgFormat[gti.Format], pnImgSize[gti.Size], gti.Palette); + } + ); +} + +void CRender::LoadObjSprite(uObjTxSprite &sprite, bool useTIAddr) +{ + TxtrInfo gti; + gti.Format = sprite.sprite.imageFmt; + gti.Size = sprite.sprite.imageSiz; + + uchar *palAddr = (uchar *) &g_wRDPTlut[0]; + + gti.Address = RSPSegmentAddr(sprite.txtr.block.image); + gti.Address += sprite.sprite.imageAdrs<<3; + gti.LeftToLoad = 0; + gti.TopToLoad = 0; + gti.Palette = sprite.sprite.imagePal; + gti.PalAddress = palAddr; + + if( sprite.txtr.block.type == S2DEX_OBJLT_TXTRBLOCK ) + { + gti.WidthToCreate = sprite.sprite.imageW/32; + if( sprite.sprite.imageW >= 0x8000 ) + { + gti.WidthToCreate = (0x10000-sprite.sprite.imageW)/32; + } + gti.HeightToCreate = sprite.sprite.imageH/32; + if( sprite.sprite.imageH >= 0x8000 ) + { + gti.HeightToCreate = (0x10000-sprite.sprite.imageH)/32; + } + gti.Pitch = (2047/(sprite.txtr.block.tline-1)) << 3; + } + else if( sprite.txtr.block.type == S2DEX_OBJLT_TXTRTILE ) + { +//#define GS_PIX2TMEM(pix, siz) ((pix)>>(4-(siz))) +//#define GS_TT_TWIDTH(pix,siz) ((GS_PIX2TMEM((pix), (siz))<<2)-1) +//#define GS_TT_THEIGHT(pix,siz) (((pix)<<2)-1) + + gti.WidthToCreate = ((sprite.txtr.tile.twidth+1)>>2)<<(4-gti.Size); + gti.HeightToCreate = (sprite.txtr.tile.theight+1)>>2; + + if( gti.Size == TXT_SIZE_4b ) + { + gti.Pitch = gti.WidthToCreate >> 1; + } + else + //gti.Pitch = (sprite.txtr.tile.twidth+1) << 3; + gti.Pitch = gti.WidthToCreate << (gti.Size-1); + } + + if( gti.Address + gti.Pitch*gti.HeightToCreate > g_dwRamSize ) + { + TRACE0("Skip Obj sprite loading, memory out of bound"); + return; + } + + gti.TLutFmt = TLUT_FMT_RGBA16; //RGBA16 + gti.bSwapped = FALSE; + + gti.HeightToLoad = gti.HeightToCreate; + gti.WidthToLoad = gti.WidthToCreate; + gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address; + gti.tileNo = -1; + TxtrCacheEntry *pEntry = gTextureManager.GetTexture(>i, false); + SetCurrentTexture(0,pEntry); +} +