jevsnes.git / third-party / c / patches / 0009-pegasus-boots-dash.patch
0009-pegasus-boots-dash.patch55 lines · 3.0 KB · raw
1diff --git a/third-party/c/zbanks-alttp/ap_map.c b/third-party/c/zbanks-alttp/ap_map.c
2index e481fe75..ec9bcde3 100644
3--- a/third-party/c/zbanks-alttp/ap_map.c
4+++ b/third-party/c/zbanks-alttp/ap_map.c
5@@ -822,7 +822,16 @@ ap_follow_targets(uint16_t * joypad, enum ap_inventory * equip_out)
6         }
7         *equip_out = INVENTORY_HAMMER;
8     } else {
9-        JOYPAD_CLEAR(A);
10+        // Carried patch (jev): a scripted dash-hold target (below) forces A
11+        // together with the direction bit in the SAME target, which no
12+        // existing sequence character does (the 'A'/'B'/'Y' taps set only
13+        // their own button, never dir_mask alongside it) - so this leaves
14+        // every existing script untouched and only stops THIS frame's clear
15+        // from erasing a dash's A the instant next_xy is plain floor, which
16+        // is every frame of the charge and the dash it triggers.
17+        if (!((joypad_mask & SNES_MASK(A)) && (joypad_mask & dir_mask))) {
18+            JOYPAD_CLEAR(A);
19+        }
20         JOYPAD_CLEAR(B);
21         JOYPAD_CLEAR(Y);
22     }
23@@ -2027,6 +2036,32 @@ ap_set_script(const struct ap_script * script) {
24         case 'D':
25             ap_targets[i++] = (struct ap_target) { .tl = xy, .joypad_mask = dir_mask, .joypad = SNES_MASK(DOWN), };
26             break;
27+        // Carried patch (jev): Pegasus Boots dash-hold, one 16px step per
28+        // character (numpad directions, so as not to collide with the plain
29+        // movement/tap letters above) - repeat to cover the distance to
30+        // charge (~29 frames stationary; LinkState_Dashing, zelda3 player.c)
31+        // and then travel. Unlike '<'/'>'/'^'/'v' this target holds A WITH
32+        // the direction the whole time it is current, because (a) it is not
33+        // popped until Link's real position reaches it, so it keeps
34+        // asserting both across every frame of the charge and the dash it
35+        // triggers, and (b) the JOYPAD_CLEAR(A) below that would otherwise
36+        // erase it every such frame is guarded for exactly this case.
37+        case '8':
38+            xy.y -= 16;
39+            ap_targets[i++] = (struct ap_target) { .tl = xy, .joypad_mask = dir_mask | SNES_MASK(A), .joypad = SNES_MASK(UP) | SNES_MASK(A), };
40+            break;
41+        case '2':
42+            xy.y += 16;
43+            ap_targets[i++] = (struct ap_target) { .tl = xy, .joypad_mask = dir_mask | SNES_MASK(A), .joypad = SNES_MASK(DOWN) | SNES_MASK(A), };
44+            break;
45+        case '4':
46+            xy.x -= 16;
47+            ap_targets[i++] = (struct ap_target) { .tl = xy, .joypad_mask = dir_mask | SNES_MASK(A), .joypad = SNES_MASK(LEFT) | SNES_MASK(A), };
48+            break;
49+        case '6':
50+            xy.x += 16;
51+            ap_targets[i++] = (struct ap_target) { .tl = xy, .joypad_mask = dir_mask | SNES_MASK(A), .joypad = SNES_MASK(RIGHT) | SNES_MASK(A), };
52+            break;
53         default:
54             LOG("Unhandled character in sequence: '%c'", *s);
55             assert_bp(false);