Add load/save global vars (#296)
This commit is contained in:
parent
37e4822ed5
commit
cf5f865a23
|
@ -341,8 +341,8 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4
|
|||
// SFALL
|
||||
premadeCharactersInit();
|
||||
|
||||
if (!sfallGlobalVarsInit()) {
|
||||
debugPrint("Failed on sfallGlobalVarsInit");
|
||||
if (!sfall_gl_vars_init()) {
|
||||
debugPrint("Failed on sfall_gl_vars_init");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -409,7 +409,7 @@ void gameReset()
|
|||
_init_options_menu();
|
||||
|
||||
// SFALL
|
||||
sfallGlobalVarsReset();
|
||||
sfall_gl_vars_reset();
|
||||
sfallListsReset();
|
||||
messageListRepositoryReset();
|
||||
sfallArraysReset();
|
||||
|
@ -425,7 +425,7 @@ void gameExit()
|
|||
sfall_gl_scr_exit();
|
||||
sfallArraysExit();
|
||||
sfallListsExit();
|
||||
sfallGlobalVarsExit();
|
||||
sfall_gl_vars_exit();
|
||||
premadeCharactersExit();
|
||||
|
||||
tileDisable();
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "interpreter_lib.h"
|
||||
#include "memory_manager.h"
|
||||
#include "platform_compat.h"
|
||||
#include "sfall_global_scripts.h"
|
||||
#include "svga.h"
|
||||
|
||||
namespace fallout {
|
||||
|
@ -3011,6 +3012,15 @@ Program* runScript(char* name)
|
|||
// 0x46E1EC
|
||||
void _updatePrograms()
|
||||
{
|
||||
// CE: Implementation is different. Sfall inserts global scripts into
|
||||
// program list upon creation, so engine does not diffirentiate between
|
||||
// global and normal scripts. Global scripts in CE are not part of program
|
||||
// list, so we need a separate call to continue execution (usually
|
||||
// non-critical calls scheduled from managed windows). One more thing to
|
||||
// note is that global scripts in CE cannot handle conditional/timed procs
|
||||
// (which are not used anyway).
|
||||
sfall_gl_scr_update(_cpuBurstSize);
|
||||
|
||||
ProgramListNode* curr = gInterpreterProgramListHead;
|
||||
while (curr != NULL) {
|
||||
ProgramListNode* next = curr->next;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "scripts.h"
|
||||
#include "settings.h"
|
||||
#include "sfall_global_scripts.h"
|
||||
#include "sfall_global_vars.h"
|
||||
#include "skill.h"
|
||||
#include "stat.h"
|
||||
#include "svga.h"
|
||||
|
@ -1588,6 +1589,73 @@ static int lsgPerformSaveGame()
|
|||
|
||||
fileClose(_flptr);
|
||||
|
||||
// SFALL: Save sfallgv.sav.
|
||||
snprintf(_gmpath, sizeof(_gmpath), "%s\\%s%.2d\\", "SAVEGAME", "SLOT", _slot_cursor + 1);
|
||||
strcat(_gmpath, "sfallgv.sav");
|
||||
|
||||
_flptr = fileOpen(_gmpath, "wb");
|
||||
if (_flptr != NULL) {
|
||||
do {
|
||||
if (!sfall_gl_vars_save(_flptr)) {
|
||||
debugPrint("LOADSAVE (SFALL): ** Error saving global vars **\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: For now fill remaining sections with zeros to that Sfall
|
||||
// can successfully read our global vars and skip the rest.
|
||||
|
||||
int nextObjectId = 0;
|
||||
if (fileWrite(&nextObjectId, sizeof(nextObjectId), 1, _flptr) != 1) {
|
||||
debugPrint("LOADSAVE (SFALL): ** Error saving next object id **\n");
|
||||
break;
|
||||
}
|
||||
|
||||
int addedYears = 0;
|
||||
if (fileWrite(&addedYears, sizeof(addedYears), 1, _flptr) != 1) {
|
||||
debugPrint("LOADSAVE (SFALL): ** Error saving added years **\n");
|
||||
break;
|
||||
}
|
||||
|
||||
int fakeTraitsCount = 0;
|
||||
if (fileWrite(&fakeTraitsCount, sizeof(fakeTraitsCount), 1, _flptr) != 1) {
|
||||
debugPrint("LOADSAVE (SFALL): ** Error saving fake traits **\n");
|
||||
break;
|
||||
}
|
||||
|
||||
int fakePerksCount = 0;
|
||||
if (fileWrite(&fakePerksCount, sizeof(fakePerksCount), 1, _flptr) != 1) {
|
||||
debugPrint("LOADSAVE (SFALL): ** Error saving fake perks **\n");
|
||||
break;
|
||||
}
|
||||
|
||||
int fakeSelectablePerksCount = 0;
|
||||
if (fileWrite(&fakeSelectablePerksCount, sizeof(fakeSelectablePerksCount), 1, _flptr) != 1) {
|
||||
debugPrint("LOADSAVE (SFALL): ** Error saving fake selectable perks **\n");
|
||||
break;
|
||||
}
|
||||
|
||||
int arraysCountOld = 0;
|
||||
if (fileWrite(&arraysCountOld, sizeof(arraysCountOld), 1, _flptr) != 1) {
|
||||
debugPrint("LOADSAVE (SFALL): ** Error saving arrays (old fmt) **\n");
|
||||
break;
|
||||
}
|
||||
|
||||
int arraysCountNew = 0;
|
||||
if (fileWrite(&arraysCountNew, sizeof(arraysCountNew), 1, _flptr) != 1) {
|
||||
debugPrint("LOADSAVE (SFALL): ** Error saving arrays (new fmt) **\n");
|
||||
break;
|
||||
}
|
||||
|
||||
int drugPidsCount = 0;
|
||||
if (fileWrite(&drugPidsCount, sizeof(drugPidsCount), 1, _flptr) != 1) {
|
||||
debugPrint("LOADSAVE (SFALL): ** Error saving drug pids **\n");
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
fileClose(_flptr);
|
||||
}
|
||||
|
||||
snprintf(_gmpath, sizeof(_gmpath), "%s\\%s%.2d\\", "SAVEGAME", "SLOT", _slot_cursor + 1);
|
||||
_MapDirErase(_gmpath, "BAK");
|
||||
|
||||
|
@ -1663,6 +1731,24 @@ static int lsgLoadGameInSlot(int slot)
|
|||
debugPrint("LOADSAVE: Total load data read: %ld bytes.\n", fileTell(_flptr));
|
||||
fileClose(_flptr);
|
||||
|
||||
// SFALL: Load sfallgv.sav.
|
||||
snprintf(_gmpath, sizeof(_gmpath), "%s\\%s%.2d\\", "SAVEGAME", "SLOT", _slot_cursor + 1);
|
||||
strcat(_gmpath, "sfallgv.sav");
|
||||
|
||||
_flptr = fileOpen(_gmpath, "rb");
|
||||
if (_flptr != NULL) {
|
||||
do {
|
||||
if (!sfall_gl_vars_load(_flptr)) {
|
||||
debugPrint("LOADSAVE (SFALL): ** Error loading global vars **\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: For now silently ignore remaining sections.
|
||||
} while (0);
|
||||
|
||||
fileClose(_flptr);
|
||||
}
|
||||
|
||||
snprintf(_str, sizeof(_str), "%s\\", "MAPS");
|
||||
_MapDirErase(_str, "BAK");
|
||||
_proto_dude_update_gender();
|
||||
|
|
|
@ -210,4 +210,11 @@ bool sfall_gl_scr_is_loaded(Program* program)
|
|||
return true;
|
||||
}
|
||||
|
||||
void sfall_gl_scr_update(int burstSize)
|
||||
{
|
||||
for (auto& scr : state->globalScripts) {
|
||||
_interpret(scr.program, burstSize);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fallout
|
||||
|
|
|
@ -17,6 +17,7 @@ void sfall_gl_scr_process_worldmap();
|
|||
void sfall_gl_scr_set_repeat(Program* program, int frames);
|
||||
void sfall_gl_scr_set_type(Program* program, int type);
|
||||
bool sfall_gl_scr_is_loaded(Program* program);
|
||||
void sfall_gl_scr_update(int burstSize);
|
||||
|
||||
} // namespace fallout
|
||||
|
||||
|
|
|
@ -10,72 +10,127 @@ struct SfallGlobalVarsState {
|
|||
std::unordered_map<uint64_t, int> vars;
|
||||
};
|
||||
|
||||
static bool sfallGlobalVarsStore(uint64_t key, int value);
|
||||
static bool sfallGlobalVarsFetch(uint64_t key, int& value);
|
||||
#pragma pack(push)
|
||||
#pragma pack(8)
|
||||
|
||||
static SfallGlobalVarsState* _state;
|
||||
/// Matches Sfall's `GlobalVar` to maintain binary compatibility.
|
||||
struct GlobalVarEntry {
|
||||
uint64_t key;
|
||||
int32_t value;
|
||||
int32_t unused;
|
||||
};
|
||||
|
||||
bool sfallGlobalVarsInit()
|
||||
#pragma pack(pop)
|
||||
|
||||
static bool sfall_gl_vars_store(uint64_t key, int value);
|
||||
static bool sfall_gl_vars_fetch(uint64_t key, int& value);
|
||||
|
||||
static SfallGlobalVarsState* sfall_gl_vars_state = nullptr;
|
||||
|
||||
bool sfall_gl_vars_init()
|
||||
{
|
||||
_state = new (std::nothrow) SfallGlobalVarsState();
|
||||
if (_state == nullptr) {
|
||||
sfall_gl_vars_state = new (std::nothrow) SfallGlobalVarsState();
|
||||
if (sfall_gl_vars_state == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void sfallGlobalVarsReset()
|
||||
void sfall_gl_vars_reset()
|
||||
{
|
||||
_state->vars.clear();
|
||||
sfall_gl_vars_state->vars.clear();
|
||||
}
|
||||
|
||||
void sfallGlobalVarsExit()
|
||||
void sfall_gl_vars_exit()
|
||||
{
|
||||
if (_state != nullptr) {
|
||||
delete _state;
|
||||
_state = nullptr;
|
||||
if (sfall_gl_vars_state != nullptr) {
|
||||
delete sfall_gl_vars_state;
|
||||
sfall_gl_vars_state = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool sfallGlobalVarsStore(const char* key, int value)
|
||||
bool sfall_gl_vars_save(File* stream)
|
||||
{
|
||||
int count = static_cast<int>(sfall_gl_vars_state->vars.size());
|
||||
if (fileWrite(&count, sizeof(count), 1, stream) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GlobalVarEntry entry = { 0 };
|
||||
for (auto& pair : sfall_gl_vars_state->vars) {
|
||||
entry.key = pair.first;
|
||||
entry.value = pair.second;
|
||||
|
||||
if (fileWrite(&entry, sizeof(entry), 1, stream) != 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sfall_gl_vars_load(File* stream)
|
||||
{
|
||||
int count;
|
||||
if (fileRead(&count, sizeof(count), 1, stream) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sfall_gl_vars_state->vars.reserve(count);
|
||||
|
||||
GlobalVarEntry entry;
|
||||
while (count > 0) {
|
||||
if (fileRead(&entry, sizeof(entry), 1, stream) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sfall_gl_vars_state->vars[entry.key] = static_cast<int>(entry.value);
|
||||
|
||||
count--;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sfall_gl_vars_store(const char* key, int value)
|
||||
{
|
||||
if (strlen(key) != 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t numericKey = *(reinterpret_cast<const uint64_t*>(key));
|
||||
return sfallGlobalVarsStore(numericKey, value);
|
||||
return sfall_gl_vars_store(numericKey, value);
|
||||
}
|
||||
|
||||
bool sfallGlobalVarsStore(int key, int value)
|
||||
bool sfall_gl_vars_store(int key, int value)
|
||||
{
|
||||
return sfallGlobalVarsStore(static_cast<uint64_t>(key), value);
|
||||
return sfall_gl_vars_store(static_cast<uint64_t>(key), value);
|
||||
}
|
||||
|
||||
bool sfallGlobalVarsFetch(const char* key, int& value)
|
||||
bool sfall_gl_vars_fetch(const char* key, int& value)
|
||||
{
|
||||
if (strlen(key) != 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t numericKey = *(reinterpret_cast<const uint64_t*>(key));
|
||||
return sfallGlobalVarsFetch(numericKey, value);
|
||||
return sfall_gl_vars_fetch(numericKey, value);
|
||||
}
|
||||
|
||||
bool sfallGlobalVarsFetch(int key, int& value)
|
||||
bool sfall_gl_vars_fetch(int key, int& value)
|
||||
{
|
||||
return sfallGlobalVarsFetch(static_cast<uint64_t>(key), value);
|
||||
return sfall_gl_vars_fetch(static_cast<uint64_t>(key), value);
|
||||
}
|
||||
|
||||
static bool sfallGlobalVarsStore(uint64_t key, int value)
|
||||
static bool sfall_gl_vars_store(uint64_t key, int value)
|
||||
{
|
||||
auto it = _state->vars.find(key);
|
||||
if (it == _state->vars.end()) {
|
||||
_state->vars.emplace(key, value);
|
||||
auto it = sfall_gl_vars_state->vars.find(key);
|
||||
if (it == sfall_gl_vars_state->vars.end()) {
|
||||
sfall_gl_vars_state->vars.emplace(key, value);
|
||||
} else {
|
||||
if (value == 0) {
|
||||
_state->vars.erase(it);
|
||||
sfall_gl_vars_state->vars.erase(it);
|
||||
} else {
|
||||
it->second = value;
|
||||
}
|
||||
|
@ -84,10 +139,10 @@ static bool sfallGlobalVarsStore(uint64_t key, int value)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool sfallGlobalVarsFetch(uint64_t key, int& value)
|
||||
static bool sfall_gl_vars_fetch(uint64_t key, int& value)
|
||||
{
|
||||
auto it = _state->vars.find(key);
|
||||
if (it == _state->vars.end()) {
|
||||
auto it = sfall_gl_vars_state->vars.find(key);
|
||||
if (it == sfall_gl_vars_state->vars.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
#ifndef FALLOUT_SFALL_GLOBAL_VARS_H_
|
||||
#define FALLOUT_SFALL_GLOBAL_VARS_H_
|
||||
|
||||
#include "db.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);
|
||||
bool sfall_gl_vars_init();
|
||||
void sfall_gl_vars_reset();
|
||||
void sfall_gl_vars_exit();
|
||||
bool sfall_gl_vars_save(File* stream);
|
||||
bool sfall_gl_vars_load(File* stream);
|
||||
bool sfall_gl_vars_store(const char* key, int value);
|
||||
bool sfall_gl_vars_store(int key, int value);
|
||||
bool sfall_gl_vars_fetch(const char* key, int& value);
|
||||
bool sfall_gl_vars_fetch(int key, int& value);
|
||||
|
||||
} // namespace fallout
|
||||
|
||||
|
|
|
@ -167,9 +167,9 @@ static void opSetGlobalVar(Program* program)
|
|||
|
||||
if ((variable.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) {
|
||||
const char* key = programGetString(program, variable.opcode, variable.integerValue);
|
||||
sfallGlobalVarsStore(key, value.integerValue);
|
||||
sfall_gl_vars_store(key, value.integerValue);
|
||||
} else if (variable.opcode == VALUE_TYPE_INT) {
|
||||
sfallGlobalVarsStore(variable.integerValue, value.integerValue);
|
||||
sfall_gl_vars_store(variable.integerValue, value.integerValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,9 +181,9 @@ static void opGetGlobalInt(Program* 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);
|
||||
sfall_gl_vars_fetch(key, value);
|
||||
} else if (variable.opcode == VALUE_TYPE_INT) {
|
||||
sfallGlobalVarsFetch(variable.integerValue, value);
|
||||
sfall_gl_vars_fetch(variable.integerValue, value);
|
||||
}
|
||||
|
||||
programStackPushInteger(program, value);
|
||||
|
|
Loading…
Reference in New Issue