1#pragma once 2#include "ap_macro.h" 3#include "ap_math.h" 4#include "alttp_public.h" 5 6#define SNES_TR_MASK ((uint16_t) (1ul << 4)) 7#define SNES_TL_MASK ((uint16_t) (1ul << 5)) 8#define SNES_X_MASK ((uint16_t) (1ul << 6)) 9#define SNES_A_MASK ((uint16_t) (1ul << 7)) 10#define SNES_RIGHT_MASK ((uint16_t) (1ul << 8)) 11#define SNES_LEFT_MASK ((uint16_t) (1ul << 9)) 12#define SNES_DOWN_MASK ((uint16_t) (1ul << 10)) 13#define SNES_UP_MASK ((uint16_t) (1ul << 11)) 14#define SNES_START_MASK ((uint16_t) (1ul << 12)) 15#define SNES_SELECT_MASK ((uint16_t) (1ul << 13)) 16#define SNES_Y_MASK ((uint16_t) (1ul << 14)) 17#define SNES_B_MASK ((uint16_t) (1ul << 15)) 18 19#define SNES_MASK(key) CONCAT(CONCAT(SNES_, key), _MASK) 20 21#define JOYPAD_TEST(key) ((*joypad) & SNES_MASK(key)) 22#define JOYPAD_SET(key) ((*joypad) |= SNES_MASK(key)) 23#define JOYPAD_CLEAR(key) ((*joypad) &= (uint16_t) ~SNES_MASK(key)) 24#define JOYPAD_MASH(key, rate) ({ if(*ap_ram.frame_counter & (rate)) { JOYPAD_SET(key); } else { JOYPAD_CLEAR(key); } }) 25#define JOYPAD_EVENT(btn) ({\ 26 static bool _debounce = false; \ 27 bool _ret = false; \ 28 if (_debounce && !JOYPAD_TEST(btn)) { \ 29 _debounce = false; \ 30 } else if (!_debounce && JOYPAD_TEST(btn)) { \ 31 _debounce = true; \ 32 _ret = true; \ 33 } \ 34 _ret; }) 35 36bool ap_manual_mode; 37 38#define AP_RAM_LIST \ 39 X(module_index, uint8_t, 0x7E0010) \ 40 X(submodule_index, uint8_t, 0x7E0011) \ 41 X(sub_submodule_index, uint8_t, 0x7E00B0) \ 42 X(frame_counter, uint8_t, 0x7E001A) \ 43 X(in_building, uint8_t, 0x7E001B) \ 44 X(main_screen_bitmask, uint8_t, 0x7E001C) \ 45 X(sub_screen_bitmask, uint8_t, 0x7E001D) \ 46 X(area, uint8_t, 0x7E008A) \ 47 X(link_x, uint16_t, 0x7E0022) \ 48 X(link_y, uint16_t, 0x7E0020) \ 49 X(link_dx, int8_t, 0x7E0031) \ 50 X(link_dy, int8_t, 0x7E0030) \ 51 X(link_hold, uint16_t, 0x7E0308) \ 52 X(link_direction, uint8_t, 0x7E002F) \ 53 X(link_swordstate, uint8_t, 0x7E003A) \ 54 X(link_falling, uint8_t, 0x7E005B) \ 55 X(link_state, uint8_t, 0x7E005D) \ 56 X(link_lower_level, uint8_t, 0x7E00EE) \ 57 X(link_on_switch, uint16_t, 0x7E0430) \ 58 X(overworld_index, uint16_t, 0x7E008A) \ 59 X(overworld_dark, uint8_t, 0x7E0FFF) \ 60 X(dungeon_room, uint16_t, 0x7E00A0) \ 61 X(dungeon_tags, uint16_t, 0x7E00AE) \ 62 X(menu_part, uint8_t, 0x7E00C8) \ 63 X(screen_transition, uint8_t, 0x7E0126) \ 64 X(current_item, uint8_t, 0x7E0202) \ 65 X(recving_item, uint8_t, 0x7E02D8) \ 66 X(room_state, uint16_t, 0x7E0400) \ 67 X(room_chest_state, uint8_t, 0x7E0403) \ 68 X(room_layout, uint8_t, 0x7E040E) \ 69 X(room_trap_doors, uint16_t, 0x7E0468) \ 70 X(room_chest_index, uint16_t, 0x7E0496) \ 71 X(room_keyblock_index, uint16_t, 0x7E0498) \ 72 X(crystal_timer, uint8_t, 0x7E04C2) \ 73 X(room_chest_tilemaps, uint16_t, 0x7E06E0) \ 74 X(dngn_open_doors, uint16_t, 0x7E068C) \ 75 X(sprite_drop, uint8_t, 0x7E0CBA) \ 76 X(sprite_y_lo, uint8_t, 0x7E0D00) \ 77 X(sprite_x_lo, uint8_t, 0x7E0D10) \ 78 X(sprite_y_hi, uint8_t, 0x7E0D20) \ 79 X(sprite_x_hi, uint8_t, 0x7E0D30) \ 80 X(sprite_spawned, uint8_t, 0x7E0D80) \ 81 X(sprite_state, uint8_t, 0x7E0DD0) \ 82 X(sprite_type, uint8_t, 0x7E0E20) \ 83 X(sprite_subtype1, uint8_t, 0x7E0E30) \ 84 X(sprite_hp, int8_t, 0x7E0E50) \ 85 X(sprite_interaction, uint8_t, 0x7E0E60) \ 86 X(sprite_subtype2, uint8_t, 0x7E0E80) \ 87 X(sprite_lower_level, uint8_t, 0x7E0F20) \ 88 X(sprite_hitbox_idx, uint8_t, 0x7E0F60) \ 89 X(overlord_types, uint8_t, 0x7E0B00) \ 90 X(overlord_timers, uint8_t, 0x7E0B28) \ 91 X(ancillia_bf0, uint8_t, 0x7E0BF0) \ 92 X(ancillia_y_lo, uint8_t, 0x7E0BFA) \ 93 X(ancillia_x_lo, uint8_t, 0x7E0C04) \ 94 X(ancillia_y_hi, uint8_t, 0x7E0C0E) \ 95 X(ancillia_x_hi, uint8_t, 0x7E0C18) \ 96 X(ancillia_y_vel, int8_t, 0x7E0C22) \ 97 X(ancillia_x_vel, int8_t, 0x7E0C2C) \ 98 X(ancillia_y_sub, uint8_t, 0x7E0C36) \ 99 X(ancillia_x_sub, uint8_t, 0x7E0C40) \ 100 X(ancillia_type, uint8_t, 0x7E0C4A) \ 101 X(ancillia_lower_level, uint8_t, 0x7E0C7C) \ 102 X(hitbox_x_lo, uint8_t, 0x06F735) \ 103 X(hitbox_x_hi, uint8_t, 0x06F755) \ 104 X(hitbox_width, uint8_t, 0x06F775) \ 105 X(hitbox_y_lo, uint8_t, 0x06F795) \ 106 X(hitbox_y_hi, uint8_t, 0x06F7B5) \ 107 X(hitbox_height, uint8_t, 0x06F7D5) \ 108 X(block_data, uint32_t, 0x7EF940) \ 109 X(map_area, uint16_t, 0x7E040A) \ 110 X(dungeon_id, uint16_t, 0x7E040C) \ 111 X(map_y_offset, uint16_t, 0x7E0708) \ 112 X(map_y_mask, uint16_t, 0x7E070A) \ 113 X(map_x_offset, uint16_t, 0x7E070C) \ 114 X(map_x_mask, uint16_t, 0x7E070E) \ 115 X(map_area_size, uint16_t, 0x7E0712) \ 116 X(over_map16, uint16_t, 0x7E2000) \ 117 X(dngn_bg1_map8, uint16_t, 0x7E2000) \ 118 X(dngn_bg2_map8, uint16_t, 0x7E4000) \ 119 /* X(map16_to_map8, uint64_t, 0x078000) */\ 120 /* X(chr_to_tattr, uint64_t, 0x078000) */\ 121 X(dngn_bg2_tattr, uint8_t, 0x7F2000) \ 122 X(dngn_bg1_tattr, uint8_t, 0x7F3000) \ 123 X(over_tattr, uint8_t, 0x1BF110) \ 124 X(over_tattr2, uint8_t, 0x0FFD94) \ 125 X(transition_dir, uint16_t, 0x7E0410) \ 126 X(layers_enabled, uint8_t, 0x7E001C) \ 127 X(vram_transfer, uint8_t, 0x7E0019) \ 128 X(entrance_ys, uint16_t, 0x02CCBD) \ 129 X(entrance_xs, uint16_t, 0x02CDC7) \ 130 X(over_ent_areas, uint16_t, 0x1BB96F) \ 131 X(over_ent_map16s, uint16_t, 0x1BBA71) \ 132 X(over_ent_ids, uint8_t, 0x1BBB73) \ 133 X(over_hle_map16s, uint16_t, 0x1BB800) \ 134 X(over_hle_areas, uint16_t, 0x1BB826) \ 135 X(over_hle_ids, uint8_t, 0x1BB84C) \ 136 X(over_overlay_map16s, uint16_t, 0x02EB29) \ 137 X(touching_chest, uint8_t, 0x7E02E5) \ 138 X(item_recv_method, uint8_t, 0x7E02E9) \ 139 X(push_dir_bitmask, uint8_t, 0x7E0026) \ 140 X(push_timer, uint8_t, 0x7E0371) \ 141 X(carrying_bit7, uint8_t, 0x7E0308) \ 142 X(ignore_sprites, uint8_t, 0x7E037B) \ 143 X(sram_room_state, uint16_t, 0x7EF000) \ 144 X(sram_overworld_state, uint8_t, 0x7EF280) \ 145 X(sram_goal_rupees, uint16_t, 0x7EF360) \ 146 X(sram_actual_rupees, uint16_t, 0x7EF362) \ 147 X(sram_dungeon_bigkeys, uint16_t, 0x7EF366) \ 148 X(sram_pendants, uint8_t, 0x7EF374) \ 149 X(sram_crystals, uint8_t, 0x7EF37A) \ 150 X(sram_dungeon_keys, uint8_t, 0x7EF37C) \ 151 X(sram_progress1, uint8_t, 0x7EF3C5) \ 152 X(sram_progress2, uint8_t, 0x7EF3C6) \ 153 X(sram_progress3, uint8_t, 0x7EF3C9) \ 154 X(sram_tagalong, uint8_t, 0x7EF3CC) \ 155 X(inventory_base, uint8_t, 0x7EF33F) \ 156 X(inventory_bombs, uint8_t, 0x7EF343) \ 157 X(inventory_hammer, uint8_t, 0x7EF34B) \ 158 X(inventory_gloves, uint8_t, 0x7EF354) \ 159 X(inventory_sword, uint8_t, 0x7EF359) \ 160 X(inventory_quiver, uint8_t, 0x7EF377) \ 161 X(dungeon_bigkeys, uint16_t, 0x7EF366) \ 162 X(dungeon_keys, uint8_t, 0x7EF37C) \ 163 X(dungeon_current_keys, uint8_t, 0x7EF36F) \ 164 X(health_current, uint8_t, 0x7EF36D) \ 165 X(health_capacity, uint8_t, 0x7EF36C) \ 166 X(dungeon_door_types, uint16_t, 0x7E1980) \ 167 X(dungeon_door_tilemaps,uint16_t, 0x7E19A0) \ 168 X(dungeon_door_dirs, uint16_t, 0x7E19C0) \ 169 X(dungeon_chests, uint8_t, 0x01E96C) \ 170 X(dngn_stairs_0, uint16_t, 0x000438) \ 171 X(dngn_stairs_1, uint16_t, 0x00047E) \ 172 X(dngn_stairs_2, uint16_t, 0x000482) \ 173 X(dngn_stairs_3, uint16_t, 0x0004A2) \ 174 X(dngn_stairs_4, uint16_t, 0x0004A4) \ 175 X(dngn_stairs_5, uint16_t, 0x00043A) \ 176 X(dngn_stairs_6, uint16_t, 0x000480) \ 177 X(dngn_stairs_7, uint16_t, 0x000484) \ 178 X(dngn_stairs_8, uint16_t, 0x0004A6) \ 179 X(dngn_stairs_9, uint16_t, 0x0004A8) \ 180 X(special_tilemaps, uint16_t, 0x0006B0) \ 181 182extern struct ap_ram { 183#define X(name, type, offset) const type * name; 184AP_RAM_LIST 185#undef X 186} ap_ram; 187 188extern struct ap_snes9x * ap_emu; 189 190#define TILE_ATTR_LIST \ 191 X(WALK) /* Walkable */ \ 192 X(SWIM) /* Swim-able */ \ 193 X(DOOR) /* Door or other transition */ \ 194 X(NODE) /* Important goal node (chest, or something under a pot, stairs) */ \ 195 X(LFT0) /* Can lift with no power ups */ \ 196 X(LFT1) /* Can lift with power glove */ \ 197 X(LFT2) /* Can lift with titans mitts */ \ 198 X(LDGE) /* Ledge */ \ 199 X(CHST) /* Chest */ \ 200 X(BONK) /* Bonk rocks */ \ 201 X(SWCH) /* Floor button */ \ 202 X(STRS) /* Dungeon Stairs */ \ 203 X(MERG) /* Merge with similar tiles */ \ 204 X(EDGE) /* Pits have weird collision; only check top edge */ \ 205 X(HMMR) /* Hammer pegs */ \ 206 207enum { 208#define X(d) CONCAT(_TILE_ATTR_INDEX_, d), 209TILE_ATTR_LIST 210#undef X 211}; 212enum { 213#define X(d) CONCAT(TILE_ATTR_, d) = 1ul << CONCAT(_TILE_ATTR_INDEX_, d), 214TILE_ATTR_LIST 215#undef X 216}; 217extern const char * const ap_tile_attr_names[]; 218const char * ap_tile_attr_name(uint8_t idx); 219 220static const uint16_t ap_tile_attrs[256] = { 221 [0x00] = TILE_ATTR_WALK, 222 [0x01] = 0, 223 [0x02] = 0, 224 225 [0x08] = TILE_ATTR_SWIM, 226 [0x09] = TILE_ATTR_WALK, 227 [0x10] = 0, // edge of ledge? 228 [0x1c] = TILE_ATTR_WALK, // open below? 229 // XXX how do these work; how are they different than 0x3X 230 [0x1d] = TILE_ATTR_WALK, // stairs? 231 [0x1e] = TILE_ATTR_NODE | TILE_ATTR_STRS, // in-room stairs? 232 [0x1f] = TILE_ATTR_NODE | TILE_ATTR_STRS, // in-room stairs? 233 [0x20] = TILE_ATTR_EDGE, // Pit 234 235 [0x22] = TILE_ATTR_WALK, 236 [0x23] = TILE_ATTR_WALK | TILE_ATTR_NODE | TILE_ATTR_SWCH, // button 0x8000 237 [0x24] = TILE_ATTR_WALK | TILE_ATTR_NODE | TILE_ATTR_SWCH, // button 0x4000 238 [0x25] = TILE_ATTR_WALK | TILE_ATTR_NODE | TILE_ATTR_SWCH, // button XXX WILD GUESS 239 [0x26] = TILE_ATTR_NODE | TILE_ATTR_DOOR, // south stairs up 240 //[0x26] = TILE_ATTR_WALK | TILE_ATTR_NODE | TILE_ATTR_SWCH, // button XXX WILD GUESS 241 242 [0x27] = TILE_ATTR_HMMR, // hammer peg (was also fence; remapped to 0x01) 243 [0x28] = TILE_ATTR_LDGE, // up 244 [0x29] = TILE_ATTR_LDGE, // down 245 [0x2a] = TILE_ATTR_LDGE, // left 246 [0x2b] = TILE_ATTR_LDGE, // right 247 [0x2c] = TILE_ATTR_LDGE, // up left 248 [0x2d] = TILE_ATTR_LDGE, // down left 249 [0x2e] = TILE_ATTR_LDGE, // up right 250 [0x2f] = TILE_ATTR_LDGE, // down right 251 252 // Door transitions, unsure how to handle, see 0x8e & 0x8f 253 [0x30] = TILE_ATTR_NODE | TILE_ATTR_DOOR | TILE_ATTR_MERG, 254 [0x31] = TILE_ATTR_NODE | TILE_ATTR_DOOR | TILE_ATTR_MERG, 255 [0x32] = TILE_ATTR_NODE | TILE_ATTR_DOOR | TILE_ATTR_MERG, 256 [0x33] = TILE_ATTR_NODE | TILE_ATTR_DOOR | TILE_ATTR_MERG, 257 [0x34] = TILE_ATTR_NODE | TILE_ATTR_DOOR | TILE_ATTR_MERG, 258 [0x35] = TILE_ATTR_NODE | TILE_ATTR_DOOR | TILE_ATTR_MERG, 259 [0x36] = TILE_ATTR_NODE | TILE_ATTR_DOOR | TILE_ATTR_MERG, 260 [0x37] = TILE_ATTR_NODE | TILE_ATTR_DOOR | TILE_ATTR_MERG, 261 [0x38] = TILE_ATTR_NODE | TILE_ATTR_DOOR | TILE_ATTR_MERG, 262 [0x39] = TILE_ATTR_NODE | TILE_ATTR_DOOR | TILE_ATTR_MERG, // south stairs up 263 264 [0x3d] = TILE_ATTR_WALK, // in-room stairs that do not change BG 265 [0x3e] = TILE_ATTR_NODE | TILE_ATTR_STRS, // in-room stairs ^-shaped 266 [0x3f] = TILE_ATTR_NODE | TILE_ATTR_STRS, // in-room stairs? 267 268 [0x40] = TILE_ATTR_WALK, 269 [0x48] = TILE_ATTR_WALK, 270 [0x4B] = TILE_ATTR_NODE | TILE_ATTR_DOOR, 271 272 [0x50] = TILE_ATTR_LFT0, 273 [0x51] = TILE_ATTR_LFT0, 274 [0x52] = TILE_ATTR_LFT1, 275 [0x53] = TILE_ATTR_LFT2, 276 [0x54] = 0, //TILE_ATTR_LFT0, 277 [0x55] = TILE_ATTR_LFT1, 278 [0x56] = TILE_ATTR_LFT2, 279 [0x57] = TILE_ATTR_BONK, 280 281 // Chest, Big Chest, Big Key Block 282 [0x58] = TILE_ATTR_CHST, 283 [0x59] = TILE_ATTR_CHST, 284 [0x5A] = TILE_ATTR_CHST, 285 [0x5B] = TILE_ATTR_CHST, 286 [0x5C] = TILE_ATTR_CHST, 287 [0x5D] = TILE_ATTR_CHST, 288 289 [0x5E] = TILE_ATTR_NODE | TILE_ATTR_DOOR, // stairs up 290 [0x5F] = TILE_ATTR_NODE | TILE_ATTR_DOOR, // stairs down 291 292 // Special pots or pushable blocks in a room 293 [0x70] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 294 [0x71] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 295 [0x72] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 296 [0x73] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 297 [0x74] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 298 [0x75] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 299 [0x76] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 300 [0x77] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 301 [0x78] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 302 [0x79] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 303 [0x7A] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 304 [0x7B] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 305 [0x7C] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 306 [0x7D] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 307 [0x7E] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 308 [0x7F] = TILE_ATTR_NODE | TILE_ATTR_LFT0, 309 310 [0x80] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, // open door? 311 [0x81] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 312 [0x82] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, // lockable door? 313 [0x83] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 314 [0x84] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 315 [0x85] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, // locked door? 316 [0x86] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 317 [0x87] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 318 [0x88] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 319 [0x89] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 320 [0x8A] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 321 [0x8B] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 322 [0x8C] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 323 [0x8D] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 324 [0x8E] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 325 [0x8F] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 326 327 [0x90] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, // open door? 328 [0x91] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 329 [0x92] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, // lockable door? 330 [0x93] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 331 [0x94] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 332 [0x95] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, // locked door? 333 [0x96] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 334 [0x97] = /* TILE_ATTR_WALK | */ TILE_ATTR_NODE | TILE_ATTR_DOOR, 335 336 [0xA0] = TILE_ATTR_WALK, 337 [0xA1] = TILE_ATTR_WALK, 338 [0xA2] = TILE_ATTR_WALK, 339 [0xA3] = TILE_ATTR_WALK, 340 [0xA4] = TILE_ATTR_WALK, 341 [0xA5] = TILE_ATTR_WALK, 342 343 [0xF0] = TILE_ATTR_DOOR | TILE_ATTR_NODE, // Locked door, 0x8000? 344 [0xF1] = TILE_ATTR_DOOR | TILE_ATTR_NODE, // Locked door, 0x4000? 345 [0xF2] = TILE_ATTR_DOOR | TILE_ATTR_NODE, // Locked door 346 [0xF3] = TILE_ATTR_DOOR | TILE_ATTR_NODE, // Locked door 347 [0xF4] = TILE_ATTR_DOOR | TILE_ATTR_NODE, // Locked door 348 [0xF5] = TILE_ATTR_DOOR | TILE_ATTR_NODE, // Locked door 349 [0xF6] = TILE_ATTR_DOOR | TILE_ATTR_NODE, // Locked door 350 [0xF7] = TILE_ATTR_DOOR | TILE_ATTR_NODE, // Locked door 351 [0xF8] = TILE_ATTR_DOOR | TILE_ATTR_NODE, // Locked door, 0x8000? 352 [0xF9] = TILE_ATTR_DOOR | TILE_ATTR_NODE, // Locked door, ??? 353 [0xFA] = TILE_ATTR_DOOR | TILE_ATTR_NODE, // Locked door, ??? 354 // Fake/unknown 355 [0xFF] = TILE_ATTR_WALK, 356}; 357 358enum ap_room_layout { 359 // Cells are laid out as follows: 360 // A B 361 // C D 362 // Undercores separate rooms; ABCD is 1 2x2 room; A_B_C_D is 4 1x1 rooms 363 ROOM_LAYOUT_A_B_C_D = 0, 364 ROOM_LAYOUT_AC_BD = 1, 365 ROOM_LAYOUT_A_BD_C = 2, 366 ROOM_LAYOUT_AC_B_D = 3, 367 ROOM_LAYOUT_AB_CD = 4, 368 ROOM_LAYOUT_A_B_CD = 5, 369 ROOM_LAYOUT_AB_C_D = 6, 370 ROOM_LAYOUT_ABCD = 7, 371 372 //DUNGEON_LAYOUT_RIGHT = 0x1, 373 //DUNGEON_LAYOUT_BOTTOM = 0x2, 374}; 375 376enum ap_link_state { 377 LINK_STATE_GROUND = 0x0, 378 LINK_STATE_FALLING_HOLE = 0x1, 379 LINK_STATE_SWIMMING = 0x4, 380 LINK_STATE_FALLING_LEDGE = 0x11, 381 LINK_STATE_RECVING_ITEM = 0x15, 382 LINK_STATE_RECVING_ITEM2 = 0x17, // XXX delete this? 383 LINK_STATE_HOLDING_BIG_ROCK = 0x18, 384}; 385/* Link State 386 0x0 - ground state 387 0x1 - falling into a hole 388 0x2 - recoil from hitting wall / enemies 389 0x3 - spin attacking 390 0x4 - swimming, or falling into water 391 0x5 - Turtle Rock platforms 392 0x6 recoil again (other movement) 393 0x7 - hit by Agahnims bug zapper 394 0x8 - using ether medallion 395 0x9 - using bombos medallion 396 0xA - using quake medallion 397 0xB - ??? 398 0xC - ??? 399 0xD - ??? 400 0xE - ??? 401 0xF - ??? 402 0x10 - ??? 403 0x11 - falling off a ledge 404 0x12 - used when coming out of a dash by pressing a direction other than the dash direction 405 0x13 - hookshot 406 0x14 - magic mirror 407 0x15 - holding up an item 408 0x16 - asleep in his bed 409 0x17 - permabunny 410 0x18 - stuck holding a heavy rock 411 0x19 - Receiving Ether Medallion 412 0x1A - Receiving Bombos Medallion 413 0x1B - Opening Desert Palace 414 0x1C - temporary bunny 415 0x1D - Rolling back from Gargoyle gate or PullForRupees object 416 0x1E - The actual spin attack motion. 417*/ 418 419#define SPRITE_ATTR_LIST \ 420 X(ENMY) /* Enemy, can hurt */ \ 421 X(BLKS) /* Blocked center 2x2 square */ \ 422 X(BLKF) /* Blocked full sprite size */ \ 423 X(SWCH) /* Button / state-changer */ \ 424 X(ITEM) /* Pick-up */ \ 425 X(TALK) /* Talk for progression item */ \ 426 X(FLLW) /* Thing that can follow you */ \ 427 X(NODE) /* Worth making a node for */ \ 428 X(SUBT) /* Has subtype flags */ \ 429 X(NVUL) /* Invulnerable, or at least not worth fighting */ \ 430 X(VBOW) /* Only vunerable to the Bow */ \ 431 432enum { 433#define X(d) CONCAT(_SPRITE_ATTR_INDEX_, d), 434SPRITE_ATTR_LIST 435#undef X 436}; 437enum { 438#define X(d) CONCAT(SPRITE_ATTR_, d) = 1ul << CONCAT(_SPRITE_ATTR_INDEX_, d), 439SPRITE_ATTR_LIST 440#undef X 441}; 442 443#define N_SPRITES ((size_t) 16) 444extern struct ap_sprite { 445 uint8_t type; 446 uint16_t subtype; 447 uint8_t state; 448 uint8_t interaction; 449 int8_t hp; 450 uint8_t drop; 451 452 bool active; 453 454 struct xy tl; 455 struct xy br; 456 struct xy hitbox_tl; 457 struct xy hitbox_br; 458 uint16_t attrs; 459} ap_sprites[N_SPRITES]; 460extern bool ap_sprites_changed; 461 462extern struct ap_pushblock { 463 struct xy tl; 464} ap_pushblocks[16]; 465 466void ap_sprites_update(); 467 468extern const char * const ap_sprite_attr_names[]; 469const char * ap_sprite_attr_name(uint16_t attr); 470void ap_sprites_print(); 471uint16_t ap_sprite_attrs_for_type(uint8_t type, uint16_t subtype, uint16_t dungeon_room); 472 473static const uint16_t ap_sprite_attrs[256] = { 474 [0x00] = SPRITE_ATTR_ENMY, // Raven 475 [0x01] = SPRITE_ATTR_ENMY, // Vulture 476 [0x02] = SPRITE_ATTR_ENMY, // Flying Stalfos Head 477 [0x03] = 0, // Unused (Don't use it, the sprite's ASM pointer is invalid. It will certainly crash the game.) 478 [0x04] = SPRITE_ATTR_SWCH, // Good Switch being pulled 479 [0x05] = SPRITE_ATTR_SWCH, // Some other sort of switch being pulled, but from above? 480 [0x06] = 0, // Bad Switch 481 [0x07] = SPRITE_ATTR_SWCH, // switch again (facing up) 482 [0x08] = SPRITE_ATTR_ENMY, // Octorock 483 [0x09] = SPRITE_ATTR_ENMY, // Giant Moldorm (boss) 484 [0x0A] = SPRITE_ATTR_ENMY, // Four Shooter Octorock 485 [0x0B] = 0, // Chicken / Chicken Transformed into Lady 486 [0x0C] = SPRITE_ATTR_ENMY, // Octorock 487 [0x0D] = SPRITE_ATTR_ENMY | SPRITE_ATTR_NVUL, // Normal Buzzblob / Morphed Buzzblob (tra la la... look for Sahashrala) 488 [0x0E] = SPRITE_ATTR_ENMY, // Plants with big mouths 489 [0x0F] = SPRITE_ATTR_ENMY, // Octobaloon (Probably the thing that explodes into 10 others) 490 491 [0x10] = SPRITE_ATTR_ENMY, // Small things from the exploder (exploder? wtf is that?) 492 [0x11] = SPRITE_ATTR_ENMY, // One Eyed Giants (bomb throwers) aka Hinox 493 [0x12] = SPRITE_ATTR_ENMY, // Moblin Spear Throwers 494 [0x13] = SPRITE_ATTR_ENMY, // Helmasaur? 495 [0x14] = SPRITE_ATTR_BLKF, // Gargoyles Domain Gate 496 [0x15] = SPRITE_ATTR_ENMY, // Fire Faery 497 [0x16] = SPRITE_ATTR_SUBT, // Sahashrala / Aginah, sage of the desert 498 [0x17] = SPRITE_ATTR_ENMY, // Water Bubbles? 499 [0x18] = SPRITE_ATTR_ENMY, // Moldorm 500 [0x19] = SPRITE_ATTR_ENMY, // Poe 501 [0x1A] = 0, // Dwarf, Mallet, and the shrapnel from it hitting 502 [0x1B] = 0, // Arrow in wall? 503 [0x1C] = SPRITE_ATTR_BLKS, // Moveable Statue 504 [0x1D] = SPRITE_ATTR_BLKF, // Weathervane 505 [0x1E] = SPRITE_ATTR_BLKF | SPRITE_ATTR_SWCH, // Crystal Switch 506 [0x1F] = SPRITE_ATTR_BLKF, // Sick Kid with Bug Catching Net 507 508 [0x20] = SPRITE_ATTR_ENMY, // Bomb Slugs 509 [0x21] = SPRITE_ATTR_SWCH, // Push Switch (like in Swamp Palace) 510 [0x22] = SPRITE_ATTR_ENMY, // Darkworld Snakebasket 511 [0x23] = SPRITE_ATTR_SWCH, // Red Onoff 512 [0x24] = SPRITE_ATTR_SWCH, // Blue Onoff 513 [0x25] = SPRITE_ATTR_BLKF, // Tree you can talk to? 514 [0x26] = SPRITE_ATTR_ENMY, // Charging Octopi? 515 [0x27] = SPRITE_ATTR_ENMY, // Dead Rocks? (Gorons bleh) 516 [0x28] = SPRITE_ATTR_BLKF, // Shrub Guy who talks about Triforce / Other storytellers 517 [0x29] = SPRITE_ATTR_BLKS, // Blind Hideout attendant, Lost woods 518 [0x2A] = SPRITE_ATTR_BLKS, // Sweeping Lady 519 [0x2B] = SPRITE_ATTR_BLKS, // Bum under the bridge + smoke and other effects like the fire 520 [0x2C] = SPRITE_ATTR_BLKF, // Lumberjack Bros. 521 [0x2D] = 0, // Telepathic stones? 522 [0x2E] = 0, // Flute Boys Notes 523 [0x2F] = SPRITE_ATTR_BLKS, // Heart Piece Race guy and girl 524 [0x30] = SPRITE_ATTR_BLKF, // Person? (HM name) 525 [0x31] = SPRITE_ATTR_BLKS, // Fortune Teller / Dwarf swordsmith 526 [0x32] = SPRITE_ATTR_BLKF, // ??? (something with a turning head) 527 [0x33] = 0, // Pull the wall for rupees 528 [0x34] = SPRITE_ATTR_BLKF, // ScaredGirl2 (HM name) 529 [0x35] = SPRITE_ATTR_BLKS, // Innkeeper 530 [0x36] = SPRITE_ATTR_BLKF, // Witch / Cane of Byrna? 531 [0x37] = 0, // Waterfall 532 [0x38] = SPRITE_ATTR_BLKF, // Arrow Target (e.g. Big Eye in Dark Palace) 533 [0x39] = SPRITE_ATTR_BLKF, // Middle Aged Guy in the desert 534 [0x3A] = 0, // Magic Powder Bat /The Lightning Bolt the bat hurls at you. 535 [0x3B] = 0, // Dash Item / such as Book of Mudora, keys 536 [0x3C] = SPRITE_ATTR_BLKS, // Kid in village near the trough 537 [0x3D] = SPRITE_ATTR_BLKS, // Signs? Chicken lady also showed up / Scared ladies outside houses. 538 [0x3E] = SPRITE_ATTR_ENMY, // Rock Rupee Crabs 539 [0x3F] = SPRITE_ATTR_ENMY, // Tutorial Soldiers from beginning of game 540 541 [0x40] = SPRITE_ATTR_ENMY /*| SPRITE_ATTR_BLKF */, // Hyrule Castle Barrier to Agahnims Tower 542 [0x41] = SPRITE_ATTR_ENMY, // Soldier 543 [0x42] = SPRITE_ATTR_ENMY, // Blue Soldier 544 [0x43] = SPRITE_ATTR_ENMY, // Red Spear Soldier 545 [0x44] = SPRITE_ATTR_ENMY, // Crazy Blue Killer Soldiers 546 [0x45] = SPRITE_ATTR_ENMY, // Crazy Red Spear Soldiers (And green ones in the village) 547 [0x46] = SPRITE_ATTR_ENMY, // Blue Archer Soldiers 548 [0x47] = SPRITE_ATTR_ENMY, // Green Archer Soldiers (in the bushes) 549 [0x48] = SPRITE_ATTR_ENMY, // Red Spear Soldiers (in special armor) 550 [0x49] = SPRITE_ATTR_ENMY, // Red Spear Soldiers (in the bushes) 551 [0x4A] = SPRITE_ATTR_ENMY, // Red Bomb Soldiers 552 [0x4B] = SPRITE_ATTR_ENMY, // Green Soldier Recruits (the idiots) 553 [0x4C] = SPRITE_ATTR_ENMY, // Sand Monsters 554 [0x4D] = SPRITE_ATTR_ENMY, // Flailing Bunnies on the ground 555 [0x4E] = SPRITE_ATTR_ENMY, // Snakebasket 556 [0x4F] = SPRITE_ATTR_ENMY, // Blobs? 557 558 [0x50] = SPRITE_ATTR_ENMY | SPRITE_ATTR_NVUL, // Metal Balls (in Eastern Palace) 559 [0x51] = SPRITE_ATTR_ENMY, // Armos 560 [0x52] = 0, // Giant Zora 561 [0x53] = SPRITE_ATTR_ENMY | SPRITE_ATTR_VBOW, // Armos Knights Boss 562 [0x54] = SPRITE_ATTR_ENMY, // Lanmolas boss 563 [0x55] = SPRITE_ATTR_ENMY, // Zora / Fireballs (including the blue Agahnim fireballs) 564 [0x56] = SPRITE_ATTR_ENMY, // Walking Zora 565 [0x57] = SPRITE_ATTR_BLKF, // Desert Palace Barriers 566 [0x58] = SPRITE_ATTR_ENMY, // Sandcrab 567 [0x59] = SPRITE_ATTR_ENMY, // Birds (boids) 568 [0x5A] = SPRITE_ATTR_ENMY, // Squirrels 569 [0x5B] = SPRITE_ATTR_ENMY, // Energy Balls (that crawl along the wall) 570 [0x5C] = SPRITE_ATTR_ENMY, // Wall crawling fireballs 571 [0x5D] = SPRITE_ATTR_ENMY, // Roller (vertical moving) 572 [0x5E] = SPRITE_ATTR_ENMY, // Roller (vertical moving) 573 [0x5F] = SPRITE_ATTR_ENMY, // Roller 574 575 [0x60] = SPRITE_ATTR_ENMY, // Roller (horizontal moving) 576 [0x61] = SPRITE_ATTR_BLKF, // Statue Sentry 577 [0x62] = SPRITE_ATTR_BLKF, // Master Sword plus pendants and beams of light 578 [0x63] = 0, // Sand Lion Pit 579 [0x64] = SPRITE_ATTR_ENMY, // Sand Lion 580 [0x65] = 0, // Shooting Gallery guy 581 [0x66] = SPRITE_ATTR_BLKF, // Moving cannon ball shooters 582 [0x67] = SPRITE_ATTR_BLKF, // Moving cannon ball shooters 583 [0x68] = SPRITE_ATTR_BLKF, // Moving cannon ball shooters 584 [0x69] = SPRITE_ATTR_BLKF, // Moving cannon ball shooters 585 [0x6A] = SPRITE_ATTR_ENMY, // Ball N' Chain Trooper 586 [0x6B] = SPRITE_ATTR_ENMY, // Cannon Ball Shooting Soldier (unused in original = WTF?) 587 [0x6C] = 0, // Warp Vortex created by Magic Mirror 588 [0x6D] = SPRITE_ATTR_ENMY, // Mouse 589 [0x6E] = SPRITE_ATTR_ENMY, // Snakes (forgot the Zelda 1 name) 590 [0x6F] = SPRITE_ATTR_ENMY, // Bats / Also one eyed bats 591 592 [0x70] = SPRITE_ATTR_ENMY, // Splitting Fireballs from Helmasaur King 593 [0x71] = SPRITE_ATTR_SWCH, // Leever 594 [0x72] = 0, // Activator for the ponds (where you throw in items) 595 [0x73] = SPRITE_ATTR_SUBT, // Links Uncle / Sage / Barrier that opens in the sanctuary 596 [0x74] = 0, // Red Hat Boy who runs from you 597 [0x75] = SPRITE_ATTR_TALK | SPRITE_ATTR_BLKS, // Bottle Vendor 598 [0x76] = SPRITE_ATTR_BLKF | SPRITE_ATTR_FLLW, // Princess Zelda 599 [0x77] = SPRITE_ATTR_ENMY, // Also Fire Faeries (seems like a different variety) 600 [0x78] = SPRITE_ATTR_BLKS, // Village Elder 601 [0x79] = 0, // Good bee / normal bee 602 [0x7A] = SPRITE_ATTR_ENMY /*| SPRITE_ATTR_NVUL*/, // Agahnim 603 [0x7B] = SPRITE_ATTR_ENMY, // Agahnim energy blasts (not the duds) 604 [0x7C] = 0, // Boos? As in the Boos from SM3/SMW? Thats crazy talk! 605 [0x7D] = 0, // 32*32 Pixel Yellow Spike Traps 606 [0x7E] = SPRITE_ATTR_ENMY, // Swinging Fireball Chains 607 [0x7F] = SPRITE_ATTR_ENMY, // Swinging Fireball Chains 608 609 [0x80] = SPRITE_ATTR_ENMY, // Wandering Fireball Chains 610 [0x81] = SPRITE_ATTR_ENMY, // Waterhoppers 611 [0x82] = SPRITE_ATTR_ENMY, // Swirling Fire Faeries (Eastern Palace) 612 [0x83] = SPRITE_ATTR_ENMY, // Green Rocklops (igor, eyegor) 613 [0x84] = SPRITE_ATTR_ENMY | SPRITE_ATTR_VBOW, // Red Rocklops 614 [0x85] = SPRITE_ATTR_ENMY, // Yellow Stalfos (drops to the ground, dislodges head) 615 [0x86] = SPRITE_ATTR_ENMY, // Fire Breathing Dinos? 616 [0x87] = SPRITE_ATTR_ENMY, // Flames 617 [0x88] = SPRITE_ATTR_ENMY, // Mothula 618 [0x89] = SPRITE_ATTR_ENMY, // Mothulas beam 619 [0x8A] = SPRITE_ATTR_ENMY, // Key holes? Spikes that move 620 [0x8B] = SPRITE_ATTR_ENMY, // Gibdos 621 [0x8C] = SPRITE_ATTR_ENMY, // Arghuss 622 [0x8D] = SPRITE_ATTR_ENMY, // Arghuss spawn 623 [0x8E] = SPRITE_ATTR_ENMY, // Chair Turtles you kill with hammers 624 [0x8F] = SPRITE_ATTR_ENMY, // Blobs / Crazy Blobs via Magic powder or Quake Medallion 625 626 [0x90] = SPRITE_ATTR_ENMY, // Grabber things? 627 [0x91] = SPRITE_ATTR_ENMY, // Stalfos Knight 628 [0x92] = SPRITE_ATTR_ENMY, // Helmasaur King 629 [0x93] = SPRITE_ATTR_ENMY, // Bungie / Red Orb? (according to HM) 630 [0x94] = SPRITE_ATTR_ENMY, // Swimmers 631 [0x95] = SPRITE_ATTR_ENMY, // Eye laser 632 [0x96] = SPRITE_ATTR_ENMY, // Eye laser 633 [0x97] = SPRITE_ATTR_ENMY, // Eye laser 634 [0x98] = SPRITE_ATTR_ENMY, // Eye laser 635 [0x99] = SPRITE_ATTR_ENMY, // Penguin 636 [0x9A] = SPRITE_ATTR_ENMY, // Moving Water Bubble (only in Swamp Palace) 637 [0x9B] = SPRITE_ATTR_ENMY, // Wizzrobes 638 [0x9C] = SPRITE_ATTR_ENMY, // Black sperm looking things 639 [0x9D] = SPRITE_ATTR_ENMY, // Black sperm looking things 640 [0x9E] = 0, // The ostrich animal w/ the flute boy? 641 [0x9F] = 0, //SPRITE_ATTR_ITEM | SPRITE_ATTR_NODE, // Flute 642 643 [0xA0] = 0, // Birds w/ the flute boy? 644 [0xA1] = SPRITE_ATTR_ENMY, // Ice man 645 [0xA2] = SPRITE_ATTR_ENMY, // Kholdstare 646 [0xA3] = SPRITE_ATTR_ENMY, // Another part of Kholdstare 647 [0xA4] = SPRITE_ATTR_ENMY, // Ice balls from above 648 [0xA5] = SPRITE_ATTR_ENMY, // Blue Horse Knight, and Lynel Fireballs 649 [0xA6] = SPRITE_ATTR_ENMY, // Red Horse Knight 650 [0xA7] = SPRITE_ATTR_ENMY, // Red Stalfos Skeleton 651 [0xA8] = SPRITE_ATTR_ENMY, // Bomber Flying Creatures from Darkworld 652 [0xA9] = SPRITE_ATTR_ENMY, // Bomber Flying Creatures from Darkworld 653 [0xAA] = SPRITE_ATTR_ENMY, // Like Like (O_o yikes) 654 [0xAB] = 0, // Maiden (as in, the maidens in the crystals after you beat a boss) 655 [0xAC] = 0, // Apples 656 [0xAD] = SPRITE_ATTR_FLLW, // Old Man on the Mountain 657 [0xAE] = 0, // Down Pipe 658 [0xAF] = 0, // Up Pipe 659 660 [0xB0] = 0, // Right Pipe 661 [0xB1] = 0, // Left Pipe 662 [0xB2] = 0, // Good bee again? 663 [0xB3] = 0, // Hylian Inscription (near Desert Palace). Also near Master Sword 664 [0xB4] = SPRITE_ATTR_FLLW, // Thiefs chest (not the one that follows you, the one that you grab from the DW smithy house) 665 [0xB5] = SPRITE_ATTR_BLKF | SPRITE_ATTR_TALK, // Bomb Salesman (elephant looking guy) 666 [0xB6] = SPRITE_ATTR_FLLW, // Kiki the monkey? 667 [0xB7] = SPRITE_ATTR_FLLW, // Maiden following you in Blind Dungeon 668 [0xB8] = 0, // Monologue Testing Sprite (Debug Artifact) 669 [0xB9] = 0, // Feuding Friends on Death Mountain 670 [0xBA] = 0, // Whirlpool 671 // subtype2: 0x00 salesman; 0x0c bombs; 0x0a one heart; 0x07 red potion 672 [0xBB] = SPRITE_ATTR_SUBT | SPRITE_ATTR_BLKF | SPRITE_ATTR_TALK, // Salesman / chestgame guy / 300 rupee giver guy / Chest game thief / Item for sale 673 [0xBC] = SPRITE_ATTR_BLKF, // Drunk in the inn 674 [0xBD] = SPRITE_ATTR_ENMY, // Vitreous (the large eyeball) 675 [0xBE] = SPRITE_ATTR_ENMY, // Vitreous' smaller eyeballs 676 [0xBF] = SPRITE_ATTR_ENMY, // Vitreous' lightning blast 677 678 [0xC0] = 0, // Monster in Lake of Ill Omen / Quake Medallion 679 [0xC1] = SPRITE_ATTR_ENMY, // Agahnim teleporting Zelda to dark world 680 [0xC2] = SPRITE_ATTR_ENMY, // Boulders 681 [0xC3] = SPRITE_ATTR_ENMY, // Symbions 2 (vulnerable part) 682 [0xC4] = SPRITE_ATTR_ENMY, // Thief 683 [0xC5] = SPRITE_ATTR_ENMY, // Evil Fireball Spitters (THE FACES!!!) 684 [0xC6] = SPRITE_ATTR_ENMY, // Four Way Fireball Spitters (spit when you use your sword) 685 [0xC7] = SPRITE_ATTR_ENMY, // Fuzzy Stack 686 [0xC8] = SPRITE_ATTR_TALK, // Big Healing Faeries / Faerie Dust 687 [0xC9] = SPRITE_ATTR_ENMY, // Ganons Firebat (HM also says Tektite?) 688 [0xCA] = SPRITE_ATTR_ENMY, // Chain Chomp 689 [0xCB] = SPRITE_ATTR_ENMY, // Trinexx 690 [0xCC] = SPRITE_ATTR_ENMY, // Another Part of Trinexx 691 [0xCD] = SPRITE_ATTR_ENMY, // Another Part of Trinexx (again) 692 [0xCE] = SPRITE_ATTR_ENMY, // Blind the Thief 693 [0xCF] = SPRITE_ATTR_ENMY, // Swamp Worms (from Swamp of Evil) 694 695 [0xD0] = SPRITE_ATTR_ENMY, // Lynel (centaur like creature) 696 [0xD1] = SPRITE_ATTR_ENMY, // A yellow hunter 697 [0xD2] = SPRITE_ATTR_ENMY, // Flopping fish 698 [0xD3] = SPRITE_ATTR_ENMY, // Animated Skulls Creatures 699 [0xD4] = SPRITE_ATTR_ENMY, // Landmines 700 [0xD5] = SPRITE_ATTR_BLKF | SPRITE_ATTR_TALK, // Digging Game Proprietor 701 [0xD6] = SPRITE_ATTR_ENMY, // Ganon! OMG 702 [0xD7] = SPRITE_ATTR_ENMY, // Copy of Ganon, except invincible? 703 [0xD8] = SPRITE_ATTR_ITEM, // Heart refill 704 [0xD9] = SPRITE_ATTR_ITEM, // Green Rupee 705 [0xDA] = SPRITE_ATTR_ITEM, // Blue Rupee 706 [0xDB] = SPRITE_ATTR_ITEM, // Red Rupee 707 [0xDC] = SPRITE_ATTR_ITEM, // Bomb Refill (1) 708 [0xDD] = SPRITE_ATTR_ITEM, // Bomb Refill (4) 709 [0xDE] = SPRITE_ATTR_ITEM, // Bomb Refill (8) 710 [0xDF] = SPRITE_ATTR_ITEM, // Small Magic Refill 711 712 [0xE0] = SPRITE_ATTR_ITEM, // Full Magic Refill 713 [0xE1] = SPRITE_ATTR_ITEM, // Arrow Refill (5) 714 [0xE2] = SPRITE_ATTR_ITEM, // Arrow Refill (10) 715 [0xE3] = SPRITE_ATTR_ITEM, // Faerie 716 [0xE4] = SPRITE_ATTR_ITEM | SPRITE_ATTR_NODE, // Key 717 [0xE5] = SPRITE_ATTR_ITEM | SPRITE_ATTR_NODE, // Big Key 718 [0xE6] = SPRITE_ATTR_ITEM | SPRITE_ATTR_NODE, // Red Shield (after dropped by pickit) 719 [0xE7] = SPRITE_ATTR_ITEM | SPRITE_ATTR_NODE, // Mushroom 720 [0xE8] = 0, // Fake Master Sword 721 [0xE9] = 0, // Magic Shop dude / His items, including the magic powder 722 [0xEA] = SPRITE_ATTR_ITEM | SPRITE_ATTR_NODE, // Full Heart Container 723 [0xEB] = SPRITE_ATTR_ITEM | SPRITE_ATTR_NODE, // Quarter Heart Container 724 [0xEC] = 0, // Bushes or pot, picked up/thrown 725 [0xED] = 0, // Cane of Somaria Platform 726 [0xEE] = SPRITE_ATTR_BLKF, // Movable Mantle (in Hyrule Castle) 727 [0xEF] = 0, // Cane of Somaria Platform (same as 0xED but this index is not used) 728 729 [0xF0] = 0, // Cane of Somaria Platform (same as 0xED but this index is not used) 730 [0xF1] = 0, // Cane of Somaria Platform (same as 0xED but this index is not used) 731 [0xF2] = SPRITE_ATTR_BLKF, // Medallion Tablet 732}; 733 734struct ap_sprite_subtype { 735 uint8_t type; 736 uint16_t subtype; 737 uint16_t attrs; 738 uint16_t only_dungeon_room; 739}; 740 741static const struct ap_sprite_subtype ap_sprite_subtypes[] = { 742 // Sahashrala 743 { .type = 0x16, .subtype = 0x0000, .attrs = SPRITE_ATTR_BLKF | SPRITE_ATTR_TALK | SPRITE_ATTR_NODE }, 744 // Desert Sage 745 { .type = 0x16, .subtype = 0x0100, .attrs = SPRITE_ATTR_BLKF }, 746 747 // Barrier in Sanctuary 748 { .type = 0x73, .subtype = 0x0000, .only_dungeon_room = 0x12, .attrs = SPRITE_ATTR_BLKF }, 749 { .type = 0x73, .subtype = 0x0100, .only_dungeon_room = 0x12, .attrs = SPRITE_ATTR_BLKF }, 750 // Link's Uncle 751 { .type = 0x73, .subtype = 0x0100, .only_dungeon_room = 0x55, .attrs = SPRITE_ATTR_TALK | SPRITE_ATTR_NODE}, 752 // Guy next to Zelda 753 { .type = 0x73, .subtype = 0x0200, .attrs = SPRITE_ATTR_BLKS }, 754 755 // Mini Moldorm Cave Guy 756 { .type = 0xBB, .subtype = 0x0200, .only_dungeon_room = 0x123, .attrs = SPRITE_ATTR_NODE | SPRITE_ATTR_TALK }, 757}; 758 759#define DOOR_ATTR_LIST \ 760 X(NORM) /* Normal; just to differentiate unknown vs. unremarkable */ \ 761 X(BOMB) /* Bombable */ \ 762 X(SKEY) /* Openable with small key */ \ 763 X(BKEY) /* Openable with big key */ \ 764 X(SLSH) /* Openable with sword */ \ 765 X(TRAP) /* Becomes a trap door */ \ 766 X(BLOK) /* Not actually a door */ \ 767 768enum { 769#define X(d) CONCAT(_DOOR_ATTR_INDEX_, d), 770DOOR_ATTR_LIST 771#undef X 772}; 773enum { 774#define X(d) CONCAT(DOOR_ATTR_, d) = 1ul << CONCAT(_DOOR_ATTR_INDEX_, d), 775DOOR_ATTR_LIST 776#undef X 777}; 778 779const char * ap_door_attr_name(uint16_t idx); 780 781static const uint16_t ap_door_attrs[256] = { 782 [0x00] = DOOR_ATTR_NORM, 783 [0x01] = DOOR_ATTR_NORM, 784 [0x02] = DOOR_ATTR_NORM, 785 [0x04] = DOOR_ATTR_NORM, 786 [0x05] = DOOR_ATTR_NORM, 787 [0x06] = DOOR_ATTR_NORM, 788 [0x07] = DOOR_ATTR_NORM, 789 [0x08] = DOOR_ATTR_NORM, 790 [0x09] = DOOR_ATTR_NORM, 791 [0x0A] = DOOR_ATTR_NORM, 792 [0x0B] = DOOR_ATTR_NORM, 793 [0x0C] = DOOR_ATTR_TRAP, 794 [0x0D] = DOOR_ATTR_BLOK, // ? Only in Turtle rock, "invisible" 795 [0x0E] = DOOR_ATTR_SKEY, 796 [0x0F] = DOOR_ATTR_BKEY, 797 [0x10] = DOOR_ATTR_SKEY, 798 [0x11] = DOOR_ATTR_SKEY, 799 [0x13] = DOOR_ATTR_SKEY, 800 [0x14] = DOOR_ATTR_BOMB, // Confirmed by ASM 801 [0x15] = DOOR_ATTR_BOMB, // Confirmed by ASM 802 [0x17] = DOOR_ATTR_BOMB, // Confirmed by ASM 803 [0x18] = DOOR_ATTR_NORM, 804 [0x19] = DOOR_ATTR_SLSH, 805 [0x1B] = DOOR_ATTR_TRAP, // ? 'right side only'? 806 [0x1C] = DOOR_ATTR_TRAP, // ? 'left side only'? 807 [0x20] = DOOR_ATTR_NORM, 808 [0x22] = DOOR_ATTR_TRAP, // ? 'left side only'? 809 [0x23] = DOOR_ATTR_NORM, 810 [0x24] = DOOR_ATTR_TRAP, // ? one side trap? 811 [0x25] = DOOR_ATTR_TRAP, // ? one side trap? 812 [0x80] = DOOR_ATTR_NORM, // Fake; stairs 0x0E 813 [0x81] = DOOR_ATTR_NORM, // Fake; stairs 0x0F 814}; 815 816// module_index 817// 0x00 Nintendo presents screen + Title screen 818// 0x01 Player select screen 819// 0x02 Copy Player Mode 820// 0x03 Erase Player Mode 821// 0x04 Register your name screen 822// 0x05 Loading Game Mode 823// 0x06 Pre House/Dungeon Mode 824// 0x07 In house/dungeon 825// 0x08 Pre Overworld Mode 826// 0x09 In OW 827// 0x0A Pre Overworld Mode (special overworld) 828// 0x0B Overworld Mode (special overworld) 829// 0x0C Unused? 830// 0x0D Blank Screen 831// 0x0E Text Mode/Item Screen/Map 832// 0x0F Closing Spotlight 833// 0x10 Opening Spotlight 834// 0x11 Happens when you fall into a hole from the OW. 835// 0x12 Death Mode 836// 0x13 Boss Victory Mode (refills stats) 837// 0x14 Cutscene in title screen (history sequence) 838// 0x15 Module for Magic Mirror 839// 0x16 Module for refilling stats after boss. 840// 0x17 Restart mode (save and quit) 841// 0x18 Ganon exits from Agahnim's body. Chase Mode. 842// 0x19 Triforce Room scene 843// 0x1A End sequence 844// 0x1B Screen to select where to start from (House, sanctuary, etc.) 845 846// current_item (guessing from inventory layout, * are confirmed) 847// 0x01 Bow 848// 0x02 Boomerang 849// 0x03 Hookshot 850// 0x04 Bombs * 851// 0x05 Powder * 852// 0x06 Fire rod 853// 0x07 Ice rod 854// 0x08 Bombos 855// 0x09 Ether 856// 0x0a Quake 857// 0x0b Lamp 858// 0x0c Hammer * 859// 0x0d Flute * 860// 0x0e Net 861// 0x0f Book of Mudora * 862// 0x10 Bottles? 863// 0x11 Red cane 864// 0x12 Blue cane 865// 0x13 Magic cape 866// 0x14 Mirror * 867 868#define INVENTORY_LIST \ 869 X(0x01, BOW) \ 870 X(0x02, BOOMERANG) \ 871 X(0x03, HOOKSHOT) \ 872 X(0x04, BOMBS) \ 873 X(0x05, POWDER) \ 874 X(0x06, FIRE_ROD) \ 875 X(0x07, ICE_ROD) \ 876 X(0x08, BOMBOS) \ 877 X(0x09, ETHER) \ 878 X(0x0a, QUAKE) \ 879 X(0x0b, LAMP) \ 880 X(0x0c, HAMMER) \ 881 X(0x0d, FLUTE) \ 882 X(0x0e, NET) \ 883 X(0x0f, BOOK) \ 884 /*X(0x10, BOTTLES) -- this is just boolean 'has bottles' */ \ 885 X(0x11, RED_CANE) \ 886 X(0x12, BLUE_CANE) \ 887 X(0x13, MAGIC_CAPE) \ 888 X(0x14, MIRROR) \ 889 X(0x15, GLOVES) \ 890 X(0x16, BOOTS) \ 891 X(0x17, FLIPPERS) \ 892 X(0x18, MOON_PEARL) \ 893 X(0x1A, SWORD) \ 894 X(0x1B, SHIELD) \ 895 X(0x1C, ARMOR) \ 896 X(0x1D, BOTTLE) /* 4 bottles 0x1D, 0x1E, 0x1F, 0x20 */\ 897 898enum ap_inventory { 899 _INVENTORY_MIN = 1, 900#define X(i, n) CONCAT(INVENTORY_, n) = i, 901INVENTORY_LIST 902#undef X 903 _INVENTORY_MAX 904}; 905 906extern const char * const ap_inventory_names[]; 907 908static const uint16_t ap_ancillia_attrs[256] = { 909 // Crystal / Pendant 910 [0x29] = SPRITE_ATTR_NODE | SPRITE_ATTR_ITEM, 911}; 912 913#define N_ANCILLIA ((size_t) 10) 914extern struct ap_ancillia { 915 uint8_t type; 916 uint8_t bf0; // 0xBF0 917 struct xy tl; 918 struct xy br; 919 struct xy subpixel; 920 struct xy velocity; 921 uint16_t attrs; 922} ap_ancillia[N_ANCILLIA]; 923 924void ap_ancillia_update(); 925void ap_ancillia_print(); 926 927enum ap_quadrant { 928 QUAD_ALL = 0xF, 929 QUAD_A = 0x1, 930 QUAD_B = 0x2, 931 QUAD_C = 0x4, 932 QUAD_D = 0x8, 933}; 934 935const char * ap_quadrant_print(uint8_t quadmask); 936 937#define ROOM_ACTION_LIST \ 938 X(NONE) \ 939 X(CLEAR_LEVEL) \ 940 X(CLEAR_QUADRANT) \ 941 X(CLEAR_ROOM) \ 942 X(KILL_ENEMY) \ 943 X(LIGHT_TORCHES) \ 944 X(MOVE_BLOCK) \ 945 X(OPEN_CHEST) \ 946 X(PULL_LEVER) \ 947 X(SWITCH_HOLD) \ 948 X(SWITCH_TOGGLE) \ 949 X(TURN_OFF_WATER) \ 950 X(TURN_ON_WATER) \ 951 952#define ROOM_RESULT_LIST \ 953 X(NONE) \ 954 X(CHEST) \ 955 X(CLEAR_LEVEL) \ 956 X(CRASH) \ 957 X(HOLES) \ 958 X(MOVE_BLOCK) \ 959 X(OPEN_DOORS) \ 960 X(OPEN_WALL) \ 961 X(WATERGATE) \ 962 963enum ap_room_action { 964#define X(n) CONCAT(ROOM_ACTION_, n), 965ROOM_ACTION_LIST 966#undef X 967}; 968 969enum ap_room_result { 970#define X(n) CONCAT(ROOM_RESULT_, n), 971ROOM_RESULT_LIST 972#undef X 973}; 974 975static const struct ap_room_tag { 976 uint8_t quadmask; 977 enum ap_room_action action; 978 enum ap_room_result result; 979 bool unsure; 980} ap_room_tags[0x40] = { 981 [0x00] = { .quadmask = 0, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_NONE }, 982 983 [0x01] = { .quadmask = QUAD_A, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_OPEN_DOORS }, 984 [0x02] = { .quadmask = QUAD_B, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_OPEN_DOORS }, 985 [0x03] = { .quadmask = QUAD_C, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_OPEN_DOORS }, 986 [0x04] = { .quadmask = QUAD_D, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_OPEN_DOORS }, 987 [0x05] = { .quadmask = QUAD_A | QUAD_C, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_OPEN_DOORS }, 988 [0x06] = { .quadmask = QUAD_B | QUAD_D, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_OPEN_DOORS }, 989 [0x07] = { .quadmask = QUAD_A | QUAD_B, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_OPEN_DOORS }, 990 [0x08] = { .quadmask = QUAD_C | QUAD_D, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_OPEN_DOORS }, 991 [0x09] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_CLEAR_QUADRANT, .result = ROOM_RESULT_OPEN_DOORS, .unsure = true }, 992 [0x0A] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_CLEAR_ROOM, .result = ROOM_RESULT_OPEN_DOORS, .unsure = true }, 993 994 [0x0B] = { .quadmask = QUAD_A, .action = ROOM_ACTION_MOVE_BLOCK, .result = ROOM_RESULT_OPEN_DOORS }, 995 [0x0C] = { .quadmask = QUAD_B, .action = ROOM_ACTION_MOVE_BLOCK, .result = ROOM_RESULT_OPEN_DOORS }, 996 [0x0D] = { .quadmask = QUAD_C, .action = ROOM_ACTION_MOVE_BLOCK, .result = ROOM_RESULT_OPEN_DOORS }, 997 [0x0E] = { .quadmask = QUAD_D, .action = ROOM_ACTION_MOVE_BLOCK, .result = ROOM_RESULT_OPEN_DOORS }, 998 [0x0F] = { .quadmask = QUAD_A | QUAD_C, .action = ROOM_ACTION_MOVE_BLOCK, .result = ROOM_RESULT_OPEN_DOORS }, 999 [0x10] = { .quadmask = QUAD_B | QUAD_D, .action = ROOM_ACTION_MOVE_BLOCK, .result = ROOM_RESULT_OPEN_DOORS }, 1000 [0x11] = { .quadmask = QUAD_A | QUAD_B, .action = ROOM_ACTION_MOVE_BLOCK, .result = ROOM_RESULT_OPEN_DOORS }, 1001 [0x12] = { .quadmask = QUAD_C | QUAD_D, .action = ROOM_ACTION_MOVE_BLOCK, .result = ROOM_RESULT_OPEN_DOORS }, 1002 1003 [0x13] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_MOVE_BLOCK, .result = ROOM_RESULT_OPEN_DOORS, .unsure = true }, 1004 [0x14] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_PULL_LEVER, .result = ROOM_RESULT_OPEN_DOORS, .unsure = true }, 1005 [0x15] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_CLEAR_LEVEL, .result = ROOM_RESULT_OPEN_DOORS, }, // Boss room 1006 1007 [0x16] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_SWITCH_HOLD, .result = ROOM_RESULT_OPEN_DOORS }, 1008 [0x17] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_SWITCH_TOGGLE, .result = ROOM_RESULT_OPEN_DOORS }, 1009 1010 [0x18] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_TURN_OFF_WATER, .result = ROOM_RESULT_NONE, .unsure = true }, 1011 [0x19] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_TURN_ON_WATER, .result = ROOM_RESULT_NONE, .unsure = true }, 1012 [0x1A] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_WATERGATE }, // Overworld Dam 1013 [0x1B] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_WATERGATE, .unsure = true }, 1014 1015 [0x1C] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_OPEN_WALL, .unsure = true }, 1016 [0x1D] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_OPEN_WALL, .unsure = true }, 1017 [0x1E] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_CRASH, .unsure = true }, 1018 [0x1F] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_CRASH, .unsure = true }, 1019 1020 [0x20] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_SWITCH_TOGGLE, .result = ROOM_RESULT_OPEN_WALL, .unsure = true }, 1021 [0x21] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_HOLES, .unsure = true }, 1022 [0x22] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_OPEN_CHEST, .result = ROOM_RESULT_HOLES, .unsure = true }, 1023 [0x23] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_HOLES, .unsure = true }, 1024 [0x24] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_HOLES, .unsure = true }, 1025 1026 [0x25] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_CLEAR_LEVEL, }, // Boss room 1027 [0x26] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_MOVE_BLOCK, .unsure = true }, 1028 1029 [0x27] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_SWITCH_TOGGLE, .result = ROOM_RESULT_CHEST }, 1030 [0x28] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_PULL_LEVER, .result = ROOM_RESULT_OPEN_WALL, .unsure = true }, 1031 1032 [0x29] = { .quadmask = QUAD_A, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_CHEST }, 1033 [0x2A] = { .quadmask = QUAD_B, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_CHEST }, 1034 [0x2B] = { .quadmask = QUAD_C, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_CHEST }, 1035 [0x2C] = { .quadmask = QUAD_D, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_CHEST }, 1036 [0x2D] = { .quadmask = QUAD_A | QUAD_C, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_CHEST }, 1037 [0x2E] = { .quadmask = QUAD_B | QUAD_D, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_CHEST }, 1038 [0x2F] = { .quadmask = QUAD_A | QUAD_B, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_CHEST }, 1039 [0x30] = { .quadmask = QUAD_C | QUAD_D, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_CHEST }, 1040 [0x31] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_CLEAR_QUADRANT, .result = ROOM_RESULT_CHEST }, 1041 [0x32] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_CLEAR_ROOM, .result = ROOM_RESULT_CHEST }, 1042 1043 [0x33] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_LIGHT_TORCHES, .result = ROOM_RESULT_OPEN_DOORS, }, 1044 1045 [0x34] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_HOLES, .unsure = true }, 1046 [0x35] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_HOLES, .unsure = true }, 1047 [0x36] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_HOLES, .unsure = true }, 1048 [0x37] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_HOLES, .unsure = true }, 1049 [0x38] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_NONE, }, 1050 [0x39] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_HOLES, .unsure = true }, 1051 [0x3A] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_NONE, .result = ROOM_RESULT_HOLES, .unsure = true }, 1052 [0x3B] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_OPEN_CHEST, .result = ROOM_RESULT_HOLES, .unsure = true }, 1053 1054 [0x3C] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_MOVE_BLOCK, .result = ROOM_RESULT_CHEST, }, 1055 [0x3D] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_OPEN_DOORS, }, 1056 [0x3E] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_LIGHT_TORCHES, .result = ROOM_RESULT_CHEST, }, 1057 [0x3F] = { .quadmask = QUAD_ALL, .action = ROOM_ACTION_KILL_ENEMY, .result = ROOM_RESULT_NONE, .unsure = true}, 1058}; 1059 1060const char * ap_room_tag_print(const struct ap_room_tag * tag); 1061 1062#define DUNGEON_LIST \ 1063 X(SEWERS, "Sr") \ 1064 X(HYRULE_CASTLE, "HC") \ 1065 X(EASTERN_PALACE, "EP") \ 1066 X(DESERT_PALACE, "DP") \ 1067 X(AGAHANIMS_TOWER, "CT") /* AKA "hyrule castle 2" & "Castle Tower" */ \ 1068 X(SWAMP_PALACE, "SP") \ 1069 X(PALACE_OF_DARKNESS, "PoD") \ 1070 X(MISERY_MIRE, "MM") \ 1071 X(SKULL_WOODS, "SW") \ 1072 X(ICE_PALACE, "IP") \ 1073 X(TOWER_OF_HERA, "ToH") \ 1074 X(THEIVES_TOWN, "TT") /* AKA "gargoyle's domain" */ \ 1075 X(TURTLE_ROCK, "TR") \ 1076 X(GANONS_TOWER, "GT") \ 1077 1078enum ap_dungeon { 1079#define X(name, abbr) CONCAT(DUNGEON_, name), 1080DUNGEON_LIST 1081#undef X 1082 _DUNGEON_MAX 1083}; 1084 1085extern const char * const ap_dungeon_names[]; 1086extern const char * const ap_dungeon_abbrs[];