foxygit / doom Log in
commit 73de5d4f6780e5b0b0e2413f1c8a4ae555a5802c
Author:     Michael Day <contact@michaelcday.com>
AuthorDate: Sat Dec 9 23:28:00 2023 -0500
Commit:     Michael Day <contact@michaelcday.com>
CommitDate: Sat Dec 9 23:28:00 2023 -0500

    hexen: Let joystick navigate menu
---
 src/hexen/h2def.h   |   2 +
 src/hexen/mn_menu.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++---
 src/hexen/p_setup.c |   4 ++
 3 files changed, 146 insertions(+), 8 deletions(-)

diff --git a/src/hexen/h2def.h b/src/hexen/h2def.h
index 8171fa6e..c156243c 100644
--- a/src/hexen/h2def.h
+++ b/src/hexen/h2def.h
@@ -855,6 +855,8 @@ int SV_GetRebornSlot(void);
 //PLAY
 //-----

+extern lumpinfo_t *maplumpinfo;
+
 void P_Ticker(void);
 // called by C_Ticker
 // can call G_PlayerExited
diff --git a/src/hexen/mn_menu.c b/src/hexen/mn_menu.c
index 64819fbc..57be51c9 100644
--- a/src/hexen/mn_menu.c
+++ b/src/hexen/mn_menu.c
@@ -21,7 +21,9 @@
 #include "h2def.h"
 #include "doomkeys.h"
 #include "i_input.h"
+#include "i_joystick.h"
 #include "i_system.h"
+#include "i_timer.h"
 #include "i_swap.h"
 #include "i_video.h"
 #include "m_controls.h"
@@ -148,6 +150,7 @@ boolean askforquit;
 static int typeofask;
 static boolean FileMenuKeySteal;
 static boolean slottextloaded;
+static boolean joypadsave;
 static char SlotText[6][SLOTTEXTLEN + 2];
 static char oldSlotText[SLOTTEXTLEN + 2];
 static int SlotStatus[6];
@@ -915,6 +918,37 @@ static void SCLoadGame(int option)
     }
 }

+//
+// Generate a default save slot name when the user saves to
+// an empty slot via the joypad.
+//
+static void SetDefaultSaveName(int slot)
+{
+    // map from IWAD or PWAD?
+    if (W_IsIWADLump(maplumpinfo) && strcmp(SavePath, ""))
+    {
+        M_snprintf(SlotText[slot], SLOTTEXTLEN,
+                   "%s", maplumpinfo->name);
+    }
+    else
+    {
+        char *wadname = M_StringDuplicate(W_WadNameForLump(maplumpinfo));
+        char *ext = strrchr(wadname, '.');
+
+        if (ext != NULL)
+        {
+            *ext = '\0';
+        }
+
+        M_snprintf(SlotText[slot], SLOTTEXTLEN,
+                   "%s (%s)", maplumpinfo->name,
+                   wadname);
+        free(wadname);
+    }
+    M_ForceUppercase(SlotText[slot]);
+    joypadsave = false;
+}
+
 //---------------------------------------------------------------------------
 //
 // PROC SCSaveGame
@@ -938,6 +972,12 @@ static void SCSaveGame(int option)

         M_StringCopy(oldSlotText, SlotText[option], sizeof(oldSlotText));
         ptr = SlotText[option];
+
+        if (!strcmp(ptr, "") && joypadsave)
+        {
+            SetDefaultSaveName(option);
+        }
+
         while (*ptr)
         {
             ptr++;
@@ -1147,6 +1187,7 @@ boolean MN_Responder(event_t * event)
     int i;
     MenuItem_t *item;
     char *textBuffer;
+    int dir;

     // In testcontrols mode, none of the function keys should do anything
     // - the only key is escape to quit.
@@ -1185,26 +1226,117 @@ boolean MN_Responder(event_t * event)
         return true;
     }

