Path: blob/master/libmupen64plus/mupen64plus-video-rice/src/ConvertImage.cpp
2 views
/*1Copyright (C) 2003 Rice196423This program is free software; you can redistribute it and/or4modify it under the terms of the GNU General Public License5as published by the Free Software Foundation; either version 26of the License, or (at your option) any later version.78This program is distributed in the hope that it will be useful,9but WITHOUT ANY WARRANTY; without even the implied warranty of10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11GNU General Public License for more details.1213You should have received a copy of the GNU General Public License14along with this program; if not, write to the Free Software15Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.1617*/1819#include "Config.h"20#include "ConvertImage.h"21#include "RenderBase.h"2223ConvertFunction gConvertFunctions_FullTMEM[ 8 ][ 4 ] =24{25// 4bpp 8bpp 16bpp 32bpp26{ Convert4b, Convert8b, Convert16b, ConvertRGBA32 }, // RGBA27{ NULL, NULL, ConvertYUV, NULL }, // YUV28{ Convert4b, Convert8b, NULL, NULL }, // CI29{ Convert4b, Convert8b, Convert16b, NULL }, // IA30{ Convert4b, Convert8b, Convert16b, NULL }, // I31{ NULL, NULL, NULL, NULL }, // ?32{ NULL, NULL, NULL, NULL }, // ?33{ NULL, NULL, NULL, NULL } // ?34};35ConvertFunction gConvertFunctions[ 8 ][ 4 ] =36{37// 4bpp 8bpp 16bpp 32bpp38{ ConvertCI4, ConvertCI8, ConvertRGBA16, ConvertRGBA32 }, // RGBA39{ NULL, NULL, ConvertYUV, NULL }, // YUV40{ ConvertCI4, ConvertCI8, NULL, NULL }, // CI41{ ConvertIA4, ConvertIA8, ConvertIA16, NULL }, // IA42{ ConvertI4, ConvertI8, ConvertIA16, NULL }, // I43{ NULL, NULL, NULL, NULL }, // ?44{ NULL, NULL, NULL, NULL }, // ?45{ NULL, NULL, NULL, NULL } // ?46};4748ConvertFunction gConvertTlutFunctions[ 8 ][ 4 ] =49{50// 4bpp 8bpp 16bpp 32bpp51{ ConvertCI4, ConvertCI8, ConvertRGBA16, ConvertRGBA32 }, // RGBA52{ NULL, NULL, ConvertYUV, NULL }, // YUV53{ ConvertCI4, ConvertCI8, NULL, NULL }, // CI54{ ConvertCI4, ConvertCI8, ConvertIA16, NULL }, // IA55{ ConvertCI4, ConvertCI8, ConvertIA16, NULL }, // I56{ NULL, NULL, NULL, NULL }, // ?57{ NULL, NULL, NULL, NULL }, // ?58{ NULL, NULL, NULL, NULL } // ?59};6061extern bool conkerSwapHack;6263void ConvertRGBA16(CTexture *pTexture, const TxtrInfo &tinfo)64{65DrawInfo dInfo;6667// Copy of the base pointer68uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);6970uint8 * pByteSrc = (uint8 *)pSrc;71if (!pTexture->StartUpdate(&dInfo))72return;7374uint32 nFiddle;7576if (tinfo.bSwapped)77{78for (uint32 y = 0; y < tinfo.HeightToLoad; y++)79{80if ((y&1) == 0)81nFiddle = 0x2;82else83nFiddle = 0x2 | 0x4;8485// dwDst points to start of destination row86uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);8788// DWordOffset points to the current dword we're looking at89// (process 2 pixels at a time). May be a problem if we don't start on even pixel90uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);9192for (uint32 x = 0; x < tinfo.WidthToLoad; x++)93{94uint16 w = *(uint16 *)&pByteSrc[dwWordOffset ^ nFiddle];9596dwDst[x] = Convert555ToRGBA(w);9798// Increment word offset to point to the next two pixels99dwWordOffset += 2;100}101}102}103else104{105for (uint32 y = 0; y < tinfo.HeightToLoad; y++)106{107// dwDst points to start of destination row108uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);109110// DWordOffset points to the current dword we're looking at111// (process 2 pixels at a time). May be a problem if we don't start on even pixel112uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);113114for (uint32 x = 0; x < tinfo.WidthToLoad; x++)115{116uint16 w = *(uint16 *)&pByteSrc[dwWordOffset ^ 0x2];117118dwDst[x] = Convert555ToRGBA(w);119120// Increment word offset to point to the next two pixels121dwWordOffset += 2;122}123}124}125126pTexture->EndUpdate(&dInfo);127pTexture->SetOthersVariables();128}129130void ConvertRGBA32(CTexture *pTexture, const TxtrInfo &tinfo)131{132DrawInfo dInfo;133if (!pTexture->StartUpdate(&dInfo))134return;135136uint32 * pSrc = (uint32*)(tinfo.pPhysicalAddress);137138if( options.bUseFullTMEM )139{140Tile &tile = gRDP.tiles[tinfo.tileNo];141142uint32 *pWordSrc;143if( tinfo.tileNo >= 0 )144{145pWordSrc = (uint32*)&g_Tmem.g_Tmem64bit[tile.dwTMem];146147for (uint32 y = 0; y < tinfo.HeightToLoad; y++)148{149uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);150151uint32 nFiddle = ( y&1 )? 0x2 : 0;152int idx = tile.dwLine*4*y;153154for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)155{156uint32 w = pWordSrc[idx^nFiddle];157uint8* psw = (uint8*)&w;158uint8* pdw = (uint8*)&dwDst[x];159pdw[0] = psw[2]; // Blue160pdw[1] = psw[1]; // Green161pdw[2] = psw[0]; // Red162pdw[3] = psw[3]; // Alpha163}164}165}166}167else168{169if (tinfo.bSwapped)170{171for (uint32 y = 0; y < tinfo.HeightToLoad; y++)172{173if ((y%2) == 0)174{175uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;176uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);177178for (uint32 x = 0; x < tinfo.WidthToLoad; x++)179{180pDst[0] = pS[1]; // Blue181pDst[1] = pS[2]; // Green182pDst[2] = pS[3]; // Red183pDst[3] = pS[0]; // Alpha184pS+=4;185pDst+=4;186}187}188else189{190uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);191uint8 *pS = (uint8 *)pSrc;192int n;193194n = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);195for (uint32 x = 0; x < tinfo.WidthToLoad; x++)196{197*pDst++ = COLOR_RGBA(pS[(n+3)^0x8],198pS[(n+2)^0x8],199pS[(n+1)^0x8],200pS[(n+0)^0x8]);201202n += 4;203}204}205}206}207else208{209for (uint32 y = 0; y < tinfo.HeightToLoad; y++)210{211uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;212uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);213214for (uint32 x = 0; x < tinfo.WidthToLoad; x++)215{216pDst[0] = pS[1]; // Blue217pDst[1] = pS[2]; // Green218pDst[2] = pS[3]; // Red219pDst[3] = pS[0]; // Alpha220pS+=4;221pDst+=4;222}223}224}225}226227pTexture->EndUpdate(&dInfo);228pTexture->SetOthersVariables();229}230231// E.g. Dear Mario text232// Copy, Score etc233void ConvertIA4(CTexture *pTexture, const TxtrInfo &tinfo)234{235DrawInfo dInfo;236uint32 nFiddle;237238uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);239240#ifdef DEBUGGER241if (((long long)pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");242#endif243244if (!pTexture->StartUpdate(&dInfo))245return;246247if (tinfo.bSwapped)248{249for (uint32 y = 0; y < tinfo.HeightToLoad; y++)250{251uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;252253// For odd lines, swap words too254if ((y%2) == 0)255nFiddle = 0x3;256else257nFiddle = 0x7;258259260// This may not work if X is not even?261uint32 dwByteOffset = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad/2);262263if (tinfo.WidthToLoad == 1)264{265// corner case266uint8 b = pSrc[dwByteOffset ^ nFiddle];267*pDst++ = ThreeToEight[(b & 0xE0) >> 5];268*pDst++ = ThreeToEight[(b & 0xE0) >> 5];269*pDst++ = ThreeToEight[(b & 0xE0) >> 5];270*pDst++ = OneToEight[(b & 0x10) >> 4];271}272else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)273{274// Do two pixels at a time275uint8 b = pSrc[dwByteOffset ^ nFiddle];276277// Even278*pDst++ = ThreeToEight[(b & 0xE0) >> 5];279*pDst++ = ThreeToEight[(b & 0xE0) >> 5];280*pDst++ = ThreeToEight[(b & 0xE0) >> 5];281*pDst++ = OneToEight[(b & 0x10) >> 4];282// Odd283*pDst++ = ThreeToEight[(b & 0x0E) >> 1];284*pDst++ = ThreeToEight[(b & 0x0E) >> 1];285*pDst++ = ThreeToEight[(b & 0x0E) >> 1];286*pDst++ = OneToEight[(b & 0x01) ];287288dwByteOffset++;289}290}291}292else293{294for (uint32 y = 0; y < tinfo.HeightToLoad; y++)295{296uint8 *pDst = (uint8 *)dInfo.lpSurface + (y * dInfo.lPitch);297298// This may not work if X is not even?299uint32 dwByteOffset = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad/2);300301if (tinfo.WidthToLoad == 1)302{303// corner case304uint8 b = pSrc[dwByteOffset ^ 0x3];305*pDst++ = ThreeToEight[(b & 0xE0) >> 5];306*pDst++ = ThreeToEight[(b & 0xE0) >> 5];307*pDst++ = ThreeToEight[(b & 0xE0) >> 5];308*pDst++ = OneToEight[(b & 0x10) >> 4];309}310else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)311{312// Do two pixels at a time313uint8 b = pSrc[dwByteOffset ^ 0x3];314315// Even316*pDst++ = ThreeToEight[(b & 0xE0) >> 5];317*pDst++ = ThreeToEight[(b & 0xE0) >> 5];318*pDst++ = ThreeToEight[(b & 0xE0) >> 5];319*pDst++ = OneToEight[(b & 0x10) >> 4];320// Odd321*pDst++ = ThreeToEight[(b & 0x0E) >> 1];322*pDst++ = ThreeToEight[(b & 0x0E) >> 1];323*pDst++ = ThreeToEight[(b & 0x0E) >> 1];324*pDst++ = OneToEight[(b & 0x01) ];325326dwByteOffset++;327}328}329}330331pTexture->EndUpdate(&dInfo);332pTexture->SetOthersVariables();333334}335336// E.g Mario's head textures337void ConvertIA8(CTexture *pTexture, const TxtrInfo &tinfo)338{339DrawInfo dInfo;340uint32 nFiddle;341342uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);343344#ifdef DEBUGGER345if (((long long)pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");346#endif347348if (!pTexture->StartUpdate(&dInfo))349return;350351if (tinfo.bSwapped)352{353for (uint32 y = 0; y < tinfo.HeightToLoad; y++)354{355// For odd lines, swap words too356if ((y%2) == 0)357nFiddle = 0x3;358else359nFiddle = 0x7;360361uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;362// Points to current byte363uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;364365for (uint32 x = 0; x < tinfo.WidthToLoad; x++)366{367uint8 b = pSrc[dwByteOffset ^ nFiddle];368uint8 I = FourToEight[(b & 0xf0)>>4];369370*pDst++ = I;371*pDst++ = I;372*pDst++ = I;373*pDst++ = FourToEight[(b & 0x0f) ];374375dwByteOffset++;376}377}378}379else380{381register const uint8* FourToEightArray = &FourToEight[0];382for (uint32 y = 0; y < tinfo.HeightToLoad; y++)383{384uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;385386// Points to current byte387uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;388389for (uint32 x = 0; x < tinfo.WidthToLoad; x++)390{391register uint8 b = pSrc[(dwByteOffset++) ^ 0x3];392uint8 I = *(FourToEightArray+(b>>4));393394*pDst++ = I;395*pDst++ = I;396*pDst++ = I;397*pDst++ = *(FourToEightArray+(b&0xF));398}399}400}401402pTexture->EndUpdate(&dInfo);403pTexture->SetOthersVariables();404405}406407// E.g. camera's clouds, shadows408void ConvertIA16(CTexture *pTexture, const TxtrInfo &tinfo)409{410DrawInfo dInfo;411uint32 nFiddle;412413uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);414uint8 * pByteSrc = (uint8 *)pSrc;415416if (!pTexture->StartUpdate(&dInfo))417return;418419if (tinfo.bSwapped)420{421for (uint32 y = 0; y < tinfo.HeightToLoad; y++)422{423uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;424425if ((y%2) == 0)426nFiddle = 0x2;427else428nFiddle = 0x4 | 0x2;429430// Points to current word431uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);432433for (uint32 x = 0; x < tinfo.WidthToLoad; x++)434{435uint16 w = *(uint16 *)&pByteSrc[dwWordOffset^nFiddle];436437*pDst++ = (uint8)(w >> 8);438*pDst++ = (uint8)(w >> 8);439*pDst++ = (uint8)(w >> 8);440*pDst++ = (uint8)(w & 0xFF);441442dwWordOffset += 2;443}444}445}446else447{448for (uint32 y = 0; y < tinfo.HeightToLoad; y++)449{450uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;451452// Points to current word453uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);454455for (uint32 x = 0; x < tinfo.WidthToLoad; x++)456{457uint16 w = *(uint16 *)&pByteSrc[dwWordOffset^0x2];458459*pDst++ = (uint8)(w >> 8);460*pDst++ = (uint8)(w >> 8);461*pDst++ = (uint8)(w >> 8);462*pDst++ = (uint8)(w & 0xFF);463464dwWordOffset += 2;465}466}467}468469470pTexture->EndUpdate(&dInfo);471pTexture->SetOthersVariables();472}473474475476// Used by MarioKart477void ConvertI4(CTexture *pTexture, const TxtrInfo &tinfo)478{479DrawInfo dInfo;480uint32 nFiddle;481482uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);483484#ifdef DEBUGGER485if (((long long) pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");486#endif487488if (!pTexture->StartUpdate(&dInfo))489return;490491if (tinfo.bSwapped)492{493for (uint32 y = 0; y < tinfo.HeightToLoad; y++)494{495uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;496497// Might not work with non-even starting X498uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);499500// For odd lines, swap words too501if( !conkerSwapHack || (y&4) == 0 )502{503if ((y%2) == 0)504nFiddle = 0x3;505else506nFiddle = 0x7;507}508else509{510if ((y%2) == 1)511nFiddle = 0x3;512else513nFiddle = 0x7;514}515516if (tinfo.WidthToLoad == 1)517{518// corner case519uint8 b = pSrc[dwByteOffset ^ nFiddle];520*pDst++ = FourToEight[(b & 0xF0)>>4];521*pDst++ = FourToEight[(b & 0xF0)>>4];522*pDst++ = FourToEight[(b & 0xF0)>>4];523*pDst++ = FourToEight[(b & 0xF0)>>4];524}525else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)526{527// two pixels at a time528uint8 b = pSrc[dwByteOffset ^ nFiddle];529530// Even531*pDst++ = FourToEight[(b & 0xF0)>>4]; // Other implementations seem to or in (b&0xF0)>>4532*pDst++ = FourToEight[(b & 0xF0)>>4]; // why?533*pDst++ = FourToEight[(b & 0xF0)>>4];534*pDst++ = FourToEight[(b & 0xF0)>>4];535// Odd536*pDst++ = FourToEight[(b & 0x0F)];537*pDst++ = FourToEight[(b & 0x0F)];538*pDst++ = FourToEight[(b & 0x0F)];539*pDst++ = FourToEight[(b & 0x0F)];540541dwByteOffset++;542}543}544545conkerSwapHack = false;546}547else548{549for (uint32 y = 0; y < tinfo.HeightToLoad; y++)550{551uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;552553// Might not work with non-even starting X554uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);555556if (tinfo.WidthToLoad == 1)557{558// corner case559uint8 b = pSrc[dwByteOffset ^ 0x3];560*pDst++ = FourToEight[(b & 0xF0)>>4];561*pDst++ = FourToEight[(b & 0xF0)>>4];562*pDst++ = FourToEight[(b & 0xF0)>>4];563*pDst++ = FourToEight[(b & 0xF0)>>4];564}565else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)566{567// two pixels at a time568uint8 b = pSrc[dwByteOffset ^ 0x3];569570// Even571*pDst++ = FourToEight[(b & 0xF0)>>4]; // Other implementations seem to or in (b&0xF0)>>4572*pDst++ = FourToEight[(b & 0xF0)>>4]; // why?573*pDst++ = FourToEight[(b & 0xF0)>>4];574*pDst++ = FourToEight[(b & 0xF0)>>4];575// Odd576*pDst++ = FourToEight[(b & 0x0F)];577*pDst++ = FourToEight[(b & 0x0F)];578*pDst++ = FourToEight[(b & 0x0F)];579*pDst++ = FourToEight[(b & 0x0F)];580581dwByteOffset++;582}583}584}585586pTexture->EndUpdate(&dInfo);587pTexture->SetOthersVariables();588}589590// Used by MarioKart591void ConvertI8(CTexture *pTexture, const TxtrInfo &tinfo)592{593DrawInfo dInfo;594uint32 nFiddle;595596long long pSrc = (long long) tinfo.pPhysicalAddress;597if (!pTexture->StartUpdate(&dInfo))598return;599600if (tinfo.bSwapped)601{602for (uint32 y = 0; y < tinfo.HeightToLoad; y++)603{604if ((y%2) == 0)605nFiddle = 0x3;606else607nFiddle = 0x7;608609uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;610611uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;612613for (uint32 x = 0; x < tinfo.WidthToLoad; x++)614{615uint8 b = *(uint8*)((pSrc+dwByteOffset)^nFiddle);616617*pDst++ = b;618*pDst++ = b;619*pDst++ = b;620*pDst++ = b; // Alpha not 255?621622dwByteOffset++;623}624}625}626else627{628for (uint32 y = 0; y < tinfo.HeightToLoad; y++)629{630uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;631632uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;633634for (uint32 x = 0; x < tinfo.WidthToLoad; x++)635{636uint8 b = *(uint8*)((pSrc+dwByteOffset)^0x3);637638*pDst++ = b;639*pDst++ = b;640*pDst++ = b;641*pDst++ = b; // Alpha not 255?642643dwByteOffset++;644}645}646}647648pTexture->EndUpdate(&dInfo);649pTexture->SetOthersVariables();650651}652653//*****************************************************************************654// Convert CI4 images. We need to switch on the palette type655//*****************************************************************************656void ConvertCI4( CTexture * p_texture, const TxtrInfo & tinfo )657{658if ( tinfo.TLutFmt == TLUT_FMT_RGBA16 )659{660ConvertCI4_RGBA16( p_texture, tinfo );661}662else if ( tinfo.TLutFmt == TLUT_FMT_IA16 )663{664ConvertCI4_IA16( p_texture, tinfo );665}666}667668//*****************************************************************************669// Convert CI8 images. We need to switch on the palette type670//*****************************************************************************671void ConvertCI8( CTexture * p_texture, const TxtrInfo & tinfo )672{673if ( tinfo.TLutFmt == TLUT_FMT_RGBA16 )674{675ConvertCI8_RGBA16( p_texture, tinfo );676}677else if ( tinfo.TLutFmt == TLUT_FMT_IA16 )678{679ConvertCI8_IA16( p_texture, tinfo );680}681}682683// Used by Starfox intro684void ConvertCI4_RGBA16(CTexture *pTexture, const TxtrInfo &tinfo)685{686DrawInfo dInfo;687uint32 nFiddle;688689uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);690uint16 * pPal = (uint16 *)tinfo.PalAddress;691bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);692693if (!pTexture->StartUpdate(&dInfo))694return;695696if (tinfo.bSwapped)697{698for (uint32 y = 0; y < tinfo.HeightToLoad; y++)699{700if ((y%2) == 0)701nFiddle = 0x3;702else703nFiddle = 0x7;704705uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);706707uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch);708709if (tinfo.WidthToLoad == 1)710{711// corner case712uint8 b = pSrc[dwByteOffset ^ nFiddle];713uint8 bhi = (b&0xf0)>>4;714*pDst = Convert555ToRGBA(pPal[bhi^1]); // Remember palette is in different endian order!715if( bIgnoreAlpha )716{717*pDst |= 0xFF000000;718}719}720else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)721{722// two at a time723uint8 b = pSrc[dwByteOffset ^ nFiddle];724725uint8 bhi = (b&0xf0)>>4;726uint8 blo = (b&0x0f);727728pDst[0] = Convert555ToRGBA(pPal[bhi^1]); // Remember palette is in different endian order!729pDst[1] = Convert555ToRGBA(pPal[blo^1]); // Remember palette is in different endian order!730731if( bIgnoreAlpha )732{733pDst[0] |= 0xFF000000;734pDst[1] |= 0xFF000000;735}736737pDst+=2;738739dwByteOffset++;740}741}742}743else744{745for (uint32 y = 0; y < tinfo.HeightToLoad; y++)746{747uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);748749uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);750751if (tinfo.WidthToLoad == 1)752{753// corner case754uint8 b = pSrc[dwByteOffset ^ 0x3];755uint8 bhi = (b&0xf0)>>4;756*pDst = Convert555ToRGBA(pPal[bhi^1]); // Remember palette is in different endian order!757if( bIgnoreAlpha )758{759*pDst |= 0xFF000000;760}761}762else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)763{764// two at a time765uint8 b = pSrc[dwByteOffset ^ 0x3];766767uint8 bhi = (b&0xf0)>>4;768uint8 blo = (b&0x0f);769770pDst[0] = Convert555ToRGBA(pPal[bhi^1]); // Remember palette is in different endian order!771pDst[1] = Convert555ToRGBA(pPal[blo^1]); // Remember palette is in different endian order!772773if( bIgnoreAlpha )774{775pDst[0] |= 0xFF000000;776pDst[1] |= 0xFF000000;777}778779pDst+=2;780781dwByteOffset++;782}783}784}785pTexture->EndUpdate(&dInfo);786pTexture->SetOthersVariables();787}788789// Used by Starfox intro790void ConvertCI4_IA16(CTexture *pTexture, const TxtrInfo &tinfo)791{792DrawInfo dInfo;793uint32 nFiddle;794795uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);796797#ifdef DEBUGGER798if (((long long) pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");799#endif800801uint16 * pPal = (uint16 *)tinfo.PalAddress;802bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);803804if (!pTexture->StartUpdate(&dInfo))805return;806807if (tinfo.bSwapped)808{809for (uint32 y = 0; y < tinfo.HeightToLoad; y++)810{811if ((y%2) == 0)812nFiddle = 0x3;813else814nFiddle = 0x7;815816uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);817818uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);819820if (tinfo.WidthToLoad == 1)821{822// corner case823uint8 b = pSrc[dwByteOffset ^ nFiddle];824uint8 bhi = (b&0xf0)>>4;825*pDst = ConvertIA16ToRGBA(pPal[bhi^1]); // Remember palette is in different endian order!826if( bIgnoreAlpha )827*pDst |= 0xFF000000;828}829else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)830{831// two at a time832uint8 b = pSrc[dwByteOffset ^ nFiddle];833834uint8 bhi = (b&0xf0)>>4;835uint8 blo = (b&0x0f);836837pDst[0] = ConvertIA16ToRGBA(pPal[bhi^1]); // Remember palette is in different endian order!838pDst[1] = ConvertIA16ToRGBA(pPal[blo^1]); // Remember palette is in different endian order!839840if( bIgnoreAlpha )841{842pDst[0] |= 0xFF000000;843pDst[1] |= 0xFF000000;844}845846pDst+=2;847848dwByteOffset++;849}850}851}852else853{854for (uint32 y = 0; y < tinfo.HeightToLoad; y++)855{856uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);857858uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);859860if (tinfo.WidthToLoad == 1)861{862// corner case863uint8 b = pSrc[dwByteOffset ^ 0x3];864uint8 bhi = (b&0xf0)>>4;865*pDst = ConvertIA16ToRGBA(pPal[bhi^1]); // Remember palette is in different endian order!866if( bIgnoreAlpha )867*pDst |= 0xFF000000;868}869else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)870{871// two pixels at a time872uint8 b = pSrc[dwByteOffset ^ 0x3];873874uint8 bhi = (b&0xf0)>>4;875uint8 blo = (b&0x0f);876877pDst[0] = ConvertIA16ToRGBA(pPal[bhi^1]); // Remember palette is in different endian order!878pDst[1] = ConvertIA16ToRGBA(pPal[blo^1]); // Remember palette is in different endian order!879880if( bIgnoreAlpha )881{882pDst[0] |= 0xFF000000;883pDst[1] |= 0xFF000000;884}885886pDst+=2;887888dwByteOffset++;889}890}891}892pTexture->EndUpdate(&dInfo);893pTexture->SetOthersVariables();894}895896897// Used by MarioKart for Cars etc898void ConvertCI8_RGBA16(CTexture *pTexture, const TxtrInfo &tinfo)899{900DrawInfo dInfo;901uint32 nFiddle;902903uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);904905#ifdef DEBUGGER906if (((long long) pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");907#endif908909uint16 * pPal = (uint16 *)tinfo.PalAddress;910bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);911912if (!pTexture->StartUpdate(&dInfo))913return;914915if (tinfo.bSwapped)916{917for (uint32 y = 0; y < tinfo.HeightToLoad; y++)918{919if ((y%2) == 0)920nFiddle = 0x3;921else922nFiddle = 0x7;923924uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);925926uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;927928for (uint32 x = 0; x < tinfo.WidthToLoad; x++)929{930uint8 b = pSrc[dwByteOffset ^ nFiddle];931932*pDst++ = Convert555ToRGBA(pPal[b^1]); // Remember palette is in different endian order!933934if( bIgnoreAlpha )935{936*(pDst-1) |= 0xFF000000;937}938939dwByteOffset++;940}941}942}943else944{945for (uint32 y = 0; y < tinfo.HeightToLoad; y++)946{947uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);948949int dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;950951for (uint32 x = 0; x < tinfo.WidthToLoad; x++)952{953uint8 b = pSrc[dwByteOffset ^ 0x3];954955*pDst++ = Convert555ToRGBA(pPal[b^1]); // Remember palette is in different endian order!956if( bIgnoreAlpha )957{958*(pDst-1) |= 0xFF000000;959}960961dwByteOffset++;962}963}964}965966pTexture->EndUpdate(&dInfo);967pTexture->SetOthersVariables();968969}970971972// Used by MarioKart for Cars etc973void ConvertCI8_IA16(CTexture *pTexture, const TxtrInfo &tinfo)974{975DrawInfo dInfo;976uint32 nFiddle;977978uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);979980#ifdef DEBUGGER981if (((long long) pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");982#endif983984uint16 * pPal = (uint16 *)tinfo.PalAddress;985bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);986987if (!pTexture->StartUpdate(&dInfo))988return;989990if (tinfo.bSwapped)991{992for (uint32 y = 0; y < tinfo.HeightToLoad; y++)993{994if ((y%2) == 0)995nFiddle = 0x3;996else997nFiddle = 0x7;998999uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);10001001uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;10021003for (uint32 x = 0; x < tinfo.WidthToLoad; x++)1004{1005uint8 b = pSrc[dwByteOffset ^ nFiddle];10061007*pDst++ = ConvertIA16ToRGBA(pPal[b^1]); // Remember palette is in different endian order!1008if( bIgnoreAlpha )1009{1010*(pDst-1) |= 0xFF000000;1011}10121013dwByteOffset++;1014}1015}1016}1017else1018{1019for (uint32 y = 0; y < tinfo.HeightToLoad; y++)1020{1021uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);10221023uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;10241025for (uint32 x = 0; x < tinfo.WidthToLoad; x++)1026{1027uint8 b = pSrc[dwByteOffset ^ 0x3];10281029*pDst++ = ConvertIA16ToRGBA(pPal[b^1]); // Remember palette is in different endian order!1030if( bIgnoreAlpha )1031{1032*(pDst-1) |= 0xFF000000;1033}10341035dwByteOffset++;1036}1037}1038}10391040pTexture->EndUpdate(&dInfo);1041pTexture->SetOthersVariables();1042}10431044void ConvertYUV(CTexture *pTexture, const TxtrInfo &tinfo)1045{1046DrawInfo dInfo;1047if (!pTexture->StartUpdate(&dInfo))1048return;10491050uint32 x, y;1051uint32 nFiddle;10521053if( options.bUseFullTMEM )1054{1055Tile &tile = gRDP.tiles[tinfo.tileNo];10561057uint16 * pSrc;1058if( tinfo.tileNo >= 0 )1059pSrc = (uint16*)&g_Tmem.g_Tmem64bit[tile.dwTMem];1060else1061pSrc = (uint16*)(tinfo.pPhysicalAddress);10621063uint8 * pByteSrc = (uint8 *)pSrc;1064for (y = 0; y < tinfo.HeightToLoad; y++)1065{1066nFiddle = ( y&1 )? 0x4 : 0;1067int dwWordOffset = tinfo.tileNo>=0? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);1068uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);10691070for (x = 0; x < tinfo.WidthToLoad/2; x++)1071{1072int y0 = *(uint8*)&pByteSrc[(dwWordOffset+1)^nFiddle];1073int y1 = *(uint8*)&pByteSrc[(dwWordOffset+3)^nFiddle];1074int u0 = *(uint8*)&pByteSrc[(dwWordOffset )^nFiddle];1075int v0 = *(uint8*)&pByteSrc[(dwWordOffset+2)^nFiddle];10761077dwDst[x*2+0] = ConvertYUV16ToR8G8B8(y0,u0,v0);1078dwDst[x*2+1] = ConvertYUV16ToR8G8B8(y1,u0,v0);10791080dwWordOffset += 4;1081}1082}1083}1084else1085{1086uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);1087uint8 * pByteSrc = (uint8 *)pSrc;10881089if (tinfo.bSwapped)1090{1091for (y = 0; y < tinfo.HeightToLoad; y++)1092{1093if ((y&1) == 0)1094nFiddle = 0x3;1095else1096nFiddle = 0x7;10971098// dwDst points to start of destination row1099uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);11001101// DWordOffset points to the current dword we're looking at1102// (process 2 pixels at a time). May be a problem if we don't start on even pixel1103uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);11041105for (x = 0; x < tinfo.WidthToLoad/2; x++)1106{1107int y0 = *(uint8*)&pByteSrc[(dwWordOffset+2)^nFiddle];1108int v0 = *(uint8*)&pByteSrc[(dwWordOffset+1)^nFiddle];1109int y1 = *(uint8*)&pByteSrc[(dwWordOffset )^nFiddle];1110int u0 = *(uint8*)&pByteSrc[(dwWordOffset+3)^nFiddle];11111112dwDst[x*2+0] = ConvertYUV16ToR8G8B8(y0,u0,v0);1113dwDst[x*2+1] = ConvertYUV16ToR8G8B8(y1,u0,v0);11141115dwWordOffset += 4;1116}1117}1118}1119else1120{1121for (y = 0; y < tinfo.HeightToLoad; y++)1122{1123// dwDst points to start of destination row1124uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);1125uint32 dwByteOffset = y * 32;11261127for (x = 0; x < tinfo.WidthToLoad/2; x++)1128{1129int y0 = *(uint8*)&pByteSrc[(dwByteOffset+2)];1130int v0 = *(uint8*)&pByteSrc[(dwByteOffset+1)];1131int y1 = *(uint8*)&pByteSrc[(dwByteOffset )];1132int u0 = *(uint8*)&pByteSrc[(dwByteOffset+3)];11331134dwDst[x*2+0] = ConvertYUV16ToR8G8B8(y0,u0,v0);1135dwDst[x*2+1] = ConvertYUV16ToR8G8B8(y1,u0,v0);11361137// Increment word offset to point to the next two pixels1138dwByteOffset += 4;1139}1140}1141}1142}11431144pTexture->EndUpdate(&dInfo);1145pTexture->SetOthersVariables();1146}11471148uint32 ConvertYUV16ToR8G8B8(int Y, int U, int V)1149{1150/*1151int R = int(g_convc0 *(Y-16) + g_convc1 * V);1152int G = int(g_convc0 *(Y-16) + g_convc2 * U - g_convc3 * V);1153int B = int(g_convc0 *(Y-16) + g_convc4 * U);1154*/11551156Y += 80;1157int R = int(Y + (1.370705f * (V-128)));1158int G = int(Y - (0.698001f * (V-128)) - (0.337633f * (U-128)));1159int B = int(Y + (1.732446f * (U-128)));11601161R = R < 0 ? 0 : (R>255 ? 255 : R);1162G = G < 0 ? 0 : (G>255 ? 255 : G);1163B = B < 0 ? 0 : (B>255 ? 255 : B);11641165return COLOR_RGBA(R, G, B, 0xFF);1166}116711681169// Used by Starfox intro1170void Convert4b(CTexture *pTexture, const TxtrInfo &tinfo)1171{1172DrawInfo dInfo;11731174if (!pTexture->StartUpdate(&dInfo))1175return;11761177uint16 * pPal = (uint16 *)tinfo.PalAddress;1178bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);1179if( tinfo.Format <= TXT_FMT_CI ) bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);11801181Tile &tile = gRDP.tiles[tinfo.tileNo];11821183uint8 *pByteSrc = tinfo.tileNo >= 0 ? (uint8*)&g_Tmem.g_Tmem64bit[tile.dwTMem] : (uint8*)(tinfo.pPhysicalAddress);11841185for (uint32 y = 0; y < tinfo.HeightToLoad; y++)1186{1187uint32 nFiddle;1188if( tinfo.tileNo < 0 )1189{1190if (tinfo.bSwapped)1191{1192if ((y%2) == 0)1193nFiddle = 0x3;1194else1195nFiddle = 0x7;1196}1197else1198{1199nFiddle = 3;1200}1201}1202else1203{1204nFiddle = ( y&1 )? 0x4 : 0;1205}12061207uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);1208int idx = tinfo.tileNo>=0 ? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);12091210if (tinfo.WidthToLoad == 1)1211{1212// corner case1213uint8 b = pByteSrc[idx^nFiddle];1214uint8 bhi = (b&0xf0)>>4;1215if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )1216{1217if( tinfo.TLutFmt == TLUT_FMT_IA16 )1218{1219if( tinfo.tileNo>=0 )1220*pDst = ConvertIA16ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);1221else1222*pDst = ConvertIA16ToRGBA(pPal[bhi^1]);1223}1224else1225{1226if( tinfo.tileNo>=0 )1227*pDst = Convert555ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);1228else1229*pDst = Convert555ToRGBA(pPal[bhi^1]);1230}1231}1232else if( tinfo.Format == TXT_FMT_IA )1233*pDst = ConvertIA4ToRGBA(b>>4);1234else // if( tinfo.Format == TXT_FMT_I )1235*pDst = ConvertI4ToRGBA(b>>4);1236if( bIgnoreAlpha )1237*pDst |= 0xFF000000;1238}1239else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2, idx++)1240{1241// two pixels at a time1242uint8 b = pByteSrc[idx^nFiddle];1243uint8 bhi = (b&0xf0)>>4;1244uint8 blo = (b&0x0f);12451246if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )1247{1248if( tinfo.TLutFmt == TLUT_FMT_IA16 )1249{1250if( tinfo.tileNo>=0 )1251{1252pDst[0] = ConvertIA16ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);1253pDst[1] = ConvertIA16ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(blo<<2)]);1254}1255else1256{1257pDst[0] = ConvertIA16ToRGBA(pPal[bhi^1]);1258pDst[1] = ConvertIA16ToRGBA(pPal[blo^1]);1259}1260}1261else1262{1263if( tinfo.tileNo>=0 )1264{1265pDst[0] = Convert555ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);1266pDst[1] = Convert555ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(blo<<2)]);1267}1268else1269{1270pDst[0] = Convert555ToRGBA(pPal[bhi^1]);1271pDst[1] = Convert555ToRGBA(pPal[blo^1]);1272}1273}1274}1275else if( tinfo.Format == TXT_FMT_IA )1276{1277pDst[0] = ConvertIA4ToRGBA(b>>4);1278pDst[1] = ConvertIA4ToRGBA(b&0xF);1279}1280else // if( tinfo.Format == TXT_FMT_I )1281{1282pDst[0] = ConvertI4ToRGBA(b>>4);1283pDst[1] = ConvertI4ToRGBA(b&0xF);1284}12851286if( bIgnoreAlpha )1287{1288pDst[0] |= 0xFF000000;1289pDst[1] |= 0xFF000000;1290}1291pDst+=2;1292}1293}12941295pTexture->EndUpdate(&dInfo);1296pTexture->SetOthersVariables();1297}12981299void Convert8b(CTexture *pTexture, const TxtrInfo &tinfo)1300{1301DrawInfo dInfo;1302if (!pTexture->StartUpdate(&dInfo))1303return;13041305uint16 * pPal = (uint16 *)tinfo.PalAddress;1306bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);1307if( tinfo.Format <= TXT_FMT_CI ) bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);13081309Tile &tile = gRDP.tiles[tinfo.tileNo];13101311uint8 *pByteSrc;1312if( tinfo.tileNo >= 0 )1313{1314pByteSrc = (uint8*)&g_Tmem.g_Tmem64bit[tile.dwTMem];1315}1316else1317{1318pByteSrc = (uint8*)(tinfo.pPhysicalAddress);1319}132013211322for (uint32 y = 0; y < tinfo.HeightToLoad; y++)1323{1324uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);13251326uint32 nFiddle;1327if( tinfo.tileNo < 0 )1328{1329if (tinfo.bSwapped)1330{1331if ((y%2) == 0)1332nFiddle = 0x3;1333else1334nFiddle = 0x7;1335}1336else1337{1338nFiddle = 3;1339}1340}1341else1342{1343nFiddle = ( y&1 )? 0x4 : 0;1344}134513461347int idx = tinfo.tileNo>=0? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;13481349for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)1350{1351uint8 b = pByteSrc[idx^nFiddle];13521353if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )1354{1355if( tinfo.TLutFmt == TLUT_FMT_IA16 )1356{1357if( tinfo.tileNo>=0 )1358*pDst = ConvertIA16ToRGBA(g_Tmem.g_Tmem16bit[0x400+(b<<2)]);1359else1360*pDst = ConvertIA16ToRGBA(pPal[b^1]);1361}1362else1363{1364if( tinfo.tileNo>=0 )1365*pDst = Convert555ToRGBA(g_Tmem.g_Tmem16bit[0x400+(b<<2)]);1366else1367*pDst = Convert555ToRGBA(pPal[b^1]);1368}1369}1370else if( tinfo.Format == TXT_FMT_IA )1371{1372uint8 I = FourToEight[(b & 0xf0)>>4];1373uint8 * pByteDst = (uint8*)pDst;1374pByteDst[0] = I;1375pByteDst[1] = I;1376pByteDst[2] = I;1377pByteDst[3] = FourToEight[(b & 0x0f) ];1378}1379else // if( tinfo.Format == TXT_FMT_I )1380{1381uint8 * pByteDst = (uint8*)pDst;1382pByteDst[0] = b;1383pByteDst[1] = b;1384pByteDst[2] = b;1385pByteDst[3] = b;1386}13871388if( bIgnoreAlpha )1389{1390*pDst |= 0xFF000000;1391}1392pDst++;1393}1394}13951396pTexture->EndUpdate(&dInfo);1397pTexture->SetOthersVariables();1398}139914001401void Convert16b(CTexture *pTexture, const TxtrInfo &tinfo)1402{1403DrawInfo dInfo;1404if (!pTexture->StartUpdate(&dInfo))1405return;14061407Tile &tile = gRDP.tiles[tinfo.tileNo];14081409uint16 *pWordSrc;1410if( tinfo.tileNo >= 0 )1411pWordSrc = (uint16*)&g_Tmem.g_Tmem64bit[tile.dwTMem];1412else1413pWordSrc = (uint16*)(tinfo.pPhysicalAddress);141414151416for (uint32 y = 0; y < tinfo.HeightToLoad; y++)1417{1418uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);14191420uint32 nFiddle;1421if( tinfo.tileNo < 0 )1422{1423if (tinfo.bSwapped)1424{1425if ((y&1) == 0)1426nFiddle = 0x1;1427else1428nFiddle = 0x3;1429}1430else1431{1432nFiddle = 0x1;1433}1434}1435else1436{1437nFiddle = ( y&1 )? 0x2 : 0;1438}143914401441int idx = tinfo.tileNo>=0? tile.dwLine*4*y : (((y+tinfo.TopToLoad) * tinfo.Pitch)>>1) + tinfo.LeftToLoad;14421443for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)1444{1445uint16 w = pWordSrc[idx^nFiddle];1446uint16 w2 = tinfo.tileNo>=0? ((w>>8)|(w<<8)) : w;14471448if( tinfo.Format == TXT_FMT_RGBA )1449{1450dwDst[x] = Convert555ToRGBA(w2);1451}1452else if( tinfo.Format == TXT_FMT_YUV )1453{1454}1455else if( tinfo.Format >= TXT_FMT_IA )1456{1457uint8 * pByteDst = (uint8*)&dwDst[x];1458*pByteDst++ = (uint8)(w2 >> 8);1459*pByteDst++ = (uint8)(w2 >> 8);1460*pByteDst++ = (uint8)(w2 >> 8);1461*pByteDst++ = (uint8)(w2 & 0xFF);1462}1463}1464}14651466pTexture->EndUpdate(&dInfo);1467pTexture->SetOthersVariables();1468}1469147014711472