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
+305
View File
@@ -0,0 +1,305 @@
#include "io.h"
std::vector<Button> &games::nost::get_buttons() {
static std::vector<Button> buttons;
if (buttons.empty()) {
buttons = GameAPI::Buttons::getButtons("Nostalgia");
GameAPI::Buttons::sortButtons(
&buttons,
"Service",
"Test",
"Coin Mech",
"Key 1",
"Key 2",
"Key 3",
"Key 4",
"Key 5",
"Key 6",
"Key 7",
"Key 8",
"Key 9",
"Key 10",
"Key 11",
"Key 12",
"Key 13",
"Key 14",
"Key 15",
"Key 16",
"Key 17",
"Key 18",
"Key 19",
"Key 20",
"Key 21",
"Key 22",
"Key 23",
"Key 24",
"Key 25",
"Key 26",
"Key 27",
"Key 28",
"Key 1 Soft",
"Key 2 Soft",
"Key 3 Soft",
"Key 4 Soft",
"Key 5 Soft",
"Key 6 Soft",
"Key 7 Soft",
"Key 8 Soft",
"Key 9 Soft",
"Key 10 Soft",
"Key 11 Soft",
"Key 12 Soft",
"Key 13 Soft",
"Key 14 Soft",
"Key 15 Soft",
"Key 16 Soft",
"Key 17 Soft",
"Key 18 Soft",
"Key 19 Soft",
"Key 20 Soft",
"Key 21 Soft",
"Key 22 Soft",
"Key 23 Soft",
"Key 24 Soft",
"Key 25 Soft",
"Key 26 Soft",
"Key 27 Soft",
"Key 28 Soft",
"Key 1 Medium",
"Key 2 Medium",
"Key 3 Medium",
"Key 4 Medium",
"Key 5 Medium",
"Key 6 Medium",
"Key 7 Medium",
"Key 8 Medium",
"Key 9 Medium",
"Key 10 Medium",
"Key 11 Medium",
"Key 12 Medium",
"Key 13 Medium",
"Key 14 Medium",
"Key 15 Medium",
"Key 16 Medium",
"Key 17 Medium",
"Key 18 Medium",
"Key 19 Medium",
"Key 20 Medium",
"Key 21 Medium",
"Key 22 Medium",
"Key 23 Medium",
"Key 24 Medium",
"Key 25 Medium",
"Key 26 Medium",
"Key 27 Medium",
"Key 28 Medium",
"Key 1 Hard",
"Key 2 Hard",
"Key 3 Hard",
"Key 4 Hard",
"Key 5 Hard",
"Key 6 Hard",
"Key 7 Hard",
"Key 8 Hard",
"Key 9 Hard",
"Key 10 Hard",
"Key 11 Hard",
"Key 12 Hard",
"Key 13 Hard",
"Key 14 Hard",
"Key 15 Hard",
"Key 16 Hard",
"Key 17 Hard",
"Key 18 Hard",
"Key 19 Hard",
"Key 20 Hard",
"Key 21 Hard",
"Key 22 Hard",
"Key 23 Hard",
"Key 24 Hard",
"Key 25 Hard",
"Key 26 Hard",
"Key 27 Hard",
"Key 28 Hard",
"Swipe Next Page",
"Swipe Previous Page",
"Touch Confirm",
"Touch Back",
"Touch Song 1",
"Touch Song 2",
"Touch Song 3",
"Touch Song 4",
"Touch Song 5",
"Touch Song 6",
"Touch Difficulty 1",
"Touch Difficulty 2",
"Touch Difficulty 3",
"Touch Difficulty 4"
);
}
return buttons;
}
std::string games::nost::get_buttons_help() {
// keep to max 100 characters wide
return
"For a MIDI piano, use [Key 1-28] for velocity-sensitive input.\n"
"For digital input (PC keyboard), use [Key 1-28 Medium].\n"
"For velocity-sensitive controllers in HID mode, use Analog tab.\n"
"\n"
"[Key 1-28] are velocity sensitive.\n"
"[Key 1-28 Soft] always trigger minimum velocity (ELEGANT in blue zone).\n"
"[Key 1-28 Medium] always trigger medium velocity (ELEGANT in both blue and yellow zones).\n"
"[Key 1-28 Hard] always trigger maximum velocity (ELEGANT in yellow zone)."
"\n"
"Swipe/Touch bindings are used for touch emulation, but enable -nostpoke first."
;
}
std::vector<Analog> &games::nost::get_analogs() {
static std::vector<Analog> analogs;
if (analogs.empty()) {
analogs = GameAPI::Analogs::getAnalogs("Nostalgia");
GameAPI::Analogs::sortAnalogs(
&analogs,
"Key 1",
"Key 2",
"Key 3",
"Key 4",
"Key 5",
"Key 6",
"Key 7",
"Key 8",
"Key 9",
"Key 10",
"Key 11",
"Key 12",
"Key 13",
"Key 14",
"Key 15",
"Key 16",
"Key 17",
"Key 18",
"Key 19",
"Key 20",
"Key 21",
"Key 22",
"Key 23",
"Key 24",
"Key 25",
"Key 26",
"Key 27",
"Key 28"
);
}
return analogs;
}
std::vector<Light> &games::nost::get_lights() {
static std::vector<Light> lights;
if (lights.empty()) {
lights = GameAPI::Lights::getLights("Nostalgia");
GameAPI::Lights::sortLights(
&lights,
"Title R",
"Title G",
"Title B",
"Bottom R",
"Bottom G",
"Bottom B",
"Key 1 R",
"Key 1 G",
"Key 1 B",
"Key 2 R",
"Key 2 G",
"Key 2 B",
"Key 3 R",
"Key 3 G",
"Key 3 B",
"Key 4 R",
"Key 4 G",
"Key 4 B",
"Key 5 R",
"Key 5 G",
"Key 5 B",
"Key 6 R",
"Key 6 G",
"Key 6 B",
"Key 7 R",
"Key 7 G",
"Key 7 B",
"Key 8 R",
"Key 8 G",
"Key 8 B",
"Key 9 R",
"Key 9 G",
"Key 9 B",
"Key 10 R",
"Key 10 G",
"Key 10 B",
"Key 11 R",
"Key 11 G",
"Key 11 B",
"Key 12 R",
"Key 12 G",
"Key 12 B",
"Key 13 R",
"Key 13 G",
"Key 13 B",
"Key 14 R",
"Key 14 G",
"Key 14 B",
"Key 15 R",
"Key 15 G",
"Key 15 B",
"Key 16 R",
"Key 16 G",
"Key 16 B",
"Key 17 R",
"Key 17 G",
"Key 17 B",
"Key 18 R",
"Key 18 G",
"Key 18 B",
"Key 19 R",
"Key 19 G",
"Key 19 B",
"Key 20 R",
"Key 20 G",
"Key 20 B",
"Key 21 R",
"Key 21 G",
"Key 21 B",
"Key 22 R",
"Key 22 G",
"Key 22 B",
"Key 23 R",
"Key 23 G",
"Key 23 B",
"Key 24 R",
"Key 24 G",
"Key 24 B",
"Key 25 R",
"Key 25 G",
"Key 25 B",
"Key 26 R",
"Key 26 G",
"Key 26 B",
"Key 27 R",
"Key 27 G",
"Key 27 B",
"Key 28 R",
"Key 28 G",
"Key 28 B"
);
}
return lights;
}
+278
View File
@@ -0,0 +1,278 @@
#pragma once
#include <vector>
#include "cfg/api.h"
namespace games::nost {
// all buttons in correct order
namespace Buttons {
enum Button {
Service,
Test,
CoinMech,
Key1,
Key2,
Key3,
Key4,
Key5,
Key6,
Key7,
Key8,
Key9,
Key10,
Key11,
Key12,
Key13,
Key14,
Key15,
Key16,
Key17,
Key18,
Key19,
Key20,
Key21,
Key22,
Key23,
Key24,
Key25,
Key26,
Key27,
Key28,
Key1Soft,
Key2Soft,
Key3Soft,
Key4Soft,
Key5Soft,
Key6Soft,
Key7Soft,
Key8Soft,
Key9Soft,
Key10Soft,
Key11Soft,
Key12Soft,
Key13Soft,
Key14Soft,
Key15Soft,
Key16Soft,
Key17Soft,
Key18Soft,
Key19Soft,
Key20Soft,
Key21Soft,
Key22Soft,
Key23Soft,
Key24Soft,
Key25Soft,
Key26Soft,
Key27Soft,
Key28Soft,
Key1Medium,
Key2Medium,
Key3Medium,
Key4Medium,
Key5Medium,
Key6Medium,
Key7Medium,
Key8Medium,
Key9Medium,
Key10Medium,
Key11Medium,
Key12Medium,
Key13Medium,
Key14Medium,
Key15Medium,
Key16Medium,
Key17Medium,
Key18Medium,
Key19Medium,
Key20Medium,
Key21Medium,
Key22Medium,
Key23Medium,
Key24Medium,
Key25Medium,
Key26Medium,
Key27Medium,
Key28Medium,
Key1Hard,
Key2Hard,
Key3Hard,
Key4Hard,
Key5Hard,
Key6Hard,
Key7Hard,
Key8Hard,
Key9Hard,
Key10Hard,
Key11Hard,
Key12Hard,
Key13Hard,
Key14Hard,
Key15Hard,
Key16Hard,
Key17Hard,
Key18Hard,
Key19Hard,
Key20Hard,
Key21Hard,
Key22Hard,
Key23Hard,
Key24Hard,
Key25Hard,
Key26Hard,
Key27Hard,
Key28Hard,
PokeNextPage,
PokePrevPage,
PokeConfirm,
PokeBack,
PokeSong1,
PokeSong2,
PokeSong3,
PokeSong4,
PokeSong5,
PokeSong6,
PokeDifficulty1,
PokeDifficulty2,
PokeDifficulty3,
PokeDifficulty4,
};
}
// all analogs in correct order
namespace Analogs {
enum {
Key1,
Key2,
Key3,
Key4,
Key5,
Key6,
Key7,
Key8,
Key9,
Key10,
Key11,
Key12,
Key13,
Key14,
Key15,
Key16,
Key17,
Key18,
Key19,
Key20,
Key21,
Key22,
Key23,
Key24,
Key25,
Key26,
Key27,
Key28,
};
}
// all lights in correct order
namespace Lights {
enum {
TitleR,
TitleG,
TitleB,
BottomR,
BottomG,
BottomB,
Key1R,
Key1G,
Key1B,
Key2R,
Key2G,
Key2B,
Key3R,
Key3G,
Key3B,
Key4R,
Key4G,
Key4B,
Key5R,
Key5G,
Key5B,
Key6R,
Key6G,
Key6B,
Key7R,
Key7G,
Key7B,
Key8R,
Key8G,
Key8B,
Key9R,
Key9G,
Key9B,
Key10R,
Key10G,
Key10B,
Key11R,
Key11G,
Key11B,
Key12R,
Key12G,
Key12B,
Key13R,
Key13G,
Key13B,
Key14R,
Key14G,
Key14B,
Key15R,
Key15G,
Key15B,
Key16R,
Key16G,
Key16B,
Key17R,
Key17G,
Key17B,
Key18R,
Key18G,
Key18B,
Key19R,
Key19G,
Key19B,
Key20R,
Key20G,
Key20B,
Key21R,
Key21G,
Key21B,
Key22R,
Key22G,
Key22B,
Key23R,
Key23G,
Key23B,
Key24R,
Key24G,
Key24B,
Key25R,
Key25G,
Key25B,
Key26R,
Key26G,
Key26B,
Key27R,
Key27G,
Key27B,
Key28R,
Key28G,
Key28B,
};
}
// getters
std::vector<Button> &get_buttons();
std::string get_buttons_help();
std::vector<Analog> &get_analogs();
std::vector<Light> &get_lights();
}
+62
View File
@@ -0,0 +1,62 @@
// enable touch functions - set version to windows 7
// mingw otherwise doesn't load touch stuff
#define _WIN32_WINNT 0x0601
#include "nost.h"
#include "poke.h"
#include "hooks/setupapihook.h"
#include "misc/wintouchemu.h"
#include "avs/game.h"
namespace games::nost {
bool ENABLE_POKE = false;
NostGame::NostGame() : Game("Nostalgia") {
}
void NostGame::attach() {
Game::attach();
// fake touchscreen
///////////////////
SETUPAPI_SETTINGS touch_settings{};
// GUID must be set to 0 to make SETUPAPI hook working
touch_settings.class_guid[0] = 0x00000000;
touch_settings.class_guid[1] = 0x00000000;
touch_settings.class_guid[2] = 0x00000000;
touch_settings.class_guid[3] = 0x00000000;
/*
* set hardware ID containing VID and PID
* there is 3 known VID/PID combinations known to the game:
* VID_04DD&PID_97CB
* VID_0EEF&PID_C000
* VID_29BD&PID_4101
*/
const char touch_hardwareid[] = "VID_29BD&PID_4101";
memcpy(touch_settings.property_hardwareid, touch_hardwareid, sizeof(touch_hardwareid));
// apply settings
setupapihook_init(avs::game::DLL_INSTANCE);
setupapihook_add(touch_settings);
// custom touch
// nostalgia crashes if you inject touch events too early
wintouchemu::hook("nostalgia", avs::game::DLL_INSTANCE, 20);
}
void NostGame::post_attach() {
if (ENABLE_POKE) {
poke::enable();
}
}
void NostGame::detach() {
if (ENABLE_POKE) {
poke::disable();
}
}
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "games/game.h"
namespace games::nost {
extern bool ENABLE_POKE;
class NostGame : public games::Game {
public:
NostGame();
virtual void attach() override;
virtual void post_attach() override;
virtual void detach() override;
};
}
+204
View File
@@ -0,0 +1,204 @@
#include "poke.h"
#include <thread>
#include <optional>
#include "games/nost/io.h"
#include "cfg/api.h"
#include "rawinput/rawinput.h"
#include "misc/eamuse.h"
#include "touch/touch.h"
#include "util/logging.h"
namespace games::nost::poke {
static std::thread *THREAD = nullptr;
static volatile bool THREAD_RUNNING = false;
static const std::unordered_map<int, std::pair<LONG, LONG>> NOST_POKE_NUM {
{EAM_IO_KEYPAD_0, {760, 440}},
{EAM_IO_KEYPAD_1, {760, 385}},
{EAM_IO_KEYPAD_2, {820, 385}},
{EAM_IO_KEYPAD_3, {880, 385}},
{EAM_IO_KEYPAD_4, {760, 325}},
{EAM_IO_KEYPAD_5, {820, 325}},
{EAM_IO_KEYPAD_6, {880, 325}},
{EAM_IO_KEYPAD_7, {760, 265}},
{EAM_IO_KEYPAD_8, {820, 265}},
{EAM_IO_KEYPAD_9, {880, 265}},
{EAM_IO_KEYPAD_00, {820, 440}}, // erase button
{EAM_IO_KEYPAD_DECIMAL, {880, 440}} // also erase button
};
static const std::unordered_map<games::nost::Buttons::Button, std::pair<LONG, LONG>> NOST_POKE {
{games::nost::Buttons::Button::PokeConfirm, {1100, 525}},
{games::nost::Buttons::Button::PokeBack, {340, 100}},
{games::nost::Buttons::Button::PokeSong1, {450, 190}},
{games::nost::Buttons::Button::PokeSong2, {450, 330}},
{games::nost::Buttons::Button::PokeSong3, {450, 480}},
{games::nost::Buttons::Button::PokeSong4, {840, 190}},
{games::nost::Buttons::Button::PokeSong5, {840, 330}},
{games::nost::Buttons::Button::PokeSong6, {840, 480}},
{games::nost::Buttons::Button::PokeDifficulty1, {820, 240}},
{games::nost::Buttons::Button::PokeDifficulty2, {820, 320}},
{games::nost::Buttons::Button::PokeDifficulty3, {820, 410}},
{games::nost::Buttons::Button::PokeDifficulty4, {820, 490}},
};
void clear_touch_points(std::vector<TouchPoint> *touch_points) {
std::vector<DWORD> touch_ids;
for (auto &touch : *touch_points) {
touch_ids.emplace_back(touch.id);
}
touch_remove_points(&touch_ids);
touch_points->clear();
}
void enable() {
// check if already running
if (THREAD) {
return;
}
// create new thread
THREAD_RUNNING = true;
THREAD = new std::thread([] {
const DWORD touch_id = (DWORD)(0xFFFFFFFE);
const int swipe_anim_total_frames = 6;
const int swipe_anim_y = 300;
const int swipe_next_page_x_begin = 1120;
const int swipe_next_page_x_end = 1120-120;
const int swipe_prev_page_x_begin = 280-120;
const int swipe_prev_page_x_end = 280;
int next_page_anim_index = -1;
int prev_page_anim_index = -1;
std::vector<TouchPoint> touch_points;
bool touch_release = false;
// log
log_info("poke", "enabled");
// set variable to false to stop
while (THREAD_RUNNING) {
// clean up touch from last frame
if (!touch_points.empty()) {
if (touch_release) {
clear_touch_points(&touch_points);
touch_release = false;
} else {
touch_points.clear();
}
}
auto &buttons = games::nost::get_buttons();
if (0 <= next_page_anim_index) {
const auto delta =
(swipe_next_page_x_end - swipe_next_page_x_begin)
* (swipe_anim_total_frames - next_page_anim_index) / swipe_anim_total_frames;
TouchPoint tp {
.id = touch_id,
.x = (LONG)swipe_next_page_x_begin + delta,
.y = (LONG)swipe_anim_y,
.mouse = true,
};
touch_points.emplace_back(tp);
next_page_anim_index--;
if (next_page_anim_index < 0) {
touch_release = true;
}
} else if (0 <= prev_page_anim_index) {
const auto delta =
(swipe_prev_page_x_end - swipe_prev_page_x_begin)
* (swipe_anim_total_frames - prev_page_anim_index) / swipe_anim_total_frames;
TouchPoint tp {
.id = touch_id,
.x = (LONG)swipe_prev_page_x_begin + delta,
.y = (LONG)swipe_anim_y,
.mouse = true,
};
touch_points.emplace_back(tp);
prev_page_anim_index--;
if (prev_page_anim_index < 0) {
touch_release = true;
}
} else {
for (const auto& it : NOST_POKE) {
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(it.first))) {
TouchPoint tp {
.id = touch_id,
.x = it.second.first,
.y = it.second.second,
.mouse = true,
};
touch_points.emplace_back(tp);
touch_release = true;
break;
}
}
if (!touch_release) {
const auto state = eamuse_get_keypad_state(0);
if (state) {
for (const auto& it : NOST_POKE_NUM) {
if (state & (1 << it.first)) {
TouchPoint tp {
.id = touch_id,
.x = it.second.first,
.y = it.second.second,
.mouse = true,
};
touch_points.emplace_back(tp);
touch_release = true;
break;
}
}
}
}
// start animations for next frame
if (!touch_release) {
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::PokeNextPage))) {
next_page_anim_index = swipe_anim_total_frames;
}
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::PokePrevPage))) {
prev_page_anim_index = swipe_anim_total_frames;
}
}
}
if (!touch_points.empty()) {
touch_write_points(&touch_points);
}
// slow down
Sleep(30);
}
return nullptr;
});
}
void disable() {
if (!THREAD) {
return;
}
// stop old thread
THREAD_RUNNING = false;
THREAD->join();
// delete thread
delete THREAD;
THREAD = nullptr;
// log
log_info("poke", "disabled");
}
}
+6
View File
@@ -0,0 +1,6 @@
#pragma once
namespace games::nost::poke {
void enable();
void disable();
}