shithub: zelda3

Download patch

ref: a5bb9ebe6e34dfd4a6b69d999bb43eb4c74f275f
parent: 719bba66e54eb8983e6318a0df1894c41ffba16c
author: Snesrev <[email protected]>
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);
 }