From c47de315c87ffe9fe02e38bf3981d409a5f4778d Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Sat, 30 Nov 2024 22:32:51 +0100 Subject: [PATCH 01/26] Volume: added logic for changing sound volume (Windows Cliend and Server) --- README.md | 6 +- client/Cargo.lock | 79 +++++++++++++++++-- client/packages/cli/Cargo.toml | 2 +- client/packages/protocol/Cargo.toml | 2 +- client/packages/vita_reports/src/lib.rs | 4 + .../packages/vita_virtual_device/Cargo.toml | 9 ++- .../vita_virtual_device/src/windows.rs | 63 +++++++++++++++ common/netprotocol.fbs | 2 + server/src/ctrl.cpp | 13 ++- server/src/net.cpp | 1 + 10 files changed, 168 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index c9468e5..88d7cb4 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,8 @@ This allows to support a large number of Windows games without any fixes. | Battery | ✅ | PS Vita's battery status is sent to the emulated DualShock 4 | | Any configuration | ✅ | You can choose from [ready-made configurations](#33-configurations) | | DS4Windows support | ✅ | Virtual Controller Support[*] requires activation | -| Sound | ❌ | Probably will never be realized | +| Changing the sound volume | ✅ | Volume Up = Select + R1, Volume Down = Select + L1 | +| Sound sending | ❌ | Probably will never be realized | [*] - Virtual Controller Support can be found in the [schmaldeo DS4Windows fork](https://github.com/schmaldeo/DS4Windows). This option can be found in `Settings -> Device Options -> Virtual Controller Support`. @@ -166,7 +167,8 @@ The behavior is close to how the DualShock 4 (`vendor: 0x054C`, `product: 0x9CC` | DualShock 4 digitizer button | ✅ | Works as a quick tap on the digitizer. Supports front and rear digitizer. Linux itself determines the behaviour | | Battery | ❌ | - | | Any configuration | ✅ | You can choose from [ready-made configurations](#33-configurations) | -| Sound | ❌ | Probably will never be realized | +| Changing the sound volume | ❌ | - | +| Sound sending | ❌ | Probably will never be realized | You can also use a convenient input signal remapper, such as [antimicrox](https://github.com/AntiMicroX/antimicrox/) or [input-remapper](https://github.com/sezanzeb/input-remapper). diff --git a/client/Cargo.lock b/client/Cargo.lock index 34c3769..a838998 100644 --- a/client/Cargo.lock +++ b/client/Cargo.lock @@ -182,9 +182,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" @@ -651,7 +651,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -1119,18 +1119,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -1442,6 +1442,7 @@ dependencies = [ "thiserror 2.0.3", "vigem-client", "vita_reports", + "windows", ] [[package]] @@ -1536,6 +1537,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -1545,6 +1556,60 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/client/packages/cli/Cargo.toml b/client/packages/cli/Cargo.toml index eab8e2c..41a3675 100644 --- a/client/packages/cli/Cargo.toml +++ b/client/packages/cli/Cargo.toml @@ -14,7 +14,7 @@ flatbuffers_structs = { version = "0.1.0", path = "../flatbuffers_structs" } protocol = { version = "0.1.0", path = "../protocol" } vita_reports = { version = "0.1.0", path = "../vita_reports" } vita_virtual_device = { version = "0.1.0", path = "../vita_virtual_device" } -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } config = "0.14.1" toml = "0.8.19" home = "0.5.9" diff --git a/client/packages/protocol/Cargo.toml b/client/packages/protocol/Cargo.toml index f8d0872..303e02f 100644 --- a/client/packages/protocol/Cargo.toml +++ b/client/packages/protocol/Cargo.toml @@ -8,7 +8,7 @@ flatbuffers_structs = { path = "../flatbuffers_structs" } thiserror = "2.0.3" vita_reports = { path = "../vita_reports" } tokio-util = { version = "0.7.12", optional = true, features = ["codec"] } -bytes = { version = "1.8.0", optional = true } +bytes = { version = "1.9.0", optional = true } [features] codec = ["dep:tokio-util", "dep:bytes"] diff --git a/client/packages/vita_reports/src/lib.rs b/client/packages/vita_reports/src/lib.rs index 1a771f9..5434a2d 100644 --- a/client/packages/vita_reports/src/lib.rs +++ b/client/packages/vita_reports/src/lib.rs @@ -12,6 +12,8 @@ pub struct ButtonsData { pub circle: bool, pub cross: bool, pub square: bool, + pub vol_up: bool, + pub vol_down: bool, // timestamp: u64; } @@ -30,6 +32,8 @@ impl From for ButtonsData { circle: buttons.circle(), cross: buttons.cross(), square: buttons.square(), + vol_up: buttons.vol_up(), + vol_down: buttons.vol_down(), // timestamp: buttons.timestamp(), } } diff --git a/client/packages/vita_virtual_device/Cargo.toml b/client/packages/vita_virtual_device/Cargo.toml index e7ea78b..c5e0119 100644 --- a/client/packages/vita_virtual_device/Cargo.toml +++ b/client/packages/vita_virtual_device/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" cfg-if = "1.0.0" derive_builder = "0.20.2" rstar = { version = "0.12.2", features = ["serde"] } -serde = { version = "1.0.214", features = ["serde_derive"] } +serde = { version = "1.0.215", features = ["serde_derive"] } thiserror = "2.0.3" vita_reports = { version = "0.1.0", path = "../vita_reports" } @@ -18,3 +18,10 @@ input-linux = "0.7.1" [target.'cfg(windows)'.dependencies] vigem-client = { git = "https://github.com/santarl/vigem_client_rust/" } +windows = { version = "0.58", features = [ + "Win32_Foundation", + "Win32_Media_Audio", + "Win32_Media_Audio_Endpoints", + "Win32_System_Com", + "Win32_UI_Input_KeyboardAndMouse", +] } diff --git a/client/packages/vita_virtual_device/src/windows.rs b/client/packages/vita_virtual_device/src/windows.rs index 728a656..0a297c2 100644 --- a/client/packages/vita_virtual_device/src/windows.rs +++ b/client/packages/vita_virtual_device/src/windows.rs @@ -6,12 +6,69 @@ use vigem_client::{ DS4TouchPoint, DS4TouchReport, DpadDirection as VigemDpadDirection, DualShock4Wired, TargetId, }; +use windows::Win32::{ + Media::Audio::Endpoints::IAudioEndpointVolume, + Media::Audio::{eMultimedia, eRender, IMMDevice, IMMDeviceEnumerator, MMDeviceEnumerator}, + System::Com::{CoCreateInstance, CoInitializeEx, CLSCTX_ALL, COINIT_MULTITHREADED}, + UI::Input::KeyboardAndMouse::{ + SendInput, INPUT, INPUT_0, INPUT_KEYBOARD, KEYBDINPUT, KEYBD_EVENT_FLAGS, KEYEVENTF_KEYUP, + VIRTUAL_KEY, VK_VOLUME_DOWN, VK_VOLUME_UP, + }, +}; + use crate::virtual_button::{Button, DpadDirection}; use crate::virtual_config::{Config, ConfigBuilder, TouchConfig, TriggerConfig}; use crate::virtual_touch::{Point, TouchAction}; use crate::virtual_utils::{compute_dpad_direction, get_pressed_buttons}; use crate::{f32_to_i16, VitaVirtualDevice, FRONT_TOUCHPAD_RECT, REAR_TOUCHPAD_RECT}; +unsafe fn simulate_key_press(vk: VIRTUAL_KEY) -> windows::core::Result<()> { + let inputs = &mut [ + INPUT { + r#type: INPUT_KEYBOARD, + Anonymous: INPUT_0 { + ki: KEYBDINPUT { + wVk: vk, + wScan: 0, + dwFlags: KEYBD_EVENT_FLAGS(0), + time: 0, + dwExtraInfo: 0, + }, + }, + }, + INPUT { + r#type: INPUT_KEYBOARD, + Anonymous: INPUT_0 { + ki: KEYBDINPUT { + wVk: vk, + wScan: 0, + dwFlags: KEYEVENTF_KEYUP, + time: 0, + dwExtraInfo: 0, + }, + }, + }, + ]; + + let result = SendInput(inputs, std::mem::size_of::() as i32); + if result == 0 { + Err(windows::core::Error::from_win32()) + } else { + Ok(()) + } +} + +fn change_volume_by_key(delta: f32) -> windows::core::Result<()> { + unsafe { + if delta > 0.0 { + simulate_key_press(VK_VOLUME_UP)?; + } else if delta < 0.0 { + simulate_key_press(VK_VOLUME_DOWN)?; + } + Ok(()) + } +} + #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Failed to connect to the client")] @@ -197,6 +254,12 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { // Get the pressed buttons let pressed_buttons = get_pressed_buttons(&report.buttons, self.config.trigger_config); + if report.buttons.vol_up { + change_volume_by_key(0.02).expect("Failed to increase volume"); + } + if report.buttons.vol_down { + change_volume_by_key(-0.02).expect("Failed to increase volume"); + } // Create DS4Buttons object let mut buttons = DS4Buttons::new().dpad(ds4_dpad); diff --git a/common/netprotocol.fbs b/common/netprotocol.fbs index 317fcc7..7bf33b0 100644 --- a/common/netprotocol.fbs +++ b/common/netprotocol.fbs @@ -34,6 +34,8 @@ struct ButtonsData circle: bool; cross: bool; square: bool; + vol_up: bool; + vol_down: bool; } struct Vector3 diff --git a/server/src/ctrl.cpp b/server/src/ctrl.cpp index 27e6d3c..6b9c530 100644 --- a/server/src/ctrl.cpp +++ b/server/src/ctrl.cpp @@ -13,7 +13,9 @@ NetProtocol::ButtonsData convert_pad_data(const SceCtrlData &data) { (data.buttons & SCE_CTRL_DOWN) > 0, (data.buttons & SCE_CTRL_LEFT) > 0, (data.buttons & SCE_CTRL_LTRIGGER) > 0, (data.buttons & SCE_CTRL_RTRIGGER) > 0, (data.buttons & SCE_CTRL_TRIANGLE) > 0, (data.buttons & SCE_CTRL_CIRCLE) > 0, - (data.buttons & SCE_CTRL_CROSS) > 0, (data.buttons & SCE_CTRL_SQUARE) > 0); + (data.buttons & SCE_CTRL_CROSS) > 0, (data.buttons & SCE_CTRL_SQUARE) > 0, + (data.buttons & SCE_CTRL_VOLUP) > 0, (data.buttons & SCE_CTRL_VOLDOWN) > 0 + ); } flatbuffers::Offset @@ -38,6 +40,15 @@ void get_ctrl_as_netprotocol(flatbuffers::FlatBufferBuilder &builder, SharedData while (pad.timeStamp <= last_ts) { sceCtrlPeekBufferPositive(0, &pad, 1); } + if (pad.buttons & SCE_CTRL_SELECT && pad.buttons & SCE_CTRL_LTRIGGER){ + sceKernelDelayThread(20 * 1000); + pad.buttons |= SCE_CTRL_VOLDOWN; + } + if (pad.buttons & SCE_CTRL_SELECT && pad.buttons & SCE_CTRL_RTRIGGER){ + sceKernelDelayThread(20 * 1000); + pad.buttons |= SCE_CTRL_VOLUP; + } + auto buttons = convert_pad_data(pad); sceTouchPeek(SCE_TOUCH_PORT_FRONT, &touch_data_front, 1); diff --git a/server/src/net.cpp b/server/src/net.cpp index 20faadf..6ade166 100644 --- a/server/src/net.cpp +++ b/server/src/net.cpp @@ -346,6 +346,7 @@ int net_thread(__attribute__((unused)) unsigned int arglen, void *argp) { } timeout = client->remaining_polling_time(); + sceKernelDelayThread(10 * 1000); } sceNetCtlInetUnregisterCallback(cbid); From 1805b14cb82ea6a0b64bba5333ec696a9bddf448 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Mon, 2 Dec 2024 22:40:31 +0100 Subject: [PATCH 02/26] Client: improved work with event sending time --- .../packages/vita_virtual_device/src/linux.rs | 60 ++++++++++--------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/client/packages/vita_virtual_device/src/linux.rs b/client/packages/vita_virtual_device/src/linux.rs index f6a97fe..dbffc6d 100644 --- a/client/packages/vita_virtual_device/src/linux.rs +++ b/client/packages/vita_virtual_device/src/linux.rs @@ -6,6 +6,8 @@ use std::{ os::fd::AsRawFd, }; +use std::time::{SystemTime, UNIX_EPOCH}; + use input_linux::{ sys::{input_event, BUS_VIRTUAL}, AbsoluteAxis, AbsoluteEvent, AbsoluteInfo, AbsoluteInfoSetup, EventKind, EventTime, InputEvent, @@ -41,6 +43,11 @@ const REAR_TOUCHPAD_MAX_X: i32 = REAR_TOUCHPAD_RECT.1 .0 - 1; const REAR_TOUCHPAD_MAX_Y: i32 = REAR_TOUCHPAD_RECT.1 .1 - 1; const REAR_TOUCHPAD_MAX_SLOTS: usize = 4; +fn get_current_event_time() -> EventTime { + let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); + EventTime::new(now.as_secs() as i64, now.subsec_nanos() as i64) +} + fn map_button_to_ds4(button: Button) -> Key { match button { Button::ThumbRight => Key::ButtonThumbr, @@ -426,8 +433,7 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { } fn send_report(&mut self, report: vita_reports::MainReport) -> crate::Result<()> { - const EVENT_TIME_ZERO: EventTime = EventTime::new(0, 0); - let syn_event = *SynchronizeEvent::report(EVENT_TIME_ZERO) + let syn_event = *SynchronizeEvent::report(get_current_event_time()) .as_event() .as_raw(); @@ -474,7 +480,7 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { .iter() .map(|&button| { KeyEvent::new( - EVENT_TIME_ZERO, + get_current_event_time(), map_button_to_ds4(button), KeyState::PRESSED, ) @@ -487,7 +493,7 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { .iter() .map(|&button| { KeyEvent::new( - EVENT_TIME_ZERO, + get_current_event_time(), map_button_to_ds4(button), KeyState::RELEASED, ) @@ -502,12 +508,12 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { let mut dpad_events = Vec::new(); if hat_x_value != self.previous_hat_x { dpad_events - .push(AbsoluteEvent::new(EVENT_TIME_ZERO, AbsoluteAxis::Hat0X, hat_x_value).into()); + .push(AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::Hat0X, hat_x_value).into()); self.previous_hat_x = hat_x_value; } if hat_y_value != self.previous_hat_y { dpad_events - .push(AbsoluteEvent::new(EVENT_TIME_ZERO, AbsoluteAxis::Hat0Y, hat_y_value).into()); + .push(AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::Hat0Y, hat_y_value).into()); self.previous_hat_y = hat_y_value; } @@ -614,21 +620,21 @@ fn create_motion_events(report: &vita_reports::MainReport) -> Vec { let gyro_z_i16 = f32_to_i16(report.motion.gyro.z, -35.0, 35.0); vec![ - AbsoluteEvent::new(EVENT_TIME_ZERO, AbsoluteAxis::X, accel_x_i16 as i32).into(), - AbsoluteEvent::new(EVENT_TIME_ZERO, AbsoluteAxis::Y, accel_z_i16 as i32).into(), - AbsoluteEvent::new(EVENT_TIME_ZERO, AbsoluteAxis::Z, accel_y_i16 as i32).into(), - AbsoluteEvent::new(EVENT_TIME_ZERO, AbsoluteAxis::RX, gyro_x_i16 as i32).into(), - AbsoluteEvent::new(EVENT_TIME_ZERO, AbsoluteAxis::RY, gyro_z_i16 as i32).into(), - AbsoluteEvent::new(EVENT_TIME_ZERO, AbsoluteAxis::RZ, gyro_y_i16 as i32).into(), + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::X, accel_x_i16 as i32).into(), + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::Y, accel_z_i16 as i32).into(), + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::Z, accel_y_i16 as i32).into(), + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::RX, gyro_x_i16 as i32).into(), + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::RY, gyro_z_i16 as i32).into(), + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::RZ, gyro_y_i16 as i32).into(), ] } fn create_stick_events(report: &vita_reports::MainReport) -> Vec { vec![ - AbsoluteEvent::new(EventTime::new(0, 0), AbsoluteAxis::X, report.lx as i32).into(), - AbsoluteEvent::new(EventTime::new(0, 0), AbsoluteAxis::Y, report.ly as i32).into(), - AbsoluteEvent::new(EventTime::new(0, 0), AbsoluteAxis::RX, report.rx as i32).into(), - AbsoluteEvent::new(EventTime::new(0, 0), AbsoluteAxis::RY, report.ry as i32).into(), + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::X, report.lx as i32).into(), + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::Y, report.ly as i32).into(), + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::RX, report.rx as i32).into(), + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::RY, report.ry as i32).into(), ] } @@ -648,11 +654,11 @@ fn create_touch_events( if old_id.is_some() && new_id.is_none() { events.push( - AbsoluteEvent::new(EVENT_TIME_ZERO, AbsoluteAxis::MultitouchSlot, slot as i32) + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::MultitouchSlot, slot as i32) .into(), ); events.push( - AbsoluteEvent::new(EVENT_TIME_ZERO, AbsoluteAxis::MultitouchTrackingId, -1).into(), + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::MultitouchTrackingId, -1).into(), ); previous_touches[slot] = None; } @@ -666,11 +672,11 @@ fn create_touch_events( break; } events.push( - AbsoluteEvent::new(EVENT_TIME_ZERO, AbsoluteAxis::MultitouchSlot, slot as i32).into(), + AbsoluteEvent::new(get_current_event_time(), AbsoluteAxis::MultitouchSlot, slot as i32).into(), ); events.push( AbsoluteEvent::new( - EVENT_TIME_ZERO, + get_current_event_time(), AbsoluteAxis::MultitouchTrackingId, touch.id as i32, ) @@ -678,7 +684,7 @@ fn create_touch_events( ); events.push( AbsoluteEvent::new( - EVENT_TIME_ZERO, + get_current_event_time(), AbsoluteAxis::MultitouchPositionX, touch.x as i32, ) @@ -686,7 +692,7 @@ fn create_touch_events( ); events.push( AbsoluteEvent::new( - EVENT_TIME_ZERO, + get_current_event_time(), AbsoluteAxis::MultitouchPositionY, touch.y as i32, ) @@ -694,7 +700,7 @@ fn create_touch_events( ); events.push( AbsoluteEvent::new( - EVENT_TIME_ZERO, + get_current_event_time(), AbsoluteAxis::MultitouchPressure, touch.force as i32, ) @@ -710,15 +716,15 @@ fn create_touch_events( if any_touch_active && !*touch_state { // Touch started - events.push(KeyEvent::new(EVENT_TIME_ZERO, Key::ButtonTouch, KeyState::PRESSED).into()); + events.push(KeyEvent::new(get_current_event_time(), Key::ButtonTouch, KeyState::PRESSED).into()); events - .push(KeyEvent::new(EVENT_TIME_ZERO, Key::ButtonToolFinger, KeyState::PRESSED).into()); + .push(KeyEvent::new(get_current_event_time(), Key::ButtonToolFinger, KeyState::PRESSED).into()); *touch_state = true; } else if !any_touch_active && *touch_state { // Touch ended - events.push(KeyEvent::new(EVENT_TIME_ZERO, Key::ButtonTouch, KeyState::RELEASED).into()); + events.push(KeyEvent::new(get_current_event_time(), Key::ButtonTouch, KeyState::RELEASED).into()); events - .push(KeyEvent::new(EVENT_TIME_ZERO, Key::ButtonToolFinger, KeyState::RELEASED).into()); + .push(KeyEvent::new(get_current_event_time(), Key::ButtonToolFinger, KeyState::RELEASED).into()); *touch_state = false; } From 85f389fcb0196acb750b63b3c4b160abdec82857 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Mon, 2 Dec 2024 22:44:30 +0100 Subject: [PATCH 03/26] Client: minor fixes in code --- client/packages/vita_virtual_device/src/linux.rs | 9 ++++----- client/packages/vita_virtual_device/src/windows.rs | 11 +++-------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/client/packages/vita_virtual_device/src/linux.rs b/client/packages/vita_virtual_device/src/linux.rs index dbffc6d..c675888 100644 --- a/client/packages/vita_virtual_device/src/linux.rs +++ b/client/packages/vita_virtual_device/src/linux.rs @@ -103,6 +103,7 @@ pub struct VitaDevice { main_handle: UInputHandle, touchpad_handle: UInputHandle, sensor_handle: UInputHandle, + keyboard_handle: UInputHandle, previous_front_touches: Vec>, previous_rear_touches: Vec>, touch_state: bool, @@ -117,6 +118,7 @@ impl VitaDevice { uinput_file: F, uinput_sensor_file: F, uinput_touchpad_file: F, + uinput_keyboard_file: F, config: Config, ) -> std::io::Result { let main_handle = UInputHandle::new(uinput_file); @@ -266,7 +268,7 @@ impl VitaDevice { }, AbsoluteInfoSetup { info: AbsoluteInfo { - minimum: 0, + minimum: -1, maximum: 128, ..Default::default() }, @@ -282,7 +284,7 @@ impl VitaDevice { }, AbsoluteInfoSetup { info: AbsoluteInfo { - minimum: 1, + minimum: 0, maximum: 128, ..Default::default() }, @@ -607,8 +609,6 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { } fn create_motion_events(report: &vita_reports::MainReport) -> Vec { - const EVENT_TIME_ZERO: EventTime = EventTime::new(0, 0); - // Convert the vita accel range [-4.0, 4.0] to the range [-32768, 32768] let accel_x_i16 = f32_to_i16(-report.motion.accelerometer.x, -4.0, 4.0); // inverted let accel_y_i16 = f32_to_i16(report.motion.accelerometer.y, -4.0, 4.0); @@ -645,7 +645,6 @@ fn create_touch_events( touch_state: &mut bool, ) -> Vec { let mut events = Vec::new(); - const EVENT_TIME_ZERO: EventTime = EventTime::new(0, 0); // Reset slots where touches have ended for slot in 0..max_slots { diff --git a/client/packages/vita_virtual_device/src/windows.rs b/client/packages/vita_virtual_device/src/windows.rs index 0a297c2..ad35b6a 100644 --- a/client/packages/vita_virtual_device/src/windows.rs +++ b/client/packages/vita_virtual_device/src/windows.rs @@ -6,14 +6,9 @@ use vigem_client::{ DS4TouchPoint, DS4TouchReport, DpadDirection as VigemDpadDirection, DualShock4Wired, TargetId, }; -use windows::Win32::{ - Media::Audio::Endpoints::IAudioEndpointVolume, - Media::Audio::{eMultimedia, eRender, IMMDevice, IMMDeviceEnumerator, MMDeviceEnumerator}, - System::Com::{CoCreateInstance, CoInitializeEx, CLSCTX_ALL, COINIT_MULTITHREADED}, - UI::Input::KeyboardAndMouse::{ - SendInput, INPUT, INPUT_0, INPUT_KEYBOARD, KEYBDINPUT, KEYBD_EVENT_FLAGS, KEYEVENTF_KEYUP, - VIRTUAL_KEY, VK_VOLUME_DOWN, VK_VOLUME_UP, - }, +use windows::Win32::UI::Input::KeyboardAndMouse::{ + SendInput, INPUT, INPUT_0, INPUT_KEYBOARD, KEYBDINPUT, KEYBD_EVENT_FLAGS, KEYEVENTF_KEYUP, + VIRTUAL_KEY, VK_VOLUME_DOWN, VK_VOLUME_UP, }; use crate::virtual_button::{Button, DpadDirection}; From 18e9c351943bf7e5bd054163296f891ea8f53f41 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Mon, 2 Dec 2024 22:45:30 +0100 Subject: [PATCH 04/26] Client: added logic for changing sound volume (Linux Client) --- .../packages/vita_virtual_device/src/linux.rs | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/client/packages/vita_virtual_device/src/linux.rs b/client/packages/vita_virtual_device/src/linux.rs index c675888..49e1982 100644 --- a/client/packages/vita_virtual_device/src/linux.rs +++ b/client/packages/vita_virtual_device/src/linux.rs @@ -337,18 +337,26 @@ impl VitaDevice { sensor_handle.create(&id, b"PS Vita VitaOxiPad (Motion Sensors)", 0, &sensor_axes)?; + let keyboard_handle = UInputHandle::new(uinput_keyboard_file); + keyboard_handle.set_evbit(EventKind::Key)?; + keyboard_handle.set_keybit(Key::VolumeUp)?; + keyboard_handle.set_keybit(Key::VolumeDown)?; + keyboard_handle.create(&id, b"PS Vita VitaOxiPad (Virtual Keyboard)", 0, &[])?; + let ids = main_handle .evdev_name() .ok() .zip(touchpad_handle.evdev_name().ok()) .zip(sensor_handle.evdev_name().ok()) - .map(|((main, touchpad), sensor)| [main, touchpad, sensor].to_vec()); + .zip(keyboard_handle.evdev_name().ok()) + .map(|(((main, touchpad), sensor), keyboard)| [main, touchpad, sensor, keyboard].to_vec()); Ok(VitaDevice { config, main_handle, touchpad_handle, sensor_handle, + keyboard_handle, previous_front_touches: vec![None; FRONT_TOUCHPAD_MAX_SLOTS], previous_rear_touches: vec![None; REAR_TOUCHPAD_MAX_SLOTS], touch_state: false, @@ -393,10 +401,17 @@ impl VitaDevice { .open("/dev/uinput") .map_err(Error::DeviceCreationFailed)?; + let uinput_keyboard_file = OpenOptions::new() + .read(true) + .write(true) + .open("/dev/uinput") + .map_err(Error::DeviceCreationFailed)?; + let device = Self::new( uinput_file, uinput_sensor_file, uinput_touchpad_file, + uinput_keyboard_file, config, ) .map_err(Error::DeviceCreationFailed)?; @@ -519,6 +534,16 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { self.previous_hat_y = hat_y_value; } + let mut volume_events: Vec = Vec::new(); + if report.buttons.vol_up { + volume_events.push(KeyEvent::new(get_current_event_time(), Key::VolumeUp, KeyState::PRESSED).into()); + volume_events.push(KeyEvent::new(get_current_event_time(), Key::VolumeUp, KeyState::RELEASED).into()); + } + if report.buttons.vol_down { + volume_events.push(KeyEvent::new(get_current_event_time(), Key::VolumeDown, KeyState::PRESSED).into()); + volume_events.push(KeyEvent::new(get_current_event_time(), Key::VolumeDown, KeyState::RELEASED).into()); + } + // Create stick events (always send) let stick_events = create_stick_events(&report); @@ -528,6 +553,7 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { .chain(button_release_events.iter()) .chain(dpad_events.iter()) .chain(stick_events.iter()) + .chain(volume_events.iter()) .map(|ev| (*ev).into()) .map(|ev: InputEvent| *ev.as_raw()) .collect(); @@ -539,6 +565,13 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { .write(&[syn_event]) .map_err(Error::WriteEventFailed)?; + self.keyboard_handle + .write(&events) + .map_err(Error::WriteEventFailed)?; + self.keyboard_handle + .write(&[syn_event]) + .map_err(Error::WriteEventFailed)?; + match self.config.touchpad_source { Some(TouchpadSource::Front) => { // Handle front touch events From 9c00274f6b3183b03459e9e31cff8c22e9f9d6d9 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Mon, 2 Dec 2024 21:48:34 +0100 Subject: [PATCH 05/26] Readme: update Linux support table --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 88d7cb4..2435905 100644 --- a/README.md +++ b/README.md @@ -151,11 +151,12 @@ This option can be found in `Settings -> Device Options -> Virtual Controller Su ### 4.2 Linux Client -The behavior is close to how the DualShock 4 (`vendor: 0x054C`, `product: 0x9CC`) is defined in Linux. Three `uinput` devices are emulated: +The behavior is close to how the DualShock 4 (`vendor: 0x054C`, `product: 0x9CC`) is defined in Linux. Four `uinput` devices are emulated: - Main `uinput` device (Dpad, Sticks, buttons, triggers) - Touchpad `uinput` device; -- Motion Sensors `uinput` device for accelerometer and gyroscope. +- Motion Sensors `uinput` device for accelerometer and gyroscope; +- Keyboard `uinput` device. | Feature | Support | Details | | ------------------------------- | :-----: | ----------------------------------------------------------------------------------------------------------------- | @@ -167,7 +168,7 @@ The behavior is close to how the DualShock 4 (`vendor: 0x054C`, `product: 0x9CC` | DualShock 4 digitizer button | ✅ | Works as a quick tap on the digitizer. Supports front and rear digitizer. Linux itself determines the behaviour | | Battery | ❌ | - | | Any configuration | ✅ | You can choose from [ready-made configurations](#33-configurations) | -| Changing the sound volume | ❌ | - | +| Changing the sound volume | ✅ | Volume Up = Select + R1, Volume Down = Select + L1 | | Sound sending | ❌ | Probably will never be realized | You can also use a convenient input signal remapper, such as [antimicrox](https://github.com/AntiMicroX/antimicrox/) From 524d447168d5eec88c750f4c72b11d2a4f16838e Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Mon, 2 Dec 2024 21:52:16 +0100 Subject: [PATCH 06/26] Server: increased sending delays when adjusting the volume --- server/src/ctrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/ctrl.cpp b/server/src/ctrl.cpp index 6b9c530..a105fb8 100644 --- a/server/src/ctrl.cpp +++ b/server/src/ctrl.cpp @@ -41,11 +41,11 @@ void get_ctrl_as_netprotocol(flatbuffers::FlatBufferBuilder &builder, SharedData sceCtrlPeekBufferPositive(0, &pad, 1); } if (pad.buttons & SCE_CTRL_SELECT && pad.buttons & SCE_CTRL_LTRIGGER){ - sceKernelDelayThread(20 * 1000); + sceKernelDelayThread(50 * 1000); pad.buttons |= SCE_CTRL_VOLDOWN; } if (pad.buttons & SCE_CTRL_SELECT && pad.buttons & SCE_CTRL_RTRIGGER){ - sceKernelDelayThread(20 * 1000); + sceKernelDelayThread(50 * 1000); pad.buttons |= SCE_CTRL_VOLUP; } From 734db759b6fe91df9169981e888288dcff2d2051 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Mon, 2 Dec 2024 21:55:52 +0100 Subject: [PATCH 07/26] Version: v1.1.1 -> 1.2.0 --- client/Cargo.lock | 2 +- client/packages/cli/Cargo.toml | 2 +- server/CMakeLists.txt | 2 +- server/src/main.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/Cargo.lock b/client/Cargo.lock index a838998..4930531 100644 --- a/client/Cargo.lock +++ b/client/Cargo.lock @@ -223,7 +223,7 @@ dependencies = [ [[package]] name = "cli" -version = "1.1.1" +version = "1.2.0" dependencies = [ "argh", "build-data", diff --git a/client/packages/cli/Cargo.toml b/client/packages/cli/Cargo.toml index 41a3675..ddb5274 100644 --- a/client/packages/cli/Cargo.toml +++ b/client/packages/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cli" -version = "1.1.1" +version = "1.2.0" edition = "2021" [dependencies] diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 1b40976..096fb6b 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -13,7 +13,7 @@ project(VitaOxiPad) include("${VITASDK}/share/vita.cmake" REQUIRED) set(VITA_APP_NAME "VitaOxiPad") set(VITA_TITLEID "VOXIPAD01") -set(VITA_VERSION "01.11") +set(VITA_VERSION "01.20") # Vita's IP to send over FTP if(DEFINED ENV{VITA_IP}) diff --git a/server/src/main.cpp b/server/src/main.cpp index d64e23f..d6b2262 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -118,7 +118,7 @@ int main() { vita2d_start_drawing(); vita2d_clear_screen(); vita2d_pgf_draw_text(debug_font, 2, 20, common_color, 1.0, - "VitaOxiPad v1.1.1 \nbuild " __DATE__ ", " __TIME__); + "VitaOxiPad v1.2.0 \nbuild " __DATE__ ", " __TIME__); if (events & MainEvent::NET_CONNECT) { connected_to_network = true; From 9ed38852edfb2ea863648dc3db3bc916fe6c884f Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Thu, 5 Dec 2024 10:56:00 +0100 Subject: [PATCH 08/26] Server: first implementation of the kernel module --- server/CMakeLists.txt | 33 +++++++++++++++-- server/module/CMakeLists.txt | 55 ++++++++++++++++++++++++++++ server/module/include/kctrl-kernel.h | 17 +++++++++ server/module/kctrl.yml | 13 +++++++ server/module/src/main.c | 44 ++++++++++++++++++++++ server/src/ctrl.cpp | 47 ++++++++++++++++++++++-- server/src/main.cpp | 37 +++++++++++++++++++ server/src/net.cpp | 2 +- 8 files changed, 239 insertions(+), 9 deletions(-) create mode 100644 server/module/CMakeLists.txt create mode 100644 server/module/include/kctrl-kernel.h create mode 100644 server/module/kctrl.yml create mode 100644 server/module/src/main.c diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 096fb6b..3cbba4a 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 3.15) +# Set up the Vita SDK toolchain if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) if(DEFINED ENV{VITASDK}) set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") @@ -8,7 +9,7 @@ if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) endif() endif() - +# Application metadata project(VitaOxiPad) include("${VITASDK}/share/vita.cmake" REQUIRED) set(VITA_APP_NAME "VitaOxiPad") @@ -20,19 +21,31 @@ if(DEFINED ENV{VITA_IP}) set(VITA_IP $ENV{VITA_IP}) endif() +# Compiler options set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") set(VITA_MKSFOEX_FLAGS "${VITA_MKSFOEX_FLAGS} -d PARENTAL_LEVEL=1") +# Build FlatBuffers set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/../cmake/") include(BuildFlatBuffers) +add_subdirectory(module) + link_directories( ${CMAKE_CURRENT_BINARY_DIR} ) + +# Include directories include_directories( + module/include + ${CMAKE_CURRENT_BINARY_DIR}/module ../include + ${CMAKE_BINARY_DIR}/generated ) + +link_directories(${CMAKE_CURRENT_BINARY_DIR}/module) + file(GLOB SRC_FLATBUFFERS ../common/*.fbs ) @@ -47,6 +60,7 @@ build_flatbuffers("${SRC_FLATBUFFERS}" include_directories(${CMAKE_BINARY_DIR}/generated) +# App Source files add_executable(${VITA_APP_NAME} src/status.cpp src/ctrl.cpp @@ -57,11 +71,16 @@ add_executable(${VITA_APP_NAME} add_compile_definitions(FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE) target_compile_options(${VITA_APP_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror) +# Dependencies add_dependencies(${VITA_APP_NAME} flatbuffers_target) +add_dependencies(${VITA_APP_NAME} kctrl_all) +# Libraries target_link_libraries(${VITA_APP_NAME} stdc++ vita2d + kctrl_stub_weak + taihen_stub SceCtrl_stub SceTouch_stub SceDisplay_stub @@ -71,9 +90,13 @@ target_link_libraries(${VITA_APP_NAME} ScePower_stub SceCommonDialog_stub SceGxm_stub + SceVshBridge_stub + SceShellSvc_stub SceLibDbg_stub ) -vita_create_self(${VITA_APP_NAME}.self ${VITA_APP_NAME}) + +# Create the application self and VPK +vita_create_self(${VITA_APP_NAME}.self ${VITA_APP_NAME} UNSAFE) vita_create_vpk(${VITA_APP_NAME}.vpk ${VITA_TITLEID} ${VITA_APP_NAME}.self VERSION ${VITA_VERSION} NAME ${VITA_APP_NAME} @@ -81,16 +104,17 @@ vita_create_vpk(${VITA_APP_NAME}.vpk ${VITA_TITLEID} ${VITA_APP_NAME}.self FILE sce_sys/livearea/contents/bg.png sce_sys/livearea/contents/bg.png FILE sce_sys/livearea/contents/startup.png sce_sys/livearea/contents/startup.png FILE sce_sys/livearea/contents/template.xml sce_sys/livearea/contents/template.xml + FILE ${CMAKE_CURRENT_BINARY_DIR}/module/kctrl.skprx module/kctrl.skprx ) -# Send the VPK directly to the PS Vita - +# Optional: Send the VPK directly to the PS Vita if (VITA_IP) add_custom_target(send COMMAND "echo" destroy | nc ${VITA_IP} 1338 COMMAND "sleep" 1s COMMAND unzip -o ${VITA_APP_NAME}.vpk eboot.bin -d ${CMAKE_BINARY_DIR} COMMAND "curl" --ftp-method nocwd -T ${CMAKE_BINARY_DIR}/eboot.bin "ftp://${VITA_IP}:1337/ux0:/app/${VITA_TITLEID}/" + COMMAND "curl" --ftp-method nocwd -T ${CMAKE_BINARY_DIR}/module/kctrl.skprx "ftp://${VITA_IP}:1337/ux0:/app/${VITA_TITLEID}/module/" COMMAND "echo" launch ${VITA_TITLEID} | nc ${VITA_IP} 1338 DEPENDS ${VITA_APP_NAME}.vpk ) @@ -100,6 +124,7 @@ if(DEFINED ENV{VITA_IP}) set(PARSECOREPATH $ENV{PARSECOREPATH}) endif() +# Optional: Dump debugging information add_custom_target(dump COMMAND ${CMAKE_SOURCE_DIR}/get_dump.sh ${VITA_IP} COMMAND python3 ${PARSECOREPATH} coredump ${CMAKE_PROJECT_NAME} diff --git a/server/module/CMakeLists.txt b/server/module/CMakeLists.txt new file mode 100644 index 0000000..a556bde --- /dev/null +++ b/server/module/CMakeLists.txt @@ -0,0 +1,55 @@ +cmake_minimum_required(VERSION 3.15) + +# Set up the Vita SDK toolchain +if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) + if(DEFINED ENV{VITASDK}) + set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "Toolchain file") + else() + message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") + endif() +endif() + +project(kctrl) +include("${VITASDK}/share/vita.cmake" REQUIRED) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions") + +# Add the module's source files +add_executable(${PROJECT_NAME} + src/main.c +) + +# Link against necessary kernel stubs +target_link_libraries(${PROJECT_NAME} + SceDebugForDriver_stub + SceCtrlForDriver_stub + SceSysmemForDriver_stub +) + +# Include the module's include directory +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) + +# Set linker flags +set_target_properties(${PROJECT_NAME} + PROPERTIES LINK_FLAGS "-nostdlib" +) + +# Create the kernel module (skprx) +vita_create_self(${PROJECT_NAME}.skprx ${PROJECT_NAME} + CONFIG kctrl.yml + UNSAFE +) + +# Generate stubs for the module +vita_create_stubs(stubs ${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/kctrl.yml KERNEL) +# vita_create_stubs(stubs ${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/kctrl.yml USER) + + +# Ensure that building the module also builds the stubs +add_custom_target(kctrl_all + ALL + DEPENDS ${PROJECT_NAME}.skprx-self + DEPENDS lib${PROJECT_NAME}_stub.a + DEPENDS lib${PROJECT_NAME}_stub_weak.a +) diff --git a/server/module/include/kctrl-kernel.h b/server/module/include/kctrl-kernel.h new file mode 100644 index 0000000..4f58637 --- /dev/null +++ b/server/module/include/kctrl-kernel.h @@ -0,0 +1,17 @@ +#ifndef _KCTRL_KERNEL_H_ +#define _KCTRL_KERNEL_H_ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + int kctrlGetCtrlData(int port, SceCtrlData* pad_data, int count); + +#ifdef __cplusplus +} +#endif + +#endif // __KCTRL_KERNEL_H_ diff --git a/server/module/kctrl.yml b/server/module/kctrl.yml new file mode 100644 index 0000000..c945786 --- /dev/null +++ b/server/module/kctrl.yml @@ -0,0 +1,13 @@ +kctrl: + attributes: 0 + version: + major: 1 + minor: 0 + main: + start: module_start + stop: module_stop + libraries: + kctrlForKernel: + syscall: true + functions: + - kctrlGetCtrlData diff --git a/server/module/src/main.c b/server/module/src/main.c new file mode 100644 index 0000000..cd5a7b2 --- /dev/null +++ b/server/module/src/main.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "kctrl-kernel.h" + +int kctrlGetCtrlData(int port, SceCtrlData *pad_data, int count) { + SceCtrlData pad; + + uint32_t state; + ENTER_SYSCALL(state); + + int res = ksceCtrlReadBufferPositive(port, &pad, count); + ksceKernelMemcpyKernelToUser((uintptr_t)pad_data, &pad, sizeof(SceCtrlData)); + + EXIT_SYSCALL(state); + return res; +} + +void _start() __attribute__((weak, alias("module_start"))); +int module_start(SceSize args, const void *argp) { return SCE_KERNEL_START_SUCCESS; } + +void _stop() __attribute__((weak, alias("module_stop"))); +int module_stop(SceSize args, const void *argp) { return SCE_KERNEL_STOP_SUCCESS; } diff --git a/server/src/ctrl.cpp b/server/src/ctrl.cpp index a105fb8..cfe54e8 100644 --- a/server/src/ctrl.cpp +++ b/server/src/ctrl.cpp @@ -1,10 +1,12 @@ #include #include +#include #include #include #include "ctrl.hpp" +#include "kctrl-kernel.h" NetProtocol::ButtonsData convert_pad_data(const SceCtrlData &data) { return NetProtocol::ButtonsData( @@ -14,8 +16,7 @@ NetProtocol::ButtonsData convert_pad_data(const SceCtrlData &data) { (data.buttons & SCE_CTRL_LTRIGGER) > 0, (data.buttons & SCE_CTRL_RTRIGGER) > 0, (data.buttons & SCE_CTRL_TRIANGLE) > 0, (data.buttons & SCE_CTRL_CIRCLE) > 0, (data.buttons & SCE_CTRL_CROSS) > 0, (data.buttons & SCE_CTRL_SQUARE) > 0, - (data.buttons & SCE_CTRL_VOLUP) > 0, (data.buttons & SCE_CTRL_VOLDOWN) > 0 - ); + (data.buttons & SCE_CTRL_VOLUP) > 0, (data.buttons & SCE_CTRL_VOLDOWN) > 0); } flatbuffers::Offset @@ -36,10 +37,48 @@ void get_ctrl_as_netprotocol(flatbuffers::FlatBufferBuilder &builder, SharedData SceMotionState motion_data; SceTouchData touch_data_front, touch_data_back; - sceCtrlPeekBufferPositive(0, &pad, 1); + int res = kctrlGetCtrlData(0, &pad, 1); + if (res < 0) { + // Handle error + SCE_DBG_LOG_ERROR("kctrlGetCtrlData failed: 0x%08X", res); + return; + } while (pad.timeStamp <= last_ts) { - sceCtrlPeekBufferPositive(0, &pad, 1); + kctrlGetCtrlData(0, &pad, 1); } + + // if (pad.buttons & SCE_CTRL_UP) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_UP"); + // if (pad.buttons & SCE_CTRL_DOWN) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_DOWN"); + // if (pad.buttons & SCE_CTRL_LEFT) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_LEFT"); + // if (pad.buttons & SCE_CTRL_RIGHT) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_RIGHT"); + // if (pad.buttons & SCE_CTRL_LTRIGGER) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_LTRIGGER"); + // if (pad.buttons & SCE_CTRL_RTRIGGER) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_RTRIGGER"); + // if (pad.buttons & SCE_CTRL_TRIANGLE) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_TRIANGLE"); + // if (pad.buttons & SCE_CTRL_CIRCLE) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_CIRCLE"); + // if (pad.buttons & SCE_CTRL_CROSS) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_CROSS"); + // if (pad.buttons & SCE_CTRL_SQUARE) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_SQUARE"); + // if (pad.buttons & SCE_CTRL_START) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_START"); + // if (pad.buttons & SCE_CTRL_SELECT) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_SELECT"); + // if (pad.buttons & SCE_CTRL_PSBUTTON) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_PSBUTTON"); + // if (pad.buttons & SCE_CTRL_VOLUP) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_VOLUP"); + // if (pad.buttons & SCE_CTRL_VOLDOWN) + // SCE_DBG_LOG_DEBUG("SCE_CTRL_VOLDOWN"); + + if (pad.buttons & SCE_CTRL_SELECT && pad.buttons & SCE_CTRL_LTRIGGER){ sceKernelDelayThread(50 * 1000); pad.buttons |= SCE_CTRL_VOLDOWN; diff --git a/server/src/main.cpp b/server/src/main.cpp index d6b2262..bc13559 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -1,11 +1,16 @@ #include +#include #include +#include #include #include #include #include +#include #include #include +#include +#include #include #include "ctrl.hpp" @@ -13,8 +18,12 @@ #include "net.hpp" #include "status.hpp" +#include "kctrl-kernel.h" + #include +#define MOD_PATH "ux0:app/VOXIPAD01/module/kctrl.skprx" + constexpr size_t NET_INIT_SIZE = 1 * 1024 * 1024; vita2d_pgf *debug_font; @@ -36,6 +45,34 @@ int stop_thread(SceUID thread_uid, SceUInt timeout) { } int main() { + SceUID mod_id; + int search_param[2]; + SceUID res = _vshKernelSearchModuleByName("kctrl", search_param); + if (res <= 0) { + tai_module_args_t argg; + memset(&argg, 0, sizeof(argg)); + argg.size = sizeof(argg); + argg.pid = KERNEL_PID; + mod_id = taiLoadStartKernelModuleForUser(MOD_PATH, &argg); + SCE_DBG_LOG_DEBUG("kctrl.skprx loading status: 0x%08X", mod_id); + sceKernelDelayThread(1000000); + sceAppMgrLoadExec("app0:eboot.bin", NULL, NULL); + } + + // sceShellUtilInitEvents(0); + // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_PS_BTN); + // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_QUICK_MENU); + // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_POWEROFF_MENU); + // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_UNK8); + // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_USB_CONNECTION); + // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_MC_INSERTED); + // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_MC_REMOVED); + // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_UNK80); + // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_UNK100); + // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_UNK200); + // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_MUSIC_PLAYER); + // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_PS_BTN_2); + // Enabling analog, motion and touch support sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG_WIDE); sceMotionStartSampling(); diff --git a/server/src/net.cpp b/server/src/net.cpp index 6ade166..dfaeede 100644 --- a/server/src/net.cpp +++ b/server/src/net.cpp @@ -346,7 +346,7 @@ int net_thread(__attribute__((unused)) unsigned int arglen, void *argp) { } timeout = client->remaining_polling_time(); - sceKernelDelayThread(10 * 1000); + sceKernelDelayThread(5 * 1000); } sceNetCtlInetUnregisterCallback(cbid); From b65e1df6e12336e77b60fdcb1c07a69011da4e97 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Thu, 5 Dec 2024 22:29:25 +0100 Subject: [PATCH 09/26] Server: header files moved to include --- server/CMakeLists.txt | 7 ++++--- server/{src => include}/client.hpp | 0 server/{src => include}/ctrl.hpp | 0 server/{src => include}/events.hpp | 0 server/{src => include}/heartbeat.hpp | 0 server/{src => include}/net.hpp | 0 server/{src => include}/status.hpp | 0 server/module/src/main.c | 2 +- server/src/ctrl.cpp | 2 +- 9 files changed, 6 insertions(+), 5 deletions(-) rename server/{src => include}/client.hpp (100%) rename server/{src => include}/ctrl.hpp (100%) rename server/{src => include}/events.hpp (100%) rename server/{src => include}/heartbeat.hpp (100%) rename server/{src => include}/net.hpp (100%) rename server/{src => include}/status.hpp (100%) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 3cbba4a..77b4f6a 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -38,9 +38,10 @@ link_directories( # Include directories include_directories( + ./include + ../include module/include ${CMAKE_CURRENT_BINARY_DIR}/module - ../include ${CMAKE_BINARY_DIR}/generated ) @@ -62,10 +63,10 @@ include_directories(${CMAKE_BINARY_DIR}/generated) # App Source files add_executable(${VITA_APP_NAME} - src/status.cpp - src/ctrl.cpp src/main.cpp src/net.cpp + src/status.cpp + src/ctrl.cpp ) add_compile_definitions(FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE) diff --git a/server/src/client.hpp b/server/include/client.hpp similarity index 100% rename from server/src/client.hpp rename to server/include/client.hpp diff --git a/server/src/ctrl.hpp b/server/include/ctrl.hpp similarity index 100% rename from server/src/ctrl.hpp rename to server/include/ctrl.hpp diff --git a/server/src/events.hpp b/server/include/events.hpp similarity index 100% rename from server/src/events.hpp rename to server/include/events.hpp diff --git a/server/src/heartbeat.hpp b/server/include/heartbeat.hpp similarity index 100% rename from server/src/heartbeat.hpp rename to server/include/heartbeat.hpp diff --git a/server/src/net.hpp b/server/include/net.hpp similarity index 100% rename from server/src/net.hpp rename to server/include/net.hpp diff --git a/server/src/status.hpp b/server/include/status.hpp similarity index 100% rename from server/src/status.hpp rename to server/include/status.hpp diff --git a/server/module/src/main.c b/server/module/src/main.c index cd5a7b2..e070f6a 100644 --- a/server/module/src/main.c +++ b/server/module/src/main.c @@ -31,7 +31,7 @@ int kctrlGetCtrlData(int port, SceCtrlData *pad_data, int count) { ENTER_SYSCALL(state); int res = ksceCtrlReadBufferPositive(port, &pad, count); - ksceKernelMemcpyKernelToUser((uintptr_t)pad_data, &pad, sizeof(SceCtrlData)); + ksceKernelMemcpyKernelToUser(pad_data, &pad, sizeof(SceCtrlData)); EXIT_SYSCALL(state); return res; diff --git a/server/src/ctrl.cpp b/server/src/ctrl.cpp index cfe54e8..d7503c5 100644 --- a/server/src/ctrl.cpp +++ b/server/src/ctrl.cpp @@ -5,7 +5,7 @@ #include #include -#include "ctrl.hpp" +#include #include "kctrl-kernel.h" NetProtocol::ButtonsData convert_pad_data(const SceCtrlData &data) { From 8c244e14b0ea0d762348b7ab7215d3e4ac087a7b Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Fri, 6 Dec 2024 11:10:12 +0100 Subject: [PATCH 10/26] Server: refactore code in main.cpp --- server/CMakeLists.txt | 2 + server/include/draw_helper.hpp | 17 +++++++ server/include/thread_helper.hpp | 23 +++++++++ server/src/draw_helper.cpp | 61 ++++++++++++++++++++++ server/src/main.cpp | 86 ++++++-------------------------- server/src/thread_helper.cpp | 39 +++++++++++++++ 6 files changed, 156 insertions(+), 72 deletions(-) create mode 100644 server/include/draw_helper.hpp create mode 100644 server/include/thread_helper.hpp create mode 100644 server/src/draw_helper.cpp create mode 100644 server/src/thread_helper.cpp diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 77b4f6a..8d30d87 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -67,6 +67,8 @@ add_executable(${VITA_APP_NAME} src/net.cpp src/status.cpp src/ctrl.cpp + src/thread_helper.cpp + src/draw_helper.cpp ) add_compile_definitions(FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE) diff --git a/server/include/draw_helper.hpp b/server/include/draw_helper.hpp new file mode 100644 index 0000000..2814aca --- /dev/null +++ b/server/include/draw_helper.hpp @@ -0,0 +1,17 @@ +#include + +#include "events.hpp" + +#ifndef DRAW_HELPER_HPP +#define DRAW_HELPER_HPP + +extern vita2d_pgf *debug_font; +extern uint32_t need_color; +extern uint32_t common_color; +extern uint32_t error_color; +extern uint32_t done_color; + +void draw_pad_mode(uint32_t *events, bool *connected_to_network, bool *pc_connect_state, + char *vita_ip, SceNetCtlInfo *info, SharedData *shared_data); + +#endif // DRAW_HELPER_HPP diff --git a/server/include/thread_helper.hpp b/server/include/thread_helper.hpp new file mode 100644 index 0000000..bed576b --- /dev/null +++ b/server/include/thread_helper.hpp @@ -0,0 +1,23 @@ +#include +// #include +// #include + +#ifndef THREAD_HELPER_HPP +#define THREAD_HELPER_HPP + +struct ThreadParams { + const char *name; + SceKernelThreadEntry entry; + int initPriority; + SceSize stackSize; + SceUInt attr; + int cpuAffinityMask; + const SceKernelThreadOptParam *option; + void *threadArgs; + SceSize threadArgSize; +}; + +SceUID create_and_start_thread(const ThreadParams ¶ms); +int stop_thread(SceUID thread_uid, SceUInt timeout); + +#endif // THREAD_HELPER_HPP diff --git a/server/src/draw_helper.cpp b/server/src/draw_helper.cpp new file mode 100644 index 0000000..f8f9c8a --- /dev/null +++ b/server/src/draw_helper.cpp @@ -0,0 +1,61 @@ +#include "draw_helper.hpp" +#include "status.hpp" + +#include + +vita2d_pgf *debug_font; +uint32_t need_color = 0; +uint32_t common_color = RGBA8(0xFF, 0xFF, 0xFF, 0xFF); // White color +uint32_t error_color = RGBA8(0xFF, 0x00, 0x00, 0xFF); // Bright red color +uint32_t done_color = RGBA8(0x00, 0xFF, 0x00, 0xFF); // Bright green color + +void draw_pad_mode(uint32_t *events, bool *connected_to_network, bool *pc_connect_state, char *vita_ip, + SceNetCtlInfo *info, SharedData *shared_data) { + vita2d_pgf_draw_text(debug_font, 2, 20, common_color, 1.0, + "VitaOxiPad v1.2.0 \nbuild " __DATE__ ", " __TIME__); + + if (*events & MainEvent::NET_CONNECT) { + *connected_to_network = true; + sceNetCtlInetGetInfo(SCE_NETCTL_INFO_GET_IP_ADDRESS, info); + snprintf(vita_ip, INET_ADDRSTRLEN, "%s", info->ip_address); + } else if (*events & MainEvent::NET_DISCONNECT) { + *connected_to_network = false; + } + + if (*connected_to_network) { + vita2d_pgf_draw_textf(debug_font, 750, 20, common_color, 1.0, "Listening on:\nIP: %s\nPort: %d", + vita_ip, NET_PORT); + } else { + vita2d_pgf_draw_text(debug_font, 750, 20, error_color, 1.0, "Not connected\nto a network :("); + } + + if (*events & MainEvent::PC_CONNECT) { + *pc_connect_state = true; + } else if (*events & MainEvent::PC_DISCONNECT) { + *pc_connect_state = false; + } + if (*pc_connect_state) { + vita2d_pgf_draw_textf(debug_font, 2, 540, done_color, 1.0, "Status: Connected (%s)", + shared_data->client_ip); + } else { + vita2d_pgf_draw_text(debug_font, 2, 540, error_color, 1.0, "Status: Not connected :("); + } + + if (shared_data->charger_connected) { + need_color = done_color; + } else if (shared_data->battery_level < 30) { + need_color = error_color; + } else { + need_color = common_color; + } + vita2d_pgf_draw_textf(debug_font, 785, 520, need_color, 1.0, "Battery: %s%d%%", + shared_data->charger_connected ? "+" : "", shared_data->battery_level); + + if (shared_data->wifi_signal_strength < 50) { + need_color = error_color; + } else { + need_color = common_color; + } + vita2d_pgf_draw_textf(debug_font, 785, 540, need_color, 1.0, "WiFi signal: %d%%", + shared_data->wifi_signal_strength); +} diff --git a/server/src/main.cpp b/server/src/main.cpp index bc13559..5e5f6d1 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -14,9 +14,11 @@ #include #include "ctrl.hpp" +#include "draw_helper.hpp" #include "events.hpp" #include "net.hpp" #include "status.hpp" +#include "thread_helper.hpp" #include "kctrl-kernel.h" @@ -26,24 +28,9 @@ constexpr size_t NET_INIT_SIZE = 1 * 1024 * 1024; -vita2d_pgf *debug_font; - std::atomic g_net_thread_running(true); std::atomic g_status_thread_running(true); -int stop_thread(SceUID thread_uid, SceUInt timeout) { - int wait_result = sceKernelWaitThreadEnd(thread_uid, NULL, &timeout); - if (wait_result < 0) { - SCE_DBG_LOG_ERROR("Error waiting for thread to end: 0x%08X", wait_result); - } - int delete_result = sceKernelDeleteThread(thread_uid); - if (delete_result < 0) { - SCE_DBG_LOG_ERROR("Error deleting thread: 0x%08X", delete_result); - } - SCE_DBG_LOG_TRACE("Thread stopped and deleted successfully"); - return delete_result; -} - int main() { SceUID mod_id; int search_param[2]; @@ -96,10 +83,6 @@ int main() { vita2d_init(); vita2d_set_clear_color(RGBA8(0x00, 0x00, 0x00, 0xFF)); debug_font = vita2d_load_default_pgf(); - uint32_t need_color = 0; - uint32_t common_color = RGBA8(0xFF, 0xFF, 0xFF, 0xFF); // White color - uint32_t error_color = RGBA8(0xFF, 0x00, 0x00, 0xFF); // Bright red color - uint32_t done_color = RGBA8(0x00, 0xFF, 0x00, 0xFF); // Bright green color // Initializing network stuffs sceSysmoduleLoadModule(SCE_SYSMODULE_NET); @@ -126,18 +109,22 @@ int main() { ThreadMessage message = {ev_flag, &shared_data}; // Creating events and status thread - SceUID status_thread_uid = sceKernelCreateThread("StatusThread", &status_thread, 0x10000100, - 0x10000, 0, SCE_KERNEL_CPU_MASK_USER_1, NULL); - sceKernelStartThread(status_thread_uid, sizeof(ThreadMessage), &message); + ThreadParams status_thread_params{ + "StatusThread", &status_thread, 0x10000100, 0x10000, 0, SCE_KERNEL_CPU_MASK_USER_1, + nullptr, &message, sizeof(ThreadMessage)}; + SceUID status_thread_uid = create_and_start_thread(status_thread_params); + if (status_thread_uid < 0) { + return -1; + } // Creating events and network thread - SceUID net_thread_uid = sceKernelCreateThread("NetThread", &net_thread, 0x10000100, 0x10000, 0, - SCE_KERNEL_CPU_MASK_USER_2, nullptr); + ThreadParams net_thread_params{"NetThread", &net_thread, 0x10000100, + 0x10000, 0, SCE_KERNEL_CPU_MASK_USER_2, + nullptr, &message, sizeof(ThreadMessage)}; + SceUID net_thread_uid = create_and_start_thread(net_thread_params); if (net_thread_uid < 0) { - SCE_DBG_LOG_ERROR("Error creating thread: 0x%08X", net_thread_uid); return -1; } - sceKernelStartThread(net_thread_uid, sizeof(ThreadMessage), &message); uint32_t events; sceNetCtlInetGetState(reinterpret_cast(&events)); @@ -154,53 +141,8 @@ int main() { do { vita2d_start_drawing(); vita2d_clear_screen(); - vita2d_pgf_draw_text(debug_font, 2, 20, common_color, 1.0, - "VitaOxiPad v1.2.0 \nbuild " __DATE__ ", " __TIME__); - - if (events & MainEvent::NET_CONNECT) { - connected_to_network = true; - sceNetCtlInetGetInfo(SCE_NETCTL_INFO_GET_IP_ADDRESS, &info); - snprintf(vita_ip, INET_ADDRSTRLEN, "%s", info.ip_address); - } else if (events & MainEvent::NET_DISCONNECT) { - connected_to_network = false; - } - if (connected_to_network) { - vita2d_pgf_draw_textf(debug_font, 750, 20, common_color, 1.0, - "Listening on:\nIP: %s\nPort: %d", vita_ip, NET_PORT); - } else { - vita2d_pgf_draw_text(debug_font, 750, 20, error_color, 1.0, "Not connected\nto a network :("); - } - - if (events & MainEvent::PC_CONNECT) { - pc_connect_state = true; - } else if (events & MainEvent::PC_DISCONNECT) { - pc_connect_state = false; - } - if (pc_connect_state) { - vita2d_pgf_draw_textf(debug_font, 2, 540, done_color, 1.0, "Status: Connected (%s)", - shared_data.client_ip); - } else { - vita2d_pgf_draw_text(debug_font, 2, 540, error_color, 1.0, "Status: Not connected :("); - } - - if (shared_data.charger_connected) { - need_color = done_color; - } else if (shared_data.battery_level < 30) { - need_color = error_color; - } else { - need_color = common_color; - } - vita2d_pgf_draw_textf(debug_font, 785, 520, need_color, 1.0, "Battery: %s%d%%", - shared_data.charger_connected ? "+" : "", shared_data.battery_level); - - if (shared_data.wifi_signal_strength < 50) { - need_color = error_color; - } else { - need_color = common_color; - } - vita2d_pgf_draw_textf(debug_font, 785, 540, need_color, 1.0, "WiFi signal: %d%%", - shared_data.wifi_signal_strength); + draw_pad_mode(&events, &connected_to_network, &pc_connect_state, vita_ip, &info, &shared_data); vita2d_end_drawing(); vita2d_wait_rendering_done(); diff --git a/server/src/thread_helper.cpp b/server/src/thread_helper.cpp new file mode 100644 index 0000000..4385d14 --- /dev/null +++ b/server/src/thread_helper.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +#include "thread_helper.hpp" + +SceUID create_and_start_thread(const ThreadParams ¶ms) { + SceUID threadUid = + sceKernelCreateThread(params.name, params.entry, params.initPriority, params.stackSize, + params.attr, params.cpuAffinityMask, params.option); + + if (threadUid < 0) { + SCE_DBG_LOG_ERROR("Error creating thread %s: 0x%08X", params.name, threadUid); + return -1; + } + + int startResult = sceKernelStartThread(threadUid, params.threadArgSize, params.threadArgs); + if (startResult < 0) { + SCE_DBG_LOG_ERROR("Error starting thread %s: 0x%08X", params.name, startResult); + sceKernelDeleteThread(threadUid); + return -1; + } + + return threadUid; +} + +int stop_thread(SceUID thread_uid, SceUInt timeout) { + int wait_result = sceKernelWaitThreadEnd(thread_uid, NULL, &timeout); + if (wait_result < 0) { + SCE_DBG_LOG_ERROR("Error waiting for thread to end: 0x%08X", wait_result); + } + int delete_result = sceKernelDeleteThread(thread_uid); + if (delete_result < 0) { + SCE_DBG_LOG_ERROR("Error deleting thread: 0x%08X", delete_result); + } + SCE_DBG_LOG_TRACE("Thread stopped and deleted successfully"); + return delete_result; +} \ No newline at end of file From 50f828d34fe73079c280ef58ad72a2ecd2436470 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Fri, 6 Dec 2024 23:36:49 +0100 Subject: [PATCH 11/26] Server: redesign of interaction logic --- server/include/ctrl.hpp | 7 ++- server/include/draw_helper.hpp | 7 ++- server/include/events.hpp | 19 +++--- server/src/ctrl.cpp | 91 +++++++++-------------------- server/src/draw_helper.cpp | 102 +++++++++++++++++++++++---------- server/src/main.cpp | 73 ++++++++++++++++------- server/src/net.cpp | 15 ++++- 7 files changed, 185 insertions(+), 129 deletions(-) diff --git a/server/include/ctrl.hpp b/server/include/ctrl.hpp index ece160e..6f581b2 100644 --- a/server/include/ctrl.hpp +++ b/server/include/ctrl.hpp @@ -5,5 +5,10 @@ #include "events.hpp" -void get_ctrl_as_netprotocol(flatbuffers::FlatBufferBuilder &builder, SharedData *shared_data); +void get_ctrl(SceCtrlData *pad, SceMotionState *motion_data, SceTouchData *touch_data_front, + SceTouchData *touch_data_back); +void ctrl_as_netprotocol(SceCtrlData *pad, SceMotionState *motion_data, + SceTouchData *touch_data_front, SceTouchData *touch_data_back, + flatbuffers::FlatBufferBuilder &builder, int battery_level); + #endif // __CTRL_H__ diff --git a/server/include/draw_helper.hpp b/server/include/draw_helper.hpp index 2814aca..c37af72 100644 --- a/server/include/draw_helper.hpp +++ b/server/include/draw_helper.hpp @@ -11,7 +11,10 @@ extern uint32_t common_color; extern uint32_t error_color; extern uint32_t done_color; -void draw_pad_mode(uint32_t *events, bool *connected_to_network, bool *pc_connect_state, - char *vita_ip, SceNetCtlInfo *info, SharedData *shared_data); +void draw_rectangle_outline(float x, float y, float width, float height, uint32_t color); +void draw_start_mode(bool connected_to_network, bool pc_connect_state, char *vita_ip, + SharedData *shared_data); +void draw_pad_mode(bool connected_to_network, bool pc_connect_state, char *vita_ip, + SharedData *shared_data); #endif // DRAW_HELPER_HPP diff --git a/server/include/events.hpp b/server/include/events.hpp index ceab4ea..80f5a1d 100644 --- a/server/include/events.hpp +++ b/server/include/events.hpp @@ -1,10 +1,10 @@ #ifndef EVENTS_HPP #define EVENTS_HPP +#include #include #include #include -#include #include @@ -13,15 +13,15 @@ enum MainEvent { // For NetThread - PC_DISCONNECT = 1 << 0, // 0x0001 - PC_CONNECT = 1 << 1, // 0x0002 - NET_CONNECT = 1 << 2, // 0x0004 - NET_DISCONNECT = 1 << 3, // 0x0008 + PC_DISCONNECT = 1 << 0, // 0x0001 + PC_CONNECT = 1 << 1, // 0x0002 + NET_CONNECT = 1 << 2, // 0x0004 + NET_DISCONNECT = 1 << 3, // 0x0008 // For StatusThread - BATTERY_LEVEL = 1 << 8, // 0x0100 - STATUS_CHARGER = 1 << 9, // 0x0200 - WIFI_SIGNAL = 1 << 10, // 0x0400 + BATTERY_LEVEL = 1 << 8, // 0x0100 + STATUS_CHARGER = 1 << 9, // 0x0200 + WIFI_SIGNAL = 1 << 10, // 0x0400 }; struct SharedData { @@ -30,6 +30,9 @@ struct SharedData { bool charger_connected = false; unsigned int wifi_signal_strength = 0; char client_ip[INET_ADDRSTRLEN] = "N/A"; + SceCtrlData pad_data; + bool pad_mode = false; + bool display_on = true; std::mutex mutex; }; diff --git a/server/src/ctrl.cpp b/server/src/ctrl.cpp index d7503c5..cd16859 100644 --- a/server/src/ctrl.cpp +++ b/server/src/ctrl.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include "ctrl.hpp" #include "kctrl-kernel.h" NetProtocol::ButtonsData convert_pad_data(const SceCtrlData &data) { @@ -30,87 +30,48 @@ convert_touch_data(flatbuffers::FlatBufferBuilder &builder, const SceTouchData & return NetProtocol::CreateTouchDataDirect(builder, &reports); } -void get_ctrl_as_netprotocol(flatbuffers::FlatBufferBuilder &builder, SharedData *shared_data) { - builder.Clear(); +void get_ctrl(SceCtrlData *pad, SceMotionState *motion_data, SceTouchData *touch_data_front, + SceTouchData *touch_data_back) { static uint64_t last_ts = 1024; - SceCtrlData pad; - SceMotionState motion_data; - SceTouchData touch_data_front, touch_data_back; - int res = kctrlGetCtrlData(0, &pad, 1); + int res = kctrlGetCtrlData(0, pad, 1); if (res < 0) { - // Handle error SCE_DBG_LOG_ERROR("kctrlGetCtrlData failed: 0x%08X", res); return; } - while (pad.timeStamp <= last_ts) { - kctrlGetCtrlData(0, &pad, 1); + while (pad->timeStamp <= last_ts) { + kctrlGetCtrlData(0, pad, 1); } - // if (pad.buttons & SCE_CTRL_UP) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_UP"); - // if (pad.buttons & SCE_CTRL_DOWN) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_DOWN"); - // if (pad.buttons & SCE_CTRL_LEFT) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_LEFT"); - // if (pad.buttons & SCE_CTRL_RIGHT) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_RIGHT"); - // if (pad.buttons & SCE_CTRL_LTRIGGER) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_LTRIGGER"); - // if (pad.buttons & SCE_CTRL_RTRIGGER) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_RTRIGGER"); - // if (pad.buttons & SCE_CTRL_TRIANGLE) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_TRIANGLE"); - // if (pad.buttons & SCE_CTRL_CIRCLE) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_CIRCLE"); - // if (pad.buttons & SCE_CTRL_CROSS) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_CROSS"); - // if (pad.buttons & SCE_CTRL_SQUARE) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_SQUARE"); - // if (pad.buttons & SCE_CTRL_START) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_START"); - // if (pad.buttons & SCE_CTRL_SELECT) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_SELECT"); - // if (pad.buttons & SCE_CTRL_PSBUTTON) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_PSBUTTON"); - // if (pad.buttons & SCE_CTRL_VOLUP) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_VOLUP"); - // if (pad.buttons & SCE_CTRL_VOLDOWN) - // SCE_DBG_LOG_DEBUG("SCE_CTRL_VOLDOWN"); - - - if (pad.buttons & SCE_CTRL_SELECT && pad.buttons & SCE_CTRL_LTRIGGER){ - sceKernelDelayThread(50 * 1000); - pad.buttons |= SCE_CTRL_VOLDOWN; - } - if (pad.buttons & SCE_CTRL_SELECT && pad.buttons & SCE_CTRL_RTRIGGER){ - sceKernelDelayThread(50 * 1000); - pad.buttons |= SCE_CTRL_VOLUP; - } + if (pad->buttons & SCE_CTRL_VOLDOWN || pad->buttons & SCE_CTRL_VOLUP) + sceKernelDelayThread(100 * 1000); - auto buttons = convert_pad_data(pad); + sceTouchPeek(SCE_TOUCH_PORT_FRONT, touch_data_front, 1); + sceTouchPeek(SCE_TOUCH_PORT_BACK, touch_data_back, 1); + sceMotionGetState(motion_data); + last_ts = pad->timeStamp; +} - sceTouchPeek(SCE_TOUCH_PORT_FRONT, &touch_data_front, 1); - auto data_front = convert_touch_data(builder, touch_data_front); +void ctrl_as_netprotocol(SceCtrlData *pad, SceMotionState *motion_data, + SceTouchData *touch_data_front, SceTouchData *touch_data_back, + flatbuffers::FlatBufferBuilder &builder, int battery_level) { + builder.Clear(); - sceTouchPeek(SCE_TOUCH_PORT_BACK, &touch_data_back, 1); - auto data_back = convert_touch_data(builder, touch_data_back); + auto buttons = convert_pad_data(*pad); + auto data_front = convert_touch_data(builder, *touch_data_front); + auto data_back = convert_touch_data(builder, *touch_data_back); - sceMotionGetState(&motion_data); - NetProtocol::Vector3 accel(motion_data.acceleration.x, motion_data.acceleration.y, - motion_data.acceleration.z); - NetProtocol::Vector3 gyro(motion_data.angularVelocity.x, motion_data.angularVelocity.y, - motion_data.angularVelocity.z); + NetProtocol::Vector3 accel(motion_data->acceleration.x, motion_data->acceleration.y, + motion_data->acceleration.z); + NetProtocol::Vector3 gyro(motion_data->angularVelocity.x, motion_data->angularVelocity.y, + motion_data->angularVelocity.z); NetProtocol::MotionData motion(gyro, accel); - int charge_percent = shared_data->battery_level; - auto content = - NetProtocol::CreatePad(builder, &buttons, pad.lx, pad.ly, pad.rx, pad.ry, data_front, - data_back, &motion, pad.timeStamp, charge_percent); + NetProtocol::CreatePad(builder, &buttons, pad->lx, pad->ly, pad->rx, pad->ry, data_front, + data_back, &motion, pad->timeStamp, battery_level); auto packet = NetProtocol::CreatePacket(builder, NetProtocol::PacketContent::Pad, content.Union()); builder.FinishSizePrefixed(packet); - last_ts = pad.timeStamp; } diff --git a/server/src/draw_helper.cpp b/server/src/draw_helper.cpp index f8f9c8a..a5635b0 100644 --- a/server/src/draw_helper.cpp +++ b/server/src/draw_helper.cpp @@ -5,57 +5,97 @@ vita2d_pgf *debug_font; uint32_t need_color = 0; -uint32_t common_color = RGBA8(0xFF, 0xFF, 0xFF, 0xFF); // White color -uint32_t error_color = RGBA8(0xFF, 0x00, 0x00, 0xFF); // Bright red color -uint32_t done_color = RGBA8(0x00, 0xFF, 0x00, 0xFF); // Bright green color - -void draw_pad_mode(uint32_t *events, bool *connected_to_network, bool *pc_connect_state, char *vita_ip, - SceNetCtlInfo *info, SharedData *shared_data) { - vita2d_pgf_draw_text(debug_font, 2, 20, common_color, 1.0, - "VitaOxiPad v1.2.0 \nbuild " __DATE__ ", " __TIME__); - - if (*events & MainEvent::NET_CONNECT) { - *connected_to_network = true; - sceNetCtlInetGetInfo(SCE_NETCTL_INFO_GET_IP_ADDRESS, info); - snprintf(vita_ip, INET_ADDRSTRLEN, "%s", info->ip_address); - } else if (*events & MainEvent::NET_DISCONNECT) { - *connected_to_network = false; +uint32_t white_color = RGBA8(0xFF, 0xFF, 0xFF, 0xFF); // White color +uint32_t error_color = RGBA8(0xFF, 0x00, 0x00, 0xFF); // Bright red color +uint32_t done_color = RGBA8(0x00, 0xFF, 0x00, 0xFF); // Bright green color + +float screen_width = 960.0f; +float screen_height = 544.0f; + +void draw_rectangle_outline(float x, float y, float width, float height, uint32_t color) { + vita2d_draw_line(x, y, x + width, y, color); + vita2d_draw_line(x + width, y, x + width, y + height, color); + vita2d_draw_line(x + width, y + height, x, y + height, color); + vita2d_draw_line(x, y + height, x, y, color); +} + +void draw_start_mode(bool connected_to_network, bool pc_connect_state, char *vita_ip, + SharedData *shared_data) { + float offset = 40; + float rect_outline_spase = 5; + float text_offset = 15; + draw_rectangle_outline(offset, offset, screen_width - 2 * offset, screen_height - 2 * offset, + white_color); + draw_rectangle_outline(rect_outline_spase + offset, rect_outline_spase + offset, + screen_width - 2 * (offset + rect_outline_spase), + screen_height - 2 * (offset + rect_outline_spase), white_color); + vita2d_pgf_draw_textf(debug_font, text_offset + offset, 35 + offset, white_color, 1.0, + "VitaOxiPad v1.2.0 build %s, %s by theSame, santarl and saidsay-so.", + __DATE__, __TIME__); + + vita2d_draw_line(10 + offset, 55 + offset, screen_width - 10 - offset, 55 + offset, white_color); + vita2d_pgf_draw_text(debug_font, text_offset + offset, 85 + offset, white_color, 1.0, "Control:"); + vita2d_pgf_draw_text(debug_font, text_offset + offset, 115 + offset, white_color, 1.0, + "* CROSS => Enter Pad mode"); + vita2d_pgf_draw_text(debug_font, text_offset + offset, 145 + offset, white_color, 1.0, + "* START + SELECT in Pad mode => Exit Pad mode"); + // vita2d_pgf_draw_text(debug_font, text_offset + offset, 175 + offset, white_color, 1.0, + // "* START + DPAD UP in Pad mode => Switch the screen on"); + // vita2d_pgf_draw_text(debug_font, text_offset + offset, 205 + offset, white_color, 1.0, + // "* START + DPAD DOWN in Pad mode => Switch the screen off"); + + vita2d_draw_line(10 + offset, 380 + offset, screen_width - 10 - offset, 380 + offset, + white_color); + if (connected_to_network) { + vita2d_pgf_draw_textf(debug_font, 740 - offset, screen_height - offset - 55, white_color, 1.0, + "Listening on:\nIP: %s\nPort: %d", vita_ip, NET_PORT); + } else { + vita2d_pgf_draw_text(debug_font, 740 - offset, screen_height - offset - 55, error_color, 1.0, + "Not connected\nto a network :("); } + if (pc_connect_state) { + vita2d_pgf_draw_textf(debug_font, text_offset + offset, screen_height - offset - 40, done_color, + 1.0, "Status:\nConnected (%s)", shared_data->client_ip); + } else { + vita2d_pgf_draw_text(debug_font, text_offset + offset, screen_height - offset - 40, error_color, + 1.0, "Status:\nNot connected :("); + } +} + +void draw_pad_mode(bool connected_to_network, bool pc_connect_state, char *vita_ip, + SharedData *shared_data) { + draw_rectangle_outline(1, 1, screen_width - 1, screen_height - 1, white_color); - if (*connected_to_network) { - vita2d_pgf_draw_textf(debug_font, 750, 20, common_color, 1.0, "Listening on:\nIP: %s\nPort: %d", + if (connected_to_network) { + vita2d_pgf_draw_textf(debug_font, 740, 20, white_color, 1.0, "Listening on:\nIP: %s\nPort: %d", vita_ip, NET_PORT); } else { - vita2d_pgf_draw_text(debug_font, 750, 20, error_color, 1.0, "Not connected\nto a network :("); + vita2d_pgf_draw_text(debug_font, 740, 20, error_color, 1.0, "Not connected\nto a network :("); } - if (*events & MainEvent::PC_CONNECT) { - *pc_connect_state = true; - } else if (*events & MainEvent::PC_DISCONNECT) { - *pc_connect_state = false; - } - if (*pc_connect_state) { - vita2d_pgf_draw_textf(debug_font, 2, 540, done_color, 1.0, "Status: Connected (%s)", + if (pc_connect_state) { + vita2d_pgf_draw_textf(debug_font, 5, 20, done_color, 1.0, "Status:\nConnected (%s)", shared_data->client_ip); } else { - vita2d_pgf_draw_text(debug_font, 2, 540, error_color, 1.0, "Status: Not connected :("); + vita2d_pgf_draw_text(debug_font, 5, 20, error_color, 1.0, "Status:\nNot connected :("); } + vita2d_pgf_draw_text(debug_font, 5, 535, white_color, 1.0, "START + SELECT => Exit Pad mode"); + if (shared_data->charger_connected) { need_color = done_color; } else if (shared_data->battery_level < 30) { need_color = error_color; } else { - need_color = common_color; + need_color = white_color; } - vita2d_pgf_draw_textf(debug_font, 785, 520, need_color, 1.0, "Battery: %s%d%%", + vita2d_pgf_draw_textf(debug_font, 740, 515, need_color, 1.0, "Battery: %s%d%%", shared_data->charger_connected ? "+" : "", shared_data->battery_level); - if (shared_data->wifi_signal_strength < 50) { need_color = error_color; } else { - need_color = common_color; + need_color = white_color; } - vita2d_pgf_draw_textf(debug_font, 785, 540, need_color, 1.0, "WiFi signal: %d%%", + vita2d_pgf_draw_textf(debug_font, 740, 535, need_color, 1.0, "WiFi signal: %d%%", shared_data->wifi_signal_strength); } diff --git a/server/src/main.cpp b/server/src/main.cpp index 5e5f6d1..5e6b845 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -27,6 +28,8 @@ #define MOD_PATH "ux0:app/VOXIPAD01/module/kctrl.skprx" constexpr size_t NET_INIT_SIZE = 1 * 1024 * 1024; +constexpr size_t TARGET_FPS = 10; +constexpr size_t FRAME_DURATION_MS = 1000 / TARGET_FPS; std::atomic g_net_thread_running(true); std::atomic g_status_thread_running(true); @@ -46,20 +49,6 @@ int main() { sceAppMgrLoadExec("app0:eboot.bin", NULL, NULL); } - // sceShellUtilInitEvents(0); - // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_PS_BTN); - // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_QUICK_MENU); - // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_POWEROFF_MENU); - // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_UNK8); - // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_USB_CONNECTION); - // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_MC_INSERTED); - // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_MC_REMOVED); - // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_UNK80); - // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_UNK100); - // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_UNK200); - // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_MUSIC_PLAYER); - // sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_PS_BTN_2); - // Enabling analog, motion and touch support sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG_WIDE); sceMotionStartSampling(); @@ -106,6 +95,8 @@ int main() { shared_data.events = 0; shared_data.battery_level = scePowerGetBatteryLifePercent(); shared_data.charger_connected = scePowerIsBatteryCharging(); + shared_data.pad_mode = false; + shared_data.display_on = true; ThreadMessage message = {ev_flag, &shared_data}; // Creating events and status thread @@ -136,19 +127,61 @@ int main() { } events = 0; - // Main loop for events - // Loop is executed if the MainEvent state changes - do { + bool exit_state = true; + while (exit_state) { + auto frame_start = std::chrono::high_resolution_clock::now(); + sceKernelPollEventFlag(ev_flag, 0xFFFFFFFF, SCE_EVENT_WAITOR | SCE_EVENT_WAITCLEAR, &events); + vita2d_start_drawing(); vita2d_clear_screen(); - draw_pad_mode(&events, &connected_to_network, &pc_connect_state, vita_ip, &info, &shared_data); + if (events & MainEvent::NET_CONNECT) { + connected_to_network = true; + sceNetCtlInetGetInfo(SCE_NETCTL_INFO_GET_IP_ADDRESS, &info); + snprintf(vita_ip, INET_ADDRSTRLEN, "%s", info.ip_address); + } else if (events & MainEvent::NET_DISCONNECT) { + connected_to_network = false; + } + + if (events & MainEvent::PC_CONNECT) { + pc_connect_state = true; + } else if (events & MainEvent::PC_DISCONNECT) { + pc_connect_state = false; + } + + if ((shared_data.pad_data.buttons & SCE_CTRL_CROSS) && !shared_data.pad_mode) { + shared_data.pad_mode = true; + sceShellUtilInitEvents(0); + sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_PS_BTN_2); + sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_POWEROFF_MENU); + } + + if ((shared_data.pad_data.buttons & SCE_CTRL_SELECT && + shared_data.pad_data.buttons & SCE_CTRL_START) && + shared_data.pad_mode) { + shared_data.pad_mode = false; + sceShellUtilUnlock(SCE_SHELL_UTIL_LOCK_TYPE_PS_BTN_2); + sceShellUtilUnlock(SCE_SHELL_UTIL_LOCK_TYPE_POWEROFF_MENU); + } + + if (shared_data.pad_mode) + draw_pad_mode(connected_to_network, pc_connect_state, vita_ip, &shared_data); + else { + draw_start_mode(connected_to_network, pc_connect_state, vita_ip, &shared_data); + } vita2d_end_drawing(); vita2d_wait_rendering_done(); vita2d_swap_buffers(); - } while (sceKernelWaitEventFlag(ev_flag, 0xFFFFFFFF, SCE_EVENT_WAITOR | SCE_EVENT_WAITCLEAR, - &events, NULL) == 0); + + auto frame_end = std::chrono::high_resolution_clock::now(); + auto elapsed_ms = + std::chrono::duration_cast(frame_end - frame_start).count(); + if (elapsed_ms < FRAME_DURATION_MS) { + SceUInt delay_us = static_cast((FRAME_DURATION_MS - elapsed_ms) * 1000); + sceKernelDelayThread(delay_us); + } + } // Turn on network thread stop signal and wait for its normal termination SceUInt THREAD_TIMEOUT = (SceUInt)(15 * 1000 * 1000); diff --git a/server/src/net.cpp b/server/src/net.cpp index dfaeede..f4ec768 100644 --- a/server/src/net.cpp +++ b/server/src/net.cpp @@ -1,4 +1,7 @@ +#include #include +#include +#include #include @@ -195,12 +198,18 @@ int net_thread(__attribute__((unused)) unsigned int arglen, void *argp) { static flatbuffers::FlatBufferBuilder pad_data(512); // keystroke data storage static flatbuffers::FlatBufferBuilder handshake_data(128); // response to heartbeat + SceCtrlData pad; + SceMotionState motion_data; + SceTouchData touch_data_front, touch_data_back; + // Main loop of the network // Ends if there was a sceNetEpollWait error or the thread was asked to stop // via g_net_thread_running while (g_net_thread_running.load()) { // Power tick for sleep disabling, update battery sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_AUTO_SUSPEND); + get_ctrl(&pad, &motion_data, &touch_data_front, &touch_data_back); + shared_data->pad_data = pad; // Receiving TCP events n = sceNetEpollWait(epoll, events, MAX_EPOLL_EVENTS, timeout); @@ -323,9 +332,11 @@ int net_thread(__attribute__((unused)) unsigned int arglen, void *argp) { } // Sending push data if the client is connected - if (client->state() == Client::State::Connected && client->is_polling_time_elapsed()) { + if (client->state() == Client::State::Connected && client->is_polling_time_elapsed() && + shared_data->pad_mode) { if (server_udp_fd >= 0) { - get_ctrl_as_netprotocol(pad_data, shared_data); + ctrl_as_netprotocol(&pad, &motion_data, &touch_data_front, &touch_data_back, pad_data, + shared_data->battery_level); client->update_sent_data_time(); auto client_addr = client->data_conn_info(); SceNetSockaddr *need_client_addr = reinterpret_cast(&client_addr); From e5d2e333551c442abbf1305424e57f43faed53ec Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Fri, 6 Dec 2024 23:38:30 +0100 Subject: [PATCH 12/26] Server: added SceShell Authid --- server/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 8d30d87..1216f8a 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -25,6 +25,7 @@ endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") set(VITA_MKSFOEX_FLAGS "${VITA_MKSFOEX_FLAGS} -d PARENTAL_LEVEL=1") +set(VITA_MAKE_FSELF_FLAGS "${VITA_MAKE_FSELF_FLAGS} -a 0x2800000000000001") # Build FlatBuffers set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/../cmake/") @@ -99,7 +100,7 @@ target_link_libraries(${VITA_APP_NAME} ) # Create the application self and VPK -vita_create_self(${VITA_APP_NAME}.self ${VITA_APP_NAME} UNSAFE) +vita_create_self(${VITA_APP_NAME}.self ${VITA_APP_NAME}) vita_create_vpk(${VITA_APP_NAME}.vpk ${VITA_TITLEID} ${VITA_APP_NAME}.self VERSION ${VITA_VERSION} NAME ${VITA_APP_NAME} From 7483b4c621b59f1d521661ad1c0b4bd019806f8a Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Fri, 6 Dec 2024 23:53:31 +0100 Subject: [PATCH 13/26] Server: added PS button support --- common/netprotocol.fbs | 1 + server/src/ctrl.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/common/netprotocol.fbs b/common/netprotocol.fbs index 7bf33b0..72c9df2 100644 --- a/common/netprotocol.fbs +++ b/common/netprotocol.fbs @@ -36,6 +36,7 @@ struct ButtonsData square: bool; vol_up: bool; vol_down: bool; + ps: bool; } struct Vector3 diff --git a/server/src/ctrl.cpp b/server/src/ctrl.cpp index cd16859..c500ed1 100644 --- a/server/src/ctrl.cpp +++ b/server/src/ctrl.cpp @@ -16,7 +16,8 @@ NetProtocol::ButtonsData convert_pad_data(const SceCtrlData &data) { (data.buttons & SCE_CTRL_LTRIGGER) > 0, (data.buttons & SCE_CTRL_RTRIGGER) > 0, (data.buttons & SCE_CTRL_TRIANGLE) > 0, (data.buttons & SCE_CTRL_CIRCLE) > 0, (data.buttons & SCE_CTRL_CROSS) > 0, (data.buttons & SCE_CTRL_SQUARE) > 0, - (data.buttons & SCE_CTRL_VOLUP) > 0, (data.buttons & SCE_CTRL_VOLDOWN) > 0); + (data.buttons & SCE_CTRL_VOLUP) > 0, (data.buttons & SCE_CTRL_VOLDOWN) > 0, + (data.buttons & SCE_CTRL_PSBUTTON) > 0); } flatbuffers::Offset From ebcf6439a6f1d5f1503fce27a5c742ea2d6f0e6e Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Sat, 7 Dec 2024 00:07:30 +0100 Subject: [PATCH 14/26] Client: added PS button support (Windows) --- client/packages/vita_reports/src/lib.rs | 2 ++ client/packages/vita_virtual_device/src/windows.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/client/packages/vita_reports/src/lib.rs b/client/packages/vita_reports/src/lib.rs index 5434a2d..890aa17 100644 --- a/client/packages/vita_reports/src/lib.rs +++ b/client/packages/vita_reports/src/lib.rs @@ -14,6 +14,7 @@ pub struct ButtonsData { pub square: bool, pub vol_up: bool, pub vol_down: bool, + pub ps: bool, // timestamp: u64; } @@ -34,6 +35,7 @@ impl From for ButtonsData { square: buttons.square(), vol_up: buttons.vol_up(), vol_down: buttons.vol_down(), + ps: buttons.ps(), // timestamp: buttons.timestamp(), } } diff --git a/client/packages/vita_virtual_device/src/windows.rs b/client/packages/vita_virtual_device/src/windows.rs index ad35b6a..a7276d3 100644 --- a/client/packages/vita_virtual_device/src/windows.rs +++ b/client/packages/vita_virtual_device/src/windows.rs @@ -312,6 +312,8 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { self.touch_start_time = None; } + special_buttons = special_buttons.ps_home(report.buttons.ps); + self.touch_state = is_touching; // Создаем touchpad report From f1eb6ad1e7b5a1a26bffd34f26049b9e60b3dde5 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Sat, 7 Dec 2024 12:11:19 +0100 Subject: [PATCH 15/26] Server; added option to switch off the screen --- server/module/CMakeLists.txt | 3 ++ server/module/include/kctrl-kernel.h | 8 +-- server/module/kctrl.yml | 3 ++ server/module/src/main.c | 74 +++++++++++++++++++++++++++- server/src/draw_helper.cpp | 10 ++-- server/src/main.cpp | 21 ++++++-- 6 files changed, 106 insertions(+), 13 deletions(-) diff --git a/server/module/CMakeLists.txt b/server/module/CMakeLists.txt index a556bde..9491074 100644 --- a/server/module/CMakeLists.txt +++ b/server/module/CMakeLists.txt @@ -24,7 +24,10 @@ add_executable(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} SceDebugForDriver_stub SceCtrlForDriver_stub + SceModulemgrForDriver_stub SceSysmemForDriver_stub + SceOledForDriver_stub_weak + SceLcdForDriver_stub_weak ) # Include the module's include directory diff --git a/server/module/include/kctrl-kernel.h b/server/module/include/kctrl-kernel.h index 4f58637..392a022 100644 --- a/server/module/include/kctrl-kernel.h +++ b/server/module/include/kctrl-kernel.h @@ -4,11 +4,13 @@ #include #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - int kctrlGetCtrlData(int port, SceCtrlData* pad_data, int count); +void kctrlScreenOn(void); +void kctrlScreenOff(void); +void kctrlToggleScreen(void); +int kctrlGetCtrlData(int port, SceCtrlData *pad_data, int count); #ifdef __cplusplus } diff --git a/server/module/kctrl.yml b/server/module/kctrl.yml index c945786..75e1a87 100644 --- a/server/module/kctrl.yml +++ b/server/module/kctrl.yml @@ -10,4 +10,7 @@ kctrl: kctrlForKernel: syscall: true functions: + - kctrlScreenOn + - kctrlScreenOff + - kctrlToggleScreen - kctrlGetCtrlData diff --git a/server/module/src/main.c b/server/module/src/main.c index e070f6a..87ea0e2 100644 --- a/server/module/src/main.c +++ b/server/module/src/main.c @@ -24,6 +24,62 @@ #include "kctrl-kernel.h" +// missing in vitasdk +int ksceOledDisplayOn(void); +int ksceOledDisplayOff(void); +int ksceOledGetBrightness(void); +int ksceOledSetBrightness(int brightness); + +int ksceLcdDisplayOn(void); +int ksceLcdDisplayOff(void); +int ksceLcdGetBrightness(void); +int ksceLcdSetBrightness(int brightness); + +static uint8_t g_is_oled = 0; +static uint8_t g_is_lcd = 0; +static int g_screen_off = 0; +static int g_prev_brightness; + +void kctrlScreenOn() { + uint32_t state; + ENTER_SYSCALL(state); + + if (g_is_oled) { + ksceOledDisplayOn(); + ksceOledSetBrightness(g_prev_brightness); + } else if (g_is_lcd) { + ksceLcdDisplayOn(); + ksceLcdSetBrightness(g_prev_brightness); + } + + EXIT_SYSCALL(state); +} + +void kctrlScreenOff() { + uint32_t state; + ENTER_SYSCALL(state); + + if (g_is_oled) { + // g_prev_brightness = ksceOledGetBrightness(); + ksceOledDisplayOff(); + } else if (g_is_lcd) { + // g_prev_brightness = ksceLcdGetBrightness(); + ksceLcdDisplayOff(); + } + + EXIT_SYSCALL(state); +} + +void kctrlToggleScreen() { + if (g_screen_off) { + kctrlScreenOn(); + g_screen_off = 0; + } else { + kctrlScreenOff(); + g_screen_off = 1; + } +} + int kctrlGetCtrlData(int port, SceCtrlData *pad_data, int count) { SceCtrlData pad; @@ -38,7 +94,23 @@ int kctrlGetCtrlData(int port, SceCtrlData *pad_data, int count) { } void _start() __attribute__((weak, alias("module_start"))); -int module_start(SceSize args, const void *argp) { return SCE_KERNEL_START_SUCCESS; } +int module_start(SceSize args, const void *argp) { + if (ksceKernelSearchModuleByName("SceLcd") >= 0) { + g_is_lcd = 1; + } else if (ksceKernelSearchModuleByName("SceOled") >= 0) { + g_is_oled = 1; + } + + ksceKernelPrintf("is_lcd: %d\n", g_is_lcd); + ksceKernelPrintf("is_oled: %d\n", g_is_oled); + + if (g_is_oled) { + g_prev_brightness = ksceOledGetBrightness(); + } else if (g_is_lcd) { + g_prev_brightness = ksceLcdGetBrightness(); + } + return SCE_KERNEL_START_SUCCESS; +} void _stop() __attribute__((weak, alias("module_stop"))); int module_stop(SceSize args, const void *argp) { return SCE_KERNEL_STOP_SUCCESS; } diff --git a/server/src/draw_helper.cpp b/server/src/draw_helper.cpp index a5635b0..39d8ed7 100644 --- a/server/src/draw_helper.cpp +++ b/server/src/draw_helper.cpp @@ -39,10 +39,8 @@ void draw_start_mode(bool connected_to_network, bool pc_connect_state, char *vit "* CROSS => Enter Pad mode"); vita2d_pgf_draw_text(debug_font, text_offset + offset, 145 + offset, white_color, 1.0, "* START + SELECT in Pad mode => Exit Pad mode"); - // vita2d_pgf_draw_text(debug_font, text_offset + offset, 175 + offset, white_color, 1.0, - // "* START + DPAD UP in Pad mode => Switch the screen on"); - // vita2d_pgf_draw_text(debug_font, text_offset + offset, 205 + offset, white_color, 1.0, - // "* START + DPAD DOWN in Pad mode => Switch the screen off"); + vita2d_pgf_draw_text(debug_font, text_offset + offset, 175 + offset, white_color, 1.0, + "* START + DPAD UP in Pad mode => Toggle screen On/Off"); vita2d_draw_line(10 + offset, 380 + offset, screen_width - 10 - offset, 380 + offset, white_color); @@ -80,7 +78,9 @@ void draw_pad_mode(bool connected_to_network, bool pc_connect_state, char *vita_ vita2d_pgf_draw_text(debug_font, 5, 20, error_color, 1.0, "Status:\nNot connected :("); } - vita2d_pgf_draw_text(debug_font, 5, 535, white_color, 1.0, "START + SELECT => Exit Pad mode"); + vita2d_pgf_draw_text(debug_font, 5, 515, white_color, 1.0, "START + SELECT => Exit Pad mode"); + vita2d_pgf_draw_text(debug_font, 5, 535, white_color, 1.0, + "START + DPAD UP => Toggle screen On/Off"); if (shared_data->charger_connected) { need_color = done_color; diff --git a/server/src/main.cpp b/server/src/main.cpp index 5e6b845..cb536d2 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -28,7 +28,7 @@ #define MOD_PATH "ux0:app/VOXIPAD01/module/kctrl.skprx" constexpr size_t NET_INIT_SIZE = 1 * 1024 * 1024; -constexpr size_t TARGET_FPS = 10; +constexpr size_t TARGET_FPS = 15; constexpr size_t FRAME_DURATION_MS = 1000 / TARGET_FPS; std::atomic g_net_thread_running(true); @@ -162,11 +162,24 @@ int main() { shared_data.pad_mode = false; sceShellUtilUnlock(SCE_SHELL_UTIL_LOCK_TYPE_PS_BTN_2); sceShellUtilUnlock(SCE_SHELL_UTIL_LOCK_TYPE_POWEROFF_MENU); + shared_data.display_on = true; + kctrlScreenOn(); } - if (shared_data.pad_mode) - draw_pad_mode(connected_to_network, pc_connect_state, vita_ip, &shared_data); - else { + if (shared_data.pad_mode) { + if ((shared_data.pad_data.buttons & SCE_CTRL_UP) && + (shared_data.pad_data.buttons & SCE_CTRL_START)) { + shared_data.display_on = !shared_data.display_on; + if (shared_data.display_on) { + kctrlScreenOn(); + } else { + kctrlScreenOff(); + } + } + if (shared_data.display_on) { + draw_pad_mode(connected_to_network, pc_connect_state, vita_ip, &shared_data); + } + } else { draw_start_mode(connected_to_network, pc_connect_state, vita_ip, &shared_data); } From 2a4534a22d10a88cd99dec3277b944f133fcbefb Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Sat, 7 Dec 2024 12:30:59 +0100 Subject: [PATCH 16/26] Server: remove old includes --- server/include/events.hpp | 2 -- server/include/net.hpp | 1 - server/include/status.hpp | 7 ------- server/include/thread_helper.hpp | 2 -- server/src/ctrl.cpp | 3 --- server/src/draw_helper.cpp | 1 - server/src/main.cpp | 9 +-------- server/src/net.cpp | 1 - server/src/status.cpp | 1 - server/src/thread_helper.cpp | 3 --- 10 files changed, 1 insertion(+), 29 deletions(-) diff --git a/server/include/events.hpp b/server/include/events.hpp index 80f5a1d..5f13105 100644 --- a/server/include/events.hpp +++ b/server/include/events.hpp @@ -3,8 +3,6 @@ #include #include -#include -#include #include diff --git a/server/include/net.hpp b/server/include/net.hpp index 0b506bc..79cc693 100644 --- a/server/include/net.hpp +++ b/server/include/net.hpp @@ -1,7 +1,6 @@ #ifndef NET_HPP #define NET_HPP -#include #include #include diff --git a/server/include/status.hpp b/server/include/status.hpp index f1f51dd..e64dbfe 100644 --- a/server/include/status.hpp +++ b/server/include/status.hpp @@ -1,13 +1,6 @@ #ifndef STATUS_HPP #define STATUS_HPP -#include -#include - -#include -#include -#include - #include #include "events.hpp" diff --git a/server/include/thread_helper.hpp b/server/include/thread_helper.hpp index bed576b..dc2179d 100644 --- a/server/include/thread_helper.hpp +++ b/server/include/thread_helper.hpp @@ -1,6 +1,4 @@ #include -// #include -// #include #ifndef THREAD_HELPER_HPP #define THREAD_HELPER_HPP diff --git a/server/src/ctrl.cpp b/server/src/ctrl.cpp index c500ed1..b26133e 100644 --- a/server/src/ctrl.cpp +++ b/server/src/ctrl.cpp @@ -1,6 +1,3 @@ -#include - -#include #include #include #include diff --git a/server/src/draw_helper.cpp b/server/src/draw_helper.cpp index 39d8ed7..0175499 100644 --- a/server/src/draw_helper.cpp +++ b/server/src/draw_helper.cpp @@ -1,5 +1,4 @@ #include "draw_helper.hpp" -#include "status.hpp" #include diff --git a/server/src/main.cpp b/server/src/main.cpp index cb536d2..417e1cb 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -1,9 +1,4 @@ -#include -#include #include -#include -#include -#include #include #include #include @@ -12,18 +7,16 @@ #include #include #include -#include #include "ctrl.hpp" #include "draw_helper.hpp" -#include "events.hpp" #include "net.hpp" #include "status.hpp" #include "thread_helper.hpp" #include "kctrl-kernel.h" -#include +// #include #define MOD_PATH "ux0:app/VOXIPAD01/module/kctrl.skprx" diff --git a/server/src/net.cpp b/server/src/net.cpp index f4ec768..5b963e0 100644 --- a/server/src/net.cpp +++ b/server/src/net.cpp @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/server/src/status.cpp b/server/src/status.cpp index a362b4e..2ab0c69 100644 --- a/server/src/status.cpp +++ b/server/src/status.cpp @@ -1,4 +1,3 @@ - #include #include diff --git a/server/src/thread_helper.cpp b/server/src/thread_helper.cpp index 4385d14..642cc95 100644 --- a/server/src/thread_helper.cpp +++ b/server/src/thread_helper.cpp @@ -1,6 +1,3 @@ -#include -#include -#include #include #include "thread_helper.hpp" From 0a71696e541eb0d39c0ee161f4541dfb94ec53e3 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Sat, 7 Dec 2024 23:20:27 +0100 Subject: [PATCH 17/26] Server: added loading pic0 --- server/CMakeLists.txt | 1 + server/sce_sys/pic0.png | Bin 0 -> 9598 bytes 2 files changed, 1 insertion(+) create mode 100644 server/sce_sys/pic0.png diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 1216f8a..f2dd89e 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -105,6 +105,7 @@ vita_create_vpk(${VITA_APP_NAME}.vpk ${VITA_TITLEID} ${VITA_APP_NAME}.self VERSION ${VITA_VERSION} NAME ${VITA_APP_NAME} FILE sce_sys/icon0.png sce_sys/icon0.png + FILE sce_sys/pic0.png sce_sys/pic0.png FILE sce_sys/livearea/contents/bg.png sce_sys/livearea/contents/bg.png FILE sce_sys/livearea/contents/startup.png sce_sys/livearea/contents/startup.png FILE sce_sys/livearea/contents/template.xml sce_sys/livearea/contents/template.xml diff --git a/server/sce_sys/pic0.png b/server/sce_sys/pic0.png new file mode 100644 index 0000000000000000000000000000000000000000..0a5335541aa8f0024e4f4c3a44d7124ad8440ad9 GIT binary patch literal 9598 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 Date: Sat, 7 Dec 2024 23:21:21 +0100 Subject: [PATCH 18/26] Server: added delay for screen toggler --- server/src/main.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/server/src/main.cpp b/server/src/main.cpp index 417e1cb..4782714 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -163,11 +163,8 @@ int main() { if ((shared_data.pad_data.buttons & SCE_CTRL_UP) && (shared_data.pad_data.buttons & SCE_CTRL_START)) { shared_data.display_on = !shared_data.display_on; - if (shared_data.display_on) { - kctrlScreenOn(); - } else { - kctrlScreenOff(); - } + kctrlToggleScreen(); + sceKernelDelayThread(300 * 1000); } if (shared_data.display_on) { draw_pad_mode(connected_to_network, pc_connect_state, vita_ip, &shared_data); From 3f9a0ee54167ce9881764eb24917da507edf79da Mon Sep 17 00:00:00 2001 From: santarl Date: Mon, 9 Dec 2024 09:30:39 +0400 Subject: [PATCH 19/26] client: Rename environment variable prefix from VITAOXIPAD_ to VITA_ for consistency with CMakeLists --- client/packages/cli/src/config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/packages/cli/src/config.rs b/client/packages/cli/src/config.rs index 7e625f6..e1cfa75 100644 --- a/client/packages/cli/src/config.rs +++ b/client/packages/cli/src/config.rs @@ -91,10 +91,10 @@ pub fn load_config() -> color_eyre::Result { } // Add the source for environment variables - settings = settings.add_source(Environment::with_prefix("VITAOXIPAD")); + settings = settings.add_source(Environment::with_prefix("VITA_")); // Check if environment variables are found - if env::vars().any(|(key, _)| key.starts_with("VITAOXIPAD_")) { + if env::vars().any(|(key, _)| key.starts_with("VITA_")) { println!("Environment variables found. They will take precedence over the config file."); } From 4ac4a738da84212ee6d4e78314378e6f098de3bb Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Mon, 9 Dec 2024 10:59:49 +0100 Subject: [PATCH 20/26] Server: minor fix --- server/module/src/main.c | 3 --- server/src/main.cpp | 5 ++--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/server/module/src/main.c b/server/module/src/main.c index 87ea0e2..ebf6dde 100644 --- a/server/module/src/main.c +++ b/server/module/src/main.c @@ -101,9 +101,6 @@ int module_start(SceSize args, const void *argp) { g_is_oled = 1; } - ksceKernelPrintf("is_lcd: %d\n", g_is_lcd); - ksceKernelPrintf("is_oled: %d\n", g_is_oled); - if (g_is_oled) { g_prev_brightness = ksceOledGetBrightness(); } else if (g_is_lcd) { diff --git a/server/src/main.cpp b/server/src/main.cpp index 4782714..34d4460 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -16,8 +16,6 @@ #include "kctrl-kernel.h" -// #include - #define MOD_PATH "ux0:app/VOXIPAD01/module/kctrl.skprx" constexpr size_t NET_INIT_SIZE = 1 * 1024 * 1024; @@ -43,7 +41,8 @@ int main() { } // Enabling analog, motion and touch support - sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG_WIDE); + sceCtrlSetButtonIntercept(1); + sceCtrlSetSamplingMode(SCE_CTRL_MODE_DIGITAL); sceMotionStartSampling(); sceTouchSetSamplingState(SCE_TOUCH_PORT_FRONT, SCE_TOUCH_SAMPLING_STATE_START); sceTouchSetSamplingState(SCE_TOUCH_PORT_BACK, SCE_TOUCH_SAMPLING_STATE_START); From a4a4c1af34ac0c5e74dbb3b444c22a2e410fbcf3 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Mon, 9 Dec 2024 12:12:23 +0100 Subject: [PATCH 21/26] Server: remove old includes in module --- server/module/src/main.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/server/module/src/main.c b/server/module/src/main.c index ebf6dde..a113572 100644 --- a/server/module/src/main.c +++ b/server/module/src/main.c @@ -1,14 +1,3 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include @@ -17,11 +6,6 @@ #include #include -#include -#include -#include -#include - #include "kctrl-kernel.h" // missing in vitasdk From b3e59c33488508782197f004fd1ff4097ca54226 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Mon, 9 Dec 2024 12:13:45 +0100 Subject: [PATCH 22/26] Server: added module version check in app --- server/include/draw_helper.hpp | 1 + server/module/include/kctrl-kernel.h | 3 +++ server/module/kctrl.yml | 1 + server/module/src/main.c | 2 ++ server/src/draw_helper.cpp | 5 +++++ server/src/main.cpp | 11 +++++++++++ 6 files changed, 23 insertions(+) diff --git a/server/include/draw_helper.hpp b/server/include/draw_helper.hpp index c37af72..fe3ddd1 100644 --- a/server/include/draw_helper.hpp +++ b/server/include/draw_helper.hpp @@ -12,6 +12,7 @@ extern uint32_t error_color; extern uint32_t done_color; void draw_rectangle_outline(float x, float y, float width, float height, uint32_t color); +void draw_old_module(); void draw_start_mode(bool connected_to_network, bool pc_connect_state, char *vita_ip, SharedData *shared_data); void draw_pad_mode(bool connected_to_network, bool pc_connect_state, char *vita_ip, diff --git a/server/module/include/kctrl-kernel.h b/server/module/include/kctrl-kernel.h index 392a022..3bd3ace 100644 --- a/server/module/include/kctrl-kernel.h +++ b/server/module/include/kctrl-kernel.h @@ -7,10 +7,13 @@ extern "C" { #endif +#define KCTRL_MODULE_API 1 // +1, if module changed + void kctrlScreenOn(void); void kctrlScreenOff(void); void kctrlToggleScreen(void); int kctrlGetCtrlData(int port, SceCtrlData *pad_data, int count); +uint8_t kctrlVersion(void); #ifdef __cplusplus } diff --git a/server/module/kctrl.yml b/server/module/kctrl.yml index 75e1a87..10228fb 100644 --- a/server/module/kctrl.yml +++ b/server/module/kctrl.yml @@ -14,3 +14,4 @@ kctrl: - kctrlScreenOff - kctrlToggleScreen - kctrlGetCtrlData + - kctrlVersion diff --git a/server/module/src/main.c b/server/module/src/main.c index a113572..cf4e603 100644 --- a/server/module/src/main.c +++ b/server/module/src/main.c @@ -77,6 +77,8 @@ int kctrlGetCtrlData(int port, SceCtrlData *pad_data, int count) { return res; } +uint8_t kctrlVersion() { return KCTRL_MODULE_API; } + void _start() __attribute__((weak, alias("module_start"))); int module_start(SceSize args, const void *argp) { if (ksceKernelSearchModuleByName("SceLcd") >= 0) { diff --git a/server/src/draw_helper.cpp b/server/src/draw_helper.cpp index 0175499..70feea6 100644 --- a/server/src/draw_helper.cpp +++ b/server/src/draw_helper.cpp @@ -18,6 +18,11 @@ void draw_rectangle_outline(float x, float y, float width, float height, uint32_ vita2d_draw_line(x, y + height, x, y, color); } +void draw_old_module() { + vita2d_pgf_draw_text(debug_font, 50, screen_height / 2, error_color, 2.0, + "Wrong module version detected.\nPlease reboot your console"); +} + void draw_start_mode(bool connected_to_network, bool pc_connect_state, char *vita_ip, SharedData *shared_data) { float offset = 40; diff --git a/server/src/main.cpp b/server/src/main.cpp index 34d4460..222ee7c 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -120,6 +120,17 @@ int main() { events = 0; bool exit_state = true; + if (kctrlVersion() != KCTRL_MODULE_API) { + vita2d_start_drawing(); + vita2d_clear_screen(); + draw_old_module(); + vita2d_end_drawing(); + vita2d_wait_rendering_done(); + vita2d_swap_buffers(); + sceKernelDelayThread(10 * 1000 * 1000); + exit_state = false; + } + while (exit_state) { auto frame_start = std::chrono::high_resolution_clock::now(); sceKernelPollEventFlag(ev_flag, 0xFFFFFFFF, SCE_EVENT_WAITOR | SCE_EVENT_WAITCLEAR, &events); From 1b3ebebb05ab7500480ac5dbdb1bb31dfc42c312 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Mon, 9 Dec 2024 12:14:30 +0100 Subject: [PATCH 23/26] Server: wait 1s for receiving first SceCtrlData data --- server/src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/main.cpp b/server/src/main.cpp index 222ee7c..f2df4ab 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -108,6 +108,7 @@ int main() { if (net_thread_uid < 0) { return -1; } + sceKernelDelayThread(1 * 1000 * 1000); // wait for the first SceCtrlData data to be received uint32_t events; sceNetCtlInetGetState(reinterpret_cast(&events)); From 7fde37a86c65d269b1142ac003368231c5cd7d0a Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Mon, 9 Dec 2024 18:49:19 +0100 Subject: [PATCH 24/26] Server: fixed sceCtrlSetSamplingMode param --- server/module/src/main.c | 1 + server/src/main.cpp | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/module/src/main.c b/server/module/src/main.c index cf4e603..0dfd2be 100644 --- a/server/module/src/main.c +++ b/server/module/src/main.c @@ -81,6 +81,7 @@ uint8_t kctrlVersion() { return KCTRL_MODULE_API; } void _start() __attribute__((weak, alias("module_start"))); int module_start(SceSize args, const void *argp) { + ksceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG_WIDE); if (ksceKernelSearchModuleByName("SceLcd") >= 0) { g_is_lcd = 1; } else if (ksceKernelSearchModuleByName("SceOled") >= 0) { diff --git a/server/src/main.cpp b/server/src/main.cpp index f2df4ab..d6fd657 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -41,8 +41,7 @@ int main() { } // Enabling analog, motion and touch support - sceCtrlSetButtonIntercept(1); - sceCtrlSetSamplingMode(SCE_CTRL_MODE_DIGITAL); + sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG_WIDE); sceMotionStartSampling(); sceTouchSetSamplingState(SCE_TOUCH_PORT_FRONT, SCE_TOUCH_SAMPLING_STATE_START); sceTouchSetSamplingState(SCE_TOUCH_PORT_BACK, SCE_TOUCH_SAMPLING_STATE_START); From d97b9d0c81eb7a0e6bd99646992214b37562c093 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Mon, 9 Dec 2024 22:41:10 +0100 Subject: [PATCH 25/26] Client: improved trigers power logic for Windows client --- .../vita_virtual_device/src/windows.rs | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/client/packages/vita_virtual_device/src/windows.rs b/client/packages/vita_virtual_device/src/windows.rs index ad35b6a..2583e57 100644 --- a/client/packages/vita_virtual_device/src/windows.rs +++ b/client/packages/vita_virtual_device/src/windows.rs @@ -12,7 +12,7 @@ use windows::Win32::UI::Input::KeyboardAndMouse::{ }; use crate::virtual_button::{Button, DpadDirection}; -use crate::virtual_config::{Config, ConfigBuilder, TouchConfig, TriggerConfig}; +use crate::virtual_config::{Config, ConfigBuilder, TouchConfig}; use crate::virtual_touch::{Point, TouchAction}; use crate::virtual_utils::{compute_dpad_direction, get_pressed_buttons}; use crate::{f32_to_i16, VitaVirtualDevice, FRONT_TOUCHPAD_RECT, REAR_TOUCHPAD_RECT}; @@ -270,24 +270,12 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { &self.config.front_touch_config, &mut buttons, ); - process_touch_reports( &report.back_touch.reports, &self.config.rear_touch_config, &mut buttons, ); - // Trigger processing for Trigger configuration - let (mut pwr_trigger_l, mut pwr_trigger_r) = (0u8, 0u8); - if let TriggerConfig::Trigger = self.config.trigger_config { - if report.buttons.lt { - pwr_trigger_l = 255; - } - if report.buttons.rt { - pwr_trigger_r = 255; - } - } - // Handling special touchpad buttons let is_touching = match ( &self.config.front_touch_config, @@ -300,6 +288,7 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { let mut special_buttons = DS4SpecialButtons::new(); + // Touch click emulation if is_touching && !self.touch_state { self.touch_start_time = Some(Instant::now()); } else if !is_touching && self.touch_state { @@ -327,6 +316,20 @@ impl VitaVirtualDevice<&ConfigBuilder> for VitaDevice { let gyro_y_i16 = f32_to_i16(-report.motion.gyro.y, -35.0, 35.0); //inverted let gyro_z_i16 = f32_to_i16(report.motion.gyro.z, -35.0, 35.0); + // Trigger processing for Trigger configuration + let (pwr_trigger_l, pwr_trigger_r) = ( + if buttons | DS4Buttons::TRIGGER_LEFT == buttons { + 255 + } else { + 0 + }, + if buttons | DS4Buttons::TRIGGER_RIGHT == buttons { + 255 + } else { + 0 + }, + ); + let report = DS4ReportExBuilder::new() .thumb_lx(report.lx) .thumb_ly(report.ly) From b35d55657c700498ddb72e31e0986da3c38be131 Mon Sep 17 00:00:00 2001 From: DvaMishkiLapa Date: Sun, 15 Dec 2024 20:19:34 +0100 Subject: [PATCH 26/26] Client: added PS Button support for Linux Client --- client/packages/vita_virtual_device/src/linux.rs | 2 ++ client/packages/vita_virtual_device/src/virtual_button.rs | 1 + client/packages/vita_virtual_device/src/virtual_utils.rs | 1 + client/packages/vita_virtual_device/src/windows.rs | 1 + 4 files changed, 5 insertions(+) diff --git a/client/packages/vita_virtual_device/src/linux.rs b/client/packages/vita_virtual_device/src/linux.rs index 49e1982..d556b7d 100644 --- a/client/packages/vita_virtual_device/src/linux.rs +++ b/client/packages/vita_virtual_device/src/linux.rs @@ -62,6 +62,7 @@ fn map_button_to_ds4(button: Button) -> Key { Button::Circle => Key::ButtonEast, Button::Cross => Key::ButtonSouth, Button::Square => Key::ButtonWest, + Button::PSButton => Key::ButtonMode, } } @@ -144,6 +145,7 @@ impl VitaDevice { Button::Circle, Button::Cross, Button::Square, + Button::PSButton, ] { main_handle.set_keybit(map_button_to_ds4(button))?; } diff --git a/client/packages/vita_virtual_device/src/virtual_button.rs b/client/packages/vita_virtual_device/src/virtual_button.rs index 335c734..59622b4 100644 --- a/client/packages/vita_virtual_device/src/virtual_button.rs +++ b/client/packages/vita_virtual_device/src/virtual_button.rs @@ -14,6 +14,7 @@ pub enum Button { Circle, Cross, Square, + PSButton, } #[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)] diff --git a/client/packages/vita_virtual_device/src/virtual_utils.rs b/client/packages/vita_virtual_device/src/virtual_utils.rs index 6555439..6db891f 100644 --- a/client/packages/vita_virtual_device/src/virtual_utils.rs +++ b/client/packages/vita_virtual_device/src/virtual_utils.rs @@ -29,6 +29,7 @@ pub fn get_pressed_buttons( (report_buttons.triangle, Button::Triangle), (report_buttons.start, Button::Options), (report_buttons.select, Button::Share), + (report_buttons.ps, Button::PSButton), ]; // Trigger processing depending on the configuration diff --git a/client/packages/vita_virtual_device/src/windows.rs b/client/packages/vita_virtual_device/src/windows.rs index 9bb0f77..3de4b46 100644 --- a/client/packages/vita_virtual_device/src/windows.rs +++ b/client/packages/vita_virtual_device/src/windows.rs @@ -90,6 +90,7 @@ fn map_button_to_ds4(button: Button) -> u16 { Button::Circle => DS4Buttons::CIRCLE, Button::Cross => DS4Buttons::CROSS, Button::Square => DS4Buttons::SQUARE, + Button::PSButton => DS4SpecialButtons::PS_HOME as u16, // Doesn't really work, added for compatibility between platforms } }