X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=source%2Fmupen64plus-video-arachnoid%2Fsrc%2FRDP%2FRDP.cpp;fp=source%2Fmupen64plus-video-arachnoid%2Fsrc%2FRDP%2FRDP.cpp;h=e0005825d1c6554c39a208f53122c11586c4088a;hb=22726e4d55be26faa48b57b22689cbedde27ae44;hp=0000000000000000000000000000000000000000;hpb=fc5d46b49a19d41f9f2da5a9336daec452900475;p=mupen64plus-pandora.git diff --git a/source/mupen64plus-video-arachnoid/src/RDP/RDP.cpp b/source/mupen64plus-video-arachnoid/src/RDP/RDP.cpp new file mode 100755 index 0000000..e000582 --- /dev/null +++ b/source/mupen64plus-video-arachnoid/src/RDP/RDP.cpp @@ -0,0 +1,923 @@ +/****************************************************************************** + * Arachnoid Graphics Plugin for Mupen64Plus + * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/ + * + * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *****************************************************************************/ + +#include "RDP.h" +#include "GBIDefs.h" +#include "GBI.h" +#include "RSP.h" +#include "DisplayListParser.h" +#include "assembler.h" +#include "OpenGLRenderer.h" +#include "TextureCache.h" +#include "VI.h" +#include "Memory.h" +#include "OpenGLManager.h" +#include "OpenGL2DRenderer.h" +#include "AdvancedCombinerManager.h" +#include "FogManager.h" +#include "Logger.h" +#include "MathLib.h" +#include "RomDetector.h" +#include "m64p.h" +#include "OpenGL.h" +#include +using std::max; + +//----------------------------------------------------------------------------- +//! Defines +//----------------------------------------------------------------------------- +#define MI_INTR_DP 0x00000020 //!< RDP Interrupt signal + +//----------------------------------------------------------------------------- +//! Static Variables +//----------------------------------------------------------------------------- +Memory* RDP::m_memory = 0; + +//----------------------------------------------------------------------------- +//! Constructor +//----------------------------------------------------------------------------- +RDP::RDP() +{ + m_graphicsInfo = 0; + m_changedTiles = false; + m_textureMode = TM_NORMAL; + m_loadType = LOADTYPE_BLOCK; + m_tmemChanged = false; + m_textureLUT = 0; + m_texRectWidth = 1; + m_texRectHeight = 1; + m_displayListParser = 0; + m_primitiveZ = 0; + m_combinerMgr = 0; + m_textureLoader = 0; + m_openGL2DRenderer = 0; + m_screenUpdatePending= false; +} + +//----------------------------------------------------------------------------- +//! Destructor +//----------------------------------------------------------------------------- +RDP::~RDP() +{ +} + +//----------------------------------------------------------------------------- +//* Initialize +//! Sets pointers to managers and initializes objects +//----------------------------------------------------------------------------- +bool RDP::initialize(GFX_INFO* graphicsInfo, RSP* rsp, Memory* memory, GBI* gbi, TextureCache* textureCache, VI* vi, DisplayListParser* displayListParser, FogManager* fogMgr) +{ + //Set pointers + m_graphicsInfo = graphicsInfo; + m_rsp = rsp; + m_vi = vi; + m_memory = memory; + m_displayListParser = displayListParser; + m_textureCache = textureCache; + m_fogMgr = fogMgr; + + //Create combiner manager + m_combinerMgr = new AdvancedCombinerManager(); + m_combinerMgr->initialize(); + + //Create texture loader + m_textureLoader = new TextureLoader(); + m_textureLoader->initialize(this, m_memory); + + //Create OpenGL 2D Renderer + m_openGL2DRenderer = new OpenGL2DRenderer(); + m_openGL2DRenderer->initialize(vi); + + return true; +} + +//----------------------------------------------------------------------------- +//* Dispose +//! Delets all allocated memory +//----------------------------------------------------------------------------- +void RDP::dispose() +{ + if ( m_combinerMgr ) { delete m_combinerMgr; m_combinerMgr = 0; } + if ( m_textureLoader ) { delete m_textureLoader; m_textureLoader = 0; } + if ( m_openGL2DRenderer ) { delete m_openGL2DRenderer; m_openGL2DRenderer = 0; } +} + +//----------------------------------------------------------------------------- +//* Update States +//! Sets OpenGL states, updates combiner, activates textures, sets blender +//----------------------------------------------------------------------------- +void RDP::updateStates() +{ + //Depth Compare + if (m_otherMode.depthCompare) + glDepthFunc( GL_LEQUAL ); + else + glDepthFunc( GL_ALWAYS ); + + //Depth Update + if (m_otherMode.depthUpdate) + glDepthMask( true ); + else + glDepthMask( false ); + + // Depth Mode + if (m_otherMode.depthMode == ZMODE_DEC) + { + glEnable( GL_POLYGON_OFFSET_FILL ); + glPolygonOffset( -3.0f, -3.0f ); + } + else + { + glDisable( GL_POLYGON_OFFSET_FILL ); + } + + // Alpha Compare + if ((m_otherMode.alphaCompare == G_AC_THRESHOLD) && !(m_otherMode.alphaCvgSel)) + { + glEnable( GL_ALPHA_TEST ); + glAlphaFunc( (m_combinerMgr->getBlendColor()[3] > 0.0f) ? GL_GEQUAL : GL_GREATER, m_combinerMgr->getBlendColor()[3] ); + } + // Used in TEX_EDGE and similar render modes + else if (m_otherMode.cvgXAlpha) + { + glEnable( GL_ALPHA_TEST ); + glAlphaFunc( GL_GEQUAL, 0.5f ); // Arbitrary number -- gives nice results though + } + else + glDisable( GL_ALPHA_TEST ); + + //Combiner + if ( m_updateCombiner ) + { + if ( m_otherMode.cycleType == G_CYC_COPY) + { + m_combinerMgr->setMux(72057594037727865LL, m_otherMode.cycleType); //Only normal texturing + m_combinerMgr->selectCombine(m_otherMode.cycleType); + } + else if ( m_otherMode.cycleType == G_CYC_FILL ) + { + m_combinerMgr->setMux( 72057594037828926LL, m_otherMode.cycleType ); + m_combinerMgr->selectCombine(m_otherMode.cycleType); + } + else + { + m_combinerMgr->selectCombine(m_otherMode.cycleType); + } + m_updateCombiner = false; + m_updateCombineColors = true; + } + + if ( m_updateCombineColors ) + { + m_combinerMgr->updateCombineColors(); + m_updateCombineColors = false; + } + + //Texturing + if ( m_changedTiles || m_tmemChanged || m_rsp->getTexturesChanged() ) + { + m_combinerMgr->beginTextureUpdate(); + + //Update Texture channel 0 + if ( m_combinerMgr->getUsesTexture0() ) + { + //Enable texture 0 + m_textureCache->update(0); + m_rsp->setTexturesChanged(false); + m_changedTiles = false; + m_tmemChanged = false; + } + else + { + //Disable texture 0 + glActiveTextureARB( GL_TEXTURE0_ARB + 0 ); + glDisable(GL_TEXTURE_2D); + } + + //Update Texture channel 1 + if ( m_combinerMgr->getUsesTexture1() ) + { + //Enable texture 1 + m_textureCache->update(1); + m_rsp->setTexturesChanged(false); + m_changedTiles = false; + m_tmemChanged = false; + } + else + { + //Disable textureing 1 + glActiveTextureARB( GL_TEXTURE0_ARB + 1 ); + glDisable(GL_TEXTURE_2D); + } + + m_combinerMgr->endTextureUpdate(); + } + + // Blending + if ( (m_otherMode.forceBlender) && + (m_otherMode.cycleType != G_CYC_COPY) && + (m_otherMode.cycleType != G_CYC_FILL) && + !(m_otherMode.alphaCvgSel)) + { + glEnable( GL_BLEND ); + switch (m_otherMode.l >> 16) + { + case 0x0448: // Add + case 0x055A: + glBlendFunc( GL_ONE, GL_ONE ); + break; + case 0x0C08: // 1080 Sky + case 0x0F0A: // Used LOTS of places + glBlendFunc( GL_ONE, GL_ZERO ); + break; + case 0xC810: // Blends fog + case 0xC811: // Blends fog + case 0x0C18: // Standard interpolated blend + case 0x0C19: // Used for antialiasing + case 0x0050: // Standard interpolated blend + case 0x0055: // Used for antialiasing + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + break; + case 0x0FA5: // Seems to be doing just blend color - maybe combiner can be used for this? + case 0x5055: // Used in Paper Mario intro, I'm not sure if this is right... + glBlendFunc( GL_ZERO, GL_ONE ); + break; + default: + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + break; + } + } + else + glDisable( GL_BLEND ); + + if (m_otherMode.cycleType == G_CYC_FILL) + { + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glEnable( GL_BLEND ); + } +} + +//----------------------------------------------------------------------------- +//* Reset +//! Resets all states on RDP +//----------------------------------------------------------------------------- +void RDP::reset() +{ + setTextureFiltering( G_TF_POINT ); + setRenderMode(0); +} + +//----------------------------------------------------------------------------- +//* Trigger Interrupt +//! Tell emulator that the RDP is idle +//----------------------------------------------------------------------------- +void RDP::triggerInterrupt() +{ + *(m_graphicsInfo->MI_INTR_REG) |= MI_INTR_DP; + m_graphicsInfo->CheckInterrupts(); +} + +//----------------------------------------------------------------------------- +//* Set Alpha Compare Mode +//----------------------------------------------------------------------------- +void RDP::setAlphaCompareMode(unsigned int mode) +{ + m_otherMode.alphaCompare = mode; + OpenGLManager::getSingleton().setAlphaTest( m_otherMode.alphaCompare != 0 ); +} + +//----------------------------------------------------------------------------- +//* Set Render Mode +//----------------------------------------------------------------------------- +void RDP::setRenderMode(unsigned int w1) +{ + unsigned int mode1 = (w1 & 0xCCCCFFFF); + unsigned int mode2 = (w1 & 0x3333FFFF); + + m_otherMode.l &= 0x00000007; + m_otherMode.l |= mode1 | mode2; +} + +//############################################################################# +// UCODE FUNCTIONS: +//############################################################################# + +//***************************************************************************** +// Combiner Mode +//***************************************************************************** + +//----------------------------------------------------------------------------- +//* Set Combine +//! Sets all combiner variables on combiner that tells it how to combine +//! the diffrent colors and textures. +//----------------------------------------------------------------------------- +void RDP::RDP_SetCombine(MicrocodeArgument* ucode) +{ + int mux0 = _SHIFTR( ucode->w0, 0, 24 ); + int mux1 = ucode->w1; + m_combinerMgr->setMux(mux0, mux1, (G_CYCLE_TYPE)m_otherMode.cycleType); + + m_updateCombiner = true; +} + +//***************************************************************************** +// Colors +//***************************************************************************** + +//----------------------------------------------------------------------------- +//* Set Environment Color +//! Sets Environment Color on combiner +//! @param r Red component of color (0.0 - 1.0) +//! @param g Green component of color (0.0 - 1.0) +//! @param b Blue component of color (0.0 - 1.0) +//! @param a Alpha component of color (0.0 - 1.0) +//----------------------------------------------------------------------------- +void RDP::RDP_SetEnvColor(float r, float g, float b, float a) +{ + m_combinerMgr->setEnvColor(r, g, b, a); + m_updateCombineColors = true; +} + +//----------------------------------------------------------------------------- +//* Set Prim Color +//! Sets Prim Color on combiner +//! @param r Red component of color (0.0 - 1.0) +//! @param g Green component of color (0.0 - 1.0) +//! @param b Blue component of color (0.0 - 1.0) +//! @param a Alpha component of color (0.0 - 1.0) +//! @param primLodMin +//! @param primLevel +//----------------------------------------------------------------------------- +void RDP::RDP_SetPrimColor(float r, float g, float b, float a, unsigned int primLodMin, unsigned int primLevel) +{ + int primLodFrac = max(primLevel, primLodMin); + m_combinerMgr->setPrimLodMin(primLodMin); + m_combinerMgr->setPrimLodFrac(primLodFrac / 255.0f); + m_combinerMgr->setPrimColor(r, g, b, a); + m_updateCombineColors = true; +} + +//----------------------------------------------------------------------------- +//* Set Blend Color +//! Sets Blend Color on combiner +//! @param r Red component of color (0.0 - 1.0) +//! @param g Green component of color (0.0 - 1.0) +//! @param b Blue component of color (0.0 - 1.0) +//! @param a Alpha component of color (0.0 - 1.0) +//----------------------------------------------------------------------------- +void RDP::RDP_SetBlendColor(float r, float g, float b, float a) +{ + m_combinerMgr->setBlendColor(r, g, b, a); + m_updateCombineColors = true; +} + +//----------------------------------------------------------------------------- +//* Set Fill Color +//! Sets Fill Color on combiner +//! @param r Red component of color (0.0 - 1.0) +//! @param g Green component of color (0.0 - 1.0) +//! @param b Blue component of color (0.0 - 1.0) +//! @param a Alpha component of color (0.0 - 1.0) +//----------------------------------------------------------------------------- +void RDP::RDP_SetFillColor(float r, float g, float b, float a) +{ + m_combinerMgr->setFillColor(r, g, b, a); + m_updateCombineColors = true; +} + +//----------------------------------------------------------------------------- +//* Set Fog Color +//! Sets fog color used when rendering fog +//! @param r Red component of color (0.0 - 1.0) +//! @param g Green component of color (0.0 - 1.0) +//! @param b Blue component of color (0.0 - 1.0) +//! @param a Alpha component of color (0.0 - 1.0) +//----------------------------------------------------------------------------- +void RDP::RDP_SetFogColor(float r, float g, float b, float a) +{ + m_fogMgr->setFogColor(r, g, b, a); +} + +//***************************************************************************** +// Misc +//***************************************************************************** + +//----------------------------------------------------------------------------- +//! Set Other Mode +//----------------------------------------------------------------------------- +void RDP::RDP_SetOtherMode(MicrocodeArgument* ucode) +{ + unsigned int mode0 = _SHIFTR( ucode->w0, 0, 24 ); + unsigned int mode1 = ucode->w1; + + m_otherMode.h = mode0; + m_otherMode.l = mode1; +} + +//----------------------------------------------------------------------------- +//! Set Prim Depth +//----------------------------------------------------------------------------- +void RDP::RDP_SetPrimDepth(unsigned int dwZ, unsigned int dwDZ) +{ + unsigned int primitiveDepth = dwZ & 0x7FFF; + + //Convert to float + m_primitiveZ = (float)(primitiveDepth)/(float)0x8000; + } + +//----------------------------------------------------------------------------- +//! Set Scissor +//----------------------------------------------------------------------------- +void RDP::RDP_SetScissor(int x0, int y0, int x1, int y1, int mode) +{ + //Get Scale + float vsx = OpenGLManager::getSingleton().getViewScaleX(); + float vsy = OpenGLManager::getSingleton().getViewScaleY(); + + //Get Offset + int offset = 0; //TODO: height offset? + + //Set Scissor + OpenGLManager::getSingleton().setScissor( + x0 * vsx, + (m_vi->getHeight() - y1) * vsy + offset, + (x1 - x0) * vsx, + (y1 - y0) * vsy + ); +} + +//----------------------------------------------------------------------------- +//* Set Full Sync +//! Called when RDP is finished +//----------------------------------------------------------------------------- +void RDP::RDP_FullSync() +{ + this->triggerInterrupt(); +} + +//***************************************************************************** +// Rendering +//***************************************************************************** + +//----------------------------------------------------------------------------- +//* Fill Rect +//! Renders a rectangle +//----------------------------------------------------------------------------- +void RDP::RDP_FillRect(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1) +{ + //Logger::getSingleton() << "RDP_FillRect: " << (int)x0 << " " << (int)y0 << " " << (int)x1 << " " << (int)y1 << "\n"; + + //Increase rectangle size? + if( m_otherMode.cycleType >= G_CYC_COPY ) + { + x1++; + y1++; + } + + //Clear Depth Buffer? + if ( m_depthImageInfo.rdramAddress == m_colorImageInfo.rdramAddress ) + { + //Clear the Z Buffer + updateStates(); + glDepthMask( true ); + glClear(GL_DEPTH_BUFFER_BIT); + + // Depth update + if (m_otherMode.depthUpdate) + { + glDepthMask(GL_TRUE); + } + else + { + glDepthMask(GL_FALSE); + } + + return; + } + + //Clear Color Buffer? + if ( m_otherMode.cycleType == G_CYC_FILL) + { + if ( x0 == 0 && y0 == 0 && x1 == m_vi->getWidth() && y1 == m_vi->getHeight() ) + { + const float* fillColor = m_combinerMgr->getFillColor(); + glClearColor(fillColor[0], fillColor[1], fillColor[2], fillColor[3]); + bool scissor = OpenGLManager::getSingleton().getScissorEnabled(); + OpenGLManager::getSingleton().setScissorEnabled(false); + glClear(GL_COLOR_BUFFER_BIT); + OpenGLManager::getSingleton().setScissorEnabled(scissor); + return; + } + } + + //Update States + this->updateStates(); + + //Ignore fill rects? + if ( ROMDetector::getSingleton().getIgnoreFillRects() ) + { + return; + } + + //Disable Scissor + glDisable( GL_SCISSOR_TEST ); + + //Set Viewport + //int oldViewport[4]; + //glGetIntegerv(GL_VIEWPORT, oldViewport); + //glViewport(0, 0, OpenGLManager::getSingleton().getWidth(), OpenGLManager::getSingleton().getHeight() ); + glDepthRange(0.0f, 1.0f); + + //Get depth and color + float depth = m_otherMode.depthSource == 1 ? m_primitiveZ : 0; //TODO: Use RSP viewport nearz? + float* color = m_otherMode.cycleType == G_CYC_FILL ? m_combinerMgr->getFillColor() : m_combinerMgr->getPrimColor(); + + //Render rectangle + m_openGL2DRenderer->renderQuad(color, x0, y0, x1, y1, depth); + + //Reset viewport + //glViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]); + + //Reset Scissor + glEnable( GL_SCISSOR_TEST ); +} + +//----------------------------------------------------------------------------- +// Texture Rectangle Flip +//----------------------------------------------------------------------------- +void RDP::RDP_TexRectFlip(unsigned int dwXH, unsigned int dwYH, unsigned int dwXL, unsigned int dwYL, + unsigned int tileno, unsigned int dwS, unsigned int dwT, int nDSDX, int nDTDY) +{ + Logger::getSingleton().printMsg("RDP_TexRect"); + + float fS0 = (float)dwS / 32.0f; + float fT0 = (float)dwT / 32.0f; + + float fDSDX = (float)nDSDX / 1024.0f; + float fDTDY = (float)nDTDY / 1024.0f; + + if (m_otherMode.cycleType == G_CYC_COPY) + { + fDSDX /= 4.0f; // In copy mode 4 pixels are copied at once. + dwXH++; + dwYH++; + } + else if (m_otherMode.cycleType == G_CYC_FILL ) + { + dwXH++; + dwYH++; + } + + float fS1 = fS0 + (fDSDX * (dwYH - dwYL)); + float fT1 = fT0 + (fDTDY * (dwXH - dwXL)); + + //Set Current Texture tiles + m_rsp->setTile( m_textureLoader->getTile(tileno), 0); + if ( tileno < 7 ) + { + m_rsp->setTile( m_textureLoader->getTile(tileno + 1), 1); + } + else { + m_rsp->setTile( m_textureLoader->getTile(tileno), 1); + } + + m_texRectWidth = (unsigned int)fS1; + m_texRectHeight = (unsigned int)fT1; + + //Update States + this->updateStates(); + + float t0u0 = 0, t0v0 = 0, t0u1 =0, t0v1 = 0; + if ( m_textureCache->getCurrentTexture(0) ) + { + t0u0 = (fS0) * m_textureCache->getCurrentTexture(0)->shiftScaleS - m_textureLoader->getTile(tileno)->uls; + t0v0 = (fT0) * m_textureCache->getCurrentTexture(0)->shiftScaleT - m_textureLoader->getTile(tileno)->ult; + t0u1 = t0u0 + (fDSDX * (dwYH - dwYL))*m_textureCache->getCurrentTexture(0)->shiftScaleS; + t0v1 = t0v0 + (fDTDY * (dwXH - dwXL))*m_textureCache->getCurrentTexture(0)->shiftScaleT; + } + + _textureRectangleFlip(dwXL, dwYL, dwXH, dwYH, t0u0, t0v0, t0u1, t0v1, tileno); + + //Restore RSP Tile + int rspTile = m_rsp->getTexture().tile; + m_rsp->setTile( m_textureLoader->getTile(tileno), 0); + m_rsp->setTile( m_textureLoader->getTile(rspTile < 7 ? rspTile + 1 : rspTile), 1); +} + +//----------------------------------------------------------------------------- +//* Texture Rect +//! Not this command use 128bits and not 64 bits wich could cause some +//! problems with the program counter. +//----------------------------------------------------------------------------- +void RDP::RDP_TexRect(unsigned int dwXH, unsigned int dwYH, unsigned int dwXL, unsigned int dwYL, + unsigned int tileno, unsigned short dwS, unsigned short dwT, unsigned short nDSDX, unsigned short nDTDY) +{ + Logger::getSingleton().printMsg("RDP_TexRect"); + + glEnable(GL_TEXTURE_2D); + + //Convert to signed + short s16S = *(short*)(&dwS); + short s16T = *(short*)(&dwT); + short s16DSDX = *(short*)(&nDSDX); + short s16DTDY = *(short*)(&nDTDY); + + //Convert to float + float s = s16S / 32.0f; + float t = s16T / 32.0f; + float dsdx = s16DSDX / 1024.0f; + float dtdy = s16DTDY / 1024.0f; + + + float ulx = (float)dwXH; + float uly = (float)dwYH; + float lrx = (float)dwXL; + float lry = (float)dwYL; + + int tile = tileno; + + _textureRectangle(ulx, uly, lrx, lry, tile, s, t, dsdx, dtdy, false); +} + +//***************************************************************************** +// Texturing +//***************************************************************************** + +//----------------------------------------------------------------------------- +//* Set Color Image +//! Sets information about color image +//----------------------------------------------------------------------------- +void RDP::RDP_SetCImg(unsigned int format, unsigned int size, unsigned int width, unsigned int segmentAddress) +{ + m_colorImageInfo.rdramAddress = m_memory->getRDRAMAddress( segmentAddress ); + m_colorImageInfo.format = format; + m_colorImageInfo.size = size; + m_colorImageInfo.width = width + 1; //Note: add plus one + m_colorImageInfo.bpl = m_colorImageInfo.width << m_colorImageInfo.size >> 1; + + if (m_screenUpdatePending) + { + OpenGLManager::getSingleton().endRendering(); + m_screenUpdatePending = false; + } +} + +//----------------------------------------------------------------------------- +//* Set Z Image +//! Sets information about depth image +//----------------------------------------------------------------------------- +void RDP::RDP_SetZImg(unsigned int format, unsigned int size, unsigned int width, unsigned int segmentAddress) +{ + m_depthImageInfo.rdramAddress = m_memory->getRDRAMAddress( segmentAddress ); + m_depthImageInfo.format = format; + m_depthImageInfo.size = size; + m_depthImageInfo.width = width + 1; //Note: add plus one + m_depthImageInfo.bpl = m_colorImageInfo.width << m_colorImageInfo.size >> 1; +} + +//----------------------------------------------------------------------------- +//* Set Texture Image +//! Sets information about texture image +//----------------------------------------------------------------------------- +void RDP::RDP_SetTImg(unsigned int format, unsigned int size, unsigned int width, unsigned int segmentAddress) +{ + m_textureLoader->setTextureImage(format, size, width, segmentAddress); +} + +//----------------------------------------------------------------------------- +// Set Tile +//----------------------------------------------------------------------------- +void RDP::RDP_SetTile(int format, int size, int line, int tmem, int tile, + int palette, int clampS, int clampT, int mirrorS, + int mirrorT, int maskS, int maskT, int shiftS, int shiftT ) +{ + //Set Tile + m_textureLoader->setTile( format, size, line, tmem, tile, palette, + clampS, clampT, mirrorS, mirrorT, maskS, maskT, + shiftS, shiftT ); + + //m_changedTiles = true; ??? Not needed? +} + +//----------------------------------------------------------------------------- +//* Load Tile +//----------------------------------------------------------------------------- +void RDP::RDP_LoadTile(int tile, int s0, int t0, int s1, int t1) +{ + //Load Tile + m_textureLoader->loadTile(tile, s0, t0, s1, t1); + + m_textureMode = TM_NORMAL; + m_loadType = LOADTYPE_TILE; + m_tmemChanged = true; +} + +//----------------------------------------------------------------------------- +// Load Block +//----------------------------------------------------------------------------- +void RDP::RDP_LoadBlock(int tile, int s0, int t0, int s1, int t1) +{ + //Load Block + m_textureLoader->loadBlock(tile, s0, t0, s1, t1); + + m_textureMode = TM_NORMAL; + m_loadType = LOADTYPE_BLOCK; + m_tmemChanged = true; +} + +//----------------------------------------------------------------------------- +//! Sets the size of tile +//! @Param tile Index of the tile to set size on +//! @param s0 Texture Coordinats for first vertex coordinate +//! @param t0 Texture Coordinats for first vertex coordinate +//! @param s1 Texture Coordinats for second vertex coordinate +//! @param t1 Texture Coordinats for second vertex coordinate +//----------------------------------------------------------------------------- +void RDP::RDP_SetTileSize(int tile, unsigned int s0, unsigned int t0, unsigned int s1, unsigned int t1) +{ + m_textureLoader->setTileSize( tile, s0, t0, s1, t1); + + m_changedTiles = true; +} + +//----------------------------------------------------------------------------- +// Load Texture Look Up Table +//----------------------------------------------------------------------------- +void RDP::RDP_LoadTLUT(int tile, int s0, int t0, int s1, int t1) +{ + m_textureLoader->loadTLUT(tile, s0, t0, s1, t1); + + m_tmemChanged = true; +} + +//***************************************************************************** +// Private Functions +//***************************************************************************** + +//----------------------------------------------------------------------------- +// Texture Rectangle +//----------------------------------------------------------------------------- +void RDP::_textureRectangle(float ulx, float uly, float lrx, float lry, int tile, float s, float t, float dsdx, float dtdy,bool flip) +{ + bool zEnabled = OpenGLManager::getSingleton().getZBufferEnabled(); + OpenGLManager::getSingleton().setZBufferEnabled(false); + + //Copy Mode + if ( m_otherMode.cycleType == G_CYC_COPY ) + { + dsdx = 1.0; + lrx += 1.0f; + lry += 1.0f; + } + else if (m_otherMode.cycleType == G_CYC_FILL ) + { + lrx++; + lry++; + } + + //Set Current Texture tiles + m_rsp->setTile( m_textureLoader->getTile(tile), 0); + m_rsp->setTile( m_textureLoader->getTile(tile < 7 ? tile + 1 : tile), 1); + + + float lrs = s + (lrx - ulx - 1) * dsdx; + float lrt = t + (lry - uly - 1) * dtdy; + + //Change mode to texture rectangle + if ( m_textureMode == TM_NORMAL ) + m_textureMode = TM_TEXRECT; + + m_texRectWidth = (unsigned int)(max( lrs, s ) + dsdx); + m_texRectHeight = (unsigned int)(max( lrt, t ) + dtdy); + + //Update States + this->updateStates(); + + //glViewport( 0, 0, OpenGLManager::getSingleton().getWidth(), OpenGLManager::getSingleton().getHeight() ); + + glDisable(GL_SCISSOR_TEST); + + if (lrs > s) + { + if (lrt > t) + OpenGLRenderer::getSingleton().renderTexRect( ulx, uly, lrx, lry, s, t, lrs, lrt, flip ); + else + OpenGLRenderer::getSingleton().renderTexRect( ulx, lry, lrx, uly, s, lrt, lrs, t, flip ); + } + else + { + if (lrt > t) + OpenGLRenderer::getSingleton().renderTexRect( lrx, uly, ulx, lry, lrs, t, s, lrt, flip ); + else + OpenGLRenderer::getSingleton().renderTexRect( lrx, lry, ulx, uly, lrs, lrt, s, t, flip ); + } + + //Restore RSP Tile + int rspTile = m_rsp->getTexture().tile; + m_rsp->setTile( m_textureLoader->getTile( rspTile ), 0); + m_rsp->setTile( m_textureLoader->getTile(rspTile < 7 ? rspTile + 1 : rspTile), 1); + + //glViewport( 0, m_windowMgr->getHeightOffset(), OpenGLManager::getSingleton().getWidth(), OpenGLManager::getSingleton().getHeight() ); + + glEnable(GL_SCISSOR_TEST); + OpenGLManager::getSingleton().setZBufferEnabled(zEnabled); +} + +//----------------------------------------------------------------------------- +//* Texture Rectangle Flip +//! @todo: Clamp Tile +//----------------------------------------------------------------------------- +void RDP::_textureRectangleFlip(int nX0, int nY0, int nX1, int nY1, float fS0, float fT0, float fS1, float fT1, int tile) +{ + //Disable z buffer + bool zEnabled = OpenGLManager::getSingleton().getZBufferEnabled(); + OpenGLManager::getSingleton().setZBufferEnabled(false); + + float widthDiv = (float)m_textureLoader->getTile( m_rsp->getTexture().tile )->getWidth(); + float heightDiv = (float)m_textureLoader->getTile( m_rsp->getTexture().tile )->getHeight(); + + float t0u0 = fS0 / widthDiv; + float t0v0 = fT0 / heightDiv; + float t0u1 = (fS1 - fS0)/ widthDiv + t0u0; + float t0v1 = (fT1 - fT0)/ heightDiv + t0v0; + + float depth = m_otherMode.depthSource == 1 ? m_primitiveZ : 0; //TODO: Use RSP viewport nearz? + + static bool warned = false; + if( t0u0 >= 0 && t0u1 <= 1 && t0u1 >= t0u0 ) + { + //TODO: Clamp Tile + if (!warned) + { + warned = true; + Logger::getSingleton().printMsg("_textureRectangleFlip - unimplemented", M64MSG_WARNING); + } + } + if( t0v0 >= 0 && t0v1 <= 1 && t0v1 >= t0v0 ) + { + //TODO: Clamp tile + if (!warned) + { + warned = true; + Logger::getSingleton().printMsg("_textureRectangleFlip - unimplemented", M64MSG_WARNING); + } + } + + //HACK + if ( ROMDetector::getSingleton().getRomID() == SUPER_MARIO_64 ) + { + t0u0 *= 0.5f; + t0v0 *= 0.5f; + t0u1 *= 0.5f; + t0v1 *= 0.5f; + } + + //glViewport( 0, m_windowMgr->getHeightOffset(), OpenGLManager::getSingleton().getWidth(), OpenGLManager::getSingleton().getHeight() ); + + //Get Color + float color[4] = { 1,1,1,0 }; + this->getCombinerMgr()->getCombinerColor( &color[0] ); + float secondaryColor[4] = { 1,1,1,1 }; + + if ( m_otherMode.cycleType == G_CYC_COPY ) + { + glActiveTextureARB( GL_TEXTURE0_ARB ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + } + + //Disable Scissor + glDisable( GL_SCISSOR_TEST ); + + //Render Quad + m_openGL2DRenderer->renderFlippedTexturedQuad( color, secondaryColor, + (float)nX0, (float)nY0, + (float)nX1, (float)nY1, + depth, + t0u0, t0v0, + t0u1, t0v1, + t0u0, t0v0, + t0u1, t0v1 ); + + //Restore states + glEnable(GL_SCISSOR_TEST); + OpenGLManager::getSingleton().setZBufferEnabled(zEnabled); +}