From 03a7e2e1b1c4975ccc0c42854e10ee03de0a3205 Mon Sep 17 00:00:00 2001 From: Alexander Batalov Date: Tue, 8 Nov 2022 18:01:00 +0300 Subject: [PATCH] Add some Sfall global vars functions See #200 --- CMakeLists.txt | 2 + src/game.cc | 10 ++++ src/sfall_global_vars.cc | 98 ++++++++++++++++++++++++++++++++++++++++ src/sfall_global_vars.h | 16 +++++++ src/sfall_opcodes.cc | 33 ++++++++++++++ 5 files changed, 159 insertions(+) create mode 100644 src/sfall_global_vars.cc create mode 100644 src/sfall_global_vars.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8267917..cc05391 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,6 +269,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC "src/settings.h" "src/sfall_config.cc" "src/sfall_config.h" + "src/sfall_global_vars.cc" + "src/sfall_global_vars.h" "src/sfall_opcodes.cc" "src/sfall_opcodes.h" ) diff --git a/src/game.cc b/src/game.cc index 3d8c859..6d3290c 100644 --- a/src/game.cc +++ b/src/game.cc @@ -57,6 +57,7 @@ #include "scripts.h" #include "settings.h" #include "sfall_config.h" +#include "sfall_global_vars.h" #include "skill.h" #include "skilldex.h" #include "stat.h" @@ -346,6 +347,11 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4 // SFALL premadeCharactersInit(); + if (!sfallGlobalVarsInit()) { + debugPrint("Failed on sfallGlobalVarsInit"); + return -1; + } + return 0; } @@ -386,6 +392,9 @@ void gameReset() _game_user_wants_to_quit = 0; automapReset(); _init_options_menu(); + + // SFALL + sfallGlobalVarsReset(); } // 0x442C34 @@ -394,6 +403,7 @@ void gameExit() debugPrint("\nGame Exit\n"); // SFALL + sfallGlobalVarsExit(); premadeCharactersExit(); tileDisable(); diff --git a/src/sfall_global_vars.cc b/src/sfall_global_vars.cc new file mode 100644 index 0000000..5335acb --- /dev/null +++ b/src/sfall_global_vars.cc @@ -0,0 +1,98 @@ +#include "sfall_global_vars.h" + +#include +#include + +namespace fallout { + +struct State { + std::unordered_map vars; +}; + +static bool sfallGlobalVarsStore(uint64_t key, int value); +static bool sfallGlobalVarsFetch(uint64_t key, int& value); + +static State* _state; + +bool sfallGlobalVarsInit() +{ + _state = new (std::nothrow) State(); + if (_state == nullptr) { + return false; + } + + return true; +} + +void sfallGlobalVarsReset() +{ + _state->vars.clear(); +} + +void sfallGlobalVarsExit() +{ + if (_state != nullptr) { + delete _state; + _state = nullptr; + } +} + +bool sfallGlobalVarsStore(const char* key, int value) +{ + if (strlen(key) != 8) { + return false; + } + + uint64_t numericKey = *(reinterpret_cast(key)); + return sfallGlobalVarsStore(numericKey, value); +} + +bool sfallGlobalVarsStore(int key, int value) +{ + return sfallGlobalVarsStore(static_cast(key), value); +} + +bool sfallGlobalVarsFetch(const char* key, int& value) +{ + if (strlen(key) != 8) { + return false; + } + + uint64_t numericKey = *(reinterpret_cast(key)); + return sfallGlobalVarsFetch(numericKey, value); +} + +bool sfallGlobalVarsFetch(int key, int& value) +{ + return sfallGlobalVarsFetch(static_cast(key), value); +} + +static bool sfallGlobalVarsStore(uint64_t key, int value) +{ + auto it = _state->vars.find(key); + if (it == _state->vars.end()) { + _state->vars.emplace(key, value); + } else { + if (value == 0) { + _state->vars.erase(it); + } else { + it->second = value; + } + } + + return true; +} + +static bool sfallGlobalVarsFetch(uint64_t key, int& value) +{ + auto it = _state->vars.find(key); + if (it == _state->vars.end()) { + return false; + } + + value = it->second; + + return true; +} + +} // namespace fallout diff --git a/src/sfall_global_vars.h b/src/sfall_global_vars.h new file mode 100644 index 0000000..184fc6f --- /dev/null +++ b/src/sfall_global_vars.h @@ -0,0 +1,16 @@ +#ifndef FALLOUT_SFALL_GLOBAL_VARS_H_ +#define FALLOUT_SFALL_GLOBAL_VARS_H_ + +namespace fallout { + +bool sfallGlobalVarsInit(); +void sfallGlobalVarsReset(); +void sfallGlobalVarsExit(); +bool sfallGlobalVarsStore(const char* key, int value); +bool sfallGlobalVarsStore(int key, int value); +bool sfallGlobalVarsFetch(const char* key, int& value); +bool sfallGlobalVarsFetch(int key, int& value); + +} // namespace fallout + +#endif /* FALLOUT_SFALL_GLOBAL_VARS_H_ */ diff --git a/src/sfall_opcodes.cc b/src/sfall_opcodes.cc index 55d09d9..9b4ba2b 100644 --- a/src/sfall_opcodes.cc +++ b/src/sfall_opcodes.cc @@ -5,6 +5,7 @@ #include "interpreter.h" #include "item.h" #include "mouse.h" +#include "sfall_global_vars.h" #include "svga.h" namespace fallout { @@ -15,6 +16,36 @@ static void opGetCurrentHand(Program* program) programStackPushInteger(program, interfaceGetCurrentHand()); } +// set_sfall_global +static void opSetGlobalVar(Program* program) +{ + ProgramValue value = programStackPopValue(program); + ProgramValue variable = programStackPopValue(program); + + if ((variable.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { + const char* key = programGetString(program, variable.opcode, variable.integerValue); + sfallGlobalVarsStore(key, value.integerValue); + } else if (variable.opcode == VALUE_TYPE_INT) { + sfallGlobalVarsStore(variable.integerValue, value.integerValue); + } +} + +// get_sfall_global_int +static void opGetGlobalInt(Program* program) +{ + ProgramValue variable = programStackPopValue(program); + + int value = 0; + if ((variable.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) { + const char* key = programGetString(program, variable.opcode, variable.integerValue); + sfallGlobalVarsFetch(key, value); + } else if (variable.opcode == VALUE_TYPE_INT) { + sfallGlobalVarsFetch(variable.integerValue, value); + } + + programStackPushInteger(program, value); +} + // get_weapon_ammo_pid static void opGetWeaponAmmoPid(Program* program) { @@ -149,6 +180,8 @@ static void opArtExists(Program* program) void sfallOpcodesInit() { interpreterRegisterOpcode(0x8193, opGetCurrentHand); + interpreterRegisterOpcode(0x819D, opSetGlobalVar); + interpreterRegisterOpcode(0x819E, opGetGlobalInt); interpreterRegisterOpcode(0x8217, opGetWeaponAmmoPid); interpreterRegisterOpcode(0x8219, opGetWeaponAmmoCount); interpreterRegisterOpcode(0x821A, opSetWeaponAmmoCount);