Skip to content

Commit

Permalink
update readme and get rid of xorstr
Browse files Browse the repository at this point in the history
  • Loading branch information
p0358 committed Jun 1, 2024
1 parent f82e6dd commit 129ac5c
Show file tree
Hide file tree
Showing 17 changed files with 60 additions and 278 deletions.
43 changes: 23 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
# Black Market Edition

Black Market Edition is a multi-purpose community enhancement mod for Titanfall game, featuring various quality-of-life changes and improvements.
Black Market Edition is a client-side multi-purpose community enhancement mod for Titanfall game, featuring various tons of quality-of-life changes and improvements.

**NOTE:** It is NOT yet finished (but is getting very close there), there are a few chore tasks needed before so. However it works as-is for the most part.

Open sourcing this for now regardless, because I slowly worked on it since 2019 and I am not sure if I will ever get a chance to finish it in the current situation.
Note that this mod is meant for playing on vanilla game and does not include game servers.

## Installation

Expand Down Expand Up @@ -61,7 +59,6 @@ Installers are built with Inno Setup using scripts from installer/ folder and th
### Known bugs

* pressing M to activate burn cards seems to activate the full screen map instead for some reason
* registering custom new Squirrel functions in native code doesn't work, but we don't really need it currently
* setting private match settings sliders to the edge unprecisely might apply a wrong setting (which will be shown within a second)

## Screenshots
Expand Down Expand Up @@ -132,37 +129,43 @@ Showing whether you're playing first or second half in switch-sides-based gamemo

## Compiling

1. Clone the repo with `git clone --recursive --depth 1 -j8 https://github.com/p0358/black_market_edition.git`
1. Clone the repo with `git clone --recursive --depth 1 https://github.com/p0358/black_market_edition.git`
2. Run `generate.bat` to generate Visual Studio project files
3. Run `copy_scripts_to_r1_modsrc.bat` to copy needed files from `bme_scripts` into `r1_modsrc`.
4. Run `build_assets.bat` to package `r1_modsrc` dir contents into `installer/source/bme/bme.bsp` and generate file list header file
5. Build the solution (`./build/bme.sln`) in VS 2022 (alternatively run `msbuild build\bme.sln -m`).
6. Look at `installer/installer_simple2.iss` to figure out which files go where (copy `bme.dll` and `Titanfall_alt.exe` most importantly).
7. Optionally build the installer (instructions below).

### Building an installer
Note: if you add/remove files in `r1_modsrc`, you need to re-compile the DLL too (as that includes the list of available files).

After doing the steps above, with Inno Setup compile out `installer/installer_simple2.iss` (or use `build_installer.bat` script if you have `iscc` in your path). The resulting installer will be in `installer/bme_installer.exe`.
### Building an installer

To build an installer for full mod, you need to look into the file `installer/installer_simple2.iss` and copy the required files into `installer/source` dir manually.
To build an installer for full mod, after doing the steps above, you need to look into the file `installer/installer_simple2.iss` and copy the required files into `installer/source` dir manually.

Under `source/bme`, copy the compiled `bme.dll` and create an empty file `bme.log`. Also create `bme_channel.txt` with the value `release`. Get `bme.bsp` from latest release in the Releases section (this file contains the filesystem replacement contents, that is scripts and some UI elements, into PakFile as lump 40 in bsp format, which can be easily mounted in the engine). Copy the built `launcher.dll` into `source/bin/x64_retail/`.
1. Under `installer/source/bme/`, copy the compiled `bme.dll` (from `build/x64-<CHANNEL>/bin/bme.dll`).
2. Also create `bme_channel.txt` with the value `staging` (or `release`).
3. `bme.bsp` should already be there after step #4 of compiling above (this file contains the filesystem replacement contents, that is scripts and some UI elements, into PakFile as lump 40 in bsp format, which can be easily mounted in the engine).
4. Copy the built `launcher.dll` into `installer/source/bin/x64_retail/` and `Titanfall_alt.exe` into `installer/source/`.
5. With Inno Setup compile out `installer/installer_simple2.iss` (or use `build_installer.bat` script if you have `iscc` in your path). The resulting installer will be in `installer/bme_installer.exe`.

