diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/xbox/MakeGameData/MakeMaps.cpp | |
| download | archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip | |
Diffstat (limited to 'utils/xbox/MakeGameData/MakeMaps.cpp')
| -rw-r--r-- | utils/xbox/MakeGameData/MakeMaps.cpp | 383 |
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; +} |