mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Merge pull request #543 from sfall-team/feature/fallback-language-by-line
Fallback to english by individual message in MSG files
This commit is contained in:
@@ -44,7 +44,7 @@ WRAP_WATCOM_FFUNC3(long, item_w_mp_cost, fo::GameObject*, source, long, hitMode,
|
|||||||
// Calculates path and returns it's length
|
// Calculates path and returns it's length
|
||||||
WRAP_WATCOM_FFUNC6(long, make_path_func, fo::GameObject*, objectFrom, long, tileFrom, long, tileTo, char*, pathDataBuffer, long, checkTileTo, void*, blockingFunc)
|
WRAP_WATCOM_FFUNC6(long, make_path_func, fo::GameObject*, objectFrom, long, tileFrom, long, tileTo, char*, pathDataBuffer, long, checkTileTo, void*, blockingFunc)
|
||||||
WRAP_WATCOM_FFUNC7(long, make_straight_path_func, fo::GameObject*, objFrom, DWORD, tileFrom, DWORD, tileTo, void*, arrayPtr, DWORD*, outObject, long, flags, void*, blockingFunc)
|
WRAP_WATCOM_FFUNC7(long, make_straight_path_func, fo::GameObject*, objFrom, DWORD, tileFrom, DWORD, tileTo, void*, arrayPtr, DWORD*, outObject, long, flags, void*, blockingFunc)
|
||||||
WRAP_WATCOM_FFUNC3(long, message_find, DWORD*, msgFile, long, msgNumber, DWORD*, outBuf)
|
WRAP_WATCOM_FFUNC3(long, message_find, fo::MessageList*, msgFile, long, msgNumber, DWORD*, outBuf)
|
||||||
WRAP_WATCOM_FFUNC4(long, mouse_click_in, long, x, long, y, long, x_offs, long, y_offs)
|
WRAP_WATCOM_FFUNC4(long, mouse_click_in, long, x, long, y, long, x_offs, long, y_offs)
|
||||||
WRAP_WATCOM_FFUNC4(long, mouse_in, long, x, long, y, long, x_offs, long, y_offs)
|
WRAP_WATCOM_FFUNC4(long, mouse_in, long, x, long, y, long, x_offs, long, y_offs)
|
||||||
WRAP_WATCOM_FFUNC3(fo::GameObject*, obj_blocking_at, fo::GameObject*, object, long, tile, long, elevation)
|
WRAP_WATCOM_FFUNC3(fo::GameObject*, obj_blocking_at, fo::GameObject*, object, long, tile, long, elevation)
|
||||||
|
|||||||
+94
-20
@@ -72,7 +72,7 @@ static long heroIsFemale = -1;
|
|||||||
|
|
||||||
// Searches the special character in the text and removes the text depending on the player's gender
|
// Searches the special character in the text and removes the text depending on the player's gender
|
||||||
// example: <MaleText^FemaleText>
|
// example: <MaleText^FemaleText>
|
||||||
static long __fastcall ReplaceGenderWord(fo::MessageNode* msgData, DWORD* msgFile) {
|
static long __fastcall ReplaceGenderWord(fo::MessageNode* msgData, fo::MessageList* msgFile) {
|
||||||
if (!InDialog() || msgData->flags & MSG_GENDER_CHECK_FLG) return 1;
|
if (!InDialog() || msgData->flags & MSG_GENDER_CHECK_FLG) return 1;
|
||||||
if (heroIsFemale < 0) heroIsFemale = fo::util::HeroIsFemale();
|
if (heroIsFemale < 0) heroIsFemale = fo::util::HeroIsFemale();
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ static long __fastcall ReplaceGenderWord(fo::MessageNode* msgData, DWORD* msgFil
|
|||||||
// set flag
|
// set flag
|
||||||
unsigned long outValue;
|
unsigned long outValue;
|
||||||
fo::func::message_find(msgFile, msgData->number, &outValue);
|
fo::func::message_find(msgFile, msgData->number, &outValue);
|
||||||
((fo::MessageNode*)(msgFile[1] + (outValue * 16)))->flags |= MSG_GENDER_CHECK_FLG;
|
msgFile->nodes[outValue].flags |= MSG_GENDER_CHECK_FLG;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -139,26 +139,96 @@ end:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MessageListInfo {
|
||||||
|
std::string FileName;
|
||||||
|
fo::MessageList* List;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_map<fo::MessageList*, MessageListInfo> messageListMap;
|
||||||
|
|
||||||
|
static bool messageLoadForceEnglish;
|
||||||
|
|
||||||
|
static fo::DbFile* __fastcall MessageLoadHook(const char* fullPath, const char* mode, const char* msgFile, fo::MessageList* messageList) {
|
||||||
|
fo::DbFile* file = !messageLoadForceEnglish ? fo::func::db_fopen(fullPath, mode) : nullptr;
|
||||||
|
if (file == nullptr) {
|
||||||
|
messageLoadForceEnglish = false;
|
||||||
|
char buf[MAX_PATH];
|
||||||
|
sprintf(buf, "text\\english\\%s", msgFile);
|
||||||
|
return fo::func::db_fopen(buf, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember loaded message list name.
|
||||||
|
messageListMap.emplace(messageList, MessageListInfo{msgFile, nullptr});
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long __fastcall MessageFindHook(fo::MessageList** list, long num, DWORD* outIndex) {
|
||||||
|
if (fo::func::message_find(*list, num, outIndex)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If message not found in original list, try to find in fallback list.
|
||||||
|
auto& listIt = messageListMap.find(*list);
|
||||||
|
if (listIt == messageListMap.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MessageListInfo& listInfo = listIt->second;
|
||||||
|
if (listInfo.List == nullptr) {
|
||||||
|
// Load fallback message list.
|
||||||
|
messageLoadForceEnglish = true;
|
||||||
|
listInfo.List = new fo::MessageList();
|
||||||
|
fo::func::message_load(listInfo.List, listInfo.FileName.c_str());
|
||||||
|
// TODO: some error message if fallback file wasn't loaded?
|
||||||
|
}
|
||||||
|
*list = listInfo.List;
|
||||||
|
return fo::func::message_find(*list, num, outIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void __fastcall MessageExitHook(fo::MessageList* list) {
|
||||||
|
// Delete fallback message file.
|
||||||
|
auto& listIt = messageListMap.find(list);
|
||||||
|
if (listIt == messageListMap.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MessageListInfo& listInfo = listIt->second;
|
||||||
|
if (listInfo.List != nullptr) {
|
||||||
|
fo::func::message_exit(listInfo.List);
|
||||||
|
delete listInfo.List;
|
||||||
|
}
|
||||||
|
messageListMap.erase(listIt);
|
||||||
|
}
|
||||||
|
|
||||||
// Loads the msg file from the 'english' folder if it does not exist in the current language directory
|
// Loads the msg file from the 'english' folder if it does not exist in the current language directory
|
||||||
static void __declspec(naked) message_load_hook() {
|
static void __declspec(naked) message_load__db_fopen_hook() {
|
||||||
__asm {
|
__asm {
|
||||||
mov ebx, edx; // keep mode
|
push esi; // message list
|
||||||
mov ecx, eax; // keep buf
|
push ebp; // relative path
|
||||||
call fo::funcoffs::db_fopen_;
|
// edx - mode
|
||||||
test eax, eax;
|
mov ecx, eax; // full path
|
||||||
jz noFile;
|
call MessageLoadHook;
|
||||||
retn;
|
retn;
|
||||||
noFile:
|
}
|
||||||
push ebp; // file
|
}
|
||||||
push 0x500208; // "english"
|
|
||||||
push 0x50B7D0; // "text"
|
static void __declspec(naked) message_search__message_find_hook() {
|
||||||
push 0x50B7D8; // "%s\%s\%s"
|
__asm {
|
||||||
push ecx; // buf
|
push ecx; // save msg list
|
||||||
call fo::funcoffs::sprintf_;
|
push ebx; // out index
|
||||||
add esp, 20;
|
// edx - msg num
|
||||||
mov edx, ebx;
|
lea ecx, [esp + 4]; // msg list **
|
||||||
mov eax, ecx;
|
call MessageFindHook;
|
||||||
jmp fo::funcoffs::db_fopen_;
|
pop ecx; // restore, possibly modified list ptr
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) message_exit__mem_free_hook() {
|
||||||
|
__asm {
|
||||||
|
push eax;
|
||||||
|
mov ecx, ebx; // message list
|
||||||
|
call MessageExitHook;
|
||||||
|
pop eax;
|
||||||
|
jmp fo::funcoffs::mem_free_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +305,11 @@ static void FallbackEnglishLoadMsgFiles() {
|
|||||||
const char* lang;
|
const char* lang;
|
||||||
if (fo::func::get_game_config_string(&lang, "system", "language")) {
|
if (fo::func::get_game_config_string(&lang, "system", "language")) {
|
||||||
strncpy_s(gameLanguage, lang, _TRUNCATE);
|
strncpy_s(gameLanguage, lang, _TRUNCATE);
|
||||||
if (_stricmp(lang, "english") != 0) HookCall(0x484B18, message_load_hook);
|
if (_stricmp(lang, "english") != 0) {
|
||||||
|
HookCall(0x484B18, message_load__db_fopen_hook);
|
||||||
|
HookCall(0x484C4B, message_search__message_find_hook);
|
||||||
|
HookCall(0x4849B9, message_exit__mem_free_hook);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ void op_message_str_game(OpcodeContext& ctx) {
|
|||||||
} else if (fileId >= 0x2000) { // Extra game message files.
|
} else if (fileId >= 0x2000) { // Extra game message files.
|
||||||
ExtraGameMessageListsMap::iterator it = Message::gExtraGameMsgLists.find(fileId);
|
ExtraGameMessageListsMap::iterator it = Message::gExtraGameMsgLists.find(fileId);
|
||||||
if (it != Message::gExtraGameMsgLists.end()) {
|
if (it != Message::gExtraGameMsgLists.end()) {
|
||||||
msg = fo::util::GetMsg(it->second.get(), msgId, 2);
|
msg = fo::util::GetMessageStr(it->second.get(), msgId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user