mupen64plus-oldsvn/rice_video/RenderExt.cpp
Scott Knauert edcef05047 Changes: Fixed nearly all warnings in Rice (Issue 24) except
one pointer arithmetic one in TextureFilters.cpp (see tracker).
Once that is fixed Issue 24 in current form can be closed.

Testing done: Code compiles for normal and debug use without 
any -Wall warnings and seems to yield the same results and previous 
svn on my r300.
2008-04-04 19:18:54 +00:00

925 lines
28 KiB
C++

/*
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 "stdafx.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 _DEBUG
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(&gti, 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(&gti, false);
//Upto here, the texture is loaded wrong because the format is wrong
DrawInfo info;
if( pEntry->pTexture->StartUpdate(&info) )
{
for( uint32 i=0; i<height; i++)
{
uint32 *psrc = (uint32*)((uint8*)buf+pitch*(i+top))+left;
uint32 *pdst = (uint32*)((uint8*)info.lpSurface+i*info.lPitch);
for( uint32 j=0; j<width; j++)
{
pdst[j]=psrc[j];
}
}
pEntry->pTexture->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(&gti, 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(&gti, 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(&gti, 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;
(gRDP.otherMode.depth_source==1) ? depth = gRDP.fPrimitiveDepth : depth = 0;
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 _DEBUG
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
int iClampS, iClampT;
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, &iClampS);
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, &iClampT);
// 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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// 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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampT);
}
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(&gti, 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;
uint8* img;
if( useTIAddr )
{
img = (uint8*)(g_pRDRAMu8+RSPSegmentAddr(g_TI.dwAddr));
}
else
img = (uint8*)(g_pRDRAMu8+RSPSegmentAddr(sprite.txtr.block.image));
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(&gti, false);
SetCurrentTexture(0,pEntry);
}