-    // Allow the menu to be activated from a joystick button if a button
-    // is bound for joybmenu.
+    charTyped = 0;
+    key = -1;
+
     if (event->type == ev_joystick)
     {
-        if (joybmenu >= 0 && (event->data1 & (1 << joybmenu)) != 0)
+        // Simulate key presses from joystick events to interact with the menu.
+
+        if (MenuActive)
+        {
+            if (JOY_GET_DPAD(event->data6) != JOY_DIR_NONE)
+            {
+                dir = JOY_GET_DPAD(event->data6);
+            }
+            else if (JOY_GET_LSTICK(event->data6) != JOY_DIR_NONE)
+            {
+                dir = JOY_GET_LSTICK(event->data6);
+            }
+            else
+            {
+                dir = JOY_GET_RSTICK(event->data6);
+            }
+
+            if (dir & JOY_DIR_UP)
+            {
+                key = key_menu_up;
+                joywait = I_GetTime() + 5;
+            }
+            else if (dir & JOY_DIR_DOWN)
+            {
+                key = key_menu_down;
+                joywait = I_GetTime() + 5;
+            }
+            if (dir & JOY_DIR_LEFT)
+            {
+                key = key_menu_left;
+                joywait = I_GetTime() + 5;
+            }
+            else if (dir & JOY_DIR_RIGHT)
+            {
+                key = key_menu_right;
+                joywait = I_GetTime() + 5;
+            }
+
+#define JOY_BUTTON_MAPPED(x) ((x) >= 0)
+#define JOY_BUTTON_PRESSED(x) (JOY_BUTTON_MAPPED(x) && (event->data1 & (1 << (x))) != 0)
+
+            if (JOY_BUTTON_PRESSED(joybfire))
+            {
+                // Simulate pressing "Enter" when we are supplying a save slot name
+                if (FileMenuKeySteal)
+                {
+                    key = KEY_ENTER;
+                }
+                else
+                {
+                    // if selecting a save slot via joypad, set a flag
+                    if (CurrentMenu == &SaveMenu)
+                    {
+                        joypadsave = true;
+                    }
+                    key = key_menu_forward;
+                }
+                joywait = I_GetTime() + 5;
+            }
+            if (JOY_BUTTON_PRESSED(joybuse))
+            {
+                // If user was entering a save name, back out
+                if (FileMenuKeySteal)
+                {
+                    key = KEY_ESCAPE;
+                }
+                else
+                {
+                    key = key_menu_back;
+                }
+                joywait = I_GetTime() + 5;
+            }
+        }
+        else if (askforquit)
+        {
+            if (JOY_BUTTON_PRESSED(joybfire))
+            {
+                // Simulate a 'Y' keypress
+                key = key_menu_confirm;
+                joywait = I_GetTime() + 5;
+            }
+            if (JOY_BUTTON_PRESSED(joybuse))
+            {
+                // Simulate a 'N' keypress
+                key = key_menu_abort;
+                joywait = I_GetTime() + 5;
+            }
+        }
+        if (JOY_BUTTON_PRESSED(joybmenu))
         {
             MN_ActivateMenu();
+            joywait = I_GetTime() + 5;
             return true;
         }
     }

-    // Only care about keypresses beyond this point.
-
-    if (event->type != ev_keydown)
+    if (event->type != ev_keydown && key == -1)
     {
         return false;
     }

-    key = event->data1;
-    charTyped = event->data2;
+    if (event->type == ev_keydown)
+    {
+        key = event->data1;
+        charTyped = event->data2;
+    }

     if (InfoType)
     {
diff --git a/src/hexen/p_setup.c b/src/hexen/p_setup.c
index 89e7cfe8..79d09e1a 100644
--- a/src/hexen/p_setup.c
+++ b/src/hexen/p_setup.c
@@ -655,6 +655,7 @@ void P_GroupLines(void)

 //=============================================================================

+lumpinfo_t *maplumpinfo;

 /*
 =================
@@ -694,6 +695,9 @@ void P_SetupLevel(int episode, int map, int playermask, skill_t skill)

     M_snprintf(lumpname, sizeof(lumpname), "MAP%02d", map);
     lumpnum = W_GetNumForName(lumpname);
+
+    maplumpinfo = lumpinfo[lumpnum];
+
     //
     // Begin processing map lumps
     // Note: most of this ordering is important