177 lines
4.8 KiB
C++
177 lines
4.8 KiB
C++
#include "keypads.h"
|
|
|
|
#include <functional>
|
|
|
|
#include <windows.h>
|
|
|
|
#include "avs/game.h"
|
|
#include "external/rapidjson/document.h"
|
|
#include "misc/eamuse.h"
|
|
|
|
using namespace std::placeholders;
|
|
using namespace rapidjson;
|
|
|
|
namespace api::modules {
|
|
|
|
struct KeypadMapping {
|
|
char character;
|
|
uint16_t state;
|
|
};
|
|
|
|
static KeypadMapping KEYPAD_MAPPINGS[] = {
|
|
{ '0', 1 << EAM_IO_KEYPAD_0 },
|
|
{ '1', 1 << EAM_IO_KEYPAD_1 },
|
|
{ '2', 1 << EAM_IO_KEYPAD_2 },
|
|
{ '3', 1 << EAM_IO_KEYPAD_3 },
|
|
{ '4', 1 << EAM_IO_KEYPAD_4 },
|
|
{ '5', 1 << EAM_IO_KEYPAD_5 },
|
|
{ '6', 1 << EAM_IO_KEYPAD_6 },
|
|
{ '7', 1 << EAM_IO_KEYPAD_7 },
|
|
{ '8', 1 << EAM_IO_KEYPAD_8 },
|
|
{ '9', 1 << EAM_IO_KEYPAD_9 },
|
|
{ 'A', 1 << EAM_IO_KEYPAD_00 },
|
|
{ 'D', 1 << EAM_IO_KEYPAD_DECIMAL },
|
|
};
|
|
|
|
Keypads::Keypads() : Module("keypads") {
|
|
functions["write"] = std::bind(&Keypads::write, this, _1, _2);
|
|
functions["set"] = std::bind(&Keypads::set, this, _1, _2);
|
|
functions["get"] = std::bind(&Keypads::get, this, _1, _2);
|
|
}
|
|
|
|
/**
|
|
* write(keypad: uint, input: str)
|
|
*/
|
|
void Keypads::write(Request &req, Response &res) {
|
|
|
|
// check params
|
|
if (req.params.Size() < 2) {
|
|
return error_params_insufficient(res);
|
|
}
|
|
if (!req.params[0].IsUint()) {
|
|
return error_type(res, "keypad", "uint");
|
|
}
|
|
if (!req.params[1].IsString()) {
|
|
return error_type(res, "input", "string");
|
|
}
|
|
|
|
// get params
|
|
auto keypad = req.params[0].GetUint();
|
|
auto input = std::string(req.params[1].GetString());
|
|
|
|
// process all chars
|
|
for (auto c : input) {
|
|
uint16_t state = 0;
|
|
|
|
// find mapping
|
|
bool mapping_found = false;
|
|
for (auto &mapping : KEYPAD_MAPPINGS) {
|
|
if (_strnicmp(&mapping.character, &c, 1) == 0) {
|
|
state |= mapping.state;
|
|
mapping_found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// check for error
|
|
if (!mapping_found) {
|
|
return error_unknown(res, "char", std::string("") + c);
|
|
}
|
|
|
|
/*
|
|
* Write input to keypad.
|
|
* We try to make sure it was accepted by waiting a bit more than two frames.
|
|
*/
|
|
DWORD sleep_time = 70;
|
|
if (avs::game::is_model("MDX")) {
|
|
|
|
// cuz fuck DDR
|
|
sleep_time = 150;
|
|
}
|
|
|
|
// set
|
|
eamuse_set_keypad_overrides(keypad, state);
|
|
Sleep(sleep_time);
|
|
|
|
// unset
|
|
eamuse_set_keypad_overrides(keypad, 0);
|
|
Sleep(sleep_time);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* set(keypad: uint, key: char, ...)
|
|
*/
|
|
void Keypads::set(Request &req, Response &res) {
|
|
|
|
// check keypad
|
|
if (req.params.Size() < 1) {
|
|
return error_params_insufficient(res);
|
|
}
|
|
if (!req.params[0].IsUint()) {
|
|
return error_type(res, "keypad", "uint");
|
|
}
|
|
auto keypad = req.params[0].GetUint();
|
|
|
|
// iterate params
|
|
uint16_t state = 0;
|
|
auto params = req.params.GetArray();
|
|
for (size_t i = 1; i < params.Size(); i++) {
|
|
auto ¶m = params[i];
|
|
|
|
// check key
|
|
if (!param.IsString()) {
|
|
error_type(res, "key", "char");
|
|
}
|
|
if (param.GetStringLength() < 1) {
|
|
error_size(res, "key", 1);
|
|
}
|
|
|
|
// find mapping
|
|
auto key = param.GetString();
|
|
bool mapping_found = false;
|
|
for (auto &mapping : KEYPAD_MAPPINGS) {
|
|
if (_strnicmp(&mapping.character, key, 1) == 0) {
|
|
state |= mapping.state;
|
|
mapping_found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// check for error
|
|
if (!mapping_found) {
|
|
return error_unknown(res, "key", key);
|
|
}
|
|
}
|
|
|
|
// set keypad state
|
|
eamuse_set_keypad_overrides(keypad, state);
|
|
}
|
|
|
|
/**
|
|
* get(keypad: uint)
|
|
*/
|
|
void Keypads::get(Request &req, Response &res) {
|
|
|
|
// check keypad
|
|
if (req.params.Size() < 1) {
|
|
return error_params_insufficient(res);
|
|
}
|
|
if (!req.params[0].IsUint()) {
|
|
return error_type(res, "keypad", "uint");
|
|
}
|
|
auto keypad = req.params[0].GetUint();
|
|
|
|
// get keypad state
|
|
auto state = eamuse_get_keypad_state(keypad);
|
|
|
|
// add keys to response
|
|
for (auto &mapping : KEYPAD_MAPPINGS) {
|
|
if (state & mapping.state) {
|
|
Value val(&mapping.character, 1);
|
|
res.add_data(val);
|
|
}
|
|
}
|
|
}
|
|
}
|