diff --git a/Config/FFBPlugin.ini b/Config/FFBPlugin.ini
index 4fd1d0f..45cdd1a 100644
--- a/Config/FFBPlugin.ini
+++ b/Config/FFBPlugin.ini
@@ -246,6 +246,23 @@ GameId=13
DefaultCentering=25
FeedbackLength=500
+[Aliens Extermination]
+GameId=36
+EscapeKeyExitViaPlugin=1
+FeedbackLength=100
+Device2GUID=
+EnableRumbleDevice2=1
+ReverseRumbleDevice=0
+Gun1pStrength=50
+Flame1pStrength=60
+Health1pStrength=100
+Gun2pStrength=50
+Flame2pStrength=60
+Health2pStrength=100
+HowtoRumbleGunEffect=0
+HowtoRumbleFlameEffect=0
+HowtoRumbleHealthEffect=0
+
[MAME 32bit Outputs]
GameId=22
SinePeriod=100
diff --git a/Dinput8Wrapper.vcxproj b/Dinput8Wrapper.vcxproj
index e126687..b5fca3e 100644
--- a/Dinput8Wrapper.vcxproj
+++ b/Dinput8Wrapper.vcxproj
@@ -19,6 +19,7 @@
+
@@ -46,6 +47,7 @@
+
diff --git a/Dinput8Wrapper.vcxproj.filters b/Dinput8Wrapper.vcxproj.filters
index 50d1cad..0ac5d4a 100644
--- a/Dinput8Wrapper.vcxproj.filters
+++ b/Dinput8Wrapper.vcxproj.filters
@@ -116,6 +116,7 @@
+
@@ -239,6 +240,9 @@
Common Header Files
+
+ Common Header Files
+
diff --git a/DllMain.cpp b/DllMain.cpp
index 25b0a8a..0291553 100644
--- a/DllMain.cpp
+++ b/DllMain.cpp
@@ -28,6 +28,7 @@ along with FFB Arcade Plugin.If not, see < https://www.gnu.org/licenses/>.
// include all game header files here.
#include "Game Files/TestGame.h"
+#include "Game Files/AliensExtermination.h"
#include "Game Files/ChaseHQ2.h"
#include "Game Files/Daytona3.h"
#include "Game Files/FordRacing.h"
@@ -936,6 +937,7 @@ const int INITIAL_D_0 = 32;
const int OLDMAME_ = 33;
const int SUPERMODEL_READING = 34;
const int OUTRUN_2Real = 35;
+const int ALIENS_EXTERMINATION = 36;
const int FORD_RACING_OTHER = 38;
const int KO_Drive = 39;
@@ -2026,6 +2028,9 @@ DWORD WINAPI FFBLoop(LPVOID lpParam)
case Demul_Emulator:
game = new Demul;
break;
+ case ALIENS_EXTERMINATION:
+ game = new AliensExtermination;
+ break;
case GTI_Club_3:
game = new GTIClub3;
break;
diff --git a/Game Files/AliensExtermination.cpp b/Game Files/AliensExtermination.cpp
new file mode 100644
index 0000000..c7defc5
--- /dev/null
+++ b/Game Files/AliensExtermination.cpp
@@ -0,0 +1,421 @@
+/*This file is part of FFB Arcade Plugin.
+FFB Arcade Plugin is free software : you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+FFB Arcade Plugin is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+GNU General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with FFB Arcade Plugin.If not, see < https://www.gnu.org/licenses/>.
+*/
+
+
+#include "AliensExtermination.h"
+#include "SDL.h"
+#include
+#include
+extern int joystick_index1;
+extern int joystick_index2;
+extern SDL_Joystick* GameController2;
+extern SDL_Haptic* ControllerHaptic2;
+extern SDL_Haptic* haptic2;
+
+static wchar_t* settingsFilename = TEXT(".\\FFBPlugin.ini");
+static int EscapeKeyExitViaPlugin = GetPrivateProfileInt(TEXT("Settings"), TEXT("EscapeKeyExitViaPlugin"), 0, settingsFilename);
+static int configFeedbackLength = GetPrivateProfileInt(TEXT("Settings"), TEXT("FeedbackLength"), 120, settingsFilename);
+static int HowtoRumbleGunEffect = GetPrivateProfileInt(TEXT("Settings"), TEXT("HowtoRumbleGunEffect"), 0, settingsFilename);
+static int HowtoRumbleFlameEffect = GetPrivateProfileInt(TEXT("Settings"), TEXT("HowtoRumbleFlameEffect"), 0, settingsFilename);
+static int HowtoRumbleHealthEffect = GetPrivateProfileInt(TEXT("Settings"), TEXT("HowtoRumbleHealthEffect"), 0, settingsFilename);
+static int Gun1pStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("Gun1pStrength"), 0, settingsFilename);
+static int Flame1pStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("Flame1pStrength"), 0, settingsFilename);
+static int Health1pStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("Health1pStrength"), 0, settingsFilename);
+static int Gun2pStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("Gun2pStrength"), 0, settingsFilename);
+static int Flame2pStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("Flame2pStrength"), 0, settingsFilename);
+static int Health2pStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("Health2pStrength"), 0, settingsFilename);
+
+static bool Ammo1pBool = false;
+static bool Ammo2pBool = false;
+static bool Flame1pBool = false;
+static bool Flame2pBool = false;
+static bool Health1pBool = false;
+static bool Health2pBool = false;
+
+void AliensExtermination::FFBLoop(EffectConstants* constants, Helpers* helpers, EffectTriggers* triggers) {
+
+ UINT8 Ammo1pA = helpers->ReadByte(0x4E7AEA0, true);
+ UINT8 Ammo1pB = helpers->ReadByte(0x4E7AEA1, true);
+ float Flame1p = helpers->ReadFloat32(0x556CB30, true);
+ float Health1p = helpers->ReadFloat32(0x556C884, true);
+ UINT8 Ammo2pA = helpers->ReadByte(0x4E7AEA2, true);
+ UINT8 Ammo2pB = helpers->ReadByte(0x4E7AEA3, true);
+ float Flame2p = helpers->ReadFloat32(0x556CEC4, true);
+ float Health2p = helpers->ReadFloat32(0x556CC18, true);
+ UINT8 Shoot1p = helpers->ReadByte(0x4E7AEC8, true);
+ UINT8 Shoot2p = helpers->ReadByte(0x4E7AF00, true);
+
+ HWND hWnd = FindWindowA(0, ("GLUT"));
+
+ if (GetAsyncKeyState((VK_ESCAPE)) && (EscapeKeyExitViaPlugin == 1))
+ {
+ if (hWnd > NULL)
+ {
+ TerminateProcess(GetCurrentProcess(), 0);
+ }
+ }
+
+ for (int i = 0; i < SDL_NumJoysticks(); i++)
+ {
+ wchar_t* deviceGUIDString2 = new wchar_t[256];
+ int Device2GUID = GetPrivateProfileString(TEXT("Settings"), TEXT("Device2GUID"), NULL, deviceGUIDString2, 256, settingsFilename);
+ char joystick_guid[256];
+ sprintf(joystick_guid, "%S", deviceGUIDString2);
+ SDL_JoystickGUID guid, dev_guid;
+ int numJoysticks = SDL_NumJoysticks();
+ std::string njs = std::to_string(numJoysticks);
+ ((char)njs.c_str());
+ for (int i = 0; i < SDL_NumJoysticks(); i++)
+ {
+ extern int joystick1Index;
+ if (i == joystick1Index)
+ {
+ continue;
+ }
+ SDL_Joystick* js2 = SDL_JoystickOpen(i);
+ joystick_index2 = SDL_JoystickInstanceID(js2);
+ SDL_JoystickGUID guid = SDL_JoystickGetGUID(js2);
+ char guid_str[1024];
+ SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
+ const char* name = SDL_JoystickName(js2);
+ char text[256];
+ sprintf(text, "Joystick: %d / Name: %s / GUID: %s\n", i, name, guid_str);
+ guid = SDL_JoystickGetGUIDFromString(joystick_guid);
+ dev_guid = SDL_JoystickGetGUID(js2);
+ if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID)))
+ {
+ GameController2 = SDL_JoystickOpen(i);
+ ControllerHaptic2 = SDL_HapticOpenFromJoystick(GameController2);
+ break;
+ }
+ SDL_JoystickClose(js2);
+ }
+ haptic2 = ControllerHaptic2;
+ if ((SDL_HapticRumbleSupported(haptic2) == SDL_TRUE))
+ {
+ SDL_HapticRumbleInit;
+ SDL_HapticRumbleInit(ControllerHaptic2);
+ }
+ }
+
+ static UINT8 oldAmmo = 0;
+ UINT8 newAmmo = Ammo1pA;
+
+ static UINT8 oldAmmo2 = 0;
+ UINT8 newAmmo2 = Ammo2pA;
+
+ static float oldFlame = 0;
+ float newFlame = Flame1p;
+
+ static float oldFlame2 = 0;
+ float newFlame2 = Flame2p;
+
+ static float oldHealth = 0;
+ float newHealth = Health1p;
+
+ static float oldHealth2 = 0;
+ float newHealth2 = Health2p;
+
+ static UINT8 oldShoot = 0;
+ UINT8 newShoot = Shoot1p;
+
+ static UINT8 oldShoot2 = 0;
+ UINT8 newShoot2 = Shoot2p;
+
+ if (oldAmmo != newAmmo)
+ {
+ if (Ammo1pBool)
+ {
+ if ((Ammo1pB >= 0) && (Ammo1pA > 0))
+ {
+ if (HowtoRumbleGunEffect == 0)
+ {
+ double percentForce = ((Gun1pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->Rumble(percentForce, percentForce, percentLength);
+ }
+ else if (HowtoRumbleGunEffect == 1)
+ {
+ double percentForce = ((Gun1pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->Rumble(0, percentForce, percentLength);
+ }
+ else if (HowtoRumbleGunEffect == 2)
+ {
+ double percentForce = ((Gun1pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->Rumble(percentForce, 0, percentLength);
+ }
+ }
+ }
+
+ if ((Ammo1pA == 0) && (Ammo1pB == 0))
+ {
+ Ammo1pBool = false;
+ }
+ else
+ {
+ Ammo1pBool = true;
+ }
+ }
+
+ if (oldShoot != newShoot)
+ {
+ if (!Ammo1pBool)
+ {
+ if (Shoot1p == 1)
+ {
+ if (HowtoRumbleGunEffect == 0)
+ {
+ double percentForce = ((Gun1pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->Rumble(percentForce, percentForce, percentLength);
+ }
+ else if (HowtoRumbleGunEffect == 1)
+ {
+ double percentForce = ((Gun1pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->Rumble(0, percentForce, percentLength);
+ }
+ else if (HowtoRumbleGunEffect == 2)
+ {
+ double percentForce = ((Gun1pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->Rumble(percentForce, 0, percentLength);
+ }
+ }
+ }
+ }
+
+ if (oldAmmo2 != newAmmo2)
+ {
+ if (Ammo2pBool)
+ {
+ if ((Ammo2pB >= 0) && (Ammo2pA > 0))
+ {
+ if (HowtoRumbleGunEffect == 0)
+ {
+ double percentForce = ((Gun2pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->RumbleDevice2(percentForce, percentForce, percentLength);
+ }
+ else if (HowtoRumbleGunEffect == 1)
+ {
+ double percentForce = ((Gun2pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->RumbleDevice2(0, percentForce, percentLength);
+ }
+ else if (HowtoRumbleGunEffect == 2)
+ {
+ double percentForce = ((Gun2pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->RumbleDevice2(percentForce, 0, percentLength);
+ }
+ }
+ }
+
+ if ((Ammo2pA == 0) && (Ammo2pB == 0))
+ {
+ Ammo2pBool = false;
+ }
+ else
+ {
+ Ammo2pBool = true;
+ }
+ }
+
+ if (oldShoot2 != newShoot2)
+ {
+ if (!Ammo2pBool)
+ {
+ if (Shoot2p == 1)
+ {
+ if (HowtoRumbleGunEffect == 0)
+ {
+ double percentForce = ((Gun2pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->RumbleDevice2(percentForce, percentForce, percentLength);
+ }
+ else if (HowtoRumbleGunEffect == 1)
+ {
+ double percentForce = ((Gun2pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->RumbleDevice2(0, percentForce, percentLength);
+ }
+ else if (HowtoRumbleGunEffect == 2)
+ {
+ double percentForce = ((Gun2pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->RumbleDevice2(percentForce, 0, percentLength);
+ }
+ }
+ }
+ }
+
+ if (oldFlame != newFlame)
+ {
+ if (Flame1pBool)
+ {
+ if (Flame1p > 0)
+ {
+ if (HowtoRumbleFlameEffect == 0)
+ {
+ double percentForce = ((Flame1pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->Rumble(percentForce, percentForce, percentLength);
+ }
+ else if (HowtoRumbleFlameEffect == 1)
+ {
+ double percentForce = ((Flame1pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->Rumble(0, percentForce, percentLength);
+ }
+ else if (HowtoRumbleFlameEffect == 2)
+ {
+ double percentForce = ((Flame1pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->Rumble(percentForce, 0, percentLength);
+ }
+ }
+ }
+
+ if ((Flame1p <= 0) )
+ {
+ Flame1pBool = false;
+ }
+ else
+ {
+ Flame1pBool = true;
+ }
+ }
+
+ if (oldFlame2 != newFlame2)
+ {
+ if (Flame2pBool)
+ {
+ if (Flame2p > 0)
+ {
+ if (HowtoRumbleFlameEffect == 0)
+ {
+ double percentForce = ((Flame2pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->RumbleDevice2(percentForce, percentForce, percentLength);
+ }
+ else if (HowtoRumbleFlameEffect == 1)
+ {
+ double percentForce = ((Flame2pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->RumbleDevice2(0, percentForce, percentLength);
+ }
+ else if (HowtoRumbleFlameEffect == 2)
+ {
+ double percentForce = ((Flame2pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->RumbleDevice2(percentForce, 0, percentLength);
+ }
+ }
+ }
+
+ if ((Flame2p <= 0))
+ {
+ Flame2pBool = false;
+ }
+ else
+ {
+ Flame2pBool = true;
+ }
+ }
+
+ if (oldHealth != newHealth)
+ {
+ if (Health1pBool)
+ {
+ if (Health1p > 0)
+ {
+ if (HowtoRumbleHealthEffect == 0)
+ {
+ double percentForce = ((Health1pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->Rumble(percentForce, percentForce, percentLength);
+ }
+ else if (HowtoRumbleHealthEffect == 1)
+ {
+ double percentForce = ((Health1pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->Rumble(0, percentForce, percentLength);
+ }
+ else if (HowtoRumbleHealthEffect == 2)
+ {
+ double percentForce = ((Health1pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->Rumble(percentForce, 0, percentLength);
+ }
+ }
+ }
+
+ if ((Health1p == 0))
+ {
+ Health1pBool = false;
+ }
+ else
+ {
+ Health1pBool = true;
+ }
+ }
+
+ if (oldHealth2 != newHealth2)
+ {
+ if (Health2pBool)
+ {
+ if (Health2p > 0)
+ {
+ if (HowtoRumbleHealthEffect == 0)
+ {
+ double percentForce = ((Health2pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->RumbleDevice2(percentForce, percentForce, percentLength);
+ }
+ else if (HowtoRumbleHealthEffect == 1)
+ {
+ double percentForce = ((Health2pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->RumbleDevice2(0, percentForce, percentLength);
+ }
+ else if (HowtoRumbleHealthEffect == 2)
+ {
+ double percentForce = ((Health2pStrength) / 100.0);
+ double percentLength = configFeedbackLength;
+ triggers->RumbleDevice2(percentForce, 0, percentLength);
+ }
+ }
+ }
+
+ if ((Health2p == 0))
+ {
+ Health2pBool = false;
+ }
+ else
+ {
+ Health2pBool = true;
+ }
+ }
+
+ oldAmmo = newAmmo;
+ oldAmmo2 = newAmmo2;
+ oldFlame = newFlame;
+ oldFlame2 = newFlame2;
+ oldHealth = newHealth;
+ oldHealth2 = newHealth2;
+ oldShoot = newShoot;
+ oldShoot2 = newShoot2;
+}
\ No newline at end of file
diff --git a/Game Files/AliensExtermination.h b/Game Files/AliensExtermination.h
new file mode 100644
index 0000000..5b29156
--- /dev/null
+++ b/Game Files/AliensExtermination.h
@@ -0,0 +1,20 @@
+/*This file is part of FFB Arcade Plugin.
+FFB Arcade Plugin is free software : you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+FFB Arcade Plugin is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+GNU General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with FFB Arcade Plugin.If not, see < https://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+#include "../Common Files/Game.h"
+class AliensExtermination : public Game {
+
+public:
+ void FFBLoop(EffectConstants* constants, Helpers* helpers, EffectTriggers* triggers);
+};
\ No newline at end of file