diff --git a/amxmodx/amxmod_compat.cpp b/amxmodx/amxmod_compat.cpp index 2d2f6fd1..4ea29501 100644 --- a/amxmodx/amxmod_compat.cpp +++ b/amxmodx/amxmod_compat.cpp @@ -2,52 +2,28 @@ #include "amxmod_compat.h" #include "format.h" -struct translate_result +bool GetTranslation(amxtrans_t trans, int &key, int &dest, int &lang) { - int suki; - int dest; - int lang; -}; + key = (trans & BCOMPAT_TRANSLATE_KEYMASK); + dest = (trans >> BCOMPAT_TRANSLATE_DESTRSH) & BCOMPAT_TRANSLATE_DESTMASK; + lang = (trans >> BCOMPAT_TRANSLATE_LANGRSH) & BCOMPAT_TRANSLATE_LANGMASK; -CVector g_tr_results; -CStack g_old_ids; - -bool GetTranslation(int id, int &key, int &dest, int &lang) -{ - if (id < 0 || (unsigned int)id > g_tr_results.size()) + if (dest == 0x3F) { - return false; + dest = -1; + } + + if (lang == 0x1F) + { + lang = -1; } - translate_result *pRes = g_tr_results[id]; - - key = pRes->suki; - dest = pRes->dest; - lang = pRes->lang; - - g_old_ids.push((size_t)id); - return true; } -void ClearTransCache() -{ - for (size_t i=0; i(*source); - trans &= ~BCOMPAT_TRANSLATE_BITS; + amxtrans_t trans = static_cast(*source); int key, _dest, lang; if (!GetTranslation(trans, key, _dest, lang)) { @@ -95,36 +71,41 @@ static cell AMX_NATIVE_CALL amx_translate(AMX *amx, cell *params) int len; char *key = get_amxstring(amx, params[1], 0, len); - translate_result *pRes; - size_t id; - if (g_old_ids.empty()) - { - pRes = new translate_result; - id = g_tr_results.size(); - g_tr_results.push_back(pRes); - } else { - if (g_tr_results.size() >= BCOMPAT_TRANSLATE_MAX) - { - LogError(amx, AMX_ERR_NATIVE, "Exceeded bcompat translation limit of %d!", BCOMPAT_TRANSLATE_MAX); - return 0; - } - id = g_old_ids.front(); - g_old_ids.pop(); - pRes = g_tr_results[id]; - } - - pRes->suki = g_langMngr.GetKeyEntry(key); + amxtrans_t trans; + int suki = g_langMngr.GetKeyEntry(key); //Some AMX Mod plugins do not register everything they need. Prevent a crash. - if (pRes->suki == -1) + if (suki == -1) { - pRes->suki = g_langMngr.AddKeyEntry(key); + suki = g_langMngr.AddKeyEntry(key); } - pRes->dest = params[2]; - pRes->lang = params[3]; + if (suki > BCOMPAT_TRANSLATE_KEYMASK) + { + LogError(amx, AMX_ERR_NATIVE, "Not enough translation space, aborting!"); + return 0; + } - return (cell)((unsigned int)BCOMPAT_TRANSLATE_BITS | (unsigned int)id); + trans = suki & BCOMPAT_TRANSLATE_KEYMASK; + int dest = static_cast(params[2]); + int lang = static_cast(params[3]); + if (dest == -1) + { + trans |= (0x3F << BCOMPAT_TRANSLATE_DESTRSH); + } else { + trans |= (dest & BCOMPAT_TRANSLATE_DESTMASK) << BCOMPAT_TRANSLATE_DESTRSH; + } + + if (lang == -1) + { + trans |= (0x1F << BCOMPAT_TRANSLATE_LANGRSH); + } else { + trans |= (lang & BCOMPAT_TRANSLATE_LANGMASK) << BCOMPAT_TRANSLATE_LANGRSH; + } + + trans |= BCOMPAT_TRANSLATE_BITS; + + return static_cast(trans); } AMX_NATIVE_INFO g_BcompatNatives[] = diff --git a/amxmodx/amxmod_compat.h b/amxmodx/amxmod_compat.h index cd2bd779..6a560331 100644 --- a/amxmodx/amxmod_compat.h +++ b/amxmodx/amxmod_compat.h @@ -1,11 +1,27 @@ #ifndef _INCLUDE_AMXMOD_CORE_COMPAT_H #define _INCLUDE_AMXMOD_CORE_COMPAT_H -#define BCOMPAT_TRANSLATE_BITS 0xFFFFF400 -#define BCOMPAT_TRANSLATE_MAX 0x400 +/** + * New format for translation: + * Note that we only support: + * 4k keys + * 32 languages + * 0000 0000 0000 0000 0000 0000 0000 0000 + * | key id | + * | | <- dest id + * | | <- lang id + */ -bool GetTranslation(int id, int &key, int &dest, int &lang); -void ClearTransCache(); +#define BCOMPAT_TRANSLATE_BITS 0xFF000000 +#define BCOMPAT_TRANSLATE_KEYMASK 0xFFF +#define BCOMPAT_TRANSLATE_DESTMASK 0x3F +#define BCOMPAT_TRANSLATE_DESTRSH 12 +#define BCOMPAT_TRANSLATE_LANGMASK 0x1F +#define BCOMPAT_TRANSLATE_LANGRSH 18 + +typedef unsigned int amxtrans_t; + +bool GetTranslation(amxtrans_t trans, int &key, int &dest, int &lang); extern AMX_NATIVE_INFO g_BcompatNatives[]; diff --git a/amxmodx/meta_api.cpp b/amxmodx/meta_api.cpp index 6aefac32..3c0cef2e 100755 --- a/amxmodx/meta_api.cpp +++ b/amxmodx/meta_api.cpp @@ -628,7 +628,6 @@ void C_ServerDeactivate_Post() g_xvars.clear(); g_plugins.clear(); ClearPluginLibraries(); - ClearTransCache(); modules_callPluginsUnloaded(); ClearMessages(); diff --git a/amxmodx/string.cpp b/amxmodx/string.cpp index 5fbaad38..2adc57fd 100755 --- a/amxmodx/string.cpp +++ b/amxmodx/string.cpp @@ -443,15 +443,42 @@ static cell AMX_NATIVE_CALL add(AMX *amx, cell *params) /* 4 param */ static cell AMX_NATIVE_CALL copy(AMX *amx, cell *params) /* 4 param */ { cell *src = get_amxaddr(amx, params[3]); - cell *dest = get_amxaddr(amx, params[1]); - cell *start = dest; int c = params[2]; - - while (c-- && *src) - *dest++ =* src++; - *dest = 0; - - return (dest - start); + + if (amx->flags & AMX_FLAG_OLDFILE) + { + if (*src & BCOMPAT_TRANSLATE_BITS) + { + const char *key, *def; + if (!translate_bcompat(amx, src, &key, &def)) + { + goto normal_string; + } + cell *dest = get_amxaddr(amx, params[1]); + cell *start = dest; + while (c-- && *def) + { + *dest++ = static_cast(*def++); + } + *dest = '\0'; + + return dest-start; + } else { + goto normal_string; + } + } else { +normal_string: + cell *dest = get_amxaddr(amx, params[1]); + cell *start = dest; + + while (c-- && *src) + { + *dest++ = *src++; + } + *dest = '\0'; + + return (dest - start); + } } static cell AMX_NATIVE_CALL copyc(AMX *amx, cell *params) /* 4 param */ @@ -568,7 +595,26 @@ static cell AMX_NATIVE_CALL format(AMX *amx, cell *params) /* 3 param */ if (copy) buf = g_cpbuf; int param = 4; - size_t total = atcprintf(buf, maxlen, fmt, amx, params, ¶m); + size_t total = 0; + + if (amx->flags & AMX_FLAG_OLDFILE) + { + if (*fmt & BCOMPAT_TRANSLATE_BITS) + { + const char *key, *def; + if (!translate_bcompat(amx, fmt, &key, &def)) + { + goto normal_string; + } + total = atcprintf(buf, maxlen, def, amx, params, ¶m); + } else { + goto normal_string; + } + } else { +normal_string: + total = atcprintf(buf, maxlen, fmt, amx, params, ¶m); + } + if (copy) { /* copy back */