mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
gitadora: various fixes for wailing (#513)
## Link to GitHub Issue, if one exists Fixes #512 ## Description of change Fix digital wailing not being recognized consistently. Also address the fact that wailing was completely broken when lefty mode was on. This requires a new option that the user needs to check off in the configurator since we can't magically guess if the user is holding the guitar in lefty mode. - [x] fix downward wail - [x] digital lefty mode - [x] implement all of this for arena model i/o - [x] test dx cab 2p - [x] lefty toggle in overlay - [x] fix analog not working for 2p guitar - [ ] analog lefty mode? ## Testing Checked GW and GW Delta
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
#include "util/libutils.h"
|
#include "util/libutils.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/sigscan.h"
|
#include "util/sigscan.h"
|
||||||
|
#include "util/socd_cleaner.h"
|
||||||
#include "hooks/setupapihook.h"
|
#include "hooks/setupapihook.h"
|
||||||
|
|
||||||
namespace games::gitadora {
|
namespace games::gitadora {
|
||||||
@@ -18,6 +19,8 @@ namespace games::gitadora {
|
|||||||
// settings
|
// settings
|
||||||
bool TWOCHANNEL = false;
|
bool TWOCHANNEL = false;
|
||||||
std::optional<unsigned int> CAB_TYPE = std::nullopt;
|
std::optional<unsigned int> CAB_TYPE = std::nullopt;
|
||||||
|
bool P1_LEFTY = false;
|
||||||
|
bool P2_LEFTY = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prevent GitaDora from creating folders on F drive
|
* Prevent GitaDora from creating folders on F drive
|
||||||
@@ -220,6 +223,9 @@ namespace games::gitadora {
|
|||||||
GRAPHICS_WINDOWED && !cfg::CONFIGURATOR_STANDALONE) {
|
GRAPHICS_WINDOWED && !cfg::CONFIGURATOR_STANDALONE) {
|
||||||
overlay::UI_SCALE_PERCENT = 250;
|
overlay::UI_SCALE_PERCENT = 250;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for guitar wail SOCD cleaning
|
||||||
|
socd::ALGORITHM = socd::SocdAlgorithm::PreferRecent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ namespace games::gitadora {
|
|||||||
// settings
|
// settings
|
||||||
extern bool TWOCHANNEL;
|
extern bool TWOCHANNEL;
|
||||||
extern std::optional<unsigned int> CAB_TYPE;
|
extern std::optional<unsigned int> CAB_TYPE;
|
||||||
|
extern bool P1_LEFTY;
|
||||||
|
extern bool P2_LEFTY;
|
||||||
|
|
||||||
class GitaDoraGame : public games::Game {
|
class GitaDoraGame : public games::Game {
|
||||||
public:
|
public:
|
||||||
@@ -38,4 +40,12 @@ namespace games::gitadora {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_player_lefty(size_t player) {
|
||||||
|
if (player == 0) {
|
||||||
|
return P1_LEFTY;
|
||||||
|
} else if (player == 1) {
|
||||||
|
return P2_LEFTY;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,9 +107,18 @@ std::string games::gitadora::get_buttons_help() {
|
|||||||
// keep to max 100 characters wide
|
// keep to max 100 characters wide
|
||||||
return
|
return
|
||||||
"guitar:\n"
|
"guitar:\n"
|
||||||
|
"\n"
|
||||||
" < R G B Y P --- Pick ] \n"
|
" < R G B Y P --- Pick ] \n"
|
||||||
"\n"
|
"\n"
|
||||||
|
" If you hold your guitar left-handed (frets on the right hand):\n"
|
||||||
|
" * bind the buttons here as righty and use the in-game option\n"
|
||||||
|
" to turn on LEFT mode to flip the order of buttons.\n"
|
||||||
|
" * turn on GitaDora Lefty Guitar option in Options tab so that\n"
|
||||||
|
" wailing is recognized correctly.\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
"drums:\n"
|
"drums:\n"
|
||||||
|
"\n"
|
||||||
" LeftCymbal RightCymbal\n"
|
" LeftCymbal RightCymbal\n"
|
||||||
" HiHat HiTom LowTom \n"
|
" HiHat HiTom LowTom \n"
|
||||||
" Snare FloorTom \n"
|
" Snare FloorTom \n"
|
||||||
@@ -117,10 +126,30 @@ std::string games::gitadora::get_buttons_help() {
|
|||||||
" Left Bass\n"
|
" Left Bass\n"
|
||||||
" Pedal Pedal\n"
|
" Pedal Pedal\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Drums are NOT velocity-sensitive!\n"
|
" Drums are NOT velocity-sensitive!\n"
|
||||||
"\n"
|
"\n"
|
||||||
"For MIDI drums with Open/Closed HiHat configurations, bind variations below. "
|
" For MIDI drums with Open/Closed HiHat configurations or pads with\n"
|
||||||
"v2_drum algorithm might work better for those drums."
|
" multiple hit zones, ensure you bind all variation using the Pages\n"
|
||||||
|
" button at the bottom."
|
||||||
|
;
|
||||||
|
}
|
||||||
|
std::string games::gitadora::get_analogs_help() {
|
||||||
|
// keep to max 100 characters wide
|
||||||
|
return
|
||||||
|
"guitar:\n"
|
||||||
|
"\n"
|
||||||
|
"X axis: 0% when body is held facing monitor, 50% when facing flat on a table\n"
|
||||||
|
"Y axis: 50% when held horizontal, 0% when neck is raised, 100% pointing down\n"
|
||||||
|
"Z axis: 50% at rest, 100% when swinging neck toward monitor (only used in XG series)\n"
|
||||||
|
"\n"
|
||||||
|
"You need both X and Y axis for up/down wail to work correctly in-game.\n"
|
||||||
|
"If you only have Y axis, consider using digital wailing instead.\n"
|
||||||
|
"\n"
|
||||||
|
"Ensure you clear all analog bindings if you want to use digital wailing.\n"
|
||||||
|
"\n"
|
||||||
|
"If you hold your guitar left-handed (frets on the right hand),\n"
|
||||||
|
"analog bindings will likely not work as intended.\n"
|
||||||
|
"Consider using digital wailing in Buttons tab."
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ namespace games::gitadora {
|
|||||||
// getters
|
// getters
|
||||||
std::vector<Button> &get_buttons();
|
std::vector<Button> &get_buttons();
|
||||||
std::string get_buttons_help();
|
std::string get_buttons_help();
|
||||||
|
std::string get_analogs_help();
|
||||||
std::vector<Analog> &get_analogs();
|
std::vector<Analog> &get_analogs();
|
||||||
std::vector<Light> &get_lights();
|
std::vector<Light> &get_lights();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
|
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "util/utils.h"
|
#include "games/gitadora/gitadora.h"
|
||||||
|
#include "util/socd_cleaner.h"
|
||||||
#include "util/time.h"
|
#include "util/time.h"
|
||||||
|
#include "util/utils.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "j33i.h"
|
#include "j33i.h"
|
||||||
|
|
||||||
|
|
||||||
#define GUITAR_BTN_R 0x7
|
#define GUITAR_BTN_R 0x7
|
||||||
#define GUITAR_BTN_G 0x6
|
#define GUITAR_BTN_G 0x6
|
||||||
#define GUITAR_BTN_B 0x5
|
#define GUITAR_BTN_B 0x5
|
||||||
@@ -111,8 +112,8 @@ bool games::gitadora::J33ISerialDevice::parse_msg(
|
|||||||
|
|
||||||
auto &analogs = get_analogs();
|
auto &analogs = get_analogs();
|
||||||
|
|
||||||
// get x,y,z analog values [-0.5f, 0.5f], centered at 0.f
|
// get x,y,z analog values [-0.5f, 0.5f]
|
||||||
float x = 0.f;
|
float x = is_player_lefty(0) ? 0.3f : -0.5f;
|
||||||
auto x_analog = analogs[Analogs::GuitarP1WailX];
|
auto x_analog = analogs[Analogs::GuitarP1WailX];
|
||||||
if (x_analog.isSet()) {
|
if (x_analog.isSet()) {
|
||||||
x = GameAPI::Analogs::getState(RI_MGR, x_analog) - 0.5f;
|
x = GameAPI::Analogs::getState(RI_MGR, x_analog) - 0.5f;
|
||||||
@@ -123,11 +124,6 @@ bool games::gitadora::J33ISerialDevice::parse_msg(
|
|||||||
if (y_analog.isSet()) {
|
if (y_analog.isSet()) {
|
||||||
y = GameAPI::Analogs::getState(RI_MGR, y_analog) - 0.5f;
|
y = GameAPI::Analogs::getState(RI_MGR, y_analog) - 0.5f;
|
||||||
}
|
}
|
||||||
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::GuitarP1WailUp])) {
|
|
||||||
y = -0.5f;
|
|
||||||
} else if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::GuitarP1WailDown])) {
|
|
||||||
y = 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float z = 0.f;
|
float z = 0.f;
|
||||||
auto z_analog = analogs[Analogs::GuitarP1WailZ];
|
auto z_analog = analogs[Analogs::GuitarP1WailZ];
|
||||||
@@ -135,6 +131,31 @@ bool games::gitadora::J33ISerialDevice::parse_msg(
|
|||||||
z = GameAPI::Analogs::getState(RI_MGR, z_analog) - 0.5f;
|
z = GameAPI::Analogs::getState(RI_MGR, z_analog) - 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle digital wail up/down
|
||||||
|
const auto wail_up = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::GuitarP1WailUp]);
|
||||||
|
const auto wail_down = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::GuitarP1WailDown]);
|
||||||
|
const auto wail_result =
|
||||||
|
socd::get_guitar_wail(0, wail_up, wail_down, get_performance_milliseconds());
|
||||||
|
if (!is_player_lefty(0)) {
|
||||||
|
// righty
|
||||||
|
if (wail_result == socd::TiltUp) {
|
||||||
|
x = 0;
|
||||||
|
y = -0.5f;
|
||||||
|
} else if (wail_result == socd::TiltDown) {
|
||||||
|
x = -0.5f;
|
||||||
|
y = 0.5f;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// lefty
|
||||||
|
if (wail_result == socd::TiltUp) {
|
||||||
|
x = 0.f;
|
||||||
|
y = 0.f;
|
||||||
|
} else if (wail_result == socd::TiltDown) {
|
||||||
|
x = 0.5f;
|
||||||
|
y = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// convert x,y,z to unsigned integer values that the game expects
|
// convert x,y,z to unsigned integer values that the game expects
|
||||||
const uint16_t x_int = x * ARENA_MODEL_WAIL_MAX * 2;
|
const uint16_t x_int = x * ARENA_MODEL_WAIL_MAX * 2;
|
||||||
const uint16_t y_int = y * ARENA_MODEL_WAIL_MAX * 2;
|
const uint16_t y_int = y * ARENA_MODEL_WAIL_MAX * 2;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ namespace games {
|
|||||||
static robin_hood::unordered_map<std::string, std::vector<Button>> buttons_keypads;
|
static robin_hood::unordered_map<std::string, std::vector<Button>> buttons_keypads;
|
||||||
static robin_hood::unordered_map<std::string, std::vector<Button>> buttons_overlay;
|
static robin_hood::unordered_map<std::string, std::vector<Button>> buttons_overlay;
|
||||||
static robin_hood::unordered_map<std::string, std::string> buttons_help;
|
static robin_hood::unordered_map<std::string, std::string> buttons_help;
|
||||||
|
static robin_hood::unordered_map<std::string, std::string> analogs_help;
|
||||||
static robin_hood::unordered_map<std::string, std::vector<Analog> &> analogs;
|
static robin_hood::unordered_map<std::string, std::vector<Analog> &> analogs;
|
||||||
static robin_hood::unordered_map<std::string, std::vector<Light> &> lights;
|
static robin_hood::unordered_map<std::string, std::vector<Light> &> lights;
|
||||||
static robin_hood::unordered_map<std::string, std::vector<Option>> options;
|
static robin_hood::unordered_map<std::string, std::vector<Option>> options;
|
||||||
@@ -107,6 +108,7 @@ namespace games {
|
|||||||
games.push_back(gitadora);
|
games.push_back(gitadora);
|
||||||
buttons.insert({ gitadora, gitadora::get_buttons() });
|
buttons.insert({ gitadora, gitadora::get_buttons() });
|
||||||
buttons_help.insert({ gitadora, gitadora::get_buttons_help() });
|
buttons_help.insert({ gitadora, gitadora::get_buttons_help() });
|
||||||
|
analogs_help.insert({ gitadora, gitadora::get_analogs_help() });
|
||||||
analogs.insert({ gitadora, gitadora::get_analogs() });
|
analogs.insert({ gitadora, gitadora::get_analogs() });
|
||||||
lights.insert({ gitadora, gitadora::get_lights() });
|
lights.insert({ gitadora, gitadora::get_lights() });
|
||||||
file_hints[gitadora].emplace_back("gdxg.dll");
|
file_hints[gitadora].emplace_back("gdxg.dll");
|
||||||
@@ -349,6 +351,15 @@ namespace games {
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string get_analogs_help(const std::string &game) {
|
||||||
|
initialize();
|
||||||
|
auto it = analogs_help.find(game);
|
||||||
|
if (it == analogs_help.end()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
static std::vector<Button> gen_buttons_keypads(const std::string &game) {
|
static std::vector<Button> gen_buttons_keypads(const std::string &game) {
|
||||||
auto buttons = GameAPI::Buttons::getButtons(game);
|
auto buttons = GameAPI::Buttons::getButtons(game);
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ namespace games {
|
|||||||
const std::vector<std::string> &get_games();
|
const std::vector<std::string> &get_games();
|
||||||
std::vector<Button> *get_buttons(const std::string &game);
|
std::vector<Button> *get_buttons(const std::string &game);
|
||||||
std::string get_buttons_help(const std::string &game);
|
std::string get_buttons_help(const std::string &game);
|
||||||
|
std::string get_analogs_help(const std::string &game);
|
||||||
std::vector<Button> *get_buttons_keypads(const std::string &game);
|
std::vector<Button> *get_buttons_keypads(const std::string &game);
|
||||||
std::vector<Button> *get_buttons_overlay(const std::string &game);
|
std::vector<Button> *get_buttons_overlay(const std::string &game);
|
||||||
std::vector<Analog> *get_analogs(const std::string &game);
|
std::vector<Analog> *get_analogs(const std::string &game);
|
||||||
|
|||||||
@@ -609,6 +609,17 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
if (options[launcher::Options::GitaDoraTwoChannelAudio].value_bool()) {
|
if (options[launcher::Options::GitaDoraTwoChannelAudio].value_bool()) {
|
||||||
games::gitadora::TWOCHANNEL = true;
|
games::gitadora::TWOCHANNEL = true;
|
||||||
}
|
}
|
||||||
|
if (options[launcher::Options::GitaDoraLefty].is_active()) {
|
||||||
|
const auto text = options[launcher::Options::GitaDoraLefty].value_text();
|
||||||
|
if (text == "p1") {
|
||||||
|
games::gitadora::P1_LEFTY = true;
|
||||||
|
} else if (text == "p2") {
|
||||||
|
games::gitadora::P2_LEFTY = true;
|
||||||
|
} else if (text == "both") {
|
||||||
|
games::gitadora::P1_LEFTY = true;
|
||||||
|
games::gitadora::P2_LEFTY = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (options[launcher::Options::LoadDDRModule].value_bool()) {
|
if (options[launcher::Options::LoadDDRModule].value_bool()) {
|
||||||
attach_ddr = true;
|
attach_ddr = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -978,6 +978,26 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.category = "Game Options",
|
.category = "Game Options",
|
||||||
.elements = {{"1", "DX"}, {"2", "SD"}, {"3", "SD2 - white cab"}},
|
.elements = {{"1", "DX"}, {"2", "SD"}, {"3", "SD2 - white cab"}},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// GitaDoraLefty
|
||||||
|
.title = "GitaDora Lefty Guitar (for Digital Wailing)",
|
||||||
|
.name = "gdlefty",
|
||||||
|
.desc = "Enables lefty mode, flipping motion sensor directions. Default: off.\n\n"
|
||||||
|
"Without this option, enabling LEFT in the game option will continuously trigger UP wail.\n\n"
|
||||||
|
"Has no effect if you are using analog bindings for X/Y axis; expectation is that your controller "
|
||||||
|
"handles this correctly (most do not, however).\n\n"
|
||||||
|
"As always, remember to restart the game after changing options. If you need to change in the game, "
|
||||||
|
"use the I/O panel overlay window",
|
||||||
|
.type = OptionType::Enum,
|
||||||
|
.game_name = "GitaDora",
|
||||||
|
.category = "Game Options",
|
||||||
|
.elements = {
|
||||||
|
{"off", "both righty"},
|
||||||
|
{"p1", "p1 is lefty"},
|
||||||
|
{"p2", "p2 is lefty"},
|
||||||
|
{"both", "both lefty"},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.title = "Force Load Jubeat Module",
|
.title = "Force Load Jubeat Module",
|
||||||
.name = "jb",
|
.name = "jb",
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ namespace launcher {
|
|||||||
LoadGitaDoraModule,
|
LoadGitaDoraModule,
|
||||||
GitaDoraTwoChannelAudio,
|
GitaDoraTwoChannelAudio,
|
||||||
GitaDoraCabinetType,
|
GitaDoraCabinetType,
|
||||||
|
GitaDoraLefty,
|
||||||
LoadJubeatModule,
|
LoadJubeatModule,
|
||||||
LoadReflecBeatModule,
|
LoadReflecBeatModule,
|
||||||
LoadShogikaiModule,
|
LoadShogikaiModule,
|
||||||
|
|||||||
+88
-42
@@ -7,6 +7,8 @@
|
|||||||
#include "util/detour.h"
|
#include "util/detour.h"
|
||||||
#include "util/libutils.h"
|
#include "util/libutils.h"
|
||||||
#include "util/circular_buffer.h"
|
#include "util/circular_buffer.h"
|
||||||
|
#include "util/socd_cleaner.h"
|
||||||
|
#include "util/time.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "cfg/api.h"
|
#include "cfg/api.h"
|
||||||
#include "acio/icca/icca.h"
|
#include "acio/icca/icca.h"
|
||||||
@@ -336,6 +338,9 @@ static int __cdecl gfdm_unit2_boot_initialize() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr int LEFTY_X_CENTER = 2040;
|
||||||
|
|
||||||
|
// this seems to be only used in the I/O test menu, not in gameplay
|
||||||
static void *__cdecl gfdm_unit_get_button_p(void *a1, int a2, size_t player) {
|
static void *__cdecl gfdm_unit_get_button_p(void *a1, int a2, size_t player) {
|
||||||
memset(a1, 0, 64);
|
memset(a1, 0, 64);
|
||||||
|
|
||||||
@@ -344,31 +349,61 @@ static void *__cdecl gfdm_unit_get_button_p(void *a1, int a2, size_t player) {
|
|||||||
return a1;
|
return a1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// log_info("gitadora", "gfdm_unit_get_button_p: a2={}, player={}", a2, player);
|
||||||
|
|
||||||
// get buttons
|
// get buttons
|
||||||
auto &buttons = games::gitadora::get_buttons();
|
auto &buttons = games::gitadora::get_buttons();
|
||||||
auto &analogs = games::gitadora::get_analogs();
|
auto &analogs = games::gitadora::get_analogs();
|
||||||
|
const auto wail_up =
|
||||||
|
Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[12 + 11 * (size_t) player]));
|
||||||
|
const auto wail_down =
|
||||||
|
Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[13 + 11 * (size_t) player]));
|
||||||
|
const auto wail_result =
|
||||||
|
socd::get_guitar_wail(player, wail_up, wail_down, get_performance_milliseconds());
|
||||||
|
|
||||||
// X
|
// wail X
|
||||||
((int *) a1)[4] = a2 == 1 ? 4080 : -4080;
|
((int *) a1)[4] = games::gitadora::is_player_lefty(player) ? LEFTY_X_CENTER : -4080;
|
||||||
if (analogs.at(player * 3 + 0).isSet())
|
auto &analog_x = analogs.at(gitadora_analog_mapping[player * 4 + 0]);
|
||||||
((int *) a1)[4] = lroundf(Analogs::getState(
|
if (analog_x.isSet())
|
||||||
RI_MGR, analogs.at(gitadora_analog_mapping[player * 4 + 0])) * 8160.f) - 4080;
|
((int *) a1)[4] = lroundf(Analogs::getState(RI_MGR, analog_x) * 8160.f) - 4080;
|
||||||
|
|
||||||
// Y
|
// wail Y
|
||||||
((int *) a1)[5] = 0;
|
((int *) a1)[5] = 0;
|
||||||
if (analogs.at(player * 3 + 1).isSet())
|
auto &analog_y = analogs.at(gitadora_analog_mapping[player * 4 + 1]);
|
||||||
((int *) a1)[5] = lroundf(Analogs::getState(
|
if (analog_y.isSet()) {
|
||||||
RI_MGR, analogs.at(gitadora_analog_mapping[player * 4 + 1])) * 8160.f) - 4080;
|
((int *) a1)[5] = lroundf(Analogs::getState(RI_MGR, analog_y) * 8160.f) - 4080;
|
||||||
if (Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[12 + 11 * (size_t) player])))
|
}
|
||||||
((int *) a1)[5] = -4080;
|
|
||||||
if (Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[13 + 11 * (size_t) player])))
|
|
||||||
((int *) a1)[5] = 4080;
|
|
||||||
|
|
||||||
// Z
|
// digital wailing
|
||||||
|
if (!games::gitadora::is_player_lefty(player)) {
|
||||||
|
// righty
|
||||||
|
if (wail_result == socd::TiltUp) {
|
||||||
|
// top center
|
||||||
|
((int *) a1)[4] = 0; // X
|
||||||
|
((int *) a1)[5] = -4080; // Y
|
||||||
|
} else if (wail_result == socd::TiltDown) {
|
||||||
|
// bottom left; for lefty, bottom right
|
||||||
|
((int *) a1)[4] = -4080; // X
|
||||||
|
((int *) a1)[5] = 4080; // Y
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// lefty
|
||||||
|
if (wail_result == socd::TiltUp) {
|
||||||
|
// left
|
||||||
|
((int *) a1)[4] = -4080; // X
|
||||||
|
((int *) a1)[5] = 0; // Y
|
||||||
|
} else if (wail_result == socd::TiltDown) {
|
||||||
|
// right
|
||||||
|
((int *) a1)[4] = 4080; // X
|
||||||
|
((int *) a1)[5] = 0; // Y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wail Z
|
||||||
((int *) a1)[6] = 0;
|
((int *) a1)[6] = 0;
|
||||||
if (analogs.at(player * 3 + 2).isSet())
|
auto &analog_z = analogs.at(gitadora_analog_mapping[player * 4 + 2]);
|
||||||
((int *) a1)[6] = lroundf(Analogs::getState(
|
if (analog_z.isSet())
|
||||||
RI_MGR, analogs.at(gitadora_analog_mapping[player * 4 + 2])) * 8160.f) - 4080;
|
((int *) a1)[6] = lroundf(Analogs::getState(RI_MGR, analog_z) * 8160.f) - 4080;
|
||||||
|
|
||||||
// return the same buffer
|
// return the same buffer
|
||||||
return a1;
|
return a1;
|
||||||
@@ -585,63 +620,74 @@ static long __cdecl gfdm_unit2_get_input(int device) {
|
|||||||
return gfdm_unit_get_input_p(device, 1);
|
return gfdm_unit_get_input_p(device, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is used in gameplay
|
||||||
static long __cdecl gfdm_unit_get_sensor_gf_p(int a1, int a2, size_t player) {
|
static long __cdecl gfdm_unit_get_sensor_gf_p(int a1, int a2, size_t player) {
|
||||||
|
|
||||||
// return if it's actually drum mania
|
// return if it's actually drum mania
|
||||||
if (games::gitadora::is_drum())
|
if (games::gitadora::is_drum())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// log_info("gitadora", "gfdm_unit_get_sensor_gf_p: a1={}, a2={}, player={}", a1, a2, player);
|
||||||
|
|
||||||
// get buttons and analogs
|
// get buttons and analogs
|
||||||
auto &buttons = games::gitadora::get_buttons();
|
auto &buttons = games::gitadora::get_buttons();
|
||||||
auto &analogs = games::gitadora::get_analogs();
|
auto &analogs = games::gitadora::get_analogs();
|
||||||
|
|
||||||
// X
|
// figure out digital wail Y
|
||||||
|
const size_t offset = (size_t) player * 11;
|
||||||
|
const auto wail_up = Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[12 + offset]));
|
||||||
|
const auto wail_down = Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[13 + offset]));
|
||||||
|
const auto wail_result = socd::get_guitar_wail(player, wail_up, wail_down, get_performance_milliseconds());
|
||||||
|
|
||||||
|
// wail X
|
||||||
if (a2 == 0) {
|
if (a2 == 0) {
|
||||||
|
long ret = games::gitadora::is_player_lefty(player) ? LEFTY_X_CENTER : -4080;
|
||||||
|
|
||||||
// analog override
|
// analog override
|
||||||
if (analogs.at(gitadora_analog_mapping[player * 3 + 0]).isSet()) {
|
auto &analog_x = analogs.at(gitadora_analog_mapping[player * 4 + 0]);
|
||||||
return lroundf(Analogs::getState(
|
if (analog_x.isSet()) {
|
||||||
RI_MGR, analogs.at(gitadora_analog_mapping[player * 4 + 0])) * 8160.f) - 4080;
|
ret = lroundf(Analogs::getState(RI_MGR, analog_x) * 8160.f) - 4080;
|
||||||
|
}
|
||||||
|
|
||||||
|
// digital wail up/down
|
||||||
|
if (wail_result == socd::TiltUp) {
|
||||||
|
ret = games::gitadora::is_player_lefty(player) ? -4080 : 0;
|
||||||
|
} else if (wail_result == socd::TiltDown) {
|
||||||
|
ret = games::gitadora::is_player_lefty(player) ? +4080 : -4080;
|
||||||
}
|
}
|
||||||
|
|
||||||
// default
|
// default
|
||||||
return a1 == 1 ? 4080 : -4080;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Y
|
// wail Y
|
||||||
if (a2 == 1) {
|
if (a2 == 1) {
|
||||||
|
long ret = 0;
|
||||||
|
|
||||||
// analog override
|
// analog override
|
||||||
if (analogs.at(player * 3 + 1).isSet()) {
|
auto &analog_y = analogs.at(gitadora_analog_mapping[player * 4 + 1]);
|
||||||
return lroundf(Analogs::getState(
|
if (analog_y.isSet()) {
|
||||||
RI_MGR, analogs.at(gitadora_analog_mapping[player * 4 + 1])) * 8160.f) - 4080;
|
ret = lroundf(Analogs::getState(RI_MGR, analog_y) * 8160.f) - 4080;
|
||||||
}
|
}
|
||||||
|
|
||||||
// variables
|
// digital wail up/down
|
||||||
long ret = 0;
|
if (wail_result == socd::TiltUp) {
|
||||||
size_t offset = (size_t) player * 11;
|
ret = games::gitadora::is_player_lefty(player) ? 0 : -4080;
|
||||||
|
} else if (wail_result == socd::TiltDown) {
|
||||||
// wail up
|
ret = games::gitadora::is_player_lefty(player) ? 0 : 4080;
|
||||||
if (Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[12 + offset]))) {
|
|
||||||
ret -= 4080;
|
|
||||||
}
|
|
||||||
|
|
||||||
// wail down
|
|
||||||
if (Buttons::getState(RI_MGR, buttons.at(gitadora_button_mapping[13 + offset]))) {
|
|
||||||
ret += 4080;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return value
|
// return value
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Z
|
// wail Z
|
||||||
if (a2 == 2) {
|
if (a2 == 2) {
|
||||||
|
|
||||||
// analog override
|
// analog override
|
||||||
if (analogs.at(gitadora_analog_mapping[player * 3 + 2]).isSet()) {
|
auto &analog_z = analogs.at(gitadora_analog_mapping[player * 4 + 2]);
|
||||||
return lroundf(Analogs::getState(
|
if (analog_z.isSet()) {
|
||||||
RI_MGR, analogs.at(gitadora_analog_mapping[player * 4 + 2])) * 8160.f) - 4080;
|
return lroundf(Analogs::getState(RI_MGR, analog_z) * 8160.f) - 4080;
|
||||||
}
|
}
|
||||||
|
|
||||||
// default
|
// default
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ namespace overlay::windows {
|
|||||||
// help text for binding buttons, if the game has one
|
// help text for binding buttons, if the game has one
|
||||||
const auto help_text = games::get_buttons_help(this->games_selected_name);
|
const auto help_text = games::get_buttons_help(this->games_selected_name);
|
||||||
if (!help_text.empty()) {
|
if (!help_text.empty()) {
|
||||||
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "Button Layout");
|
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "Button Bindings");
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::TextWrapped("%s", help_text.c_str());
|
ImGui::TextWrapped("%s", help_text.c_str());
|
||||||
ImGui::TextUnformatted("");
|
ImGui::TextUnformatted("");
|
||||||
@@ -299,8 +299,18 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
if (ImGui::BeginTabItem("Analogs")) {
|
if (ImGui::BeginTabItem("Analogs")) {
|
||||||
tab_selected_new = ConfigTab::CONFIG_TAB_ANALOGS;
|
tab_selected_new = ConfigTab::CONFIG_TAB_ANALOGS;
|
||||||
|
|
||||||
ImGui::BeginChild("Analogs", ImVec2(
|
ImGui::BeginChild("Analogs", ImVec2(
|
||||||
0, ImGui::GetWindowContentRegionMax().y - page_offset2), false);
|
0, ImGui::GetWindowContentRegionMax().y - page_offset2), false);
|
||||||
|
|
||||||
|
// help text for binding analog, if the game has one
|
||||||
|
const auto help_text = games::get_analogs_help(this->games_selected_name);
|
||||||
|
if (!help_text.empty()) {
|
||||||
|
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "Analog Bindings");
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::TextWrapped("%s", help_text.c_str());
|
||||||
|
ImGui::TextUnformatted("");
|
||||||
|
}
|
||||||
this->build_analogs("Game", games::get_analogs(this->games_selected_name));
|
this->build_analogs("Game", games::get_analogs(this->games_selected_name));
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "launcher/launcher.h"
|
#include "launcher/launcher.h"
|
||||||
#include "games/io.h"
|
#include "games/io.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
|
#include "overlay/imgui/extensions.h"
|
||||||
|
|
||||||
namespace overlay::windows {
|
namespace overlay::windows {
|
||||||
|
|
||||||
@@ -80,6 +81,9 @@ namespace overlay::windows {
|
|||||||
{
|
{
|
||||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - ImGui::GetFrameHeightWithSpacing());
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - ImGui::GetFrameHeightWithSpacing());
|
||||||
this->build_button("+", tall, this->test_button, this->service_button);
|
this->build_button("+", tall, this->test_button, this->service_button);
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::HelpTooltip("SERVICE + TEST");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "games/io.h"
|
#include "games/io.h"
|
||||||
#include "games/gitadora/gitadora.h"
|
#include "games/gitadora/gitadora.h"
|
||||||
#include "games/gitadora/io.h"
|
#include "games/gitadora/io.h"
|
||||||
|
#include "overlay/imgui/extensions.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
|
|
||||||
@@ -11,6 +12,7 @@ namespace overlay::windows {
|
|||||||
GitadoraIOPanel::GitadoraIOPanel(SpiceOverlay *overlay) : IOPanel(overlay) {
|
GitadoraIOPanel::GitadoraIOPanel(SpiceOverlay *overlay) : IOPanel(overlay) {
|
||||||
this->title = "GITADORA IO Panel";
|
this->title = "GITADORA IO Panel";
|
||||||
|
|
||||||
|
this->has_menu_controls = true;
|
||||||
// by default, make a safer assumption that there are two players
|
// by default, make a safer assumption that there are two players
|
||||||
this->two_players = true;
|
this->two_players = true;
|
||||||
// by default, enable the extra input only available on DX cabs...
|
// by default, enable the extra input only available on DX cabs...
|
||||||
@@ -33,6 +35,12 @@ namespace overlay::windows {
|
|||||||
this->has_guitar_knobs = false;
|
this->has_guitar_knobs = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (games::gitadora::is_arena_model()) {
|
||||||
|
this->has_menu_controls = false;
|
||||||
|
this->two_players = false;
|
||||||
|
this->has_guitar_knobs = false;
|
||||||
|
}
|
||||||
|
|
||||||
find_gfdm_buttons();
|
find_gfdm_buttons();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,23 +78,43 @@ namespace overlay::windows {
|
|||||||
void GitadoraIOPanel::build_io_panel() {
|
void GitadoraIOPanel::build_io_panel() {
|
||||||
ImGui::Dummy(overlay::apply_scaling_to_vector(12, 0));
|
ImGui::Dummy(overlay::apply_scaling_to_vector(12, 0));
|
||||||
|
|
||||||
ImGui::SameLine();
|
if (this->has_menu_controls) {
|
||||||
this->draw_buttons(0);
|
|
||||||
if (this->has_guitar_knobs) {
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
this->draw_sliders(0);
|
ImGui::PushID("P1");
|
||||||
|
this->draw_buttons(0);
|
||||||
|
if (this->has_guitar_knobs) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
this->draw_sliders(0);
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
// draw p2 only if guitar freaks
|
||||||
|
if (this->two_players) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Dummy(overlay::apply_scaling_to_vector(12, 0));
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::PushID("P2");
|
||||||
|
this->draw_buttons(1);
|
||||||
|
if (this->has_guitar_knobs) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
this->draw_sliders(1);
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw p2 only if guitar freaks
|
if (games::gitadora::is_guitar()) {
|
||||||
if (this->two_players) {
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Dummy(overlay::apply_scaling_to_vector(12, 0));
|
ImGui::Dummy(overlay::apply_scaling_to_vector(12, 0));
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
this->draw_buttons(1);
|
ImGui::BeginGroup();
|
||||||
if (this->has_guitar_knobs) {
|
{
|
||||||
ImGui::SameLine();
|
ImGui::Checkbox("P1 Lefty", &games::gitadora::P1_LEFTY);
|
||||||
this->draw_sliders(1);
|
if (this->two_players) {
|
||||||
|
ImGui::Checkbox("P2 Lefty", &games::gitadora::P2_LEFTY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ImGui::EndGroup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +135,10 @@ namespace overlay::windows {
|
|||||||
{
|
{
|
||||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetFrameHeightWithSpacing());
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetFrameHeightWithSpacing());
|
||||||
this->build_button("<", leftright_size, this->left[p], nullptr, this->leftright_light[p]);
|
this->build_button("<", leftright_size, this->left[p], nullptr, this->leftright_light[p]);
|
||||||
|
this->build_button("+", tiny_size, this->help[p], this->start[p], nullptr);
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::HelpTooltip("HELP + START");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
|
|
||||||
@@ -135,6 +167,9 @@ namespace overlay::windows {
|
|||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
{
|
{
|
||||||
this->build_button("?", tiny_size, this->help[p], nullptr, this->help_light[p]);
|
this->build_button("?", tiny_size, this->help[p], nullptr, this->help_light[p]);
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::HelpTooltip("HELP");
|
||||||
|
}
|
||||||
this->build_button(">", leftright_size, this->right[p], nullptr, this->leftright_light[p]);
|
this->build_button(">", leftright_size, this->right[p], nullptr, this->leftright_light[p]);
|
||||||
}
|
}
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace overlay::windows {
|
|||||||
void draw_buttons(const int player);
|
void draw_buttons(const int player);
|
||||||
void draw_sliders(const int player);
|
void draw_sliders(const int player);
|
||||||
|
|
||||||
|
bool has_menu_controls;
|
||||||
bool two_players;
|
bool two_players;
|
||||||
bool has_guitar_knobs;
|
bool has_guitar_knobs;
|
||||||
|
|
||||||
|
|||||||
@@ -1986,7 +1986,7 @@ void CALLBACK rawinput::RawInputManager::input_midi_proc(HMIDIIN hMidiIn, UINT w
|
|||||||
device.midiInfo->v2_last_off_time[midi_index] = get_performance_milliseconds();
|
device.midiInfo->v2_last_off_time[midi_index] = get_performance_milliseconds();
|
||||||
device.updated = true;
|
device.updated = true;
|
||||||
}
|
}
|
||||||
// for v2_drum, NOTE ON is ignored
|
// for v2_drum, NOTE OFF is ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,4 +84,63 @@ namespace socd {
|
|||||||
return SocdNone;
|
return SocdNone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// first dimension: p1/p2
|
||||||
|
// second dimension: TiltUp / TiltDown
|
||||||
|
// value: last timestamp when it was on
|
||||||
|
static double most_recent_active[2][2] = {};
|
||||||
|
|
||||||
|
uint32_t TILT_HOLD_MS = 100;
|
||||||
|
|
||||||
|
TiltResult get_guitar_wail(uint8_t device, bool up, bool down, double time_now) {
|
||||||
|
if (device >= 2) {
|
||||||
|
log_fatal("socd", "invalid device index in socd_clean: {}", device);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto socd_result = socd_clean(device, up, down, time_now);
|
||||||
|
|
||||||
|
if (up) {
|
||||||
|
most_recent_active[device][TiltUp] = time_now;
|
||||||
|
}
|
||||||
|
if (down) {
|
||||||
|
most_recent_active[device][TiltDown] = time_now;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug(
|
||||||
|
"socd",
|
||||||
|
"p{} wail up={}, down={}",
|
||||||
|
device + 1,
|
||||||
|
most_recent_active[device][TiltUp],
|
||||||
|
most_recent_active[device][TiltDown]);
|
||||||
|
|
||||||
|
const auto delta_up = time_now - most_recent_active[device][TiltUp];
|
||||||
|
const auto delta_down = time_now - most_recent_active[device][TiltDown];
|
||||||
|
const bool is_up = delta_up <= TILT_HOLD_MS;
|
||||||
|
const bool is_down = delta_down <= TILT_HOLD_MS;
|
||||||
|
|
||||||
|
auto result = TiltNone;
|
||||||
|
if (is_up && is_down) {
|
||||||
|
// both held recently: prefer more recently held using SOCD logic
|
||||||
|
if (socd_result == SocdCCW) {
|
||||||
|
result = TiltUp;
|
||||||
|
} else if (socd_result == SocdCW) {
|
||||||
|
result = TiltDown;
|
||||||
|
} else {
|
||||||
|
result = TiltUp;
|
||||||
|
}
|
||||||
|
} else if (is_up) {
|
||||||
|
result = TiltUp;
|
||||||
|
} else if (is_down) {
|
||||||
|
result = TiltDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear opposite direction being held
|
||||||
|
if (result == TiltUp) {
|
||||||
|
most_recent_active[device][TiltDown] = 0.f;
|
||||||
|
} else if (result == TiltDown) {
|
||||||
|
most_recent_active[device][TiltUp] = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
namespace socd {
|
namespace socd {
|
||||||
|
|
||||||
|
// SOCD for knobs / turntables
|
||||||
|
|
||||||
enum class SocdAlgorithm {
|
enum class SocdAlgorithm {
|
||||||
Neutral,
|
Neutral,
|
||||||
PreferRecent,
|
PreferRecent,
|
||||||
@@ -19,4 +21,16 @@ namespace socd {
|
|||||||
} SocdResult;
|
} SocdResult;
|
||||||
|
|
||||||
SocdResult socd_clean(uint8_t device, bool ccw, bool cw, double time_now);
|
SocdResult socd_clean(uint8_t device, bool ccw, bool cw, double time_now);
|
||||||
|
|
||||||
|
// for guitar wail (up/down only)
|
||||||
|
|
||||||
|
extern uint32_t TILT_HOLD_MS;
|
||||||
|
|
||||||
|
typedef enum _TiltResult {
|
||||||
|
TiltUp = 0,
|
||||||
|
TiltDown = 1,
|
||||||
|
TiltNone = 2
|
||||||
|
} TiltResult;
|
||||||
|
|
||||||
|
TiltResult get_guitar_wail(uint8_t device, bool up, bool down, double time_now);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user