Added language path for loading fonts (#368)

Some code fixes to support the language path.
This commit is contained in:
NovaRain
2021-04-25 08:36:36 +08:00
parent c34b910e9c
commit 4ce513f42f
14 changed files with 134 additions and 65 deletions
+1
View File
@@ -6,6 +6,7 @@
UseCommandLine=0
;Uncomment and point to a file to get alternate translations for some sfall messages
;This file can be placed in text\<language>\ for sfall to get the translations depending on the game language
;TranslationsINI=sfall\Translations.ini
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+51 -8
View File
@@ -508,18 +508,52 @@ long __fastcall fo_get_game_config_string(const char** outValue, const char* sec
static MSGNode messageBuf;
const char* GetMessageStr(const MSGList* fileAddr, long messageId) {
return fo_getmsg(fileAddr, &messageBuf, messageId);
const char* GetMessageStr(const MSGList* file, long messageId) {
return fo_getmsg(file, &messageBuf, messageId);
}
const char* MessageSearch(const MSGList* fileAddr, long messageId) {
const char* MessageSearch(const MSGList* file, long messageId) {
messageBuf.number = messageId;
if (fo_message_search(fileAddr, &messageBuf) == 1) {
if (fo_message_search(file, &messageBuf) == 1) {
return messageBuf.message;
}
return nullptr;
}
MSGNode* GetMsgNode(MSGList* msgList, int msgNum) {
if (msgList != nullptr && msgList->numMsgs > 0) {
MSGNode *msgNode = msgList->nodes;
long last = msgList->numMsgs - 1;
long first = 0;
long mid;
// Use Binary Search to find msg
while (first <= last) {
mid = (first + last) / 2;
if (msgNum > msgNode[mid].number)
first = mid + 1;
else if (msgNum < msgNode[mid].number)
last = mid - 1;
else
return &msgNode[mid];
}
}
return nullptr;
}
// Alternative version of getmsg_ function
char* GetMsg(MSGList* msgList, int msgNum, int msgType) {
MSGNode *msgNode = GetMsgNode(msgList, msgNum);
if (msgNode) {
if (msgType == 2) {
return msgNode->message;
} else if (msgType == 1) {
return msgNode->audio;
}
}
return nullptr;
}
Queue* QueueFind(TGameObj* object, long type) {
if (*ptr_queue) {
Queue* queue = *ptr_queue;
@@ -981,14 +1015,23 @@ static bool LoadFrmFrame(UNLSTDfrm::Frame *frame, DbFile* frmStream) {
UNLSTDfrm *LoadUnlistedFrm(char *frmName, unsigned int folderRef) {
if (folderRef > OBJ_TYPE_SKILLDEX) return nullptr;
char *artfolder = ptr_art[folderRef].path; // address of art type name
char FrmPath[MAX_PATH];
const char *artfolder = ptr_art[folderRef].path; // address of art type name
char frmPath[MAX_PATH];
sprintf_s(FrmPath, MAX_PATH, "art\\%s\\%s", artfolder, frmName);
if (*ptr_use_language) {
sprintf_s(frmPath, MAX_PATH, "art\\%s\\%s\\%s", (const char*)ptr_language, artfolder, frmName);
} else {
sprintf_s(frmPath, MAX_PATH, "art\\%s\\%s", artfolder, frmName);
}
UNLSTDfrm *frm = new UNLSTDfrm;
DbFile* frmStream = fo_xfopen(FrmPath, "rb");
DbFile* frmStream = fo_db_fopen(frmPath, "rb");
if (!frmStream && *ptr_use_language) {
sprintf_s(frmPath, MAX_PATH, "art\\%s\\%s", artfolder, frmName);
frmStream = fo_db_fopen(frmPath, "rb");
}
if (frmStream != nullptr) {
if (!LoadFrmHeader(frm, frmStream)) {
+10
View File
@@ -33,6 +33,7 @@
// Global variable offsets
// TODO: probably need to hide these by moving inside implementation file
#define FO_VAR_aDialogS_msg 0x50DBE8
#define FO_VAR_aiInfoList 0x510948
#define FO_VAR_ambient_light 0x51923C
#define FO_VAR_anim_set 0x54CC14
@@ -42,6 +43,9 @@
#define FO_VAR_art_vault_guy_num 0x5108A4
#define FO_VAR_art_vault_person_nums 0x5108A8
#define FO_VAR_artCritterFidShouldRunData 0x56CAF0
#define FO_VAR_aTextSCuts 0x501A8C
#define FO_VAR_aTextSCutsS 0x503530
#define FO_VAR_aTextSCutsSS 0x50B01C
#define FO_VAR_background_volume 0x518E88
#define FO_VAR_bboxslot 0x5970E0
#define FO_VAR_bckgnd 0x5707A4
@@ -154,6 +158,7 @@
#define FO_VAR_itemButtonItems 0x5970F8
#define FO_VAR_itemCurrentItem 0x518F78
#define FO_VAR_kb_lock_flags 0x51E2EA
#define FO_VAR_language 0x56C970 // aka _darn_foreign_sub_path
#define FO_VAR_last_buttons 0x51E2AC
#define FO_VAR_last_button_winID 0x51E404
#define FO_VAR_last_level 0x5707B4
@@ -293,6 +298,7 @@
#define FO_VAR_title_color 0x56D750
#define FO_VAR_title_font 0x56D748
#define FO_VAR_trait_data 0x51DB84
#define FO_VAR_use_language 0x510898 // aka _darn_foreigners
#define FO_VAR_view_page 0x664520
#define FO_VAR_wd_obj 0x59E98C
#define FO_VAR_window 0x6ADE58
@@ -505,6 +511,10 @@ const char* GetMessageStr(const MSGList* fileAddr, long messageId);
// similar to GetMessageStr, but returns nullptr when no message is found
const char* MessageSearch(const MSGList* fileAddr, long messageId);
MSGNode* GetMsgNode(MSGList* msgList, int msgNum);
char* GetMsg(MSGList* msgList, int msgNum, int msgType);
Queue* QueueFind(TGameObj* object, long type);
// returns weapon animation code
+3 -1
View File
@@ -90,6 +90,7 @@ PTR_(inventry_message_file, MSGList)
PTR_(itemButtonItems, ItemButtonItem) // array of 2 ItemButtonItem, 0 - left, 1 - right
PTR_(itemCurrentItem, long) // 0 - left, 1 - right
PTR_(kb_lock_flags, DWORD)
PTR_(language, char) // array of 32 char
PTR_(last_buttons, DWORD)
PTR_(last_button_winID, DWORD)
PTR_(last_level, DWORD)
@@ -212,7 +213,8 @@ PTR_(text_width, DWORD)
PTR_(tile, DWORD)
PTR_(title_color, DWORD)
PTR_(title_font, DWORD)
PTR_(trait_data, TraitInfo) // // array of size == TRAIT_count
PTR_(trait_data, TraitInfo) // array of size == TRAIT_count
PTR_(use_language, DWORD)
PTR_(view_page, DWORD)
PTR_(wd_obj, DWORD)
PTR_(window, WINinfo*) // array of 50 WINinfo*
+2 -2
View File
@@ -20,7 +20,7 @@
#include "IniReader.h"
DWORD IniReader_modifiedIni;
DWORD modifiedIni;
static const char* ddrawIni = ".\\ddraw.ini";
static char ini[65] = ".\\";
@@ -107,5 +107,5 @@ int SetConfigInt(const char* section, const char* setting, int value) {
}
void IniReader_Init() {
IniReader_modifiedIni = GetConfigInt("Main", "ModifiedIni", 0);
modifiedIni = GetConfigInt("Main", "ModifiedIni", 0);
}
+1 -1
View File
@@ -18,7 +18,7 @@
#pragma once
extern DWORD IniReader_modifiedIni;
extern DWORD modifiedIni;
void IniReader_Init();
+33
View File
@@ -283,6 +283,32 @@ artNotExist:
}
}
static DbFile* __fastcall LoadFont(const char* font, const char* mode) {
char file[128];
const char* lang;
if (fo_get_game_config_string(&lang, "system", "language") && _stricmp(lang, "english") != 0) {
std::sprintf(file, "%s\\%s", lang, font);
return fo_db_fopen(file, mode);
}
return nullptr;
}
void __declspec(naked) load_font_hook() {
__asm {
mov ebp, edx;
mov ebx, eax;
mov ecx, eax;
call LoadFont;
test eax, eax;
jz default;
retn;
default:
mov edx, ebp;
mov eax, ebx;
jmp db_fopen_;
}
}
void LoadOrder_OnGameLoad() {
savPrototypes.clear();
RemoveSavFiles();
@@ -318,4 +344,11 @@ void LoadOrder_Init() {
MakeCall(0x47FB80, SlotMap2Game_hack); // load game
MakeCall(0x47FBBF, SlotMap2Game_hack_attr, 1);
dlogr(" Done", DL_INIT);
// Load fonts based on the game language
const DWORD loadFontAddr[] = {
0x4D5621, // load_font_
0x441D58 // FMLoadFont_
};
HookCalls(load_font_hook, loadFontAddr);
}
+1 -34
View File
@@ -48,7 +48,7 @@ const MSGList* gameMsgFiles[] = {
};
#undef CASTMSG
static char gameLanguage[41]; // max length of language string is 40
static char gameLanguage[32]; // (max length of language string is 40)
const char* Message_GameLanguage() {
return &gameLanguage[0];
@@ -82,39 +82,6 @@ noFile:
}
}
MSGNode* GetMsgNode(MSGList* msgList, int msgRef) {
if (msgList != nullptr && msgList->numMsgs > 0) {
MSGNode *MsgNode = msgList->nodes;
long last = msgList->numMsgs - 1;
long first = 0;
long mid;
// Use Binary Search to find msg
while (first <= last) {
mid = (first + last) / 2;
if (msgRef > MsgNode[mid].number)
first = mid + 1;
else if (msgRef < MsgNode[mid].number)
last = mid - 1;
else
return &MsgNode[mid];
}
}
return nullptr;
}
char* GetMsg(MSGList* msgList, int msgRef, int msgNum) {
MSGNode *msgNode = GetMsgNode(msgList, msgRef);
if (msgNode) {
if (msgNum == 2) {
return msgNode->message;
} else if (msgNum == 1) {
return msgNode->audio;
}
}
return nullptr;
}
void ReadExtraGameMsgFiles() {
if (!msgFileList.empty()) {
int number = 0;
+1 -4
View File
@@ -21,7 +21,7 @@
#include <unordered_map>
#include "main.h"
#include "FalloutEngine.h"
//#include "FalloutEngine.h"
#define MSG_FILE_COMBAT (0x56D368)
#define MSG_FILE_AI (0x56D510)
@@ -58,6 +58,3 @@ void ClearScriptAddedExtraGameMsg();
const char* Message_GameLanguage();
long __stdcall Message_AddExtraMsgFile(const char* msgName, long msgNumber);
MSGNode* GetMsgNode(MSGList* msgList, int msgRef);
char* GetMsg(MSGList* msgList, int msgRef, int msgNum);
+2 -2
View File
@@ -23,7 +23,7 @@
#include "ScriptExtender.h"
static char mapName[17] = {};
static char mapName[16] = {};
static char patchName[65] = {};
static char versionString[65] = {};
@@ -711,7 +711,7 @@ static void EngineOptimizationPatches() {
void MiscPatches_Init() {
EngineOptimizationPatches();
if (GetConfigString("Misc", "StartingMap", "", mapName, 17)) {
if (GetConfigString("Misc", "StartingMap", "", mapName, 16)) {
dlog("Applying starting map patch.", DL_INIT);
SafeWrite32(0x480AAA, (DWORD)&mapName);
dlogr(" Done", DL_INIT);
+4 -4
View File
@@ -21,19 +21,19 @@
#include "Logging.h"
#include "SafeWrite.h"
static char startMaleModelName[65] = {};
static char startMaleModelName[33] = {};
char defaultMaleModelName[65] = {};
static char startFemaleModelName[65] = {};
static char startFemaleModelName[33] = {};
char defaultFemaleModelName[65] = {};
void PlayerModel_Init() {
if (GetConfigString("Misc", "MaleStartModel", "", startMaleModelName, 65)) {
if (GetConfigString("Misc", "MaleStartModel", "", startMaleModelName, 33)) {
dlog("Applying male start model patch.", DL_INIT);
SafeWrite32(0x418B88, (DWORD)&startMaleModelName);
dlogr(" Done", DL_INIT);
}
if (GetConfigString("Misc", "FemaleStartModel", "", startFemaleModelName, 65)) {
if (GetConfigString("Misc", "FemaleStartModel", "", startFemaleModelName, 33)) {
dlog("Applying female start model patch.", DL_INIT);
SafeWrite32(0x418BAB, (DWORD)&startFemaleModelName);
dlogr(" Done", DL_INIT);
+2 -2
View File
@@ -23,14 +23,14 @@
static PremadeChar* premade;
static const char* __fastcall GetLangPremadePath(const char* premadePath) {
static char premadeLangPath[65]; // premade\<language>\combat.bio
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 > 40) {
if (len == 0 || len >= 32) {
isDefault = true;
return nullptr;
}
+22 -6
View File
@@ -568,16 +568,27 @@ static FrmFile* __stdcall LoadArtFile(const char* file, long frame, long directi
return frmPtr;
}
static long __stdcall GetArtFIDFile(long fid, const char* &file) {
static long __stdcall GetArtFIDFile(long fid, char* outFilePath) {
long direction = 0;
long _fid = fid & 0xFFFFFFF;
file = fo_art_get_name(_fid); // .frm
const char* artPathName = fo_art_get_name(_fid); // <cd>\art\type\file.frm
if (_fid >> 24 == OBJ_TYPE_CRITTER) {
direction = (fid >> 28);
if (direction > 0 && !fo_db_access(file)) {
file = fo_art_get_name(fid); // .fr#
if (direction > 0 && !fo_db_access(artPathName)) {
artPathName = fo_art_get_name(fid); // .fr#
}
} else {
if (*ptr_use_language) {
const char* _artPathName = std::strchr(artPathName, '\\');
if (_artPathName && *(++_artPathName)) {
sprintf_s(outFilePath, MAX_PATH, "art\\%s\\%s", (const char*)ptr_language, _artPathName);
if (fo_db_access(outFilePath)) return direction;
}
}
}
std::strcpy(outFilePath, artPathName);
return direction;
}
@@ -594,7 +605,9 @@ static long __stdcall DrawImage(OpcodeHandler& opHandler, bool isScaled, const c
long fid = opHandler.arg(0).rawValue();
if (fid == -1) return -1;
direction = GetArtFIDFile(fid, file);
char fileBuf[MAX_PATH];
direction = GetArtFIDFile(fid, fileBuf);
file = fileBuf;
} else {
file = opHandler.arg(0).strValue(); // path to frm/pcx file
}
@@ -664,7 +677,10 @@ static long __stdcall InterfaceDrawImage(OpcodeHandler& opHandler, WINinfo* ifac
if (fid == -1) return -1;
useShift = (((fid & 0xF000000) >> 24) == OBJ_TYPE_CRITTER);
direction = GetArtFIDFile(fid, file);
char fileBuf[MAX_PATH];
direction = GetArtFIDFile(fid, fileBuf);
file = fileBuf;
} else {
file = opHandler.arg(1).strValue(); // path to frm/pcx file
}
+1 -1
View File
@@ -524,7 +524,7 @@ fail:
static void __declspec(naked) op_modified_ini() {
__asm {
mov edx, IniReader_modifiedIni;
mov edx, modifiedIni;
_J_RET_VAL_TYPE(VAR_TYPE_INT);
}
}