diff --git a/asm/include/main_0204B4EC.inc b/asm/include/main_0204B678.inc similarity index 95% rename from asm/include/main_0204B4EC.inc rename to asm/include/main_0204B678.inc index 2e96e6b5..e651156f 100644 --- a/asm/include/main_0204B4EC.inc +++ b/asm/include/main_0204B678.inc @@ -18,6 +18,7 @@ .public GetNotifyNote .public GetPartyMembers .public LoadScriptVariableRaw +.public LoadScriptVariableValue .public MemcpySimple .public RandInt .public ScenarioFlagBackup diff --git a/asm/main_0204B4EC.s b/asm/main_0204B678.s similarity index 93% rename from asm/main_0204B4EC.s rename to asm/main_0204B678.s index 17bcbf83..ff8967b1 100644 --- a/asm/main_0204B4EC.s +++ b/asm/main_0204B678.s @@ -1,136 +1,8 @@ .include "asm/macros.inc" - .include "main_0204B4EC.inc" + .include "main_0204B678.inc" .text - arm_func_start LoadScriptVariableValue -LoadScriptVariableValue: ; 0x0204B4EC - stmdb sp!, {r4, lr} - sub sp, sp, #8 - mov r2, r0 - mov r4, r1 - mov r1, r2 - add r0, sp, #0 - mov r2, r4 - bl LoadScriptVariableRaw - ldr r1, [sp] - ldrsh r0, [r1] - cmp r0, #9 - addls pc, pc, r0, lsl #2 - b _0204B66C -_0204B520: ; jump table - b _0204B66C ; case 0 - b _0204B548 ; case 1 - b _0204B56C ; case 2 - b _0204B56C ; case 3 - b _0204B578 ; case 4 - b _0204B584 ; case 5 - b _0204B590 ; case 6 - b _0204B59C ; case 7 - b _0204B59C ; case 8 - b _0204B5A8 ; case 9 -_0204B548: - ldrsh r1, [r1, #6] - ldr r2, [sp, #4] - mov r0, #1 - mov r1, r0, lsl r1 - ldrb r2, [r2] - and r1, r1, #0xff - tst r2, r1 - moveq r0, #0 - b _0204B670 -_0204B56C: - ldr r0, [sp, #4] - ldrb r0, [r0] - b _0204B670 -_0204B578: - ldr r0, [sp, #4] - ldrsb r0, [r0] - b _0204B670 -_0204B584: - ldr r0, [sp, #4] - ldrh r0, [r0] - b _0204B670 -_0204B590: - ldr r0, [sp, #4] - ldrsh r0, [r0] - b _0204B670 -_0204B59C: - ldr r0, [sp, #4] - ldr r0, [r0] - b _0204B670 -_0204B5A8: - cmp r4, #0x48 - bgt _0204B5E4 - bge _0204B62C - cmp r4, #0x3d - bgt _0204B5D8 - subs r0, r4, #0x3a - addpl pc, pc, r0, lsl #2 - b _0204B66C -_0204B5C8: ; jump table - b _0204B600 ; case 0 - b _0204B608 ; case 1 - b _0204B614 ; case 2 - b _0204B61C ; case 3 -_0204B5D8: - cmp r4, #0x47 - beq _0204B624 - b _0204B66C -_0204B5E4: - cmp r4, #0x49 - bgt _0204B5F4 - beq _0204B634 - b _0204B66C -_0204B5F4: - cmp r4, #0x70 - beq _0204B664 - b _0204B66C -_0204B600: - mov r0, #1 - b _0204B670 -_0204B608: - mov r0, #0 - bl GetPartyMembers - b _0204B670 -_0204B614: - bl GetMoneyCarried - b _0204B670 -_0204B61C: - bl GetMoneyStored - b _0204B670 -_0204B624: - bl GetLanguageType - b _0204B670 -_0204B62C: - bl GetGameMode - b _0204B670 -_0204B634: - bl GetGameMode - cmp r0, #1 - beq _0204B64C - cmp r0, #3 - beq _0204B654 - b _0204B65C -_0204B64C: - bl sub_0204C918 - b _0204B670 -_0204B654: - bl GetSpecialEpisodeType - b _0204B670 -_0204B65C: - mvn r0, #0 - b _0204B670 -_0204B664: - bl GetNotifyNote - b _0204B670 -_0204B66C: - mov r0, #0 -_0204B670: - add sp, sp, #8 - ldmia sp!, {r4, pc} - arm_func_end LoadScriptVariableValue - arm_func_start LoadScriptVariableValueAtIndex LoadScriptVariableValueAtIndex: ; 0x0204B678 stmdb sp!, {r3, r4, r5, lr} diff --git a/include/enums.h b/include/enums.h index 753e206b..a4f7fa4b 100644 --- a/include/enums.h +++ b/include/enums.h @@ -2961,8 +2961,56 @@ enum dungeon_restriction_flags { // Remaining flags are unused }; -enum script_variables { - PLAYED_OLD_GAME = 0x6f +enum script_var_type { + VARTYPE_NONE = 0, + VARTYPE_BIT = 1, + // VARTYPE_STRING is an array of characters, and implementation-wise are treated exactly the + // same way as VARTYPE_UINT8 + VARTYPE_STRING = 2, + VARTYPE_UINT8 = 3, + VARTYPE_INT8 = 4, + VARTYPE_UINT16 = 5, + VARTYPE_INT16 = 6, + VARTYPE_UINT32 = 7, + VARTYPE_INT32 = 8, + VARTYPE_SPECIAL = 9, + // This dummy value ensures compilation that matches the original assembly. + // Without it, the compiler reads the enum using ldrb instead of ldrsh + VARTYPE_DUMMY_PADDING = 256 +}; + +enum script_var_id { + VAR_FRIEND_SUM = 58, + VAR_UNIT_SUM = 59, + // The amount of money the player has on hand. + VAR_CARRY_GOLD = 60, + // The amount of money stored in Duskull Bank. + VAR_BANK_GOLD = 61, + // The language determined by the NDS firmware. Notably checked in some scripts to display + // different backgrounds or objects, such as in the intro. + // 0: Japanese + // 1: English + // 2: French + // 3: German + // 4: Italian + // 5: Spanish + PLAYED_OLD_GAME = 0x6f, + VAR_LANGUAGE_TYPE = 71, + // A value to distinguish the type of game being played. This mainly differentiates between maingame and Special Episodes, and the game + // checks for this value in numerous places (not necessarily in scripts) to differentiate + // maingame versus Special Episode behavior. + VAR_GAME_MODE = 72, + // Used to distinguish which Special Episode is currently being played. + VAR_EXECUTE_SPECIAL_EPISODE_TYPE = 73, + VAR_NOTE_MODIFY_FLAG = 112, +}; + +enum special_episode_type { + EPISODE_BIDOOFS_WISH = 0, + EPISODE_IGGLYBUFF_THE_PRODIGY = 1, + EPISODE_TODAYS_OH_MY_GOSH = 2, + EPISODE_HERE_COMES_TEAM_CHARM = 3, + EPISODE_IN_THE_FUTURE_OF_DARKNESS = 4, }; #endif //PMDSKY_ENUMS_H diff --git a/include/scripting.h b/include/scripting.h index 2f15f889..4ac29205 100644 --- a/include/scripting.h +++ b/include/scripting.h @@ -4,37 +4,37 @@ #include "enums.h" #include "util.h" -struct script_var_definition { - s16 p1; - s16 p2; - s16 value_offset; // offset within SCRIPT_VAR_VALUES, or local script var values. - s16 p4; - s16 p5; - s16 p6; - s16 p7; - s16 p8; +struct script_var_def { + enum script_var_type type; // 0x0: type of data contained in this script variable + u16 field_0x1; // 0x2 + // 0x4: value's offset into struct script_var_value_table, if type != VARTYPE_SPECIAL + s16 mem_offset; + s16 bitshift; // 0x6: bit position if type == VARTYPE_BIT + u16 n_values; // 0x8: number of values (>1 means this variable is an array) + // 0xA: 0 for every variable except VAR_VERSION, which has a default value of 1. + s16 default_val; + char* name; // 0xC: variable name }; -struct script_var_local_value { - u32 p1; -}; - -struct script_var_global_value { - u8 p1; +union script_var_value { + u8 u8; + u16 u16; + u32 u32; + s8 s8; + s16 s16; }; struct script_var_raw { - struct script_var_definition* def; - union { - struct script_var_local_value* local; - struct script_var_global_value* global; - } value; + struct script_var_def* def; + union script_var_value *value; }; const short LOCAL_SCRIPT_VAR_OFFSET = 0x400; void LoadScriptVariableRaw(struct script_var_raw* sv_raw, - struct script_var_local_value sv_locals[], - const enum script_variables sv_id); + union script_var_value sv_val_local[], + const enum script_var_id sv_id); + +s32 LoadScriptVariableValue(union script_var_value sv_local[], enum script_var_id sv_id); #endif //PMDSKY_SCRIPTING_H diff --git a/main.lsf b/main.lsf index 47a03956..6a4013dd 100644 --- a/main.lsf +++ b/main.lsf @@ -80,7 +80,7 @@ Static main Object src/main_0204AFF8.o Object asm/main_0204B018.o Object src/scripting.o - Object asm/main_0204B4EC.o + Object asm/main_0204B678.o Object src/dungeon_recruitment_3.o Object asm/main_0204CA94.o Object src/main_0204DA2C.o diff --git a/src/scripting.c b/src/scripting.c index e536b0e8..23de9fe6 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -1,22 +1,91 @@ #include "enums.h" #include "scripting.h" +// 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 struct script_var_definition SCRIPT_VARS[]; -extern struct script_var_definition SCRIPT_VARS_LOCALS[]; -extern struct script_var_global_value SCRIPT_VARS_VALUES[]; +extern s32 GetPartyMembers(s32 param1); +extern s32 GetMoneyCarried(); +extern s32 GetMoneyStored(); +extern s32 GetLanguageType(); +extern s32 GetGameMode(); +extern s32 sub_0204C918(); +extern s32 GetSpecialEpisodeType(); +extern s32 GetNotifyNote(); void LoadScriptVariableRaw(struct script_var_raw* sv_raw, - struct script_var_local_value sv_locals[], - const enum script_variables sv_id) -{ + union script_var_value sv_val_local[], + const enum script_var_id sv_id) { + if (sv_id < LOCAL_SCRIPT_VAR_OFFSET) { - // script var is global + // global script var sv_raw->def = &SCRIPT_VARS[sv_id]; - sv_raw->value.global = &SCRIPT_VARS_VALUES[sv_raw->def->value_offset]; + sv_raw->value = (union script_var_value*) + &SCRIPT_VARS_VALUES[sv_raw->def->mem_offset]; } else { - // script var is local + // local script var sv_raw->def = &SCRIPT_VARS_LOCALS[sv_id - LOCAL_SCRIPT_VAR_OFFSET]; - sv_raw->value.local = &sv_locals[sv_raw->def->value_offset]; + sv_raw->value = &sv_val_local[sv_raw->def->mem_offset]; } } + +s32 LoadScriptVariableValue(union script_var_value sv_local[], enum script_var_id 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 EPISODE_IGGLYBUFF_THE_PRODIGY: + return sub_0204C918(); + case EPISODE_HERE_COMES_TEAM_CHARM: + return GetSpecialEpisodeType(); + default: + return -1; + } + case VAR_NOTE_MODIFY_FLAG: + return GetNotifyNote(); + } + } + + return 0; +}