Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add rawfilesdump cmd #6

Merged
merged 2 commits into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions src/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,30 @@ namespace filesystem
{
void create_nested_dirs(const char *path)
{
if (!path || !*path)
return;

char temp_path[256];
strncpy(temp_path, path, sizeof(temp_path));
strncpy(temp_path, path, sizeof(temp_path) - 1);
temp_path[sizeof(temp_path) - 1] = '\0';

char *p = temp_path;
while (*p)

// Skip leading drive letter (e.g., "C:\") or "game:\" prefix
if ((p[0] && p[1] == ':') || strncmp(p, "game:\\", 6) == 0)
p += (p[1] == ':' ? 3 : 6); // Move past "C:\" or "game:\"

for (; *p; p++)
{
if (*p == '\\' || *p == '/')
{
*p = '\0';

// Create the directory if it doesn't exist
_mkdir(temp_path);

_mkdir(temp_path); // Attempt to create the directory
*p = '\\';
}
p++;
}

_mkdir(temp_path);
_mkdir(temp_path); // Create final directory
}

/**
Expand Down
73 changes: 53 additions & 20 deletions src/game/mp_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ namespace mp
Cmd_AddCommandInternal_t Cmd_AddCommandInternal = reinterpret_cast<Cmd_AddCommandInternal_t>(0x8223ADE0);

Com_Printf_t Com_Printf = reinterpret_cast<Com_Printf_t>(0x82237000);
Com_PrintError_t Com_PrintError = reinterpret_cast<Com_PrintError_t>(0x82235C50);
Com_PrintWarning_t Com_PrintWarning = reinterpret_cast<Com_PrintWarning_t>(0x822356B8);

DB_EnumXAssets_FastFile_t DB_EnumXAssets_FastFile = reinterpret_cast<DB_EnumXAssets_FastFile_t>(0x8229ED48);

Load_MapEntsPtr_t Load_MapEntsPtr = reinterpret_cast<Load_MapEntsPtr_t>(0x822A9648);

Expand Down Expand Up @@ -158,22 +162,8 @@ namespace mp

char *Scr_ReadFile_FastFile_Hook(const char *filename, const char *extFilename, const char *codePos, bool archive)
{

xbox::DbgPrint("Scr_ReadFile_FastFile_Hook extFilename=%s \n", extFilename);

auto contents = Scr_ReadFile_FastFile_Detour.GetOriginal<decltype(&Scr_ReadFile_FastFile_Hook)>()(filename, extFilename, codePos, archive);

// Dump the file to disk if it exists
// It might not exist if it's not a stock file
if (contents != nullptr)
{
// Dump the file to disk
std::string file_path = "game:\\dump\\";
file_path += extFilename;
std::replace(file_path.begin(), file_path.end(), '/', '\\'); // Replace forward slashes with backslashes
filesystem::write_file_to_disk(file_path.c_str(), contents, strlen(contents));
}

std::string raw_file_path = "game:\\raw\\";
raw_file_path += extFilename;
std::replace(raw_file_path.begin(), raw_file_path.end(), '/', '\\'); // Replace forward slashes with backslashes
Expand Down Expand Up @@ -203,12 +193,56 @@ namespace mp
}
}

return contents;
return Scr_ReadFile_FastFile_Detour.GetOriginal<decltype(&Scr_ReadFile_FastFile_Hook)>()(filename, extFilename, codePos, archive);
}

const unsigned int MAX_RAWFILES = 2048;
struct RawFileList
{
unsigned int count;
RawFile *files[MAX_RAWFILES];
};

void R_AddRawFileToList(void *asset, void *inData)
{
RawFileList *rawFileList = reinterpret_cast<RawFileList *>(inData);
RawFile *rawFile = reinterpret_cast<RawFile *>(asset);

if (!rawFile)
{
Com_PrintError(CON_CHANNEL_ERROR, "R_AddRawFileToList: Null RawFile!\n");
return;
}

if (rawFileList->count >= MAX_RAWFILES)
{
Com_PrintError(CON_CHANNEL_ERROR, "R_AddRawFileToList: RawFileList is full!\n");
return;
}

rawFileList->files[rawFileList->count++] = rawFile;
}

void R_GetRawFileList(RawFileList *rawFileList)
{
rawFileList->count = 0;
DB_EnumXAssets_FastFile(ASSET_TYPE_RAWFILE, R_AddRawFileToList, rawFileList, true);
}

void Cmd_test_f()
void Cmd_rawfilesdump()
{
xbox::DbgPrint("test command\n");
RawFileList rawFileList;
R_GetRawFileList(&rawFileList);

Com_Printf(CON_CHANNEL_CONSOLEONLY, "Dumping %d raw files to `raw\\` %d\n", rawFileList.count);

for (unsigned int i = 0; i < rawFileList.count; i++)
{
auto rawfile = rawFileList.files[i];
std::string asset_name = rawfile->name;
std::replace(asset_name.begin(), asset_name.end(), '/', '\\'); // Replace forward slashes with backslashes
filesystem::write_file_to_disk(("game:\\dump\\" + asset_name).c_str(), rawfile->buffer, rawfile->len);
}
}

void init()
Expand All @@ -227,8 +261,7 @@ namespace mp
Scr_ReadFile_FastFile_Detour = Detour(Scr_ReadFile_FastFile, Scr_ReadFile_FastFile_Hook);
Scr_ReadFile_FastFile_Detour.Install();

cmd_function_s *test_cmd = new cmd_function_s;

Cmd_AddCommandInternal("test", Cmd_test_f, test_cmd);
cmd_function_s *rawfilesdump_VAR = new cmd_function_s;
Cmd_AddCommandInternal("rawfilesdump", Cmd_rawfilesdump, rawfilesdump_VAR);
}
}
120 changes: 118 additions & 2 deletions src/game/mp_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace mp
{

struct cmd_function_s
{
cmd_function_s *next;
Expand Down Expand Up @@ -157,14 +156,131 @@ namespace mp
int numEntityChars;
};

enum XAssetType : __int32
{
ASSET_TYPE_XMODELPIECES = 0x0,
ASSET_TYPE_PHYSPRESET = 0x1,
ASSET_TYPE_XANIMPARTS = 0x2,
ASSET_TYPE_XMODEL = 0x3,
ASSET_TYPE_MATERIAL = 0x4,
ASSET_TYPE_PIXELSHADER = 0x5,
ASSET_TYPE_TECHNIQUE_SET = 0x6,
ASSET_TYPE_IMAGE = 0x7,
ASSET_TYPE_SOUND = 0x8,
ASSET_TYPE_SOUND_CURVE = 0x9,
ASSET_TYPE_LOADED_SOUND = 0xA,
ASSET_TYPE_CLIPMAP = 0xB,
ASSET_TYPE_CLIPMAP_PVS = 0xC,
ASSET_TYPE_COMWORLD = 0xD,
ASSET_TYPE_GAMEWORLD_SP = 0xE,
ASSET_TYPE_GAMEWORLD_MP = 0xF,
ASSET_TYPE_MAP_ENTS = 0x10,
ASSET_TYPE_GFXWORLD = 0x11,
ASSET_TYPE_LIGHT_DEF = 0x12,
ASSET_TYPE_UI_MAP = 0x13,
ASSET_TYPE_FONT = 0x14,
ASSET_TYPE_MENULIST = 0x15,
ASSET_TYPE_MENU = 0x16,
ASSET_TYPE_LOCALIZE_ENTRY = 0x17,
ASSET_TYPE_WEAPON = 0x18,
ASSET_TYPE_SNDDRIVER_GLOBALS = 0x19,
ASSET_TYPE_FX = 0x1A,
ASSET_TYPE_IMPACT_FX = 0x1B,
ASSET_TYPE_AITYPE = 0x1C,
ASSET_TYPE_MPTYPE = 0x1D,
ASSET_TYPE_CHARACTER = 0x1E,
ASSET_TYPE_XMODELALIAS = 0x1F,
ASSET_TYPE_RAWFILE = 0x20,
ASSET_TYPE_STRINGTABLE = 0x21,
ASSET_TYPE_COUNT = 0x22,
ASSET_TYPE_STRING = 0x22,
ASSET_TYPE_ASSETLIST = 0x23,
};

struct RawFile
{
const char *name;
int len;
const char *buffer;
};

union XAssetHeader
{
// XModelPieces *xmodelPieces;
// PhysPreset *physPreset;
// XAnimParts *parts;
// XModel *model;
// Material *material;
// MaterialPixelShader *pixelShader;
// MaterialVertexShader *vertexShader;
// MaterialTechniqueSet *techniqueSet;
// GfxImage *image;
// snd_alias_list_t *sound;
// SndCurve *sndCurve;
// LoadedSound *loadSnd;
// clipMap_t *clipMap;
// ComWorld *comWorld;
// GameWorldSp *gameWorldSp;
// GameWorldMp *gameWorldMp;
// MapEnts *mapEnts;
// GfxWorld *gfxWorld;
// GfxLightDef *lightDef;
// Font_s *font;
// MenuList *menuList;
// menuDef_t *menu;
// LocalizeEntry *localize;
// WeaponDef *weapon;
// SndDriverGlobals *sndDriverGlobals;
// const FxEffectDef *fx;
// FxImpactTable *impactFx;
RawFile *rawfile;
// StringTable *stringTable;
void *data;
};

enum conChannel_t : __int32
{
CON_CHANNEL_DONT_FILTER = 0x0,
CON_CHANNEL_ERROR = 0x1,
CON_CHANNEL_GAMENOTIFY = 0x2,
CON_CHANNEL_BOLDGAME = 0x3,
CON_CHANNEL_SUBTITLE = 0x4,
CON_CHANNEL_OBITUARY = 0x5,
CON_CHANNEL_LOGFILEONLY = 0x6,
CON_CHANNEL_CONSOLEONLY = 0x7,
CON_CHANNEL_GFX = 0x8,
CON_CHANNEL_SOUND = 0x9,
CON_CHANNEL_FILES = 0xA,
CON_CHANNEL_DEVGUI = 0xB,
CON_CHANNEL_PROFILE = 0xC,
CON_CHANNEL_UI = 0xD,
CON_CHANNEL_CLIENT = 0xE,
CON_CHANNEL_SERVER = 0xF,
CON_CHANNEL_SYSTEM = 0x10,
CON_CHANNEL_PLAYERWEAP = 0x11,
CON_CHANNEL_AI = 0x12,
CON_CHANNEL_ANIM = 0x13,
CON_CHANNEL_PHYS = 0x14,
CON_CHANNEL_FX = 0x15,
CON_CHANNEL_LEADERBOARDS = 0x16,
CON_CHANNEL_PARSERSCRIPT = 0x17,
CON_CHANNEL_SCRIPT = 0x18,
CON_BUILTIN_CHANNEL_COUNT = 0x19,
};

typedef void (*Cbuf_AddText_t)(int localClientNum, const char *text);

typedef void (*CL_ConsolePrint_t)(int localClientNum, int channel, const char *txt, int duration, int pixelWidth, int flags);
typedef void (*CL_GamepadButtonEvent_t)(int localClientNum, int controllerIndex, int key, int down, unsigned int time);

typedef void (*Cmd_AddCommandInternal_t)(const char *cmdName, void (*function)(), cmd_function_s *allocedCmd);

typedef void (*Com_Printf_t)(int channel, const char *fmt, ...);
typedef void (*Com_PrintError_t)(conChannel_t channel, const char *fmt, ...);
typedef void (*Com_PrintMessage_t)(conChannel_t channel, const char *msg, int error);
typedef void (*Com_Printf_t)(conChannel_t channel, const char *fmt, ...);
typedef void (*Com_PrintWarning_t)(conChannel_t channel, const char *fmt, ...);

typedef void (*DB_EnumXAssets_FastFile_t)(XAssetType type, void (*func)(void *asset, void *inData), void *inData, bool includeOverride);

typedef void (*Load_MapEntsPtr_t)();

Expand Down
72 changes: 53 additions & 19 deletions src/game/sp_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ namespace sp

Cmd_AddCommandInternal_t Cmd_AddCommandInternal = reinterpret_cast<Cmd_AddCommandInternal_t>(0x821DFAD0);

Com_PrintError_t Com_PrintError = reinterpret_cast<Com_PrintError_t>(0x821DAC90);
Com_Printf_t Com_Printf = reinterpret_cast<Com_Printf_t>(0x821DC0A0);
Com_PrintWarning_t Com_PrintWarning = reinterpret_cast<Com_PrintWarning_t>(0x821DA798);

DB_EnumXAssets_FastFile_t DB_EnumXAssets_FastFile = reinterpret_cast<DB_EnumXAssets_FastFile_t>(0x822AEF88);

Scr_AddSourceBuffer_t Scr_AddSourceBuffer = reinterpret_cast<Scr_AddSourceBuffer_t>(0x821C5A18);
Scr_ReadFile_FastFile_t Scr_ReadFile_FastFile = reinterpret_cast<Scr_ReadFile_FastFile_t>(0x821C5978);
Expand Down Expand Up @@ -89,19 +93,6 @@ namespace sp
{
xbox::DbgPrint("Scr_ReadFile_FastFile_Hook extFilename=%s \n", extFilename);

auto contents = Scr_ReadFile_FastFile_Detour.GetOriginal<decltype(&Scr_ReadFile_FastFile_Hook)>()(filename, extFilename, codePos, archive);

// Dump the file to disk if it exists
// It might not exist if it's not a stock file
if (contents != nullptr)
{
// Dump the file to disk
std::string file_path = "game:\\dump\\";
file_path += extFilename;
std::replace(file_path.begin(), file_path.end(), '/', '\\'); // Replace forward slashes with backslashes
filesystem::write_file_to_disk(file_path.c_str(), contents, strlen(contents));
}

std::string raw_file_path = "game:\\raw\\";
raw_file_path += extFilename;
std::replace(raw_file_path.begin(), raw_file_path.end(), '/', '\\'); // Replace forward slashes with backslashes
Expand Down Expand Up @@ -131,12 +122,56 @@ namespace sp
}
}

return contents;
return Scr_ReadFile_FastFile_Detour.GetOriginal<decltype(&Scr_ReadFile_FastFile_Hook)>()(filename, extFilename, codePos, archive);
}

void Cmd_test_f()
const unsigned int MAX_RAWFILES = 2048;
struct RawFileList
{
unsigned int count;
RawFile *files[MAX_RAWFILES];
};

void R_AddRawFileToList(void *asset, void *inData)
{
xbox::DbgPrint("test command\n");
RawFileList *rawFileList = reinterpret_cast<RawFileList *>(inData);
RawFile *rawFile = reinterpret_cast<RawFile *>(asset);

if (!rawFile)
{
Com_PrintError(CON_CHANNEL_ERROR, "R_AddRawFileToList: Null RawFile!\n");
return;
}

if (rawFileList->count >= MAX_RAWFILES)
{
Com_PrintError(CON_CHANNEL_ERROR, "R_AddRawFileToList: RawFileList is full!\n");
return;
}

rawFileList->files[rawFileList->count++] = rawFile;
}

void R_GetRawFileList(RawFileList *rawFileList)
{
rawFileList->count = 0;
DB_EnumXAssets_FastFile(ASSET_TYPE_RAWFILE, R_AddRawFileToList, rawFileList, true);
}

void Cmd_rawfilesdump()
{
RawFileList rawFileList;
R_GetRawFileList(&rawFileList);

Com_Printf(CON_CHANNEL_CONSOLEONLY, "Dumping %d raw files to `raw\\` %d\n", rawFileList.count);

for (unsigned int i = 0; i < rawFileList.count; i++)
{
auto rawfile = rawFileList.files[i];
std::string asset_name = rawfile->name;
std::replace(asset_name.begin(), asset_name.end(), '/', '\\'); // Replace forward slashes with backslashes
filesystem::write_file_to_disk(("game:\\dump\\" + asset_name).c_str(), rawfile->buffer, rawfile->len);
}
}

void init()
Expand All @@ -152,8 +187,7 @@ namespace sp
Scr_ReadFile_FastFile_Detour = Detour(Scr_ReadFile_FastFile, Scr_ReadFile_FastFile_Hook);
Scr_ReadFile_FastFile_Detour.Install();

cmd_function_s *test_cmd = new cmd_function_s;

Cmd_AddCommandInternal("test", Cmd_test_f, test_cmd);
cmd_function_s *rawfilesdump_VAR = new cmd_function_s;
Cmd_AddCommandInternal("rawfilesdump", Cmd_rawfilesdump, rawfilesdump_VAR);
}
}
Loading