complete reverse of dvardump & dvarlist

This commit is contained in:
FutureRave 2022-10-10 03:33:45 +01:00
parent 5ac7a59eba
commit 6424fd291d
No known key found for this signature in database
GPG Key ID: 22F9079C86CFAB31
8 changed files with 265 additions and 31 deletions

View File

@ -9,6 +9,7 @@ namespace game
Cmd_RemoveCommand_t Cmd_RemoveCommand;
Com_Error_t Com_Error;
Com_Filter_t Com_Filter;
DB_LoadXAssets_t DB_LoadXAssets;
@ -19,7 +20,10 @@ namespace game
Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
Dvar_SetString_t Dvar_SetString;
Dvar_ForEach_t Dvar_ForEach;
Dvar_DisplayableValue_t Dvar_DisplayableValue;
Dvar_DisplayableLatchedValue_t Dvar_DisplayableLatchedValue;
G_RunFrame_t G_RunFrame;
G_GetWeaponForName_t G_GetWeaponForName;
@ -127,6 +131,11 @@ namespace game
int* dvarCount;
dvar_t** sortedDvars;
int Vec4Compare(const float* a, const float* b)
{
return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3];
}
namespace mp
{
SV_GetGuid_t SV_GetGuid;
@ -977,6 +986,7 @@ namespace game
native::Cmd_RemoveCommand = native::Cmd_RemoveCommand_t(SELECT_VALUE(0x443A30, 0x545E20, 0x4CC060));
native::Com_Error = native::Com_Error_t(SELECT_VALUE(0x425540, 0x555450, 0x4D93F0));
native::Com_Filter = native::Com_Filter_t(SELECT_VALUE(0x44EFF0, 0x5B7C30, 0x0));
native::DB_LoadXAssets = native::DB_LoadXAssets_t(SELECT_VALUE(0x48A8E0, 0x4CD020, 0x44F770));
@ -988,7 +998,10 @@ namespace game
SELECT_VALUE(0x4DD090, 0x5BF740, 0x518DF0));
native::Dvar_SetString = native::Dvar_SetString_t(SELECT_VALUE(0x540570, 0x5BF3E0, 0x0));
native::Dvar_ForEach = native::Dvar_ForEach_t(SELECT_VALUE(0x536720, 0x5BFFB0, 0x0));
native::Dvar_DisplayableValue = native::Dvar_DisplayableValue_t(SELECT_VALUE(0x4AB1D0, 0x5BD260, 0x0));
native::Dvar_DisplayableLatchedValue = native::Dvar_DisplayableLatchedValue_t(SELECT_VALUE(0x464F50, 0x5BD290, 0x0));
native::G_RunFrame = native::G_RunFrame_t(SELECT_VALUE(0x52EAA0, 0x50CB70, 0x48AD60));
native::G_GetWeaponForName = native::G_GetWeaponForName_t(SELECT_VALUE(0x495E40, 0x531070, 0x0));

View File

