Created
April 1, 2013 10:35
-
-
Save dosomder/5284215 to your computer and use it in GitHub Desktop.
Load localized strings in IW4M
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ========================================================== | |
// IW4M project | |
// | |
// Component: clientdll | |
// Sub-component: steam_api | |
// Purpose: Code to replace localized strings in the game. | |
// | |
// Initial author: NTAuthority | |
// Edited by zxz0O0 to add the ability of loading custom str files | |
// Started: 2013-01-17 | |
// ========================================================== | |
#include "StdInc.h" | |
#include <google/dense_hash_map> | |
struct localizedEntry_s | |
{ | |
const char* value; | |
const char* name; | |
}; | |
StompHook loadLocalizeHook; | |
DWORD loadLocalizeHookLoc = 0x629B90; | |
static google::dense_hash_map<std::string, std::string> _localizedStrings; | |
int LoadStrFiles(char* language) | |
{ | |
char buf[256]; | |
sprintf_s(buf, sizeof(buf), "%s/localizedstrings/", language); | |
int count; | |
char** list = FS_ListFiles(buf, "str", 0, &count); | |
for(int i = 0;i < count;i++) | |
{ | |
sprintf_s(buf, sizeof(buf), "%s/localizedstrings/%s", language, list[i]); | |
Com_Printf(0, "Parsing localized string file: %s\n", buf); | |
char* Error = SE_Load(buf, 0); | |
if(Error) | |
Com_Printf(0, "Error parsing localized string file: %s\n", Error); | |
} | |
FS_FreeFileList(list); | |
return count; | |
} | |
void SELoadLanguageHookStub() | |
{ | |
_localizedStrings.clear(); | |
//get language from loc_modLanguage | |
dvar_t* modLang = Dvar_FindVar("loc_modLanguage"); | |
char** enumList = *(char***)&(modLang->max); //not sure if this is really dvar_maxmin_t max. | |
char* language = enumList[modLang->current.integer]; | |
//'official' iw4m localized strings | |
SE_Load("localizedstrings/iw4m.str", 0); | |
if(LoadStrFiles(language)==0) | |
LoadStrFiles("english");//load english str files if there aren't any of selected language | |
__asm | |
{ | |
leave | |
mov eax, 0x41D885 //back to SE_LoadLanguage | |
jmp eax | |
} | |
} | |
//can't use dense_hash_map in a naked | |
void AddCustomString(char* key, char* value) | |
{ | |
_localizedStrings[key] = value; | |
} | |
void __declspec(naked) SetString(char* key, char* value, bool isEnglish) | |
{ | |
__asm | |
{ | |
push [esp+8] | |
push [esp+8] | |
call AddCustomString | |
add esp,8 | |
mov eax,[esp] //get return address | |
add esp,0x10 //remove stack space for parameters + return address | |
jmp eax //return | |
} | |
} | |
const char* SEH_GetLocalizedString(const char* key) | |
{ | |
google::dense_hash_map<std::string, std::string>::const_iterator iter = _localizedStrings.find(key); | |
if (iter != _localizedStrings.end()) | |
{ | |
return (*iter).second.c_str(); | |
} | |
localizedEntry_s* entry = (localizedEntry_s*)DB_FindXAssetHeader(ASSET_TYPE_LOCALIZE, key); | |
if (entry) | |
{ | |
return entry->value; | |
} | |
return NULL; | |
} | |
//loc_language codes | |
//"english", "french", "german", "italian", "spanish", "british", "russian", "polish", "korean", "taiwanese", "japanese", "chinese", "thai", "leet", "czech" | |
char* ModLanguageEnum[] = { "english", "french", "german", "italian", "spanish", "english", "russian", "polish", 0 }; | |
void PatchMW2_LocalizedStrings() | |
{ | |
_localizedStrings.set_empty_key(""); | |
loadLocalizeHook.initialize(loadLocalizeHookLoc, SEH_GetLocalizedString); | |
loadLocalizeHook.installHook(); | |
call(0x4CE5EE, SetString, PATCH_CALL); //instead of calling CStringEdPackage::SetString in CStringEdPackage::ParseLine we call our SetString | |
call(0x41D860, SELoadLanguageHookStub, PATCH_JUMP); //instead of the game loading str files according to loc_language we load them according to loc_modlanguage | |
Dvar_RegisterEnum("loc_modLanguage", ModLanguageEnum, 0, DVAR_FLAG_SAVED, "Preferred language for custom localized strings."); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment