Files
sfall/sfall/Modules/Premade.cpp
T
NovaRain b72b26d292 Added language path for loading fonts (#368)
Some code fixes to support the language path.
2021-04-24 10:25:51 +08:00

119 lines
3.6 KiB
C++

/*
* sfall
* Copyright (C) 2009, 2010 The sfall team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "..\main.h"
#include "..\FalloutEngine\Fallout2.h"
#include "Message.h"
#include "Premade.h"
namespace sfall
{
static fo::PremadeChar* premade;
static const char* __fastcall GetLangPremadePath(const char* premadePath) {
static char premadeLangPath[56]; // premade\<language>\combat.bio
static bool isDefault = false;
static long len = 0;
if (isDefault) return nullptr;
if (len == 0) {
len = std::strlen(Message::GameLanguage());
if (len == 0 || len >= 32) {
isDefault = true;
return nullptr;
}
isDefault = (_stricmp(Message::GameLanguage(), "english") == 0);
if (isDefault) return nullptr;
std::strncpy(premadeLangPath, premadePath, 8);
std::strcpy(&premadeLangPath[8], Message::GameLanguage());
}
std::strcpy(&premadeLangPath[8 + len], &premadePath[7]);
return premadeLangPath;
}
static const char* __fastcall PremadeGCD(const char* premadePath) {
const char* path = GetLangPremadePath(premadePath);
return (path && fo::func::db_access(path)) ? path : premadePath;
}
static fo::DbFile* __fastcall PremadeBIO(const char* premadePath, const char* mode) {
premadePath = GetLangPremadePath(premadePath);
return (premadePath) ? fo::func::db_fopen(premadePath, mode) : nullptr;
}
static void __declspec(naked) select_display_bio_hook() {
__asm {
push eax;
push edx;
mov ecx, eax; // premade path
call PremadeBIO;
test eax, eax;
jz default;
add esp, 8;
retn;
default:
pop edx;
pop eax;
jmp fo::funcoffs::db_fopen_;
}
}
static void __declspec(naked) select_update_display_hook() {
__asm {
mov ecx, eax; // premade path
call PremadeGCD;
jmp fo::funcoffs::proto_dude_init_;
}
}
void Premade::init() {
auto premadePaths = IniReader::GetConfigList("misc", "PremadePaths", "", 512);
auto premadeFids = IniReader::GetConfigList("misc", "PremadeFIDs", "", 512);
if (!premadePaths.empty() && !premadeFids.empty()) {
dlog("Applying premade characters patch.", DL_INIT);
int count = min(premadePaths.size(), premadeFids.size());
premade = new fo::PremadeChar[count];
for (int i = 0; i < count; i++) {
auto path = "premade\\" + premadePaths[i];
if (path.size() > 19) {
dlog_f(" Failed: %s exceeds 11 characters\n", DL_INIT, premadePaths[i].c_str());
return;
}
std::strcpy(premade[i].path, path.c_str());
premade[i].fid = atoi(premadeFids[i].c_str());
}
SafeWrite32(0x51C8D4, count); // _premade_total
SafeWrite32(0x4A7D76, (DWORD)premade); // select_update_display_
SafeWrite32(0x4A8B1E, (DWORD)premade); // select_display_bio_
SafeWrite32(0x4A7E2C, (DWORD)&premade[0].fid); // select_display_portrait_
std::strcpy((char*)0x50AF68, premade[0].path); // for selfrun
dlogr(" Done", DL_INIT);
}
// Add language path for premade GCD/BIO files
HookCall(0x4A8B44, select_display_bio_hook);
HookCall(0x4A7D91, select_update_display_hook);
}
}