Initial commit for GitHub migration based on spice2x-25-03-03

This commit is contained in:
sp2xdev
2025-03-10 19:16:49 -07:00
parent 94af8d32c9
commit ed8c72852f
1008 changed files with 296815 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
#include "bc.h"
#include "hooks/setupapihook.h"
#include "util/libutils.h"
#include "acio2emu/handle.h"
#include "acioemu/handle.h"
#include "hooks/graphics/graphics.h"
#include "util/detour.h"
#include "node.h"
namespace games::bc {
static decltype(ShowCursor) *ShowCursor_orig = nullptr;
static int WINAPI ShowCursor_hook(BOOL bShow) {
// log_misc("bsac", "ShowCursor {}", bShow);
return 1;
}
void BCGame::attach() {
Game::attach();
setupapihook_init(libutils::load_library("libaio.dll"));
SETUPAPI_SETTINGS settings {};
const char hwid[] = "USB\\VID_1CCF&PID_8050\\0000";
memcpy(settings.property_hardwareid, hwid, sizeof(hwid));
const char comport[] = "COM3";
memcpy(settings.interface_detail, comport, sizeof(comport));
setupapihook_add(settings);
auto iob = new acio2emu::IOBHandle(L"COM3");
iob->register_node(std::make_unique<TBSNode>());
if (GRAPHICS_SHOW_CURSOR) {
detour::trampoline_try(
"user32.dll", "ShowCursor",
(void*)ShowCursor_hook, (void**)&ShowCursor_orig);
}
devicehook_init();
devicehook_add(iob);
devicehook_add(new acioemu::ACIOHandle(L"COM1"));
}
void BCGame::detach() {
Game::detach();
devicehook_dispose();
}
}
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include "games/game.h"
namespace games::bc {
class BCGame : public games::Game {
public:
BCGame() : Game("Busou Shinki: Armored Princess Battle Conductor") {}
virtual void attach() override;
virtual void detach() override;
};
}
+49
View File
@@ -0,0 +1,49 @@
#include "io.h"
std::vector<Button> &games::bc::get_buttons() {
static std::vector<Button> buttons;
if (buttons.empty()) {
buttons = GameAPI::Buttons::getButtons("Busou Shinki: Armored Princess Battle Conductor");
GameAPI::Buttons::sortButtons(
&buttons,
"Service",
"Test",
"Up",
"Down",
"Left",
"Right",
"Joystick Button",
"Trigger 1",
"Trigger 2",
"Button 1",
"Button 2",
"Button 3",
"Button 4"
);
}
return buttons;
}
std::string games::bc::get_buttons_help() {
// keep to max 100 characters wide
return "";
}
std::vector<Analog> &games::bc::get_analogs() {
static std::vector<Analog> analogs;
if (analogs.empty()) {
analogs = GameAPI::Analogs::getAnalogs("Busou Shinki: Armored Princess Battle Conductor");
GameAPI::Analogs::sortAnalogs(
&analogs,
"Stick X",
"Stick Y"
);
}
return analogs;
}
+36
View File
@@ -0,0 +1,36 @@
#pragma once
#include <vector>
#include "cfg/api.h"
namespace games::bc {
namespace Buttons {
enum {
Service,
Test,
Up,
Down,
Left,
Right,
JoystickButton,
Trigger1,
Trigger2,
Button1,
Button2,
Button3,
Button4,
};
}
namespace Analogs {
enum {
StickX,
StickY,
};
}
std::vector<Button> &get_buttons();
std::string get_buttons_help();
std::vector<Analog> &get_analogs();
}
+111
View File
@@ -0,0 +1,111 @@
#pragma once
#include <cstdint>
#include "io.h"
#include "acio2emu/firmware/bi2x.h"
#include "misc/eamuse.h"
#include "util/logging.h"
namespace games::bc {
class TBSNode : public acio2emu::firmware::BI2XNode {
private:
uint8_t coins_ = 0;
public:
void read_firmware_version(std::vector<uint8_t> &buffer) {
static constexpr uint8_t ver[] = {
0x0D, 0x06, 0x00, 0x01,
0x00, 0x01, 0x02, 0x08,
0x42, 0x49, 0x32, 0x58,
0x01, 0x94, 0xF1, 0x8E,
0x00, 0x00, 0x01, 0x0B,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0xA8, 0x24, 0x8E, 0xE2,
};
buffer.insert(buffer.end(), ver, &ver[sizeof(ver)]);
}
bool read_input(std::vector<uint8_t> &buffer) {
auto &buttons = get_buttons();
auto &analogs = get_analogs();
coins_ += eamuse_coin_consume_stock();
buffer.reserve(buffer.size() + 10);
buffer.push_back(0);
buffer.push_back(0);
buffer.push_back(coins_);
uint8_t b = 0;
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Test])) {
b |= 1;
}
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Service])) {
b |= (1 << 2);
}
buffer.push_back(b);
buffer.push_back(0);
int16_t joy = INT16_MAX;
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Left])) {
joy += INT16_MAX;
}
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Right])) {
joy -= INT16_MAX;
}
if (analogs[Analogs::StickX].isSet()) {
joy = 65535 - (uint16_t) (GameAPI::Analogs::getState(RI_MGR, analogs[Analogs::StickX]) * 65535);
}
buffer.push_back(static_cast<uint8_t>(joy >> 8));
buffer.push_back(static_cast<uint8_t>(joy));
joy = INT16_MAX;
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Down])) {
joy += INT16_MAX;
}
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Up])) {
joy -= INT16_MAX;
}
if (analogs[Analogs::StickY].isSet()) {
joy = 65535 - (uint16_t) (GameAPI::Analogs::getState(RI_MGR, analogs[Analogs::StickY]) * 65535);
}
buffer.push_back(static_cast<uint8_t>(joy >> 8));
buffer.push_back(static_cast<uint8_t>(joy));
b = 0;
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::JoystickButton])) {
b |= 1;
}
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Trigger1])) {
b |= (1 << 1);
}
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Trigger2])) {
b |= (1 << 2);
}
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button1])) {
b |= (1 << 3);
}
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button2])) {
b |= (1 << 4);
}
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button3])) {
b |= (1 << 5);
}
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button4])) {
b |= (1 << 6);
}
buffer.push_back(b);
return true;
}
int write_output(std::span<const uint8_t> buffer) {
return 8;
}
};
}