foxygit / doom Log in
commit 5221114acce7a1321f06f638b72479a7b6038288
Author:     Michael Day <contact@michaelcday.com>
AuthorDate: Thu Dec 7 07:46:12 2023 -0500
Commit:     Michael Day <contact@michaelcday.com>
CommitDate: Thu Dec 7 07:46:12 2023 -0500

    heretic: Let joystick navigate menu
---
 src/heretic/doomdef.h |   2 +
 src/heretic/mn_menu.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++---
 src/heretic/p_setup.c |   3 ++
 3 files changed, 145 insertions(+), 6 deletions(-)

diff --git a/src/heretic/doomdef.h b/src/heretic/doomdef.h
index 01c34198..8139a7b3 100644
--- a/src/heretic/doomdef.h
+++ b/src/heretic/doomdef.h
@@ -718,6 +718,8 @@ void G_ScreenShot(void);
 //PLAY
 //-----

+extern lumpinfo_t *maplumpinfo;
+
 void P_Ticker(void);
 // called by C_Ticker
 // can call G_PlayerExited
diff --git a/src/heretic/mn_menu.c b/src/heretic/mn_menu.c
index a9ecb8bd..95cb62ce 100644
--- a/src/heretic/mn_menu.c
+++ b/src/heretic/mn_menu.c
@@ -23,7 +23,9 @@
 #include "doomdef.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 "m_controls.h"
 #include "m_misc.h"
@@ -139,6 +141,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];
@@ -834,6 +837,37 @@ static boolean SCLoadGame(int option)
     return true;
 }

+//
+// 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(savegamedir, ""))
+    {
+        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
@@ -857,6 +891,12 @@ static boolean SCSaveGame(int option)

         M_StringCopy(oldSlotText, SlotText[option], sizeof(oldSlotText));
         ptr = SlotText[option];
+
+        if (!strcmp(ptr, "") && joypadsave)
+        {
+            SetDefaultSaveName(option);
+        }
+
         while (*ptr)
         {
             ptr++;
@@ -1041,6 +1081,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.
@@ -1078,24 +1119,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;
         }
     }

-    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/heretic/p_setup.c b/src/heretic/p_setup.c
index 0dd0dcfa..2acb0167 100644
--- a/src/heretic/p_setup.c
+++ b/src/heretic/p_setup.c
@@ -543,6 +543,7 @@ void P_GroupLines(void)

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

+lumpinfo_t *maplumpinfo;

 /*
 =================
@@ -586,6 +587,8 @@ void P_SetupLevel(int episode, int map, int playermask, skill_t skill)

     lumpnum = W_GetNumForName(lumpname);

+    maplumpinfo = lumpinfo[lumpnum];
+
 // note: most of this ordering is important
     P_LoadBlockMap(lumpnum + ML_BLOCKMAP);
     P_LoadVertexes(lumpnum + ML_VERTEXES);