diff --git a/source/common/engine/sc_man.cpp b/source/common/engine/sc_man.cpp index b9f3cc882..96fd75ddc 100644 --- a/source/common/engine/sc_man.cpp +++ b/source/common/engine/sc_man.cpp @@ -300,6 +300,12 @@ void FScanner :: OpenLumpNum (int lump) void FScanner::PrepareScript () { + // If the file got a UTF-8 byte order mark, remove that. + if (ScriptBuffer.Len() > 3 && ScriptBuffer[0] == (char)0xEF && ScriptBuffer[1] == (char)0xBB && ScriptBuffer[2] == (char)0xBF) + { + ScriptBuffer = ScriptBuffer.Mid(3); + } + // The scanner requires the file to end with a '\n', so add one if // it doesn't already. if (ScriptBuffer.Len() == 0 || ScriptBuffer.Back() != '\n') diff --git a/source/common/engine/stringtable.h b/source/common/engine/stringtable.h index f9f714f3e..6562834b5 100644 --- a/source/common/engine/stringtable.h +++ b/source/common/engine/stringtable.h @@ -110,6 +110,8 @@ public: bool exists(const char *name); void SetCallbacks(StringtableCallbacks* cb) { callbacks = cb; } + void InsertString(int lumpnum, int langid, FName label, const FString& string); + private: FString activeLanguage; @@ -124,7 +126,6 @@ private: bool LoadLanguageFromSpreadsheet(int lumpnum, const TArray &buffer); bool readMacros(int lumpnum); - void InsertString(int lumpnum, int langid, FName label, const FString &string); void DeleteString(int langid, FName label); void DeleteForLabel(int lumpnum, FName label); diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index 9984a033e..b09eac735 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -752,6 +752,83 @@ static TArray SetupGame() return usedgroups; } +//========================================================================== +// +// reads a Duke Nukem World Tour translation file. +// +//========================================================================== + +static void LoadLanguageWT(int lumpnum, TArray& buffer, const char* langid) +{ + uint32_t activeMap; + FScanner sc; + + if (stricmp(langid, "default") == 0) activeMap = FStringTable::default_table; + else activeMap = MAKE_ID(tolower(langid[0]), tolower(langid[1]), tolower(langid[2]), 0); + + // Notes about the text files: + // The English text has a few lines where a period follows a quoted string, they are skipped over by the first check in the loop. + // The Russian text file contains a line starting with two quotation marks. + // Unfortunately we need to get across that because important stuff comes afterward. + // The Japanese text also has a fatal error, but it comes after all the texts we actually need so it is easier to handle by just aborting the parse. + + if (!stricmp(langid, "ru")) + { + for (unsigned i = 1; i < buffer.Size(); i++) + { + if (buffer[i] == '"' && buffer[i - 1] == '"') + { + buffer.Delete(i); + break; + } + } + } + + sc.OpenMem(fileSystem.GetFileFullName(lumpnum), buffer); + while (sc.GetString()) + { + + if (sc.String[0] != '#') sc.MustGetString();// there's a few fucked up texts in the files. + if (sc.String[0] != '#') return; + FName strName(sc.String); + sc.MustGetString(); + GStrings.InsertString(lumpnum, activeMap, strName, sc.String); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void InitLanguages() +{ + GStrings.LoadStrings(language); + if (g_gameType & GAMEFLAG_DUKE) // these are for World Tour but at this point we do not know yet, do just look for them anyway + { + static const struct wt_lang + { + const char* filename; + const char* langid; + } langfiles[] = { + { "locale/english/strings.txt", "default" }, + { "locale/brazilian/brazilian.txt", "pt" }, + { "locale/french/french.txt", "fr" }, + { "locale/german/german.txt", "de" }, + { "locale/italian/italian.txt", "it" }, + { "locale/japanese/japanese.txt", "jp" }, + { "locale/russian/russian.txt", "ru" }, + { "locale/spanish/spanish.txt", "es" } }; + + for (const auto& li : langfiles) + { + auto buffer = fileSystem.LoadFile(li.filename, 1); + if (buffer.Size() > 0) LoadLanguageWT(fileSystem.FindFile(li.filename), buffer, li.langid); + } + } +} + //========================================================================== // // @@ -801,7 +878,8 @@ int RunGame() G_ReadConfig(currentGame); V_InitFontColors(); - GStrings.LoadStrings(language); + InitLanguages(); + CheckCPUID(&CPU); CalculateCPUSpeed(); @@ -1260,7 +1338,7 @@ CVAR(Int, crosshairhealth, 2, CVAR_ARCHIVE); void ST_LoadCrosshair(int num, bool alwaysload) { - char name[16], size; + char name[16]; if (!alwaysload && CrosshairNum == num && CrosshairImage != NULL) { // No change. diff --git a/wadsrc/static/engine/grpinfo.txt b/wadsrc/static/engine/grpinfo.txt index e52fb0d07..7afbd86cd 100644 --- a/wadsrc/static/engine/grpinfo.txt +++ b/wadsrc/static/engine/grpinfo.txt @@ -84,6 +84,16 @@ grpinfo dependency 0 } +grpinfo // another variant? I got this one, dated 2016-10-12 +{ + name "Duke Nukem 3D: Atomic Edition (WT)" + size 44486702 + crc 0x89792E05 + flags GAMEFLAG_DUKE + gamefilter "Duke.Duke" + dependency 0 +} + grpinfo { name "Duke Nukem 3D: Plutonium Pak"