Files
sfall/sfall/Message.cpp
T

156 lines
3.9 KiB
C++

/*
* sfall
* Copyright (C) 2008-2016 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 <string>
#include "main.h"
#include "FalloutEngine.h"
#include "Message.h"
#define CASTMSG(adr) reinterpret_cast<MSGList*>(adr)
const MSGList* gameMsgFiles[] = {
CASTMSG(MSG_FILE_COMBAT),
CASTMSG(MSG_FILE_AI),
CASTMSG(MSG_FILE_SCRNAME),
CASTMSG(MSG_FILE_MISC),
CASTMSG(MSG_FILE_CUSTOM),
CASTMSG(MSG_FILE_INVENTRY),
CASTMSG(MSG_FILE_ITEM),
CASTMSG(MSG_FILE_LSGAME),
CASTMSG(MSG_FILE_MAP),
CASTMSG(MSG_FILE_OPTIONS),
CASTMSG(MSG_FILE_PERK),
CASTMSG(MSG_FILE_PIPBOY),
CASTMSG(MSG_FILE_QUESTS),
CASTMSG(MSG_FILE_PROTO),
CASTMSG(MSG_FILE_SCRIPT),
CASTMSG(MSG_FILE_SKILL),
CASTMSG(MSG_FILE_SKILLDEX),
CASTMSG(MSG_FILE_STAT),
CASTMSG(MSG_FILE_TRAIT),
CASTMSG(MSG_FILE_WORLDMAP)
};
#undef CASTMSG
ExtraGameMessageListsMap gExtraGameMsgLists;
static std::vector<std::string> msgFileList;
// 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() {
__asm {
mov ebx, edx; // keep mode
mov ecx, eax; // keep buf
call db_fopen_;
test eax, eax;
jz noFile;
retn;
noFile:
push ebp; // file
push 0x500208; // "english"
push 0x50B7D0; // "text"
push 0x50B7D8; // "%s\%s\%s"
push ecx; // buf
call sprintf_;
add esp, 20;
mov edx, ebx;
mov eax, ecx;
jmp db_fopen_;
}
}
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;
for (std::vector<std::string>::const_iterator it = msgFileList.begin(); it != msgFileList.end(); ++it) {
std::string path("game\\");
size_t n = it->find(':');
if (n == std::string::npos) {
path += *it;
} else {
path += it->substr(0, n);
number = std::stoi(it->substr(n + 1), nullptr, 0);
}
path += ".msg";
MSGList* list = new MSGList();
if (MessageLoad(list, path.c_str()) == 1) {
gExtraGameMsgLists.insert(std::make_pair(0x2000 + number, list));
} else {
delete list;
}
if (++number == 4096) break;
}
msgFileList.clear();
}
}
void FallbackEnglishLoadMsgFiles() {
char value[128];
if (GetGameConfigString(value, "system", "language") && _stricmp(value, "english") != 0) {
HookCall(0x484B18, message_load_hook);
}
}
void ClearReadExtraGameMsgFiles() {
for (ExtraGameMessageListsMap::iterator it = gExtraGameMsgLists.begin(); it != gExtraGameMsgLists.end(); ++it) {
MessageExit(it->second);
delete it->second;
}
}
void MessageInit() {
msgFileList = GetConfigList("Misc", "ExtraGameMsgFileList", "", 512);
}
//void MessageExit() {
//gExtraGameMsgLists.clear();
//}