summaryrefslogtreecommitdiff
path: root/utils/xbox/MakeGameData/MakeMaps.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/xbox/MakeGameData/MakeMaps.cpp')
-rw-r--r--utils/xbox/MakeGameData/MakeMaps.cpp383
1 files changed, 383 insertions, 0 deletions
diff --git a/utils/xbox/MakeGameData/MakeMaps.cpp b/utils/xbox/MakeGameData/MakeMaps.cpp
new file mode 100644
index 0000000..618e5f6
--- /dev/null
+++ b/utils/xbox/MakeGameData/MakeMaps.cpp
@@ -0,0 +1,383 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: .360 Creation for all studiomdl generated files (mdl, vvd, vtx, ani, phy)
+//
+//=====================================================================================//
+
+#include "MakeGameData.h"
+#include "filesystem.h"
+#include "../../common/bsplib.h"
+#include "ibsppack.h"
+#include "vtf/vtf.h"
+#include "../../game/server/ai_hull.h"
+#include "zip_utils.h"
+
+#define AINET_VERSION_NUMBER 37
+#define MAX_NODES 1500
+
+bool ReadBSPHeader( const char *pFilename, dheader_t *pHeader )
+{
+ V_memset( pHeader, 0, sizeof( dheader_t ) );
+
+ int handle = _open( pFilename, _O_RDONLY|_O_BINARY );
+ if ( handle == -1 )
+ {
+ return false;
+ }
+
+ _read( handle, pHeader, sizeof( dheader_t ) );
+ close( handle );
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Run possible lod culling fixup
+//-----------------------------------------------------------------------------
+bool ConvertVHV( const char *pVhvFilename, const char *pModelName, CUtlBuffer &sourceBuffer, CUtlBuffer &targetBuffer )
+{
+ // find strip info from model
+ char vsiFilename[MAX_PATH];
+ V_strncpy( vsiFilename, pModelName, sizeof( vsiFilename ) );
+ V_SetExtension( vsiFilename, ".vsi", sizeof( vsiFilename ) );
+
+ CUtlBuffer vsiBuffer;
+ if ( !g_pFullFileSystem->ReadFile( vsiFilename, NULL, vsiBuffer ) )
+ {
+ // cannot convert bsp's without model converions
+ Msg( "Error! Missing expected model conversion file '%s'. Cannot perform VHV fixup.\n", vsiFilename );
+ return false;
+ }
+
+ IMdlStripInfo *pMdlStripInfo = NULL;
+ if ( !mdllib->CreateNewStripInfo( &pMdlStripInfo ) )
+ {
+ Msg( "Error! Failed to allocate strip info object\n" );
+ return false;
+ }
+
+ if ( !pMdlStripInfo->UnSerialize( vsiBuffer ) )
+ {
+ Msg( "Error! Failed to unserialize strip info object '%s'\n", vsiFilename );
+ pMdlStripInfo->DeleteThis();
+ return false;
+ }
+
+ long originalChecksum = 0;
+ long newChecksum = 0;
+ if ( !pMdlStripInfo->GetCheckSum( &originalChecksum, &newChecksum ) )
+ {
+ Msg( "Error! Failed to get checksums from '%s'\n", vsiFilename );
+ pMdlStripInfo->DeleteThis();
+ return false;
+ }
+
+ HardwareVerts::FileHeader_t *pVHVhdr = (HardwareVerts::FileHeader_t*)sourceBuffer.Base();
+ if ( pVHVhdr->m_nChecksum != originalChecksum )
+ {
+ // vhv file should have matching original checksums
+ Msg( "Error! Mismatched checksums from '%s' and '%s'\n", vsiFilename, pVhvFilename );
+ pMdlStripInfo->DeleteThis();
+ return false;
+ }
+
+ targetBuffer.EnsureCapacity( sourceBuffer.TellMaxPut() );
+ targetBuffer.Put( sourceBuffer.Base(), sourceBuffer.TellMaxPut() );
+ if ( !pMdlStripInfo->StripHardwareVertsBuffer( targetBuffer ) )
+ {
+ pMdlStripInfo->DeleteThis();
+ return false;
+ }
+
+ // success
+ pMdlStripInfo->DeleteThis();
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Generate .360 bsp
+//-----------------------------------------------------------------------------
+bool CreateTargetFile_BSP( const char *pSourceName, const char *pTargetName, bool bWriteToZip )
+{
+ CUtlBuffer targetBuffer;
+ CUtlBuffer zipBuffer;
+ CUtlBuffer fileBuffer;
+ CUtlBuffer tempBuffer;
+ char tempZipName[MAX_PATH];
+ char tempSwapName[MAX_PATH];
+
+ tempZipName[0] = '\0';
+ tempSwapName[0] = '\0';
+ void *pPakData = NULL;
+ int pakSize = 0;
+ CXZipTool *pNewXZip = NULL;
+
+ if ( !g_bModPathIsValid )
+ {
+ Msg( "Indeterminate mod path, Cannot perform BSP conversion\n" );
+ return false;
+ }
+
+ // Load bsppack.dll
+ void *pBSPPack;
+ CSysModule *pBSPModule;
+ if ( !Sys_LoadInterface( "bsppack.dll", IBSPPACK_VERSION_STRING, &pBSPModule, &pBSPPack ) )
+ {
+ Msg( "Failed to load bsppack interface\n" );
+ return false;
+ }
+
+ scriptlib->MakeTemporaryFilename( g_szModPath, tempSwapName, sizeof( tempSwapName ) );
+
+ // Swaps the bsp directly to disk
+ bool bOK = ((IBSPPack*)pBSPPack)->SwapBSPFile( g_pFullFileSystem, pSourceName, tempSwapName, false, ConvertVTFTo360Format, ConvertVHV, CompressCallback );
+ if ( !bOK )
+ {
+ goto cleanUp;
+ }
+
+ // get the pak file from the swapped bsp
+ bOK = ((IBSPPack*)pBSPPack)->GetPakFileLump( g_pFullFileSystem, tempSwapName, &pPakData, &pakSize );
+ if ( !bOK )
+ {
+ goto cleanUp;
+ }
+
+ // build an xzip version of the pak file
+ if ( pPakData && pakSize )
+ {
+ // mount current pak file
+ IZip *pOldZip = IZip::CreateZip( false, true );
+ pOldZip->ParseFromBuffer( pPakData, pakSize );
+
+ // start a new xzip version
+ scriptlib->MakeTemporaryFilename( g_szModPath, tempZipName, sizeof( tempZipName ) );
+
+ pNewXZip = new CXZipTool;
+ pNewXZip->Begin( tempZipName, XBOX_DVD_SECTORSIZE );
+
+ // iterate each file in existing zip, add to new zip
+ int zipIndex = -1;
+ for ( ;; )
+ {
+ char filename[MAX_PATH];
+ filename[0] = '\0';
+ int fileSize = 0;
+ zipIndex = pOldZip->GetNextFilename( zipIndex, filename, sizeof( filename ), fileSize );
+ if ( zipIndex == -1 )
+ {
+ break;
+ }
+
+ fileBuffer.Purge();
+ bOK = pOldZip->ReadFileFromZip( filename, false, fileBuffer );
+ if ( !bOK )
+ {
+ goto cleanUp;
+ }
+
+ bOK = pNewXZip->AddBuffer( filename, fileBuffer, true );
+ if ( !bOK )
+ {
+ goto cleanUp;
+ }
+ }
+
+ IZip::ReleaseZip( pOldZip );
+ pNewXZip->End();
+
+ // read the new zip into memory
+ bOK = scriptlib->ReadFileToBuffer( tempZipName, zipBuffer );
+ if ( !bOK )
+ {
+ goto cleanUp;
+ }
+
+ // replace old pak lump with new zip
+ bOK = ((IBSPPack*)pBSPPack)->SetPakFileLump( g_pFullFileSystem, tempSwapName, tempSwapName, zipBuffer.Base(), zipBuffer.TellMaxPut() );
+ if ( !bOK )
+ {
+ goto cleanUp;
+ }
+ }
+
+ bOK = scriptlib->ReadFileToBuffer( tempSwapName, targetBuffer );
+ if ( !bOK )
+ {
+ goto cleanUp;
+ }
+
+ // never zip, always write local file
+ bOK = WriteBufferToFile( pTargetName, targetBuffer, false, WRITE_TO_DISK_ALWAYS );
+
+cleanUp:
+ if ( tempZipName[0] )
+ {
+ _unlink( tempZipName );
+ }
+ if ( tempSwapName[0] )
+ {
+ _unlink( tempSwapName );
+ }
+
+ Sys_UnloadModule( pBSPModule );
+
+ if ( pPakData )
+ {
+ free( pPakData );
+ }
+
+ delete pNewXZip;
+
+ return bOK;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Generate .360 node graphs
+//-----------------------------------------------------------------------------
+bool CreateTargetFile_AIN( const char *pSourceName, const char *pTargetName, bool bWriteToZip )
+{
+ CUtlBuffer sourceBuf;
+ if ( !scriptlib->ReadFileToBuffer( pSourceName, sourceBuf ) )
+ {
+ return false;
+ }
+
+ // the pc ain is tied to the pc bsp and should have been generated after the bsp
+ char szBspName[MAX_PATH];
+ char szBspPath[MAX_PATH];
+ V_FileBase( pSourceName, szBspName, sizeof( szBspName ) );
+ V_ExtractFilePath( pSourceName, szBspPath, sizeof( szBspPath ) );
+ V_AppendSlash( szBspPath, sizeof( szBspPath ) );
+ V_strncat( szBspPath, "..\\", sizeof( szBspPath ) );
+ V_strncat( szBspPath, szBspName, sizeof( szBspPath ) );
+ V_strncat( szBspPath, ".bsp", sizeof( szBspPath ) );
+ if ( scriptlib->CompareFileTime( pSourceName, szBspPath ) < 0 )
+ {
+ // ain has a smaller filetime, thus older than bsp
+ Msg( "%s: Need to regenerate PC nodegraph (stale)\n", pSourceName );
+ if ( !g_bForce )
+ {
+ return false;
+ }
+ }
+
+ // Check the version
+ if ( sourceBuf.GetChar() == 'V' && sourceBuf.GetChar() == 'e' && sourceBuf.GetChar() == 'r' )
+ {
+ Msg( "%s: Need to regenerate PC nodegraph (bad format)\n", pSourceName );
+ return false;
+ }
+
+ // reset
+ sourceBuf.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
+
+ // Version number
+ int version = sourceBuf.GetInt();
+ if ( version != AINET_VERSION_NUMBER )
+ {
+ Msg( "%s: Need to regenerate PC nodegraph (got version '%d', expected '%d')\n", pSourceName, version, AINET_VERSION_NUMBER );
+ return false;
+ }
+
+ // check the map revision
+ int mapVersion = sourceBuf.GetInt();
+ dheader_t bspHeader;
+ if ( ReadBSPHeader( szBspPath, &bspHeader ) )
+ {
+ if ( mapVersion != bspHeader.mapRevision )
+ {
+ Msg( "%s: Need to regenerate PC nodegraph (ai revision '%d' does not match bsp revision '%d')\n", pSourceName, mapVersion, bspHeader.mapRevision );
+ return false;
+ }
+ }
+ else
+ {
+ Msg( "%s: Could not find expected bsp '%s'\n", pSourceName, szBspPath );
+ }
+
+ // Nodes
+ int nodeCt = sourceBuf.GetInt();
+ if ( nodeCt > MAX_NODES || nodeCt < 0 )
+ {
+ Msg( "%s: Need to regenerate PC nodegraph (corrupt)\n", pSourceName );
+ return false;
+ }
+
+ CUtlBuffer targetBuf;
+ targetBuf.ActivateByteSwapping( true );
+
+ CByteswap swap;
+ swap.ActivateByteSwapping( true );
+
+ targetBuf.PutInt( version );
+ targetBuf.PutInt( mapVersion );
+ targetBuf.PutInt( nodeCt );
+
+ int numFloats = NUM_HULLS + 4;
+ for ( int node = 0; node < nodeCt; ++node )
+ {
+ targetBuf.EnsureCapacity( targetBuf.TellPut() + numFloats * sizeof( float ) );
+ swap.SwapBufferToTargetEndian<float>( (float*)targetBuf.PeekPut(), (float*)sourceBuf.PeekGet(), numFloats );
+ sourceBuf.SeekGet( CUtlBuffer::SEEK_CURRENT, numFloats * sizeof( float ) );
+ targetBuf.SeekPut( CUtlBuffer::SEEK_CURRENT, numFloats * sizeof( float ) );
+
+ targetBuf.PutChar( sourceBuf.GetChar() );
+
+ // Align the remaining data
+ targetBuf.SeekPut( CUtlBuffer::SEEK_CURRENT, 3 );
+
+ targetBuf.PutUnsignedShort( sourceBuf.GetUnsignedShort() );
+ targetBuf.PutShort( sourceBuf.GetShort() );
+ }
+
+ // Node links
+ int totalNumLinks = sourceBuf.GetInt();
+ targetBuf.PutInt( totalNumLinks );
+
+ for ( int link = 0; link < totalNumLinks; ++link )
+ {
+ targetBuf.PutShort( sourceBuf.GetShort() );
+ targetBuf.PutShort( sourceBuf.GetShort() );
+ targetBuf.Put( sourceBuf.PeekGet(), NUM_HULLS );
+ sourceBuf.SeekGet( CUtlBuffer::SEEK_CURRENT, NUM_HULLS );
+ }
+
+ // WC lookup table
+ targetBuf.EnsureCapacity( targetBuf.TellPut() + nodeCt * sizeof( int ) );
+ swap.SwapBufferToTargetEndian<int>( (int*)targetBuf.PeekPut(), (int*)sourceBuf.PeekGet(), nodeCt );
+ targetBuf.SeekPut( CUtlBuffer::SEEK_CURRENT, nodeCt * sizeof( int ) );
+
+ // Write the file out
+ return WriteBufferToFile( pTargetName, targetBuf, bWriteToZip, WRITE_TO_DISK_ALWAYS );
+}
+
+bool GetDependants_BSP( const char *pBspName, CUtlVector< CUtlString > *pList )
+{
+ if ( !g_bModPathIsValid )
+ {
+ Msg( "Indeterminate mod path, Cannot perform BSP conversion\n" );
+ return false;
+ }
+
+ // Load bsppack.dll
+ void *pBSPPack;
+ CSysModule *pBSPModule;
+ if ( !Sys_LoadInterface( "bsppack.dll", IBSPPACK_VERSION_STRING, &pBSPModule, &pBSPPack ) )
+ {
+ Msg( "Failed to load bsppack interface\n" );
+ return false;
+ }
+
+ // 360 builds a more complete reslist that includes bsp internal files
+ // build full path to bsp file
+ char szBspFilename[MAX_PATH];
+ V_ComposeFileName( g_szGamePath, pBspName, szBspFilename, sizeof( szBspFilename ) );
+
+ bool bOK = ((IBSPPack*)pBSPPack)->GetBSPDependants( g_pFullFileSystem, szBspFilename, pList );
+
+ Sys_UnloadModule( pBSPModule );
+
+ return bOK;
+}