Skip to content

Commit

Permalink
Added load_fxt and unload_fxt opcodes (#170)
Browse files Browse the repository at this point in the history
  • Loading branch information
MiranDMC authored Jul 29, 2024
1 parent 5e81b14 commit 90bca75
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 13 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
- new opcode **2603 ([is_text_prefix](https://library.sannybuilder.com/#/sa/text/2603))**
- new opcode **2604 ([is_text_suffix](https://library.sannybuilder.com/#/sa/text/2604))**
- new opcode **2605 ([display_text_formatted](https://library.sannybuilder.com/#/sa/text/2605))**
- new opcode **2606 ([load_fxt](https://library.sannybuilder.com/#/sa/text/2606))**
- new opcode **2607 ([unload_fxt](https://library.sannybuilder.com/#/sa/text/2607))**
- new and updated opcodes
- implemented support for **memory pointer string** arguments for all game's native opcodes
- **0B1E ([sign_extend](https://library.sannybuilder.com/#/sa/bitwise/0B1E))**
Expand Down
33 changes: 22 additions & 11 deletions cleo_plugins/Text/CTextManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,13 @@ namespace CLEO

bool CTextManager::AddFxt(const char *key, const char *value, bool dynamic)
{
// TODO: replace this part with in-place construction of FxtEntry,
// when it will be implemented in libstdc++
// ^^ me iz noob and doesnt can use GNU

auto fxt = fxts.find(key);

if (fxt != fxts.end())
{
if (fxt->second->text.compare(value) == 0)
return true; // already present

if (!dynamic || fxt->second->is_static)
{
LOG_WARNING(0, "Attempting to add FXT \'%s\' - FAILED (GXT conflict)", key, value);
Expand All @@ -47,6 +46,7 @@ namespace CLEO
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
fxts[str.c_str()] = new FxtEntry(value, !dynamic);
}

return true;
}

Expand Down Expand Up @@ -122,13 +122,13 @@ namespace CLEO
{
}

size_t CTextManager::ParseFxtFile(std::istream& stream)
size_t CTextManager::ParseFxtFile(std::istream& stream, bool dynamic, bool remove)
{
static char buf[0x100];
char *key_iterator, *value_iterator, *value_start, *key_start;
stream.exceptions(std::ios::badbit);

size_t addedCount = 0;
size_t keyCount = 0;
while (true)
{
if (stream.eof()) break;
Expand All @@ -142,11 +142,22 @@ namespace CLEO
{
if (*key_iterator == '#') // start of comment
break;
if (*key_iterator == '/' && key_iterator[1] == '/')
if (*key_iterator == '/' && key_iterator[1] == '/') // comment
break;

if (isspace(*key_iterator))
{
*key_iterator = '\0';
*key_iterator = '\0'; // terminate key string

if (remove)
{
if (RemoveFxt(key_start))
{
keyCount++;
}
break;
}

// while (isspace(*++key_iterator)) ; // skip leading spaces
value_start = value_iterator = key_iterator + 1;
while (*value_iterator)
Expand All @@ -162,9 +173,9 @@ namespace CLEO
}

// register found fxt entry
if (AddFxt(key_start, value_start, false))
if (AddFxt(key_start, value_start, dynamic))
{
addedCount++;
keyCount++;
}

break;
Expand All @@ -173,6 +184,6 @@ namespace CLEO
}
}

return addedCount;
return keyCount;
}
}
2 changes: 1 addition & 1 deletion cleo_plugins/Text/CTextManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ namespace CLEO
const char *LocateFxt(const char *key);
// erase all fxts, added by scripts
void ClearDynamicFxts();
size_t ParseFxtFile(std::istream& stream);
size_t ParseFxtFile(std::istream& stream, bool dynamic = false, bool remove = false);
};
}
44 changes: 43 additions & 1 deletion cleo_plugins/Text/Text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class Text
CLEO_RegisterOpcode(0x2603, opcode_2603); // is_text_prefix
CLEO_RegisterOpcode(0x2604, opcode_2604); // is_text_sufix
CLEO_RegisterOpcode(0x2605, opcode_2605); // display_text_formatted
CLEO_RegisterOpcode(0x2606, opcode_2606); // load_fxt
CLEO_RegisterOpcode(0x2607, opcode_2607); // unload_fxt

// register event callbacks
CLEO_RegisterCallback(eCallbackId::GameBegin, OnGameBegin);
Expand Down Expand Up @@ -427,7 +429,7 @@ class Text
OPCODE_READ_PARAM_STRING_FORMATTED(text);

// new GXT label
// includes unprintable character, to ensure there will be no collision with user GXT lables
// includes unprintable character, to ensure there will be no collision with user GXT labels
char gxt[8] = { 0x01, 'C', 'L', 'E', 'O', '_', 0x01, 0x00 };
gxt[6] += CTheScripts::NumberOfIntroTextLinesThisFrame; // unique label for each possible entry

Expand All @@ -442,6 +444,46 @@ class Text

return OR_CONTINUE;
}

//2606=1, load_fxt %1d%
static OpcodeResult __stdcall opcode_2606(CLEO::CRunningScript* thread)
{
OPCODE_READ_PARAM_FILEPATH(filename);

size_t added = 0;
try
{
std::ifstream stream(filename);
added = textManager.ParseFxtFile(stream, true, false);
}
catch (std::exception& ex)
{
LOG_WARNING(0, "Loading of FXT file '%s' failed: \n%s", filename, ex.what());
}

OPCODE_CONDITION_RESULT(added != 0);
return OR_CONTINUE;
}

//2607=1, unload_fxt %1d%
static OpcodeResult __stdcall opcode_2607(CLEO::CRunningScript* thread)
{
OPCODE_READ_PARAM_FILEPATH(filename);

size_t removed = 0;
try
{
std::ifstream stream(filename);
removed = textManager.ParseFxtFile(stream, true, true);
}
catch (std::exception& ex)
{
LOG_WARNING(0, "Unloading of FXT file '%s' failed: \n%s", filename, ex.what());
}

OPCODE_CONDITION_RESULT(removed != 0);
return OR_CONTINUE;
}
} textInstance;

CTextManager Text::textManager;
Expand Down
56 changes: 56 additions & 0 deletions tests/cleo_tests/Text/2606.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{$CLEO .s}
{$INCLUDE_ONCE ../cleo_tester.inc}

script_name '2606'
test("2606 (load_fxt)", tests)
terminate_this_custom_script

function tests
it("GXTs should not exists yet", test1)
it("should load new GXTs", test2)
return

function test1
int ptr

ptr = get_text_label_string {key} 'CLEO_T1'
assert_ptr(ptr)
assert_eqs(ptr, "")

ptr = get_text_label_string {key} 'CLEO_T2'
assert_ptr(ptr)
assert_eqs(ptr, "")

ptr = get_text_label_string {key} 'CLEO_T3'
assert_ptr(ptr)
assert_eqs(ptr, "")
end

function test2
2606: load_fxt {filepath} "cleo\cleo_tests\text\non existing file.fxt"
assert_result_false()

2606: load_fxt {filepath} "cleo\cleo_tests\text\test.fxt"
assert_result_true()

int ptr

ptr = get_text_label_string {key} 'CLEO_T1'
assert_ptr(ptr)
assert_eqs(ptr, "Test one")

ptr = get_text_label_string {key} 'CLEO_T2'
assert_ptr(ptr)
assert_eqs(ptr, "Test two")

ptr = get_text_label_string {key} 'CLEO_T3'
assert_ptr(ptr)
assert_eqs(ptr, "Test three")

// load again
2606: load_fxt {filepath} "cleo\cleo_tests\text\test.fxt"
assert_result_true()

unload_fxt {filepath} "cleo\cleo_tests\text\test.fxt"
end
end
74 changes: 74 additions & 0 deletions tests/cleo_tests/Text/2607.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{$CLEO .s}
{$INCLUDE_ONCE ../cleo_tester.inc}

script_name '2607'
test("2607 (unload_fxt)", tests)
terminate_this_custom_script

function tests
it("GXTs should not exists yet", test1)
it("should load new GXTs", test2)
it("should unload GXTs", test3)
return

function test1
int ptr

ptr = get_text_label_string {key} 'CLEO_T1'
assert_ptr(ptr)
assert_eqs(ptr, "")

ptr = get_text_label_string {key} 'CLEO_T2'
assert_ptr(ptr)
assert_eqs(ptr, "")

ptr = get_text_label_string {key} 'CLEO_T3'
assert_ptr(ptr)
assert_eqs(ptr, "")
end

function test2
load_fxt {filepath} "cleo\cleo_tests\text\test.fxt"
assert_result_true()

int ptr

ptr = get_text_label_string {key} 'CLEO_T1'
assert_ptr(ptr)
assert_eqs(ptr, "Test one")

ptr = get_text_label_string {key} 'CLEO_T2'
assert_ptr(ptr)
assert_eqs(ptr, "Test two")

ptr = get_text_label_string {key} 'CLEO_T3'
assert_ptr(ptr)
assert_eqs(ptr, "Test three")

// load again
load_fxt {filepath} "cleo\cleo_tests\text\test.fxt"
assert_result_true()
end

function test3
2607: unload_fxt {filepath} "cleo\cleo_tests\text\non existing file.fxt"
assert_result_false()

2607: unload_fxt {filepath} "cleo\cleo_tests\text\test.fxt"
assert_result_true()

int ptr

ptr = get_text_label_string {key} 'CLEO_T1'
assert_ptr(ptr)
assert_eqs(ptr, "")

ptr = get_text_label_string {key} 'CLEO_T2'
assert_ptr(ptr)
assert_eqs(ptr, "")

ptr = get_text_label_string {key} 'CLEO_T3'
assert_ptr(ptr)
assert_eqs(ptr, "")
end
end
3 changes: 3 additions & 0 deletions tests/cleo_tests/Text/Test.fxt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CLEO_T1 Test one
CLEO_T2 Test two
CLEO_T3 Test three

0 comments on commit 90bca75

Please sign in to comment.