diff --git a/asm/manager30.s b/asm/manager30.s deleted file mode 100644 index 6d5e1c08..00000000 --- a/asm/manager30.s +++ /dev/null @@ -1,204 +0,0 @@ - .include "asm/macros.inc" - - .include "constants/constants.inc" - - .syntax unified - - .text - - thumb_func_start sub_0805D4AC -sub_0805D4AC: @ 0x0805D4AC - push {r4, r5, r6, r7, lr} - mov r7, sb - mov r6, r8 - push {r6, r7} - adds r6, r0, #0 - ldrb r0, [r6, #0xc] - cmp r0, #1 - beq _0805D520 - cmp r0, #1 - bgt _0805D4C6 - cmp r0, #0 - beq _0805D4D2 - b _0805D628 -_0805D4C6: - cmp r0, #2 - beq _0805D5A4 - cmp r0, #3 - bne _0805D4D0 - b _0805D604 -_0805D4D0: - b _0805D628 -_0805D4D2: - movs r0, #1 - strb r0, [r6, #0xc] - ldrb r0, [r6, #0xe] - strb r0, [r6, #0xf] - ldrh r1, [r6, #0x38] - lsls r1, r1, #0x10 - asrs r1, r1, #0x14 - movs r3, #0x3f - ands r1, r3 - ldrh r0, [r6, #0x3a] - lsls r0, r0, #0x10 - asrs r0, r0, #0x14 - ands r0, r3 - lsls r0, r0, #6 - orrs r1, r0 - strh r1, [r6, #0x28] - ldr r4, _0805D518 @ =gPlayerEntity - movs r0, #0x2e - ldrsh r1, [r4, r0] - ldr r2, _0805D51C @ =gRoomControls - ldrh r0, [r2, #6] - subs r1, r1, r0 - asrs r1, r1, #4 - ands r1, r3 - movs r5, #0x32 - ldrsh r0, [r4, r5] - ldrh r2, [r2, #8] - subs r0, r0, r2 - asrs r0, r0, #4 - ands r0, r3 - lsls r0, r0, #6 - orrs r1, r0 - strh r1, [r6, #0x2e] - strh r1, [r6, #0x2c] - b _0805D628 - .align 2, 0 -_0805D518: .4byte gPlayerEntity -_0805D51C: .4byte gRoomControls -_0805D520: - ldr r4, _0805D568 @ =gPlayerEntity - movs r1, #0x2e - ldrsh r0, [r4, r1] - ldr r3, _0805D56C @ =gRoomControls - ldrh r1, [r3, #6] - subs r0, r0, r1 - asrs r5, r0, #4 - movs r2, #0x3f - ands r5, r2 - movs r1, #0x32 - ldrsh r0, [r4, r1] - ldrh r1, [r3, #8] - subs r0, r0, r1 - asrs r0, r0, #4 - ands r0, r2 - lsls r0, r0, #6 - orrs r5, r0 - strh r5, [r6, #0x2e] - ldrh r2, [r6, #0x2c] - cmp r5, r2 - beq _0805D5A4 - strh r5, [r6, #0x2c] - ldrh r0, [r6, #0x2e] - ldrb r1, [r6, #0xb] - bl GetTileType - adds r1, r0, #0 - ldr r3, _0805D570 @ =0x00000317 - cmp r1, r3 - beq _0805D574 - movs r0, #0xc6 - lsls r0, r0, #2 - cmp r1, r0 - beq _0805D580 - b _0805D5A4 - .align 2, 0 -_0805D568: .4byte gPlayerEntity -_0805D56C: .4byte gRoomControls -_0805D570: .4byte 0x00000317 -_0805D574: - movs r0, #2 - strb r0, [r6, #0xc] - movs r0, #0x6d - bl PlaySFX - b _0805D5A4 -_0805D580: - ldrh r1, [r6, #0x2e] - ldrb r2, [r6, #0xb] - adds r0, r3, #0 - bl sub_0807B7D8 - movs r0, #0x6b - bl PlaySFX - ldrb r0, [r6, #0xe] - subs r0, #1 - strb r0, [r6, #0xe] - lsls r0, r0, #0x18 - cmp r0, #0 - bne _0805D5A4 - movs r0, #3 - strb r0, [r6, #0xc] - movs r0, #0x40 - strb r0, [r6, #0xe] -_0805D5A4: - ldrh r0, [r6, #0x3e] - cmp r0, #0 - beq _0805D628 - bl CheckFlags - cmp r0, #0 - beq _0805D628 - ldrh r0, [r6, #0x3e] - bl ClearFlag - movs r0, #1 - strb r0, [r6, #0xc] - ldrb r0, [r6, #0xf] - strb r0, [r6, #0xe] - movs r1, #0 - adds r0, r6, #0 - adds r0, #0x37 - mov sb, r0 - ldrb r5, [r0] - cmp r1, r5 - bhs _0805D628 - movs r0, #0x36 - adds r0, r0, r6 - mov r8, r0 -_0805D5D4: - lsls r0, r1, #6 - ldrh r2, [r6, #0x28] - adds r5, r0, r2 - movs r4, #0 - adds r7, r1, #1 - mov r0, r8 - ldrb r0, [r0] - cmp r4, r0 - bhs _0805D5F8 -_0805D5E6: - adds r0, r5, r4 - ldrb r1, [r6, #0xb] - bl sub_0807BA8C - adds r4, #1 - mov r1, r8 - ldrb r1, [r1] - cmp r4, r1 - blo _0805D5E6 -_0805D5F8: - adds r1, r7, #0 - mov r2, sb - ldrb r2, [r2] - cmp r1, r2 - blo _0805D5D4 - b _0805D628 -_0805D604: - ldrb r0, [r6, #0xe] - cmp r0, #0 - beq _0805D628 - subs r0, #1 - strb r0, [r6, #0xe] - lsls r0, r0, #0x18 - lsrs r0, r0, #0x18 - cmp r0, #0 - beq _0805D622 - cmp r0, #0x20 - bne _0805D628 - ldrh r0, [r6, #0x3c] - bl SetFlag - b _0805D628 -_0805D622: - movs r0, #0x72 - bl PlaySFX -_0805D628: - pop {r3, r4} - mov r8, r3 - mov sb, r4 - pop {r4, r5, r6, r7, pc} diff --git a/include/functions.h b/include/functions.h index cd11f49e..c499fe02 100644 --- a/include/functions.h +++ b/include/functions.h @@ -32,6 +32,7 @@ extern u32 GetFacingDirection(Entity*, Entity*); extern Entity* CreatePlayerItem(u32, u32, u32, u32); extern Entity* GetEmptyEntity(void); extern u32 GetTileTypeByPos(s32 x, s32 y, u32 layer); +extern u32 GetTileType(u32 pos, u32 layer); extern void _DmaZero(void* src, u32 count); extern void EraseAllEntities(void); extern void SetTile(u32, u32, u32); diff --git a/linker.ld b/linker.ld index 962668bc..2407b66a 100644 --- a/linker.ld +++ b/linker.ld @@ -518,7 +518,7 @@ SECTIONS { src/manager/manager2E.o(.text); asm/manager2E.o(.text); asm/manager2F.o(.text); - asm/manager30.o(.text); + src/manager/manager30.o(.text); asm/manager31.o(.text); asm/manager32.o(.text); asm/manager33.o(.text); diff --git a/src/enemy/rollobite.c b/src/enemy/rollobite.c index 9a662526..1a9fc159 100644 --- a/src/enemy/rollobite.c +++ b/src/enemy/rollobite.c @@ -17,7 +17,6 @@ u32 sub_08020B6C(Entity*); extern void sub_080AE58C(); extern void sub_080AE7E8(); extern void sub_08078930(); -extern s32 GetTileType(s32 tilePosition, s32 layerIndex); void Rollobite(Entity* this) { EnemyFunctionHandler(this, gUnk_080CA66C); diff --git a/src/manager/manager30.c b/src/manager/manager30.c new file mode 100644 index 00000000..5f5ead82 --- /dev/null +++ b/src/manager/manager30.c @@ -0,0 +1,98 @@ +#include "global.h" +#include "manager.h" +#include "flags.h" +#include "functions.h" + +typedef struct Manager30 { + Manager manager; + u8 unk_20[8];//unused + u16 own_tile; + u8 unk_2a[0x2];//unused + u16 player_previous_tile; + u16 player_current_tile; + u8 unk_30[0x6];//unused + u8 width; + u8 height; + s16 x; + s16 y; + u16 flag_succeeded; + u16 flag_reset; +} Manager30; + +extern void sub_0807B7D8(u32, u32, u32); + +enum { + INIT, + IN_PROGRESS, + FAILED, + SUCCEEDED +}; + +/* + * Tile puzzles (step on all blue tiles exactly once). + * + * The Manager's field 0xe is used for the remaining number of tiles to be changed. + * field 0xf is used for the total number of tiles to be changed. +*/ +void Manager30_Main(Manager30* this) { + u32 i, j, tmp, tmp2; + switch (this->manager.action) { + default: + break; + case INIT: + this->manager.action = IN_PROGRESS; + this->manager.unk_0f = this->manager.unk_0e; + this->own_tile = (((this->x >> 4) & 0x3fU) | + ((this->y >> 4) & 0x3fU) << 6); + this->player_previous_tile = this->player_current_tile = COORD_TO_TILE((&gPlayerEntity)); + break; + case 1: + this->player_current_tile = COORD_TO_TILE((&gPlayerEntity)); + if (this->player_current_tile != this->player_previous_tile) { + this->player_previous_tile = this->player_current_tile; + switch (GetTileType(this->player_current_tile, this->manager.unk_0b)) { + case 0x317: + //stepped on a red tile again + this->manager.action = FAILED; + PlaySFX(0x6d); + break; + case 0x318: + //stepped on a blue tile + //turn the tile into a red tile + sub_0807B7D8(0x317, this->player_current_tile, this->manager.unk_0b); + PlaySFX(0x6b); + //decrease the number of remaining tiles and check if we're done + if (--this->manager.unk_0e == 0) { + this->manager.action = SUCCEEDED; + //set up delay for setting the flag/playing the success sfx + this->manager.unk_0e = 0x40; + } + break; + } + } + //fall through, can be reset in-progress + case FAILED: + if (!this->flag_reset) return;//can't be reset + if (!CheckFlags(this->flag_reset)) return;//wait for the flag telling it to reset + ClearFlag(this->flag_reset);//make sure the puzzle can be reset again later + this->manager.action = IN_PROGRESS; + this->manager.unk_0e = this->manager.unk_0f; + for (i = 0; i < this->height; i++) { + tmp = this->own_tile + (i << 6); + for (j = 0; j < this->width; j++) { + sub_0807BA8C(tmp + j, this->manager.unk_0b); + } + } + break; + case SUCCEEDED: + if (this->manager.unk_0e == 0) return; + tmp2 = --this->manager.unk_0e; + if (tmp2) { + if (tmp2 == 0x20) { + SetFlag(this->flag_succeeded); + } + } else { + PlaySFX(0x72); + } + } +}