diff --git a/asm/npc4E.s b/asm/npc4E.s deleted file mode 100644 index 53931b77..00000000 --- a/asm/npc4E.s +++ /dev/null @@ -1,35 +0,0 @@ - .include "asm/macros.inc" - - .include "constants/constants.inc" - - .syntax unified - - .text - - thumb_func_start NPC4F -NPC4F: @ 0x0806DD44 - push {r4, lr} - adds r4, r0, #0 - ldrb r0, [r4, #0xc] - cmp r0, #0 - bne _0806DD5A - adds r0, #1 - strb r0, [r4, #0xc] - ldrb r1, [r4, #0xa] - adds r0, r4, #0 - bl InitAnimationForceUpdate -_0806DD5A: - adds r0, r4, #0 - bl UpdateAnimationSingleFrame - adds r4, #0x59 - ldrb r0, [r4] - cmp r0, #0xfe - bne _0806DD74 - bl Random - movs r1, #0x1f - ands r0, r1 - adds r0, #0x14 - strb r0, [r4] -_0806DD74: - pop {r4, pc} - .align 2, 0 diff --git a/data/animations/npc/npc4f.s b/data/animations/npc/npc4F.s similarity index 100% rename from data/animations/npc/npc4f.s rename to data/animations/npc/npc4F.s diff --git a/linker.ld b/linker.ld index 15fda49a..e885258c 100644 --- a/linker.ld +++ b/linker.ld @@ -638,6 +638,8 @@ SECTIONS { src/npc/bigGoron.o(.text); asm/bigGoron.o(.text); src/npc/ezloCap.o(.text); + src/npc/npc4E.o(.text); + src/npc/npc4F.o(.text); asm/npc4E.o(.text); src/npc/clothesRack.o(.text); asm/clothesRack.o(.text); @@ -1363,7 +1365,9 @@ SECTIONS { data/animations/npc/mayorHagen.o(.rodata); data/const/npc/bigGoron.o(.rodata); src/npc/ezloCap.o(.rodata); - data/animations/npc/npc4f.o(.rodata); + src/npc/npc4E.o(.rodata); + src/npc/npc4F.o(.rodata); + data/animations/npc/npc4F.o(.rodata); data/const/npc/clothesRack.o(.rodata); data/animations/npc/clothesRack.o(.rodata); data/const/npc/picolyteBottle.o(.rodata); diff --git a/src/npc/ezloCap.c b/src/npc/ezloCap.c index 655ad588..6f1a16bd 100644 --- a/src/npc/ezloCap.c +++ b/src/npc/ezloCap.c @@ -1,33 +1,11 @@ #include "global.h" #include "entity.h" -#include "flags.h" -#include "save.h" #include "script.h" #include "audio.h" -#include "object.h" #include "functions.h" -extern Hitbox gUnk_080FD170; -extern void script_08016030; // Cutscene data type? -extern void script_0801606C; // Cutscene data type? - -extern void sub_0809623C(Entity*); -extern void sub_08096260(Entity*); - const u8 gUnk_08114134[]; const u8 gUnk_08114144[]; -const Hitbox gUnk_08114154; -const u8 gUnk_0811415C[]; -const ScreenTransitionData* const gUnk_081141A4[]; -const u8 gUnk_081141E4[]; -const u16 gUnk_081141F4[]; - -typedef struct { - u32 unk_00; - s8 unk_04; -} gUnk_0810C89C_struct; - -extern void sub_08078850(Entity*, u32, u8 /* TODO this is a s8 in beedle.c*/, gUnk_0810C89C_struct*); // Ezlo as a cap in the Minish Woods, is destroyed as soon as link wears ezlo void EzloCap(Entity* this) { @@ -93,211 +71,6 @@ void sub_0806D9A4(Entity* this) { gPlayerEntity.animationState = 4; } -// NPC4E is created when link enters minish woods for the first time and -// destroyed once he wears ezlo. Also exists when entering hyrule for the second time -// and fusing kinstones. Is destroyed as soon as the kinstone is fused. -void NPC4E(Entity* this) { - if (this->action == 0) { - this->action = 1; - this->spriteSettings.b.draw = 4; - this->hitbox = &gUnk_080FD170; - sub_0807DD50(this); - } else { - sub_0807DD94(this, 0); - } -} - -void sub_0806DA04(Entity* this, ScriptExecutionContext* context) { - // TODO gUnk_0811415C should be a gUnk_0810C89C_struct[], but then a lot of bytes everywhere are wrong? - gUnk_0810C89C_struct* a = (gUnk_0810C89C_struct*)&( - (gUnk_0810C89C_struct*)gUnk_0811415C)[context->intVariable]; // cast necessary to no longer make it a const* ? - sub_08078850(this, 1, a->unk_04, a); -} - -void sub_0806DA1C(Entity* this, ScriptExecutionContext* context) { - sub_0808091C((ScreenTransitionData*)(gUnk_081141A4)[context->intVariable], - (u32)(gUnk_081141E4[context->intVariable])); -} - -// Returns the kinstone id? -u8 sub_0806DA3C(Entity* this) { - u32 result; - - switch (this->type) { - default: - result = 0; - break; - case 1: - result = 1; - break; - case 2: - result = 2; - break; - case 3: - result = 3; - break; - case 4: - result = 4; - break; - case 5: - result = 5; - break; - case 11: - result = 9; - break; - case 6: - case 7: - case 8: - case 9: - case 10: - result = sub_0801E99C(this); - break; - } - return result; -} - -// Check whether a kinstone fusion is possible and store the result somewhere in param_2? -void sub_0806DAAC(Entity* this, ScriptExecutionContext* context) { - context->condition = CheckKinstoneFused(sub_0806DA3C(this)); - gActiveScriptInfo.flags |= 1; -} - -// maybe actually execute the kinstone fusion? -void sub_0806DAD0(Entity* this) { - sub_08078790(this, sub_0806DA3C(this)); -} - -void sub_0806DAE8(Entity* this) { - switch (this->type - 1) { - case 0: - SetLocalFlag(0xee); - break; - case 1: - SetLocalFlag(0xef); - break; - case 2: - SetLocalFlag(0xf0); - break; - case 3: - SetLocalFlag(0xf1); - break; - case 4: - SetLocalFlag(0xf2); - break; - } - - SoundReq(SFX_TASK_COMPLETE); -} - -void sub_0806DB44(Entity* this, ScriptExecutionContext* context) { - context->condition = 0; - - if (CheckLocalFlag(0xee) != 0 && CheckLocalFlag(0xef) != 0 && CheckLocalFlag(0xf0) != 0 && - CheckLocalFlag(0xf1) != 0 && CheckLocalFlag(0xf2) != 0) { - context->condition = 1; - } -} - -void sub_0806DB84(Entity* this, ScriptExecutionContext* context) { - Entity* ent; - this->hitbox = (Hitbox*)&gUnk_08114154; - ent = CreateObject(OBJECT_3E, 4, 0); - if (ent != NULL) { - PositionRelative(this, ent, -0x80000, 0); - *(ScriptExecutionContext**)&ent->cutsceneBeh = StartCutscene(ent, &script_08016030); - } - ent = CreateObject(OBJECT_3E, 5, 0); - if (ent != NULL) { - PositionRelative(this, ent, 0x80000, 0); - *(ScriptExecutionContext**)&ent->cutsceneBeh = StartCutscene(ent, &script_0801606C); - } -} - -u32 sub_0806DBF4(u32 param_1) { - switch (param_1) { - case 1: - case 2: - case 3: - case 4: - case 6: - param_1 = 1; - if (GetInventoryValue(2) != 0) { - param_1 = 2; - } - if (GetInventoryValue(3) != 0) { - param_1 = 3; - } - if (GetInventoryValue(4) != 0) { - param_1 = 4; - } - if (GetInventoryValue(6) != 0) { - param_1 = 6; - } - break; - } - return param_1; -} - -void sub_0806DC3C(Entity* this) { - this->field_0x68.HALF.LO = gSave.stats.itemOnA; - this->field_0x68.HALF.HI = gSave.stats.itemOnB; -} - -void sub_0806DC58(Entity* this) { - ForceEquipItem(sub_0806DBF4(this->field_0x68.HALF.LO), 0); - ForceEquipItem(sub_0806DBF4(this->field_0x68.HALF.HI), 1); -} - -void sub_0806DC7C() { - const u16* tiles = gUnk_081141F4; - while (*tiles != 0) { - u32 tile = *tiles; - tiles = tiles + 1; - SetTileType(0x4072, tile, 1); - } -} - -void sub_0806DCA0() { - u16 uVar1; - const u16* tiles = gUnk_081141F4; - while (*tiles != 0) { - u32 tile = *tiles; - tiles = tiles + 1; - sub_0807BA8C(tile, 1); - } -} - -void sub_0806DCC0() { - gScreenTransition.field_0x20 = 0x7c8; - gScreenTransition.field_0x22 = 0xf8; -} - -void NPC4E_Fusion(Entity* this) { - if (this->action == 0) { - this->action += 1; - switch (this->type) { - case 1: - case 2: - case 3: - case 4: - case 5: - sub_0809623C(this); - break; - case 6: - case 7: - case 8: - case 9: - case 10: - sub_08096260(this); - break; - case 11: - sub_0806DB84(this, 0); - this->hitbox = NULL; - break; - } - } -} - // animation states const u8 gUnk_08114134[] = { 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x00 }; @@ -305,38 +78,3 @@ const u8 gUnk_08114134[] = { 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, // animation states const u8 gUnk_08114144[] = { 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x00 }; - -const Hitbox gUnk_08114154 = { 0, -8, 0, 0, 0, 0, 24, 8 }; - -const u8 gUnk_0811415C[] = { 0x00, 0x00, 0x08, 0x08, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x0e, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x08, - 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x08, 0x0e, 0x00, 0x00, 0x00 }; -extern ScreenTransitionData gUnk_0813AB6C; -extern ScreenTransitionData gUnk_0813ABBC; -extern ScreenTransitionData gUnk_0813ABE4; -extern ScreenTransitionData gUnk_0813ABF8; -extern ScreenTransitionData gUnk_0813AC0C; -extern ScreenTransitionData gUnk_0813AC20; -extern ScreenTransitionData gUnk_0813AC5C; -extern ScreenTransitionData gUnk_0813AC70; -extern ScreenTransitionData gUnk_0813AC84; -extern ScreenTransitionData gUnk_0813AC98; -extern ScreenTransitionData gUnk_0813ACAC; -extern ScreenTransitionData gUnk_0813ACC0; -extern ScreenTransitionData gUnk_0813ACD4; -extern ScreenTransitionData gUnk_0813ACE8; -extern ScreenTransitionData gUnk_0813ACFC; -// Array of pointers to ScreenTransitionData -const ScreenTransitionData* const gUnk_081141A4[] = { &gUnk_0813AB6C, &gUnk_0813ABBC, &gUnk_0813ABE4, &gUnk_0813ABF8, - &gUnk_0813AC0C, &gUnk_0813AC20, &gUnk_0813AC5C, &gUnk_0813AC70, - &gUnk_0813AC84, &gUnk_0813AC98, &gUnk_0813ACAC, &gUnk_0813ACC0, - &gUnk_0813ACD4, &gUnk_0813ACE8, &gUnk_0813AC5C, &gUnk_0813ACFC }; - -// param_2 for the call to sub_0808091C, same indices as gUnk_081141A4 -const u8 gUnk_081141E4[] = { 0x02, 0x02, 0x04, 0x04, 0x02, 0x02, 0x09, 0x02, - 0x02, 0x04, 0x02, 0x04, 0x04, 0x04, 0x04, 0x02 }; - -// tiles that are changed? -const u16 gUnk_081141F4[] = { 0x047a, 0x047b, 0x05af, 0x05ef, 0x0738, 0x0739, 0x073a, 0x073b, 0x0000, 0x0000 }; diff --git a/src/npc/npc4E.c b/src/npc/npc4E.c new file mode 100644 index 00000000..0adc5744 --- /dev/null +++ b/src/npc/npc4E.c @@ -0,0 +1,273 @@ +#include "global.h" +#include "entity.h" +#include "functions.h" +#include "script.h" +#include "functions.h" +#include "audio.h" +#include "save.h" +#include "flags.h" +#include "object.h" + +extern Hitbox gUnk_080FD170; +typedef struct { + u32 unk_00; + s8 unk_04; +} gUnk_0810C89C_struct; + +extern void sub_08078850(Entity*, u32, u8 /* TODO this is a s8 in beedle.c*/, gUnk_0810C89C_struct*); + +extern void script_08016030; // Cutscene data type? +extern void script_0801606C; // Cutscene data type? + +const Hitbox gUnk_08114154; +const u8 gUnk_0811415C[]; +const ScreenTransitionData* const gUnk_081141A4[]; +const u8 gUnk_081141E4[]; +const u16 gUnk_081141F4[]; + +extern void sub_0809623C(Entity*); +extern void sub_08096260(Entity*); + +// NPC4E is created when link enters minish woods for the first time and +// destroyed once he wears ezlo. Also exists when entering hyrule for the second time +// and fusing kinstones. Is destroyed as soon as the kinstone is fused. +void NPC4E(Entity* this) { + if (this->action == 0) { + this->action = 1; + this->spriteSettings.b.draw = 4; + this->hitbox = &gUnk_080FD170; + sub_0807DD50(this); + } else { + sub_0807DD94(this, 0); + } +} + +void sub_0806DA04(Entity* this, ScriptExecutionContext* context) { + // TODO gUnk_0811415C should be a gUnk_0810C89C_struct[], but then a lot of bytes everywhere are wrong? + gUnk_0810C89C_struct* a = (gUnk_0810C89C_struct*)&( + (gUnk_0810C89C_struct*)gUnk_0811415C)[context->intVariable]; // cast necessary to no longer make it a const* ? + sub_08078850(this, 1, a->unk_04, a); +} + +void sub_0806DA1C(Entity* this, ScriptExecutionContext* context) { + sub_0808091C((ScreenTransitionData*)(gUnk_081141A4)[context->intVariable], + (u32)(gUnk_081141E4[context->intVariable])); +} + +// Returns the kinstone id? +u8 sub_0806DA3C(Entity* this) { + u32 result; + + switch (this->type) { + default: + result = 0; + break; + case 1: + result = 1; + break; + case 2: + result = 2; + break; + case 3: + result = 3; + break; + case 4: + result = 4; + break; + case 5: + result = 5; + break; + case 11: + result = 9; + break; + case 6: + case 7: + case 8: + case 9: + case 10: + result = sub_0801E99C(this); + break; + } + return result; +} + +// Check whether a kinstone fusion is possible and store the result somewhere in param_2? +void sub_0806DAAC(Entity* this, ScriptExecutionContext* context) { + context->condition = CheckKinstoneFused(sub_0806DA3C(this)); + gActiveScriptInfo.flags |= 1; +} + +// maybe actually execute the kinstone fusion? +void sub_0806DAD0(Entity* this) { + sub_08078790(this, sub_0806DA3C(this)); +} + +void sub_0806DAE8(Entity* this) { + switch (this->type - 1) { + case 0: + SetLocalFlag(0xee); + break; + case 1: + SetLocalFlag(0xef); + break; + case 2: + SetLocalFlag(0xf0); + break; + case 3: + SetLocalFlag(0xf1); + break; + case 4: + SetLocalFlag(0xf2); + break; + } + + SoundReq(SFX_TASK_COMPLETE); +} + +void sub_0806DB44(Entity* this, ScriptExecutionContext* context) { + context->condition = 0; + + if (CheckLocalFlag(0xee) != 0 && CheckLocalFlag(0xef) != 0 && CheckLocalFlag(0xf0) != 0 && + CheckLocalFlag(0xf1) != 0 && CheckLocalFlag(0xf2) != 0) { + context->condition = 1; + } +} + +void sub_0806DB84(Entity* this, ScriptExecutionContext* context) { + Entity* ent; + this->hitbox = (Hitbox*)&gUnk_08114154; + ent = CreateObject(OBJECT_3E, 4, 0); + if (ent != NULL) { + PositionRelative(this, ent, -0x80000, 0); + *(ScriptExecutionContext**)&ent->cutsceneBeh = StartCutscene(ent, &script_08016030); + } + ent = CreateObject(OBJECT_3E, 5, 0); + if (ent != NULL) { + PositionRelative(this, ent, 0x80000, 0); + *(ScriptExecutionContext**)&ent->cutsceneBeh = StartCutscene(ent, &script_0801606C); + } +} + +u32 sub_0806DBF4(u32 param_1) { + switch (param_1) { + case 1: + case 2: + case 3: + case 4: + case 6: + param_1 = 1; + if (GetInventoryValue(2) != 0) { + param_1 = 2; + } + if (GetInventoryValue(3) != 0) { + param_1 = 3; + } + if (GetInventoryValue(4) != 0) { + param_1 = 4; + } + if (GetInventoryValue(6) != 0) { + param_1 = 6; + } + break; + } + return param_1; +} + +void sub_0806DC3C(Entity* this) { + this->field_0x68.HALF.LO = gSave.stats.itemOnA; + this->field_0x68.HALF.HI = gSave.stats.itemOnB; +} + +void sub_0806DC58(Entity* this) { + ForceEquipItem(sub_0806DBF4(this->field_0x68.HALF.LO), 0); + ForceEquipItem(sub_0806DBF4(this->field_0x68.HALF.HI), 1); +} + +void sub_0806DC7C() { + const u16* tiles = gUnk_081141F4; + while (*tiles != 0) { + u32 tile = *tiles; + tiles = tiles + 1; + SetTileType(0x4072, tile, 1); + } +} + +void sub_0806DCA0() { + u16 uVar1; + const u16* tiles = gUnk_081141F4; + while (*tiles != 0) { + u32 tile = *tiles; + tiles = tiles + 1; + sub_0807BA8C(tile, 1); + } +} + +void sub_0806DCC0() { + gScreenTransition.field_0x20 = 0x7c8; + gScreenTransition.field_0x22 = 0xf8; +} + +void NPC4E_Fusion(Entity* this) { + if (this->action == 0) { + this->action += 1; + switch (this->type) { + case 1: + case 2: + case 3: + case 4: + case 5: + sub_0809623C(this); + break; + case 6: + case 7: + case 8: + case 9: + case 10: + sub_08096260(this); + break; + case 11: + sub_0806DB84(this, 0); + this->hitbox = NULL; + break; + } + } +} + +const Hitbox gUnk_08114154 = { 0, -8, 0, 0, 0, 0, 24, 8 }; + +const u8 gUnk_0811415C[] = { // + 0x00, 0x00, 0x08, 0x08, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x04, 0x0e, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0x18, 0x08, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x08, 0x0e, 0x00, 0x00, 0x00 +}; +extern ScreenTransitionData gUnk_0813AB6C; +extern ScreenTransitionData gUnk_0813ABBC; +extern ScreenTransitionData gUnk_0813ABE4; +extern ScreenTransitionData gUnk_0813ABF8; +extern ScreenTransitionData gUnk_0813AC0C; +extern ScreenTransitionData gUnk_0813AC20; +extern ScreenTransitionData gUnk_0813AC5C; +extern ScreenTransitionData gUnk_0813AC70; +extern ScreenTransitionData gUnk_0813AC84; +extern ScreenTransitionData gUnk_0813AC98; +extern ScreenTransitionData gUnk_0813ACAC; +extern ScreenTransitionData gUnk_0813ACC0; +extern ScreenTransitionData gUnk_0813ACD4; +extern ScreenTransitionData gUnk_0813ACE8; +extern ScreenTransitionData gUnk_0813ACFC; + +// Array of pointers to ScreenTransitionData +const ScreenTransitionData* const gUnk_081141A4[] = { // + &gUnk_0813AB6C, &gUnk_0813ABBC, &gUnk_0813ABE4, &gUnk_0813ABF8, &gUnk_0813AC0C, &gUnk_0813AC20, + &gUnk_0813AC5C, &gUnk_0813AC70, &gUnk_0813AC84, &gUnk_0813AC98, &gUnk_0813ACAC, &gUnk_0813ACC0, + &gUnk_0813ACD4, &gUnk_0813ACE8, &gUnk_0813AC5C, &gUnk_0813ACFC +}; + +// param_2 for the call to sub_0808091C, same indices as gUnk_081141A4 +const u8 gUnk_081141E4[] = { // + 0x02, 0x02, 0x04, 0x04, 0x02, 0x02, 0x09, 0x02, 0x02, 0x04, 0x02, 0x04, 0x04, 0x04, 0x04, 0x02 +}; + +// tiles that are changed? +const u16 gUnk_081141F4[] = { 0x047a, 0x047b, 0x05af, 0x05ef, 0x0738, 0x0739, 0x073a, 0x073b, 0x0000, 0x0000 }; diff --git a/src/npc/npc4F.c b/src/npc/npc4F.c new file mode 100644 index 00000000..0285ac2d --- /dev/null +++ b/src/npc/npc4F.c @@ -0,0 +1,14 @@ +#include "global.h" +#include "entity.h" +#include "random.h" + +void NPC4F(Entity* this) { + if (this->action == 0) { + this->action += 1; + InitAnimationForceUpdate(this, this->type); + } + UpdateAnimationSingleFrame(this); + if (this->frameDuration == 0xfe) { + this->frameDuration = (Random() & 0x1f) + 0x14; + } +} \ No newline at end of file