## Acknowledgements

Parts of code from [TTF2SDK by James Wilkinson and Will Donohoe](https://github.com/Titanfall-Mods/TTF2SDK/blob/master/LICENSE.md) were used.

Black Market Edition makes use of the following third-party libraries:

| Package Name | URL |
|---------------|----------------------------------------------------------------------|
| curl | https://curl.se/docs/copyright.html |
| discord-rpc | https://github.com/harmonytf/discord-rpc/blob/master/LICENSE |
| sentry-native | https://github.com/getsentry/sentry-native/blob/master/LICENSE |
| crashpad | https://chromium.googlesource.com/crashpad/crashpad/+/master/LICENSE |
| imgui | https://github.com/ocornut/imgui/blob/master/LICENSE.txt |
| MinHook | https://github.com/TFORevive/minhook/blob/master/LICENSE.txt |
| rapidjson | https://github.com/Tencent/rapidjson/blob/master/license.txt |
| spdlog | https://github.com/gabime/spdlog/blob/v1.x/LICENSE |
| Package Name | URL |
|-------------------------|----------------------------------------------------------------------------|
| crashpad | https://chromium.googlesource.com/crashpad/crashpad/+/master/LICENSE |
| curl | https://curl.se/docs/copyright.html |
| discord-rpc | https://github.com/harmonytf/discord-rpc/blob/master/LICENSE |
| imgui | https://github.com/ocornut/imgui/blob/master/LICENSE.txt |
| InnoDependencyInstaller | https://github.com/DomGries/InnoDependencyInstaller/blob/master/LICENSE.md |
| MinHook | https://github.com/TFORevive/minhook/blob/master/LICENSE.txt |
| nghttp2 | https://github.com/nghttp2/nghttp2/blob/master/COPYING |
| sentry-native | https://github.com/getsentry/sentry-native/blob/master/LICENSE |
| spdlog | https://github.com/gabime/spdlog/blob/v1.x/LICENSE |
| rapidjson | https://github.com/Tencent/rapidjson/blob/master/license.txt |

TITANFALL™ is a trademark of Respawn Entertainment, LLC.
2 changes: 1 addition & 1 deletion bmedll/BMEGUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ BMEGUI::BMEGUI(ConCommandManager& conCommandManager, UIManager& uiManager/*, Squ

BMEGUI::~BMEGUI()
{
SPDLOG_LOGGER_DEBUG(spdlog::get(_("logger")), "BMEGUI destructor");
spdlog::debug("BMEGUI destructor");
m_uiManager->RemoveDrawCallback("UpdaterDownloadProgress");
m_uiManager->RemoveDrawCallback("DrawUpdaterLaunchingSplashScreen");
}
Expand Down
2 changes: 0 additions & 2 deletions bmedll/ConCommandManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ ConCommandManager::ConCommandManager() noexcept

void ConCommandManager::RegisterCommand(const char* name, void(*callback)(const CCommand&), const char* helpString, int flags)
{
//m_logger->info(_("Adding console command: {}"), name);
SPDLOG_LOGGER_DEBUG(m_logger, "Adding console command: {}", name);
m_commands.emplace_back();
ConCommand* newCommand = &m_commands.back();
Expand All @@ -24,7 +23,6 @@ void ConCommandManager::RegisterCommand(const char* name, void(*callback)(const

ConVar* ConCommandManager::RegisterConVar(const char* name, const char* defaultValue, int flags, const char* helpString)
{
//m_logger->info(_("Adding cvar: {}"), name);
SPDLOG_LOGGER_DEBUG(m_logger, "Adding cvar: {}", name);
m_cvars.emplace_back();
ConVar2* newCvar = &m_cvars.back();
Expand Down
2 changes: 1 addition & 1 deletion bmedll/CrashReporting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include "tier0.h"

// this sig may be wrong
SigScanFunc<void*, _se_translator_function> engine_set_se_translator(_("engine.dll"), "\x48\x89\x5C\x24\x00\x57\x48\x83\xEC\x00\x48\x8B\xF9\xE8\x00\x00\x00\x00\x48\x8B\x98\x00\x00\x00\x00", "xxxx?xxxx?xxxx????xxx????");
SigScanFunc<void*, _se_translator_function> engine_set_se_translator("engine.dll", "\x48\x89\x5C\x24\x00\x57\x48\x83\xEC\x00\x48\x8B\xF9\xE8\x00\x00\x00\x00\x48\x8B\x98\x00\x00\x00\x00", "xxxx?xxxx?xxxx????xxx????");
FuncStatic<void*, _se_translator_function> engine_set_se_translator2("engine.dll", 0x56BC04);

void TranslatorFunc(unsigned int, struct _EXCEPTION_POINTERS* exinfo)
Expand Down
8 changes: 4 additions & 4 deletions bmedll/Discord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,9 @@ void DiscordWrapper::handleDiscordJoinRequest(const DiscordUser* request)
const char* map = SDK().GetPresence().map;
if (map && *map && std::strcmp(map, "mp_lobby") == 0)
{
Chat::showChatLineEasy(_("\n[Discord] "), 0xFF7289DA);
Chat::showChatLineEasy("\n[Discord] ", 0xFF7289DA);
Chat::showChatLineEasy(request->username, 0xFFDDDDDD);
Chat::showChatLineEasy(_(" asked to join your game. You can accept this request in Discord."), 0xFFFFFFFF);
Chat::showChatLineEasy(" asked to join your game. You can accept this request in Discord.", 0xFFFFFFFF);
}
}
//Discord_Respond(request->userId, response); // response = DISCORD_REPLY_YES / _NO
Expand All @@ -189,9 +189,9 @@ void DiscordWrapper::handleDiscordInvited(/* DISCORD_ACTIVITY_ACTION_TYPE_ */ in
const char* map = SDK().GetPresence().map;
if (map && *map && std::strcmp(map, "mp_lobby") == 0)
{
Chat::showChatLineEasy(_("\n[Discord] "), 0x7289DAFF);
Chat::showChatLineEasy("\n[Discord] ", 0x7289DAFF);
Chat::showChatLineEasy(user->username, 0xDDDDDDFF);
Chat::showChatLineEasy(_(" invited you to join their game. You can accept this invite in Discord."), 0xFFFFFFFF);
Chat::showChatLineEasy(" invited you to join their game. You can accept this invite in Discord.", 0xFFFFFFFF);
}
}
//Discord_AcceptInvite(user->userId, type, sessionId, channelId, messageId);
Expand Down
2 changes: 1 addition & 1 deletion bmedll/FileSystemManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ FileSystemManager::FileSystemManager(const std::string& basePath)

FileSystemManager::~FileSystemManager()
{
SPDLOG_LOGGER_DEBUG(spdlog::get(_("logger")), "FileSystemManager destructor");
SPDLOG_LOGGER_DEBUG(m_logger, "FileSystemManager destructor");
IFileSystem_AddSearchPath.Unhook();
IFileSystem_ReadFromCache.Unhook();
IFileSystem_MountVPK.Unhook();
Expand Down
4 changes: 2 additions & 2 deletions bmedll/Preloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ DWORD WINAPI precachePlaylists(PVOID pThreadParameter)
std::string response_string;
std::string header_string;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFunction);
curl_easy_setopt(curl, CURLOPT_USERAGENT, _("Respawn HTTPS/1.0"));
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Respawn HTTPS/1.0");
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_string);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header_string);

