/* 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) { // Check for valid arguments if( strFilename == NULL || strPath == NULL ) { RARCH_ERR("Util_FindMediaFile(): Invalid arguments\n" ); return E_INVALIDARG; } // Default path is the filename itself as a fully qualified path strlcpy( strPath, strFilename, strPathsize); // Check for the ':' character to see if the filename is a fully // qualified path. If not, pre-pend the media directory if(strFilename[1] != ':') snprintf(strPath, strPathsize, "%s%s", g_strMediaPath, strFilename); // Try to open the file HANDLE hFile = CreateFile( strPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); if( hFile == INVALID_HANDLE_VALUE ) { RARCH_ERR("FindMediaFile(): Could not find file.\n"); return 0x82000004; } // Found the file. Close the file and return 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 { #ifdef _XBOX1 BOOL bHasResourceOffsetsTable = FALSE; // Find the media file CHAR strResourcePath[512]; if( FAILED(FindMediaFile(strResourcePath, strFilename, sizeof(strResourcePath)))) return E_FAIL; else strFilename = strResourcePath; #endif // Open the file HANDLE hFile; DWORD dwNumBytesRead; hFile = CreateFile( strFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL ); if( hFile == INVALID_HANDLE_VALUE ) { RARCH_ERR( "PackedResource::Create(): File <%s> not found.\n", strFilename ); return E_FAIL; } // Read in and verify the XPR magic header XPR_HEADER xprh; bool 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) { RARCH_ERR("Error reading XPR header in file %s.\n", strFilename ); CloseHandle( hFile ); return E_FAIL; } if( xprh.dwMagic != XPR2_MAGIC_VALUE ) #endif { RARCH_ERR( "Invalid Xbox Packed Resource (.xpr) file: Magic = 0x%08lx\n", xprh.dwMagic ); 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) { RARCH_ERR( "Could not allocate system memory.\n" ); 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 ) { RARCH_ERR( "Could not allocate physical memory.\n" ); 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 ) ) { RARCH_ERR( "Unable to read Xbox Packed Resource (.xpr) file\n" ); 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 // Fixup the texture memory if( ( m_pResourceTags[i].dwType & 0xffff0000 ) == ( RESOURCETYPE_TEXTURE & 0xffff0000 ) ) { D3DTexture* pTexture = ( D3DTexture* )&m_pSysMemData[m_pResourceTags[i].dwOffset]; // Adjust Base address according to where memory was allocated 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; }