Add some Sfall global vars functions

See #200
This commit is contained in:
Alexander Batalov 2022-11-08 18:01:00 +03:00
parent 19bcfebe0d
commit 03a7e2e1b1
5 changed files with 159 additions and 0 deletions

View File

@ -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"
)

View File

@ -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();

98
src/sfall_global_vars.cc Normal file
View File

@ -0,0 +1,98 @@
#include "sfall_global_vars.h"
#include <cstdint>
#include <unordered_map>
namespace fallout {
struct State {
std::unordered_map<uint64_t, int> 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<const uint64_t*>(key));
return sfallGlobalVarsStore(numericKey, value);
}
bool sfallGlobalVarsStore(int key, int value)
{
return sfallGlobalVarsStore(static_cast<uint64_t>(key), value);
}
bool sfallGlobalVarsFetch(const char* key, int& value)
{
if (strlen(key) != 8) {
return false;
}
uint64_t numericKey = *(reinterpret_cast<const uint64_t*>(key));
return sfallGlobalVarsFetch(numericKey, value);
}
bool sfallGlobalVarsFetch(int key, int& value)
{
return sfallGlobalVarsFetch(static_cast<uint64_t>(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

16
src/sfall_global_vars.h Normal file
View File

@ -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_ */

View File

@ -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);