@ -20,6 +20,9 @@ namespace game
typedef void (*Com_Error_t)(errorParm_t code, const char* fmt, ...);
extern Com_Error_t Com_Error;
typedef bool (*Com_Filter_t)(const char* filter, const char* name, int casesensitive);
extern Com_Filter_t Com_Filter;
typedef void (*DB_LoadXAssets_t)(XZoneInfo* zoneInfo, unsigned int zoneCount, int sync);
extern DB_LoadXAssets_t DB_LoadXAssets;
@ -40,9 +43,15 @@ namespace game
typedef void (*Dvar_SetString_t)(const dvar_t* dvar, const char* value);
extern Dvar_SetString_t Dvar_SetString;
typedef void (*Dvar_ForEach_t)(void (*callback)(const dvar_t*, void*), void* userData);
extern Dvar_ForEach_t Dvar_ForEach;
typedef const char* (*Dvar_DisplayableValue_t)(const dvar_t* dvar);
extern Dvar_DisplayableValue_t Dvar_DisplayableValue;
typedef const char* (*Dvar_DisplayableLatchedValue_t)(const dvar_t* dvar);
extern Dvar_DisplayableLatchedValue_t Dvar_DisplayableLatchedValue;
typedef int (*G_RunFrame_t)(int, int);
extern G_RunFrame_t G_RunFrame;
@ -212,6 +221,8 @@ namespace game
template <typename T, typename R>
constexpr auto VectorScale(T v, R s, T out) { out[0] = v[0] * s; out[1] = v[1] * s; out[2] = v[2] * s; }
int Vec4Compare(const float* a, const float* b);
namespace mp
{
typedef char* (*SV_GetGuid_t)(int clientNum);

View File

@ -611,6 +611,7 @@ namespace game
DVAR_CODINFO = 1 << 3,
DVAR_SCRIPTINFO = 1 << 4,
DVAR_SAVED = 1 << 6,
DVAR_USERINFO = 1 << 9,
DVAR_SERVERINFO = 1 << 10,
DVAR_INIT = 1 << 11,
DVAR_ROM = 1 << 13,
@ -629,6 +630,8 @@ namespace game
DVAR_TYPE_STRING = 0x7,
DVAR_TYPE_COLOR = 0x8,
DVAR_TYPE_FLOAT_3_COLOR = 0x9,
DVAR_TYPE_COUNT = 0xA
};
union DvarValue
@ -680,10 +683,17 @@ namespace game
DvarValue latched;
DvarValue reset;
DvarLimits domain;
bool (__cdecl *domainFunc)(dvar_t*, DvarValue);
bool (*domainFunc)(dvar_t*, DvarValue);
dvar_t* hashNext;
};
struct DvarDumpInfo
{
int count;
int channel;
const char* match;
};
struct Bounds
{
float midPoint[3];

View File

@ -77,6 +77,10 @@ public:
signature.process();
// Checks on startup
utils::hook::set<DWORD>(0x402ED0, 0xC301B0);
utils::hook::set<DWORD>(0x4b9280, 0xC301B0);
// Function fixup
utils::hook(0x4CA310, game::native::DB_LoadXAssets, HOOK_JUMP).install()->quick();

View File

@ -7,7 +7,6 @@
#include <utils/io.hpp>
#include "command.hpp"
#include "log_file.hpp"
utils::memory::allocator command::allocator_;
@ -369,33 +368,6 @@ void command::post_load()
}
add("quit", game::native::Com_Quit_f);
add("dvarDump", [](const params& params)
{
if (params.size() < 2)
{
return;
}
std::string file_name = "userraw/";
file_name.append(params.get(1));
if (!file_name.ends_with(".txt"))
{
file_name.append(".txt");
}
for (auto i = 0; i < *game::native::dvarCount; ++i)
{
const auto* dvar = game::native::sortedDvars[i];
if (dvar)
{
const auto* line = utils::string::va("%s \"%s\"\r\n", dvar->name, game::native::Dvar_DisplayableValue(dvar));
utils::io::write_file(file_name, line, i != 0);
}
}
log_file::info("%i dvars\n", *game::native::dvarCount);
});
if (game::is_mp())
{

205
src/module/dvar.cpp Normal file
View File

@ -0,0 +1,205 @@
#include <std_include.hpp>
#include <loader/module_loader.hpp>
#include "game/game.hpp"
#include "command.hpp"
#include "log_file.hpp"
#include "dvar.hpp"
int dvar::values_equal(unsigned char type, game::native::DvarValue val0, game::native::DvarValue val1)
{
switch (type)
{
case game::native::DVAR_TYPE_BOOL:
return val0.enabled == val1.enabled;
case game::native::DVAR_TYPE_FLOAT:
return val0.value == val1.value;
case game::native::DVAR_TYPE_FLOAT_2:
return val0.vector[0] == val1.vector[0] && val0.vector[1] == val1.vector[1];
case game::native::DVAR_TYPE_FLOAT_3:
case game::native::DVAR_TYPE_FLOAT_3_COLOR:
return val0.vector[0] == val1.vector[0] && val0.vector[1] == val1.vector[1] &&
val0.vector[2] == val1.vector[2] && val0.vector[3] == val1.vector[3];
case game::native::DVAR_TYPE_FLOAT_4:
return game::native::Vec4Compare(val0.vector, val1.vector);
case game::native::DVAR_TYPE_INT:
return val0.integer == val1.integer;
case game::native::DVAR_TYPE_ENUM:
return val0.integer == val1.integer;
case game::native::DVAR_TYPE_STRING:
assert(val0.string);
assert(val1.string);
return std::strcmp(val0.string, val1.string) == 0;
case game::native::DVAR_TYPE_COLOR:
return val0.integer == val1.integer;
default:
assert(0 && "unhandled dvar type");
return 0;
}
}
bool dvar::has_latched_value(const game::native::dvar_t* dvar)
{
return values_equal(dvar->type, dvar->current, dvar->latched) == 0;
}
void dvar::list_single(const game::native::dvar_t* dvar, void* user_data)
{
if ((user_data != nullptr) && !game::native::Com_Filter(static_cast<const char*>(user_data), dvar->name, 0))
{
return;
}
if (dvar->flags & game::native::DVAR_SERVERINFO)
{
log_file::info("S");
}
else
{
log_file::info(" ");
}
if (dvar->flags & game::native::DVAR_USERINFO)
{
log_file::info("U");
}
else
{
log_file::info(" ");
}
if (dvar->flags & game::native::DVAR_ROM)
{
log_file::info("R");
}
else
{
log_file::info(" ");
}
if (dvar->flags & game::native::DVAR_INIT)
{
log_file::info("I");
}
else
{
log_file::info(" ");
}
if (dvar->flags & game::native::DVAR_ARCHIVE)
{
log_file::info("A");
}
else
{
log_file::info(" ");
}
if (dvar->flags & game::native::DVAR_LATCH)
{
log_file::info("L");
}
else
{
log_file::info(" ");
}
if (dvar->flags & game::native::DVAR_CHEAT)
{
log_file::info("C");
}
else
{
log_file::info(" ");
}
log_file::info(" %s \"%s\"\n", dvar->name, game::native::Dvar_DisplayableValue(dvar));
}
void dvar::com_dvar_dump_single(const game::native::dvar_t* dvar, void* user_data)
{
char message[2048];
auto* dumpInfo = static_cast<game::native::DvarDumpInfo*>(user_data);
++dumpInfo->count;
if (dumpInfo->match && !game::native::Com_Filter(dumpInfo->match, dvar->name, 0))
{
return;
}
if (has_latched_value(dvar))
{
sprintf_s(message, " %s \"%s\" -- latched \"%s\"\n", dvar->name, game::native::Dvar_DisplayableValue(dvar), game::native::Dvar_DisplayableLatchedValue(dvar));
}
else
{
sprintf_s(message, " %s \"%s\"\n", dvar->name, game::native::Dvar_DisplayableValue(dvar));
}
log_file::info("%s", message);
}
void dvar::com_dvar_dump(int channel, const char* match)
{
game::native::DvarDumpInfo dump_info;
char summary[128];
if (!log_file::com_logfile->current.integer)
{
return;
}
log_file::info("=============================== DVAR DUMP ========================================\n");
dump_info.count = 0;
dump_info.channel = channel;
dump_info.match = match;
game::native::Dvar_ForEach(com_dvar_dump_single, &dump_info);
sprintf_s(summary, "\n%i total dvars\n%i dvar indexes\n", dump_info.count, *game::native::dvarCount);
log_file::info("%s", summary);
log_file::info("=============================== END DVAR DUMP =====================================\n");
}
void dvar::dump_f(const command::params& params)
{
const char* match;
if (params.size() > 1)
{
match = params.get(1);
}
else
{
match = nullptr;
}
com_dvar_dump(0, match);
}
void dvar::list_f(const command::params& params)
{
const char* match;
if (params.size() > 1)
{
match = params.get(1);
}
else
{
match = nullptr;
}
game::native::Dvar_ForEach(list_single, (void*)match);
log_file::info("\n%i total dvars\n", *game::native::dvarCount);
}
void dvar::post_load()
{
if (game::is_dedi())
{
return;
}
command::add("dvardump", dump_f);
command::add("dvarlist", list_f);
}
REGISTER_MODULE(dvar)

19
src/module/dvar.hpp Normal file
View File

@ -0,0 +1,19 @@
#pragma once
class dvar final : public module
{
public:
void post_load() override;
static int values_equal(unsigned char type, game::native::DvarValue val0, game::native::DvarValue val1);
static bool has_latched_value(const game::native::dvar_t* dvar);
private:
static void com_dvar_dump_single(const game::native::dvar_t* dvar, void* user_data);
static void com_dvar_dump(int channel, const char* match);
static void list_single(const game::native::dvar_t* dvar, void* user_data);
static void dump_f(const command::params& params);
static void list_f(const command::params& params);
};

View File

@ -8,13 +8,13 @@ public:
static void com_log_print_message(const std::string& msg);
static void info(const char* fmt, ...);
static const game::native::dvar_t* com_logfile;
private:
static const char* log_file_name;
static int opening_qconsole;
static int com_console_log_open_failed;
static const game::native::dvar_t* com_logfile;
static void com_open_log_file();
};