mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
otoca: add cam hook, fix printer rotation (#573)
## Link to GitHub Issue or related Pull Request, if one exists related to #154 though this PR doesn't fix it ## Description of change 1. Add an option for cam hook so that the game can be launched without any camera 1. Rotate image printed out by print-to-file so that it's right side up (portrait orientation) ## Testing Able to boot the game without any cameras, and tested printing in test menu. "Holo" printing remains broken.
This commit is contained in:
@@ -256,6 +256,7 @@ namespace games {
|
|||||||
const std::string otoca("Otoca D'or");
|
const std::string otoca("Otoca D'or");
|
||||||
games.push_back(otoca);
|
games.push_back(otoca);
|
||||||
buttons.insert({ otoca, otoca::get_buttons() });
|
buttons.insert({ otoca, otoca::get_buttons() });
|
||||||
|
buttons_help.insert({ otoca, otoca::get_buttons_help() });
|
||||||
file_hints[otoca].emplace_back("arkkep.dll");
|
file_hints[otoca].emplace_back("arkkep.dll");
|
||||||
|
|
||||||
// winning eleven
|
// winning eleven
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ std::vector<Button> &games::otoca::get_buttons() {
|
|||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string games::otoca::get_buttons_help() {
|
||||||
|
// keep to max 100 characters wide
|
||||||
|
return " BT_Left Lever BT_Right";
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Light> &games::otoca::get_lights() {
|
std::vector<Light> &games::otoca::get_lights() {
|
||||||
static std::vector<Light> lights;
|
static std::vector<Light> lights;
|
||||||
|
|
||||||
|
|||||||
@@ -30,5 +30,6 @@ namespace games::otoca {
|
|||||||
|
|
||||||
// getters
|
// getters
|
||||||
std::vector<Button> &get_buttons();
|
std::vector<Button> &get_buttons();
|
||||||
|
std::string get_buttons_help();
|
||||||
std::vector<Light> &get_lights();
|
std::vector<Light> &get_lights();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,121 @@
|
|||||||
#include "otoca.h"
|
#include "otoca.h"
|
||||||
#include "p4io.h"
|
#include "p4io.h"
|
||||||
#include "games/shared/printer.h"
|
#include "games/shared/printer.h"
|
||||||
|
#include "util/detour.h"
|
||||||
#include "util/libutils.h"
|
#include "util/libutils.h"
|
||||||
|
#include "util/logging.h"
|
||||||
|
|
||||||
|
#define OTOCA_DEBUG_VERBOSE 0
|
||||||
|
#if OTOCA_DEBUG_VERBOSE
|
||||||
|
#define log_debug(module, format_str, ...) logger::push( \
|
||||||
|
LOG_FORMAT("M", module, format_str, ## __VA_ARGS__), logger::Style::GREY)
|
||||||
|
#else
|
||||||
|
#define log_debug(module, format_str, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace games::otoca {
|
namespace games::otoca {
|
||||||
|
|
||||||
|
bool BYPASS_CAMERA = false;
|
||||||
|
|
||||||
|
// for dev only
|
||||||
|
static bool CAMLIB_CALL_ORIGINAL = false;
|
||||||
|
|
||||||
OtocaGame::OtocaGame() : Game("Otoca D'or") {
|
OtocaGame::OtocaGame() : Game("Otoca D'or") {
|
||||||
}
|
}
|
||||||
|
|
||||||
OtocaGame::~OtocaGame() {
|
OtocaGame::~OtocaGame() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void (__cdecl *LibCameraInit_t)();
|
||||||
|
static LibCameraInit_t LibCameraInit_orig = nullptr;
|
||||||
|
static void __cdecl LibCameraInit_hook() {
|
||||||
|
if (CAMLIB_CALL_ORIGINAL) {
|
||||||
|
LibCameraInit_orig();
|
||||||
|
log_debug("otoca::cam", "LibCameraInit returned");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int (__cdecl *LibCameraOpen_t)(double, int, int);
|
||||||
|
static LibCameraOpen_t LibCameraOpen_orig = nullptr;
|
||||||
|
static int __cdecl LibCameraOpen_hook(double a1, int a2, int a3) {
|
||||||
|
int ret = 0;
|
||||||
|
if (CAMLIB_CALL_ORIGINAL) {
|
||||||
|
// with webcam, (15, 2, 0) returned 0
|
||||||
|
ret = LibCameraOpen_orig(a1, a2, a3);
|
||||||
|
log_debug("otoca::cam", "LibCameraOpen({}, {}, {}) returned {}", a1, a2, a3, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int (__cdecl *LibCameraStop_t)(int);
|
||||||
|
static LibCameraStop_t LibCameraStop_orig = nullptr;
|
||||||
|
static int __cdecl LibCameraStop_hook(int a1) {
|
||||||
|
int ret = 0;
|
||||||
|
if (CAMLIB_CALL_ORIGINAL) {
|
||||||
|
// with webcam,
|
||||||
|
ret = LibCameraStop_orig(a1);
|
||||||
|
log_debug("otoca::cam", "LibCameraStop({}) returned {}", a1, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (__cdecl *LibCameraGetCameraNr_t)();
|
||||||
|
static LibCameraGetCameraNr_t LibCameraGetCameraNr_orig = nullptr;
|
||||||
|
static void __cdecl LibCameraGetCameraNr_hook() {
|
||||||
|
if (CAMLIB_CALL_ORIGINAL) {
|
||||||
|
LibCameraGetCameraNr_orig();
|
||||||
|
log_debug("otoca::cam", "LibCameraGetCameraNr returned");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int (__cdecl *LibCameraRun_t)(int);
|
||||||
|
static LibCameraRun_t LibCameraRun_orig = nullptr;
|
||||||
|
static int __cdecl LibCameraRun_hook(int a1) {
|
||||||
|
int ret = 0;
|
||||||
|
if (CAMLIB_CALL_ORIGINAL) {
|
||||||
|
// with webcam, (0) returned 0
|
||||||
|
ret = LibCameraRun_orig(a1);
|
||||||
|
log_debug("otoca::cam", "LibCameraRun({}) returned {}", a1, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int (__cdecl *LibCameraGetImage_t)(int, void *);
|
||||||
|
static LibCameraGetImage_t LibCameraGetImage_orig = nullptr;
|
||||||
|
static int __cdecl LibCameraGetImage_hook(int a1, void *a2) {
|
||||||
|
int ret = 0;
|
||||||
|
if (CAMLIB_CALL_ORIGINAL) {
|
||||||
|
// not sure if this is called
|
||||||
|
ret = LibCameraGetImage_orig(a1, a2);
|
||||||
|
log_debug("otoca::cam", "LibCameraGetImage({}, {}) returned {}", a1, fmt::ptr(a2), ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int (__cdecl *LibCameraGetBrightness_t)(int *, int);
|
||||||
|
static LibCameraGetBrightness_t LibCameraGetBrightness_orig = nullptr;
|
||||||
|
static int __cdecl LibCameraGetBrightness_hook(int *a1, int a2) {
|
||||||
|
int ret = 0;
|
||||||
|
if (CAMLIB_CALL_ORIGINAL) {
|
||||||
|
// with webcam, (ptr,) returned
|
||||||
|
ret = LibCameraGetBrightness_orig(a1, a2);
|
||||||
|
}
|
||||||
|
log_debug("otoca::cam", "LibCameraGetBrightness({}, {}) returned {}", fmt::ptr(a1), a2, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int (__cdecl *LibCameraGetBrightnessRange_t)(int *, int *, int);
|
||||||
|
static LibCameraGetBrightnessRange_t LibCameraGetBrightnessRange_orig = nullptr;
|
||||||
|
static int __cdecl LibCameraGetBrightnessRange_hook(int *a1, int *a2, int a3) {
|
||||||
|
int ret = 0;
|
||||||
|
if (CAMLIB_CALL_ORIGINAL) {
|
||||||
|
// with webcam, (ptr, ptr, 0) returned 0
|
||||||
|
ret = LibCameraGetBrightnessRange_orig(a1, a2, a3);
|
||||||
|
log_debug("otoca::cam", "LibCameraGetBrightnessRange({}, {}, {}) returned {}", fmt::ptr(a1), fmt::ptr(a2), a3, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void OtocaGame::attach() {
|
void OtocaGame::attach() {
|
||||||
Game::attach();
|
Game::attach();
|
||||||
|
|
||||||
@@ -23,5 +128,42 @@ namespace games::otoca {
|
|||||||
// initialize IO hooks
|
// initialize IO hooks
|
||||||
p4io_hook();
|
p4io_hook();
|
||||||
games::shared::printer_attach();
|
games::shared::printer_attach();
|
||||||
|
|
||||||
|
if (BYPASS_CAMERA) {
|
||||||
|
libutils::try_library("libcamera.dll");
|
||||||
|
const auto libcamera = "libcamera.dll";
|
||||||
|
detour::trampoline_try(
|
||||||
|
libcamera,
|
||||||
|
"?LibCameraInit@@YAXXZ",
|
||||||
|
LibCameraInit_hook, &LibCameraInit_orig);
|
||||||
|
detour::trampoline_try(
|
||||||
|
libcamera,
|
||||||
|
"?LibCameraOpen@@YA?AW4LIBCAMERA_STATUS@@NHPAUt_libcamera_open_param@@@Z",
|
||||||
|
LibCameraOpen_hook, &LibCameraOpen_orig);
|
||||||
|
detour::trampoline_try(
|
||||||
|
libcamera,
|
||||||
|
"?LibCameraStop@@YA?AW4LIBCAMERA_STATUS@@H@Z",
|
||||||
|
LibCameraStop_hook, &LibCameraStop_orig);
|
||||||
|
detour::trampoline_try(
|
||||||
|
libcamera,
|
||||||
|
"?LibCameraGetCameraNr@@YAHXZ",
|
||||||
|
LibCameraGetCameraNr_hook, &LibCameraGetCameraNr_orig);
|
||||||
|
detour::trampoline_try(
|
||||||
|
libcamera,
|
||||||
|
"?LibCameraRun@@YA?AW4LIBCAMERA_STATUS@@H@Z",
|
||||||
|
LibCameraRun_hook, &LibCameraRun_orig);
|
||||||
|
detour::trampoline_try(
|
||||||
|
libcamera,
|
||||||
|
"?LibCameraGetImage@@YA?AW4LIBCAMERA_STATUS@@HPAX@Z",
|
||||||
|
LibCameraGetImage_hook, &LibCameraGetImage_orig);
|
||||||
|
detour::trampoline_try(
|
||||||
|
libcamera,
|
||||||
|
"?LibCameraGetBrightness@@YA?AW4LIBCAMERA_STATUS@@PAJH@Z",
|
||||||
|
LibCameraGetBrightness_hook, &LibCameraGetBrightness_orig);
|
||||||
|
detour::trampoline_try(
|
||||||
|
libcamera,
|
||||||
|
"?LibCameraGetBrightnessRange@@YA?AW4LIBCAMERA_STATUS@@PAJ0H@Z",
|
||||||
|
LibCameraGetBrightnessRange_hook, &LibCameraGetBrightnessRange_orig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
namespace games::otoca {
|
namespace games::otoca {
|
||||||
|
|
||||||
|
extern bool BYPASS_CAMERA;
|
||||||
|
|
||||||
class OtocaGame : public games::Game {
|
class OtocaGame : public games::Game {
|
||||||
public:
|
public:
|
||||||
OtocaGame();
|
OtocaGame();
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ namespace games::shared {
|
|||||||
image_data[index + 2] = tmp;
|
image_data[index + 2] = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avs::game::is_model({"KLP", "KFC"})) {
|
if (avs::game::is_model({"KLP", "KFC", "NCG"})) {
|
||||||
// rotate image clockwise
|
// rotate image clockwise
|
||||||
log_misc("printer", "rotate clockwise...");
|
log_misc("printer", "rotate clockwise...");
|
||||||
auto rotated = new uint8_t[image_width * image_height * 3];
|
auto rotated = new uint8_t[image_width * image_height * 3];
|
||||||
|
|||||||
@@ -559,6 +559,10 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
nvenc_hook::FORCE_DISABLE = true;
|
nvenc_hook::FORCE_DISABLE = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (options[launcher::Options::OtocaCamHook].value_bool()) {
|
||||||
|
games::otoca::BYPASS_CAMERA = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (options[launcher::Options::LoadJubeatModule].value_bool()) {
|
if (options[launcher::Options::LoadJubeatModule].value_bool()) {
|
||||||
attach_jb = true;
|
attach_jb = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2678,6 +2678,17 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.type = OptionType::Bool,
|
.type = OptionType::Bool,
|
||||||
.category = "Development",
|
.category = "Development",
|
||||||
.disabled = true,
|
.disabled = true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// OtocaCamHook
|
||||||
|
.title = "Otoca Camera Check Bypass",
|
||||||
|
.name = "otocacamhook",
|
||||||
|
.desc =
|
||||||
|
"This game REQUIRES a (compatible) webcam to save progress. If you don't have any, check this "
|
||||||
|
"option to bypass camera error during boot, allowing you to try out the game.",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.game_name = "Otoca D'or",
|
||||||
|
.category = "Game Options",
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -271,6 +271,7 @@ namespace launcher {
|
|||||||
LovePlusPrinterOutputFormat,
|
LovePlusPrinterOutputFormat,
|
||||||
LovePlusPrinterJPGQuality,
|
LovePlusPrinterJPGQuality,
|
||||||
OptionConflictResolution,
|
OptionConflictResolution,
|
||||||
|
OtocaCamHook,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class OptionsCategory {
|
enum class OptionsCategory {
|
||||||
|
|||||||
Reference in New Issue
Block a user