Expand Down Expand Up @@ -66,7 +66,7 @@ DWORD WINAPI precachePlaylists(PVOID pThreadParameter)
loadPlaylists(response_string.c_str());
}
//MessageBoxA(0, ss.str().c_str(), "Loaded playlists", 0);
SPDLOG_LOGGER_DEBUG(logger, _("[Preloader] Preloaded playlists"));
SPDLOG_LOGGER_DEBUG(logger, "[Preloader] Preloaded playlists");
}
else
{
Expand Down
8 changes: 4 additions & 4 deletions bmedll/Presence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -672,10 +672,10 @@ HookedFuncStatic<int64_t __fastcall, int64_t, void*, uint64_t*, void*> _originEv

Presence::Presence()
{
m_logger = spdlog::get(_("logger"));
m_logger = spdlog::get("logger");
//auto enginedllBaseAddress = *engineClient->ba;
auto enginedllBaseAddress = Util::GetModuleBaseAddress(_("engine.dll"));
auto clientdllBaseAddress = Util::GetModuleBaseAddress(_("client.dll"));
auto enginedllBaseAddress = Util::GetModuleBaseAddress("engine.dll");
auto clientdllBaseAddress = Util::GetModuleBaseAddress("client.dll");
isConnectedAndInLobby = (int*)(enginedllBaseAddress + 0x79725C);
teamNum = (int*)(enginedllBaseAddress + 0x797260);
match_playlist = (const char*)(enginedllBaseAddress + 0x2EDABB0);
Expand Down Expand Up @@ -724,7 +724,7 @@ Presence::Presence()

Presence::~Presence()
{
SPDLOG_LOGGER_DEBUG(spdlog::get(_("logger")), "Presence destructor");
SPDLOG_LOGGER_DEBUG(m_logger, "Presence destructor");
_updatePresence2.Unhook();
_sub_180473500.Unhook();
}
Expand Down
4 changes: 2 additions & 2 deletions bmedll/SourceConsole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,9 @@ void SourceConsole::OnCommandSubmittedHook(CConsoleDialog* consoleDialog, const
if (!IsConsoleAvailable() || !m_gameConsole->IsConsoleVisible())
return;

//Print(_("] "));
//Print("] ");
//Print(pCommand);
//Print(_("\n"));
//Print("\n");
m_logger->info("] {}", pCommand);

CConsoleDialog_OnCommandSubmitted(consoleDialog, pCommand);
Expand Down
24 changes: 13 additions & 11 deletions bmedll/TTFSDK.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,14 +280,14 @@ void TTFSDK::Init()

#if 0
/*{ // patch the restriction "Can't send client command; not connected to a server" of ClientCommand in script
void* ptr = (void*)(Util::GetModuleBaseAddress(_("client.dll")) + 0x2DB33B);
void* ptr = (void*)(Util::GetModuleBaseAddress("client.dll") + 0x2DB33B);
TempReadWrite rw(ptr);
*((unsigned char*)ptr) = 0xEB;
}*/

/*{ // FOV range patch
{
void* ptr = (void*)(Util::GetModuleBaseAddress(_("engine.dll")) + 0x6C6D34);
void* ptr = (void*)(Util::GetModuleBaseAddress("engine.dll") + 0x6C6D34);
TempReadWrite rw(ptr);
*((float*)ptr) = 2.5f; // will work only before cvar is registered
}
Expand All @@ -297,22 +297,22 @@ void TTFSDK::Init()
//*(float*)((DWORD64)fov + 100) = 0.5f; // min
}*/
{ // FOV range patch 2
void* ptr = (void*)(Util::GetModuleBaseAddress(_("engine.dll")) + 0x31A1BE0 + 108);
//void* ptr = (void*)(*((unsigned __int64*)(Util::GetModuleBaseAddress(_("engine.dll")) + 0x31A1BE0)) + 108);
void* ptr = (void*)(Util::GetModuleBaseAddress("engine.dll") + 0x31A1BE0 + 108);
//void* ptr = (void*)(*((unsigned __int64*)(Util::GetModuleBaseAddress("engine.dll") + 0x31A1BE0)) + 108);
TempReadWrite rw(ptr);
*((float*)ptr) = 2.5f;
}
#endif

this->origin = (TFOrigin*)(Util::GetModuleBaseAddress(_("engine.dll")) + 0x2ECB770);
this->origin = (TFOrigin*)(Util::GetModuleBaseAddress("engine.dll") + 0x2ECB770);

/*{
std::string game_s3_url{ _("bme.titanfall.top/backend/game_s3.php/ver=") };
std::string game_s3_url{ "bme.titanfall.top/backend/game_s3.php/ver=" };
game_s3_url += BME_VERSION;
game_s3_url += _("/chan=");
game_s3_url += "/chan=";
game_s3_url += GetBMEChannel();
game_s3_url += "/";
std::string cmd{ _("staticfile_hostname ") };
std::string cmd{ "staticfile_hostname " };
cmd += game_s3_url;
//ConVar* staticfile_hostname = m_vstdlibCvar->FindVar("staticfile_hostname");
//staticfile_hostname->SetValueString(game_s3_url.c_str());
Expand Down Expand Up @@ -372,7 +372,7 @@ void __fastcall TTFSDK::RunFrameHook(__int64 a1, double frameTime)
if (!called)
{
runFrameHookCalled = true;
m_logger->info(_("RunFrame called for the first time"));
m_logger->info("RunFrame called for the first time");
called = true;
Updater::drawModalWillUpdaterLaunchAfterGameClose = false;
m_sourceConsole->InitializeSource();
Expand All @@ -386,8 +386,8 @@ void __fastcall TTFSDK::RunFrameHook(__int64 a1, double frameTime)
}

{ // FOV range patch 2
void* ptr = (void*)(Util::GetModuleBaseAddress(_("engine.dll")) + 0x31A1BE0 + 108);
//void* ptr = (void*)(*((unsigned __int64*)(Util::GetModuleBaseAddress(_("engine.dll")) + 0x31A1BE0)) + 108);
void* ptr = (void*)(Util::GetModuleBaseAddress("engine.dll") + 0x31A1BE0 + 108);
//void* ptr = (void*)(*((unsigned __int64*)(Util::GetModuleBaseAddress("engine.dll") + 0x31A1BE0)) + 108);
TempReadWrite rw(ptr);
*((float*)ptr) = 2.5f;
}
Expand Down Expand Up @@ -582,6 +582,8 @@ bool SetupLogger()

spdlog::info("Logger has been initialized at {}.", strtok(std::ctime(&time), "\n"));
spdlog::info("Raw command line: {}", GetCommandLineA());
spdlog::info("BME version: " BME_VERSION);
spdlog::info("BME channel: " BME_CHANNEL);

spdlog::info("CPU: {}", Util::GetProcessorNameString());
bool ishdd = Util::DoesStorageDeviceIncurSeekPenaltyAtPath((basePath / L"vpk" / L"client_mp_common.bsp.pak000_000.vpk").wstring().c_str());
Expand Down
6 changes: 3 additions & 3 deletions bmedll/UIManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ UIManager::UIManager(ConCommandManager& conCommandManager/*, SquirrelManager& sq

UIManager::~UIManager()
{
SPDLOG_LOGGER_DEBUG(spdlog::get(_("logger")), "UIManager destructor");
SPDLOG_LOGGER_DEBUG(m_logger, "UIManager destructor");
IDXGISwapChain_Present.Unhook();
GameWindowProc.Unhook();
ISurface_SetCursor.Unhook();
Expand Down Expand Up @@ -286,7 +286,7 @@ int UIManager::WindowProcHook(void* game, HWND hWnd, UINT uMsg, WPARAM wParam, L

if (uMsg == WM_ENDSESSION && lParam == ENDSESSION_CLOSEAPP)
{
/*SPDLOG_LOGGER_DEBUG(spdlog::get(_("logger")), "WM_ENDSESSION");
/*SPDLOG_DEBUG("WM_ENDSESSION");
isProcessTerminating = true;
SDK().GetEngineClient()->ClientCmd_Unrestricted("quit");
if (!SDK().runFrameHookCalled)
Expand All @@ -300,7 +300,7 @@ int UIManager::WindowProcHook(void* game, HWND hWnd, UINT uMsg, WPARAM wParam, L

if (uMsg == WM_CLOSE)
{
/*SPDLOG_LOGGER_DEBUG(spdlog::get(_("logger")), "WM_CLOSE");
/*SPDLOG_DEBUG("WM_CLOSE");
isProcessTerminating = true;
if (&SDK() != nullptr && SDK().GetEngineClient() != nullptr && SDK().GetEngineClient() != NULL)
SDK().GetEngineClient()->ClientCmd_Unrestricted("quit");
Expand Down
2 changes: 1 addition & 1 deletion bmedll/Updater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ namespace Updater {
if (&SDK() != nullptr && SDK().runFrameHookCalled)
{
//pendingUpdateLaunch = true;
//logger->info(_("Game is already launched, delaying update until it's quit."));
//logger->info("Game is already launched, delaying update until it's quit.");
}
else
{
Expand Down
6 changes: 3 additions & 3 deletions bmedll/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,12 +452,12 @@ void DoBinaryPatches()
}
{ // FOV range patch 2
void* ptr = (void*)(Util::GetModuleBaseAddress("engine.dll") + 0x31A1BE0 + 108);
//void* ptr = (void*)(*((unsigned __int64*)(Util::GetModuleBaseAddress(_("engine.dll")) + 0x31A1BE0)) + 108);
//void* ptr = (void*)(*((unsigned __int64*)(Util::GetModuleBaseAddress("engine.dll") + 0x31A1BE0)) + 108);
TempReadWrite rw(ptr);
*((float*)ptr) = 3.85f;
}
{ // FOV range patch
void* ptr = (void*)(Util::GetModuleBaseAddress(_("client.dll")) + 0x9CDB74);
void* ptr = (void*)(Util::GetModuleBaseAddress("client.dll") + 0x9CDB74);
TempReadWrite rw(ptr);
*((float*)ptr) = 3.85f; // will work only before cvar is registered
}
Expand Down Expand Up @@ -527,7 +527,7 @@ void DoBinaryPatches()
{
// default is m_bRestrictServerCommands=true, don't let it be set to false
// this is the easiest way that at the same time allows m_bRestrictClientCommands to be false
void* ptr = (void*)(Util::GetModuleBaseAddress(_("engine.dll")) + 0x19C516);
void* ptr = (void*)(Util::GetModuleBaseAddress("engine.dll") + 0x19C516);
TempReadWrite rw(ptr);
memset(ptr, 0x90, 0x19C523 - 0x19C516);
}*/
Expand Down
2 changes: 0 additions & 2 deletions bmedll/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ using namespace std::literals::string_view_literals;
#include <imgui/backends/imgui_impl_win32.h>

#include <MinHook.h>
#include <xorstr.hpp>
#define _(str) xorstr_(str)

#include <curl/curl.h>
#include <curl/easy.h>
Expand Down
2 changes: 1 addition & 1 deletion loader_launcher_exe/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ void SetMitigationPolicies()
bool result = SetProcessMitigationPolicy(MitigationPolicy, lpBuffer, dwLength);
if (!result)
{
auto lastError = GetLastError();
if (MitigationPolicy == ProcessUserShadowStackPolicy && !DoesCpuSupportCetShadowStack())
return;
auto lastError = GetLastError();
MessageBoxA(0, ("Failed mitigation: "
+ (g_mitigationPolicyNames.contains(MitigationPolicy) ? g_mitigationPolicyNames[MitigationPolicy] : std::to_string(MitigationPolicy))
+ ", error: " + std::to_string(lastError) + "\n\nThis is a non-fatal error.").c_str(),
Expand Down
Loading

0 comments on commit 129ac5c

Please sign in to comment.