mirror of
https://github.com/celisej567/source-engine.git
synced 2026-01-04 18:09:53 +03:00
1
This commit is contained in:
383
utils/xbox/MakeGameData/MakeMaps.cpp
Normal file
383
utils/xbox/MakeGameData/MakeMaps.cpp
Normal file
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user