idLangDict: Workaround for Doom3: Lost Mission stringtables #265

The Doom3: Lost Mission (aka D3LE) mod uses string table entry keys that
don't follow the proper Doom3 scheme of "#str_01234", but look like
"#str_adil_exis_pda_01_audio_info" - the "hash" algorithm of idLangDict,
which basically just converts the number after "#str_" into an int,
probably doesn't work very well with this and there was an assertion
to prevent this..
However, it seems to work well enough, so now I only print one warning
for the first "invalid" key and otherwise accept those keys.

The stringtable (strings/*.lang) also has font-related entries
(like "#font" "Chainlink_Semi-Bold") that triggered another assertion,
now everything that starts with "#font" is silently skipped.
This commit is contained in:
Daniel Gibson 2020-01-05 02:34:53 +01:00
parent f24f18a61e
commit dd7a6b2832

View file

@ -100,10 +100,13 @@ bool idLangDict::Load( const char *fileName, bool clear /* _D3XP */ ) {
idLangKeyValue kv; idLangKeyValue kv;
kv.key = tok; kv.key = tok;
kv.value = tok2; kv.value = tok2;
// DG: D3LE has #font_ entries in english.lang, maybe from D3BFG? not supported here, just skip them
if(kv.key.Cmpn("#font_", 6) != 0) {
assert( kv.key.Cmpn( STRTABLE_ID, STRTABLE_ID_LENGTH ) == 0 ); assert( kv.key.Cmpn( STRTABLE_ID, STRTABLE_ID_LENGTH ) == 0 );
hash.Add( GetHashKey( kv.key ), args.Append( kv ) ); hash.Add( GetHashKey( kv.key ), args.Append( kv ) );
} }
} }
}
idLib::common->Printf( "%i strings read from %s\n", args.Num(), fileName ); idLib::common->Printf( "%i strings read from %s\n", args.Num(), fileName );
idLib::fileSystem->FreeFile( (void*)buffer ); idLib::fileSystem->FreeFile( (void*)buffer );
@ -303,8 +306,20 @@ idLangDict::GetHashKey
*/ */
int idLangDict::GetHashKey( const char *str ) const { int idLangDict::GetHashKey( const char *str ) const {
int hashKey = 0; int hashKey = 0;
// DG: Replace assertion for invalid entries with a warning that's shown only once
// (for D3LE mod that seems to have lots of entries like #str_adil_exis_pda_01_audio_info)
const char* strbk = str;
static bool warnedAboutInvalidKey = false;
for ( str += STRTABLE_ID_LENGTH; str[0] != '\0'; str++ ) { for ( str += STRTABLE_ID_LENGTH; str[0] != '\0'; str++ ) {
assert( str[0] >= '0' && str[0] <= '9' ); // assert( str[0] >= '0' && str[0] <= '9' );
if(!warnedAboutInvalidKey && (str[0] < '0' || str[0] > '9')) {
// The "hash" code here very obviously expects numbers, but apparently it still somehow works,
// so just warn about it and otherwise accept those entries, seems to work for D3LE?
idLib::common->Warning( "We have at least one invalid key in a language dict: %s\n"
" (might still work, but Doom3 really wants #str_01234, i.e. only a number after '#str_')\n", strbk );
warnedAboutInvalidKey = true;
}
// DG end
hashKey = hashKey * 10 + str[0] - '0'; hashKey = hashKey * 10 + str[0] - '0';
} }
return hashKey; return hashKey;