Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GameTextCompiler RTL #1

Open
wants to merge 10 commits into
base: xezon-gametextcompiler
Choose a base branch
from
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,9 @@ endif()
# Build Thyme
add_subdirectory(src)

# Build gametextcompiler
add_subdirectory(src/tools/gametextcompiler)

if(STANDALONE)
list(APPEND INSTALL_TARGETS thyme)
endif()
Expand Down
24 changes: 17 additions & 7 deletions src/game/client/gametextfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ constexpr const char *const s_option_2 = "Check_Buffer_Length_On_Load";
constexpr const char *const s_option_3 = "Check_Buffer_Length_On_Save";
constexpr const char *const s_option_4 = "Keep_Obsolete_Spaces_On_Load";
constexpr const char *const s_option_5 = "Write_Extra_LF_On_STR_Save";
constexpr const char *const s_option_6 = "RTL_Reverse";

constexpr const char *const s_options[] = {
s_option_0,
Expand All @@ -77,6 +78,7 @@ constexpr const char *const s_options[] = {
s_option_3,
s_option_4,
s_option_5,
s_option_6,
};

static_assert(s_option_0 == s_options[size_t(GameTextOption::NONE)]);
Expand All @@ -85,6 +87,7 @@ static_assert(s_option_2 == s_options[1 + Bit_To_Index(GameTextOption::CHECK_BUF
static_assert(s_option_3 == s_options[1 + Bit_To_Index(GameTextOption::CHECK_BUFFER_LENGTH_ON_SAVE)]);
static_assert(s_option_4 == s_options[1 + Bit_To_Index(GameTextOption::KEEP_OBSOLETE_SPACES_ON_LOAD)]);
static_assert(s_option_5 == s_options[1 + Bit_To_Index(GameTextOption::WRITE_EXTRA_LF_ON_STR_SAVE)]);
static_assert(s_option_6 == s_options[1 + Bit_To_Index(GameTextOption::RTL_REVERSE)]);
} // namespace

bool Name_To_Game_Text_Option(const char *name, GameTextOption &option)
Expand Down Expand Up @@ -359,7 +362,7 @@ bool GameTextFile::Save(const char *filename, FileType filetype, Languages langu
break;
}
case FileType::STR: {
success = Write_STR_File(file, Get_String_Infos(), m_options);
success = Write_STR_File(file, const_cast<StringInfos &>(Get_String_Infos()), m_options);
break;
}
case FileType::MULTI_STR: {
Expand Down Expand Up @@ -919,6 +922,10 @@ void GameTextFile::Parse_STR_Text(Utf8Array &buf, Utf16String &text, Options opt

// Translate final UTF16 string.
text.Translate(buf.data());
if (options.has(Options::Value::RTL_REVERSE)) {
text.ReverseString();
}

}

void GameTextFile::Parse_STR_Speech(Utf8View &buf, Utf8String &speech)
Expand Down Expand Up @@ -1128,7 +1135,7 @@ bool GameTextFile::Write_Multi_STR_File(
Utf8String str;
str.Get_Buffer_For_Read(TEXT_8_SIZE);

for (const MultiStringInfo &string_info : multi_string_infos) {
for (MultiStringInfo &string_info : multi_string_infos) {
if (!string_info.label.Is_Empty()) {
if (!Write_Multi_STR_Entry(file, string_info, languages, options, buf, str)) {
return false;
Expand All @@ -1139,7 +1146,7 @@ bool GameTextFile::Write_Multi_STR_File(
}

bool GameTextFile::Write_Multi_STR_Entry(
FileRef &file, const MultiStringInfo &string_info, Languages languages, Options options, Utf8Array &buf, Utf8String &str)
FileRef &file, MultiStringInfo &string_info, Languages languages, Options options, Utf8Array &buf, Utf8String &str)
{
bool ok = true;

Expand Down Expand Up @@ -1175,15 +1182,15 @@ bool GameTextFile::Write_STR_Language(FileRef &file, LanguageID language)
return ok;
}

bool GameTextFile::Write_STR_File(FileRef &file, const StringInfos &string_infos, Options options)
bool GameTextFile::Write_STR_File(FileRef &file, StringInfos &string_infos, Options options)
{
GAMETEXTLOG_INFO("Writing text file '%s' in STR format", file.Get_File_Name().Str());

Utf8Array buf = {};
Utf8String str;
str.Get_Buffer_For_Read(TEXT_8_SIZE);

for (const StringInfo &string_info : string_infos) {
for (StringInfo &string_info : string_infos) {
if (!string_info.label.Is_Empty()) {
if (!Write_STR_Entry(file, string_info, options, buf, str)) {
return false;
Expand All @@ -1194,7 +1201,7 @@ bool GameTextFile::Write_STR_File(FileRef &file, const StringInfos &string_infos
}

bool GameTextFile::Write_STR_Entry(
FileRef &file, const StringInfo &string_info, Options options, Utf8Array &buf, Utf8String &str)
FileRef &file, StringInfo &string_info, Options options, Utf8Array &buf, Utf8String &str)
{
bool ok = true;
ok &= Write_STR_Label(file, string_info.label);
Expand All @@ -1215,9 +1222,12 @@ bool GameTextFile::Write_STR_Label(FileRef &file, const Utf8String &label)
return ok;
}

bool GameTextFile::Write_STR_Text(FileRef &file, const Utf16String &text, Options options, Utf8Array &buf, Utf8String &str)
bool GameTextFile::Write_STR_Text(FileRef &file, Utf16String &text, Options options, Utf8Array &buf, Utf8String &str)
{
// Convert utf16 to utf8.
if (options.has(Options::Value::RTL_REVERSE)) {
text.ReverseString();
}
str.Translate(text.Str());

// STR does support escaped characters for special control characters. Write them out as escaped characters so they
Expand Down
9 changes: 5 additions & 4 deletions src/game/client/gametextfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ enum class GameTextOption : uint32_t
CHECK_BUFFER_LENGTH_ON_SAVE = (1 << 2),
KEEP_OBSOLETE_SPACES_ON_LOAD = (1 << 3),
WRITE_EXTRA_LF_ON_STR_SAVE = (1 << 4),
RTL_REVERSE = (1 << 5),
};

bool Name_To_Game_Text_Option(const char *name, GameTextOption &option);
Expand Down Expand Up @@ -218,18 +219,18 @@ class GameTextFile
static bool Write_Multi_STR_File(
FileRef &file, const ConstStringInfosPtrArray &string_infos_ptrs, Languages languages, Options options);
static bool Write_Multi_STR_Entry(FileRef &file,
const MultiStringInfo &string_info,
MultiStringInfo &string_info,
Languages languages,
Options options,
Utf8Array &buf,
Utf8String &str);
static bool Write_STR_Language(FileRef &file, LanguageID language);

static bool Write_STR_File(FileRef &file, const StringInfos &string_infos, Options options);
static bool Write_STR_File(FileRef &file, StringInfos &string_infos, Options options);
static bool Write_STR_Entry(
FileRef &file, const StringInfo &string_info, Options options, Utf8Array &buf, Utf8String &str);
FileRef &file, StringInfo &string_info, Options options, Utf8Array &buf, Utf8String &str);
static bool Write_STR_Label(FileRef &file, const Utf8String &label);
static bool Write_STR_Text(FileRef &file, const Utf16String &text, Options options, Utf8Array &buf, Utf8String &str);
static bool Write_STR_Text(FileRef &file, Utf16String &text, Options options, Utf8Array &buf, Utf8String &str);
static bool Write_STR_Speech(FileRef &file, const Utf8String &speech);
static bool Write_STR_End(FileRef &file);

Expand Down
30 changes: 30 additions & 0 deletions src/game/common/system/unicodestring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,36 @@ void Utf16String::Trim()
}
}

/**
* Reverse string for RTL languages
*/
void Utf16String::ReverseString()
{
if (m_data == nullptr) {
return;
}

size_type len = Get_Length();
if (len <= 1) {
return;
}

unichar_t* buffer = Get_Buffer_For_Read(len);

size_t start = 0;
size_t end = len - 1;

while (start < end) {
unichar_t temp = buffer[start];
buffer[start] = buffer[end];
buffer[end] = temp;

start++;
end--;
}
}


void Utf16String::To_Lower()
{
unichar_t buf[MAX_FORMAT_BUF_LEN];
Expand Down
1 change: 1 addition & 0 deletions src/game/common/system/unicodestring.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class Utf16String
void Concat(unichar_t c);
void Concat(const unichar_t *s);
void Concat(Utf16String const &string) { Concat(string.Str()); }
void ReverseString();

void Trim();
void To_Lower();
Expand Down
18 changes: 16 additions & 2 deletions src/tools/gametextcompiler/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ All|English|German|French|Spanish|Italian|Japanese|Korean|Chinese|Brazilian|Poli

OPTION:enum
OPTION takes one [1] or multiple [n] options, separated by pipe:
None|Check_Buffer_Length_On_Load|Check_Buffer_Length_On_Save|
None|Check_Buffer_Length_On_Load|Check_Buffer_Length_On_Save|RTL_Reverse
Keep_Obsolete_Spaces_On_Load|Write_Extra_LF_On_STR_Save|Optimize_Memory_Size
)#");
// 1 2 3 4 5 6 7 8 9 10 11 12
Expand All @@ -119,6 +119,8 @@ All capital words are NOT interpreted keywords and are substituted by the comman
[1] and [n] words show that argument takes one or multiple values.
Commands and command arguments are not case sensitive.

WARNING: Commands that save files will overwrite existing files without confirmation.

-options OPTION[n]
> Sets option(s) for loaded and saved file.

Expand All @@ -142,6 +144,18 @@ Commands and command arguments are not case sensitive.

-save_str_languages LANGUAGE[n]
> Sets language(s) to save Multi STR file with.

Example 1: Convert a CSF file to STR format
> gametextcompiler.exe -load_csf D:\generals.csf -save_str D:\generals.str

Example 2: Convert an STR file to CSF format with given language
> gametextcompiler.exe -load_str D:\generals.str -swap_and_set_language English -save_csf D:\generals.csf

Example 3: Load a specific language from a multi-language file and save to a CSF file
> gametextcompiler.exe -load_str_languages English -load_str D:\generals.str -save_csf D:\generals.csf

Example 4: Convert a CSF file to STR format with RTL reversing
> -load_csf D:\generals.csf -save_str D:\generals.str -options RTL_REVERSE
)#");
}
// clang-format on
Expand Down Expand Up @@ -219,7 +233,7 @@ struct EngineSystemsCreator

int main(int argc, const char *argv[])
{
Print_Line("Game Text Compiler 1.1 by The Assembly Armada");
Print_Line("Game Text Compiler 1.2 by The Assembly Armada");

if (argc < 2) {
Print_Help();
Expand Down