From 102403cd9ae2cadca0dfd81e8aac915bc16b7d80 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Tue, 12 Nov 2024 12:30:12 +0100 Subject: [PATCH] decompile dungeon_generation --- asm/code_804AFAC.s | 662 ------------------ include/dungeon_generation.h | 11 + include/structs/map.h | 1 + ld_script.txt | 3 +- ...{code_804AFAC_1.c => dungeon_generation.c} | 216 +++++- 5 files changed, 226 insertions(+), 667 deletions(-) delete mode 100644 asm/code_804AFAC.s rename src/{code_804AFAC_1.c => dungeon_generation.c} (93%) diff --git a/asm/code_804AFAC.s b/asm/code_804AFAC.s deleted file mode 100644 index be57e660a..000000000 --- a/asm/code_804AFAC.s +++ /dev/null @@ -1,662 +0,0 @@ - #include "asm/constants/gba_constants.inc" - #include "asm/macros.inc" - - .syntax unified - - .text - - - - thumb_func_start GenerateSecondaryStructure -GenerateSecondaryStructure: - push {r4-r7,lr} - mov r7, r10 - mov r6, r9 - mov r5, r8 - push {r5-r7} - sub sp, 0x8 - adds r7, r0, 0 - movs r0, 0x6 - bl DungeonRandInt - subs r0, 0x1 - cmp r0, 0x4 - bls _0804F6B0 - b _0804FBD6 -_0804F6B0: - lsls r0, 2 - ldr r1, _0804F6BC - adds r0, r1 - ldr r0, [r0] - mov pc, r0 - .align 2, 0 -_0804F6BC: .4byte _0804F6C0 - .align 2, 0 -_0804F6C0: - .4byte _0804FB24 - .4byte _0804FA98 - .4byte _0804F9DC - .4byte _0804F826 - .4byte _0804F6D4 -_0804F6D4: - ldr r1, _0804F70C - ldr r0, [r1] - cmp r0, 0 - bne _0804F6DE - b _0804FBD6 -_0804F6DE: - subs r0, 0x1 - str r0, [r1] - adds r0, r7, 0 - bl SetSpawnFlag5 - movs r0, 0x2 - bl DungeonRandInt - cmp r0, 0 - beq _0804F78E - movs r5, 0 - movs r1, 0 - ldrsh r0, [r7, r1] - movs r2, 0x4 - ldrsh r1, [r7, r2] - adds r0, r1 - lsrs r1, r0, 31 - adds r0, r1 - asrs r0, 1 - mov r8, r0 - movs r3, 0x2 - ldrsh r4, [r7, r3] - b _0804F712 - .align 2, 0 -_0804F70C: .4byte gUnknown_202F1C8 -_0804F710: - adds r4, 0x1 -_0804F712: - movs r1, 0x6 - ldrsh r0, [r7, r1] - cmp r4, r0 - bge _0804F72A - mov r0, r8 - adds r1, r4, 0 - bl IsNextToHallway - lsls r0, 24 - cmp r0, 0 - beq _0804F710 - movs r5, 0x1 -_0804F72A: - cmp r5, 0 - beq _0804F730 - b _0804FBD6 -_0804F730: - movs r2, 0x2 - ldrsh r4, [r7, r2] - movs r3, 0x6 - ldrsh r0, [r7, r3] - cmp r4, r0 - bge _0804F754 -_0804F73C: - mov r0, r8 - adds r1, r4, 0 - bl GetTileSafe - movs r1, 0 - bl sub_804F5C4 - adds r4, 0x1 - movs r5, 0x6 - ldrsh r0, [r7, r5] - cmp r4, r0 - blt _0804F73C -_0804F754: - movs r0, 0 - ldrsh r5, [r7, r0] - cmp r5, r8 - blt _0804F75E - b _0804FBD2 -_0804F75E: - movs r1, 0x2 - ldrsh r4, [r7, r1] - movs r2, 0x6 - ldrsh r0, [r7, r2] - adds r6, r5, 0x1 - cmp r4, r0 - bge _0804F786 -_0804F76C: - adds r0, r5, 0 - adds r1, r4, 0 - bl GetTileSafe - ldrh r2, [r0] - movs r1, 0x80 - orrs r1, r2 - strh r1, [r0] - adds r4, 0x1 - movs r3, 0x6 - ldrsh r0, [r7, r3] - cmp r4, r0 - blt _0804F76C -_0804F786: - adds r5, r6, 0 - cmp r5, r8 - blt _0804F75E - b _0804FBD2 -_0804F78E: - movs r5, 0 - movs r4, 0x2 - ldrsh r0, [r7, r4] - movs r2, 0x6 - ldrsh r1, [r7, r2] - adds r0, r1 - lsrs r1, r0, 31 - adds r0, r1 - asrs r0, 1 - mov r8, r0 - movs r3, 0 - ldrsh r4, [r7, r3] - b _0804F7AA -_0804F7A8: - adds r4, 0x1 -_0804F7AA: - movs r1, 0x4 - ldrsh r0, [r7, r1] - cmp r4, r0 - bge _0804F7C2 - adds r0, r4, 0 - mov r1, r8 - bl IsNextToHallway - lsls r0, 24 - cmp r0, 0 - beq _0804F7A8 - movs r5, 0x1 -_0804F7C2: - cmp r5, 0 - beq _0804F7C8 - b _0804FBD6 -_0804F7C8: - movs r2, 0 - ldrsh r4, [r7, r2] - movs r3, 0x4 - ldrsh r0, [r7, r3] - cmp r4, r0 - bge _0804F7EC -_0804F7D4: - adds r0, r4, 0 - mov r1, r8 - bl GetTileSafe - movs r1, 0 - bl sub_804F5C4 - adds r4, 0x1 - movs r5, 0x4 - ldrsh r0, [r7, r5] - cmp r4, r0 - blt _0804F7D4 -_0804F7EC: - movs r0, 0x2 - ldrsh r5, [r7, r0] - cmp r5, r8 - blt _0804F7F6 - b _0804FBD2 -_0804F7F6: - movs r1, 0 - ldrsh r4, [r7, r1] - movs r2, 0x4 - ldrsh r0, [r7, r2] - adds r6, r5, 0x1 - cmp r4, r0 - bge _0804F81E -_0804F804: - adds r0, r4, 0 - adds r1, r5, 0 - bl GetTileSafe - ldrh r2, [r0] - movs r1, 0x80 - orrs r1, r2 - strh r1, [r0] - adds r4, 0x1 - movs r3, 0x4 - ldrsh r0, [r7, r3] - cmp r4, r0 - blt _0804F804 -_0804F81E: - adds r5, r6, 0 - cmp r5, r8 - blt _0804F7F6 - b _0804FBD2 -_0804F826: - movs r4, 0x4 - ldrsh r3, [r7, r4] - movs r5, 0 - ldrsh r1, [r7, r5] - subs r0, r3, r1 - cmp r0, 0x5 - bgt _0804F836 - b _0804FBD6 -_0804F836: - movs r0, 0x6 - ldrsh r4, [r7, r0] - movs r5, 0x2 - ldrsh r2, [r7, r5] - subs r0, r4, r2 - cmp r0, 0x5 - bgt _0804F846 - b _0804FBD6 -_0804F846: - adds r0, r1, r3 - lsrs r1, r0, 31 - adds r0, r1 - asrs r0, 1 - str r0, [sp] - adds r0, r2, r4 - lsrs r1, r0, 31 - adds r0, r1 - asrs r0, 1 - str r0, [sp, 0x4] - ldr r1, _0804F9D8 - ldr r0, [r1] - cmp r0, 0 - bne _0804F864 - b _0804FBD6 -_0804F864: - subs r0, 0x1 - str r0, [r1] - adds r0, r7, 0 - bl SetSpawnFlag5 - ldr r5, [sp] - subs r5, 0x2 - ldr r0, [sp, 0x4] - subs r0, 0x2 - mov r10, r0 - adds r0, r5, 0 - mov r1, r10 - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - ldr r1, [sp] - subs r1, 0x1 - mov r9, r1 - mov r0, r9 - mov r1, r10 - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - ldr r0, [sp] - mov r1, r10 - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - ldr r2, [sp] - adds r2, 0x1 - mov r8, r2 - mov r0, r8 - mov r1, r10 - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - ldr r6, [sp, 0x4] - subs r6, 0x1 - adds r0, r5, 0 - adds r1, r6, 0 - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - adds r0, r5, 0 - ldr r1, [sp, 0x4] - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - ldr r4, [sp, 0x4] - adds r4, 0x1 - adds r0, r5, 0 - adds r1, r4, 0 - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - adds r0, r5, 0 - adds r1, r4, 0 - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - mov r0, r9 - adds r1, r4, 0 - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - ldr r0, [sp] - adds r1, r4, 0 - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - mov r0, r8 - mov r1, r10 - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - mov r0, r8 - adds r1, r6, 0 - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - mov r0, r8 - ldr r1, [sp, 0x4] - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - mov r0, r8 - adds r1, r4, 0 - bl GetTileSafe - movs r1, 0x4 - bl sub_804F5C4 - mov r0, r9 - adds r1, r6, 0 - bl GetTileSafe - ldrh r2, [r0, 0x4] - movs r1, 0x4 - orrs r1, r2 - strh r1, [r0, 0x4] - mov r0, r9 - adds r1, r6, 0 - bl GetTileSafe - ldrh r1, [r0, 0x4] - movs r2, 0x40 - orrs r1, r2 - strh r1, [r0, 0x4] - ldr r0, [sp] - adds r1, r6, 0 - bl GetTileSafe - ldrh r1, [r0, 0x4] - movs r4, 0x2 - orrs r1, r4 - strh r1, [r0, 0x4] - mov r0, r9 - ldr r1, [sp, 0x4] - bl GetTileSafe - ldrh r1, [r0, 0x4] - orrs r1, r4 - strh r1, [r0, 0x4] - ldr r0, [sp] - ldr r1, [sp, 0x4] - bl GetTileSafe - ldrh r1, [r0, 0x4] - orrs r1, r4 - strh r1, [r0, 0x4] - mov r0, r9 - adds r1, r6, 0 - bl GetTileSafe - ldrh r1, [r0, 0x4] - movs r4, 0x10 - orrs r1, r4 - strh r1, [r0, 0x4] - ldr r0, [sp] - adds r1, r6, 0 - bl GetTileSafe - ldrh r1, [r0, 0x4] - orrs r1, r4 - strh r1, [r0, 0x4] - mov r0, r9 - ldr r1, [sp, 0x4] - bl GetTileSafe - ldrh r1, [r0, 0x4] - orrs r1, r4 - strh r1, [r0, 0x4] - ldr r0, [sp] - ldr r1, [sp, 0x4] - bl GetTileSafe - ldrh r1, [r0, 0x4] - orrs r4, r1 - strh r4, [r0, 0x4] - b _0804FBD2 - .align 2, 0 -_0804F9D8: .4byte gUnknown_202F1C8 -_0804F9DC: - movs r4, 0x4 - ldrsh r3, [r7, r4] - movs r5, 0 - ldrsh r2, [r7, r5] - subs r0, r3, r2 - cmp r0, 0x4 - bgt _0804F9EC - b _0804FBD6 -_0804F9EC: - movs r1, 0x6 - ldrsh r0, [r7, r1] - movs r4, 0x2 - ldrsh r1, [r7, r4] - subs r0, r1 - cmp r0, 0x4 - bgt _0804F9FC - b _0804FBD6 -_0804F9FC: - adds r0, r2, 0x2 - subs r1, r3, 0x3 - bl DungeonRandRange - adds r4, r0, 0 - movs r5, 0x2 - ldrsh r0, [r7, r5] - adds r0, 0x2 - movs r2, 0x6 - ldrsh r1, [r7, r2] - subs r1, 0x3 - bl DungeonRandRange - mov r10, r0 - movs r3, 0 - ldrsh r0, [r7, r3] - adds r0, 0x2 - movs r5, 0x4 - ldrsh r1, [r7, r5] - subs r1, 0x3 - bl DungeonRandRange - mov r9, r0 - movs r1, 0x2 - ldrsh r0, [r7, r1] - adds r0, 0x2 - movs r2, 0x6 - ldrsh r1, [r7, r2] - subs r1, 0x3 - bl DungeonRandRange - adds r6, r0, 0 - ldr r1, _0804FA94 - ldr r0, [r1] - cmp r0, 0 - bne _0804FA46 - b _0804FBD6 -_0804FA46: - subs r0, 0x1 - str r0, [r1] - adds r0, r7, 0 - bl SetSpawnFlag5 - cmp r4, r9 - ble _0804FA5A - adds r0, r4, 0 - mov r4, r9 - mov r9, r0 -_0804FA5A: - cmp r10, r6 - ble _0804FA64 - mov r0, r10 - mov r10, r6 - adds r6, r0, 0 -_0804FA64: - adds r5, r4, 0 - cmp r5, r9 - ble _0804FA6C - b _0804FBD2 -_0804FA6C: - mov r4, r10 - adds r3, r5, 0x1 - mov r8, r3 - cmp r4, r6 - bgt _0804FA8A -_0804FA76: - adds r0, r5, 0 - adds r1, r4, 0 - bl GetTileSafe - movs r1, 0 - bl sub_804F5C4 - adds r4, 0x1 - cmp r4, r6 - ble _0804FA76 -_0804FA8A: - mov r5, r8 - cmp r5, r9 - ble _0804FA6C - b _0804FBD2 - .align 2, 0 -_0804FA94: .4byte gUnknown_202F1C8 -_0804FA98: - movs r4, 0x4 - ldrsh r0, [r7, r4] - movs r5, 0 - ldrsh r1, [r7, r5] - subs r0, r1 - movs r2, 0x1 - ands r0, r2 - cmp r0, 0 - bne _0804FAAC - b _0804FBD6 -_0804FAAC: - movs r1, 0x6 - ldrsh r0, [r7, r1] - movs r3, 0x2 - ldrsh r1, [r7, r3] - subs r0, r1 - ands r0, r2 - cmp r0, 0 - bne _0804FABE - b _0804FBD6 -_0804FABE: - ldr r1, _0804FB20 - ldr r0, [r1] - cmp r0, 0 - bne _0804FAC8 - b _0804FBD6 -_0804FAC8: - subs r0, 0x1 - str r0, [r1] - adds r0, r7, 0 - bl SetSpawnFlag5 - movs r6, 0x3F -_0804FAD4: - movs r4, 0x4 - ldrsh r0, [r7, r4] - movs r5, 0 - ldrsh r1, [r7, r5] - subs r0, r1 - bl DungeonRandInt - adds r4, r0, 0 - movs r1, 0x6 - ldrsh r0, [r7, r1] - movs r2, 0x2 - ldrsh r1, [r7, r2] - subs r0, r1 - bl DungeonRandInt - adds r2, r0, 0 - adds r0, r4, r2 - movs r5, 0x1 - ands r0, r5 - cmp r0, 0 - beq _0804FB14 - movs r3, 0 - ldrsh r0, [r7, r3] - adds r0, r4 - movs r4, 0x2 - ldrsh r1, [r7, r4] - adds r1, r2 - bl GetTileSafe - movs r1, 0 - bl sub_804F5C4 -_0804FB14: - subs r6, 0x1 - cmp r6, 0 - bge _0804FAD4 - strb r5, [r7, 0x9] - b _0804FBD6 - .align 2, 0 -_0804FB20: .4byte gUnknown_202F1C8 -_0804FB24: - ldr r1, _0804FBC0 - ldr r0, [r1] - cmp r0, 0 - beq _0804FBD6 - subs r0, 0x1 - str r0, [r1] - movs r5, 0x4 - ldrsh r3, [r7, r5] - movs r0, 0 - ldrsh r2, [r7, r0] - subs r6, r3, r2 - movs r4, 0x1 - adds r0, r6, 0 - ands r0, r4 - cmp r0, 0 - beq _0804FB54 - movs r1, 0x6 - ldrsh r0, [r7, r1] - movs r5, 0x2 - ldrsh r1, [r7, r5] - subs r0, r1 - ands r0, r4 - cmp r0, 0 - bne _0804FBC4 -_0804FB54: - adds r0, r2, r3 - lsrs r1, r0, 31 - adds r0, r1 - asrs r5, r0, 1 - movs r0, 0x2 - ldrsh r3, [r7, r0] - movs r1, 0x6 - ldrsh r2, [r7, r1] - adds r0, r3, r2 - lsrs r1, r0, 31 - adds r0, r1 - asrs r4, r0, 1 - cmp r6, 0x4 - ble _0804FBAE - subs r0, r2, r3 - cmp r0, 0x4 - ble _0804FBAE - adds r0, r5, 0x1 - adds r1, r4, 0 - bl GetTileSafe - movs r1, 0 - bl sub_804F5C4 - adds r1, r4, 0x1 - adds r0, r5, 0 - bl GetTileSafe - movs r1, 0 - bl sub_804F5C4 - subs r0, r5, 0x1 - adds r1, r4, 0 - bl GetTileSafe - movs r1, 0 - bl sub_804F5C4 - subs r1, r4, 0x1 - adds r0, r5, 0 - bl GetTileSafe - movs r1, 0 - bl sub_804F5C4 -_0804FBAE: - adds r0, r5, 0 - adds r1, r4, 0 - bl GetTileSafe - movs r1, 0 - bl sub_804F5C4 - b _0804FBD2 - .align 2, 0 -_0804FBC0: .4byte gUnknown_202F1C8 -_0804FBC4: - adds r0, r7, 0 - bl SetSpawnFlag5 - adds r0, r7, 0 - movs r1, 0x1 - bl GenerateMaze -_0804FBD2: - movs r0, 0x1 - strb r0, [r7, 0x9] -_0804FBD6: - add sp, 0x8 - pop {r3-r5} - mov r8, r3 - mov r9, r4 - mov r10, r5 - pop {r4-r7} - pop {r0} - bx r0 - thumb_func_end GenerateSecondaryStructure - - .align 2,0 diff --git a/include/dungeon_generation.h b/include/dungeon_generation.h index fd49803bb..777d3693d 100644 --- a/include/dungeon_generation.h +++ b/include/dungeon_generation.h @@ -15,4 +15,15 @@ enum FloorType { FLOOR_TYPE_RESCUE, // Rescuing another player }; +// Helper type used to make explicit the possible secondary structures which can be randomly rolled to generate in the dungeon algorithm. +enum SecondaryStructureType { + SECONDARY_STRUCTURE_NONE, // No secondary structure will be generated. + SECONDARY_STRUCTURE_MAZE_PLUS_DOT, // One of 3 secondary structures depending on the dimensions of the room. If the room has odd dimensions, the result is a maze room. Otherwise, if the room has dimensions of at least `5x5`, a cross or plus pattern is made instead. If both fail, a single tile of secondary terrain will be placed in the center of the room. + SECONDARY_STRUCTURE_CHECKERBOARD, // If the room has odd dimensions, a checkerboard pattern made of randomly placed diagonal stripes of secondary terrain will be generated. If not, no secondary structure will be generated. + SECONDARY_STRUCTURE_POOL, // If the room has dimensions of at least `5x5`, a rectangular pool of secondary terrain will be generated. If not, no secondary structure will be generated. + SECONDARY_STRUCTURE_ISLAND, // If the room has dimensions of at least `6x6`, an island of items and a warp tile surrounded by secondary terrain will be generated. If not, no secondary structure will be generated. + SECONDARY_STRUCTURE_DIVIDER, // A "divider" of secondary terrain will split the room in half randomly either horizontally or vertically. +}; + + #endif diff --git a/include/structs/map.h b/include/structs/map.h index 1f0c4c92c..287a7deda 100644 --- a/include/structs/map.h +++ b/include/structs/map.h @@ -18,6 +18,7 @@ enum TerrainType TERRAIN_TYPE_IMPASSABLE_WALL = 1 << 4, // x10 TERRAIN_TYPE_SHOP = 1 << 5, // x20 TERRAIN_TYPE_IN_MONSTER_HOUSE = 1 << 6, // x40 + TERRAIN_TYPE_UNK_7 = 1 << 7, // x80 TERRAIN_TYPE_UNK_8 = 1 << 8, // x100 TERRAIN_TYPE_STAIRS = 1 << 9, // x200 TERRAIN_TYPE_UNK_x400 = 1 << 10, diff --git a/ld_script.txt b/ld_script.txt index 8afa0922a..7482d6939 100755 --- a/ld_script.txt +++ b/ld_script.txt @@ -228,8 +228,7 @@ SECTIONS { src/dungeon_ai_item_weight.o(.text); src/dungeon_map_access.o(.text); src/tile_types.o(.text); - src/code_804AFAC_1.o(.text); - asm/code_804AFAC.o(.text); + src/dungeon_generation.o(.text); src/code_804AFAC.o(.text); asm/code_804FD30.o(.text); src/dungeon_message.o(.text); diff --git a/src/code_804AFAC_1.c b/src/dungeon_generation.c similarity index 93% rename from src/code_804AFAC_1.c rename to src/dungeon_generation.c index 635a4a6b5..959b5e349 100644 --- a/src/code_804AFAC_1.c +++ b/src/dungeon_generation.c @@ -2315,6 +2315,19 @@ void CreateRoomsAndAnchors(struct GridCell grid[GRID_CELL_LEN][GRID_CELL_LEN], s } } +/* + * GenerateSecondaryStructures - Attempt to generate secondary structures in flagged rooms. + * + * For a valid flagged room with no extra features, one of the following will attempt to generate: + * 0. No Secondary Structure + * 1. A maze (made of water/lava walls), or a "plus" sign fallback, or a single dot in the center fallback + * 2. Checkerboard pattern of water/lava + * 3. A central pool in the room made of water/lava + * 4. A central island with items and a warp tile, surrounded by water/lava + * 5. A horizontal or vertical line of water/lava splitting the room in two. + * + * If a room doesn't meet the conditions for the secondary structure chosen, it will be left unchanged. + */ void GenerateSecondaryStructures(struct GridCell grid[GRID_CELL_LEN][GRID_CELL_LEN], s32 gridSizeX, s32 gridSizeY) { s32 x, y; @@ -4177,16 +4190,17 @@ void GenerateMazeLine(s32 x0, s32 y0, s32 xMin, s32 yMin, s32 xMax, s32 yMax, bo } } -void sub_804F5C4(Tile *tile, u32 terrainFlag) +void SetTerrainSecondaryWithFlag(Tile *tile, u32 additionalFlag) { SetTerrainSecondary(tile); - tile->terrainType |= terrainFlag; + tile->terrainType |= additionalFlag; } /* * SetSpawnFlag5 - Sets unknown spawn flag 0x5 on all tiles in a room */ -void SetSpawnFlag5(struct GridCell *gridCell) { +void SetSpawnFlag5(struct GridCell *gridCell) +{ s32 x, y; for (x = gridCell->start.x; x < gridCell->end.x; x++) { @@ -4228,4 +4242,200 @@ bool8 IsNextToHallway(s32 x, s32 y) return FALSE; } +// See GenerateSecondaryStructures for more information. +void GenerateSecondaryStructure(struct GridCell *gridCell) +{ + switch (DungeonRandInt(6)) { + // Generate a "split room" with two sides separated by a line of water/lava + case SECONDARY_STRUCTURE_DIVIDER: + if (gUnknown_202F1C8 != 0) { + s32 i; + + gUnknown_202F1C8--; + + SetSpawnFlag5(gridCell); + if (DungeonRandInt(2) != 0) { + // Split the room with a vertical line + s32 curX, curY; + bool8 invalid = FALSE; + s32 middleX = (gridCell->start.x + gridCell->end.x) / 2; + + for (i = gridCell->start.y; i < gridCell->end.y; i++) { + if (IsNextToHallway(middleX, i)) { + invalid = TRUE; + break; + } + } + + if (!invalid) { + for (i = gridCell->start.y; i < gridCell->end.y; i++) { + SetTerrainSecondaryWithFlag(GetTileSafe(middleX, i), 0); + } + + for (curX = gridCell->start.x; curX < middleX; curX++) { + for (curY = gridCell->start.y; curY < gridCell->end.y; curY++) { + GetTileSafe(curX, curY)->terrainType |= TERRAIN_TYPE_UNK_7; + } + } + + gridCell->hasSecondaryStructure = TRUE; + } + } + else { + // Split the room with a horizontal line + s32 curX, curY; + bool8 invalid = FALSE; + s32 middleY = (gridCell->start.y + gridCell->end.y) / 2; + + for (i = gridCell->start.x; i < gridCell->end.x; i++) { + if (IsNextToHallway(i, middleY)) { + invalid = TRUE; + break; + } + } + + if (!invalid) { + for (i = gridCell->start.x; i < gridCell->end.x; i++) { + SetTerrainSecondaryWithFlag(GetTileSafe(i, middleY), 0); + } + + for (curY = gridCell->start.y; curY < middleY; curY++) { + for (curX = gridCell->start.x; curX < gridCell->end.x; curX++) { + GetTileSafe(curX, curY)->terrainType |= TERRAIN_TYPE_UNK_7; + } + } + + gridCell->hasSecondaryStructure = TRUE; + } + } + } + break; + case SECONDARY_STRUCTURE_ISLAND: + if ((gridCell->end.x - gridCell->start.x) >= 6 && (gridCell->end.y - gridCell->start.y) >= 6) { + s32 middleX = (gridCell->start.x + gridCell->end.x) / 2; + s32 middleY = (gridCell->start.y + gridCell->end.y) / 2; + // Both dimensions are at least 6. Generate an "island" with lava, items, and a Warp Tile at the center + if (gUnknown_202F1C8 != 0) { + gUnknown_202F1C8--; + + SetSpawnFlag5(gridCell); + + // Water "Moat" + SetTerrainSecondaryWithFlag(GetTileSafe(middleX - 2, middleY - 2), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX - 1, middleY - 2), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX, middleY - 2), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX + 1, middleY - 2), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX - 2, middleY - 1), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX - 2, middleY), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX - 2, middleY + 1), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX - 2, middleY + 1), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX - 1, middleY + 1), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX, middleY + 1), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX + 1, middleY - 2), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX + 1, middleY - 1), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX + 1, middleY), TERRAIN_TYPE_UNK_2); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX + 1, middleY + 1), TERRAIN_TYPE_UNK_2); + + // Warp Tile ? + GetTileSafe(middleX - 1, middleY - 1)->unk4 |= 0x4; + GetTileSafe(middleX - 1, middleY - 1)->unk4 |= 0x40; + + // Items ? + GetTileSafe(middleX, middleY - 1)->unk4 |= 0x2; + GetTileSafe(middleX - 1, middleY)->unk4 |= 0x2; + GetTileSafe(middleX, middleY)->unk4 |= 0x2; + GetTileSafe(middleX - 1, middleY - 1)->unk4 |= 0x10; + GetTileSafe(middleX, middleY - 1)->unk4 |= 0x10; + GetTileSafe(middleX - 1, middleY)->unk4 |= 0x10; + GetTileSafe(middleX, middleY)->unk4 |= 0x10; + + gridCell->hasSecondaryStructure = TRUE; + } + } + break; + case SECONDARY_STRUCTURE_POOL: + if ((gridCell->end.x - gridCell->start.x) >= 5 && (gridCell->end.y - gridCell->start.y) >= 5) { + s32 curX, curY; + // Both dimensions are at least 5, generate a "pool" of water/lava + + s32 randX1 = DungeonRandRange(gridCell->start.x + 2, gridCell->end.x - 3); + s32 randY1 = DungeonRandRange(gridCell->start.y + 2, gridCell->end.y - 3); + s32 randX2 = DungeonRandRange(gridCell->start.x + 2, gridCell->end.x - 3); + s32 randY2 = DungeonRandRange(gridCell->start.y + 2, gridCell->end.y - 3); + + if (gUnknown_202F1C8 != 0) { + gUnknown_202F1C8--; + + SetSpawnFlag5(gridCell); + + if (randX1 > randX2) { + s32 temp; + SWAP(randX1, randX2, temp); + } + + if (randY1 > randY2) { + s32 temp; + SWAP(randY1, randY2, temp); + } + + for (curX = randX1; curX <= randX2; curX++) { + for (curY = randY1; curY <= randY2; curY++) { + SetTerrainSecondaryWithFlag(GetTileSafe(curX, curY), 0); + } + } + + gridCell->hasSecondaryStructure = TRUE; + } + } + break; + case SECONDARY_STRUCTURE_CHECKERBOARD: + if ((gridCell->end.x - gridCell->start.x) % 2 != 0 && (gridCell->end.y - gridCell->start.y) % 2 != 0 && gUnknown_202F1C8 != 0) { + s32 i; + // Dimensions are odd, generate diagonal stripes/checkerboard of water/lava + gUnknown_202F1C8--; + + SetSpawnFlag5(gridCell); + + for (i = 0; i < 64; i++) { + s32 randX = DungeonRandInt(gridCell->end.x - gridCell->start.x); + s32 randY = DungeonRandInt(gridCell->end.y - gridCell->start.y); + if ((randX + randY) % 2 != 0) { + SetTerrainSecondaryWithFlag(GetTileSafe(gridCell->start.x + randX, gridCell->start.y + randY), 0); + } + } + + gridCell->hasSecondaryStructure = TRUE; + } + break; + case SECONDARY_STRUCTURE_MAZE_PLUS_DOT: + if (gUnknown_202F1C8 != 0) { + gUnknown_202F1C8--; + + // If the dimensions are odd, generate a maze room + if ((gridCell->end.x - gridCell->start.x) % 2 == 0 || (gridCell->end.y - gridCell->start.y) % 2 == 0) { + s32 middleX = (gridCell->start.x + gridCell->end.x) / 2; + s32 middleY = (gridCell->start.y + gridCell->end.y) / 2; + if ((gridCell->end.x - gridCell->start.x) >= 5 && (gridCell->end.y - gridCell->start.y) >= 5) { + // Both dimensions are at least 5, generate a water/lava cross in the center + SetTerrainSecondaryWithFlag(GetTileSafe(middleX + 1, middleY), 0); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX, middleY + 1), 0); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX - 1, middleY), 0); + SetTerrainSecondaryWithFlag(GetTileSafe(middleX, middleY - 1), 0); + } + + // Generate a single water/lava spot in the center + SetTerrainSecondaryWithFlag(GetTileSafe(middleX, middleY), 0); + } + else { + // Both dimensions are odd. Generate a maze room + SetSpawnFlag5(gridCell); + GenerateMaze(gridCell, TRUE); + } + + gridCell->hasSecondaryStructure = TRUE; + } + break; + } +} + //