//-------------------------------------------------------------------------------------- // Outputs verbose error message from NUI errors //-------------------------------------------------------------------------------------- VOID NuiPrintError( HRESULT hResult, const CHAR* szFunctionName ) { switch (hResult) { case E_INVALIDARG: ATG_PrintError( "%s failed with E_INVALIDARG\n", szFunctionName ); break; case E_NUI_ALREADY_INITIALIZED: ATG_PrintError( "%s failed with E_NUI_ALREADY_INITIALIZED\n", szFunctionName ); break; case E_NUI_DATABASE_NOT_FOUND: ATG_PrintError( "%s failed with E_NUI_DATABASE_NOT_FOUND\n", szFunctionName ); break; case E_NUI_DATABASE_VERSION_MISMATCH: ATG_PrintError( "%s failed with E_NUI_DATABASE_VERSION_MISMATCH\n", szFunctionName ); break; case E_OUTOFMEMORY: ATG_PrintError( "%s failed with E_OUTOFMEMORY\n", szFunctionName ); break; case E_NUI_DEVICE_NOT_READY: ATG_PrintError( "%s failed with E_NUI_DEVICE_NOT_READY\n", szFunctionName ); break; case E_NUI_DEVICE_NOT_CONNECTED: ATG_PrintError( "%s failed with E_NUI_DEVICE_NOT_CONNECTED\n", szFunctionName ); break; case E_NUI_FEATURE_NOT_INITIALIZED: ATG_PrintError( "%s failed with E_NUI_FEATURE_NOT_INITIALIZED\n", szFunctionName ); break; case E_NUI_IMAGE_STREAM_IN_USE: ATG_PrintError( "%s failed with E_NUI_IMAGE_STREAM_IN_USE\n", szFunctionName ); break; default: ATG_PrintError( "%s failed with 0x%x\n", szFunctionName, (UINT)hResult ); } }
//-------------------------------------------------------------------------------------- // Name: Run() // Desc: Creates the D3D device, calls Initialize() and enters an infinite loop // calling Update() and Render() //-------------------------------------------------------------------------------------- VOID Application::Run() { HRESULT hr; // Create Direct3D LPDIRECT3D9 pD3D = Direct3DCreate9( D3D_SDK_VERSION ); // Create the D3D device if( FAILED( hr = pD3D->CreateDevice( 0, D3DDEVTYPE_HAL, NULL, m_dwDeviceCreationFlags, &m_d3dpp, ( ::D3DDevice** )&m_pd3dDevice ) ) ) { ATG_PrintError( "Could not create D3D device!\n" ); DebugBreak(); } pD3D->Release(); // Allow global access to the device g_pd3dDevice = m_pd3dDevice; // Initialize the app's device-dependent objects if( FAILED( hr = Initialize() ) ) { ATG_PrintError( "Call to Initialize() failed!\n" ); DebugBreak(); } // Run the game loop for(; ; ) { // Update the scene Update(); // Render the scene Render(); } }
//-------------------------------------------------------------------------------------- // Name: Create() // Desc: Initialize the class, create D3D and the font texture //-------------------------------------------------------------------------------------- HRESULT Console::Create( LPCSTR strFontFileName, D3DCOLOR colBackColor, D3DCOLOR colTextColor, UINT nLines ) { // Create Direct3D LPDIRECT3D9 pD3D = Direct3DCreate9( D3D_SDK_VERSION ); // Check video mode settings XVIDEO_MODE VideoMode; ZeroMemory( &VideoMode, sizeof( VideoMode ) ); XGetVideoMode( &VideoMode ); BOOL bEnable720p = VideoMode.dwDisplayWidth >= 1280; m_d3dpp.BackBufferWidth = bEnable720p ? SCREEN_SIZE_X_720p : SCREEN_SIZE_X_DEFAULT; m_d3dpp.BackBufferHeight = bEnable720p ? SCREEN_SIZE_Y_720p : SCREEN_SIZE_Y_DEFAULT; // Calculate the safe area UINT uiSafeAreaPct = bEnable720p ? SAFE_AREA_PCT_HDTV : SAFE_AREA_PCT_4x3; m_cxSafeArea = ( m_d3dpp.BackBufferWidth * uiSafeAreaPct ) / 100; m_cySafeArea = ( m_d3dpp.BackBufferHeight * uiSafeAreaPct ) / 100; m_cxSafeAreaOffset = ( m_d3dpp.BackBufferWidth - m_cxSafeArea ) / 2; m_cySafeAreaOffset = ( m_d3dpp.BackBufferHeight - m_cySafeArea ) / 2; // Create the D3D device HRESULT hr = pD3D->CreateDevice( 0, D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_d3dpp, ( ::D3DDevice** )&m_pd3dDevice ); if( FAILED( hr ) ) { ATG_PrintError( "Could not create D3D device!\n" ); DebugBreak(); } // Allow global access to the device g_pd3dDevice = m_pd3dDevice; // Create the font hr = m_Font.Create( strFontFileName ); if( FAILED( hr ) ) { ATG_PrintError( "Could not create font.\n" ); DebugBreak(); } // Save the colors m_colBackColor = colBackColor; m_colTextColor = colTextColor; // Calculate the number of lines on the screen FLOAT fCharWidth, fCharHeight; m_Font.GetTextExtent( L"i", &fCharWidth, &fCharHeight, FALSE ); m_cScreenHeight = ( UINT )( m_cySafeArea / fCharHeight ); m_cScreenWidth = ( UINT )( m_cxSafeArea / fCharWidth ); m_cScreenHeightVirtual = max( m_cScreenHeight, nLines ); m_fLineHeight = fCharHeight; // Allocate memory to hold the lines m_Buffer = new WCHAR[ m_cScreenHeightVirtual * ( m_cScreenWidth + 1 ) ]; m_Lines = new WCHAR*[ m_cScreenHeightVirtual ]; // Set the line pointers as indexes into the buffer for( UINT i = 0; i < m_cScreenHeightVirtual; i++ ) { m_Lines[ i ] = m_Buffer + ( m_cScreenWidth + 1 ) * i; } m_bSuspendFlag = FALSE; // Clear the screen Clear(); return hr; }
Flyer::Flyer(PE::GameContext &context, PE::MemoryArena arena, PE::Handle hMyself, int &threadOwnershipMask) : Component(context, arena, hMyself) , m_prevCameraType(CameraManager::CameraType_Count) { // NUI testing #ifdef _XBOX // Could also try for a bit more smoothing ( 0.25f, 0.25f, 0.25f, 0.03f, 0.05f ); m_JointFilter.Init( 0.5f, 0.5f, 0.5f, 0.05f, 0.05f ); // create event which will be signaled when frame processing ends m_hFrameEndEvent = CreateEvent( NULL, FALSE, // auto-reset FALSE, // create unsignaled "NuiFrameEndEvent" ); if ( !m_hFrameEndEvent ) { ATG_PrintError( "Failed to create NuiFrameEndEvent\n" ); return; // return E_FAIL; } HRESULT hr = NuiInitialize( NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX, NUI_INITIALIZE_DEFAULT_HARDWARE_THREAD ); if( FAILED( hr )) { ATG::NuiPrintError( hr, "NuiInitialize" ); return; // return E_FAIL; } // register frame end event with NUI hr = NuiSetFrameEndEvent( m_hFrameEndEvent, 0 ); if( FAILED(hr) ) { ATG::NuiPrintError( hr, "NuiSetFrameEndEvent" ); return; // return E_FAIL; } /* // Open the color stream hr = NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 1, NULL, &m_hImage ); if( FAILED (hr) ) { ATG::NuiPrintError( hr, "NuiImageStreamOpen" ); return E_FAIL; } // Open the depth stream hr = NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_320x240, 0, 1, NULL, &m_hDepth ); if( FAILED (hr) ) { ATG::NuiPrintError( hr, "NuiImageStreamOpen" ); return E_FAIL; } */ hr = NuiSkeletonTrackingEnable( NULL, 0 ); if( FAILED( hr )) { ATG::NuiPrintError( hr, "NuiSkeletonTrackingEnable" ); } m_pNuiJointConverterConstrained = new ATG::NuiJointConverter(); if( m_pNuiJointConverterConstrained == NULL ) { // return E_FAIL; return; } m_pNuiJointConverterConstrained->AddDefaultConstraints(); Handle hSN("SceneNode", sizeof(SceneNode)); m_pNuiSN = new(hSN) SceneNode(context, arena, hSN); m_pNuiSN->addDefaultComponents(); m_pNuiSN->m_base.setPos(Vector3(0.0f, 0, 25.0f)); m_pNuiSN->m_base.turnRight(1.2f * 3.1415f); RootSceneNode::Instance()->addComponent(hSN); for (int i = 0; i < XAVATAR_MAX_SKELETON_JOINTS; i++) { PE::Handle hMeshInstance("MeshInstance", sizeof(MeshInstance)); MeshInstance *pMeshInstance = new(hMeshInstance) MeshInstance(*m_pContext, m_arena, hMeshInstance); pMeshInstance->addDefaultComponents(); pMeshInstance->initFromFile("box.x_main_mesh.mesha", "Default", threadOwnershipMask); Handle hSN("SceneNode", sizeof(SceneNode)); m_sceneNodes[i] = new(hSN) SceneNode(context, arena, hSN); m_sceneNodes[i]->addDefaultComponents(); m_sceneNodes[i]->addComponent(hMeshInstance); m_pNuiSN->addComponent(hSN); if (m_pNuiJointConverterConstrained->MapAvatarJointToNUI_POSITION_INDEX(i) == NUI_SKELETON_POSITION_SHOULDER_RIGHT) { PE::Handle hMeshInstance("MeshInstance", sizeof(MeshInstance)); MeshInstance *pMeshInstance = new(hMeshInstance) MeshInstance(*m_pContext, m_arena, hMeshInstance); pMeshInstance->addDefaultComponents(); pMeshInstance->initFromFile("wings.x_rwing_mesh.mesha", "City", threadOwnershipMask); m_sceneNodes[i]->addComponent(hMeshInstance); } if (m_pNuiJointConverterConstrained->MapAvatarJointToNUI_POSITION_INDEX(i) == NUI_SKELETON_POSITION_SHOULDER_LEFT) { PE::Handle hMeshInstance("MeshInstance", sizeof(MeshInstance)); MeshInstance *pMeshInstance = new(hMeshInstance) MeshInstance(*m_pContext, m_arena, hMeshInstance); pMeshInstance->addDefaultComponents(); pMeshInstance->initFromFile("wings.x_lwing_mesh.mesha", "City", threadOwnershipMask); m_sceneNodes[i]->addComponent(hMeshInstance); } } { // put a camera here PE::Handle hMeshInstance("MeshInstance", sizeof(MeshInstance)); MeshInstance *pMeshInstance = new(hMeshInstance) MeshInstance(*m_pContext, m_arena, hMeshInstance); pMeshInstance->addDefaultComponents(); pMeshInstance->initFromFile("box.x_main_mesh.mesha", "Default", threadOwnershipMask); // we put camera in a scene node so we can rotate the camera within that scene node, but we could have also just added camera on its own Handle hSN("SceneNode", sizeof(SceneNode)); m_pCamSN = new(hSN) SceneNode(context, arena,hSN); m_pCamSN->addDefaultComponents(); m_pCamSN->addComponent(hMeshInstance); m_pNuiSN->addComponent(hSN); m_pCamSN->m_base.setPos(Vector3(0, +1.0f, +1.5f)); Handle hDebugCamera("Camera", sizeof(Camera)); Camera *debugCamera = new(hDebugCamera) Camera(context, arena, hDebugCamera, hSN); debugCamera->addDefaultComponents(); CameraManager::Instance()->setCamera(CameraManager::PLAYER, hDebugCamera); //SceneNode *pCamSN = debugCamera->getCamSceneNode(); } m_framesWithNoData = 0; m_framesWithData = 0; #endif // #ifdef _XBOX }
//-------------------------------------------------------------------------------------- // Name: Create() // Desc: Creates a mesh from an XBG file //-------------------------------------------------------------------------------------- HRESULT Mesh2::Create( const CHAR* strFilename, const PackedResource* pResource ) { // Open the file DWORD dwNumBytesRead; HANDLE hFile = CreateFile( strFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL ); if( hFile == INVALID_HANDLE_VALUE ) { ATG_PrintError( "File not found!\n" ); return E_FAIL; } // Read the magic number XBG_HEADER xbgHeader; if( !ReadFile( hFile, &xbgHeader, sizeof( XBG_HEADER ), &dwNumBytesRead, NULL ) ) { CloseHandle( hFile ); ATG_PrintError( "Unable to read file header!\n" ); return E_FAIL; } if( xbgHeader.dwMagic != XBG7_FILE_ID ) { CloseHandle( hFile ); ATG_PrintError( "Invalid XBG file type!\n" ); return E_FAIL; } // Read in system memory objects DWORD dwSysMemSize = xbgHeader.dwSysMemSize; m_pAllocatedSysMem = ( VOID* )new BYTE[dwSysMemSize]; if( !ReadFile( hFile, m_pAllocatedSysMem, dwSysMemSize, &dwNumBytesRead, NULL ) ) { CloseHandle( hFile ); ATG_PrintError( "Unable to read system memory objects!\n" ); return E_FAIL; } // Read in video memory objects DWORD dwVidMemSize = xbgHeader.dwVidMemSize; m_pAllocatedVidMem = ( BYTE* )XPhysicalAllocEx( dwVidMemSize, 0, MAXULONG_PTR, D3DVERTEXBUFFER_ALIGNMENT, PAGE_READWRITE | PAGE_WRITECOMBINE ); if( !ReadFile( hFile, m_pAllocatedVidMem, dwVidMemSize, &dwNumBytesRead, NULL ) ) { CloseHandle( hFile ); ATG_PrintError( "Unable to read video memory objects!\n" ); return E_FAIL; } // Done with the file CloseHandle( hFile ); // Now we need to patch the mesh data. Any pointers read from the file were // stored as file offsets. So, we simply need to add a base address to patch // things up. MESH_FRAME* pFrames = ( MESH_FRAME* )m_pAllocatedSysMem; DWORD dwPatchOffset = ( DWORD )m_pAllocatedSysMem - sizeof( XBG_HEADER ); // Note: for a simple mesh class, we only consider the first frame m_pMeshData = ( MESH_DATA* )( ( DWORD )pFrames[0].m_pMeshData + dwPatchOffset ); // Patch up the GPU addresses XGOffsetResourceAddress( &m_pMeshData->m_VB, m_pAllocatedVidMem ); XGOffsetResourceAddress( &m_pMeshData->m_IB, m_pAllocatedVidMem ); // Create a vertex declaration for the mesh g_pd3dDevice->CreateVertexDeclaration( m_pMeshData->m_VertexElements, &m_pMeshData->m_pVertexDecl ); // Finally, create any textures used by the meshes' subsets. In this // implementation, we are pulling textures out of the passed in resource. if( pResource ) { for( DWORD i = 0; i < m_pMeshData->m_dwNumSubsets; i++ ) { m_pMeshData->m_pSubsets[i].pTexture = pResource->GetTexture( m_pMeshData->m_pSubsets[i].strTexture ); } } return S_OK; }
//-------------------------------------------------------------------------------------- // Name: Write() // Desc: Writes the mesh to an XBG file //-------------------------------------------------------------------------------------- HRESULT Mesh::Write( const CHAR* strFilename ) { // Open the file DWORD dwNumBytesWritten; HANDLE hFile = CreateFile( strFilename, FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile == INVALID_HANDLE_VALUE ) { ATG_PrintError( "File not found!\n" ); return E_FAIL; } // Compute storage requirements DWORD g_dwFrameSpace = 0; DWORD g_dwMeshSpace = 0; DWORD g_dwVertexSpace = 0; DWORD g_dwIndexSpace = 0; for( DWORD i = 0; i < m_dwNumFrames; i++ ) { MESH_FRAME* pFrame = &m_pFrames[i]; MESH_DATA* pMesh = pFrame->m_pMeshData; DWORD dwIndexSize = pMesh->m_IB.Common & D3DINDEXBUFFER_INDEX32 ? sizeof( DWORD ) : sizeof( WORD ); g_dwFrameSpace += sizeof( MESH_FRAME ); g_dwMeshSpace += sizeof( MESH_DATA ) - sizeof( MESH_SUBSET ); g_dwMeshSpace += sizeof( MESH_SUBSET ) * pMesh->m_dwNumSubsets; g_dwIndexSpace += ( ( dwIndexSize * pMesh->m_dwNumIndices + ( 4096 - 1 ) ) / 4096 ) * 4096; g_dwVertexSpace += ( ( pMesh->m_dwVertexSize * pMesh->m_dwNumVertices + ( 4096 - 1 ) ) / 4096 ) * 4096; } DWORD dwNumSysMemBytes = g_dwFrameSpace + g_dwMeshSpace; DWORD dwNumVidMemBytes = g_dwIndexSpace + g_dwVertexSpace; // Read the magic number XBG_HEADER xbgHeader; xbgHeader.dwMagic = XBG7_FILE_ID; xbgHeader.dwSysMemSize = dwNumSysMemBytes; xbgHeader.dwVidMemSize = dwNumVidMemBytes; xbgHeader.dwNumFrames = m_dwNumFrames; WriteFile( hFile, &xbgHeader, sizeof( XBG_HEADER ), &dwNumBytesWritten, NULL ); DWORD g_dwFramesFileOffset = sizeof( XBG_HEADER ); DWORD g_dwMeshesFileOffset = g_dwFramesFileOffset + g_dwFrameSpace; DWORD g_dwIndicesFileOffset = 0; DWORD g_dwVerticesFileOffset = g_dwIndexSpace; // Write the frames for( DWORD i = 0; i < m_dwNumFrames; i++ ) { MESH_FRAME* pFrame = &m_pFrames[i]; MESH_DATA* pMesh = pFrame->m_pMeshData; // Write out the frame MESH_FRAME frame = *pFrame; frame.Pad[0] = 0x11111111; if( pFrame->m_pChild ) { DWORD dwOffset = ( DWORD )pFrame->m_pChild - ( DWORD )m_pFrames; frame.m_pChild = ( MESH_FRAME* )( g_dwFramesFileOffset + dwOffset ); } if( pFrame->m_pNext ) { DWORD dwOffset = ( DWORD )pFrame->m_pNext - ( DWORD )m_pFrames; frame.m_pNext = ( MESH_FRAME* )( g_dwFramesFileOffset + dwOffset ); } frame.m_pMeshData = ( MESH_DATA* )g_dwMeshesFileOffset; g_dwMeshesFileOffset += ( sizeof( MESH_DATA ) - sizeof( MESH_SUBSET ) ) + sizeof( MESH_SUBSET ) * pMesh->m_dwNumSubsets; // Write out frame info WriteFile( hFile, &frame, sizeof( MESH_FRAME ), &dwNumBytesWritten, NULL ); } // Write the meshes for( DWORD i = 0; i < m_dwNumFrames; i++ ) { MESH_FRAME* pFrame = &m_pFrames[i]; MESH_DATA* pMesh = pFrame->m_pMeshData; DWORD dwIndexSize = pMesh->m_IB.Common & D3DINDEXBUFFER_INDEX32 ? sizeof( DWORD ) : sizeof( WORD ); D3DFORMAT d3dIndexFormat = pMesh->m_IB.Common & D3DINDEXBUFFER_INDEX32 ? D3DFMT_INDEX32 : D3DFMT_INDEX16; // Write out the meshdata MESH_DATA mesh = *pMesh; if( pMesh->m_dwNumVertices ) { XGSetVertexBufferHeader( pMesh->m_dwNumVertices * pMesh->m_dwVertexSize, 0, D3DPOOL_DEFAULT, g_dwVerticesFileOffset, &mesh.m_VB ); g_dwVerticesFileOffset += ( ( pMesh->m_dwVertexSize * pMesh->m_dwNumVertices + ( 4096 - 1 ) ) / 4096 ) * 4096; } if( mesh.m_dwNumIndices ) { XGSetIndexBufferHeader( pMesh->m_dwNumIndices * dwIndexSize, 0, d3dIndexFormat, D3DPOOL_DEFAULT, g_dwIndicesFileOffset, &mesh.m_IB ); g_dwIndicesFileOffset += ( ( pMesh->m_dwNumIndices * dwIndexSize + ( 4096 - 1 ) ) / 4096 ) * 4096; } mesh.m_pVertexDecl = NULL; // Write out mesh info WriteFile( hFile, &mesh, sizeof( MESH_DATA ) - sizeof( MESH_SUBSET ), &dwNumBytesWritten, NULL ); // Write out subset data for( DWORD j = 0; j < pMesh->m_dwNumSubsets; j++ ) { MESH_SUBSET subset = pMesh->m_pSubsets[j]; subset.Pad[0] = 0x11111111; subset.pTexture = NULL; WriteFile( hFile, &subset, sizeof( MESH_SUBSET ), &dwNumBytesWritten, NULL ); } } static BYTE Pad[4096] = { 0 }; // Write indices for( DWORD i = 0; i < m_dwNumFrames; i++ ) { MESH_FRAME* pFrame = &m_pFrames[i]; MESH_DATA* pMesh = pFrame->m_pMeshData; if( pMesh->m_dwNumIndices ) { VOID* pIndexData; DWORD dwIndexSize = pMesh->m_IB.Common & D3DINDEXBUFFER_INDEX32 ? sizeof( DWORD ) : sizeof( WORD ); DWORD dwSize = pMesh->m_dwNumIndices * dwIndexSize; pMesh->m_IB.Lock( 0, 0, &pIndexData, 0 ); WriteFile( hFile, pIndexData, dwSize, &dwNumBytesWritten, NULL ); pMesh->m_IB.Unlock(); // Pad to aligment DWORD dwPadSize = ( 4096 - ( dwSize % 4096 ) ) % 4096; if( dwPadSize ) WriteFile( hFile, Pad, dwPadSize, &dwNumBytesWritten, NULL ); } } // Write vertices for( DWORD i = 0; i < m_dwNumFrames; i++ ) { MESH_FRAME* pFrame = &m_pFrames[i]; MESH_DATA* pMesh = pFrame->m_pMeshData; if( pMesh->m_dwNumVertices ) { VOID* pVertexData; DWORD dwSize = pMesh->m_dwNumVertices * pMesh->m_dwVertexSize; pMesh->m_VB.Lock( 0, 0, &pVertexData, 0 ); WriteFile( hFile, pVertexData, dwSize, &dwNumBytesWritten, NULL ); pMesh->m_VB.Unlock(); // Pad to aligment DWORD dwPadSize = ( 4096 - ( dwSize % 4096 ) ) % 4096; if( dwPadSize ) WriteFile( hFile, Pad, dwPadSize, &dwNumBytesWritten, NULL ); } } // Done with the file CloseHandle( hFile ); return S_OK; }
//-------------------------------------------------------------------------------------- // Name: Create // Desc: Loads all the texture resources from the given XPR. //-------------------------------------------------------------------------------------- HRESULT PackedResource::Create( const CHAR* strFilename ) { // Open the file DWORD dwNumBytesRead; HANDLE hFile = CreateFile( strFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL ); if( hFile == INVALID_HANDLE_VALUE ) { ATG_PrintError( "File <%s> not found\n", strFilename ); return E_FAIL; } // Read in and verify the XPR magic header XPR_HEADER xprh; if( !ReadFile( hFile, &xprh, sizeof( XPR_HEADER ), &dwNumBytesRead, NULL ) ) { ATG_PrintError( "Error reading XPR header in file <%s>\n", strFilename ); CloseHandle( hFile ); return E_FAIL; } #ifdef _PC XGEndianSwapMemory( &xprh, &xprh, XGENDIAN_8IN32, sizeof(DWORD), sizeof(XPR_HEADER)/sizeof(DWORD) ); #endif if( xprh.dwMagic != XPR2_MAGIC_VALUE ) { ATG_PrintError( "Invalid Xbox Packed Resource (.xpr) file: Magic = 0x%08lx\n", xprh.dwMagic ); CloseHandle( hFile ); return E_FAIL; } // Compute memory requirements m_dwSysMemDataSize = xprh.dwHeaderSize; m_dwVidMemDataSize = xprh.dwDataSize; // Allocate memory m_pSysMemData = new BYTE[m_dwSysMemDataSize]; if( m_pSysMemData == NULL ) { ATG_PrintError( "Could not allocate system memory.\n" ); m_dwSysMemDataSize = 0; return E_FAIL; } m_pVidMemData = ( BYTE* )AllocateContiguousMemory( m_dwVidMemDataSize, XALLOC_PHYSICAL_ALIGNMENT_4K ); if( m_pVidMemData == NULL ) { ATG_PrintError( "Could not allocate physical memory.\n" ); m_dwSysMemDataSize = 0; m_dwVidMemDataSize = 0; delete[] 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 ) ) { ATG_PrintError( "Unable to read Xbox Packed Resource (.xpr) file\n" ); CloseHandle( hFile ); return E_FAIL; } // Done with the file CloseHandle( hFile ); #ifdef _PC XGEndianSwapData( m_pSysMemData, m_pSysMemData, XGENDIAN_8IN32 ); #endif // Extract resource table from the header data m_dwNumResourceTags = *( DWORD* )( m_pSysMemData + 0 ); m_pResourceTags = ( RESOURCE* )( m_pSysMemData + 4 ); #ifdef _PC XGEndianSwapMemory( m_pResourceTags, m_pResourceTags, XGENDIAN_8IN32, sizeof(DWORD), m_dwNumResourceTags * ( sizeof(RESOURCE) / sizeof(DWORD) ) ); #endif // Patch up the resources for( DWORD i = 0; i < m_dwNumResourceTags; i++ ) { m_pResourceTags[i].strName = ( CHAR* )( m_pSysMemData + ( DWORD )m_pResourceTags[i].strName ); // Fixup the texture memory if( ( m_pResourceTags[i].dwType & 0xffff0000 ) == ( RESOURCETYPE_TEXTURE & 0xffff0000 ) ) { D3DTexture* pTexture = ( D3DTexture* )&m_pSysMemData[m_pResourceTags[i].dwOffset]; #ifdef _PC XGEndianSwapTextureHeader( pTexture ); #endif // Adjust Base address according to where memory was allocated XGOffsetBaseTextureAddress( pTexture, m_pVidMemData, m_pVidMemData ); // Let PIX know the name of the texture PIXSetTextureName(pTexture, m_pResourceTags[i].strName); } } m_bInitialized = TRUE; return S_OK; }