Skip to content
Draft
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
16 changes: 16 additions & 0 deletions codxe.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@
<ClCompile Include="src\game\t5\mp\components\scr_parser.cpp" />
<ClCompile Include="src\game\t5\mp\main.cpp" />

<ClCompile Include="src\game\t6\sp\components\scr_parser.cpp" />
<ClCompile Include="src\game\t6\sp\main.cpp" />

<ClCompile Include="src\game\t6\mp\components\scr_parser.cpp" />
<ClCompile Include="src\game\t6\mp\main.cpp" />

<ClCompile Include="src\game\qos\sp\main.cpp" />
<ClCompile Include="src\game\qos\sp\components\scr_parser.cpp" />

Expand Down Expand Up @@ -313,6 +319,16 @@
<ClInclude Include="src\game\t5\mp\structs.h" />
<ClInclude Include="src\game\t5\mp\symbols.h" />

<ClInclude Include="src\game\t6\sp\components\scr_parser.h" />
<ClInclude Include="src\game\t6\sp\main.h" />
<ClInclude Include="src\game\t6\sp\structs.h" />
<ClInclude Include="src\game\t6\sp\symbols.h" />

<ClInclude Include="src\game\t6\mp\components\scr_parser.h" />
<ClInclude Include="src\game\t6\mp\main.h" />
<ClInclude Include="src\game\t6\mp\structs.h" />
<ClInclude Include="src\game\t6\mp\symbols.h" />

<ClInclude Include="src\game\qos\sp\main.h" />
<ClInclude Include="src\game\qos\sp\components\scr_parser.h" />
<ClInclude Include="src\game\qos\sp\structs.h" />
Expand Down
Binary file not shown.
3 changes: 3 additions & 0 deletions resources/t6/_codxe/codxe.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"active_mod": "example"
}
66 changes: 66 additions & 0 deletions resources/t6/_codxe/mods/example/maps/mp/gametypes/_clientids.gsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
init()
{
level.clientid = 0;
level thread onPlayerConnect();
}

onPlayerConnect()
{
for (;;)
{
level waittill("connecting", player);

player.clientid = level.clientid;
level.clientid++;

player thread onPlayerSpawned();
}
}

onPlayerSpawned()
{
self endon("disconnect");
level endon("game_ended");

for (;;)
{
self waittill("spawned_player");

self iprintlnbold(rainbow_text("Welcome to the Example Mod !"));
}
}

rainbow_text(str)
{
if (!isDefined(str))
return "";

colors = [];
colors[colors.size] = "^1"; // Red
colors[colors.size] = "^2"; // Green
colors[colors.size] = "^3"; // Yellow
colors[colors.size] = "^4"; // Blue
colors[colors.size] = "^5"; // Cyan
colors[colors.size] = "^6"; // Pink
colors[colors.size] = "^7"; // White

rainbow = "";
colorCount = colors.size;
colorIndex = 0;

for (i = 0; i < str.size; i++)
{
ch = str[i];
if (ch == " ")
{
rainbow += ch;
continue;
}

color = colors[colorIndex % colorCount];
rainbow += color + ch;
colorIndex++;
}

return rainbow;
}
Binary file not shown.
15 changes: 15 additions & 0 deletions resources/xenia/plugins/415608C3/plugins.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
title_name = "Call of Duty: Black Ops II"
title_id = "415608C3" # AV-2243
#media_id = "05C7492A" # Disc (World): http://redump.org/disc/37078/

# TU18

[[plugin]]
file = "codxe.xex"
hash = "B56F16A83B7E7CCC" # default.xex
is_enabled = true

[[plugin]]
file = "codxe.xex"
hash = "5699D5C3866AD7DF" # default_mp.xex
is_enabled = true
63 changes: 63 additions & 0 deletions src/game/t6/mp/components/scr_parser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include "pch.h"
#include "scr_parser.h"

namespace t6
{
namespace mp
{

Detour Load_ScriptParseTreeAsset_Detour;

void Load_ScriptParseTreeAsset_Hook(ScriptParseTree **a1)
{
ScriptParseTree *scriptParseTree = *a1;
DbgPrint("GSCLoader: Loading script %s\n", scriptParseTree->name);

std::string modBasePath = Config::GetModBasePath();
if (!modBasePath.empty())
{
std::string overridePath = modBasePath + "\\" + scriptParseTree->name + "bin";
std::replace(overridePath.begin(), overridePath.end(), '/', '\\');
DbgPrint("GSCLoader: Checking for override script at %s\n", overridePath.c_str());

HANDLE file = CreateFileA(overridePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);

if (file != INVALID_HANDLE_VALUE)
{
DWORD fileSize = GetFileSize(file, NULL);
if (fileSize != INVALID_FILE_SIZE && fileSize > 0)
{
char *buffer = new char[fileSize];
DWORD bytesRead = 0;
if (ReadFile(file, buffer, fileSize, &bytesRead, NULL) && bytesRead == fileSize)
{
scriptParseTree->buffer = buffer;
scriptParseTree->len = fileSize;
DbgPrint("GSCLoader: Overridden script loaded (%d bytes)\n", fileSize);
}
else
{
delete[] buffer;
DbgPrint("GSCLoader: Failed to read override script\n");
}
}
CloseHandle(file);
}
}

Load_ScriptParseTreeAsset_Detour.GetOriginal<decltype(Load_ScriptParseTreeAsset)>()(a1);
}

scr_parser::scr_parser()
{
Load_ScriptParseTreeAsset_Detour = Detour(Load_ScriptParseTreeAsset, Load_ScriptParseTreeAsset_Hook);
Load_ScriptParseTreeAsset_Detour.Install();
}

scr_parser::~scr_parser()
{
Load_ScriptParseTreeAsset_Detour.Remove();
}
} // namespace mp
} // namespace t6
21 changes: 21 additions & 0 deletions src/game/t6/mp/components/scr_parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include "pch.h"

