diff --git a/src/spice2x/acio/icca/icca.cpp b/src/spice2x/acio/icca/icca.cpp index 82d3b4f..f8493cb 100644 --- a/src/spice2x/acio/icca/icca.cpp +++ b/src/spice2x/acio/icca/icca.cpp @@ -35,24 +35,33 @@ struct ICCA_STATUS_LA9 { static_assert(sizeof(struct ICCA_STATUS) == 24, "ICCA_STATUS must be 24 bytes"); enum ICCA_WORKFLOW { - STEP, - SLEEP, - START, - INIT, - READY, - GET_USERID, - ACTIVE, - EJECT, - EJECT_CHECK, - END, - CLOSE_EJECT, - CLOSE_E_CHK, - CLOSE_END, - ERR_GETUID = -2 + STEP = 0, + SLEEP = 1, + START = 2, + INIT = 3, + READY = 4, + GET_USERID = 5, + ACTIVE = 6, + EJECT = 7, + EJECT_CHECK = 8, + END = 9, + CLOSE_EJECT = 10, + CLOSE_E_CHK = 11, + CLOSE_END = 12, + ERR_GETUID = -2, + ERR_REMOVED = -11 }; + +// used by RA as the status_code +enum ICCA_STATUS_CODE { + EMPTY = 1, + ENGAGED = 2 +}; + struct ICCA_UNIT { struct ICCA_STATUS status {}; enum ICCA_WORKFLOW state = STEP; + enum ICCA_WORKFLOW state_jdz = SLEEP; bool card_cmd_pressed = false; bool card_in = false; double card_in_time = 0.0; @@ -75,6 +84,11 @@ static inline int icca_get_active_count() { } static inline int icca_get_unit_id(int unit_id) { + // on RA the unit_id is zero-indexed + if (avs::game::is_model("JDZ")) { + return unit_id; + } + if (icca_get_active_count() < 2) return 1; else { @@ -122,9 +136,15 @@ static inline void update_card(int unit_id) { IS_LAST_CARD_FELICA = is_card_uid_felica(unit->status.uid); unit->state = acio::ICCA_COMPAT_ACTIVE ? START : ACTIVE; + unit->state_jdz = ACTIVE; unit->status.error = 0; + unit->status.front_sensor = 1; + unit->status.rear_sensor = 1; } else { unit->state = ERR_GETUID; + unit->state_jdz = ERR_GETUID; + unit->status.front_sensor = 1; + unit->status.rear_sensor = 1; memset(unit->status.uid, 0, 8); } unit->card_in = true; @@ -132,10 +152,25 @@ static inline void update_card(int unit_id) { } else if (unit->state == EJECT_CHECK) { unit->state = SLEEP; unit->card_in = false; + unit->status.front_sensor = 0; + unit->status.rear_sensor = 0; + } else if (unit->state_jdz == READY) { + unit->state = GET_USERID; + unit->state_jdz = GET_USERID; + unit->status.error = 0; + unit->status.front_sensor = 1; + unit->status.rear_sensor = 1; + unit->card_in = true; + unit->card_in_time = get_performance_seconds(); } } else { unit->state = acio::ICCA_COMPAT_ACTIVE ? START : ACTIVE; + if (unit->state_jdz == READY) { + unit->state_jdz = GET_USERID; + } unit->status.error = 0; + unit->status.front_sensor = 1; + unit->status.rear_sensor = 1; unit->card_in = true; unit->card_in_time = get_performance_seconds(); } @@ -144,6 +179,12 @@ static inline void update_card(int unit_id) { unit->state = CLOSE_EJECT; if (fabs(get_performance_seconds() - unit->card_in_time) > CARD_TIMEOUT) { unit->card_in = false; + memset(unit->status.uid, 0, 8); + if (unit->state_jdz == ACTIVE || unit->state_jdz == GET_USERID) { + unit->state_jdz = ERR_REMOVED; + } + unit->status.front_sensor = 0; + unit->status.rear_sensor = 0; } } @@ -302,7 +343,11 @@ static char __cdecl ac_io_icca_get_status(void *a1, void *a2) { // copy state to output buffer ICCA_UNIT *unit = &ICCA_UNITS[unit_id]; - unit->status.status_code = unit->state; + if (avs::game::is_model("JDZ")) { + unit->status.status_code = unit->card_in ? ENGAGED : EMPTY; + } else { + unit->status.status_code = unit->state; + } memcpy(status, &unit->status, sizeof(struct ICCA_STATUS)); // funny workaround @@ -387,6 +432,11 @@ static char __cdecl ac_io_icca_req_uid(int unit_id) { static int __cdecl ac_io_icca_req_uid_isfinished(int unit_id, DWORD *read_state) { unit_id = icca_get_unit_id(unit_id); ICCA_UNIT *unit = &ICCA_UNITS[unit_id]; + if (avs::game::is_model("JDZ")) { + // hack for RA - only ever seen it as this + *read_state = 8; + return 1; + } if (unit->card_in) { if (fabs(get_performance_seconds() - unit->card_in_time) < CARD_TIMEOUT) { unit->state = END; @@ -403,16 +453,61 @@ static int __cdecl ac_io_icca_send_keep_alive_packet(int a1, int a2, int a3) { return 0; } +static int __cdecl ac_io_icca_workflow_jdz(int workflow, int unit_id) { + + unit_id = icca_get_unit_id(unit_id); + ICCA_UNIT *unit = &ICCA_UNITS[unit_id]; + switch (workflow) { + // RA uses "STEP" as more of a polling thing it seems + case STEP: + switch (unit->state_jdz) { + case CLOSE_EJECT: + unit->state_jdz = CLOSE_E_CHK; + break; + case CLOSE_E_CHK: + unit->state_jdz = CLOSE_END; + break; + case CLOSE_END: + unit->state_jdz = SLEEP; + break; + default: + break; + } + break; + case SLEEP: + unit->state = SLEEP; + break; + case START: + unit->state_jdz = INIT; + break; + case INIT: + case READY: + unit->state_jdz = READY; + break; + case CLOSE_EJECT: + unit->state_jdz = CLOSE_EJECT; + return CLOSE_E_CHK; + case CLOSE_END: + unit->state_jdz = SLEEP; + break; + default: + // should probably log a warning here + break; + } + return unit->state_jdz; +} + static int __cdecl ac_io_icca_workflow(int workflow, int unit_id) { + // RA uses a different workflow process for the slotted readers; treat it differently + if (avs::game::is_model("JDZ")) { + return ac_io_icca_workflow_jdz(workflow, unit_id); + } unit_id = icca_get_unit_id(unit_id); ICCA_UNIT *unit = &ICCA_UNITS[unit_id]; switch (workflow) { case STEP: - if (avs::game::is_model("JDZ")) - unit->state = SLEEP; - else - unit->state = STEP; + unit->state = STEP; break; case SLEEP: unit->state = SLEEP; @@ -441,7 +536,6 @@ static int __cdecl ac_io_icca_workflow(int workflow, int unit_id) { default: break; } - return unit->state; } @@ -467,6 +561,14 @@ acio::ICCAModule::ICCAModule(HMODULE module, acio::HookMode hookMode) : ACIOModu void acio::ICCAModule::attach() { ACIOModule::attach(); + // workaround for RA; ac_io_icca_cardunit_init is never called so treat like both are initialized + if (avs::game::is_model("JDZ")) { + ICCA_UNITS[0].initialized = true; + ICCA_UNITS[1].initialized = true; + + CARD_TIMEOUT = 10.0; // keep the card in the slot for longer + } + // hooks ACIO_MODULE_HOOK(ac_io_icca_cardunit_init); ACIO_MODULE_HOOK(ac_io_icca_cardunit_init_isfinished); diff --git a/src/spice2x/cfg/screen_resize.h b/src/spice2x/cfg/screen_resize.h index f986028..aa4cdcc 100644 --- a/src/spice2x/cfg/screen_resize.h +++ b/src/spice2x/cfg/screen_resize.h @@ -60,6 +60,7 @@ namespace cfg { // window = rectangle including the frame // client = just the content area without frames. bool window_always_on_top = false; + bool window_disable_round_corners = false; bool client_keep_aspect_ratio = true; bool enable_window_resize = false; int window_decoration = 0; // enum type WindowDecorationMode diff --git a/src/spice2x/games/iidx/iidx.cpp b/src/spice2x/games/iidx/iidx.cpp index de17cb4..0bf0f09 100644 --- a/src/spice2x/games/iidx/iidx.cpp +++ b/src/spice2x/games/iidx/iidx.cpp @@ -915,8 +915,7 @@ namespace games::iidx { log_warning( "iidx", "Failed to apply ASIO compatibility fix for iidx32+. " - "Unless patches are applied, your ASIO device ({}) may hang or fail to work", - ASIO_DRIVER->c_str()); + "Unless patches are applied, your ASIO device may hang or fail to work"); } else { log_info( "iidx", diff --git a/src/spice2x/games/popn/bi3a_hook.cpp b/src/spice2x/games/popn/bi3a_hook.cpp index 95e07e5..cfc3409 100644 --- a/src/spice2x/games/popn/bi3a_hook.cpp +++ b/src/spice2x/games/popn/bi3a_hook.cpp @@ -475,7 +475,7 @@ namespace games::popn { const auto data_size = std::min(map.data.capacity(), (size_t)number_of_leds / 3); // pick a color to use - const auto rgb = tapeledutils::pick_color_from_led_tape((uint8_t *)i_pData, data_size); + const auto rgb = tapeledutils::pick_color_from_led_tape(map, (uint8_t *)i_pData, data_size); // program the lights into API auto &lights = get_lights(); diff --git a/src/spice2x/games/popn/io.cpp b/src/spice2x/games/popn/io.cpp index c4c156d..091b432 100644 --- a/src/spice2x/games/popn/io.cpp +++ b/src/spice2x/games/popn/io.cpp @@ -136,6 +136,18 @@ std::vector &games::popn::get_lights() { {"Pika", "IC Card R"}, {"Pika", "IC Card G"}, {"Pika", "IC Card B"}, + {"Pika", "Speakers R"}, + {"Pika", "Speakers G"}, + {"Pika", "Speakers B"}, + {"Pika", "Monitor R"}, + {"Pika", "Monitor G"}, + {"Pika", "Monitor B"}, + {"Pika", "Control Panel R"}, + {"Pika", "Control Panel G"}, + {"Pika", "Control Panel B"}, + {"Pika", "Cabinet R"}, + {"Pika", "Cabinet G"}, + {"Pika", "Cabinet B"}, }); } diff --git a/src/spice2x/games/popn/io.h b/src/spice2x/games/popn/io.h index e2f1393..36345cd 100644 --- a/src/spice2x/games/popn/io.h +++ b/src/spice2x/games/popn/io.h @@ -121,6 +121,18 @@ namespace games::popn { IC_Card_R, IC_Card_G, IC_Card_B, + Speaker_R, + Speaker_G, + Speaker_B, + Monitor_R, + Monitor_G, + Monitor_B, + ControlPanel_R, + ControlPanel_G, + ControlPanel_B, + Cabinet_R, + Cabinet_G, + Cabinet_B, } popn_lights_t; } diff --git a/src/spice2x/games/popn/popn.cpp b/src/spice2x/games/popn/popn.cpp index ac3f0f1..c6b4fe6 100644 --- a/src/spice2x/games/popn/popn.cpp +++ b/src/spice2x/games/popn/popn.cpp @@ -19,11 +19,13 @@ #include "util/sysutils.h" #include "io.h" #include "util/deferlog.h" +#include "misc/nativetouchhook.h" #include "misc/wintouchemu.h" namespace games::popn { bool SHOW_PIKA_MONITOR_WARNING = false; + bool NATIVE_TOUCH = false; #if SPICE64 && !SPICE_XP @@ -36,39 +38,83 @@ namespace games::popn { // pin 1 = left pop (red pop kun), size 16, values 0-0xFF // pin 2 = right pop (blue pop kun), size 16, values 0-0xFF // pin 3 = title, size 44, values 0-0xFF - // pin 4 = speaker, size 40, values 0-0xFF - U region only + // pin 4 = speaker, size 40, values 0-0x7F - U region only // pin 5 = monitor, size 18, values 0-0x7F - U region only // pin 6 = control panel, size 28, values 0-0x7F - U region only // pin 7 = cabinet, size 22, values 0-0x7F - U region only tapeledutils::tape_led TAPELED_MAPPING[POPN_TAPELED_TOTAL] = { { - 0, // these are button lights and handled specially + // [0] button lights: these are button lights and handled specially + 0, + 0, 0, 0, 0, "Invalid" }, { + // [1] red pop-kun 5, // 5*3; game reports 16 but make it 15 Lights::popn_lights_t::RedPopKun_R, Lights::popn_lights_t::RedPopKun_G, Lights::popn_lights_t::RedPopKun_B, + 0xFF, "Red Pop-Kun" }, { + // [2] blue pop-kun 5, // 5*3; game reports 16 but make it 15 Lights::popn_lights_t::BluePopKun_R, Lights::popn_lights_t::BluePopKun_G, Lights::popn_lights_t::BluePopKun_B, + 0xFF, "Blue Pop-Kun" }, { - 14, // 14*3; game reports 44 but make it 42; these are lights above the banner + // [3] top LED + 14, // 14*3; game reports 44 but make it 42 Lights::popn_lights_t::TopLED_R, Lights::popn_lights_t::TopLED_G, Lights::popn_lights_t::TopLED_B, + 0xFF, "Top" }, + { + // [4] speakers + 13, // 13*3; game reports 40 but make it 39 + Lights::popn_lights_t::Speaker_G, + Lights::popn_lights_t::Speaker_R, + Lights::popn_lights_t::Speaker_B, + 0x7F, + "Speakers" + }, + { + // [5] monitor + 6, + Lights::popn_lights_t::Monitor_G, + Lights::popn_lights_t::Monitor_R, + Lights::popn_lights_t::Monitor_B, + 0x7F, + "Monitor" + }, + { + // [6] control panel + 9, // 9*3; game reports 28 + Lights::popn_lights_t::ControlPanel_G, + Lights::popn_lights_t::ControlPanel_R, + Lights::popn_lights_t::ControlPanel_B, + 0x7F, + "Control Panel" + }, + { + // [7] Cabinet + 7, // 7*3; game reports 22 + Lights::popn_lights_t::Cabinet_G, + Lights::popn_lights_t::Cabinet_R, + Lights::popn_lights_t::Cabinet_B, + 0x7F, + "Cabinet" + }, }; @@ -670,9 +716,13 @@ namespace games::popn { // set third column to 0 and it will work with BIO2 if (!GRAPHICS_WINDOWED) { - wintouchemu::FORCE = true; - wintouchemu::INJECT_MOUSE_AS_WM_TOUCH = true; - wintouchemu::hook_title_ends("", "Main Screen", avs::game::DLL_INSTANCE); + if (NATIVE_TOUCH) { + nativetouchhook::hook(avs::game::DLL_INSTANCE); + } else { + wintouchemu::FORCE = true; + wintouchemu::INJECT_MOUSE_AS_WM_TOUCH = true; + wintouchemu::hook_title_ends("", "Main Screen", avs::game::DLL_INSTANCE); + } } sysutils::hook_EnumDisplayDevicesA(); diff --git a/src/spice2x/games/popn/popn.h b/src/spice2x/games/popn/popn.h index caebe6e..105e3b9 100644 --- a/src/spice2x/games/popn/popn.h +++ b/src/spice2x/games/popn/popn.h @@ -17,11 +17,12 @@ namespace games::popn { } #if SPICE64 - constexpr int POPN_TAPELED_TOTAL = 4; + constexpr int POPN_TAPELED_TOTAL = 8; extern tapeledutils::tape_led TAPELED_MAPPING[POPN_TAPELED_TOTAL]; #endif extern bool SHOW_PIKA_MONITOR_WARNING; + extern bool NATIVE_TOUCH; class POPNGame : public games::Game { public: diff --git a/src/spice2x/hooks/graphics/graphics.cpp b/src/spice2x/hooks/graphics/graphics.cpp index 3d54e17..02bdba6 100644 --- a/src/spice2x/hooks/graphics/graphics.cpp +++ b/src/spice2x/hooks/graphics/graphics.cpp @@ -476,6 +476,14 @@ static HWND WINAPI CreateWindowExW_hook(DWORD dwExStyle, LPCWSTR lpClassName, LP } } + // FTT + if (avs::game::is_model("MMD")) { + // set window name + if (!lpWindowName) { + lpWindowName = L"Future TomTom"; + } + } + if (GRAPHICS_WINDOWED) { graphics_window_check_bounds_before_creation(x, y, nWidth, nHeight); } @@ -924,6 +932,9 @@ void graphics_hook_subscreen_window(HWND hWnd) { if (GRAPHICS_WSUB_ALWAYS_ON_TOP) { graphics_update_z_order(hWnd, true); } + if (GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS) { + graphics_set_corner_preference(hWnd, true); + } } void graphics_screens_register(int screen) { diff --git a/src/spice2x/hooks/graphics/graphics.h b/src/spice2x/hooks/graphics/graphics.h index f49ce21..060fa73 100644 --- a/src/spice2x/hooks/graphics/graphics.h +++ b/src/spice2x/hooks/graphics/graphics.h @@ -7,6 +7,9 @@ #include #include +#if !SPICE_XP +#include +#endif #include "external/toojpeg/toojpeg.h" @@ -50,6 +53,7 @@ extern std::optional> GRAPHICS_WINDOW_SIZE; extern std::optional GRAPHICS_WINDOW_POS; extern bool GRAPHICS_WINDOW_ALWAYS_ON_TOP; extern bool GRAPHICS_WINDOW_BACKBUFFER_SCALE; +extern bool GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS; extern std::optional GRAPHICS_HOOKED_WINDOW; extern bool GRAPHICS_IIDX_WSUB; @@ -103,6 +107,7 @@ void graphics_windowed_wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara void graphics_capture_initial_window(HWND hWnd); void graphics_update_window_style(HWND hWnd, bool force_update=false); void graphics_update_z_order(HWND hWnd, bool always_on_top); +void graphics_set_corner_preference(HWND hWnd, bool disable); void graphics_move_resize_window(HWND hWnd); bool graphics_window_options_breaks_game(); bool graphics_window_decoration_change_crashes_game(); diff --git a/src/spice2x/hooks/graphics/graphics_windowed.cpp b/src/spice2x/hooks/graphics/graphics_windowed.cpp index 12a4f8a..d215b34 100644 --- a/src/spice2x/hooks/graphics/graphics_windowed.cpp +++ b/src/spice2x/hooks/graphics/graphics_windowed.cpp @@ -24,6 +24,7 @@ std::optional> GRAPHICS_WINDOW_SIZE; std::optional GRAPHICS_WINDOW_POS; bool GRAPHICS_WINDOW_ALWAYS_ON_TOP = false; bool GRAPHICS_WINDOW_BACKBUFFER_SCALE = false; +bool GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS = false; std::optional GRAPHICS_HOOKED_WINDOW; // IIDX Windowed Subscreen - starts out as false, enabled by IIDX module on pre-attach as needed @@ -132,6 +133,10 @@ void graphics_capture_initial_window(HWND hWnd) { log_info("graphics-windowed", "[{}] change window z-order - always on top", fmt::ptr(hWnd)); graphics_update_z_order(hWnd, true); } + if (cfg::SCREENRESIZE->window_disable_round_corners) { + log_info("graphics-windowed", "[{}] disabling rounded corners", fmt::ptr(hWnd)); + graphics_set_corner_preference(hWnd, true); + } // ensure spicetouch coordinates are initialized update_spicetouch_window_dimensions(hWnd); @@ -181,6 +186,10 @@ void graphics_load_windowed_parameters() { cfg::SCREENRESIZE->window_always_on_top = true; } + if (GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS) { + cfg::SCREENRESIZE->window_disable_round_corners = true; + } + log_debug("graphics-windowed", "graphics_load_windowed_parameters returned"); } @@ -469,6 +478,27 @@ void graphics_update_z_order(HWND hWnd, bool always_on_top) { log_debug("graphics-windowed", "graphics_update_z_order returned"); } +void graphics_set_corner_preference(HWND hWnd, bool disable) { + if (!GRAPHICS_WINDOWED) { + return; + } + +#if !SPICE_XP + log_debug("graphics-windowed", "graphics_set_corner_preference called"); + + DWM_WINDOW_CORNER_PREFERENCE corner_preference = disable ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT; + DwmSetWindowAttribute( + hWnd, + DWMWA_WINDOW_CORNER_PREFERENCE, + &corner_preference, sizeof(corner_preference)); + + log_debug("graphics-windowed", "graphics_set_corner_preference returned"); +#else + // don't link against DwmSetWindowAttribute on XP + log_debug("graphics-windowed", "graphics_set_corner_preference called; ignoring"); +#endif +} + void graphics_move_resize_window(HWND hWnd) { if (!GRAPHICS_WINDOWED) { return; @@ -502,8 +532,8 @@ bool graphics_window_decoration_change_crashes_game() { static std::once_flag flag; static bool result = false; std::call_once(flag, []() { - // ddr crashes when frame style changes - if (avs::game::is_model("MDX")) { + // ddr and ftt crash when frame style changes + if (avs::game::is_model("MDX") || avs::game::is_model("MMD")) { result = true; } diff --git a/src/spice2x/launcher/launcher.cpp b/src/spice2x/launcher/launcher.cpp index ad6789c..6e93f78 100644 --- a/src/spice2x/launcher/launcher.cpp +++ b/src/spice2x/launcher/launcher.cpp @@ -597,6 +597,9 @@ int main_implementation(int argc, char *argv[]) { if (options[launcher::Options::PopnSubMonitorOverride].is_active()) { sysutils::SECOND_MONITOR_OVERRIDE = options[launcher::Options::PopnSubMonitorOverride].value_text(); } + if (options[launcher::Options::PopnNativeTouch].value_bool()) { + games::popn::NATIVE_TOUCH = true; + } if (options[launcher::Options::LoadMetalGearArcadeModule].value_bool()) { attach_mga = true; } @@ -1117,6 +1120,7 @@ int main_implementation(int argc, char *argv[]) { } GRAPHICS_WINDOW_ALWAYS_ON_TOP = options[launcher::Options::spice2x_WindowAlwaysOnTop].value_bool(); GRAPHICS_WINDOW_BACKBUFFER_SCALE = options[launcher::Options::WindowForceScaling].value_bool(); + GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS = options[launcher::Options::WindowDisableRoundedCorners].value_bool(); // IIDX/SDVX Windowed Subscreen if (options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].is_active()) { @@ -1831,9 +1835,7 @@ int main_implementation(int argc, char *argv[]) { attach_ftt = true; // the game is windowed by default unless we set the env - if (GRAPHICS_WINDOWED) { - GRAPHICS_WINDOWED = false; - } else { + if (!GRAPHICS_WINDOWED) { SetEnvironmentVariable("DAMAC_VIEWER_FULLSCREEN", "0"); } diff --git a/src/spice2x/launcher/options.cpp b/src/spice2x/launcher/options.cpp index 66c6e28..42944cf 100644 --- a/src/spice2x/launcher/options.cpp +++ b/src/spice2x/launcher/options.cpp @@ -32,6 +32,7 @@ static const std::vector CATEGORY_ORDER_BASIC = { static const std::vector CATEGORY_ORDER_ADVANCED = { "Game Options (Advanced)", + "Game Options (Peripherals)", "Overlay", "Network (Advanced)", "Performance", @@ -513,7 +514,7 @@ static const std::vector OPTION_DEFINITIONS = { .desc = "Flip the camera order.", .type = OptionType::Bool, .game_name = "Beatmania IIDX", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { // IIDXDisableCameras @@ -523,7 +524,7 @@ static const std::vector OPTION_DEFINITIONS = { .type = OptionType::Bool, .hidden = true, .game_name = "Beatmania IIDX", - .category = "Game Options", + .category = "Game Options (Peripherals)", }, { // IIDXCabCamAccess @@ -533,7 +534,7 @@ static const std::vector OPTION_DEFINITIONS = { "Only turn this on if you have OFFICIAL arcade cameras connected to the correct USB ports. Default: auto.", .type = OptionType::Enum, .game_name = "Beatmania IIDX", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", .elements = { {"auto", ""}, {"off", ""}, @@ -549,7 +550,7 @@ static const std::vector OPTION_DEFINITIONS = { .desc = "Experimental camera support for IIDX 27+ via texture hooking. Requires camera(s) that support YUY2 or NV12 encoding.", .type = OptionType::Bool, .game_name = "Beatmania IIDX", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { // IIDXCamHookRatio @@ -561,7 +562,7 @@ static const std::vector OPTION_DEFINITIONS = { .type = OptionType::Enum, .hidden = true, .game_name = "Beatmania IIDX", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", .elements = { {"43", "4:3"}, {"169", "16:9"}, @@ -579,7 +580,7 @@ static const std::vector OPTION_DEFINITIONS = { .type = OptionType::Text, .setting_name = "0x5817a0,0x6fffbd8,0xbbae40,0xe0,0x30", .game_name = "Beatmania IIDX", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { // IIDXCamHookTopId @@ -594,7 +595,7 @@ static const std::vector OPTION_DEFINITIONS = { .type = OptionType::Text, .setting_name = "vid_1234&pid_5678", .game_name = "Beatmania IIDX", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { // IIDXCamHookFrontId @@ -609,7 +610,7 @@ static const std::vector OPTION_DEFINITIONS = { .type = OptionType::Text, .setting_name = "vid_90ab&pid_cdef", .game_name = "Beatmania IIDX", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { .title = "IIDX Sound Output Device", @@ -772,11 +773,11 @@ static const std::vector OPTION_DEFINITIONS = { .category = "Game Options (Advanced)", }, { - .title = "SDVX Force 720p", + .title = "SDVX Vivid Wave Force 720p Window (DEPRECATED - use -windowsize instead)", .name = "sdvx720", - .desc = "Force Sound Voltex 720p display mode, used by older games. " - "For newer games, use window resize function instead.", + .desc = "Old & deprecated option for launching Vivid Wave in 720p when using windowed mode.", .type = OptionType::Bool, + .hidden = true, .game_name = "Sound Voltex", .category = "Game Options (Advanced)", }, @@ -786,7 +787,7 @@ static const std::vector OPTION_DEFINITIONS = { .desc = "Enable Sound Voltex printer emulation.", .type = OptionType::Bool, .game_name = "Sound Voltex", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { // SDVXPrinterOutputPath @@ -795,7 +796,7 @@ static const std::vector OPTION_DEFINITIONS = { .desc = "Path to folder where images will be stored.", .type = OptionType::Text, .game_name = "Sound Voltex", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", .picker = OptionPickerType::DirectoryPath, }, { @@ -804,7 +805,7 @@ static const std::vector OPTION_DEFINITIONS = { .desc = "Clean up saved images in the output directory on startup.", .type = OptionType::Bool, .game_name = "Sound Voltex", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { .title = "SDVX Printer Output Overwrite", @@ -812,7 +813,7 @@ static const std::vector OPTION_DEFINITIONS = { .desc = "Always overwrite the same file in output directory.", .type = OptionType::Bool, .game_name = "Sound Voltex", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { // SDVXPrinterOutputFormat @@ -822,7 +823,7 @@ static const std::vector OPTION_DEFINITIONS = { .type = OptionType::Text, .setting_name = "(png/bmp/tga/jpg)", .game_name = "Sound Voltex", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { .title = "SDVX Printer JPG Quality", @@ -831,7 +832,7 @@ static const std::vector OPTION_DEFINITIONS = { .type = OptionType::Integer, .setting_name = "(0-100)", .game_name = "Sound Voltex", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { .title = "SDVX Disable Cameras (DEPRECATED - no longer needed)", @@ -842,7 +843,7 @@ static const std::vector OPTION_DEFINITIONS = { .type = OptionType::Bool, .hidden = true, .game_name = "Sound Voltex", - .category = "Game Options", + .category = "Game Options (Peripherals)", }, { .title = "SDVX FS Subscreen Native Touch Handling", @@ -1008,6 +1009,18 @@ static const std::vector OPTION_DEFINITIONS = { .category = "Monitor", .picker = OptionPickerType::Monitor, }, + { + // PopnNativeTouch + .title = "Pop'n Music PikaPika Native Touch Handling", + .name = "popnnativetouch", + .desc = "Disables touch hooks and lets the game access a touch screen directly. " + "Requires a touch screen to be connected as a secondary monitor. " + "Touch input must be routed to the primary screen via Windows Tablet PC settings. " + "Enable this when you get duplicate touch inputs from an actual touch screen.", + .type = OptionType::Bool, + .game_name = "Pop'n Music", + .category = "Game Options (Advanced)", + }, { .title = "Force Load HELLO! Pop'n Music Module", .name = "hpm", @@ -2218,6 +2231,14 @@ static const std::vector OPTION_DEFINITIONS = { .type = OptionType::Bool, .category = "Graphics (Windowed)", }, + { + // WindowDisableRoundedCorners + .title = "Disable Round Window Corners", + .name = "windownoroundcorners", + .desc = "Windows 11 and above only: Disables rounded corners on the game window(s).", + .type = OptionType::Bool, + .category = "Graphics (Windowed)", + }, { // spice2x_IIDXWindowedSubscreenSize .title = "IIDX Windowed Subscreen Size", @@ -2347,7 +2368,7 @@ static const std::vector OPTION_DEFINITIONS = { "Note: this is NOT for the motion camera - you still need a real RealSense camera for that!", .type = OptionType::Bool, .game_name = "DANCERUSH", - .category = "Game Options", + .category = "Game Options (Peripherals)", }, { // spice2x_IIDXNativeTouch @@ -2681,7 +2702,7 @@ static const std::vector OPTION_DEFINITIONS = { .desc = "Allow game to access camera; camera must be compatible with game.", .type = OptionType::Bool, .game_name = "LovePlus", - .category = "Game Options", + .category = "Game Options (Peripherals)", }, { // LovePlusPrinterOutputPath @@ -2690,7 +2711,7 @@ static const std::vector OPTION_DEFINITIONS = { .desc = "Path to folder where images will be stored.", .type = OptionType::Text, .game_name = "LovePlus", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", .picker = OptionPickerType::DirectoryPath, }, { @@ -2699,7 +2720,7 @@ static const std::vector OPTION_DEFINITIONS = { .desc = "Clean up saved images in the output directory on startup.", .type = OptionType::Bool, .game_name = "LovePlus", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { .title = "LovePlus Printer Output Overwrite", @@ -2707,7 +2728,7 @@ static const std::vector OPTION_DEFINITIONS = { .desc = "Always overwrite the same file in output directory.", .type = OptionType::Bool, .game_name = "LovePlus", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { // LovePlusPrinterOutputFormat @@ -2717,7 +2738,7 @@ static const std::vector OPTION_DEFINITIONS = { .type = OptionType::Text, .setting_name = "(png/bmp/tga/jpg)", .game_name = "LovePlus", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { .title = "LovePlus Printer JPG Quality", @@ -2726,7 +2747,7 @@ static const std::vector OPTION_DEFINITIONS = { .type = OptionType::Integer, .setting_name = "(0-100)", .game_name = "LovePlus", - .category = "Game Options (Advanced)", + .category = "Game Options (Peripherals)", }, { // OptionConflictResolution @@ -2747,7 +2768,7 @@ static const std::vector OPTION_DEFINITIONS = { "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", + .category = "Game Options (Peripherals)", } }; diff --git a/src/spice2x/launcher/options.h b/src/spice2x/launcher/options.h index bf1d03d..49974c5 100644 --- a/src/spice2x/launcher/options.h +++ b/src/spice2x/launcher/options.h @@ -101,6 +101,7 @@ namespace launcher { PopnMusicForceSDMode, PopnNoSub, PopnSubMonitorOverride, + PopnNativeTouch, LoadHelloPopnMusicModule, LoadGitaDoraModule, GitaDoraTwoChannelAudio, @@ -232,6 +233,7 @@ namespace launcher { spice2x_WindowPosition, spice2x_WindowAlwaysOnTop, WindowForceScaling, + WindowDisableRoundedCorners, spice2x_IIDXWindowedSubscreenSize, spice2x_IIDXWindowedSubscreenPosition, IIDXWindowedSubscreenBorderless, diff --git a/src/spice2x/launcher/shutdown.cpp b/src/spice2x/launcher/shutdown.cpp index 38f5058..b1e68ff 100644 --- a/src/spice2x/launcher/shutdown.cpp +++ b/src/spice2x/launcher/shutdown.cpp @@ -86,13 +86,12 @@ namespace launcher { if (LAUNCHER_ARGC > 0) { // build cmd line - std::stringstream cmd_line; - cmd_line << "START \"\" "; + std::string cmd_line = "START \"\" "; for (int i = 0; i < LAUNCHER_ARGC; i++) - cmd_line << " \"" << LAUNCHER_ARGV[i] << "\""; + cmd_line += " \"" + std::string(LAUNCHER_ARGV[i]) + "\""; // run command - system(cmd_line.str().c_str()); + system(cmd_line.c_str()); } } diff --git a/src/spice2x/overlay/windows/config.cpp b/src/spice2x/overlay/windows/config.cpp index 1ff8bca..1a9683f 100644 --- a/src/spice2x/overlay/windows/config.cpp +++ b/src/spice2x/overlay/windows/config.cpp @@ -17,6 +17,7 @@ #include "external/imgui/misc/cpp/imgui_stdlib.h" #include "games/io.h" #include "games/sdvx/sdvx.h" +#include "games/popn/popn.h" #include "avs/core.h" #include "avs/ea3.h" #include "avs/game.h" @@ -283,18 +284,8 @@ namespace overlay::windows { // keypad buttons ImGui::TextUnformatted(""); - if (this->games_selected_name == "Beatmania IIDX") { - ImGui::Indent(INDENT); - ImGui::TextColored( - ImVec4(1, 0.5f, 0.5f, 1.f), - "WARNING: Lightning Model (TDJ) I/O will ignore the keypad!"); - ImGui::TextWrapped( - "Use Toggle Sub Screen button to show the overlay and use your mouse, " - "connect using SpiceCompanion app, or connect a touch screen to enter " - "the PIN."); - ImGui::Unindent(INDENT); - ImGui::TextUnformatted(""); - } + this->build_keypad_warning(); + auto keypad_buttons = games::get_buttons_keypads(this->games_selected_name); auto keypad_count = eamuse_get_game_keypads_name(); if (keypad_count == 1) { @@ -602,6 +593,34 @@ namespace overlay::windows { } } + void Config::build_keypad_warning() { + // not checking the -iidxtdj option here, we could do that in the future + const bool is_tdj = this->games_selected_name == "Beatmania IIDX"; + + // not using games::popn::is_pikapika_model() here since that always returns false on 32-bit + const bool is_popn = this->games_selected_name == "Pop'n Music" && avs::game::SPEC[0] == 'D'; + if (!is_tdj && !is_popn) { + return; + } + + ImGui::Indent(INDENT); + if (is_tdj) { + ImGui::TextColored( + ImVec4(1, 0.5f, 0.5f, 1.f), + "WARNING: Lightning Model (TDJ) I/O will ignore keypad number input!"); + } else if (is_popn) { + ImGui::TextColored( + ImVec4(1, 0.5f, 0.5f, 1.f), + "WARNING: PikaPika Pop-Kun model will ignore keypad number input!"); + } + ImGui::TextWrapped( + "Use Toggle Sub Screen button (Overlay tab) to show the overlay and use your mouse, " + "connect using SpiceCompanion app, or connect a touch screen to enter " + "the PIN."); + ImGui::Unindent(INDENT); + ImGui::TextUnformatted(""); + } + void Config::build_buttons(const std::string &name, std::vector