diff options
Diffstat (limited to 'guilib/TextureBundleXPR.cpp')
-rw-r--r-- | guilib/TextureBundleXPR.cpp | 507 |
1 files changed, 0 insertions, 507 deletions
diff --git a/guilib/TextureBundleXPR.cpp b/guilib/TextureBundleXPR.cpp deleted file mode 100644 index cab3256d8b..0000000000 --- a/guilib/TextureBundleXPR.cpp +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright (C) 2005-2010 Team XBMC - * http://www.xbmc.org - * - * 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, 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 XBMC; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "system.h" -#include "TextureBundleXPR.h" -#include "Texture.h" -#include "GraphicContext.h" -#include "DirectXGraphics.h" -#include "utils/log.h" -#ifndef _LINUX -#include <sys/stat.h> -#include "utils/CharsetConverter.h" -#include "lib/liblzo/LZO1X.H" -#else -#include <lzo/lzo1x.h> -#endif -#include "addons/Skin.h" -#include "GUISettings.h" -#include "Util.h" -#include "FileSystem/SpecialProtocol.h" -#include "utils/EndianSwap.h" - -#if !defined(__GNUC__) -#pragma comment(lib,"../../xbmc/lib/liblzo/lzo.lib") -#endif - -// alignment of file blocks - should be a multiple of the sector size of the disk and a power of 2 -// HDD sector = 512 bytes, DVD/CD sector = 2048 bytes -#undef ALIGN -#define ALIGN (512) - - -enum XPR_FLAGS -{ - XPRFLAG_PALETTE = 0x00000001, - XPRFLAG_ANIM = 0x00000002 -}; - -class CAutoBuffer -{ - BYTE* p; -public: - CAutoBuffer() { p = 0; } - explicit CAutoBuffer(size_t s) { p = (BYTE*)malloc(s); } - ~CAutoBuffer() { free(p); } -operator BYTE*() { return p; } - void Set(BYTE* buf) { free(p); p = buf; } - bool Resize(size_t s); -void Release() { p = 0; } -}; - -bool CAutoBuffer::Resize(size_t s) -{ - if (s == 0) - { - if (!p) - return false; - free(p); - p = 0; - return true; - } - void* q = realloc(p, s); - if (q) - { - p = (BYTE*)q; - return true; - } - return false; -} - -// as above but for texture allocation (do not change from XPhysicalAlloc!) -class CAutoTexBuffer -{ - BYTE* p; -public: - CAutoTexBuffer() { p = 0; } - explicit CAutoTexBuffer(size_t s) { p = (BYTE*)XPhysicalAlloc(s, MAXULONG_PTR, 128, PAGE_READWRITE); } - ~CAutoTexBuffer() { if (p) XPhysicalFree(p); } -operator BYTE*() { return p; } - BYTE* Set(BYTE* buf) { if (p) XPhysicalFree(p); return p = buf; } -void Release() { p = 0; } -}; - -CTextureBundleXPR::CTextureBundleXPR(void) -{ - m_hFile = NULL; - m_themeBundle = false; -} - -CTextureBundleXPR::~CTextureBundleXPR(void) -{ - if (m_hFile != NULL) - fclose(m_hFile); -} - -bool CTextureBundleXPR::OpenBundle() -{ - DWORD AlignedSize; - DWORD HeaderSize; - int Version; - XPR_HEADER* pXPRHeader; - - if (m_hFile != NULL) - Cleanup(); - - CStdString strPath; - - if (m_themeBundle) - { - // if we are the theme bundle, we only load if the user has chosen - // a valid theme (or the skin has a default one) - CStdString theme = g_guiSettings.GetString("lookandfeel.skintheme"); - if (!theme.IsEmpty() && theme.CompareNoCase("SKINDEFAULT")) - { - CStdString themeXPR(CUtil::ReplaceExtension(theme, ".xpr")); - strPath = CUtil::AddFileToFolder(g_graphicsContext.GetMediaDir(), "media"); - strPath = CUtil::AddFileToFolder(strPath, themeXPR); - } - else - return false; - } - else - strPath = CUtil::AddFileToFolder(g_graphicsContext.GetMediaDir(), "media/Textures.xpr"); - - strPath = PTH_IC(strPath); - -#ifndef _LINUX - CStdStringW strPathW; - g_charsetConverter.utf8ToW(_P(strPath), strPathW, false); - m_hFile = _wfopen(strPathW.c_str(), L"rb"); -#else - m_hFile = fopen(strPath.c_str(), "rb"); -#endif - if (m_hFile == NULL) - return false; - - struct stat fileStat; - if (fstat(fileno(m_hFile), &fileStat) == -1) - return false; - m_TimeStamp = fileStat.st_mtime; - - CAutoBuffer HeaderBuf(ALIGN); - DWORD n; - - n = fread(HeaderBuf, 1, ALIGN, m_hFile); - if (n < ALIGN) - goto LoadError; - - pXPRHeader = (XPR_HEADER*)(BYTE*)HeaderBuf; - pXPRHeader->dwMagic = Endian_SwapLE32(pXPRHeader->dwMagic); - Version = (pXPRHeader->dwMagic >> 24) - '0'; - pXPRHeader->dwMagic -= Version << 24; - Version &= 0x0f; - - if (pXPRHeader->dwMagic != XPR_MAGIC_VALUE || Version < 2) - goto LoadError; - - HeaderSize = Endian_SwapLE32(pXPRHeader->dwHeaderSize); - AlignedSize = (HeaderSize - 1) & ~(ALIGN - 1); // align to sector, but remove the first sector - HeaderBuf.Resize(AlignedSize + ALIGN); - - if (fseek(m_hFile, ALIGN, SEEK_SET) == -1) - goto LoadError; - n = fread(HeaderBuf + ALIGN, 1, AlignedSize, m_hFile); - if (n < ALIGN) - goto LoadError; - - struct DiskFileHeader_t - { - char Name[116]; - DWORD Offset; - DWORD UnpackedSize; - DWORD PackedSize; - } - *FileHeader; - FileHeader = (DiskFileHeader_t*)(HeaderBuf + sizeof(XPR_HEADER)); - - n = (HeaderSize - sizeof(XPR_HEADER)) / sizeof(DiskFileHeader_t); - for (unsigned i = 0; i < n; ++i) - { - std::pair<CStdString, FileHeader_t> entry; - entry.first = Normalize(FileHeader[i].Name); - entry.second.Offset = Endian_SwapLE32(FileHeader[i].Offset); - entry.second.UnpackedSize = Endian_SwapLE32(FileHeader[i].UnpackedSize); - entry.second.PackedSize = Endian_SwapLE32(FileHeader[i].PackedSize); - m_FileHeaders.insert(entry); - } - - if (lzo_init() != LZO_E_OK) - goto LoadError; - - return true; - -LoadError: - CLog::Log(LOGERROR, "Unable to load file: %s: %s", strPath.c_str(), strerror(errno)); - fclose(m_hFile); - m_hFile = NULL; - - return false; -} - -void CTextureBundleXPR::Cleanup() -{ - if (m_hFile != NULL) - fclose(m_hFile); - m_hFile = NULL; - - m_FileHeaders.clear(); -} - -bool CTextureBundleXPR::HasFile(const CStdString& Filename) -{ - if (m_hFile == NULL && !OpenBundle()) - return false; - - struct stat fileStat; - if (fstat(fileno(m_hFile), &fileStat) == -1) - return false; - if (fileStat.st_mtime > m_TimeStamp) - { - CLog::Log(LOGINFO, "Texture bundle has changed, reloading"); - Cleanup(); - if (!OpenBundle()) - return false; - } - - CStdString name = Normalize(Filename); - return m_FileHeaders.find(name) != m_FileHeaders.end(); -} - -void CTextureBundleXPR::GetTexturesFromPath(const CStdString &path, std::vector<CStdString> &textures) -{ - if (path.GetLength() > 1 && path[1] == ':') - return; - - if (m_hFile == NULL && !OpenBundle()) - return; - - CStdString testPath = Normalize(path); - if (!CUtil::HasSlashAtEnd(testPath)) - testPath += "\\"; - int testLength = testPath.GetLength(); - std::map<CStdString, FileHeader_t>::iterator it; - for (it = m_FileHeaders.begin(); it != m_FileHeaders.end(); it++) - { - if (it->first.Left(testLength).Equals(testPath)) - textures.push_back(it->first); - } -} - -bool CTextureBundleXPR::LoadFile(const CStdString& Filename, CAutoTexBuffer& UnpackedBuf) -{ - CStdString name = Normalize(Filename); - - std::map<CStdString, FileHeader_t>::iterator file = m_FileHeaders.find(name); - if (file == m_FileHeaders.end()) - return false; - - // found texture - allocate the necessary buffers - DWORD ReadSize = (file->second.PackedSize + (ALIGN - 1)) & ~(ALIGN - 1); - BYTE *buffer = (BYTE*)malloc(ReadSize); - - if (!buffer || !UnpackedBuf.Set((BYTE*)XPhysicalAlloc(file->second.UnpackedSize, MAXULONG_PTR, 128, PAGE_READWRITE))) - { // failed due to lack of memory -#ifndef _LINUX - MEMORYSTATUS stat; - GlobalMemoryStatus(&stat); - CLog::Log(LOGERROR, "Out of memory loading texture: %s (need %lu bytes, have %lu bytes)", name.c_str(), - file->second.UnpackedSize + file->second.PackedSize, stat.dwAvailPhys); -#elif defined(__APPLE__) - CLog::Log(LOGERROR, "Out of memory loading texture: %s (need %d bytes)", name.c_str(), - file->second.UnpackedSize + file->second.PackedSize); -#else - struct sysinfo info; - sysinfo(&info); - CLog::Log(LOGERROR, "Out of memory loading texture: %s " - "(need %u bytes, have %lu bytes)", - name.c_str(), file->second.UnpackedSize + file->second.PackedSize, - info.totalram); -#endif - free(buffer); - return false; - } - - // read the file into our buffer - DWORD n; - fseek(m_hFile, file->second.Offset, SEEK_SET); - n = fread(buffer, 1, ReadSize, m_hFile); - if (n < ReadSize && !feof(m_hFile)) - { - CLog::Log(LOGERROR, "Error loading texture: %s: %s", Filename.c_str(), strerror(ferror(m_hFile))); - free(buffer); - return false; - } - - // allocate a buffer for our unpacked texture - lzo_uint s = file->second.UnpackedSize; - bool success = true; - if (lzo1x_decompress(buffer, file->second.PackedSize, UnpackedBuf, &s, NULL) != LZO_E_OK || - s != file->second.UnpackedSize) - { - CLog::Log(LOGERROR, "Error loading texture: %s: Decompression error", Filename.c_str()); - success = false; - } - - try - { - free(buffer); - } - catch (...) - { - CLog::Log(LOGERROR, "Error freeing preload buffer."); - } - - return success; -} - -bool CTextureBundleXPR::LoadTexture(const CStdString& Filename, CBaseTexture** ppTexture, - int &width, int &height) -{ - DWORD ResDataOffset; - *ppTexture = NULL; - - CAutoTexBuffer UnpackedBuf; - if (!LoadFile(Filename, UnpackedBuf)) - return false; - - D3DTexture *pTex = (D3DTexture *)(new char[sizeof (D3DTexture)]); - D3DPalette* pPal = 0; - void* ResData = 0; - - WORD RealSize[2]; - - enum XPR_FLAGS - { - XPRFLAG_PALETTE = 0x00000001, - XPRFLAG_ANIM = 0x00000002 - }; - - BYTE* Next = UnpackedBuf; - - DWORD flags = Endian_SwapLE32(*(DWORD*)Next); - Next += sizeof(DWORD); - if ((flags & XPRFLAG_ANIM) || (flags >> 16) > 1) - goto PackedLoadError; - - if (flags & XPRFLAG_PALETTE) - Next += sizeof(D3DPalette); - - memcpy(pTex, Next, sizeof(D3DTexture)); - pTex->Common = Endian_SwapLE32(pTex->Common); - pTex->Data = Endian_SwapLE32(pTex->Data); - pTex->Lock = Endian_SwapLE32(pTex->Lock); - pTex->Format = Endian_SwapLE32(pTex->Format); - pTex->Size = Endian_SwapLE32(pTex->Size); - Next += sizeof(D3DTexture); - - memcpy(RealSize, Next, 4); - Next += 4; - - ResDataOffset = ((Next - UnpackedBuf) + 127) & ~127; - ResData = UnpackedBuf + ResDataOffset; - - if ((pTex->Common & D3DCOMMON_TYPE_MASK) != D3DCOMMON_TYPE_TEXTURE) - goto PackedLoadError; - - GetTextureFromData(pTex, ResData, ppTexture); - delete[] pTex; - - width = Endian_SwapLE16(RealSize[0]); - height = Endian_SwapLE16(RealSize[1]); -/* DXMERGE - this was previously used to specify the format of the image - probably only affects directx? -#ifndef HAS_SDL - D3DSURFACE_DESC desc; - (*ppTexture)->GetLevelDesc(0, &desc); - pInfo->Format = desc.Format; -#endif -*/ - return true; - -PackedLoadError: - CLog::Log(LOGERROR, "Error loading texture: %s: Invalid data", Filename.c_str()); - delete[] pTex; - delete pPal; - return false; -} - -int CTextureBundleXPR::LoadAnim(const CStdString& Filename, CBaseTexture*** ppTextures, - int &width, int &height, int& nLoops, int** ppDelays) -{ - DWORD ResDataOffset; - int nTextures = 0; - - *ppTextures = NULL; *ppDelays = NULL; - - CAutoTexBuffer UnpackedBuf; - if (!LoadFile(Filename, UnpackedBuf)) - return 0; - - struct AnimInfo_t - { - DWORD nLoops; - WORD RealSize[2]; - } - *pAnimInfo; - - D3DTexture** ppTex = 0; - void* ResData = 0; - - BYTE* Next = UnpackedBuf; - - DWORD flags = Endian_SwapLE32(*(DWORD*)Next); - Next += sizeof(DWORD); - if (!(flags & XPRFLAG_ANIM)) - goto PackedAnimError; - - pAnimInfo = (AnimInfo_t*)Next; - Next += sizeof(AnimInfo_t); - nLoops = Endian_SwapLE32(pAnimInfo->nLoops); - - if (flags & XPRFLAG_PALETTE) - Next += sizeof(D3DPalette); - - nTextures = flags >> 16; - ppTex = new D3DTexture * [nTextures]; - *ppDelays = new int[nTextures]; - for (int i = 0; i < nTextures; ++i) - { - ppTex[i] = (D3DTexture *)(new char[sizeof (D3DTexture)+ sizeof (DWORD)]); - - memcpy(ppTex[i], Next, sizeof(D3DTexture)); - ppTex[i]->Common = Endian_SwapLE32(ppTex[i]->Common); - ppTex[i]->Data = Endian_SwapLE32(ppTex[i]->Data); - ppTex[i]->Lock = Endian_SwapLE32(ppTex[i]->Lock); - ppTex[i]->Format = Endian_SwapLE32(ppTex[i]->Format); - ppTex[i]->Size = Endian_SwapLE32(ppTex[i]->Size); - Next += sizeof(D3DTexture); - - (*ppDelays)[i] = Endian_SwapLE32(*(int*)Next); - Next += sizeof(int); - } - - ResDataOffset = ((DWORD)(Next - UnpackedBuf) + 127) & ~127; - ResData = UnpackedBuf + ResDataOffset; - - *ppTextures = new CBaseTexture*[nTextures]; - for (int i = 0; i < nTextures; ++i) - { - if ((ppTex[i]->Common & D3DCOMMON_TYPE_MASK) != D3DCOMMON_TYPE_TEXTURE) - goto PackedAnimError; - - GetTextureFromData(ppTex[i], ResData, &(*ppTextures)[i]); - delete[] ppTex[i]; - } - - delete[] ppTex; - ppTex = 0; - - width = Endian_SwapLE16(pAnimInfo->RealSize[0]); - height = Endian_SwapLE16(pAnimInfo->RealSize[1]); - - return nTextures; - -PackedAnimError: - CLog::Log(LOGERROR, "Error loading texture: %s: Invalid data", Filename.c_str()); - if (ppTex) - { - for (int i = 0; i < nTextures; ++i) - delete [] ppTex[i]; - delete [] ppTex; - } - delete [] *ppDelays; - return 0; -} - -void CTextureBundleXPR::SetThemeBundle(bool themeBundle) -{ - m_themeBundle = themeBundle; -} - -// normalize to how it's stored within the bundle -// lower case + using \\ rather than / -CStdString CTextureBundleXPR::Normalize(const CStdString &name) -{ - CStdString newName(name); - newName.Normalize(); - newName.Replace('/','\\'); - return newName; -} |