spicetools/acio/panb/panb.cpp

204 lines
8.7 KiB
C++

#include "panb.h"
#include "launcher/launcher.h"
#include "rawinput/rawinput.h"
#include "games/nost/io.h"
#include "games/nost/nost.h"
#include "util/logging.h"
#include "avs/game.h"
using namespace GameAPI;
// static stuff
static uint8_t STATUS_BUFFER[277];
static bool STATUS_BUFFER_FREEZE = false;
/*
* Implementations
*/
static long __cdecl ac_io_panb_control_led_bright(size_t index, uint8_t value) {
// nostalgia
if (avs::game::is_model("PAN")) {
// get lights
auto &lights = games::nost::get_lights();
// mapping
static const size_t mapping[] {
games::nost::Lights::Key1R, games::nost::Lights::Key1G, games::nost::Lights::Key1B,
games::nost::Lights::Key2R, games::nost::Lights::Key2G, games::nost::Lights::Key2B,
games::nost::Lights::Key3R, games::nost::Lights::Key3G, games::nost::Lights::Key3B,
games::nost::Lights::Key4R, games::nost::Lights::Key4G, games::nost::Lights::Key4B,
games::nost::Lights::Key5R, games::nost::Lights::Key5G, games::nost::Lights::Key5B,
games::nost::Lights::Key6R, games::nost::Lights::Key6G, games::nost::Lights::Key6B,
games::nost::Lights::Key7R, games::nost::Lights::Key7G, games::nost::Lights::Key7B,
games::nost::Lights::Key8R, games::nost::Lights::Key8G, games::nost::Lights::Key8B,
games::nost::Lights::Key9R, games::nost::Lights::Key9G, games::nost::Lights::Key9B,
games::nost::Lights::Key10R, games::nost::Lights::Key10G, games::nost::Lights::Key10B,
games::nost::Lights::Key11R, games::nost::Lights::Key11G, games::nost::Lights::Key11B,
games::nost::Lights::Key12R, games::nost::Lights::Key12G, games::nost::Lights::Key12B,
games::nost::Lights::Key13R, games::nost::Lights::Key13G, games::nost::Lights::Key13B,
games::nost::Lights::Key14R, games::nost::Lights::Key14G, games::nost::Lights::Key14B,
games::nost::Lights::Key15R, games::nost::Lights::Key15G, games::nost::Lights::Key15B,
games::nost::Lights::Key16R, games::nost::Lights::Key16G, games::nost::Lights::Key16B,
games::nost::Lights::Key17R, games::nost::Lights::Key17G, games::nost::Lights::Key17B,
games::nost::Lights::Key18R, games::nost::Lights::Key18G, games::nost::Lights::Key18B,
games::nost::Lights::Key19R, games::nost::Lights::Key19G, games::nost::Lights::Key19B,
games::nost::Lights::Key20R, games::nost::Lights::Key20G, games::nost::Lights::Key20B,
games::nost::Lights::Key21R, games::nost::Lights::Key21G, games::nost::Lights::Key21B,
games::nost::Lights::Key22R, games::nost::Lights::Key22G, games::nost::Lights::Key22B,
games::nost::Lights::Key23R, games::nost::Lights::Key23G, games::nost::Lights::Key23B,
games::nost::Lights::Key24R, games::nost::Lights::Key24G, games::nost::Lights::Key24B,
games::nost::Lights::Key25R, games::nost::Lights::Key25G, games::nost::Lights::Key25B,
games::nost::Lights::Key26R, games::nost::Lights::Key26G, games::nost::Lights::Key26B,
games::nost::Lights::Key27R, games::nost::Lights::Key27G, games::nost::Lights::Key27B,
games::nost::Lights::Key28R, games::nost::Lights::Key28G, games::nost::Lights::Key28B,
};
// write light
if (index < std::size(mapping)) {
Lights::writeLight(RI_MGR, lights.at(mapping[index]), value / 127.f);
}
}
return 1;
}
static long __cdecl ac_io_panb_control_reset() {
return 0;
}
static void* __cdecl ac_io_panb_get_control_status_buffer(uint8_t* buffer) {
// copy buffer
return memcpy(buffer, STATUS_BUFFER, sizeof(STATUS_BUFFER));
}
static bool __cdecl ac_io_panb_start_auto_input() {
return true;
}
static bool __cdecl ac_io_panb_update_control_status_buffer() {
// check freeze
if (STATUS_BUFFER_FREEZE) {
return true;
}
// clear buffer
memset(STATUS_BUFFER, 0, 277);
/*
* first byte is number of input data
* when it's set to 0 the game will not update it's key states
* setting it too high will make the game read over the buffer
*
* unsure why you would send more than one set of data, so
* we just set it to 1 and provide our current status
*/
STATUS_BUFFER[0] = 1;
// Nostalgia
if (avs::game::is_model("PAN")) {
// get buttons/analogs
auto &buttons = games::nost::get_buttons();
auto &analogs = games::nost::get_analogs();
// mappings
static const size_t button_mapping[] = {
games::nost::Buttons::Key1, games::nost::Buttons::Key2,
games::nost::Buttons::Key3, games::nost::Buttons::Key4,
games::nost::Buttons::Key5, games::nost::Buttons::Key6,
games::nost::Buttons::Key7, games::nost::Buttons::Key8,
games::nost::Buttons::Key9, games::nost::Buttons::Key10,
games::nost::Buttons::Key11, games::nost::Buttons::Key12,
games::nost::Buttons::Key13, games::nost::Buttons::Key14,
games::nost::Buttons::Key15, games::nost::Buttons::Key16,
games::nost::Buttons::Key17, games::nost::Buttons::Key18,
games::nost::Buttons::Key19, games::nost::Buttons::Key20,
games::nost::Buttons::Key21, games::nost::Buttons::Key22,
games::nost::Buttons::Key23, games::nost::Buttons::Key24,
games::nost::Buttons::Key25, games::nost::Buttons::Key26,
games::nost::Buttons::Key27, games::nost::Buttons::Key28,
};
static const size_t analog_mapping[] = {
games::nost::Analogs::Key1, games::nost::Analogs::Key2,
games::nost::Analogs::Key3, games::nost::Analogs::Key4,
games::nost::Analogs::Key5, games::nost::Analogs::Key6,
games::nost::Analogs::Key7, games::nost::Analogs::Key8,
games::nost::Analogs::Key9, games::nost::Analogs::Key10,
games::nost::Analogs::Key11, games::nost::Analogs::Key12,
games::nost::Analogs::Key13, games::nost::Analogs::Key14,
games::nost::Analogs::Key15, games::nost::Analogs::Key16,
games::nost::Analogs::Key17, games::nost::Analogs::Key18,
games::nost::Analogs::Key19, games::nost::Analogs::Key20,
games::nost::Analogs::Key21, games::nost::Analogs::Key22,
games::nost::Analogs::Key23, games::nost::Analogs::Key24,
games::nost::Analogs::Key25, games::nost::Analogs::Key26,
games::nost::Analogs::Key27, games::nost::Analogs::Key28,
};
// iterate pairs of keys
for (size_t key_pair = 0; key_pair < 28 / 2; key_pair++) {
// default states
uint8_t state0 = 0;
uint8_t state1 = 0;
// check analogs
auto &analog0 = analogs.at(analog_mapping[key_pair * 2 + 0]);
auto &analog1 = analogs.at(analog_mapping[key_pair * 2 + 1]);
if (analog0.isSet()) {
state0 = (uint8_t) (Analogs::getState(RI_MGR, analog0) * 15.999f);
}
if (analog1.isSet()) {
state1 = (uint8_t) (Analogs::getState(RI_MGR, analog1) * 15.999f);
}
// check buttons
auto velocity0 = Buttons::getVelocity(RI_MGR, buttons.at(button_mapping[key_pair * 2 + 0]));
auto velocity1 = Buttons::getVelocity(RI_MGR, buttons.at(button_mapping[key_pair * 2 + 1]));
if (velocity0 > 0.f) {
state0 = (uint8_t) (velocity0 * 15.999f);
}
if (velocity1 > 0.f) {
state1 = (uint8_t) (velocity1 * 15.999f);
}
// build value
uint8_t value = 0;
value |= state0 << 4;
value |= state1 & 0xF;
// set value
STATUS_BUFFER[key_pair + 3] = value;
}
}
// return success
return true;
}
/*
* Module stuff
*/
acio::PANBModule::PANBModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("PANB", module, hookMode) {
this->status_buffer = STATUS_BUFFER;
this->status_buffer_size = sizeof(STATUS_BUFFER);
this->status_buffer_freeze = &STATUS_BUFFER_FREEZE;
}
void acio::PANBModule::attach() {
ACIOModule::attach();
// hooks
ACIO_MODULE_HOOK(ac_io_panb_control_led_bright);
ACIO_MODULE_HOOK(ac_io_panb_control_reset);
ACIO_MODULE_HOOK(ac_io_panb_get_control_status_buffer);
ACIO_MODULE_HOOK(ac_io_panb_start_auto_input);
ACIO_MODULE_HOOK(ac_io_panb_update_control_status_buffer);
}