diff --git a/src/sfall_arrays.cc b/src/sfall_arrays.cc index 0681f84..f7357a5 100644 --- a/src/sfall_arrays.cc +++ b/src/sfall_arrays.cc @@ -55,6 +55,8 @@ public: virtual ProgramValue GetArray(const ProgramValue& key) = 0; virtual void SetArray(const ProgramValue& key, const ProgramValue& val, bool allowUnset) = 0; virtual void ResizeArray(int newLen) = 0; + virtual ProgramValue ScanArray(const ProgramValue& value, ValueCompareStrings& cmp) = 0; + virtual ~SFallArray() = default; }; @@ -127,6 +129,16 @@ public: ListSort(values, newLen, std::less()); } } + + ProgramValue ScanArray(const ProgramValue& value, ValueCompareStrings& cmp) + { + for (size_t i = 0; i < size(); i++) { + if (cmp(value, values[i])) { + return ProgramValue(i); + } + } + return ProgramValue(-1); + } }; class SFallArrayAssoc : public SFallArray { @@ -232,6 +244,16 @@ public: MapSort(newLen); } }; + + ProgramValue ScanArray(const ProgramValue& value, ValueCompareStrings& cmp) + { + for (const auto &pair : map) { + if (cmp(pair.second, value)) { + return pair.first; + } + } + return ProgramValue(-1); + } }; void SFallArrayAssoc::MapSort(int type) @@ -389,4 +411,14 @@ int StackArray(const ProgramValue& key, const ProgramValue& val) return 0; } +ProgramValue ScanArray(ArrayId array_id, const ProgramValue& val, ValueCompareStrings& cmp) +{ + auto arr = get_array_by_id(array_id); + if (!arr) { + return ProgramValue(-1); + }; + + return arr->ScanArray(val, cmp); +} + } \ No newline at end of file diff --git a/src/sfall_arrays.h b/src/sfall_arrays.h index 1ee94c3..818b9f2 100644 --- a/src/sfall_arrays.h +++ b/src/sfall_arrays.h @@ -3,6 +3,7 @@ #include "interpreter.h" #include "object.h" +#include #include namespace fallout { @@ -13,6 +14,8 @@ namespace fallout { using ArrayId = unsigned int; +using ValueCompareStrings = const std::function; + ArrayId CreateArray(int len, uint32_t flags); ArrayId CreateTempArray(int len, uint32_t flags); ProgramValue GetArrayKey(ArrayId array_id, int index); @@ -25,6 +28,7 @@ void ResizeArray(ArrayId array_id, int newLen); void DeleteAllTempArrays(); void sfallArraysReset(); int StackArray(const ProgramValue& key, const ProgramValue& val); +ProgramValue ScanArray(ArrayId array_id, const ProgramValue& val, ValueCompareStrings& cmp); } #endif /* SFALL_ARRAYS */ \ No newline at end of file diff --git a/src/sfall_opcodes.cc b/src/sfall_opcodes.cc index 8ab43c6..c9a76bd 100644 --- a/src/sfall_opcodes.cc +++ b/src/sfall_opcodes.cc @@ -533,18 +533,37 @@ static void opSetArray(Program* program) SetArray(arrayId, key, value, true); } - // arrayexpr static void opStackArray(Program* program) { auto value = programStackPopValue(program); - auto key = programStackPopValue(program); + auto key = programStackPopValue(program); auto returnValue = StackArray(key, value); programStackPushInteger(program, returnValue); } +// scan array +static void opScanArray(Program* program) +{ + auto value = programStackPopValue(program); + auto arrayId = programStackPopInteger(program); - + auto returnValue = ScanArray(arrayId, value, [&program](const ProgramValue& a, const ProgramValue& b) -> bool { + if (!a.isString()) { + return a == b; + }; + if (!b.isString()) { + return false; + }; + auto str1 = programGetString(program, a.opcode, a.integerValue); + auto str2 = programGetString(program, a.opcode, a.integerValue); + if (!str1 || !str2) { + return false; + }; + return strcmp(str1, str2) == 0; + }); + programStackPushValue(program, returnValue); +} // get_array static void opGetArray(Program* program) @@ -598,8 +617,8 @@ static void opPartyMemberList(Program* program) // type_of static void opTypeOf(Program* program) -{ - auto value = programStackPopValue(program); +{ + auto value = programStackPopValue(program); if (value.isInt()) { programStackPushInteger(program, 1); } else if (value.isFloat()) { @@ -753,6 +772,7 @@ void sfallOpcodesInit() interpreterRegisterOpcode(0x8233, opFixArray); interpreterRegisterOpcode(0x8237, opParseInt); interpreterRegisterOpcode(0x8238, op_atof); + interpreterRegisterOpcode(0x8239, opScanArray); interpreterRegisterOpcode(0x824B, op_tile_under_cursor); interpreterRegisterOpcode(0x824F, opGetStringLength); interpreterRegisterOpcode(0x8253, opTypeOf);