namespace t6
{
namespace mp
{
class scr_parser : public Module
{
public:
scr_parser();
~scr_parser();

const char *get_name() override
{
return "scr_parser";
};
};
} // namespace mp
} // namespace t6
16 changes: 16 additions & 0 deletions src/game/t6/mp/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "pch.h"
#include "components/scr_parser.h"
#include "main.h"

namespace t6
{
namespace mp
{
T6_MP_Plugin::T6_MP_Plugin()
{
DbgPrint("T6 MP: Registering modules\n");
RegisterModule(new Config());
RegisterModule(new scr_parser());
}
} // namespace mp
} // namespace t6
13 changes: 13 additions & 0 deletions src/game/t6/mp/main.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

namespace t6
{
namespace mp
{
class T6_MP_Plugin : public Plugin
{
public:
T6_MP_Plugin();
};
} // namespace mp
} // namespace t6
13 changes: 13 additions & 0 deletions src/game/t6/mp/structs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

namespace t6
{
namespace mp
{
enum scriptInstance_t : __int32
{
SCRIPTINSTANCE_SERVER = 0x0,
SCRIPTINSTANCE_CLIENT = 0x1,
};
} // namespace mp
} // namespace t6
25 changes: 25 additions & 0 deletions src/game/t6/mp/symbols.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include "structs.h"

namespace t6
{
namespace mp
{
static auto Hunk_AllocateTempMemoryHighInternal = reinterpret_cast<void *(*)(int size)>(0x8248F1B0);

static auto Scr_AddSourceBuffer =
reinterpret_cast<char *(*)(scriptInstance_t inst, const char *filename, const char *extFilename,
const char *codePos, bool archive)>(0x82530128);

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

static auto Load_ScriptParseTreeAsset = reinterpret_cast<void (*)(ScriptParseTree **a1)>(0x822CA4C8);

} // namespace mp
} // namespace t6
73 changes: 73 additions & 0 deletions src/game/t6/sp/components/scr_parser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include "pch.h"
#include "scr_parser.h"

namespace t6
{
namespace sp
{
Detour Scr_AddSourceBuffer_Detour;

char *Scr_AddSourceBuffer_Hook(scriptInstance_t inst, const char *filename, const char *extFilename,
const char *codePos, bool archive)
{
auto callOriginal = [&]()
{
return Scr_AddSourceBuffer_Detour.GetOriginal<decltype(Scr_AddSourceBuffer)>()(inst, filename, extFilename,
codePos, archive);
};

if (Config::dump_rawfile)
{
DbgPrint("GSCLoader: Dumping script %s\n", extFilename);
auto contents = callOriginal();
if (contents)
{
// Dump the script to a file
std::string dumpPath = std::string(DUMP_DIR) + "\\" + extFilename;
std::replace(dumpPath.begin(), dumpPath.end(), '/', '\\');
filesystem::write_file_to_disk(dumpPath.c_str(), contents, std::strlen(contents));
DbgPrint("GSCLoader: Dumped script to %s\n", dumpPath.c_str());
}

return contents;
}

// Check if mod is active
std::string modBasePath = Config::GetModBasePath();
if (modBasePath.empty())
return callOriginal();

// Build full path to override file
std::string overridePath = modBasePath + "\\" + extFilename;
std::replace(overridePath.begin(), overridePath.end(), '/', '\\');

// Try to load override file
std::string fileContent = filesystem::read_file_to_string(overridePath);
if (fileContent.empty())
return callOriginal();

// Allocate buffer using game's memory allocator
char *buffer = (char *)Hunk_AllocateTempMemoryHighInternal(fileContent.size() + 1);
if (!buffer)
return callOriginal();

// Copy content and null terminate
memcpy(buffer, fileContent.c_str(), fileContent.size());
buffer[fileContent.size()] = '\0';

DbgPrint("GSCLoader: Loaded override script: %s\n", overridePath.c_str());
return buffer;
}

scr_parser::scr_parser()
{
Scr_AddSourceBuffer_Detour = Detour(Scr_AddSourceBuffer, Scr_AddSourceBuffer_Hook);
Scr_AddSourceBuffer_Detour.Install();
}

scr_parser::~scr_parser()
{
Scr_AddSourceBuffer_Detour.Remove();
}
} // namespace sp
} // namespace t6
21 changes: 21 additions & 0 deletions src/game/t6/sp/components/scr_parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include "pch.h"

namespace t6
{
namespace sp
{
class scr_parser : public Module
{
public:
scr_parser();
~scr_parser();

const char *get_name() override
{
return "scr_parser";
};
};
} // namespace sp
} // namespace t6
16 changes: 16 additions & 0 deletions src/game/t6/sp/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "pch.h"
#include "components/scr_parser.h"
#include "main.h"

namespace t6
{
namespace sp
{
T6_SP_Plugin::T6_SP_Plugin()
{
DbgPrint("T6 SP: Registering modules\n");
RegisterModule(new Config());
RegisterModule(new scr_parser());
}
} // namespace sp
} // namespace t6
Loading
Loading