mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-07 17:29:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,430 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Spews BSP Info
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include "xbspinfo.h"
|
||||
|
||||
BEGIN_BYTESWAP_DATADESC( dheader_t )
|
||||
DEFINE_FIELD( ident, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( version, FIELD_INTEGER ),
|
||||
DEFINE_EMBEDDED_ARRAY( lumps, HEADER_LUMPS ),
|
||||
DEFINE_FIELD( mapRevision, FIELD_INTEGER ),
|
||||
END_BYTESWAP_DATADESC()
|
||||
|
||||
BEGIN_BYTESWAP_DATADESC( lump_t )
|
||||
DEFINE_FIELD( fileofs, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( filelen, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( version, FIELD_INTEGER ),
|
||||
DEFINE_ARRAY( fourCC, FIELD_CHARACTER, 4 ),
|
||||
END_BYTESWAP_DATADESC()
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *pFriendlyName;
|
||||
const char *pName;
|
||||
int lumpNum;
|
||||
} lumpName_t;
|
||||
|
||||
lumpName_t g_lumpNames[] =
|
||||
{
|
||||
{"Entities", "LUMP_ENTITIES", LUMP_ENTITIES},
|
||||
{"Planes", "LUMP_PLANES", LUMP_PLANES},
|
||||
{"TexData", "LUMP_TEXDATA", LUMP_TEXDATA},
|
||||
{"Vertexes", "LUMP_VERTEXES", LUMP_VERTEXES},
|
||||
{"Visibility", "LUMP_VISIBILITY", LUMP_VISIBILITY},
|
||||
{"Nodes", "LUMP_NODES", LUMP_NODES},
|
||||
{"TexInfo", "LUMP_TEXINFO", LUMP_TEXINFO},
|
||||
{"Faces", "LUMP_FACES", LUMP_FACES},
|
||||
{"Face IDs", "LUMP_FACEIDS", LUMP_FACEIDS},
|
||||
{"Lighting", "LUMP_LIGHTING", LUMP_LIGHTING},
|
||||
{"Occlusion", "LUMP_OCCLUSION", LUMP_OCCLUSION},
|
||||
{"Leafs", "LUMP_LEAFS", LUMP_LEAFS},
|
||||
{"Edges", "LUMP_EDGES", LUMP_EDGES},
|
||||
{"Surf Edges", "LUMP_SURFEDGES", LUMP_SURFEDGES},
|
||||
{"Models", "LUMP_MODELS", LUMP_MODELS},
|
||||
{"World Lights", "LUMP_WORLDLIGHTS", LUMP_WORLDLIGHTS},
|
||||
{"Leaf Faces", "LUMP_LEAFFACES", LUMP_LEAFFACES},
|
||||
{"Leaf Brushes", "LUMP_LEAFBRUSHES", LUMP_LEAFBRUSHES},
|
||||
{"Brushes", "LUMP_BRUSHES", LUMP_BRUSHES},
|
||||
{"Brush Sides", "LUMP_BRUSHSIDES", LUMP_BRUSHSIDES},
|
||||
{"Areas", "LUMP_AREAS", LUMP_AREAS},
|
||||
{"Area Portals", "LUMP_AREAPORTALS", LUMP_AREAPORTALS},
|
||||
{"Disp Info", "LUMP_DISPINFO", LUMP_DISPINFO},
|
||||
{"Original Faces", "LUMP_ORIGINALFACES", LUMP_ORIGINALFACES},
|
||||
{"Phys Disp", "LUMP_PHYSDISP", LUMP_PHYSDISP},
|
||||
{"Phys Collide", "LUMP_PHYSCOLLIDE", LUMP_PHYSCOLLIDE},
|
||||
{"Vert Normals", "LUMP_VERTNORMALS", LUMP_VERTNORMALS},
|
||||
{"Vert Normal Indices", "LUMP_VERTNORMALINDICES", LUMP_VERTNORMALINDICES},
|
||||
{"Disp Lightmap Alphas", "LUMP_DISP_LIGHTMAP_ALPHAS", LUMP_DISP_LIGHTMAP_ALPHAS},
|
||||
{"Disp Verts", "LUMP_DISP_VERTS", LUMP_DISP_VERTS},
|
||||
{"Disp Lightmap Sample Positions", "LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS", LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS},
|
||||
{"Game Lump", "LUMP_GAME_LUMP", LUMP_GAME_LUMP},
|
||||
{"Leaf Water Data", "LUMP_LEAFWATERDATA", LUMP_LEAFWATERDATA},
|
||||
{"Primitives", "LUMP_PRIMITIVES", LUMP_PRIMITIVES},
|
||||
{"Prim Verts", "LUMP_PRIMVERTS", LUMP_PRIMVERTS},
|
||||
{"Prim Indices", "LUMP_PRIMINDICES", LUMP_PRIMINDICES},
|
||||
{"Pak File", "LUMP_PAKFILE", LUMP_PAKFILE},
|
||||
{"Clip Portal Verts", "LUMP_CLIPPORTALVERTS", LUMP_CLIPPORTALVERTS},
|
||||
{"Cube Maps", "LUMP_CUBEMAPS", LUMP_CUBEMAPS},
|
||||
{"Tex Data String Data", "LUMP_TEXDATA_STRING_DATA", LUMP_TEXDATA_STRING_DATA},
|
||||
{"Tex Data String Table", "LUMP_TEXDATA_STRING_TABLE", LUMP_TEXDATA_STRING_TABLE},
|
||||
{"Overlays", "LUMP_OVERLAYS", LUMP_OVERLAYS},
|
||||
{"Leaf Min Dist To Water", "LUMP_LEAFMINDISTTOWATER", LUMP_LEAFMINDISTTOWATER},
|
||||
{"Face Macro Texture Info", "LUMP_FACE_MACRO_TEXTURE_INFO", LUMP_FACE_MACRO_TEXTURE_INFO},
|
||||
{"Disp Tris", "LUMP_DISP_TRIS", LUMP_DISP_TRIS},
|
||||
{"Phys Collide Surface", "LUMP_PHYSCOLLIDESURFACE", LUMP_PHYSCOLLIDESURFACE},
|
||||
{"Water Overlays", "LUMP_WATEROVERLAYS", LUMP_WATEROVERLAYS},
|
||||
{"Leaf Ambient index HDR", "LUMP_LEAF_AMBIENT_INDEX_HDR", LUMP_LEAF_AMBIENT_INDEX_HDR},
|
||||
{"Leaf Ambient index", "LUMP_LEAF_AMBIENT_INDEX", LUMP_LEAF_AMBIENT_INDEX},
|
||||
{"Lighting (HDR)", "LUMP_LIGHTING_HDR", LUMP_LIGHTING_HDR},
|
||||
{"World Lights (HDR)", "LUMP_WORLDLIGHTS_HDR", LUMP_WORLDLIGHTS_HDR},
|
||||
{"Leaf Ambient Lighting (HDR)", "LUMP_LEAF_AMBIENT_LIGHTING_HDR", LUMP_LEAF_AMBIENT_LIGHTING_HDR},
|
||||
{"Leaf Ambient Lighting", "LUMP_LEAF_AMBIENT_LIGHTING", LUMP_LEAF_AMBIENT_LIGHTING},
|
||||
{"*** DEAD ***", "LUMP_XZIPPAKFILE", LUMP_XZIPPAKFILE},
|
||||
{"Faces (HDR)", "LUMP_FACES_HDR", LUMP_FACES_HDR},
|
||||
{"Flags", "LUMP_MAP_FLAGS", LUMP_MAP_FLAGS},
|
||||
{"Fade Overlays", "LUMP_OVERLAY_FADES", LUMP_OVERLAY_FADES},
|
||||
};
|
||||
|
||||
bool g_bQuiet;
|
||||
bool g_bAsPercent;
|
||||
bool g_bAsBytes;
|
||||
bool g_bSortByOffset;
|
||||
bool g_bSortBySize;
|
||||
bool g_bFriendlyNames;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Convert lump ID to descriptive Name
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *BSP_LumpNumToName( int lumpNum )
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i=0; i<ARRAYSIZE( g_lumpNames ); ++i )
|
||||
{
|
||||
if ( g_lumpNames[i].lumpNum == lumpNum )
|
||||
{
|
||||
if ( g_bFriendlyNames )
|
||||
{
|
||||
return g_lumpNames[i].pFriendlyName;
|
||||
}
|
||||
else
|
||||
{
|
||||
return g_lumpNames[i].pName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "???";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Extract Lump Pak
|
||||
//-----------------------------------------------------------------------------
|
||||
void ExtractZip( const char *pFilename, void *pBSPFile )
|
||||
{
|
||||
dheader_t *pBSPHeader = (dheader_t *)pBSPFile;
|
||||
|
||||
if ( pBSPHeader->lumps[LUMP_PAKFILE].filelen )
|
||||
{
|
||||
Msg( "Extracting Zip to %s\n", pFilename );
|
||||
|
||||
FILE *fp = fopen( pFilename, "wb" );
|
||||
if ( !fp )
|
||||
{
|
||||
Warning( "Failed to create %s\n", pFilename );
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite( (unsigned char *)pBSPFile + pBSPHeader->lumps[LUMP_PAKFILE].fileofs, pBSPHeader->lumps[LUMP_PAKFILE].filelen, 1, fp );
|
||||
fclose( fp );
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "Nothing to do!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
// compare function for qsort below
|
||||
static dheader_t *g_pSortBSPHeader;
|
||||
static int LumpCompare( const void *pElem1, const void *pElem2 )
|
||||
{
|
||||
int lump1 = *(byte *)pElem1;
|
||||
int lump2 = *(byte *)pElem2;
|
||||
|
||||
int fileOffset1 = g_pSortBSPHeader->lumps[lump1].fileofs;
|
||||
int fileOffset2 = g_pSortBSPHeader->lumps[lump2].fileofs;
|
||||
|
||||
int fileSize1 = g_pSortBSPHeader->lumps[lump1].filelen;
|
||||
int fileSize2 = g_pSortBSPHeader->lumps[lump2].filelen;
|
||||
|
||||
if ( g_bSortByOffset )
|
||||
{
|
||||
// invalid or empty lumps will get sorted together
|
||||
if ( !fileSize1 )
|
||||
{
|
||||
fileOffset1 = 0;
|
||||
}
|
||||
|
||||
if ( !fileSize2 )
|
||||
{
|
||||
fileOffset2 = 0;
|
||||
}
|
||||
|
||||
// compare by offset
|
||||
if ( fileOffset1 < fileOffset2 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if ( fileOffset1 > fileOffset2 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if ( g_bSortBySize )
|
||||
{
|
||||
if ( fileSize1 < fileSize2 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if ( fileSize1 > fileSize2 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Spew Info
|
||||
//-----------------------------------------------------------------------------
|
||||
void DumpInfo( const char *pFilename, void *pBSPFile, int bspSize )
|
||||
{
|
||||
const char *pName;
|
||||
dheader_t *pBSPHeader;
|
||||
|
||||
pBSPHeader = (dheader_t *)pBSPFile;
|
||||
|
||||
Msg( "\n" );
|
||||
Msg( "%s\n", pFilename );
|
||||
|
||||
// sort by offset order
|
||||
int readOrder[HEADER_LUMPS];
|
||||
for ( int i=0; i<HEADER_LUMPS; i++ )
|
||||
{
|
||||
readOrder[i] = i;
|
||||
}
|
||||
|
||||
if ( g_bSortByOffset || g_bSortBySize )
|
||||
{
|
||||
g_pSortBSPHeader = pBSPHeader;
|
||||
qsort( readOrder, HEADER_LUMPS, sizeof( int ), LumpCompare );
|
||||
}
|
||||
|
||||
for ( int i=0; i<HEADER_LUMPS; ++i )
|
||||
{
|
||||
int lump = readOrder[i];
|
||||
pName = BSP_LumpNumToName( lump );
|
||||
if ( !pName )
|
||||
continue;
|
||||
|
||||
if ( g_bSortByOffset )
|
||||
{
|
||||
Msg( "[Offset: 0x%8.8x] ", pBSPHeader->lumps[lump].fileofs );
|
||||
}
|
||||
|
||||
if ( g_bAsPercent )
|
||||
{
|
||||
Msg( "%5.2f%s (%2d) %s\n", 100.0f*pBSPHeader->lumps[lump].filelen/( float )bspSize, "%%", lump, pName );
|
||||
}
|
||||
else if ( g_bAsBytes )
|
||||
{
|
||||
Msg( "%8d: (%2d) %s\n", pBSPHeader->lumps[lump].filelen, lump, pName );
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "%5.2f MB: (%2d) %s\n", pBSPHeader->lumps[lump].filelen/( 1024.0f*1024.0f ), lump, pName );
|
||||
}
|
||||
}
|
||||
|
||||
Msg( "-------\n" );
|
||||
if ( g_bAsBytes )
|
||||
{
|
||||
Msg( "%8d: %s\n", bspSize, "Total Bytes" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "%6.2f MB %s\n", bspSize/( 1024.0f*1024.0f ), "Total" );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Load the bsp file
|
||||
//-----------------------------------------------------------------------------
|
||||
bool LoadBSPFile( const char* pFilename, void **ppBSPBuffer, int *pBSPSize )
|
||||
{
|
||||
CByteswap byteSwap;
|
||||
|
||||
*ppBSPBuffer = NULL;
|
||||
*pBSPSize = 0;
|
||||
|
||||
FILE *fp = fopen( pFilename, "rb" );
|
||||
if ( fp )
|
||||
{
|
||||
fseek( fp, 0, SEEK_END );
|
||||
int size = ftell( fp );
|
||||
fseek( fp, 0, SEEK_SET );
|
||||
|
||||
*ppBSPBuffer = malloc( size );
|
||||
if ( !*ppBSPBuffer )
|
||||
{
|
||||
Warning( "Failed to alloc %d bytes\n", size );
|
||||
goto cleanUp;
|
||||
}
|
||||
|
||||
*pBSPSize = size;
|
||||
fread( *ppBSPBuffer, size, 1, fp );
|
||||
fclose( fp );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !g_bQuiet )
|
||||
{
|
||||
Warning( "Missing %s\n", pFilename );
|
||||
}
|
||||
goto cleanUp;
|
||||
}
|
||||
|
||||
dheader_t *pBSPHeader = (dheader_t *)*ppBSPBuffer;
|
||||
|
||||
if ( pBSPHeader->ident != IDBSPHEADER )
|
||||
{
|
||||
if ( pBSPHeader->ident != BigLong( IDBSPHEADER ) )
|
||||
{
|
||||
if ( !g_bQuiet )
|
||||
{
|
||||
Warning( "BSP %s has bad id: got %d, expected %d\n", pFilename, pBSPHeader->ident, IDBSPHEADER );
|
||||
}
|
||||
goto cleanUp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// bsp is for 360, swap the header
|
||||
byteSwap.ActivateByteSwapping( true );
|
||||
byteSwap.SwapFieldsToTargetEndian( pBSPHeader );
|
||||
}
|
||||
}
|
||||
|
||||
if ( pBSPHeader->version < MINBSPVERSION || pBSPHeader->version > BSPVERSION )
|
||||
{
|
||||
if ( !g_bQuiet )
|
||||
{
|
||||
Warning( "BSP %s has bad version: got %d, expected %d\n", pFilename, pBSPHeader->version, BSPVERSION );
|
||||
}
|
||||
goto cleanUp;
|
||||
}
|
||||
|
||||
// sucess
|
||||
return true;
|
||||
|
||||
cleanUp:
|
||||
if ( *ppBSPBuffer )
|
||||
{
|
||||
free( *ppBSPBuffer );
|
||||
*ppBSPBuffer = NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Usage
|
||||
//-----------------------------------------------------------------------------
|
||||
void Usage( void )
|
||||
{
|
||||
Msg( "usage: bspinfo <bspfile> [options]\n" );
|
||||
Msg( "options:\n" );
|
||||
Msg( "-percent, -p: Show as percentages\n" );
|
||||
Msg( "-bytes, -b: Show as bytes\n" );
|
||||
Msg( "-q: Quiet, no header, no errors\n" );
|
||||
Msg( "-names: Show friendly lump names\n" );
|
||||
Msg( "-so: Sort by offset\n" );
|
||||
Msg( "-ss: Sort by size\n" );
|
||||
Msg( "-extract <zipname>: Extract pak file\n" );
|
||||
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: default output func
|
||||
//-----------------------------------------------------------------------------
|
||||
SpewRetval_t OutputFunc( SpewType_t spewType, char const *pMsg )
|
||||
{
|
||||
printf( pMsg );
|
||||
|
||||
if ( spewType == SPEW_ERROR )
|
||||
{
|
||||
return SPEW_ABORT;
|
||||
}
|
||||
return ( spewType == SPEW_ASSERT ) ? SPEW_DEBUGGER : SPEW_CONTINUE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// main
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
char bspPath[MAX_PATH];
|
||||
|
||||
// set the valve library printer
|
||||
SpewOutputFunc( OutputFunc );
|
||||
|
||||
CommandLine()->CreateCmdLine( argc, argv );
|
||||
|
||||
Msg( "\nXBSPINFO - Valve Xbox 360 BSP Info ( Build: %s %s )\n", __DATE__, __TIME__ );
|
||||
Msg( "( C ) Copyright 1996-2006, Valve Corporation, All rights reserved.\n\n" );
|
||||
|
||||
if ( argc < 2 || CommandLine()->FindParm( "?" ) || CommandLine()->FindParm( "-h" ) || CommandLine()->FindParm( "-help" ) )
|
||||
{
|
||||
Usage();
|
||||
}
|
||||
|
||||
if ( argc >= 2 && argv[1][0] != '-' )
|
||||
{
|
||||
strcpy( bspPath, argv[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
Usage();
|
||||
}
|
||||
|
||||
g_bQuiet = CommandLine()->FindParm( "-q" ) != 0;
|
||||
g_bAsPercent = CommandLine()->FindParm( "-p" ) != 0 || CommandLine()->FindParm( "-percent" ) != 0;
|
||||
g_bAsBytes = CommandLine()->FindParm( "-b" ) != 0 || CommandLine()->FindParm( "-bytes" ) != 0;
|
||||
g_bSortByOffset = CommandLine()->FindParm( "-so" ) != 0;
|
||||
g_bSortBySize = CommandLine()->FindParm( "-ss" ) != 0;
|
||||
g_bFriendlyNames = CommandLine()->FindParm( "-names" ) != 0;
|
||||
|
||||
void *pBSPBuffer;
|
||||
int bspSize;
|
||||
if ( LoadBSPFile( bspPath, &pBSPBuffer, &bspSize ) )
|
||||
{
|
||||
const char *pZipName = CommandLine()->ParmValue( "-extract", "" );
|
||||
if ( pZipName && pZipName[0] )
|
||||
{
|
||||
ExtractZip( pZipName, pBSPBuffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
DumpInfo( bspPath, pBSPBuffer, bspSize );
|
||||
}
|
||||
|
||||
free( pBSPBuffer );
|
||||
}
|
||||
|
||||
return ( 0 );
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utime.h>
|
||||
#include "icommandline.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
#include "tier1/utlstring.h"
|
||||
#include "datamap.h"
|
||||
#include "byteswap.h"
|
||||
#include "../../common/bsplib.h"
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// XBSPINFO.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\devtools\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_exe_con_win32_base.vpc"
|
||||
|
||||
$Project "xbspinfo"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "xbspinfo.cpp"
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "xbspinfo.h"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user