/* RetroArch - A frontend for libretro. * Copyright (C) 2010-2012 - Hans-Kristian Arntzen * Copyright (C) 2011-2012 - 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" #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 const DWORD eXALLOCAllocatorId_AtgResource = eXALLOCAllocatorId_GameMax; 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( NULL == m_pResourceTags || NULL == strName ) 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( !_stricmp( strName, m_pResourceTags[i].strName ) ) { return &m_pSysMemData[m_pResourceTags[i].dwOffset]; } } return NULL; } static __forceinline void* AllocateContiguousMemory( DWORD Size, DWORD Alignment, DWORD Protection = XALLOC_MEMPROTECT_WRITECOMBINE ) { #if defined(_XBOX1) return D3D_AllocContiguousMemory(Size, Alignment); #elif defined(_XBOX360) return XMemAlloc( Size, MAKE_XALLOC_ATTRIBUTES( 0, 0, 0, 0, eXALLOCAllocatorId_AtgResource, Alignment, Protection, 0, XALLOC_MEMTYPE_PHYSICAL ) ); #endif } static __forceinline 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_AtgResource, 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; }