239 lines
6.4 KiB
C++
239 lines
6.4 KiB
C++
|
#include "klpa.h"
|
||
|
|
||
|
#include "avs/game.h"
|
||
|
#include "games/loveplus/io.h"
|
||
|
#include "misc/eamuse.h"
|
||
|
#include "rawinput/rawinput.h"
|
||
|
#include "util/utils.h"
|
||
|
|
||
|
using namespace GameAPI;
|
||
|
|
||
|
static uint8_t STATUS_BUFFER[48];
|
||
|
static bool STATUS_BUFFER_FREEZE = false;
|
||
|
|
||
|
static const size_t LOVEPLUS_LIGHTS_MAPPING[] = {
|
||
|
games::loveplus::Lights::Red,
|
||
|
games::loveplus::Lights::Green,
|
||
|
games::loveplus::Lights::Blue,
|
||
|
SIZE_MAX,
|
||
|
games::loveplus::Lights::Right,
|
||
|
games::loveplus::Lights::Left,
|
||
|
};
|
||
|
|
||
|
static char __cdecl ac_io_klpa_consume_coinstock(int a1, DWORD *a2) {
|
||
|
*a2 = (DWORD) eamuse_coin_get_stock();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_klpa_control_coin_blocker_close(int a1) {
|
||
|
eamuse_coin_set_block(true);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_klpa_control_coin_blocker_open(int a1) {
|
||
|
eamuse_coin_set_block(false);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_klpa_control_led_off(size_t index) {
|
||
|
|
||
|
// LovePlus
|
||
|
if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) {
|
||
|
|
||
|
// get lights
|
||
|
auto &lights = games::loveplus::get_lights();
|
||
|
|
||
|
if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) {
|
||
|
Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), 0.f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// return success
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_klpa_control_led_on(size_t index) {
|
||
|
|
||
|
// LovePlus
|
||
|
if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) {
|
||
|
|
||
|
// get lights
|
||
|
auto &lights = games::loveplus::get_lights();
|
||
|
|
||
|
if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) {
|
||
|
Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), 1.f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// return success
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_klpa_create_get_status_thread() {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_klpa_current_coinstock(int a1, DWORD *a2) {
|
||
|
|
||
|
// check bounds
|
||
|
if (a1 < 0 || a1 >= 2) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
*a2 = (DWORD) eamuse_coin_get_stock();
|
||
|
|
||
|
// return success
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_klpa_destroy_get_status_thread() {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static void* __cdecl ac_io_klpa_get_control_status_buffer(void *a1) {
|
||
|
|
||
|
// copy buffer
|
||
|
return memcpy(a1, STATUS_BUFFER, sizeof(STATUS_BUFFER));
|
||
|
}
|
||
|
|
||
|
static void __cdecl ac_io_klpa_get_io_command_mode(void *a1) {
|
||
|
memset(a1, 0, 4);
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_klpa_led_reset() {
|
||
|
if (avs::game::is_model("KLP")) {
|
||
|
|
||
|
// get lights
|
||
|
auto &lights = games::loveplus::get_lights();
|
||
|
|
||
|
for (const auto &mapping : LOVEPLUS_LIGHTS_MAPPING) {
|
||
|
if (mapping != SIZE_MAX) {
|
||
|
Lights::writeLight(RI_MGR, lights.at(mapping), 0.f);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_klpa_lock_coincounter(int a1) {
|
||
|
eamuse_coin_set_block(true);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_klpa_set_io_command_mode(int a1) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_klpa_set_io_command_mode_is_finished(uint8_t *a1) {
|
||
|
*a1 = 0;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_klpa_set_led_bright(size_t index, uint8_t brightness) {
|
||
|
|
||
|
// LovePlus
|
||
|
if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) {
|
||
|
|
||
|
// get lights
|
||
|
auto &lights = games::loveplus::get_lights();
|
||
|
|
||
|
if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) {
|
||
|
Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), brightness / 127.f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_klpa_set_sound_mute(int a1) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_klpa_set_sound_mute_is_finished(int a1) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_klpa_set_watchdog_time(short a1) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_klpa_unlock_coincounter(int a1) {
|
||
|
eamuse_coin_set_block(false);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_klpa_update_control_status_buffer() {
|
||
|
|
||
|
// check freeze
|
||
|
if (STATUS_BUFFER_FREEZE) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// reset buffer
|
||
|
memset(STATUS_BUFFER, 0, sizeof(STATUS_BUFFER));
|
||
|
|
||
|
// LovePlus
|
||
|
if (avs::game::is_model("KLP")) {
|
||
|
|
||
|
// get buttons
|
||
|
auto &buttons = games::loveplus::get_buttons();
|
||
|
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Test)) == Buttons::State::BUTTON_PRESSED) {
|
||
|
STATUS_BUFFER[5] |= 1 << 5;
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Service)) == Buttons::State::BUTTON_PRESSED) {
|
||
|
STATUS_BUFFER[5] |= 1 << 4;
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Left)) == Buttons::State::BUTTON_PRESSED) {
|
||
|
STATUS_BUFFER[12] |= 1 << 6;
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Right)) == Buttons::State::BUTTON_PRESSED) {
|
||
|
STATUS_BUFFER[12] |= 1 << 7;
|
||
|
}
|
||
|
|
||
|
// x[9] & 0x3F) = volume output level?
|
||
|
// x[11] & 0x3F) = volume output level?
|
||
|
// x[12] |= (1 << 4) = headphone jack
|
||
|
}
|
||
|
|
||
|
// success
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Module stuff
|
||
|
*/
|
||
|
|
||
|
acio::KLPAModule::KLPAModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("KLPA", module, hookMode) {
|
||
|
this->status_buffer = STATUS_BUFFER;
|
||
|
this->status_buffer_size = sizeof(STATUS_BUFFER);
|
||
|
this->status_buffer_freeze = &STATUS_BUFFER_FREEZE;
|
||
|
}
|
||
|
|
||
|
void acio::KLPAModule::attach() {
|
||
|
ACIOModule::attach();
|
||
|
|
||
|
// hooks
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_consume_coinstock);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_control_coin_blocker_close);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_control_coin_blocker_open);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_control_led_off);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_control_led_on);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_create_get_status_thread);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_current_coinstock);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_destroy_get_status_thread);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_get_control_status_buffer);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_get_io_command_mode);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_led_reset);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_lock_coincounter);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_set_io_command_mode);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_set_io_command_mode_is_finished);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_set_led_bright);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_set_sound_mute);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_set_sound_mute_is_finished);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_set_watchdog_time);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_unlock_coincounter);
|
||
|
ACIO_MODULE_HOOK(ac_io_klpa_update_control_status_buffer);
|
||
|
}
|