2019-09-14 03:13:05 +02:00
|
|
|
/*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/>.
|
|
|
|
*/
|
|
|
|
|
2019-04-07 07:16:19 +02:00
|
|
|
#include <string>
|
|
|
|
#include "Outrun2Fake.h"
|
2019-05-15 09:25:41 +02:00
|
|
|
#include "SDL.h"
|
|
|
|
#include <Windows.h>
|
|
|
|
static EffectTriggers *myTriggers;
|
|
|
|
static EffectConstants *myConstants;
|
|
|
|
static Helpers *myHelpers;
|
|
|
|
static SDL_Event e;
|
2019-12-18 01:41:02 +01:00
|
|
|
static bool init = false;
|
2019-05-15 09:25:41 +02:00
|
|
|
static wchar_t *settingsFilename = TEXT(".\\FFBPlugin.ini");
|
|
|
|
static int ShowButtonNumbersForSetup = GetPrivateProfileInt(TEXT("Settings"), TEXT("ShowButtonNumbersForSetup"), 0, settingsFilename);
|
|
|
|
static int ChangeGearsViaPlugin = GetPrivateProfileInt(TEXT("Settings"), TEXT("ChangeGearsViaPlugin"), 0, settingsFilename);
|
|
|
|
static int Gear1 = GetPrivateProfileInt(TEXT("Settings"), TEXT("Gear1"), 0, settingsFilename);
|
|
|
|
static int Gear2 = GetPrivateProfileInt(TEXT("Settings"), TEXT("Gear2"), 0, settingsFilename);
|
|
|
|
static int Gear3 = GetPrivateProfileInt(TEXT("Settings"), TEXT("Gear3"), 0, settingsFilename);
|
|
|
|
static int Gear4 = GetPrivateProfileInt(TEXT("Settings"), TEXT("Gear4"), 0, settingsFilename);
|
|
|
|
static int Gear5 = GetPrivateProfileInt(TEXT("Settings"), TEXT("Gear5"), 0, settingsFilename);
|
|
|
|
static int Gear6 = GetPrivateProfileInt(TEXT("Settings"), TEXT("Gear6"), 0, settingsFilename);
|
|
|
|
static int SpeedStrength;
|
2019-04-07 07:16:19 +02:00
|
|
|
|
2019-12-18 01:41:02 +01:00
|
|
|
static int ThreadLoop()
|
2019-05-15 09:25:41 +02:00
|
|
|
{
|
2019-12-18 01:41:02 +01:00
|
|
|
int ff = myHelpers->ReadInt32(0x0827A1A0, /* isRelativeOffset */ false);
|
|
|
|
int ffwall = myHelpers->ReadInt32(0x08273FAC, /* isRelativeOffset */ false);
|
|
|
|
int ff3 = myHelpers->ReadInt32(0x0827A1DA, /* isRelativeOffset */ false);
|
|
|
|
int ff4 = myHelpers->ReadInt32(0x0827A35D, /* isRelativeOffset */ false);
|
|
|
|
int ff5 = myHelpers->ReadInt32(0x0827A1D4, /* isRelativeOffset */ false);
|
|
|
|
UINT8 ff6 = myHelpers->ReadByte(0x08670DC8, /* isRelativeOffset */ false); // steering
|
|
|
|
float ff7 = myHelpers->ReadFloat32(0x08273AD4, /* isRelativeOffset */ false);
|
|
|
|
UINT8 ff8 = myHelpers->ReadByte(0x08304ADC, /* isRelativeOffset */ false); // 1 when race
|
|
|
|
UINT8 ff9 = myHelpers->ReadByte(0x086749CA, /* isRelativeOffset */ false); // 1 when menu
|
|
|
|
UINT8 gear = myHelpers->ReadByte(0x0827A160, /* isRelativeOffset */ false); // gear address
|
|
|
|
float ffspeed = myHelpers->ReadFloat32(0x08273DF0, /* isRelativeOffset */ false); //speedo
|
|
|
|
UINT8 static oldgear = 0;
|
|
|
|
int static oldFloat = 0.0;
|
|
|
|
int newFloat = ff3;
|
|
|
|
int static oldFloat1 = 0.0;
|
|
|
|
int newFloat1 = ff4;
|
|
|
|
float newgear = gear;
|
|
|
|
|
|
|
|
if ((ffspeed >= 0.1) && (ffspeed <= 80))
|
|
|
|
{
|
|
|
|
SpeedStrength = 10;
|
|
|
|
}
|
|
|
|
else if ((ffspeed >= 80.1) && (ffspeed <= 130))
|
|
|
|
{
|
|
|
|
SpeedStrength = 20;
|
|
|
|
}
|
|
|
|
else if ((ffspeed >= 130.1) && (ffspeed <= 180))
|
|
|
|
{
|
|
|
|
SpeedStrength = 30;
|
|
|
|
}
|
|
|
|
else if ((ffspeed >= 180.1) && (ffspeed <= 220))
|
|
|
|
{
|
|
|
|
SpeedStrength = 40;
|
|
|
|
}
|
|
|
|
else if ((ffspeed >= 220.1) && (ffspeed <= 270))
|
|
|
|
{
|
|
|
|
SpeedStrength = 50;
|
|
|
|
}
|
|
|
|
else if ((ffspeed >= 270.1) && (ffspeed <= 320))
|
|
|
|
{
|
|
|
|
SpeedStrength = 60;
|
|
|
|
}
|
|
|
|
else if ((ffspeed >= 320.1) && (ffspeed <= 380))
|
|
|
|
{
|
|
|
|
SpeedStrength = 70;
|
|
|
|
}
|
|
|
|
else if ((ffspeed >= 380.1) && (ffspeed <= 430))
|
|
|
|
{
|
|
|
|
SpeedStrength = 80;
|
|
|
|
}
|
|
|
|
else if ((ffspeed >= 430.1) && (ffspeed <= 500))
|
|
|
|
{
|
|
|
|
SpeedStrength = 90;
|
|
|
|
}
|
|
|
|
else if ((ffspeed >= 500.1) && (ffspeed <= 1000))
|
|
|
|
{
|
|
|
|
SpeedStrength = 100;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SpeedStrength = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ff8 == 1)
|
|
|
|
{
|
|
|
|
if ((ff6 >= 0x00) & (ff6 < 0x7F))
|
2019-04-07 07:16:19 +02:00
|
|
|
{
|
2019-12-18 01:41:02 +01:00
|
|
|
double percentForce = ((127 - ff6) / 127.0);
|
|
|
|
double percentLength = 100;
|
|
|
|
myTriggers->Rumble(percentForce, 0, percentLength);
|
|
|
|
myTriggers->Constant(myConstants->DIRECTION_FROM_LEFT, percentForce);
|
2019-04-07 07:16:19 +02:00
|
|
|
}
|
2019-12-18 01:41:02 +01:00
|
|
|
if ((ff6 > 0x7F)& (ff6 < 0x100))
|
2019-04-07 07:16:19 +02:00
|
|
|
{
|
2019-12-18 01:41:02 +01:00
|
|
|
double percentForce = ((ff6 - 127) / 128.0);
|
|
|
|
double percentLength = 100;
|
|
|
|
myTriggers->Rumble(0, percentForce, percentLength);
|
|
|
|
myTriggers->Constant(myConstants->DIRECTION_FROM_RIGHT, percentForce);
|
2019-04-07 07:16:19 +02:00
|
|
|
}
|
2019-12-18 01:41:02 +01:00
|
|
|
}
|
|
|
|
if (ff9 == 1)
|
|
|
|
{
|
|
|
|
if ((ff6 >= 0x00) & (ff6 < 0x7F))
|
2019-04-07 07:16:19 +02:00
|
|
|
{
|
2019-12-18 01:41:02 +01:00
|
|
|
double percentForce = ((127 - ff6) / 127.0);
|
|
|
|
double percentLength = 100;
|
|
|
|
myTriggers->Rumble(percentForce, 0, percentLength);
|
|
|
|
myTriggers->Constant(myConstants->DIRECTION_FROM_LEFT, percentForce);
|
2019-04-07 07:16:19 +02:00
|
|
|
}
|
2019-12-18 01:41:02 +01:00
|
|
|
if ((ff6 > 0x7F)& (ff6 < 0x100))
|
2019-04-07 07:16:19 +02:00
|
|
|
{
|
2019-12-18 01:41:02 +01:00
|
|
|
double percentForce = ((ff6 - 127) / 128.0);
|
|
|
|
double percentLength = 100;
|
|
|
|
myTriggers->Rumble(0, percentForce, percentLength);
|
|
|
|
myTriggers->Constant(myConstants->DIRECTION_FROM_RIGHT, percentForce);
|
2019-04-07 07:16:19 +02:00
|
|
|
}
|
2019-12-18 01:41:02 +01:00
|
|
|
}
|
|
|
|
if (ff5 == 2)
|
|
|
|
{
|
|
|
|
if (oldFloat != newFloat)
|
2019-04-07 07:16:19 +02:00
|
|
|
{
|
2019-12-18 01:41:02 +01:00
|
|
|
double percentForce = SpeedStrength / 100.0;
|
|
|
|
double percentLength = 100;
|
|
|
|
myTriggers->Rumble(0, percentForce, percentLength);
|
|
|
|
myTriggers->Constant(myConstants->DIRECTION_FROM_RIGHT, percentForce);
|
2019-04-07 07:16:19 +02:00
|
|
|
}
|
2019-12-18 01:41:02 +01:00
|
|
|
}
|
|
|
|
else if (ff5 == 1)
|
|
|
|
{
|
|
|
|
if (oldFloat != newFloat)
|
2019-04-07 07:16:19 +02:00
|
|
|
{
|
2019-12-18 01:41:02 +01:00
|
|
|
double percentForce = SpeedStrength / 100.0;
|
|
|
|
double percentLength = 100;
|
|
|
|
myTriggers->Rumble(percentForce, 0, percentLength);
|
|
|
|
myTriggers->Constant(myConstants->DIRECTION_FROM_LEFT, percentForce);
|
2019-04-07 07:16:19 +02:00
|
|
|
}
|
2019-12-18 01:41:02 +01:00
|
|
|
}
|
2019-04-07 07:16:19 +02:00
|
|
|
|
2019-12-18 01:41:02 +01:00
|
|
|
if (oldFloat1 != newFloat1)
|
|
|
|
{
|
|
|
|
double percentForce = SpeedStrength / 100.0;
|
|
|
|
double percentLength = 100;
|
|
|
|
myTriggers->Rumble(percentForce, percentForce, percentLength);
|
|
|
|
myTriggers->Sine(200, 200, percentForce);
|
|
|
|
}
|
|
|
|
else if (ff == 8)
|
|
|
|
{
|
|
|
|
if (SpeedStrength > 0)
|
2019-05-15 09:25:41 +02:00
|
|
|
{
|
2019-12-18 01:41:02 +01:00
|
|
|
double percentForce = 0.1;
|
2019-05-15 09:25:41 +02:00
|
|
|
double percentLength = 100;
|
2019-10-30 07:03:50 +01:00
|
|
|
myTriggers->Rumble(percentForce, percentForce, percentLength);
|
2019-12-18 01:41:02 +01:00
|
|
|
myTriggers->Sine(70, 70, percentForce);
|
2019-05-15 09:25:41 +02:00
|
|
|
}
|
2019-12-18 01:41:02 +01:00
|
|
|
}
|
|
|
|
else if (ff == 4)
|
|
|
|
{
|
|
|
|
if (SpeedStrength > 0)
|
2019-05-15 09:25:41 +02:00
|
|
|
{
|
2019-12-18 01:41:02 +01:00
|
|
|
double percentForce = 0.2;
|
|
|
|
double percentLength = 50;
|
|
|
|
myTriggers->Rumble(percentForce, percentForce, percentLength);
|
|
|
|
myTriggers->Sine(50, 50, percentForce);
|
2019-05-15 09:25:41 +02:00
|
|
|
}
|
2019-12-18 01:41:02 +01:00
|
|
|
}
|
|
|
|
else if (ff == 16)
|
|
|
|
{
|
|
|
|
if (SpeedStrength > 0)
|
2019-05-15 09:25:41 +02:00
|
|
|
{
|
2019-12-18 01:41:02 +01:00
|
|
|
double percentForce = 0.2;
|
|
|
|
double percentLength = 50;
|
|
|
|
myTriggers->Rumble(percentForce, percentForce, percentLength);
|
|
|
|
myTriggers->Sine(100, 50, percentForce);
|
2019-05-15 09:25:41 +02:00
|
|
|
}
|
2019-04-07 07:16:19 +02:00
|
|
|
}
|
2019-12-18 01:41:02 +01:00
|
|
|
|
|
|
|
oldFloat = newFloat;
|
|
|
|
oldFloat1 = newFloat1;
|
2019-05-15 09:25:41 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2019-12-18 01:41:02 +01:00
|
|
|
|
|
|
|
static DWORD WINAPI RunningLoop(LPVOID lpParam)
|
|
|
|
{
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
ThreadLoop();
|
|
|
|
Sleep(16);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-15 09:25:41 +02:00
|
|
|
void OutRun2Fake::FFBLoop(EffectConstants *constants, Helpers *helpers, EffectTriggers* triggers) {
|
2019-12-18 01:41:02 +01:00
|
|
|
|
|
|
|
if (!init)
|
|
|
|
{
|
|
|
|
myTriggers = triggers;
|
|
|
|
myConstants = constants;
|
|
|
|
myHelpers = helpers;
|
|
|
|
CreateThread(NULL, 0, RunningLoop, NULL, 0, NULL);
|
|
|
|
init = true;
|
|
|
|
}
|
|
|
|
|
2019-05-15 09:25:41 +02:00
|
|
|
int ff = myHelpers->ReadInt32(0x0827A1A0, /* isRelativeOffset */ false);
|
|
|
|
helpers->log("got value: ");
|
|
|
|
std::string ffs = std::to_string(ff);
|
|
|
|
helpers->log((char *)ffs.c_str());
|
|
|
|
|
|
|
|
while (SDL_WaitEvent(&e) != 0)
|
2019-04-07 07:16:19 +02:00
|
|
|
{
|
2019-05-15 09:25:41 +02:00
|
|
|
UINT8 transmission = helpers->ReadByte(0x082932C2, /* isRelativeOffset */ false); // Auto or Manual
|
|
|
|
myTriggers = triggers;
|
|
|
|
myConstants = constants;
|
|
|
|
myHelpers = helpers;
|
2019-09-27 22:23:02 +02:00
|
|
|
|
2019-05-15 09:25:41 +02:00
|
|
|
if (ShowButtonNumbersForSetup == 1)
|
|
|
|
{
|
|
|
|
if (e.type == SDL_JOYBUTTONDOWN)
|
|
|
|
{
|
2019-09-27 22:23:02 +02:00
|
|
|
if (e.jbutton.button >= 0)
|
2019-05-15 09:25:41 +02:00
|
|
|
{
|
2019-09-27 22:23:02 +02:00
|
|
|
char buff[100];
|
|
|
|
sprintf_s(buff, "Button %d Pressed", e.jbutton.button);
|
|
|
|
MessageBoxA(NULL, buff, "", NULL);
|
2019-05-15 09:25:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-09-27 22:23:02 +02:00
|
|
|
|
2019-05-15 09:25:41 +02:00
|
|
|
if (e.type == SDL_JOYBUTTONDOWN)
|
|
|
|
{
|
|
|
|
if (ChangeGearsViaPlugin == 1)
|
|
|
|
{
|
|
|
|
if ((ChangeGearsViaPlugin == 1) && (transmission == 1))
|
|
|
|
{
|
|
|
|
if (e.jbutton.button == Gear1)
|
|
|
|
{
|
|
|
|
helpers->WriteByte(0x0827A160, 0x01, false);
|
|
|
|
}
|
|
|
|
else if (e.jbutton.button == Gear2)
|
|
|
|
{
|
|
|
|
helpers->WriteByte(0x0827A160, 0x02, false);
|
|
|
|
}
|
|
|
|
else if (e.jbutton.button == Gear3)
|
|
|
|
{
|
|
|
|
helpers->WriteByte(0x0827A160, 0x03, false);
|
|
|
|
}
|
|
|
|
else if (e.jbutton.button == Gear4)
|
|
|
|
{
|
|
|
|
helpers->WriteByte(0x0827A160, 0x04, false);
|
|
|
|
}
|
|
|
|
else if (e.jbutton.button == Gear5)
|
|
|
|
{
|
|
|
|
helpers->WriteByte(0x0827A160, 0x05, false);
|
|
|
|
}
|
|
|
|
else if (e.jbutton.button == Gear6)
|
|
|
|
{
|
|
|
|
helpers->WriteByte(0x0827A160, 0x06, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-07 07:16:19 +02:00
|
|
|
}
|
|
|
|
}
|