mirror of
https://github.com/libretro/RetroArch.git
synced 2024-12-11 10:13:53 +00:00
306 lines
8.1 KiB
C++
306 lines
8.1 KiB
C++
/* RetroArch - A frontend for libretro.
|
|
* Copyright (C) 2010-2013 - Hans-Kristian Arntzen
|
|
* Copyright (C) 2011-2013 - 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <xgraphics.h>
|
|
#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
|
|
|
|
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;
|
|
}
|