/* RetroArch - A frontend for libretro. * Copyright (C) 2011-2015 - Daniel De Matteis * * RetroArch 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 Found- * ation, either version 3 of the License, or (at your option) any later version. * * RetroArch 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 RetroArch. * If not, see . */ #include #include "xdk_resources.h" #include #ifdef _XBOX360 struct XPR_HEADER { DWORD dwMagic; DWORD dwHeaderSize; DWORD dwDataSize; }; #endif #define XPR0_MAGIC_VALUE 0x30525058 #define XPR1_MAGIC_VALUE 0x31525058 #define XPR2_MAGIC_VALUE 0x58505232 PackedResource::PackedResource() { m_pSysMemData = NULL; m_dwSysMemDataSize = 0L; m_pVidMemData = NULL; m_dwVidMemDataSize = 0L; m_pResourceTags = NULL; m_dwNumResourceTags = 0L; m_bInitialized = FALSE; } PackedResource::~PackedResource() { Destroy(); } void *PackedResource::GetData(const char *strName) const { if (m_pResourceTags == NULL || strName == NULL) return NULL; #if defined(_XBOX1) for (DWORD i=0; m_pResourceTags[i].strName; i++) #elif defined(_XBOX360) for (DWORD i = 0; i < m_dwNumResourceTags; i++) #endif { if (!strcasecmp(strName, m_pResourceTags[i].strName)) return &m_pSysMemData[m_pResourceTags[i].dwOffset]; } return NULL; } static INLINE void* AllocateContiguousMemory(DWORD Size, DWORD Alignment) { #if defined(_XBOX1) return D3D_AllocContiguousMemory(Size, Alignment); #elif defined(_XBOX360) return XMemAlloc(Size, MAKE_XALLOC_ATTRIBUTES(0, 0, 0, 0, eXALLOCAllocatorId_GameMax, Alignment, XALLOC_MEMPROTECT_WRITECOMBINE, 0, XALLOC_MEMTYPE_PHYSICAL)); #endif } static INLINE void FreeContiguousMemory(void* pData) { #if defined(_XBOX1) return D3D_FreeContiguousMemory(pData); #elif defined(_XBOX360) return XMemFree(pData, MAKE_XALLOC_ATTRIBUTES(0, 0, 0, 0, eXALLOCAllocatorId_GameMax, 0, 0, 0, XALLOC_MEMTYPE_PHYSICAL)); #endif } #ifdef _XBOX1 char g_strMediaPath[512] = "D:\\Media\\"; static HRESULT FindMediaFile(char *strPath, const char *strFilename, size_t strPathsize) { if(strFilename == NULL || strPath == NULL) return E_INVALIDARG; strlcpy(strPath, strFilename, strPathsize); if(strFilename[1] != ':') snprintf(strPath, strPathsize, "%s%s", g_strMediaPath, strFilename); HANDLE hFile = CreateFile(strPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) return 0x82000004; CloseHandle(hFile); return S_OK; } #endif #if defined(_XBOX1) HRESULT PackedResource::Create(const char *strFilename, DWORD dwNumResourceTags, XBRESOURCE* pResourceTags) #elif defined(_XBOX360) HRESULT PackedResource::Create(const char *strFilename) #endif { HANDLE hFile; DWORD dwNumBytesRead; XPR_HEADER xprh; bool retval; #ifdef _XBOX1 BOOL bHasResourceOffsetsTable = FALSE; char strResourcePath[512]; if (FAILED(FindMediaFile(strResourcePath, strFilename, sizeof(strResourcePath)))) return E_FAIL; strFilename = strResourcePath; #endif hFile = CreateFile(strFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); if (hFile == INVALID_HANDLE_VALUE) return E_FAIL; retval = ReadFile(hFile, &xprh, sizeof(XPR_HEADER), &dwNumBytesRead, NULL); #if defined(_XBOX1) if(xprh.dwMagic == XPR0_MAGIC_VALUE) bHasResourceOffsetsTable = FALSE; else if(xprh.dwMagic == XPR1_MAGIC_VALUE) bHasResourceOffsetsTable = TRUE; else #elif defined(_XBOX360) if(!retval) { CloseHandle(hFile); return E_FAIL; } if (xprh.dwMagic != XPR2_MAGIC_VALUE) #endif { CloseHandle(hFile); return E_FAIL; } // Compute memory requirements #if defined(_XBOX1) m_dwSysMemDataSize = xprh.dwHeaderSize - sizeof(XPR_HEADER); m_dwVidMemDataSize = xprh.dwTotalSize - xprh.dwHeaderSize; #elif defined(_XBOX360) m_dwSysMemDataSize = xprh.dwHeaderSize; m_dwVidMemDataSize = xprh.dwDataSize; #endif // Allocate memory m_pSysMemData = (BYTE*)malloc(m_dwSysMemDataSize); if (m_pSysMemData == NULL) { m_dwSysMemDataSize = 0; return E_FAIL; } m_pVidMemData = (BYTE*)AllocateContiguousMemory(m_dwVidMemDataSize, #if defined(_XBOX1) D3DTEXTURE_ALIGNMENT #elif defined(_XBOX360) XALLOC_PHYSICAL_ALIGNMENT_4K #endif ); if(m_pVidMemData == NULL) { m_dwSysMemDataSize = 0; m_dwVidMemDataSize = 0; free(m_pSysMemData); m_pSysMemData = NULL; return E_FAIL; } // Read in the data from the file if( !ReadFile( hFile, m_pSysMemData, m_dwSysMemDataSize, &dwNumBytesRead, NULL) || !ReadFile( hFile, m_pVidMemData, m_dwVidMemDataSize, &dwNumBytesRead, NULL)) { CloseHandle( hFile); return E_FAIL; } // Done with the file CloseHandle( hFile); #ifdef _XBOX1 if (bHasResourceOffsetsTable) { #endif // Extract resource table from the header data m_dwNumResourceTags = *(DWORD*)(m_pSysMemData + 0); m_pResourceTags = (XBRESOURCE*)(m_pSysMemData + 4); // Patch up the resources for(DWORD i = 0; i < m_dwNumResourceTags; i++) { m_pResourceTags[i].strName = (char*)(m_pSysMemData + (DWORD)m_pResourceTags[i].strName); #ifdef _XBOX360 if((m_pResourceTags[i].dwType & 0xffff0000) == (RESOURCETYPE_TEXTURE & 0xffff0000)) { D3DTexture *pTexture = (D3DTexture*)&m_pSysMemData[m_pResourceTags[i].dwOffset]; XGOffsetBaseTextureAddress(pTexture, m_pVidMemData, m_pVidMemData); } #endif } #ifdef _XBOX1 } #endif #ifdef _XBOX1 // Use user-supplied number of resources and the resource tags if(dwNumResourceTags != 0 || pResourceTags != NULL) { m_pResourceTags = pResourceTags; m_dwNumResourceTags = dwNumResourceTags; } #endif m_bInitialized = TRUE; return S_OK; } #ifdef _XBOX360 void PackedResource::GetResourceTags(DWORD* pdwNumResourceTags, XBRESOURCE** ppResourceTags) { if (pdwNumResourceTags) (*pdwNumResourceTags) = m_dwNumResourceTags; if (ppResourceTags) (*ppResourceTags) = m_pResourceTags; } #endif void PackedResource::Destroy() { free(m_pSysMemData); m_pSysMemData = NULL; m_dwSysMemDataSize = 0L; if (m_pVidMemData != NULL) FreeContiguousMemory(m_pVidMemData); m_pVidMemData = NULL; m_dwVidMemDataSize = 0L; m_pResourceTags = NULL; m_dwNumResourceTags = 0L; m_bInitialized = FALSE; } BOOL PackedResource::Initialized() const { return m_bInitialized; }