ap_snes.h1086 lines · 48.2 KB · raw
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 Agahnim’s 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, // Gargoyle’s 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 Boy’s 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 Agahnim’s 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, // Link’s 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? That’s 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, // Mothula’s 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, // Thief’s 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, // Ganon’s 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[];