shithub: zelda3

Download patch

ref: c9c6843f7d74f3c448f623e58b5364cf73bd0eb9
parent: 825f449e5860ac0e8b617afa0535d529d968470d
author: xander-haj <114783946+xander-haj@users.noreply.github.com>
date: Thu Oct 27 15:23:39 EDT 2022

Can now assign items to L and R (#171)


--- a/features.h
+++ b/features.h
@@ -48,8 +48,10 @@
 #define msu_curr_sample (*(uint32*)(g_ram+0x650))
 #define msu_volume (*(uint8*)(g_ram+0x654))
 #define msu_track (*(uint8*)(g_ram+0x655))
-#define hud_cur_item_x (*(uint8*)(g_ram+0x656))
 #define hud_inventory_order ((uint8*)(g_ram + 0x225)) // 4x6 bytes
+#define hud_cur_item_x (*(uint8*)(g_ram+0x656))
+#define hud_cur_item_l (*(uint8*)(g_ram+0x657))
+#define hud_cur_item_r (*(uint8*)(g_ram+0x658))
 
 
 
--- a/hud.c
+++ b/hud.c
@@ -594,6 +594,21 @@
   } while (!Hud_DoWeHaveThisItem(*item));
 }
 
+int GetCurrentItemButtonIndex() {
+  if (enhanced_features0 & kFeatures0_SwitchLR) {
+    return (joypad1L_last & kJoypadL_X) ? 1 :
+           (joypad1L_last & kJoypadL_L) ? 2 :
+           (joypad1L_last & kJoypadL_R) ? 3 : 0;
+  }
+  return 0;
+}
+
+uint8 *GetCurrentItemButtonPtr(int i) {
+  return (i == 0) ? &hud_cur_item : 
+         (i == 1) ? &hud_cur_item_x : 
+         (i == 2) ? &hud_cur_item_l : &hud_cur_item_r;
+}
+
 void Hud_NormalMenu() {  // 8ddf15
   timer_for_flashing_circle++;
   if (!BYTE(joypad1H_last))
@@ -624,8 +639,9 @@
       Hud_ReorderItem(1);
     }
   } else if (!BYTE(hud_tmp1)) {
-    // If the x button is down, then move the blue circle
-    uint8 *item_p = (joypad1L_last & kJoypadL_X && (enhanced_features0 & kFeatures0_SwitchLR)) ? &hud_cur_item_x : &hud_cur_item;
+    // If Special Key button is down, then move their circle
+    int btn_index = GetCurrentItemButtonIndex();
+    uint8 *item_p = GetCurrentItemButtonPtr(btn_index);
     uint16 old_item = *item_p;
     if (filtered_joypad_H & kJoypadH_Up) {
       Hud_EquipItemAbove(item_p);
@@ -912,22 +928,80 @@
   return &kHudItemBoxGfxPtrs[i - 1][item_val];
 }
 
+static void CopyTilesForSwitchLR(int switch_lr) {
+#define PV(a0,a1,a2,a3,a4,a5,a6,a7)  ((a0 & 1) << 7 | (a0 >> 1 & 1) << 15 | (a1 & 1) << 6 | (a1 >> 1 & 1) << 14 | (a2 & 1) <<5 | (a2 >> 1&1) <<13 | (a3 & 1) << 4 | (a3>> 1 & 1) << 12 | (a4 & 1) << 3 | (a4 >> 1 & 1) << 11 | (a5 & 1) << 2 | (a5 >> 1 & 1) << 10 | (a6 & 1) << 1 | (a6 >> 1 & 1) << 9 | (a7 & 1) << 0 | (a7 >> 1 & 1) << 8) 
+    
+  if (switch_lr == 3) {
+    static const uint16 kBytesForNewTile0xC_TopOfR[8] = {
+      PV(1,1,1,1,1,1,3,3),
+      PV(1,1,1,1,1,1,1,3),
+      PV(1,1,1,1,1,1,1,1),
+      PV(1,1,1,3,3,1,1,1),
+      PV(1,1,1,3,3,1,1,1),
+      PV(1,1,1,3,3,1,1,1),
+      PV(1,1,1,3,3,1,1,1),
+      PV(1,1,1,1,1,1,1,3)
+    };
+    memcpy(&g_zenv.vram[0x7000 + 0xc * 8], kBytesForNewTile0xC_TopOfR, sizeof(kBytesForNewTile0xC_TopOfR));
+
+    static const uint16 kBytesForNewTile0xD_BottomofR[8] = {
+      PV(1,1,1,1,1,1,3,3),
+      PV(1,1,1,3,1,1,1,3),
+      PV(1,1,1,3,3,1,1,1),
+      PV(1,1,1,3,3,1,1,1),
+      PV(1,1,1,3,3,1,1,1),
+      PV(1,1,1,3,3,1,1,1),
+      PV(1,1,1,3,3,1,1,1),
+      PV(1,1,1,3,3,1,1,1)
+    };
+    memcpy(&g_zenv.vram[0x7000 + 0xd * 8], kBytesForNewTile0xD_BottomofR, sizeof(kBytesForNewTile0xD_BottomofR));;
+  }else if (switch_lr == 2) {
+    static const uint16 kBytesForNewTile0xE_TopOfL[8] = {
+      PV(1,1,1,3,3,3,3,3),
+      PV(1,1,1,3,3,3,3,3),
+      PV(1,1,1,3,3,3,3,3),
+      PV(1,1,1,3,3,3,3,3),
+      PV(1,1,1,3,3,3,3,3),
+      PV(1,1,1,3,3,3,3,3),
+      PV(1,1,1,3,3,3,3,3),
+      PV(1,1,1,3,3,3,3,3)
+    };
+    memcpy(&g_zenv.vram[0x7000 + 0xe * 8], kBytesForNewTile0xE_TopOfL, sizeof(kBytesForNewTile0xE_TopOfL));
+
+    static const uint16 kBytesForNewTile0xF_BottomofL[8] = {
+      PV(1,1,1,3,3,3,3,3),
+      PV(1,1,1,3,3,3,3,3),
+      PV(1,1,1,3,3,3,3,3),
+      PV(1,1,1,3,3,3,3,3),
+      PV(1,1,1,3,3,3,3,3),
+      PV(1,1,1,1,1,1,1,1),
+      PV(1,1,1,1,1,1,1,1),
+      PV(1,1,1,1,1,1,1,1)
+    };
+    memcpy(&g_zenv.vram[0x7000 + 0xf * 8], kBytesForNewTile0xF_BottomofL, sizeof(kBytesForNewTile0xF_BottomofL));
+  }
+#undef PV
+}
+
+static const uint8 kSwitchLR_palettes[] = { 7, 3, 4, 4 };
+
 void Hud_DrawYButtonItems() {  // 8de3d9
   uint16 *dst = uvram_screen.row[0].col;
   int x = kNewStyleInventory ? 0 : 1;
 
-  bool is_x = (joypad1L_last & kJoypadL_X && (enhanced_features0 & kFeatures0_SwitchLR));
-  uint8 palette = is_x ? 3 : 7;
-  Hud_DrawBox(dst, x, 5, 20 - x, 19, palette);
+  int btn_index = GetCurrentItemButtonIndex();
+  CopyTilesForSwitchLR(btn_index);
+  Hud_DrawBox(dst, x, 5, 20 - x, 19, kSwitchLR_palettes[btn_index]);
+  static const uint16 kEquipmentLetterTiles[4][2] = {
+    {0x3CF0, 0x3CF1},  // Y
+    {0x2CF0, 0x2CF0 | 0x8000},  // X
+    {0x200E | 4 << 10, 0x200F | 4 << 10},  // L
+    {0x200C | 4 << 10, 0x200D | 4 << 10}   // R
+   };
 
   if (!kNewStyleInventory) {
-    if (palette == 3) {
-      dst[HUDXY(2, 6)] = 0x2CF0;
-      dst[HUDXY(2, 7)] = 0x2CF0 | 0x8000;
-    } else {
-      dst[HUDXY(2, 6)] = 0x3CF0;
-      dst[HUDXY(2, 7)] = 0x3CF1;
-    }
+    dst[HUDXY(2, 6)] = kEquipmentLetterTiles[btn_index][0];
+    dst[HUDXY(2, 7)] = kEquipmentLetterTiles[btn_index][1]; 
   }
   dst[HUDXY(x + 2, 5)] = 0x246E;
   dst[HUDXY(x + 3, 5)] = 0x246F;
@@ -1128,20 +1202,18 @@
 
   uint16 *dst_org = uvram_screen.row[0].col;
   uint16 *dst_box = dst_org + (kNewStyleInventory ? 1 : 0);
+  
+  int btn_index = GetCurrentItemButtonIndex();
+  int item = *GetCurrentItemButtonPtr(btn_index);
+  Hud_DrawBox(dst_box, 21, 5, 21 + 9, 10, kSwitchLR_palettes[btn_index]);
 
-  bool is_x = (joypad1L_last & kJoypadL_X && (enhanced_features0 & kFeatures0_SwitchLR));
-  uint8 palette = is_x ? 3 : 7;
-  Hud_DrawBox(dst_box, 21, 5, 21 + 9, 10, palette);
-
   // Display either the current item or the item assigned
-  // to the x key.
-  int item = is_x ? hud_cur_item_x : hud_cur_item;
-
+  // to the x, l, or r key.
   if (item != 0) {
     uint16 *p = dst_org + kHudItemInVramPtr[Hud_GetItemPosition(item)];
     Hud_Copy2x2(dst_box + HUDXY(25, 6), p);
     if (timer_for_flashing_circle & 0x10)
-      Hud_DrawFlashingCircle(p, palette);
+      Hud_DrawFlashingCircle(p, kSwitchLR_palettes[btn_index]);
   }
 
   const uint16 *src_p;
@@ -1160,7 +1232,7 @@
   } else if (item == kHudItem_Shovel) {
     src_p = &kHudItemText[(13 - 1) * 16];
   } else if (item == 0) {
-    src_p = is_x ? kNotAssignedItemText : &kHudItemText[(20 - 1) * 16];
+    src_p = btn_index ? kNotAssignedItemText : &kHudItemText[(20 - 1) * 16];
   } else {
     src_p = &kHudItemText[(item - 1) * 16];
   }
@@ -1434,25 +1506,31 @@
 void Hud_HandleItemSwitchInputs() {
   if (!(enhanced_features0 & kFeatures0_SwitchLR))
     return;
-  if (filtered_joypad_L & (kJoypadL_L | kJoypadL_R)) {
-    int old_item = hud_cur_item;
-    for (int i = 0; ; i++) {
-      if (i >= kHudItemCount) {
-        hud_cur_item = 0;
-        break;
+  
+  bool direction;
+  
+  if (filtered_joypad_L & kJoypadL_L && (hud_cur_item_l == 0))
+    direction = false;
+  else if (filtered_joypad_L & kJoypadL_R && (hud_cur_item_r == 0))
+    direction = true;
+  else
+    return;
+
+  uint8 item = hud_cur_item;
+  for (int i = 0; i < kHudItemCount; i++) {
+    if (!direction)
+      Hud_GotoPrevItem(&item, 1);
+    else
+      Hud_GotoNextItem(&item, 1);
+    if (Hud_DoWeHaveThisItem(item)) {
+      if (item != hud_cur_item) {
+        hud_cur_item = item;
+        sound_effect_2 = 32;
+        Hud_UpdateEquippedItem();
+        Hud_UpdateItemBox();
+        flag_update_hud_in_nmi++;
       }
-      if (filtered_joypad_L & kJoypadL_L)
-        Hud_GotoPrevItem(&hud_cur_item, 1);
-      else
-        Hud_GotoNextItem(&hud_cur_item, 1);
-      if (Hud_DoWeHaveThisItem(hud_cur_item))
-        break;
-    }
-    if (hud_cur_item != old_item) {
-      sound_effect_2 = 32;
-      Hud_UpdateEquippedItem();
-      Hud_UpdateItemBox();
-      flag_update_hud_in_nmi++;
+      break;
     }
   }
 }
--- a/hud.h
+++ b/hud.h
@@ -56,5 +56,7 @@
 void Hud_RebuildIndoor();
 void Hud_Rebuild();
 const uint16 *Hud_GetItemBoxPtr(int item);
+int GetCurrentItemButtonIndex();
+uint8 *GetCurrentItemButtonPtr(int i);
 
 void Hud_HandleItemSwitchInputs();
--- a/player.c
+++ b/player.c
@@ -1985,16 +1985,20 @@
   }
 
   uint8 old_down = joypad1H_last, old_pressed = filtered_joypad_H, old_bottle = link_item_bottle_index;
-  if ((link_item_in_hand | link_position_mode) == 0) {
-    // Is X held down?
-    if (joypad1L_last & kJoypadL_X && !(old_down & kJoypadH_Y) && hud_cur_item_x != 0) {
-      
-      if (hud_cur_item_x >= kHudItem_Bottle1)
-        link_item_bottle_index = hud_cur_item_x - kHudItem_Bottle1 + 1;
-      item = Hud_LookupInventoryItem(hud_cur_item_x);
-      // Pretend it's actually Y that's down
-      joypad1H_last = old_down | kJoypadH_Y;
-      filtered_joypad_H = old_pressed | ((filtered_joypad_L & kJoypadL_X) ? kJoypadH_Y : 0);
+  if ((link_item_in_hand | link_position_mode) == 0 && !(old_down & kJoypadH_Y)) {
+    // Is any special key held down?
+    int btn_index = GetCurrentItemButtonIndex();
+    if (btn_index != 0) {
+      uint8 *cur_item_ptr = GetCurrentItemButtonPtr(btn_index);
+      if (*cur_item_ptr) {
+        if (*cur_item_ptr >= kHudItem_Bottle1)
+          link_item_bottle_index = *cur_item_ptr - kHudItem_Bottle1 + 1;
+        item = Hud_LookupInventoryItem(*cur_item_ptr);
+        // Pretend it's actually Y that's down
+        joypad1H_last = old_down | kJoypadH_Y;
+        static const uint8 kButtonIndexKeys[4] = { 0, kJoypadL_X, kJoypadL_L, kJoypadL_R };
+        filtered_joypad_H = old_pressed | ((filtered_joypad_L & kButtonIndexKeys[btn_index]) ? kJoypadH_Y : 0);
+      }
     }
   }
 
--- a/zelda3.ini
+++ b/zelda3.ini
@@ -85,9 +85,11 @@
 
 [Features]
 # Item switch on L/R. Also allows reordering of items in inventory by pressing Y+direction
-# Hold X inside of the item selection screen to reassign the X key into a separate item slot.
+# Hold X,L,or R inside of the item selection screen to reassign an item into a separate item slot.
 # When X is assigned to an item, the Select key is used to enter the map. Press Select inside
 # of the Start menu to see the old select options.
+# When L is assigned an item, Item cycle will cease for the L button
+# this also applies for the R button.
 ItemSwitchLR = 0
 
 # Allow turning while dashing