ref: a5bb9ebe6e34dfd4a6b69d999bb43eb4c74f275f
parent: 719bba66e54eb8983e6318a0df1894c41ffba16c
author: Snesrev <snesrev@protonmail.com>
date: Fri Sep 23 12:02:54 EDT 2022
Extend size of some ancilla arrays - Some rare zelda bug would overwrite things otherwise
--- a/ancilla.c
+++ b/ancilla.c
@@ -1309,7 +1309,7 @@
Boomerang_Terminate(k);
return;
}
- int j = boomerang_arr1[k] >> 1;
+ int j = ancilla_arr23[k] >> 1;
Ancilla_SetXY(k, link_x_coord + kBoomerang_X0[j], link_y_coord + 8 + kBoomerang_Y0[j]);
ancilla_aux_timer[k]++;
}
@@ -1598,6 +1598,7 @@
}
if (ancilla_item_to_link[k] == 11) {
+ // transmute to door debris?
ancilla_type[k] = ancilla_step[k] ? 8 : 0;
return;
}
@@ -1605,9 +1606,10 @@
}
if (ancilla_item_to_link[k] == 7 && ancilla_arr3[k] == 2) {
- uint16 x = Ancilla_GetX(k), y = Ancilla_GetY(k);
+ // check whether the bomb causes any door debris, the bomb
+ // will transmute to debris later on.
door_debris_x[k] = 0;
- Bomb_CheckForDestructibles(x, y, k);
+ Bomb_CheckForDestructibles(Ancilla_GetX(k), Ancilla_GetY(k), k);
if (door_debris_x[k])
ancilla_step[k] = 1;
}
@@ -5999,10 +6001,13 @@
ancilla_R[k] = 0;
ancilla_step[k] = 0;
ancilla_item_to_link[k] = 0;
- ancilla_arr25[k] = 0;
ancilla_L[k] = 0;
ancilla_arr3[k] = kBomb_Tab0[0];
+
+ // These are not used directly by bombs, but used by door debris
+ ancilla_arr25[k] = 0;
ancilla_arr26[k] = 7;
+
ancilla_z[k] = 0;
ancilla_timer[k] = 8;
ancilla_dir[k] = link_direction_facing >> 1;
@@ -6073,7 +6078,7 @@
if (j < 0)
j = 0;
ancilla_arr1[k] = kBoomerang_Tab5[j];
- boomerang_arr1[k] = j << 1;
+ ancilla_arr23[k] = j << 1;
if (button_b_frames >= 9) {
ancilla_aux_timer[k]++;
} else {
@@ -7185,31 +7190,37 @@
return CalculateSfxPan(Ancilla_GetX(k));
}
-int Ancilla_AllocInit(uint8 type, uint8 y) { // 8ff577
+int Ancilla_AllocInit(uint8 type, uint8 limit) { // 8ff577
// snes bug: R14 is used in tile detection already
// unless this is here it the memcmp will fail when entering/leaving a water through steps quickly
if (g_ram[kRam_BugsFixed] >= kBugFix_PolyRenderer)
- BYTE(R14) = y + 1;
+ BYTE(R14) = limit + 1;
int n = 0;
- for (int k = 0; k < 5; k++) {
- if (ancilla_type[k] == type)
+ for (int i = 0; i < 5; i++) {
+ if (ancilla_type[i] == type)
n++;
}
- if (y + 1 == n)
+ if (limit + 1 == n)
return -1;
- int k = (type == 7 || type == 8) ? 1 : 4;
- for (; k >= 0; k--) {
- if (ancilla_type[k] == 0)
- return k;
+
+ // Try to reuse an empty ancilla slot
+ for (int j = (type == 7 || type == 8) ? limit : 4; j >= 0; j--) {
+ if (ancilla_type[j] == 0)
+ return j;
}
+ int k = ancilla_alloc_rotate;
do {
- if (sign8(--ancilla_alloc_rotate))
- ancilla_alloc_rotate = y;
- uint8 type = ancilla_type[ancilla_alloc_rotate];
- if (type == 0x3c || type == 0x13 || type == 0xa)
- return ancilla_alloc_rotate;
- } while (ancilla_alloc_rotate != 0);
+ if (--k < 0)
+ k = limit;
+ uint8 old_type = ancilla_type[k];
+ // reuse slots for sparkles or arrows in wall
+ if (old_type == 0x3c || old_type == 0x13 || old_type == 0xa) {
+ ancilla_alloc_rotate = k;
+ return k;
+ }
+ } while (k != 0);
+ ancilla_alloc_rotate = 0;
return -1;
}
--- a/variables.h
+++ b/variables.h
@@ -362,19 +362,23 @@
#define ancilla_arr1 ((uint8*)(g_ram+0x3A4))
#define ancilla_S ((uint8*)(g_ram+0x3A9))
#define ancilla_aux_timer ((uint8*)(g_ram+0x3B1))
-#define door_debris_x ((uint16*)(g_ram+0x3B6))
-#define door_debris_y ((uint16*)(g_ram+0x3BA))
-#define door_debris_direction ((uint8*)(g_ram+0x3BE))
-#define ancilla_arr26 ((uint8*)(g_ram+0x3C0))
-#define ancilla_arr25 ((uint8*)(g_ram+0x3C2))
+
+// relocated those so they have 5 entries each
+#define door_debris_x ((uint16*)(g_ram+0x728))
+#define door_debris_y ((uint16*)(g_ram+0x732))
+#define door_debris_direction ((uint8*)(g_ram+0x73c))
+#define ancilla_arr26 ((uint8*)(g_ram+0x741))
+#define ancilla_arr25 ((uint8*)(g_ram+0x746))
+#define ancilla_arr22 ((uint8*)(g_ram+0x74b))
+
#define ancilla_alloc_rotate (*(uint8*)(g_ram+0x3C4))
#define ancilla_H ((uint8*)(g_ram+0x3C5))
#define ancilla_floor2 ((uint8*)(g_ram+0x3CA))
-#define boomerang_arr1 ((uint8*)(g_ram+0x3CF))
-#define ancilla_arr23 ((uint8*)(g_ram+0x3D2))
+
+// extended the size of this array by merging it with the adjacent one
+#define ancilla_arr23 ((uint8*)(g_ram+0x3CF))
#define ancilla_T ((uint8*)(g_ram+0x3D5))
#define ancilla_arr24 ((uint8*)(g_ram+0x3DB))
-#define ancilla_arr22 ((uint8*)(g_ram+0x3E1))
#define ancilla_tile_attr ((uint8*)(g_ram+0x3E4))
#define link_something_with_hookshot (*(uint8*)(g_ram+0x3E9))
#define ancilla_R ((uint8*)(g_ram+0x3EA))
--- a/zelda_cpu_infra.c
+++ b/zelda_cpu_infra.c
@@ -953,6 +953,29 @@
// CleanUpAndPrepDesertPrayerHDMA clearing too much
PatchRomWord(rom, 0x2C7E5 + 1, 0x1df, 0x1cf);
+ // Merge ancilla_arr23 with boomerang_arr1 because they're only 3 bytes long,
+ // and boomerang might get allocated in slot 4.
+ PatchRomByte(rom, 0x9816C, 0xd2, 0xCF);
+ PatchRomByte(rom, 0xffdeb, 0xd2, 0xCF);
+ PatchRomByte(rom, 0xffdee, 0xd2, 0xCF);
+ PatchRomByte(rom, 0xffdf7, 0xd2, 0xCF);
+ PatchRomByte(rom, 0xffdfa, 0xd2, 0xCF);
+
+ // Relocate the door debris variables so they become 5 entries each (they were 2 before).
+ static const int kDoorDebrisX_Uses[] = {0x1CFC6, 0x1d29d, 0x89794, 0x897a3, 0x8a0a1, 0x8edca, 0x99aa6};
+ for (int i = 0; i < countof(kDoorDebrisX_Uses); i++) PatchRomWord(rom, kDoorDebrisX_Uses[i] + 1, 0x3b6, 0x728);
+ static const int kDoorDebrisX1_Uses[] = { 0x89797, 0x897A6 };
+ for (int i = 0; i < countof(kDoorDebrisX1_Uses); i++) PatchRomWord(rom, kDoorDebrisX1_Uses[i] + 1, 0x3b7, 0x729);
+ static const int kDoorDebrisY_Uses[] = { 0x1CFD7, 0x1D2AE, 0x8A099, 0x8EDC5, 0x99AA1 };
+ for (int i = 0; i < countof(kDoorDebrisY_Uses); i++) PatchRomWord(rom, kDoorDebrisY_Uses[i] + 1, 0x3ba, 0x732);
+ static const int kDoorDebrisDir_Uses[] = { 0x1CFB2, 0x1D2BA, 0x8A0B7 };
+ for (int i = 0; i < countof(kDoorDebrisDir_Uses); i++) PatchRomWord(rom, kDoorDebrisDir_Uses[i] + 1, 0x3be, 0x73c);
+ static const int ancilla_arr26_Uses[] = { 0x89fb9, 0x89fc0, 0x98157, 0x99c49 };
+ for (int i = 0; i < countof(ancilla_arr26_Uses); i++) PatchRomWord(rom, ancilla_arr26_Uses[i] + 1, 0x3c0, 0x741);
+ static const int ancilla_arr25_Uses[] = { 0x89fc3, 0x89fc6, 0x8a0ae, 0x8ab7c, 0x8aba7, 0x8abb6, 0x8ae92, 0x8bae2, 0x8baff, 0x8f429, 0x98148, 0x98e0a, 0x98ebc, 0x9920a, 0x9931e, 0x9987f, 0x99c44 };
+ for (int i = 0; i < countof(ancilla_arr25_Uses); i++) PatchRomWord(rom, ancilla_arr25_Uses[i] + 1, 0x3c2, 0x746);
+ static const int ancilla_arr22_Uses[] = { 0x9816e, 0xffde0, 0xffde7 };
+ for (int i = 0; i < countof(ancilla_arr22_Uses); i++) PatchRomWord(rom, ancilla_arr22_Uses[i] + 1, 0x3e1, 0x74b);
}