From 72e033ba19687bd64d130adca2c0d5713f2de1b4 Mon Sep 17 00:00:00 2001
From: xkiv <xkiv@a31d4220-a93d-0410-bf67-fe4944624d44>
Date: Mon, 24 Nov 2008 20:13:57 +0000
Subject: [PATCH] SDL: new option to slow down autofire (needed for it to work
 with some games)

git-svn-id: https://svn.code.sf.net/p/vbam/code/trunk@802 a31d4220-a93d-0410-bf67-fe4944624d44
---
 doc/ReadMe.SDL.txt   | 10 ++++++++++
 src/sdl/SDL.cpp      | 13 +++++++++++++
 src/sdl/inputSDL.cpp |  9 ++++++++-
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/doc/ReadMe.SDL.txt b/doc/ReadMe.SDL.txt
index c5805f7c..2fd5a057 100644
--- a/doc/ReadMe.SDL.txt
+++ b/doc/ReadMe.SDL.txt
@@ -164,4 +164,14 @@ which means:
 	     circle button)
 So when I press and hold this button on my gamepad, VBA-M rewards me with autofire on A *on that pad only*.
 
+[2008-11-21] new autofire configuration:
+  commandline argument: --autofire NNN
+  configfile attribute: autoFireMaxCount=NNN
+  default value: NNN=1 (does exactly the same thing as without this new feature)
+This controls the "length" of each press (and depress). It is measured in vba-m cycles
+(so --autofire 30 means something like "press once every second" - don't forget that
+the button is not just "virtually pressed" but also "virtually non-pressed" in between).
+This is needed for some games that apparently check whether the button isn't pressed
+faster than a human could do it.
+For example, autofire doesn't work in Mother 3 with --autofire 1 or 2, but it works with 5.
 
diff --git a/src/sdl/SDL.cpp b/src/sdl/SDL.cpp
index f1298289..65967478 100644
--- a/src/sdl/SDL.cpp
+++ b/src/sdl/SDL.cpp
@@ -190,6 +190,8 @@ static int sdlSoundToggledOff = 0;
 int	sdl_patch_num	= 0;
 char *	(sdl_patch_names[PATCH_MAX_NUM])	= { NULL }; // and so on
 
+int autoFireMaxCount = 1;
+
 #define REWIND_NUM 8
 #define REWIND_SIZE 400000
 #define SYSMSG_BUFFER_SIZE 1024
@@ -287,6 +289,7 @@ struct option sdlOptions[] = {
   { "throttle", required_argument, 0, 'T' },
   { "verbose", required_argument, 0, 'v' },
   { "cheat", required_argument, 0, 1000 },
+  { "autofire", required_argument, 0, 1001 },
   { NULL, no_argument, NULL, 0 }
 };
 
@@ -793,6 +796,10 @@ void sdlReadPreferences(FILE *f)
       sdlSaveKeysSwitch = sdlFromHex(value);
     } else if(!strcmp(key, "openGLscale")) {
       sdlOpenglScale = sdlFromHex(value);
+    } else if(!strcmp(key, "autoFireMaxCount")) {
+      autoFireMaxCount = sdlFromDec(value);
+      if(autoFireMaxCount < 1)
+        autoFireMaxCount = 1;
     } else {
       fprintf(stderr, "Unknown configuration key %s\n", key);
     }
@@ -1901,6 +1908,12 @@ int main(int argc, char **argv)
 	      sdlPreparedCheatCodes[sdlPreparedCheats++]	= cpy;
       }
       break;
+    case 1001:
+      // --autofire
+      autoFireMaxCount = sdlFromDec(optarg);
+      if (autoFireMaxCount < 1)
+         autoFireMaxCount = 1;
+      break;
     case 'b':
       useBios = true;
       if(optarg == NULL) {
diff --git a/src/sdl/inputSDL.cpp b/src/sdl/inputSDL.cpp
index 1d8c78a0..9e27f116 100644
--- a/src/sdl/inputSDL.cpp
+++ b/src/sdl/inputSDL.cpp
@@ -53,6 +53,8 @@ static EPad sdlDefaultJoypad = PAD_MAIN;
 
 static int autoFire = 0;
 static bool autoFireToggle = false;
+static int autoFireCountdown = 0;
+extern int autoFireMaxCount;
 
 static uint32_t joypad[5][SDLBUTTONS_NUM] = {
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
@@ -533,7 +535,12 @@ uint32_t inputReadJoypad(int which)
     res &= (~realAutoFire);
     if(autoFireToggle)
       res |= realAutoFire;
-    autoFireToggle = !autoFireToggle;
+    if (autoFireCountdown <= 0) {
+      autoFireToggle = !autoFireToggle;
+      autoFireCountdown = autoFireMaxCount;
+    } else {
+      autoFireCountdown--;
+    }
   }
 
   return res;