376 lines
12 KiB
C++
376 lines
12 KiB
C++
|
#include "i36g.h"
|
||
|
#include "launcher/launcher.h"
|
||
|
#include "avs/game.h"
|
||
|
#include "rawinput/rawinput.h"
|
||
|
#include "games/mga/io.h"
|
||
|
#include "misc/eamuse.h"
|
||
|
#include "util/utils.h"
|
||
|
|
||
|
using namespace GameAPI;
|
||
|
|
||
|
// static stuff
|
||
|
static uint8_t STATUS_BUFFER[88 * 2] {};
|
||
|
static bool STATUS_BUFFER_FREEZE = false;
|
||
|
|
||
|
/*
|
||
|
* Implementations
|
||
|
*/
|
||
|
|
||
|
static int __cdecl ac_io_i36g_add_coin(int a1, int a2, int a3) {
|
||
|
|
||
|
// not so sure we want to add coins
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_consume_coinstock(int a1, int a2, int a3) {
|
||
|
eamuse_coin_consume_stock();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_i36g_control_coin_blocker_close(int a1, int a2) {
|
||
|
eamuse_coin_set_block(true);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_i36g_control_coin_blocker_open(int a1, int a2) {
|
||
|
eamuse_coin_set_block(false);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_i36g_control_lamp_bright(uint32_t device, uint32_t lamp_bits, uint8_t brightness) {
|
||
|
|
||
|
// calculate value
|
||
|
float value = (float) brightness / 255.f;
|
||
|
|
||
|
// get lights
|
||
|
auto &lights = games::mga::get_lights();
|
||
|
|
||
|
// cabinet device
|
||
|
if (device == 21) {
|
||
|
if (lamp_bits & 1) {
|
||
|
Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftR], value);
|
||
|
}
|
||
|
if (lamp_bits & 2) {
|
||
|
Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftG], value);
|
||
|
}
|
||
|
if (lamp_bits & 4) {
|
||
|
Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftB], value);
|
||
|
}
|
||
|
if (lamp_bits & 8) {
|
||
|
Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightR], value);
|
||
|
}
|
||
|
if (lamp_bits & 16) {
|
||
|
Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightG], value);
|
||
|
}
|
||
|
if (lamp_bits & 32) {
|
||
|
Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightB], value);
|
||
|
}
|
||
|
if (lamp_bits & 512) {
|
||
|
Lights::writeLight(RI_MGR, lights[games::mga::Lights::Start], value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// gun device
|
||
|
if (device == 22) {
|
||
|
if (lamp_bits & 1) {
|
||
|
Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunR], value);
|
||
|
}
|
||
|
if (lamp_bits & 2) {
|
||
|
Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunG], value);
|
||
|
}
|
||
|
if (lamp_bits & 4) {
|
||
|
Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunB], value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// success
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_i36g_control_motor_power(int device, uint8_t strength) {
|
||
|
|
||
|
// gun device
|
||
|
if (device == 22) {
|
||
|
float value = (float) strength / 255.f;
|
||
|
auto &lights = games::mga::get_lights();
|
||
|
Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunVibration], value);
|
||
|
}
|
||
|
|
||
|
// success
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_current_coinstock(int a1, int a2, int *a3) {
|
||
|
|
||
|
// get coinstock
|
||
|
*a3 = eamuse_coin_get_stock();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_get_coin_input_wave_buffer(int a1, char *a2) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static void __cdecl ac_io_i36g_get_control_status_buffer(int device, void *buffer) {
|
||
|
|
||
|
// cabinet buffer
|
||
|
if (device == 21) {
|
||
|
memcpy(buffer, &STATUS_BUFFER[0], 88);
|
||
|
}
|
||
|
|
||
|
// gun buffer
|
||
|
if (device == 22) {
|
||
|
memcpy(buffer, &STATUS_BUFFER[88], 88);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_get_softwareid(int a1, int a2) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_get_systemid(int a1, int a2) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_i36g_get_watchdog_status(int a1) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
static short __cdecl ac_io_i36g_get_watchdog_time_min(int a1) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static short __cdecl ac_io_i36g_get_watchdog_time_now(int a1) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_lock_coincounter(int a1, int a2) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_req_coin_input_wave(int a1) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_req_get_control_status(int a1, int *a2) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_req_secplug_check(int a1, char *a2) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_i36g_req_secplug_check_isfinished(int a1, int *a2) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_req_secplug_check_softwareplug(int a1, char *a2) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_req_secplug_check_systemplug(int a1) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_req_secplug_missing_check(int a1) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_i36g_req_secplug_missing_check_isfinished(int a1, int *a2) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_i36g_req_volume_control(int a1, char a2, char a3, char a4, char a5) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_i36g_req_volume_control_isfinished(int a1, int *ret_state) {
|
||
|
*ret_state = 3;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_i36g_set_cmdmode(int a1, int a2) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_i36g_set_framing_err_packet_send_interval(int a1) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_i36g_set_watchdog_time(int a1, short a2) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static char __cdecl ac_io_i36g_unlock_coincounter(int a1, int a2) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static bool __cdecl ac_io_i36g_update_control_status_buffer(int node) {
|
||
|
|
||
|
// check freeze
|
||
|
if (STATUS_BUFFER_FREEZE) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Metal Gear Arcade
|
||
|
if (avs::game::is_model("I36")) {
|
||
|
|
||
|
// get buttons
|
||
|
auto &buttons = games::mga::get_buttons();
|
||
|
|
||
|
// cabinet device
|
||
|
if (node == 21) {
|
||
|
|
||
|
// clear status buffer
|
||
|
memset(&STATUS_BUFFER[0], 0, 88);
|
||
|
|
||
|
// update buttons
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Service))) {
|
||
|
ARRAY_SETB(&STATUS_BUFFER[0], 44);
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Test))) {
|
||
|
ARRAY_SETB(&STATUS_BUFFER[0], 45);
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::CoinMech))) {
|
||
|
ARRAY_SETB(&STATUS_BUFFER[0], 42);
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Start))) {
|
||
|
ARRAY_SETB(&STATUS_BUFFER[0], 124);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// gun device
|
||
|
if (node == 22) {
|
||
|
|
||
|
// clear status buffer
|
||
|
memset(&STATUS_BUFFER[88], 0, 88);
|
||
|
|
||
|
// update buttons
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::TriggerButton))
|
||
|
|| (GetKeyState(VK_LBUTTON) & 0x100) != 0) { // mouse button
|
||
|
ARRAY_SETB(&STATUS_BUFFER[88], 109);
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::FrontTop))) {
|
||
|
ARRAY_SETB(&STATUS_BUFFER[88], 108);
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::FrontBottom))) {
|
||
|
ARRAY_SETB(&STATUS_BUFFER[88], 106);
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideLeft))) {
|
||
|
ARRAY_SETB(&STATUS_BUFFER[88], 107);
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideRight))) {
|
||
|
ARRAY_SETB(&STATUS_BUFFER[88], 105);
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideLever))) {
|
||
|
ARRAY_SETB(&STATUS_BUFFER[88], 104);
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SwitchButton))) {
|
||
|
ARRAY_SETB(&STATUS_BUFFER[88], 125);
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Top))) {
|
||
|
ARRAY_SETB(&STATUS_BUFFER[88], 124);
|
||
|
}
|
||
|
|
||
|
// joy stick
|
||
|
unsigned short joy_x = 0x7FFF;
|
||
|
unsigned short joy_y = 0x7FFF;
|
||
|
bool joy_x_pressed = false;
|
||
|
bool joy_y_pressed = false;
|
||
|
if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyForwards])) {
|
||
|
joy_y -= 0x7FFF;
|
||
|
joy_y_pressed = true;
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyBackwards])) {
|
||
|
joy_y += 0x7FFF;
|
||
|
joy_y_pressed = true;
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyLeft])) {
|
||
|
joy_x -= 0x7FFF;
|
||
|
joy_x_pressed = true;
|
||
|
}
|
||
|
if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyRight])) {
|
||
|
joy_x += 0x7FFF;
|
||
|
joy_x_pressed = true;
|
||
|
}
|
||
|
|
||
|
// joy stick raw input
|
||
|
auto &analogs = games::mga::get_analogs();
|
||
|
if (!joy_x_pressed && analogs[games::mga::Analogs::JoyX].isSet()) {
|
||
|
joy_x = (unsigned short) (Analogs::getState(RI_MGR, analogs[games::mga::Analogs::JoyX]) * 0xFFFF);
|
||
|
}
|
||
|
if (!joy_y_pressed && analogs[games::mga::Analogs::JoyY].isSet()) {
|
||
|
joy_y = (unsigned short) (Analogs::getState(RI_MGR, analogs[games::mga::Analogs::JoyY]) * 0xFFFF);
|
||
|
}
|
||
|
|
||
|
// save joy stick
|
||
|
STATUS_BUFFER[88 + 42] = LOBYTE(joy_y);
|
||
|
STATUS_BUFFER[88 + 43] = HIBYTE(joy_y);
|
||
|
STATUS_BUFFER[88 + 44] = LOBYTE(joy_x);
|
||
|
STATUS_BUFFER[88 + 45] = HIBYTE(joy_x);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// return success
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static int __cdecl ac_io_i36g_watchdog_off(int a1) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Module stuff
|
||
|
*/
|
||
|
|
||
|
acio::I36GModule::I36GModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("I36G", module, hookMode) {
|
||
|
this->status_buffer = &STATUS_BUFFER[0];
|
||
|
this->status_buffer_size = sizeof(STATUS_BUFFER);
|
||
|
this->status_buffer_freeze = &STATUS_BUFFER_FREEZE;
|
||
|
}
|
||
|
|
||
|
void acio::I36GModule::attach() {
|
||
|
ACIOModule::attach();
|
||
|
|
||
|
// hooks
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_add_coin);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_consume_coinstock);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_control_coin_blocker_close);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_control_coin_blocker_open);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_control_lamp_bright);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_control_motor_power);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_current_coinstock);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_get_coin_input_wave_buffer);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_get_control_status_buffer);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_get_softwareid);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_get_systemid);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_status);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_time_min);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_time_now);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_lock_coincounter);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_req_coin_input_wave);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_req_get_control_status);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_isfinished);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_softwareplug);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_systemplug);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_missing_check);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_missing_check_isfinished);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_req_volume_control);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_req_volume_control_isfinished);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_set_cmdmode);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_set_framing_err_packet_send_interval);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_set_watchdog_time);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_unlock_coincounter);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_update_control_status_buffer);
|
||
|
ACIO_MODULE_HOOK(ac_io_i36g_watchdog_off);
|
||
|
|
||
|
// I36S links
|
||
|
this->hook((void *) ac_io_i36g_update_control_status_buffer,
|
||
|
"ac_io_i36s_update_control_status_buffer");
|
||
|
this->hook((void *) ac_io_i36g_get_control_status_buffer,
|
||
|
"ac_io_i36s_get_control_status_buffer");
|
||
|
this->hook((void *) ac_io_i36g_set_cmdmode,
|
||
|
"ac_io_i36s_set_cmdmode");
|
||
|
}
|