Fix storing pointers in map global variables

This commit is contained in:
Alexander Batalov 2022-11-09 14:35:07 +03:00
parent 3f25c9265b
commit 6c03e4e293
3 changed files with 37 additions and 10 deletions

View File

@ -1220,16 +1220,20 @@ static void opGetMapVar(Program* program)
{
int data = programStackPopInteger(program);
int value = mapGetGlobalVar(data);
ProgramValue value;
if (mapGetGlobalVar(data, value) == -1) {
value.opcode = VALUE_TYPE_INT;
value.integerValue = -1;
}
programStackPushInteger(program, value);
programStackPushValue(program, value);
}
// set_map_var
// 0x4558C8
static void opSetMapVar(Program* program)
{
int value = programStackPopInteger(program);
ProgramValue value = programStackPopValue(program);
int variable = programStackPopInteger(program);
mapSetGlobalVar(variable, value);

View File

@ -164,6 +164,11 @@ static char _scratchStr[40];
// 0x631E78
static char _map_path[COMPAT_MAX_PATH];
// CE: Basically the same problem described in |gMapLocalPointers|, but this
// time Olympus folks use global map variables to store objects (looks like
// only `self_obj`).
static std::vector<void*> gMapGlobalPointers;
// CE: There is a bug in the user-space scripting where they want to store
// pointers to |Object| instances in local vars. This is obviously wrong as it's
// meaningless to save these pointers in file. As a workaround use second array
@ -390,27 +395,41 @@ int mapSetElevation(int elevation)
}
// 0x482220
int mapSetGlobalVar(int var, int value)
int mapSetGlobalVar(int var, ProgramValue& value)
{
if (var < 0 || var >= gMapGlobalVarsLength) {
debugPrint("ERROR: attempt to reference map var out of range: %d", var);
return -1;
}
gMapGlobalVars[var] = value;
if (value.opcode == VALUE_TYPE_PTR) {
gMapGlobalVars[var] = 0;
gMapGlobalPointers[var] = value.pointerValue;
} else {
gMapGlobalVars[var] = value.integerValue;
gMapGlobalPointers[var] = nullptr;
}
return 0;
}
// 0x482250
int mapGetGlobalVar(int var)
int mapGetGlobalVar(int var, ProgramValue& value)
{
if (var < 0 || var >= gMapGlobalVarsLength) {
debugPrint("ERROR: attempt to reference map var out of range: %d", var);
return 0;
return -1;
}
return gMapGlobalVars[var];
if (gMapGlobalPointers[var] != nullptr) {
value.opcode = VALUE_TYPE_PTR;
value.pointerValue = gMapGlobalPointers[var];
} else {
value.opcode = VALUE_TYPE_INT;
value.integerValue = gMapGlobalVars[var];
}
return 0;
}
// 0x482280
@ -1521,6 +1540,8 @@ static int mapGlobalVariablesInit(int count)
if (gMapGlobalVars == NULL) {
return -1;
}
gMapGlobalPointers.resize(count);
}
gMapGlobalVarsLength = count;
@ -1536,6 +1557,8 @@ static void mapGlobalVariablesFree()
gMapGlobalVars = NULL;
gMapGlobalVarsLength = 0;
}
gMapGlobalPointers.clear();
}
// NOTE: Inlined.

View File

@ -86,8 +86,8 @@ void isoEnable();
bool isoDisable();
bool isoIsDisabled();
int mapSetElevation(int elevation);
int mapSetGlobalVar(int var, int value);
int mapGetGlobalVar(int var);
int mapSetGlobalVar(int var, ProgramValue& value);
int mapGetGlobalVar(int var, ProgramValue& value);
int mapSetLocalVar(int var, ProgramValue& value);
int mapGetLocalVar(int var, ProgramValue& value);
int _map_malloc_local_var(int a1);