diff --git a/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/common/patch.asm b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/common/patch.asm new file mode 100644 index 000000000..eb4a40ccb --- /dev/null +++ b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/common/patch.asm @@ -0,0 +1,407 @@ +; For use with ARMIPS +; 2021/03/23 +; For Explorers of Sky All Versions +; ------------------------------------------------------------------------------ +; Adds a menu to choose the starter after the quiz +; ------------------------------------------------------------------------------ + + + .org BegSwitch + .area 0x4 + cmp r1,#0x48 + .endarea + .org BegSwitch+0xC + .area 0x4 + b move_beg_switch + .endarea + + .org EndSwitch + .area 11*0x4 + b SwitchCase42 + b SwitchCase43 + b SwitchCase44 + b SwitchCase45 + b SwitchCase46 + b SwitchCase47 + b SwitchCase48 + .fill 11*0x4+EndSwitch-., 0xCC + .endarea + + .org HookEventSeq + .area 0xC + mov r0,#0x42 ; 0x26 Originally + .endarea + + .org OldGetPersonalityResult + .area 0x48 + stmdb r13!,{r14} + ldr r0,[player_id] + mvn r1,#0 + cmp r0,r1 + bne end_ogpr + bl GetPersonalityResult + str r0,[player_id] + end_ogpr: + ldmia r13!,{r15} + player_id: + .word 0xFFFFFFFF + .pool + .fill 0x48+OldGetPersonalityResult-., 0xCC + .endarea + + .org OverlayStart+OrgSize + .area ExtendSize + + GetPersonalityResult: + stmdb r13!,{r3,r14} + ldr r0,=GlobalStructPointer + mov r12,#0x0 + ldr r14,[r0, #+0x0] + mov r0,r12 + mov r3,r12 + loop_players: + add r1,r14,r3 + ldrb r2,[r1, #+0x34] + ldrb r1,[r1, #+0x44] + add r1,r2,r1 + cmp r12,r1 + movlt r0,r3 + add r3,r3,#0x1 + movlt r12,r1 + cmp r3,#0x10 + blt loop_players + ldmia r13!,{r3,r15} + move_beg_switch: + mov r0,#0x64 + bl RandMax + cmp r0,#0x4B + blt case0_alt1 + add r0,r13,#0x14 + bl UnknownFuncCase0 + ldrb r1,[r13, #+0x19] + ldr r0,[r15, #+0xe20] + ldr r0,[r0, #+0x0] + and r1,r1,#0xF + b case0_alt2 + SwitchCase42: + add r0,r13,#0x128 + bl PrepDBUnk1 + bl OldGetPersonalityResult + bl GetPlayerPkmnID + str r0,[r13, #+0x128] + ldr r0,=GlobalStructPointer + ldr r1,[r0] + ldrsb r0,[r1, #+0x2] + bl ShowDB + ldr r0,=GlobalStructPointer + mov r1,#0x4 + ldr r0,[r0, #+0x0] + add r3,r13,#0x128 + ldrsb r0,[r0, #+0x2] + add r2,r1,#0x6C0 + bl ShowMessageInDB + ldr r1,=GlobalStructPointer + ldr r1,[r1, #+0x0] + ldr r0,[r1, #+0x20] + add r0,r0,#0x1 + str r0,[r1, #+0x20] + b EndCodeSwitch + SwitchCase43: + ldrsb r0,[r0, #+0x2] + bl IsDBActive + cmp r0,#0x0 + bne EndCodeSwitch + ldr r0,=DBLayout5 + mov r4,#0x2 + ldr r1,=0x00300013 + ldr r3,=QuizMenu1 + mov r2,#0x0 + str r4,[r13, #+0x0] + bl CreateNormalMenu + ldr r1,=GlobalStructPointer + ldr r2,[r1, #+0x0] + strb r0,[r2, #+0x3] + ldr r1,[r1, #+0x0] + ldr r0,[r1, #+0x20] + add r0,r0,#0x1 + str r0,[r1, #+0x20] + b EndCodeSwitch + SwitchCase44: + ldrsb r0,[r0, #+0x3] ;r0+0x3=*(000f1e03) + bl GetNormalMenuResult + cmp r0,#0x1 + beq case44_yes + cmp r0,#0x2 + beq case44_no + b EndCodeSwitch + case44_yes: + ldr r0,=GlobalStructPointer + ldr r0,[r0, #+0x0] + ldrsb r0,[r0, #+0x3] + bl FreeNormalMenu + mvn r2,#0x1 + ldr r0,=GlobalStructPointer + ldr r1,[r0, #+0x0] + strb r2,[r1, #+0x3] + ldr r1,=GlobalStructPointer + ldr r1,[r1, #+0x0] + mov r0,#0x26 + str r0,[r1, #+0x20] + b EndCodeSwitch + case44_no: + ldr r0,=GlobalStructPointer + ldr r0,[r0, #+0x0] + ldrsb r0,[r0, #+0x3] + bl FreeNormalMenu + mvn r2,#0x1 + ldr r0,=GlobalStructPointer + ldr r1,[r0, #+0x0] + strb r2,[r1, #+0x3] + ldr r1,=GlobalStructPointer + ldr r1,[r1, #+0x0] + mov r0,#0x45 + str r0,[r1, #+0x20] + b EndCodeSwitch + SwitchCase45: + ldrsb r0,[r0, #+0x2] + bl ShowDB + ldr r1,=GlobalStructPointer + ldr r1,[r1, #+0x0] + ldrsb r0,[r1, #+0x5] + bl HidePortraitBox + ldr r1,=GlobalStructPointer + ldr r3,[r1, #+0x0] + ldrsb r0,[r3, #+0x2] + ldr r2,=SpecialStringID + mov r1,#0x8 + mov r3,#0x0 + bl ShowMessageInDB + ldr r1,=GlobalStructPointer + ldr r1,[r1, #+0x0] + mov r0,#0x46 + str r0,[r1, #+0x20] + b EndCodeSwitch + SwitchCase46: + ldrsb r0,[r0, #+0x2] + bl IsDBActive + cmp r0,#0x0 + bne EndCodeSwitch + ldr r1,=GlobalStructPointer + ldr r0,=DBLayout6 + ldr r2,[r1, #+0x0] + ldr r1,=0x00001011 + mov r2,#0x10 + ldr r3,=PlayerMenuDisp + str r2,[r13, #+0x0] + mov r4,#0x6 + mov r2,#0x0 + str r4,[r13, #+0x4] + bl CreateAdvancedMenu + ldr r2,=GlobalStructPointer + ldr r1,[r2, #+0x0] + strb r0,[r1, #+0x3] + ldr r3,[r1, #+0x20] + add r3,r3,#0x1 + str r3,[r1, #+0x20] + + ;For Portraits + mov r0,#0x0 + sub r1,r0,#0x2 + str r0,[r2, #+0x4] + str r0,[r2, #+0x8] + ldr r2,[r2] + ldrsb r2,[r2, #+0x5] + cmp r2,r1 + bne no_pt_box + mov r1,#0x3 + mov r2,#0x1 + bl CreatePortraitBox + ldr r1,=GlobalStructPointer + ldr r1,[r1] + strb r0,[r1, #+0x5] + no_pt_box: + ldr r1,=GlobalStructPointer + ldr r1,[r1] + add r4,r1,#0x3B4 + mov r0,#0 + bl GetPlayerPkmnID + mov r1,r0 + mov r0,r4 + bl SetPortraitPkmnID + mov r0,r4 + mov r1,#0 + bl SetPortraitExpressionID + mov r0,r4 + mov r1,#4 + bl SetPortraitUnknownAttr + mov r0,r4 + ldr r1,=PortraitAttrStruct + bl SetPortraitAttrStruct + ldr r1,=GlobalStructPointer + ldr r1,[r1] + ldrsb r0,[r1, #+0x5] + mov r1,r4 + bl ShowPortraitBox + b EndCodeSwitch + SwitchCase47: + ldrsb r0,[r0, #+0x3] + ldr r4,[r2, #+0x4] + bl GetAdvancedMenuCurrentOption + cmp r4,r0 + beq case47_same_pkmn + ldr r0,=GlobalStructPointer + mov r1,#0x0 + str r1,[r0, #+0x8] + ldr r0,[r0, #+0x0] + ldrsb r0,[r0, #+0x3] + bl GetAdvancedMenuCurrentOption + ldr r1,=GlobalStructPointer + str r0,[r1, #+0x4] + ldr r1,[r1] + add r4,r1,#0x3B4 + bl GetPlayerPkmnID + mov r1,r0 + mov r0,r4 + bl SetPortraitPkmnID + mov r1,0x0 + mov r0,r4 + bl SetPortraitExpressionID + mov r1,0x4 + mov r0,r4 + bl SetPortraitUnknownAttr + ldr r1,=PortraitAttrStruct + mov r0,r4 + bl SetPortraitAttrStruct + ldr r1,=GlobalStructPointer + ldr r1,[r1] + ldrsb r0,[r1, #+0x5] + mov r1,r4 + bl ShowPortraitBox + b case47_after_portraits + case47_same_pkmn: + ldr r0,=GlobalStructPointer + ldr r1,[r0, #+0x8] + cmp r1,#0x20 + addne r1,r1,#0x1 + strne r1,[r0, #+0x8] + bne case47_after_portraits + ldr r1,[r0] + mov r0,r4 + add r4,r1,#0x3B4 + bl GetPlayerPkmnID + mov r1,r0 + mov r0,r4 + bl SetPortraitPkmnID + mov r1,0x1 + mov r0,r4 + bl SetPortraitExpressionID + mov r1,0x4 + mov r0,r4 + bl SetPortraitUnknownAttr + ldr r1,=PortraitAttrStruct + mov r0,r4 + bl SetPortraitAttrStruct + ldr r1,=GlobalStructPointer + ldr r1,[r1] + ldrsb r0,[r1, #+0x5] + mov r1,r4 + bl ShowPortraitBox + case47_after_portraits: + ldr r0,=GlobalStructPointer + ldr r0,[r0, #+0x0] + ldrsb r0,[r0, #+0x3] + bl IsAdvancedMenuActive + cmp r0,#0x0 + bne EndCodeSwitch + ldr r0,=GlobalStructPointer + ldr r4,[r0, #+0x0] + ldrsb r0,[r4, #+0x3] + bl GetAdvancedMenuResult + ldr r1,=player_id + str r0,[r1] + + ldr r1,=GlobalStructPointer + ldr r1,[r1] + add r4,r1,#0x3B4 + bl GetPlayerPkmnID + mov r1,r0 + mov r0,r4 + bl SetPortraitPkmnID + mov r1,0x1 + mov r0,r4 + bl SetPortraitExpressionID + mov r1,0x4 + mov r0,r4 + bl SetPortraitUnknownAttr + ldr r1,=PortraitAttrStruct + mov r0,r4 + bl SetPortraitAttrStruct + ldr r1,=GlobalStructPointer + ldr r1,[r1] + ldrsb r0,[r1, #+0x5] + mov r1,r4 + bl ShowPortraitBox + + ldr r0,=GlobalStructPointer + ldr r0,[r0, #+0x0] + ldrsb r0,[r0, #+0x3] + bl FreeAdvancedMenu + mvn r0,#0x1 + ldr r2,=GlobalStructPointer + ldr r1,[r2, #+0x0] + strb r0,[r1, #+0x3] + ldr r1,[r2, #+0x0] + mov r0,#0x42 + str r0,[r1, #+0x20] + b EndCodeSwitch + SwitchCase48: ;Special Case to skip the quiz + mov r0,#0x0 + mov r1,#0x3 + mov r2,#0x1 + bl CreatePortraitBox + ldr r1,=GlobalStructPointer + ldr r1,[r1] + strb r0,[r1, #+0x5] + ldr r1,=GlobalStructPointer + ldr r0,[r1] + ldrb r1,[r0, #+0x5f] + ldr r0,=BorderColorTable + ldrb r0,[r0, +r1] + bl ChangeBorderColor + ldr r1,=GlobalStructPointer + ldr r1,[r1] + mov r0,#0x45 + str r0,[r1, #+0x20] + b EndCodeSwitch + .pool + GetPlayerPkmnID: + ldr r1,=GlobalStructPointer + ldr r1,[r1] + ldrb r1,[r1, #+0x5f] + add r0,r1,r0,lsl #0x1 + mov r0,r0,lsl #0x1 + ldr r2,=PlayersListPkmnID + ldrsh r0,[r2, r0] + bx r14 + PlayerMenuDisp: + stmdb r13!,{r3,r4,r14} + sub r13,r13,#0x54 + add r12,r13,#0x4 + mov r4,r0 + mov r0,r1 + bl GetPlayerPkmnID + ldr r3,=0x0000c402 + orr r14,r0,#0x10000 + str r0,[r13, #+0x4] + str r14,[r13, #+0x14] + mov r1,#0x400 + ldr r2,=MenuOptionString + str r12,[r13, #+0x0] + mov r0,r4 + bl MenuCreateOptionString + mov r0,r4 + add r13,r13,#0x54 + ldmia r13!,{r3,r4,r15} + .pool + .fill OverlayStart+OrgSize+ExtendSize-., 0xCC + .endarea diff --git a/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/eu/offsets.asm b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/eu/offsets.asm new file mode 100644 index 000000000..dd59dc98d --- /dev/null +++ b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/eu/offsets.asm @@ -0,0 +1,83 @@ +; For use with ARMIPS +; 2021/03/23 +; For Explorers of Sky EU Only +; ------------------------------------------------------------------------------ +; Adds a menu to choose the starter after the quiz +; ------------------------------------------------------------------------------ + + +.relativeinclude on +.nds +.arm + +.definelabel SpecialStringID, 0xA35 + +.definelabel OrgSize, 0x2E80 +.definelabel ExtendSize, 0x1000 +.definelabel OverlayStart, 0x0238AC80 + + +.definelabel RandMax, 0x02002274 + +.definelabel MenuCreateOptionString, 0x020225EC + +.definelabel ChangeBorderColor, 0x02027D74 + +.definelabel CreateNormalMenu, 0x0202B3E0 +.definelabel FreeNormalMenu, 0x0202B7B8 +.definelabel GetNormalMenuResult, 0x0202B870 + +.definelabel CreateAdvancedMenu, 0x0202BD14 +.definelabel FreeAdvancedMenu, 0x0202BF38 +.definelabel IsAdvancedMenuActive, 0x0202BFD0 +.definelabel GetAdvancedMenuCurrentOption, 0x0202BFF0 +.definelabel GetAdvancedMenuResult, 0x0202C004 + +.definelabel IsDBActive, 0x0202F474 +.definelabel ShowMessageInDB, 0x0202F4A8 +.definelabel ShowDB, 0x0202F698 + +.definelabel CreatePortraitBox, 0x0202F8A0 +.definelabel ShowPortraitBox, 0x0202F984 +.definelabel HidePortraitBox, 0x0202F9D0 + +.definelabel PrepDBUnk1, 0x020238B4 + +.definelabel UnknownFuncCase0, 0x0204A4D0 + +.definelabel SetPortraitPkmnID, 0x0204DB0C +.definelabel SetPortraitExpressionID, 0x0204DB2C +.definelabel SetPortraitUnknownAttr, 0x0204DB3C +.definelabel SetPortraitAttrStruct, 0x0204DB80 + + +.definelabel BegSwitch, 0x0238B0E0 +.definelabel EndSwitch, 0x0238B1F4 + +.definelabel case0_alt1, 0x0238B220 +.definelabel case0_alt2, 0x0238B234 + +.definelabel HookEventSeq, 0x0238B908 + +.definelabel EndCodeSwitch, 0x0238C8B4 + +.definelabel WaitForNextStep, 0x0238C98C + +.definelabel OldGetPersonalityResult, 0x0238C8E8 + +.definelabel BorderColorTable, 0x0238CB50 +.definelabel PortraitAttrStruct, 0x0238CB54 +.definelabel QuizMenu1, 0x0238CBB4 +.definelabel PlayersListPkmnID, 0x0238CBF8 +.definelabel MenuOptionString, 0x0238D9B0 + +.definelabel GlobalStructPointer, 0x0238D9E0 +;0x2 = CurrentDialogueBoxID [0x1] +;0x3 = CurrentMenuID [0x1] +;0x5 = CurrentPortraitBoXID [0x1] +;0x20 = NextSwitchCase [0x4] +;0x30 = WaitingCase [0x4] +;0x5F = Gender [0x1] + +.definelabel DBLayout5, 0x0238D9EC +.definelabel DBLayout6, 0x0238D9FC diff --git a/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/jp/offsets.asm b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/jp/offsets.asm new file mode 100644 index 000000000..1eab38a42 --- /dev/null +++ b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/jp/offsets.asm @@ -0,0 +1,84 @@ +; For use with ARMIPS +; 2021/03/23 +; For Explorers of Sky JP Only +; ------------------------------------------------------------------------------ +; Adds a menu to choose the starter after the quiz +; ------------------------------------------------------------------------------ + +; WARNING! Not tested! + +.relativeinclude on +.nds +.arm + +.definelabel SpecialStringID, 0xA35 ;Guess + +.definelabel OrgSize, 0x2E80 +.definelabel ExtendSize, 0x1000 +.definelabel OverlayStart, 0x0238B6A0 + + +.definelabel RandMax, 0x02002274 + +.definelabel MenuCreateOptionString, 0x02022440 + +.definelabel ChangeBorderColor, 0x02027DE0 + +.definelabel CreateNormalMenu, 0x0202B444 +.definelabel FreeNormalMenu, 0x0202B81C +.definelabel GetNormalMenuResult, 0x0202B8D4 + +.definelabel CreateAdvancedMenu, 0x0202BD78 +.definelabel FreeAdvancedMenu, 0x0202BF9C +.definelabel IsAdvancedMenuActive, 0x0202C034 +.definelabel GetAdvancedMenuCurrentOption, 0x0202C054 +.definelabel GetAdvancedMenuResult, 0x0202C068 + +.definelabel IsDBActive, 0x0202F4C4 +.definelabel ShowMessageInDB, 0x0202F4F8 +.definelabel ShowDB, 0x0202F6E8 + +.definelabel CreatePortraitBox, 0x0202F8F0 +.definelabel ShowPortraitBox, 0x0202F9D4 +.definelabel HidePortraitBox, 0x0202FA20 + +.definelabel PrepDBUnk1, 0x020236E0 + +.definelabel UnknownFuncCase0, 0x0204A500 + +.definelabel SetPortraitPkmnID, 0x0204DB34 +.definelabel SetPortraitExpressionID, 0x0204DB54 +.definelabel SetPortraitUnknownAttr, 0x0204DB64 +.definelabel SetPortraitAttrStruct, 0x0204DBA8 + + +.definelabel BegSwitch, 0x0238BB00 +.definelabel EndSwitch, 0x0238BC14 + +.definelabel case0_alt1, 0x0238BC40 +.definelabel case0_alt2, 0x0238BC54 + +.definelabel HookEventSeq, 0x0238C328 + +.definelabel EndCodeSwitch, 0x0238D2D8 + +.definelabel WaitForNextStep, 0x0238D3B0 + +.definelabel OldGetPersonalityResult, 0x0238D30C + +.definelabel BorderColorTable, 0x0238D578 +.definelabel PortraitAttrStruct, 0x0238D57C +.definelabel QuizMenu1, 0x0238D5DC +.definelabel PlayersListPkmnID, 0x0238D620 +.definelabel MenuOptionString, 0x0238E3D8 + +.definelabel GlobalStructPointer, 0x0238E408 +;0x2 = CurrentDialogueBoxID [0x1] +;0x3 = CurrentMenuID [0x1] +;0x5 = CurrentPortraitBoXID [0x1] +;0x20 = NextSwitchCase [0x4] +;0x30 = WaitingCase [0x4] +;0x5F = Gender [0x1] + +.definelabel DBLayout5, 0x0238E414 +.definelabel DBLayout6, 0x0238E424 diff --git a/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/na/offsets.asm b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/na/offsets.asm new file mode 100644 index 000000000..c85cab68e --- /dev/null +++ b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/na/offsets.asm @@ -0,0 +1,83 @@ +; For use with ARMIPS +; 2021/03/23 +; For Explorers of Sky NA Only +; ------------------------------------------------------------------------------ +; Adds a menu to choose the starter after the quiz +; ------------------------------------------------------------------------------ + + +.relativeinclude on +.nds +.arm + +.definelabel SpecialStringID, 0xA35 + +.definelabel OrgSize, 0x2E80 +.definelabel ExtendSize, 0x1000 +.definelabel OverlayStart, 0x0238A140 + + +.definelabel RandMax, 0x02002274 + +.definelabel MenuCreateOptionString, 0x020223F0 + +.definelabel ChangeBorderColor, 0x02027A80 + +.definelabel CreateNormalMenu, 0x0202B0EC +.definelabel FreeNormalMenu, 0x0202B4C4 +.definelabel GetNormalMenuResult, 0x0202B57C + +.definelabel CreateAdvancedMenu, 0x0202BA20 +.definelabel FreeAdvancedMenu, 0x0202BC44 +.definelabel IsAdvancedMenuActive, 0x0202BCDC +.definelabel GetAdvancedMenuCurrentOption, 0x0202BCFC +.definelabel GetAdvancedMenuResult, 0x0202BD10 + +.definelabel IsDBActive, 0x0202F180 +.definelabel ShowMessageInDB, 0x0202F1B4 +.definelabel ShowDB, 0x0202F3A4 + +.definelabel CreatePortraitBox, 0x0202F5AC +.definelabel ShowPortraitBox, 0x0202F690 +.definelabel HidePortraitBox, 0x0202F6DC + +.definelabel PrepDBUnk1, 0x02023690 + +.definelabel UnknownFuncCase0, 0x0204A198 + +.definelabel SetPortraitPkmnID, 0x0204D7D4 +.definelabel SetPortraitExpressionID, 0x0204D7F4 +.definelabel SetPortraitUnknownAttr, 0x0204D804 +.definelabel SetPortraitAttrStruct, 0x0204D848 + + +.definelabel BegSwitch, 0x0238A5A0 +.definelabel EndSwitch, 0x0238A6B4 + +.definelabel case0_alt1, 0x0238A6E0 +.definelabel case0_alt2, 0x0238A6F4 + +.definelabel HookEventSeq, 0x0238ADC8 + +.definelabel EndCodeSwitch, 0x0238BD74 + +.definelabel WaitForNextStep, 0x0238BE4C + +.definelabel OldGetPersonalityResult, 0x0238BDA8 + +.definelabel BorderColorTable, 0x0238C010 +.definelabel PortraitAttrStruct, 0x0238C014 +.definelabel QuizMenu1, 0x0238C074 +.definelabel PlayersListPkmnID, 0x238C0B8 +.definelabel MenuOptionString, 0x0238CE70 + +.definelabel GlobalStructPointer, 0x0238CEA0 +;0x2 = CurrentDialogueBoxID [0x1] +;0x3 = CurrentMenuID [0x1] +;0x5 = CurrentPortraitBoXID [0x1] +;0x20 = NextSwitchCase [0x4] +;0x30 = WaitingCase [0x4] +;0x5F = Gender [0x1] + +.definelabel DBLayout5, 0x0238CEAC +.definelabel DBLayout6, 0x0238CEBC diff --git a/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/selector_overlay13.asm b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/selector_overlay13.asm new file mode 100644 index 000000000..7952b3319 --- /dev/null +++ b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/choose_starter/selector_overlay13.asm @@ -0,0 +1,22 @@ +; For use with ARMIPS +; 2021/03/23 +; For Explorers of Sky All Versions +; ------------------------------------------------------------------------------ +; Selects the correct version to use +; ------------------------------------------------------------------------------ + +.relativeinclude on + +; Selects the correct region to apply the patch +.if PPMD_GameVer == GameVer_EoS_NA + .include "na/offsets.asm" + .include "common/patch.asm" +.elseif PPMD_GameVer == GameVer_EoS_EU + .include "eu/offsets.asm" + .include "common/patch.asm" +.elseif PPMD_GameVer == GameVer_EoS_JP + .include "jp/offsets.asm" + .include "common/patch.asm" +.endif + +.relativeinclude off diff --git a/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/common/patch.asm b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/common/patch.asm new file mode 100644 index 000000000..a1a40ff6b --- /dev/null +++ b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/common/patch.asm @@ -0,0 +1,29 @@ +; For use with ARMIPS +; 2021/03/23 +; For Explorers of Sky All Versions +; ------------------------------------------------------------------------------ +; Gets rid of the personality quiz +; ------------------------------------------------------------------------------ + + .org HookBeforeQuestions + .area 0x4*14 + mov r1,#0xE + ldr r3,[r0, #+0x0] + mov r0,#0x0 + strb r1,[r3, #+0x0] + mov r1,#9 + str r1,[r3, #+0x24] + strb r0,[r3, #+0x5e] + strb r0,[r3, #+0x5f] + ldr r1,[r3, #+0x20] + add r1,r1,#0x1 + str r1,[r3, #+0x20] + mov r1,#0x6F + mov r2,#0x1 + bl SetGameVariable + .endarea + + .org HookAfterQuestions + .area 0x4 + mov r2,#0x48 + .endarea diff --git a/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/eu/offsets.asm b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/eu/offsets.asm new file mode 100644 index 000000000..97e77f2be --- /dev/null +++ b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/eu/offsets.asm @@ -0,0 +1,15 @@ +; For use with ARMIPS +; 2021/03/23 +; For Explorers of Sky EU Only +; ------------------------------------------------------------------------------ +; Adds a menu to choose the starter after the quiz +; ------------------------------------------------------------------------------ + + +.relativeinclude on +.nds +.arm + +.definelabel SetGameVariable, 0x0204BB58 +.definelabel HookBeforeQuestions, 0x0238B240 +.definelabel HookAfterQuestions, 0x0238B7BC diff --git a/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/jp/offsets.asm b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/jp/offsets.asm new file mode 100644 index 000000000..3ce93365c --- /dev/null +++ b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/jp/offsets.asm @@ -0,0 +1,16 @@ +; For use with ARMIPS +; 2021/03/23 +; For Explorers of Sky JP Only +; ------------------------------------------------------------------------------ +; Adds a menu to choose the starter after the quiz +; ------------------------------------------------------------------------------ + +; WARNING! Not tested! + +.relativeinclude on +.nds +.arm + +.definelabel SetGameVariable, 0x0204BB80 +.definelabel HookBeforeQuestions, 0x0238BC60 +.definelabel HookAfterQuestions, 0x0238C1DC diff --git a/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/na/offsets.asm b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/na/offsets.asm new file mode 100644 index 000000000..e4ff2d690 --- /dev/null +++ b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/na/offsets.asm @@ -0,0 +1,15 @@ +; For use with ARMIPS +; 2021/03/23 +; For Explorers of Sky NA Only +; ------------------------------------------------------------------------------ +; Adds a menu to choose the starter after the quiz +; ------------------------------------------------------------------------------ + + +.relativeinclude on +.nds +.arm + +.definelabel SetGameVariable, 0x0204B820 +.definelabel HookBeforeQuestions, 0x0238A700 +.definelabel HookAfterQuestions, 0x0238AC7C diff --git a/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/selector_overlay13.asm b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/selector_overlay13.asm new file mode 100644 index 000000000..7952b3319 --- /dev/null +++ b/skytemple_files/_resources/patches/asm_patches/irdkwia_asm_mods/skip_quiz/selector_overlay13.asm @@ -0,0 +1,22 @@ +; For use with ARMIPS +; 2021/03/23 +; For Explorers of Sky All Versions +; ------------------------------------------------------------------------------ +; Selects the correct version to use +; ------------------------------------------------------------------------------ + +.relativeinclude on + +; Selects the correct region to apply the patch +.if PPMD_GameVer == GameVer_EoS_NA + .include "na/offsets.asm" + .include "common/patch.asm" +.elseif PPMD_GameVer == GameVer_EoS_EU + .include "eu/offsets.asm" + .include "common/patch.asm" +.elseif PPMD_GameVer == GameVer_EoS_JP + .include "jp/offsets.asm" + .include "common/patch.asm" +.endif + +.relativeinclude off diff --git a/skytemple_files/_resources/ppmdu_config/pmd2data.xml b/skytemple_files/_resources/ppmdu_config/pmd2data.xml index b97b66752..7c20d7d13 100644 --- a/skytemple_files/_resources/ppmdu_config/pmd2data.xml +++ b/skytemple_files/_resources/ppmdu_config/pmd2data.xml @@ -962,6 +962,20 @@ + + + + + + + + + + + + + + diff --git a/skytemple_files/common/i18n_util.py b/skytemple_files/common/i18n_util.py index 0c93137ce..747ec69c0 100644 --- a/skytemple_files/common/i18n_util.py +++ b/skytemple_files/common/i18n_util.py @@ -14,13 +14,48 @@ # # You should have received a copy of the GNU General Public License # along with SkyTemple. If not, see . - +import gettext +from abc import ABC, abstractmethod from inspect import currentframe -try: - import builtins - __ = builtins._ -except Exception: - __ = lambda a: a + + +class AbstractLocaleManager(ABC): + @abstractmethod + def translate(self, message, locale_code): + pass + + @abstractmethod + def gettext(self, message): + pass + + +class LocaleManager(AbstractLocaleManager): + def __init__(self, domain, localedir, main_languages): + self.domain = domain + self.localedir = localedir + self.main_languages = main_languages + + self.main_translations = gettext.translation(domain, localedir=localedir, languages=main_languages) + + def translate(self, message, locale_code): + try: + return gettext.translation(self.domain, localedir=self.localedir, languages=[locale_code]).gettext(message) + except Exception: + return message + + def gettext(self, message): + return self.main_translations.gettext(message) + + +class NullLocaleManager(AbstractLocaleManager): + def translate(self, message, locale_code): + return message + + def gettext(self, message): + return message + + +_locales: AbstractLocaleManager = NullLocaleManager() def _(s): @@ -29,13 +64,19 @@ def _(s): We use a proxy, so when imported before the localization is ready, we can ensure the reload()'ed function is actually called. """ - return __(s) + return _locales.gettext(s) + + +def get_locales(): + return _locales -def reload_locale(): +def reload_locale(domain, localedir, main_languages): + global _locales + _locales = LocaleManager(domain, localedir, main_languages) + _locales.main_translations.install() global __ import builtins - __ = builtins._ try: from explorerscript import util util._ = builtins._ diff --git a/skytemple_files/patch/handler/choose_starter.py b/skytemple_files/patch/handler/choose_starter.py new file mode 100644 index 000000000..9e7e3ae65 --- /dev/null +++ b/skytemple_files/patch/handler/choose_starter.py @@ -0,0 +1,109 @@ +# Copyright 2020-2021 Parakoopa and the SkyTemple Contributors +# +# This file is part of SkyTemple. +# +# SkyTemple is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SkyTemple is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SkyTemple. If not, see . +from typing import Callable, Dict, List, Set + +from ndspy.code import loadOverlayTable, saveOverlayTable +from ndspy.rom import NintendoDSRom + +from skytemple_files.common.util import * +from skytemple_files.common.ppmdu_config.data import Pmd2Data, GAME_VERSION_EOS, GAME_REGION_US, GAME_REGION_EU, GAME_REGION_JP +from skytemple_files.patch.handler.abstract import AbstractPatchHandler +from skytemple_files.common.i18n_util import _, get_locales +from skytemple_files.data.str.handler import StrHandler + +PATCH_CHECK_ADDR_APPLIED_US = 0xC88 +PATCH_CHECK_ADDR_APPLIED_EU = 0xC88 +PATCH_CHECK_ADDR_APPLIED_JP = 0xC88 +PATCH_CHECK_INSTR_APPLIED = 0xE3A00026 + +OVERLAY13_INITAL_SIZE_US = 0x2E80 +OVERLAY13_INITAL_SIZE_EU = 0x2E80 +OVERLAY13_INITAL_SIZE_JP = 0x2E80 + +OVERLAY13_ADD_SIZE = 0x1000 + +STRING_ID_US = 2613 +STRING_ID_EU = 2613 +STRING_ID_JP = 2613 #Just a guess + +MESSAGE = "Then, who would you like to be?" +# For xgettext scanning: _("Then, who would you like to be?") + + +class ChooseStarterPatchHandler(AbstractPatchHandler): + + @property + def name(self) -> str: + return 'ChooseStarter' + + @property + def description(self) -> str: + return _("""Adds an extra menu during the personality test to choose the starter. +Uses the supposedly unused string 2613 in the strings file. """) + + @property + def author(self) -> str: + return 'irdkwia' + + @property + def version(self) -> str: + return '0.0.1' + + def is_applied(self, rom: NintendoDSRom, config: Pmd2Data) -> bool: + if config.game_version == GAME_VERSION_EOS: + if config.game_region == GAME_REGION_US: + return read_uintle(rom.loadArm9Overlays([13])[13].data, PATCH_CHECK_ADDR_APPLIED_US, 4)!=PATCH_CHECK_INSTR_APPLIED + if config.game_region == GAME_REGION_EU: + return read_uintle(rom.loadArm9Overlays([13])[13].data, PATCH_CHECK_ADDR_APPLIED_EU, 4)!=PATCH_CHECK_INSTR_APPLIED + if config.game_region == GAME_REGION_JP: + return read_uintle(rom.loadArm9Overlays([13])[13].data, PATCH_CHECK_ADDR_APPLIED_JP, 4)!=PATCH_CHECK_INSTR_APPLIED + raise NotImplementedError() + + def apply(self, apply: Callable[[], None], rom: NintendoDSRom, config: Pmd2Data): + if config.game_version == GAME_VERSION_EOS: + if config.game_region == GAME_REGION_US: + string_id = STRING_ID_US + overlay_size = OVERLAY13_INITAL_SIZE_US + if config.game_region == GAME_REGION_EU: + string_id = STRING_ID_EU + overlay_size = OVERLAY13_INITAL_SIZE_EU + if config.game_region == GAME_REGION_JP: + string_id = STRING_ID_JP + overlay_size = OVERLAY13_INITAL_SIZE_JP + + # Change dialogue + for lang in config.string_index_data.languages: + filename = 'MESSAGE/' + lang.filename + bin_before = rom.getFileByName(filename) + strings = StrHandler.deserialize(bin_before) + strings.strings[string_id-1] = get_locales().translate(MESSAGE, lang.locale.replace('-', '_')) + bin_after = StrHandler.serialize(strings) + rom.setFileByName(filename, bin_after) + + table = loadOverlayTable(rom.arm9OverlayTable, lambda x,y:bytes()) + ov = table[13] + if ov.ramSize. +from typing import Callable, Dict, List, Set + +from ndspy.rom import NintendoDSRom + +from skytemple_files.common.util import * +from skytemple_files.common.ppmdu_config.data import Pmd2Data, GAME_VERSION_EOS, GAME_REGION_US, GAME_REGION_EU, GAME_REGION_JP +from skytemple_files.patch.handler.abstract import AbstractPatchHandler, DependantPatch +from skytemple_files.common.i18n_util import _, get_locales +from skytemple_files.data.str.handler import StrHandler + +PATCH_CHECK_ADDR_APPLIED_US = 0xB3C +PATCH_CHECK_ADDR_APPLIED_EU = 0xB3C +PATCH_CHECK_ADDR_APPLIED_JP = 0xB3C +PATCH_CHECK_INSTR_APPLIED = 0xE2822001 + +STRING_ID_US = 2613 +STRING_ID_EU = 2613 +STRING_ID_JP = 2613 #Just a guess + +MESSAGE = "Who would you like to be?" +# For xgettext scanning: _("Who would you like to be?") + + +class SkipQuizPatchHandler(AbstractPatchHandler, DependantPatch): + + @property + def name(self) -> str: + return 'SkipQuiz' + + @property + def description(self) -> str: + return _("""Skips the quiz, only leaving the gender question. +Needs ChooseStarter patch to be applied. """) + + @property + def author(self) -> str: + return 'irdkwia' + + @property + def version(self) -> str: + return '0.0.1' + + def depends_on(self) -> List[str]: + return ['ChooseStarter'] + + def is_applied(self, rom: NintendoDSRom, config: Pmd2Data) -> bool: + if config.game_version == GAME_VERSION_EOS: + if config.game_region == GAME_REGION_US: + return read_uintle(rom.loadArm9Overlays([13])[13].data, PATCH_CHECK_ADDR_APPLIED_US, 4)!=PATCH_CHECK_INSTR_APPLIED + if config.game_region == GAME_REGION_EU: + return read_uintle(rom.loadArm9Overlays([13])[13].data, PATCH_CHECK_ADDR_APPLIED_EU, 4)!=PATCH_CHECK_INSTR_APPLIED + if config.game_region == GAME_REGION_JP: + return read_uintle(rom.loadArm9Overlays([13])[13].data, PATCH_CHECK_ADDR_APPLIED_JP, 4)!=PATCH_CHECK_INSTR_APPLIED + raise NotImplementedError() + + def apply(self, apply: Callable[[], None], rom: NintendoDSRom, config: Pmd2Data): + if config.game_version == GAME_VERSION_EOS: + if config.game_region == GAME_REGION_US: + string_id = STRING_ID_US + if config.game_region == GAME_REGION_EU: + string_id = STRING_ID_EU + if config.game_region == GAME_REGION_JP: + string_id = STRING_ID_JP + + # Change dialogue + for lang in config.string_index_data.languages: + filename = 'MESSAGE/' + lang.filename + bin_before = rom.getFileByName(filename) + strings = StrHandler.deserialize(bin_before) + strings.strings[string_id-1] = get_locales().translate(MESSAGE, lang.locale.replace('-', '_')) + bin_after = StrHandler.serialize(strings) + rom.setFileByName(filename, bin_after) + try: + apply() + except RuntimeError as ex: + raise ex + + + def unapply(self, unapply: Callable[[], None], rom: NintendoDSRom, config: Pmd2Data): + raise NotImplementedError() diff --git a/skytemple_files/patch/patches.py b/skytemple_files/patch/patches.py index 1048f8aac..621b83bc5 100644 --- a/skytemple_files/patch/patches.py +++ b/skytemple_files/patch/patches.py @@ -45,6 +45,8 @@ from skytemple_files.patch.handler.fairy_gummies import ImplementFairyGummiesPatchHandler from skytemple_files.patch.handler.extract_bar_list import ExtractBarItemListPatchHandler from skytemple_files.patch.handler.exp_share import ExpSharePatchHandler +from skytemple_files.patch.handler.choose_starter import ChooseStarterPatchHandler +from skytemple_files.patch.handler.skip_quiz import SkipQuizPatchHandler from skytemple_files.patch.handler.complete_team_control import CompleteTeamControl from skytemple_files.patch.handler.far_off_pal_overdrive import FarOffPalOverdrive from skytemple_files.patch.handler.partners_trigger_hidden_traps import PartnersTriggerHiddenTraps @@ -67,6 +69,8 @@ class PatchType(Enum): EXTRACT_DUNGEON_DATA = ExtractDungeonDataPatchHandler FIX_EVOLUTION = FixEvolutionPatchHandler EXP_SHARE = ExpSharePatchHandler + CHOOSE_STARTER = ChooseStarterPatchHandler + SKIP_QUIZ = SkipQuizPatchHandler COMPLETE_TEAM_CONTROL = CompleteTeamControl FAR_OFF_PAL_OVERDRIVE = FarOffPalOverdrive PARTNERS_TRIGGER_HIDDEN_TRAPS = PartnersTriggerHiddenTraps