pmd-sky/src/script_variable.c
2025-12-18 13:09:43 +00:00

724 lines
27 KiB
C

#include "debug.h"
#include "enums.h"
#include "main_0200224C.h"
#include "main_0200330C.h"
#include "main_0200ECFC.h"
#include "scenario_flag.h"
#include "script_variable.h"
#include "script_variable_2.h"
#include "special_episode.h"
#include "story_progress.h"
#define LOCAL_SCRIPT_VAR_OFFSET (s16) 0x400
#ifdef JAPAN
#define VAR_GROUND_ENTER_VALUE 0x13C
#elif EUROPE
#define VAR_GROUND_ENTER_VALUE 0x143
#else
#define VAR_GROUND_ENTER_VALUE 0x137
#endif
// Global script variable definitions
extern struct script_var_def SCRIPT_VARS[];
// Local script variable definitions
extern struct script_var_def SCRIPT_VARS_LOCALS[];
// Global script variable values
extern u8 SCRIPT_VARS_VALUES[];
extern u8 EVENT_FLAG_EXPANSION_ERROR;
extern u8 EVENT_FLAG_COMPARE_SCRIPT_VARIABLES_ERROR;
extern const u8 EVENT_FLAG_GAME_MODE_DEBUG_MSG;
extern const u8 EVENT_FLAG_BACKUP_DEBUG_MSG;
extern u8 EVENT_FLAG_SIZE_DEBUG_MSG;
extern s16 _0209DF70[18];
extern s32 GetPartyMembers(s32 param1);
extern s32 GetMoneyStored();
extern s32 GetLanguageType();
extern enum game_mode GetGameMode();
extern s32 GetNotifyNote();
extern s32 AddMoneyCarried(s32 arg0);
extern s32 SetMoneyCarried(s32 arg0);
extern s32 SetMoneyStored(s32 arg0);
extern s32 SetNotifyNote(s32 arg0);
extern void InitDungeonListScriptVars();
const u8 EVENT_FLAG_FILE_NAME[] = "event_flag.c";
const struct prog_pos_info EVENT_FLAG_PROG_POS_INFO_CALC_SCRIPT_VARIABLES = {
(u8*) EVENT_FLAG_FILE_NAME,
1001
};
const struct prog_pos_info EVENT_FLAG_PROG_POS_INFO_COMPARE_SCRIPT_VARIABLES = {
(u8*) EVENT_FLAG_FILE_NAME,
1044
};
void DebugPrintEventFlagSize() {
Debug_Print0(&EVENT_FLAG_SIZE_DEBUG_MSG, _0209DF70[18], 0x400);
}
void InitScriptVariableValues() {
for(s32 sv_id = 0; sv_id < LOCAL_SCRIPT_VAR_OFFSET; sv_id++) {
SCRIPT_VARS_VALUES[sv_id] = 0;
}
for (s16 sv_id = 0; sv_id < 114; sv_id++) {
struct script_var_def* def = &SCRIPT_VARS[sv_id];
s16 type = def->type;
if (type != 0 && type != 9) {
for (u16 idx = 0; idx < def->n_values; idx++) {
SaveScriptVariableValueAtIndex(0, sv_id, idx, def->default_val);
}
}
}
SaveScriptVariableValue(0, VAR_ROM_VARIATION, 0);
ZeroInitScriptVariable(0, 1);
InitEventFlagScriptVars();
for(s32 idx2 = 0; idx2 < 4; idx2++) {
SaveScriptVariableValueAtIndex(0, VAR_GROUND_ENTER_BACKUP, idx2, VAR_GROUND_ENTER_VALUE);
SaveScriptVariableValueAtIndex(0, VAR_GROUND_ENTER_LINK_BACKUP, idx2, 0);
SaveScriptVariableValueAtIndex(0, VAR_GROUND_GETOUT_BACKUP, idx2, VAR_GROUND_ENTER_VALUE);
SaveScriptVariableValueAtIndex(0, VAR_GROUND_MAP_BACKUP, idx2, -1);
SaveScriptVariableValueAtIndex(0, VAR_GROUND_PLACE_BACKUP, idx2, 0xBB);
SaveScriptVariableValueAtIndex(0, VAR_DUNGEON_ENTER_BACKUP, idx2, 0);
SaveScriptVariableValueAtIndex(0, VAR_DUNGEON_ENTER_INDEX_BACKUP, idx2, -1);
SaveScriptVariableValueAtIndex(0, VAR_DUNGEON_RESULT_BACKUP, idx2, 0);
SaveScriptVariableValueAtIndex(0, VAR_GROUND_START_MODE_BACKUP, idx2, 0);
SaveScriptVariableValueAtIndex(0, VAR_PLAYER_KIND_BACKUP, idx2, 0);
SaveScriptVariableValueAtIndex(0, VAR_ATTENDANT1_KIND_BACKUP, idx2, 2);
SaveScriptVariableValueAtIndex(0, VAR_ATTENDANT2_KIND_BACKUP, idx2, 0);
}
SaveScriptVariableValue(0, VAR_DUNGEON_SELECT, -1);
SaveScriptVariableValue(0, VAR_REQUEST_CLEAR_COUNT, 0);
SaveScriptVariableValue(0, VAR_TEAM_RANK_EVENT_LEVEL, 0);
SaveScriptVariableValue(0, VAR_HERO_FIRST_KIND, 0);
SaveScriptVariableValue(0, VAR_PARTNER_FIRST_KIND, 0);
SaveScriptVariableValue(0, VAR_HERO_TALK_KIND, 4);
SaveScriptVariableValue(0, VAR_PARTNER_TALK_KIND, 1);
SaveScriptVariableValue(0, VAR_SPECIAL_EPISODE_TYPE, -1);
ZeroInitScriptVariable(0, VAR_SPECIAL_EPISODE_OPEN);
ZeroInitScriptVariable(0, VAR_SPECIAL_EPISODE_OPEN_OLD);
ZeroInitScriptVariable(0, VAR_SPECIAL_EPISODE_CONQUEST);
InitScenarioProgressScriptVars();
InitWorldMapScriptVars();
InitDungeonListScriptVars();
}
void InitEventFlagScriptVars() {
SaveScriptVariableValue(0, VAR_GROUND_ENTER, VAR_GROUND_ENTER_VALUE);
SaveScriptVariableValue(0, VAR_GROUND_ENTER_LINK, 0);
SaveScriptVariableValue(0, VAR_GROUND_GETOUT, VAR_GROUND_ENTER_VALUE);
SaveScriptVariableValue(0, VAR_GROUND_MAP, -1);
SaveScriptVariableValue(0, VAR_GROUND_PLACE, 0xBB);
SaveScriptVariableValue(0, VAR_DUNGEON_ENTER, 0);
SaveScriptVariableValue(0, VAR_DUNGEON_ENTER_INDEX, -1);
SaveScriptVariableValue(0, VAR_DUNGEON_RESULT, 0);
SaveScriptVariableValue(0, VAR_GROUND_START_MODE, 0);
SaveScriptVariableValue(0, VAR_PLAYER_KIND, 0);
SaveScriptVariableValue(0, VAR_ATTENDANT1_KIND, 2);
SaveScriptVariableValue(0, VAR_ATTENDANT2_KIND, 0);
}
void DefaultInitScriptVariable(union script_var_value sv_locals[], s16 sv_id) {
struct script_var_def* def;
if (sv_id < LOCAL_SCRIPT_VAR_OFFSET) {
def = &SCRIPT_VARS[sv_id];
} else {
def = &SCRIPT_VARS_LOCALS[sv_id - LOCAL_SCRIPT_VAR_OFFSET];
}
for(u16 idx = 0; idx < def->n_values; idx++) {
SaveScriptVariableValueAtIndex(sv_locals, sv_id, idx, def->default_val);
}
}
void ZeroInitScriptVariable(union script_var_value sv_locals[], s16 sv_id) {
struct script_var_def* def;
if (sv_id < LOCAL_SCRIPT_VAR_OFFSET) {
def = &SCRIPT_VARS[sv_id];
} else {
def = &SCRIPT_VARS_LOCALS[sv_id - LOCAL_SCRIPT_VAR_OFFSET];
}
for(u16 idx = 0; idx < def->n_values; idx++) {
SaveScriptVariableValueAtIndex(sv_locals, sv_id, idx, 0);
}
}
void LoadScriptVariableRaw(struct script_var_raw* sv_raw,
union script_var_value sv_val_local[],
const s16 sv_id) {
if (sv_id < (s16) LOCAL_SCRIPT_VAR_OFFSET) {
// global script var
sv_raw->def = &SCRIPT_VARS[sv_id];
sv_raw->value = (union script_var_value*)
&SCRIPT_VARS_VALUES[sv_raw->def->mem_offset];
} else {
// local script var
sv_raw->def = &SCRIPT_VARS_LOCALS[sv_id - LOCAL_SCRIPT_VAR_OFFSET];
sv_raw->value = &sv_val_local[sv_raw->def->mem_offset];
}
}
s32 LoadScriptVariableValue(union script_var_value sv_local[], s16 sv_id)
{
struct script_var_raw result;
LoadScriptVariableRaw(&result, sv_local, sv_id);
switch((s16)result.def->type) {
case VARTYPE_NONE:
break;
case VARTYPE_BIT:
// Return true if the value has a particular bit set
if(result.value->u8 & (u8)(1 << result.def->bitshift)) {
return TRUE;
}
return FALSE;
case VARTYPE_STRING:
case VARTYPE_UINT8:
return result.value->u8;
case VARTYPE_INT8:
return result.value->s8;
case VARTYPE_UINT16:
return result.value->u16;
case VARTYPE_INT16:
return result.value->s16;
case VARTYPE_UINT32:
case VARTYPE_INT32:
return result.value->u32;
case VARTYPE_SPECIAL:
switch(sv_id) {
case VAR_FRIEND_SUM:
return 1;
case VAR_UNIT_SUM:
return GetPartyMembers(0);
case VAR_CARRY_GOLD:
return GetMoneyCarried();
case VAR_BANK_GOLD:
return GetMoneyStored();
case VAR_LANGUAGE_TYPE:
return GetLanguageType();
case VAR_GAME_MODE:
return GetGameMode();
case VAR_EXECUTE_SPECIAL_EPISODE_TYPE:
switch(GetGameMode()) {
case GAME_MODE_1:
return GetDebugSpecialEpisodeNumber();
case GAME_MODE_SPECIAL_EPISODE:
return GetSpecialEpisodeType();
default:
return -1;
}
case VAR_NOTE_MODIFY_FLAG:
return GetNotifyNote();
}
}
return 0;
}
s32 LoadScriptVariableValueAtIndex(union script_var_value sv_local[], s16 id, u16 idx)
{
struct script_var_raw result;
LoadScriptVariableRaw(&result, sv_local, id);
switch ((s16)result.def->type) {
case VARTYPE_NONE:
break;
case VARTYPE_BIT: {
u16 offset = idx + result.def->bitshift;
u8 val = ((u8*)result.value)[offset / 8];
u8 bit = (1 << (offset & (8 - 1)));
return (val & bit) != 0;
}
case VARTYPE_STRING:
case VARTYPE_UINT8:
return ((u8*)result.value)[idx];
case VARTYPE_INT8:
return ((s8*)result.value)[idx];
case VARTYPE_UINT16:
return ((u16*)result.value)[idx];
case VARTYPE_INT16:
return ((s16*)result.value)[idx];
case VARTYPE_UINT32:
case VARTYPE_INT32:
return ((u32*)result.value)[idx];
case VARTYPE_SPECIAL:
switch (id) {
case VAR_FRIEND_SUM:
return 1;
case VAR_UNIT_SUM:
return GetPartyMembers(0);
case VAR_CARRY_GOLD:
return GetMoneyCarried();
case VAR_BANK_GOLD:
return GetMoneyStored();
case VAR_LANGUAGE_TYPE:
return GetLanguageType();
case VAR_GAME_MODE:
return GetGameMode();
case VAR_EXECUTE_SPECIAL_EPISODE_TYPE:
switch (GetGameMode()) {
case GAME_MODE_1:
return GetDebugSpecialEpisodeNumber();
case GAME_MODE_SPECIAL_EPISODE:
return GetSpecialEpisodeType();
default:
return -1;
}
case VAR_NOTE_MODIFY_FLAG:
return GetNotifyNote();
}
}
return 0;
}
void SaveScriptVariableValue(union script_var_value sv_locals[], const s16 script_var_id, u32 new_val)
{
struct script_var_raw script_var_raw;
LoadScriptVariableRaw(&script_var_raw, sv_locals, script_var_id);
switch ((s16)script_var_raw.def->type) {
case VARTYPE_BIT:
u32 bitmask = 1 << script_var_raw.def->bitshift;
u8 truncated_bitmask = bitmask & 0xff;
if (new_val != FALSE) {
// the new value is true, so we set the bits specified in the bitmask
script_var_raw.value->u8 |= truncated_bitmask;
return;
}
// the new value is false, so we unset the bits specified in bitmask
u8 current_val;
current_val = script_var_raw.value->u8;
current_val |= truncated_bitmask;
script_var_raw.value->u8 = truncated_bitmask ^ current_val;
return;
case VARTYPE_STRING:
case VARTYPE_UINT8:
script_var_raw.value->u8 = (u8)new_val;
return;
case VARTYPE_INT8:
script_var_raw.value->s8 = (s8)new_val;
return;
case VARTYPE_UINT16:
script_var_raw.value->u16 = (u16)new_val;
return;
case VARTYPE_INT16:
script_var_raw.value->s16 = (s16)new_val;
return;
case VARTYPE_UINT32:
case VARTYPE_INT32:
script_var_raw.value->u32 = new_val;
return;
case VARTYPE_SPECIAL:
switch (script_var_id) {
case VAR_CARRY_GOLD:
SetMoneyCarried(new_val);
AddMoneyCarried(0);
return;
case VAR_BANK_GOLD:
SetMoneyStored(new_val);
return;
case VAR_EXECUTE_SPECIAL_EPISODE_TYPE:
if (GetGameMode() == GAME_MODE_1) {
SetDebugSpecialEpisodeNumber(new_val);
return;
}
return;
case VAR_NOTE_MODIFY_FLAG:
u8 param;
if (new_val != FALSE) {
param = TRUE;
} else {
param = FALSE;
}
SetNotifyNote(param);
break;
}
break;
default:
return;
}
return;
}
void SaveScriptVariableValueAtIndex(union script_var_value sv_locals[], s16 script_var_id, u16 idx, s32 new_val)
{
struct script_var_raw script_var_raw;
LoadScriptVariableRaw(&script_var_raw, sv_locals, script_var_id);
switch ((s16)script_var_raw.def->type) {
case VARTYPE_BIT:
// For VARTYPE_BIT, idx specifies a number of bits
u16 offset = idx + script_var_raw.def->bitshift;
u8 *val = &((u8*)script_var_raw.value)[offset / 8];
u8 bitmask = (1 << (offset & (8 - 1)));
if (new_val != FALSE) {
// new value is true, so we set the bits specified in the bitmask
*val = *val | bitmask;
return;
}
// new value is false, so we unset the bits specified in bitmask
*val = bitmask ^ (*val | bitmask);
return;
case VARTYPE_STRING:
case VARTYPE_UINT8:
((u8*)script_var_raw.value)[idx] = new_val;
return;
case VARTYPE_INT8:
((s8*)script_var_raw.value)[idx] = new_val;
return;
case VARTYPE_UINT16:
((u16*)script_var_raw.value)[idx] = (u16)new_val;
return;
case VARTYPE_INT16:
((s16*)script_var_raw.value)[idx] = (s16)new_val;
return;
case VARTYPE_UINT32:
case VARTYPE_INT32:
((s32*)script_var_raw.value)[idx] = (s32)new_val;
return;
case VARTYPE_SPECIAL:
switch (script_var_id) {
case VAR_CARRY_GOLD:
SetMoneyCarried(new_val);
AddMoneyCarried(0);
return;
case VAR_BANK_GOLD:
SetMoneyStored(new_val);
return;
case VAR_EXECUTE_SPECIAL_EPISODE_TYPE:
if (GetGameMode() == GAME_MODE_1) {
SetDebugSpecialEpisodeNumber(new_val);
return;
}
return;
case VAR_NOTE_MODIFY_FLAG:
SetNotifyNote((u8)(new_val != FALSE));
break;
}
break;
default:
return;
}
return;
}
s32 LoadScriptVariableValueSum(union script_var_value sv_local[], const s16 sv_id)
{
struct script_var_raw script_var_raw;
s32 total = 0;
LoadScriptVariableRaw(&script_var_raw, 0, sv_id);
for(s32 idx = 0; idx < (s16) script_var_raw.def->n_values; idx++) {
total += LoadScriptVariableValueAtIndex(sv_local, sv_id, (u16) idx);
}
return total;
}
void LoadScriptVariableValueBytes(const s16 sv_id, u8* result, s32 num_bytes)
{
struct script_var_raw sv_raw;
LoadScriptVariableRaw(&sv_raw, 0, sv_id);
s32 i = 0;
u8* val_ptr = (u8*) sv_raw.value;
for(i = 0; i < num_bytes; i++) {
u8 val = *val_ptr;
*result = val;
val_ptr += 1;
result += 1;
}
}
void LoadScriptVariableValueString(const s16 sv_id, u8* result, u8 num_bytes)
{
LoadScriptVariableValueBytes(sv_id, result, num_bytes);
result[num_bytes] = 0;
}
void SaveScriptVariableValueBytes(const s16 sv_id, u8* result, s32 num_bytes)
{
struct script_var_raw sv_raw;
LoadScriptVariableRaw(&sv_raw, 0, sv_id);
s32 i = 0;
u8* val_ptr = (u8*) sv_raw.value;
for(i = 0; i < num_bytes; i++) {
u8 val = *result;
*val_ptr = val;
val_ptr += 1;
result += 1;
}
}
bool8 ScriptVariablesEqual(union script_var_value sv_val_ptr_local[], s16 sv_id_1, s16 sv_id_2)
{
struct script_var_raw script_var_raw_1, script_var_raw_2;
LoadScriptVariableRaw(&script_var_raw_1, sv_val_ptr_local, sv_id_1);
LoadScriptVariableRaw(&script_var_raw_2, sv_val_ptr_local, sv_id_2);
s32 n_values = script_var_raw_1.def->n_values;
for(int idx = 0; idx < n_values; idx++) {
if (LoadScriptVariableValueAtIndex(sv_val_ptr_local, sv_id_1, idx) !=
LoadScriptVariableValueAtIndex(sv_val_ptr_local, sv_id_2, idx)) {
return FALSE;
}
}
return TRUE;
}
s32 CalcScriptVariables(s32 param_1, s32 param_2, enum script_calc_operation operation)
{
switch (operation) {
case CALC_SET:
return param_2;
case CALC_SUB:
return param_1 - param_2;
case CALC_ADD:
return param_1 + param_2;
case CALC_MUL:
return param_1 * param_2;
case CALC_DIV:
return param_1 / param_2;
case CALC_MOD:
return param_1 % param_2;
case CALC_AND:
return param_1 & param_2;
case CALC_OR:
return param_1 | param_2;
case CALC_XOR:
return param_1 ^ param_2;
case CALC_SETBIT:
return (1 << param_2) | param_1;
case CALC_CLEARBIT:
return param_1 & ~(1 << param_2);
case CALC_RANDOM:
return RandInt(param_2);
default:
struct prog_pos_info ppi = EVENT_FLAG_PROG_POS_INFO_CALC_SCRIPT_VARIABLES;
Debug_FatalError(&ppi, &EVENT_FLAG_EXPANSION_ERROR, operation);
}
}
bool8 CompareScriptVariables(s32 param_1, s32 param_2, enum compare_operation operation)
{
switch (operation) {
case CMP_TRUE:
return TRUE;
case CMP_FALSE:
return FALSE;
case CMP_EQ:
return param_1 == param_2;
case CMP_NE:
return param_1 != param_2;
case CMP_GT:
return param_1 > param_2;
case CMP_GE:
return param_1 >= param_2;
case CMP_LT:
return param_1 < param_2;
case CMP_LE:
return param_1 <= param_2;
case CMP_AND_NONZERO:
return (param_1 & param_2) != 0;
case CMP_XOR_NONZERO:
return (param_1 ^ param_2) != 0;
case CMP_BIT_SET:
if(param_1 & (1 << param_2)) {
return 1;
} else {
return 0;
}
default:
struct prog_pos_info ppi = EVENT_FLAG_PROG_POS_INFO_COMPARE_SCRIPT_VARIABLES;
Debug_FatalError(&ppi, &EVENT_FLAG_COMPARE_SCRIPT_VARIABLES_ERROR, operation);
}
}
s32 CalcScriptVariablesVeneer(s32 param_1, s32 param_2, enum script_calc_operation operation)
{
return CalcScriptVariables(param_1, param_2, operation);
}
void CalcAndUpdateScriptVarWithOtherValue(union script_var_value sv_local[], const s16 script_var_id, s32 param, enum script_calc_operation operation)
{
s32 value = LoadScriptVariableValue(sv_local, script_var_id);
s32 result = CalcScriptVariables(value, param, operation);
SaveScriptVariableValue(sv_local, script_var_id, result);
}
void CalcAndUpdateScriptVarWithOtherScriptVar(union script_var_value sv_local[], s16 sv_id_1, s16 sv_id_2, enum script_calc_operation op)
{
s32 value_1 = LoadScriptVariableValue(sv_local, sv_id_1);
s32 value_2 = LoadScriptVariableValue(sv_local, sv_id_2);
s32 result = CalcScriptVariables(value_1, value_2, op);
SaveScriptVariableValue(sv_local, sv_id_1, result);
}
bool8 CompareScriptVariablesVeneer(s32 param_1, s32 param_2, enum compare_operation op)
{
return CompareScriptVariables(param_1, param_2, op);
}
bool8 LoadAndCompareScriptVarAndValue(union script_var_value sv_local[], s16 sv_id, s32 param, enum compare_operation op)
{
s32 value = LoadScriptVariableValue(sv_local, sv_id);
return CompareScriptVariables(value, param, op);
}
bool8 LoadAndCompareScriptVars(union script_var_value sv_local[], s16 sv_id_1, s16 sv_id_2, enum compare_operation op)
{
s32 value_1 = LoadScriptVariableValue(sv_local, sv_id_1);
s32 value_2 = LoadScriptVariableValue(sv_local, sv_id_2);
return CompareScriptVariables(value_1, value_2, op);
}
// This inline allows EventFlagResume to match
static inline s32 LoadScriptVariableValueAtIndexInline(s16 sv_id, u32 idx)
{
return LoadScriptVariableValueAtIndex(0, sv_id, idx);
}
void EventFlagResume()
{
u32 game_mode = GetGameMode();
if (game_mode <= 1U) {
return;
}
u32 idx = game_mode - 2;
Debug_Print0(&EVENT_FLAG_GAME_MODE_DEBUG_MSG, idx);
SaveScriptVariableValue(0, VAR_GROUND_ENTER, LoadScriptVariableValueAtIndexInline(VAR_GROUND_ENTER_BACKUP, idx));
SaveScriptVariableValue(0, VAR_GROUND_ENTER_LINK, LoadScriptVariableValueAtIndexInline(VAR_GROUND_ENTER_LINK_BACKUP, idx));
SaveScriptVariableValue(0, VAR_GROUND_GETOUT, LoadScriptVariableValueAtIndexInline(VAR_GROUND_GETOUT_BACKUP, idx));
SaveScriptVariableValue(0, VAR_GROUND_MAP, LoadScriptVariableValueAtIndexInline(VAR_GROUND_MAP_BACKUP, idx));
SaveScriptVariableValue(0, VAR_GROUND_PLACE, LoadScriptVariableValueAtIndexInline(VAR_GROUND_PLACE_BACKUP, idx));
SaveScriptVariableValue(0, VAR_DUNGEON_ENTER, LoadScriptVariableValueAtIndexInline(VAR_DUNGEON_ENTER_BACKUP, idx));
SaveScriptVariableValue(0, VAR_DUNGEON_ENTER_MODE, LoadScriptVariableValueAtIndexInline(VAR_DUNGEON_ENTER_MODE_BACKUP, idx));
SaveScriptVariableValue(0, VAR_DUNGEON_ENTER_INDEX, LoadScriptVariableValueAtIndexInline(VAR_DUNGEON_ENTER_INDEX_BACKUP, idx));
SaveScriptVariableValue(0, VAR_DUNGEON_ENTER_FREQUENCY, LoadScriptVariableValueAtIndexInline(VAR_DUNGEON_ENTER_FREQUENCY_BACKUP, idx));
SaveScriptVariableValue(0, VAR_DUNGEON_RESULT, LoadScriptVariableValueAtIndexInline(VAR_DUNGEON_RESULT_BACKUP, idx));
SaveScriptVariableValue(0, VAR_GROUND_START_MODE, LoadScriptVariableValueAtIndexInline(VAR_GROUND_START_MODE_BACKUP, idx));
SaveScriptVariableValue(0, VAR_PLAYER_KIND, LoadScriptVariableValueAtIndexInline(VAR_PLAYER_KIND_BACKUP, idx));
SaveScriptVariableValue(0, VAR_ATTENDANT1_KIND, LoadScriptVariableValueAtIndexInline(VAR_ATTENDANT1_KIND_BACKUP, idx));
SaveScriptVariableValue(0, VAR_ATTENDANT2_KIND, LoadScriptVariableValueAtIndexInline(VAR_ATTENDANT2_KIND_BACKUP, idx));
ScenarioFlagRestore();
}
// This inline allows EventFlagBackup to match
static inline s32 SaveScriptVariableValueAtIndexInline(s16 sv_id, u32 idx, u32 new_val)
{
SaveScriptVariableValueAtIndex(0, sv_id, idx, new_val);
}
void EventFlagBackup()
{
u32 game_mode;
u32 idx;
game_mode = GetGameMode();
if (game_mode <= 1U) {
return;
}
idx = game_mode - 2;
Debug_Print0(&EVENT_FLAG_BACKUP_DEBUG_MSG, idx);
SaveScriptVariableValueAtIndexInline(VAR_GROUND_ENTER_BACKUP, idx, LoadScriptVariableValue(0, VAR_GROUND_ENTER));
SaveScriptVariableValueAtIndexInline(VAR_GROUND_ENTER_LINK_BACKUP, idx, LoadScriptVariableValue(0, VAR_GROUND_ENTER_LINK));
SaveScriptVariableValueAtIndexInline(VAR_GROUND_GETOUT_BACKUP, idx, LoadScriptVariableValue(0, VAR_GROUND_GETOUT));
SaveScriptVariableValueAtIndexInline(VAR_GROUND_MAP_BACKUP, idx, LoadScriptVariableValue(0, VAR_GROUND_MAP));
SaveScriptVariableValueAtIndexInline(VAR_GROUND_PLACE_BACKUP, idx, LoadScriptVariableValue(0, VAR_GROUND_PLACE));
SaveScriptVariableValueAtIndexInline(VAR_DUNGEON_ENTER_BACKUP, idx, LoadScriptVariableValue(0, VAR_DUNGEON_ENTER));
SaveScriptVariableValueAtIndexInline(VAR_DUNGEON_ENTER_MODE_BACKUP, idx, LoadScriptVariableValue(0, VAR_DUNGEON_ENTER_MODE));
SaveScriptVariableValueAtIndexInline(VAR_DUNGEON_ENTER_INDEX_BACKUP, idx, LoadScriptVariableValue(0, VAR_DUNGEON_ENTER_INDEX));
SaveScriptVariableValueAtIndexInline(VAR_DUNGEON_ENTER_FREQUENCY_BACKUP, idx, LoadScriptVariableValue(0, VAR_DUNGEON_ENTER_FREQUENCY));
SaveScriptVariableValueAtIndexInline(VAR_DUNGEON_RESULT_BACKUP, idx, LoadScriptVariableValue(0, VAR_DUNGEON_RESULT));
SaveScriptVariableValueAtIndexInline(VAR_GROUND_START_MODE_BACKUP, idx, LoadScriptVariableValue(0, VAR_GROUND_START_MODE));
SaveScriptVariableValueAtIndexInline(VAR_PLAYER_KIND_BACKUP, idx, LoadScriptVariableValue(0, VAR_PLAYER_KIND));
SaveScriptVariableValueAtIndexInline(VAR_ATTENDANT1_KIND_BACKUP, idx, LoadScriptVariableValue(0, VAR_ATTENDANT1_KIND));
SaveScriptVariableValueAtIndexInline(VAR_ATTENDANT2_KIND_BACKUP, idx, LoadScriptVariableValue(0, VAR_ATTENDANT2_KIND));
ScenarioFlagBackup();
}
// This dumps the global script variables (up to 0x400 bytes),
// but doesn't dump the local script variables (0x400 onwards).
bool8 DumpScriptVariableValues(u8* dest)
{
EventFlagBackup();
MemcpySimple(dest, &SCRIPT_VARS_VALUES[0], LOCAL_SCRIPT_VAR_OFFSET);
return TRUE;
}
// This restores the global script variables (up to 0x400 bytes),
// but doesn't restore the local script variables (0x400 onwards).
bool8 RestoreScriptVariableValues(u8* src)
{
struct script_var_raw sv_raw;
u8 ret_val;
LoadScriptVariableRaw(&sv_raw, 0, VAR_VERSION);
MemcpySimple(&SCRIPT_VARS_VALUES[0], src, 0x400);
// If these values are not equal, then the save file
// will be treated as corrupted, which thus gets deleted.
if (sv_raw.def->default_val == sv_raw.value->u32) {
ret_val = TRUE;
} else {
ret_val = FALSE;
}
return ret_val;
}
void InitScenarioProgressScriptVars()
{
SetScenarioProgressScriptVar(VAR_SCENARIO_SELECT, 0, 0);
SetScenarioProgressScriptVar(VAR_SCENARIO_MAIN, 0, 0);
SetScenarioProgressScriptVar(VAR_SCENARIO_SIDE, 0, 0);
SetScenarioProgressScriptVar(VAR_SCENARIO_SUB1, 0, 0);
SetScenarioProgressScriptVar(VAR_SCENARIO_SUB2, 0, 0);
SetScenarioProgressScriptVar(VAR_SCENARIO_SUB3, 0, 0);
SetScenarioProgressScriptVar(VAR_SCENARIO_SUB4, 0, 0);
SetScenarioProgressScriptVar(VAR_SCENARIO_SUB5, 0, 0);
SetScenarioProgressScriptVar(VAR_SCENARIO_SUB6, 0, 0);
SetScenarioProgressScriptVar(VAR_SCENARIO_SUB7, 0, 0);
SetScenarioProgressScriptVar(VAR_SCENARIO_SUB8, 0, 0);
ZeroInitScriptVariable(0, VAR_SCENARIO_MAIN_BIT_FLAG);
ZeroInitScriptVariable(0, VAR_SCENARIO_MAIN_BIT_FLAG_BACKUP);
s32 idx = 0;
do {
SaveScriptVariableValueAtIndex(0, VAR_SCENARIO_SELECT_BACKUP, idx, 0);
SaveScriptVariableValueAtIndex(0, VAR_SCENARIO_SELECT_BACKUP, (u16) (idx + 4), 0);
idx += 1;
} while (idx < 4);
SaveScriptVariableValue(0, VAR_SCENARIO_BALANCE_FLAG, 0);
SaveScriptVariableValue(0, VAR_SCENARIO_BALANCE_DEBUG, -1);
SaveScriptVariableValue(0, VAR_PLAY_OLD_GAME, 0);
}
void LoadScriptVarValuePair(s16 script_var_id, s32* val_1, s32* val_2)
{
*val_1 = LoadScriptVariableValueAtIndex(0, script_var_id, 0);
*val_2 = LoadScriptVariableValueAtIndex(0, script_var_id, 1);
}