Path: blob/master/libmupen64plus/mupen64plus-video-rice/src/ConvertImage16.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"2223// Still to be swapped:24// IA162526ConvertFunction gConvertFunctions_16_FullTMEM[ 8 ][ 4 ] =27{28// 4bpp 8bpp 16bpp 32bpp29{ Convert4b_16, Convert8b_16, Convert16b_16, ConvertRGBA32_16 }, // RGBA30{ NULL, NULL, ConvertYUV_16, NULL }, // YUV31{ Convert4b_16, Convert8b_16, NULL, NULL }, // CI32{ Convert4b_16, Convert8b_16, Convert16b_16, NULL }, // IA33{ Convert4b_16, Convert8b_16, Convert16b_16, NULL }, // I34{ NULL, NULL, NULL, NULL }, // ?35{ NULL, NULL, NULL, NULL }, // ?36{ NULL, NULL, NULL, NULL } // ?37};38ConvertFunction gConvertFunctions_16[ 8 ][ 4 ] =39{40// 4bpp 8bpp 16bpp 32bpp41{ ConvertCI4_16, ConvertCI8_16, ConvertRGBA16_16, ConvertRGBA32_16 }, // RGBA42{ NULL, NULL, ConvertYUV_16, NULL }, // YUV43{ ConvertCI4_16, ConvertCI8_16, NULL, NULL }, // CI44{ ConvertIA4_16, ConvertIA8_16, ConvertIA16_16, NULL }, // IA45{ ConvertI4_16, ConvertI8_16, ConvertRGBA16_16, NULL }, // I46{ NULL, NULL, NULL, NULL }, // ?47{ NULL, NULL, NULL, NULL }, // ?48{ NULL, NULL, NULL, NULL } // ?49};5051ConvertFunction gConvertTlutFunctions_16[ 8 ][ 4 ] =52{53// 4bpp 8bpp 16bpp 32bpp54{ ConvertCI4_16, ConvertCI8_16, ConvertRGBA16_16, ConvertRGBA32_16 }, // RGBA55{ NULL, NULL, ConvertYUV_16, NULL }, // YUV56{ ConvertCI4_16, ConvertCI8_16, NULL, NULL }, // CI57{ ConvertCI4_16, ConvertCI8_16, ConvertIA16_16, NULL }, // IA58{ ConvertCI4_16, ConvertCI8_16, ConvertRGBA16_16, NULL }, // I59{ NULL, NULL, NULL, NULL }, // ?60{ NULL, NULL, NULL, NULL }, // ?61{ NULL, NULL, NULL, NULL } // ?62};6364extern bool conkerSwapHack;6566void ConvertRGBA16_16(CTexture *pTexture, const TxtrInfo &tinfo)67{68DrawInfo dInfo;69uint32 x, y;70uint32 nFiddle;7172// Copy of the base pointer73uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);74uint8 * pByteSrc = (uint8 *)pSrc;7576if (!pTexture->StartUpdate(&dInfo))77return;7879if (tinfo.bSwapped)80{81for (y = 0; y < tinfo.HeightToLoad; y++)82{83if ((y%2) == 0)84nFiddle = 0x2;85else86nFiddle = 0x2 | 0x4;8788// dwDst points to start of destination row89uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);9091// DWordOffset points to the current dword we're looking at92// (process 2 pixels at a time). May be a problem if we don't start on even pixel93uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);9495for (x = 0; x < tinfo.WidthToLoad; x++)96{97uint16 w = *(uint16 *)&pByteSrc[dwWordOffset ^ nFiddle];9899wDst[x] = Convert555ToR4G4B4A4(w);100101// Increment word offset to point to the next two pixels102dwWordOffset += 2;103}104}105}106else107{108for (y = 0; y < tinfo.HeightToLoad; y++)109{110// dwDst points to start of destination row111uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);112113// DWordOffset points to the current dword we're looking at114// (process 2 pixels at a time). May be a problem if we don't start on even pixel115uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);116117for (x = 0; x < tinfo.WidthToLoad; x++)118{119uint16 w = *(uint16 *)&pByteSrc[dwWordOffset ^ 0x2];120121wDst[x] = Convert555ToR4G4B4A4(w);122123// Increment word offset to point to the next two pixels124dwWordOffset += 2;125}126}127}128129pTexture->EndUpdate(&dInfo);130pTexture->SetOthersVariables();131}132133void ConvertRGBA32_16(CTexture *pTexture, const TxtrInfo &tinfo)134{135DrawInfo dInfo;136uint32 * pSrc = (uint32*)(tinfo.pPhysicalAddress);137if (!pTexture->StartUpdate(&dInfo))138return;139140if( options.bUseFullTMEM )141{142Tile &tile = gRDP.tiles[tinfo.tileNo];143144uint32 *pWordSrc;145if( tinfo.tileNo >= 0 )146{147pWordSrc = (uint32*)&g_Tmem.g_Tmem64bit[tile.dwTMem];148149for (uint32 y = 0; y < tinfo.HeightToLoad; y++)150{151uint16 * dwDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);152153uint32 nFiddle = ( y&1 )? 0x2 : 0;154int idx = tile.dwLine*4*y;155156for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)157{158uint32 w = pWordSrc[idx^nFiddle];159uint8* psw = (uint8*)&w;160dwDst[x] = R4G4B4A4_MAKE( (psw[0]>>4), (psw[1]>>4), (psw[2]>>4), (psw[3]>>4));161}162}163}164}165else166{167if (tinfo.bSwapped)168{169for (uint32 y = 0; y < tinfo.HeightToLoad; y++)170{171if ((y%2) == 0)172{173uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);174uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);175176for (uint32 x = 0; x < tinfo.WidthToLoad; x++)177{178179*pDst++ = R4G4B4A4_MAKE((pS[3]>>4), // Red180(pS[2]>>4), // Green181(pS[1]>>4), // Blue182(pS[0]>>4)); // Alpha183pS+=4;184}185}186else187{188uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);189uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);190int n;191192n = 0;193for (uint32 x = 0; x < tinfo.WidthToLoad; x++)194{195*pDst++ = R4G4B4A4_MAKE((pS[(n^0x8) + 3]>>4), // Red196(pS[(n^0x8) + 2]>>4), // Green197(pS[(n^0x8) + 1]>>4), // Blue198(pS[(n^0x8) + 0]>>4)); // Alpha199200n += 4;201}202}203}204}205else206{207for (uint32 y = 0; y < tinfo.HeightToLoad; y++)208{209uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);210uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);211212for (uint32 x = 0; x < tinfo.WidthToLoad; x++)213{214*pDst++ = R4G4B4A4_MAKE((pS[3]>>4), // Red215(pS[2]>>4), // Green216(pS[1]>>4), // Blue217(pS[0]>>4)); // Alpha218pS+=4;219}220}221}222}223224pTexture->EndUpdate(&dInfo);225pTexture->SetOthersVariables();226227}228229// E.g. Dear Mario text230// Copy, Score etc231void ConvertIA4_16(CTexture *pTexture, const TxtrInfo &tinfo)232{233DrawInfo dInfo;234uint32 nFiddle;235236uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);237if (!pTexture->StartUpdate(&dInfo))238return;239240if (tinfo.bSwapped)241{242for (uint32 y = 0; y < tinfo.HeightToLoad; y++)243{244uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);245246// For odd lines, swap words too247if ((y%2) == 0)248nFiddle = 0x3;249else250nFiddle = 0x7;251252253// This may not work if X is not even?254uint32 dwByteOffset = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad/2);255256// Do two pixels at a time257for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)258{259uint8 b = pSrc[dwByteOffset ^ nFiddle];260261// Even262*pDst++ = R4G4B4A4_MAKE(ThreeToFour[(b & 0xE0) >> 5],263ThreeToFour[(b & 0xE0) >> 5],264ThreeToFour[(b & 0xE0) >> 5],265OneToFour[(b & 0x10) >> 4]);266267// Odd268*pDst++ = R4G4B4A4_MAKE(ThreeToFour[(b & 0x0E) >> 1],269ThreeToFour[(b & 0x0E) >> 1],270ThreeToFour[(b & 0x0E) >> 1],271OneToFour[(b & 0x01)] );272273dwByteOffset++;274}275}276}277else278{279for (uint32 y = 0; y < tinfo.HeightToLoad; y++)280{281uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);282283// This may not work if X is not even?284uint32 dwByteOffset = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad/2);285286// Do two pixels at a time287for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)288{289uint8 b = pSrc[dwByteOffset ^ 0x3];290291// Even292*pDst++ = R4G4B4A4_MAKE(ThreeToFour[(b & 0xE0) >> 5],293ThreeToFour[(b & 0xE0) >> 5],294ThreeToFour[(b & 0xE0) >> 5],295OneToFour[(b & 0x10) >> 4]);296297// Odd298*pDst++ = R4G4B4A4_MAKE(ThreeToFour[(b & 0x0E) >> 1],299ThreeToFour[(b & 0x0E) >> 1],300ThreeToFour[(b & 0x0E) >> 1],301OneToFour[(b & 0x01)] );302303dwByteOffset++;304}305}306}307308pTexture->EndUpdate(&dInfo);309pTexture->SetOthersVariables();310}311312// E.g Mario's head textures313void ConvertIA8_16(CTexture *pTexture, const TxtrInfo &tinfo)314{315DrawInfo dInfo;316uint32 nFiddle;317318uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);319if (!pTexture->StartUpdate(&dInfo))320return;321322if (tinfo.bSwapped)323{324for (uint32 y = 0; y < tinfo.HeightToLoad; y++)325{326// For odd lines, swap words too327if ((y%2) == 0)328nFiddle = 0x3;329else330nFiddle = 0x7;331332333uint16 *pDst = (uint16 *)((uint8*)dInfo.lpSurface + y * dInfo.lPitch);334// Points to current byte335uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;336337for (uint32 x = 0; x < tinfo.WidthToLoad; x++)338{339uint8 b = pSrc[dwByteOffset ^ nFiddle];340341*pDst++ = R4G4B4A4_MAKE( ((b&0xf0)>>4),((b&0xf0)>>4),((b&0xf0)>>4),(b&0x0f));342343dwByteOffset++;344}345}346}347else348{349for (uint32 y = 0; y < tinfo.HeightToLoad; y++)350{351uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);352353// Points to current byte354uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;355356for (uint32 x = 0; x < tinfo.WidthToLoad; x++)357{358uint8 b = pSrc[dwByteOffset ^ 0x3];359360*pDst++ = R4G4B4A4_MAKE(((b&0xf0)>>4),((b&0xf0)>>4),((b&0xf0)>>4),(b&0x0f));361362dwByteOffset++;363}364}365}366367pTexture->EndUpdate(&dInfo);368pTexture->SetOthersVariables();369370}371372// E.g. camera's clouds, shadows373void ConvertIA16_16(CTexture *pTexture, const TxtrInfo &tinfo)374{375DrawInfo dInfo;376377uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);378uint8 * pByteSrc = (uint8 *)pSrc;379380if (!pTexture->StartUpdate(&dInfo))381return;382383for (uint32 y = 0; y < tinfo.HeightToLoad; y++)384{385uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);386387// Points to current word388uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);389390for (uint32 x = 0; x < tinfo.WidthToLoad; x++)391{392uint16 w = *(uint16 *)&pByteSrc[dwWordOffset^0x2];393394uint8 i = (uint8)(w >> 12);395uint8 a = (uint8)(w & 0xFF);396397*pDst++ = R4G4B4A4_MAKE(i, i, i, (a>>4));398399dwWordOffset += 2;400}401}402403pTexture->EndUpdate(&dInfo);404pTexture->SetOthersVariables();405}406407408409// Used by MarioKart410void ConvertI4_16(CTexture *pTexture, const TxtrInfo &tinfo)411{412DrawInfo dInfo;413uint32 nFiddle;414415uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);416if (!pTexture->StartUpdate(&dInfo))417return;418419if (tinfo.bSwapped)420{421for (uint32 y = 0; y < tinfo.HeightToLoad; y++)422{423uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);424425// Might not work with non-even starting X426uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);427428// For odd lines, swap words too429if( !conkerSwapHack || (y&4) == 0 )430{431if ((y%2) == 0)432nFiddle = 0x3;433else434nFiddle = 0x7;435}436else437{438if ((y%2) == 1)439nFiddle = 0x3;440else441nFiddle = 0x7;442}443444for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)445{446uint8 b = pSrc[dwByteOffset ^ nFiddle];447448// Even449//*pDst++ = R4G4B4A4_MAKE(b>>4, b>>4, b>>4, b>>4);450*pDst++ = FourToSixteen[(b & 0xF0)>>4];451// Odd452//*pDst++ = R4G4B4A4_MAKE(b & 0x0f, b & 0x0f, b & 0x0f, b & 0x0f);453*pDst++ = FourToSixteen[b & 0x0f];454455dwByteOffset++;456}457}458}459else460{461for (uint32 y = 0; y < tinfo.HeightToLoad; y++)462{463uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;464465// Might not work with non-even starting X466uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);467468for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)469{470uint8 b = pSrc[dwByteOffset ^ 0x3];471472// Even473//*pDst++ = R4G4B4A4_MAKE(b>>4, b>>4, b>>4, b>>4);474*pDst++ = FourToEight[(b & 0xF0)>>4];475476// Odd477//*pDst++ = R4G4B4A4_MAKE(b & 0x0f, b & 0x0f, b & 0x0f, b & 0x0f);478*pDst++ = FourToEight[b & 0x0f];479480dwByteOffset++;481}482}483}484485pTexture->EndUpdate(&dInfo);486pTexture->SetOthersVariables();487}488489// Used by MarioKart490void ConvertI8_16(CTexture *pTexture, const TxtrInfo &tinfo)491{492DrawInfo dInfo;493uint32 nFiddle;494495long long pSrc = (long long) (tinfo.pPhysicalAddress);496if (!pTexture->StartUpdate(&dInfo))497return;498499if (tinfo.bSwapped)500{501for (uint32 y = 0; y < tinfo.HeightToLoad; y++)502{503if ((y%2) == 0)504nFiddle = 0x3;505else506nFiddle = 0x7;507508uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);509510uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;511512for (uint32 x = 0; x < tinfo.WidthToLoad; x++)513{514uint8 b = *(uint8*)((pSrc+dwByteOffset)^nFiddle);515516*pDst++ = R4G4B4A4_MAKE(b>>4,517b>>4,518b>>4,519b>>4);520521dwByteOffset++;522}523}524}525else526{527for (uint32 y = 0; y < tinfo.HeightToLoad; y++)528{529uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);530531uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;532533for (uint32 x = 0; x < tinfo.WidthToLoad; x++)534{535uint8 b = *(uint8*)((pSrc+dwByteOffset)^0x3);536537*pDst++ = R4G4B4A4_MAKE(b>>4,538b>>4,539b>>4,540b>>4);541542dwByteOffset++;543}544}545546}547pTexture->EndUpdate(&dInfo);548pTexture->SetOthersVariables();549550}551552553// Used by Starfox intro554void ConvertCI4_RGBA16_16(CTexture *pTexture, const TxtrInfo &tinfo)555{556DrawInfo dInfo;557uint32 nFiddle;558559uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);560uint16 * pPal = (uint16 *)tinfo.PalAddress;561if (!pTexture->StartUpdate(&dInfo))562return;563564if (tinfo.bSwapped)565{566567for (uint32 y = 0; y < tinfo.HeightToLoad; y++)568{569if ((y%2) == 0)570nFiddle = 0x3;571else572nFiddle = 0x7;573574575uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);576577uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);578579for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)580{581uint8 b = pSrc[dwByteOffset ^ nFiddle];582583uint8 bhi = (b&0xf0)>>4;584uint8 blo = (b&0x0f);585586pDst[0] = Convert555ToR4G4B4A4(pPal[bhi^1]); // Remember palette is in different endian order!587pDst[1] = Convert555ToR4G4B4A4(pPal[blo^1]); // Remember palette is in different endian order!588pDst+=2;589590dwByteOffset++;591}592}593594}595else596{597for (uint32 y = 0; y < tinfo.HeightToLoad; y++)598{599uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);600601uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);602603for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)604{605uint8 b = pSrc[dwByteOffset ^ 0x3];606607uint8 bhi = (b&0xf0)>>4;608uint8 blo = (b&0x0f);609610pDst[0] = Convert555ToR4G4B4A4(pPal[bhi^1]); // Remember palette is in different endian order!611pDst[1] = Convert555ToR4G4B4A4(pPal[blo^1]); // Remember palette is in different endian order!612pDst+=2;613614dwByteOffset++;615}616}617}618619pTexture->EndUpdate(&dInfo);620pTexture->SetOthersVariables();621}622623//*****************************************************************************624// Convert CI4 images. We need to switch on the palette type625//*****************************************************************************626void ConvertCI4_16( CTexture * p_texture, const TxtrInfo & tinfo )627{628if ( tinfo.TLutFmt == TLUT_FMT_RGBA16 )629{630ConvertCI4_RGBA16_16( p_texture, tinfo );631}632else if ( tinfo.TLutFmt == TLUT_FMT_IA16 )633{634ConvertCI4_IA16_16( p_texture, tinfo );635}636}637638//*****************************************************************************639// Convert CI8 images. We need to switch on the palette type640//*****************************************************************************641void ConvertCI8_16( CTexture * p_texture, const TxtrInfo & tinfo )642{643if ( tinfo.TLutFmt == TLUT_FMT_RGBA16 )644{645ConvertCI8_RGBA16_16( p_texture, tinfo );646}647else if ( tinfo.TLutFmt == TLUT_FMT_IA16 )648{649ConvertCI8_IA16_16( p_texture, tinfo );650}651}652653// Used by Starfox intro654void ConvertCI4_IA16_16(CTexture *pTexture, const TxtrInfo &tinfo)655{656DrawInfo dInfo;657uint32 nFiddle;658659uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);660uint16 * pPal = (uint16 *)tinfo.PalAddress;661if (!pTexture->StartUpdate(&dInfo))662return;663664if (tinfo.bSwapped)665{666for (uint32 y = 0; y < tinfo.HeightToLoad; y++)667{668if ((y%2) == 0)669nFiddle = 0x3;670else671nFiddle = 0x7;672673uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);674675uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);676677for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)678{679uint8 b = pSrc[dwByteOffset ^ nFiddle];680681uint8 bhi = (b&0xf0)>>4;682uint8 blo = (b&0x0f);683684pDst[0] = ConvertIA16ToR4G4B4A4(pPal[bhi^1]); // Remember palette is in different endian order!685pDst[1] = ConvertIA16ToR4G4B4A4(pPal[blo^1]); // Remember palette is in different endian order!686pDst += 2;687dwByteOffset++;688}689}690}691else692{693for (uint32 y = 0; y < tinfo.HeightToLoad; y++)694{695uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);696697uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);698699for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)700{701uint8 b = pSrc[dwByteOffset ^ 0x3];702703uint8 bhi = (b&0xf0)>>4;704uint8 blo = (b&0x0f);705706pDst[0] = ConvertIA16ToR4G4B4A4(pPal[bhi^1]); // Remember palette is in different endian order!707pDst[1] = ConvertIA16ToR4G4B4A4(pPal[blo^1]); // Remember palette is in different endian order!708pDst+=2;709710dwByteOffset++;711}712}713}714715pTexture->EndUpdate(&dInfo);716pTexture->SetOthersVariables();717}718719720// Used by MarioKart for Cars etc721void ConvertCI8_RGBA16_16(CTexture *pTexture, const TxtrInfo &tinfo)722{723DrawInfo dInfo;724uint32 nFiddle;725726uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);727uint16 * pPal = (uint16 *)tinfo.PalAddress;728if (!pTexture->StartUpdate(&dInfo))729return;730731if (tinfo.bSwapped)732{733for (uint32 y = 0; y < tinfo.HeightToLoad; y++)734{735if ((y%2) == 0)736nFiddle = 0x3;737else738nFiddle = 0x7;739740uint16 *pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);741742uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;743744for (uint32 x = 0; x < tinfo.WidthToLoad; x++)745{746uint8 b = pSrc[dwByteOffset ^ nFiddle];747748*pDst++ = Convert555ToR4G4B4A4(pPal[b^1]); // Remember palette is in different endian order!749750dwByteOffset++;751}752}753}754else755{756for (uint32 y = 0; y < tinfo.HeightToLoad; y++)757{758uint16 *pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);759760uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;761762for (uint32 x = 0; x < tinfo.WidthToLoad; x++)763{764uint8 b = pSrc[dwByteOffset ^ 0x3];765766*pDst++ = Convert555ToR4G4B4A4(pPal[b^1]); // Remember palette is in different endian order!767768dwByteOffset++;769}770}771}772773pTexture->EndUpdate(&dInfo);774pTexture->SetOthersVariables();775}776777778// Used by MarioKart for Cars etc779void ConvertCI8_IA16_16(CTexture *pTexture, const TxtrInfo &tinfo)780{781DrawInfo dInfo;782uint32 nFiddle;783784uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);785uint16 * pPal = (uint16 *)tinfo.PalAddress;786if (!pTexture->StartUpdate(&dInfo))787return;788789if (tinfo.bSwapped)790{791for (uint32 y = 0; y < tinfo.HeightToLoad; y++)792{793if ((y%2) == 0)794nFiddle = 0x3;795else796nFiddle = 0x7;797798uint16 *pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);799800uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;801802for (uint32 x = 0; x < tinfo.WidthToLoad; x++)803{804uint8 b = pSrc[dwByteOffset ^ nFiddle];805806*pDst++ = ConvertIA16ToR4G4B4A4(pPal[b^1]); // Remember palette is in different endian order!807808dwByteOffset++;809}810}811}812else813{814for (uint32 y = 0; y < tinfo.HeightToLoad; y++)815{816uint16 *pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);817818uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;819820for (uint32 x = 0; x < tinfo.WidthToLoad; x++)821{822uint8 b = pSrc[dwByteOffset ^ 0x3];823824*pDst++ = ConvertIA16ToR4G4B4A4(pPal[b^1]); // Remember palette is in different endian order!825826dwByteOffset++;827}828}829}830831pTexture->EndUpdate(&dInfo);832pTexture->SetOthersVariables();833}834835836void ConvertYUV_16(CTexture *pTexture, const TxtrInfo &tinfo)837{838DrawInfo dInfo;839if (!pTexture->StartUpdate(&dInfo))840return;841842uint32 x, y;843uint32 nFiddle;844845if( options.bUseFullTMEM )846{847Tile &tile = gRDP.tiles[tinfo.tileNo];848849uint16 * pSrc;850if( tinfo.tileNo >= 0 )851pSrc = (uint16*)&g_Tmem.g_Tmem64bit[tile.dwTMem];852else853pSrc = (uint16*)(tinfo.pPhysicalAddress);854855uint8 * pByteSrc = (uint8 *)pSrc;856for (y = 0; y < tinfo.HeightToLoad; y++)857{858nFiddle = ( y&1 )? 0x4 : 0;859int dwWordOffset = tinfo.tileNo>=0? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);860uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);861862for (x = 0; x < tinfo.WidthToLoad/2; x++)863{864int y0 = *(uint8*)&pByteSrc[(dwWordOffset+1)^nFiddle];865int y1 = *(uint8*)&pByteSrc[(dwWordOffset+3)^nFiddle];866int u0 = *(uint8*)&pByteSrc[(dwWordOffset )^nFiddle];867int v0 = *(uint8*)&pByteSrc[(dwWordOffset+2)^nFiddle];868869wDst[x*2+0] = ConvertYUV16ToR4G4B4(y0,u0,v0);870wDst[x*2+1] = ConvertYUV16ToR4G4B4(y1,u0,v0);871872dwWordOffset += 4;873}874}875}876else877{878// Copy of the base pointer879uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);880uint8 * pByteSrc = (uint8 *)pSrc;881882883if (tinfo.bSwapped)884{885for (y = 0; y < tinfo.HeightToLoad; y++)886{887if ((y%2) == 0)888nFiddle = 0x2;889else890nFiddle = 0x2 | 0x4;891892// dwDst points to start of destination row893uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);894895// DWordOffset points to the current dword we're looking at896// (process 2 pixels at a time). May be a problem if we don't start on even pixel897uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);898899for (x = 0; x < tinfo.WidthToLoad/2; x++)900{901uint32 y0 = *(uint8*)&pByteSrc[(dwWordOffset+1)^nFiddle];902uint32 y1 = *(uint8*)&pByteSrc[(dwWordOffset+3)^nFiddle];903uint32 u0 = *(uint8*)&pByteSrc[(dwWordOffset )^nFiddle];904uint32 v0 = *(uint8*)&pByteSrc[(dwWordOffset+2)^nFiddle];905906wDst[x*2+0] = ConvertYUV16ToR4G4B4(y0,u0,v0);907wDst[x*2+1] = ConvertYUV16ToR4G4B4(y1,u0,v0);908909dwWordOffset += 4;910}911}912}913else914{915for (y = 0; y < tinfo.HeightToLoad; y++)916{917// dwDst points to start of destination row918uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);919920// DWordOffset points to the current dword we're looking at921// (process 2 pixels at a time). May be a problem if we don't start on even pixel922uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);923924for (x = 0; x < tinfo.WidthToLoad/2; x++)925{926uint32 y0 = *(uint8*)&pByteSrc[(dwWordOffset+1)^3];927uint32 y1 = *(uint8*)&pByteSrc[(dwWordOffset+3)^3];928uint32 u0 = *(uint8*)&pByteSrc[(dwWordOffset )^3];929uint32 v0 = *(uint8*)&pByteSrc[(dwWordOffset+2)^3];930931wDst[x*2+0] = ConvertYUV16ToR4G4B4(y0,u0,v0);932wDst[x*2+1] = ConvertYUV16ToR4G4B4(y1,u0,v0);933934dwWordOffset += 4;935}936}937}938}939940pTexture->EndUpdate(&dInfo);941pTexture->SetOthersVariables();942}943944uint16 ConvertYUV16ToR4G4B4(int Y, int U, int V)945{946uint32 A=1;947uint32 R1 = Y + g_convk0 * V;948uint32 G1 = Y + g_convk1 * U + g_convk2 * V;949uint32 B1 = Y + g_convk3 * U;950uint32 R = (R1 - g_convk4) * g_convk5 + R1;951uint32 G = (G1 - g_convk4) * g_convk5 + G1;952uint32 B = (B1 - g_convk4) * g_convk5 + B1;953return (uint16)R4G4B4A4_MAKE((R>>4), (G>>4), (B>>4), 0xF*A);954}955956957// Used by Starfox intro958void Convert4b_16(CTexture *pTexture, const TxtrInfo &tinfo)959{960DrawInfo dInfo;961962if (!pTexture->StartUpdate(&dInfo))963return;964965uint16 * pPal = (uint16 *)tinfo.PalAddress;966bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);967if( tinfo.Format <= TXT_FMT_CI ) bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);968969Tile &tile = gRDP.tiles[tinfo.tileNo];970971uint8 *pByteSrc = tinfo.tileNo >= 0 ? (uint8*)&g_Tmem.g_Tmem64bit[tile.dwTMem] : (uint8*)(tinfo.pPhysicalAddress);972973for (uint32 y = 0; y < tinfo.HeightToLoad; y++)974{975uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);976977uint32 nFiddle;978if( tinfo.tileNo < 0 )979{980if (tinfo.bSwapped)981{982if ((y%2) == 0)983nFiddle = 0x3;984else985nFiddle = 0x7;986}987else988{989nFiddle = 3;990}991}992else993{994nFiddle = ( y&1 )? 0x4 : 0;995}996997int idx = tinfo.tileNo>=0 ? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);998999for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2, idx++)1000{1001uint8 b = pByteSrc[idx^nFiddle];1002uint8 bhi = (b&0xf0)>>4;1003uint8 blo = (b&0x0f);10041005if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )1006{1007if( tinfo.TLutFmt == TLUT_FMT_IA16 )1008{1009if( tinfo.tileNo>=0 )1010{1011pDst[0] = ConvertIA16ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);1012pDst[1] = ConvertIA16ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(blo<<2)]);1013}1014else1015{1016pDst[0] = ConvertIA16ToR4G4B4A4(pPal[bhi^1]);1017pDst[1] = ConvertIA16ToR4G4B4A4(pPal[blo^1]);1018}1019}1020else1021{1022if( tinfo.tileNo>=0 )1023{1024pDst[0] = Convert555ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);1025pDst[1] = Convert555ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(blo<<2)]);1026}1027else1028{1029pDst[0] = Convert555ToR4G4B4A4(pPal[bhi^1]);1030pDst[1] = Convert555ToR4G4B4A4(pPal[blo^1]);1031}1032}1033}1034else if( tinfo.Format == TXT_FMT_IA )1035{1036pDst[0] = ConvertIA4ToR4G4B4A4(b>>4);1037pDst[1] = ConvertIA4ToR4G4B4A4(b&0xF);1038}1039else //if( tinfo.Format == TXT_FMT_I )1040{1041pDst[0] = ConvertI4ToR4G4B4A4(b>>4);1042pDst[1] = ConvertI4ToR4G4B4A4(b&0xF);1043}10441045if( bIgnoreAlpha )1046{1047pDst[0] |= 0xF000;1048pDst[1] |= 0xF000;1049}1050pDst+=2;1051}1052}10531054pTexture->EndUpdate(&dInfo);1055pTexture->SetOthersVariables();1056}10571058void Convert8b_16(CTexture *pTexture, const TxtrInfo &tinfo)1059{1060DrawInfo dInfo;1061if (!pTexture->StartUpdate(&dInfo))1062return;106310641065uint16 * pPal = (uint16 *)tinfo.PalAddress;1066bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);1067if( tinfo.Format <= TXT_FMT_CI ) bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);10681069Tile &tile = gRDP.tiles[tinfo.tileNo];10701071uint8 *pByteSrc;1072if( tinfo.tileNo >= 0 )1073pByteSrc = (uint8*)&g_Tmem.g_Tmem64bit[tile.dwTMem];1074else1075pByteSrc = (uint8*)(tinfo.pPhysicalAddress);107610771078for (uint32 y = 0; y < tinfo.HeightToLoad; y++)1079{1080uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);10811082uint32 nFiddle;1083if( tinfo.tileNo < 0 )1084{1085if (tinfo.bSwapped)1086{1087if ((y%2) == 0)1088nFiddle = 0x3;1089else1090nFiddle = 0x7;1091}1092else1093{1094nFiddle = 3;1095}1096}1097else1098{1099nFiddle = ( y&1 )? 0x4 : 0;1100}11011102int idx = tinfo.tileNo>=0? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;11031104for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)1105{1106uint8 b = pByteSrc[idx^nFiddle];11071108if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )1109{1110if( tinfo.TLutFmt == TLUT_FMT_IA16 )1111{1112if( tinfo.tileNo>=0 )1113*pDst = ConvertIA16ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+(b<<2)]);1114else1115*pDst = ConvertIA16ToR4G4B4A4(pPal[b^1]);1116}1117else1118{1119if( tinfo.tileNo>=0 )1120*pDst = Convert555ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+(b<<2)]);1121else1122*pDst = Convert555ToR4G4B4A4(pPal[b^1]);1123}1124}1125else if( tinfo.Format == TXT_FMT_IA )1126{1127*pDst = R4G4B4A4_MAKE( ((b&0xf0)>>4),((b&0xf0)>>4),((b&0xf0)>>4),(b&0x0f));1128}1129else //if( tinfo.Format == TXT_FMT_I )1130{1131*pDst = R4G4B4A4_MAKE(b>>4, b>>4, b>>4, b>>4);1132}11331134if( bIgnoreAlpha )1135{1136*pDst |= 0xFF000000;1137}1138pDst++;1139}1140}11411142pTexture->EndUpdate(&dInfo);1143pTexture->SetOthersVariables();1144}114511461147void Convert16b_16(CTexture *pTexture, const TxtrInfo &tinfo)1148{1149DrawInfo dInfo;1150if (!pTexture->StartUpdate(&dInfo))1151return;11521153Tile &tile = gRDP.tiles[tinfo.tileNo];11541155uint16 *pWordSrc;1156if( tinfo.tileNo >= 0 )1157pWordSrc = (uint16*)&g_Tmem.g_Tmem64bit[tile.dwTMem];1158else1159pWordSrc = (uint16*)(tinfo.pPhysicalAddress);116011611162for (uint32 y = 0; y < tinfo.HeightToLoad; y++)1163{1164uint16 * dwDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);11651166uint32 nFiddle;1167if( tinfo.tileNo < 0 )1168{1169if (tinfo.bSwapped)1170{1171if ((y&1) == 0)1172nFiddle = 0x1;1173else1174nFiddle = 0x3;1175}1176else1177{1178nFiddle = 0x1;1179}1180}1181else1182{1183nFiddle = ( y&1 )? 0x2 : 0;1184}11851186int idx = tinfo.tileNo>=0? tile.dwLine*4*y : (((y+tinfo.TopToLoad) * tinfo.Pitch)>>1) + tinfo.LeftToLoad;11871188for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)1189{1190uint16 w = pWordSrc[idx^nFiddle];1191uint16 w2 = tinfo.tileNo>=0? ((w>>8)|(w<<8)) : w;11921193if( tinfo.Format == TXT_FMT_RGBA )1194{1195dwDst[x] = Convert555ToR4G4B4A4(w2);1196}1197else if( tinfo.Format == TXT_FMT_YUV )1198{1199}1200else if( tinfo.Format >= TXT_FMT_IA )1201{1202uint8 i = (uint8)(w2 >> 12);1203uint8 a = (uint8)(w2 & 0xFF);1204dwDst[x] = R4G4B4A4_MAKE(i, i, i, (a>>4));1205}1206}1207}12081209pTexture->EndUpdate(&dInfo);1210pTexture->SetOthersVariables();1211}1212121312141215