jevsnes.git / third-party / c / patches / 0012-dam-push-block-not-a-hammer-peg.patch
0012-dam-push-block-not-a-hammer-peg.patch53 lines · 2.5 KB · raw
1diff --git a/third-party/c/zbanks-alttp/ap_map.c b/third-party/c/zbanks-alttp/ap_map.c
2index e481fe75..d5beb8a0 100644
3--- a/third-party/c/zbanks-alttp/ap_map.c
4+++ b/third-party/c/zbanks-alttp/ap_map.c
5@@ -338,6 +338,25 @@ ap_map_attr(struct xy xy)
6     return screen->attr_cache[y][x];
7 }
8 
9+// Carried patch (jev): raw tile ids are reused for different things in
10+// different rooms - ap_snes.h's own entry for 0x27 already notes this
11+// ("hammer peg (was also fence; remapped to 0x01)"). Dungeon room $010B
12+// (the Dam's block-puzzle room) reuses 0x27 for its push blocks, not a
13+// hammer peg: hammering does nothing to them, but upstream's flat,
14+// room-agnostic ap_tile_attrs[] has no way to say so, so ap_pathfind_local
15+// scored it "liftable" (cost 20, not a wall) and ap_follow_targets swung
16+// the hammer at it - Link stood there mashing Y forever, one pixel from a
17+// solid block. Evidence: research/zbanks-alttp.md, "The Dam Chest push
18+// block".
19+static uint16_t
20+ap_tile_attrs_here(uint8_t raw_tile)
21+{
22+    if (raw_tile == 0x27 && *ap_ram.dungeon_room == 0x010B) {
23+        return 0;
24+    }
25+    return ap_tile_attrs[raw_tile];
26+}
27+
28 static uint16_t
29 ap_link_tile_attr(struct xy link)
30 {
31@@ -812,11 +831,11 @@ ap_follow_targets(uint16_t * joypad, enum ap_inventory * equip_out)
32     uint8_t tile = ap_map_attr(next_xy);
33     if (tile == 0x50 && *ap_ram.inventory_sword > 0) {
34         JOYPAD_MASH(B, 0x04); // Sword
35-    } else if ((ap_tile_attrs[tile] & lift_mask) && *ap_ram.push_timer != 0x20) {
36+    } else if ((ap_tile_attrs_here(tile) & lift_mask) && *ap_ram.push_timer != 0x20) {
37         JOYPAD_MASH(A, 0x01); // Lift
38     } else if (*ap_ram.carrying_bit7) {
39         JOYPAD_MASH(A, 0x01);
40-    } else if ((ap_tile_attrs[tile] & TILE_ATTR_HMMR) && *ap_ram.inventory_hammer != 0) {
41+    } else if ((ap_tile_attrs_here(tile) & TILE_ATTR_HMMR) && *ap_ram.inventory_hammer != 0) {
42         if (*equip_out == INVENTORY_HAMMER) {
43             JOYPAD_MASH(Y, 0x1);
44         }
45@@ -1074,7 +1093,7 @@ ap_pathfind_local(struct ap_screen * screen, struct xy start_xy, struct xy desti
46                 uint32_t cost = 0;
47                 struct xy mapxy = XYOP2(XYOP1(XY(x, y), * 8), +, screen->tl);
48                 uint8_t raw_tile = ap_map_attr(mapxy);
49-                uint16_t tile = ap_tile_attrs[raw_tile];
50+                uint16_t tile = ap_tile_attrs_here(raw_tile);
51                 state[y][x].tile_attrs = tile;
52                 state[y][x].raw_tile = raw_tile;
53                 uint8_t ledge_mask = 0;