mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-18 23:07:07 -05:00
feat(pad): touch the left or right touchpad half from the input command file
APS5_PAD_INPUT_FILE commands can set bit 0x200000 or 0x400000 to put a finger on the left or right half of the touchpad, as the TouchLeft and TouchRight keys do, so scripted runs can press touchpad combinations. tools/pad_input.py queues them as touch-left and touch-right. AI-assisted: yes
This commit is contained in:
1 parent
20a84154ff
commit
a9377e34ba
6 files changed
+45
-8
No files matched your search
@@ -16,6 +16,8 @@ public:
|
||||
std::uint32_t buttons = 0;
|
||||
bool hasSticks = false;
|
||||
std::array<std::uint8_t, 4> sticks{};
|
||||
bool touchLeft = false;
|
||||
bool touchRight = false;
|
||||
|
||||
bool operator==(const Input&) const = default;
|
||||
};
|
||||
@@ -65,10 +67,12 @@ private:
|
||||
const auto parsed = std::from_chars(first, last, values[i]);
|
||||
if (first == last || parsed.ec != std::errc{} || parsed.ptr != last) return {};
|
||||
}
|
||||
if (values[0] == 0 || (values[1] & ~0x10fffeull) != 0 || values[2] == 0 || values[2] > 5000) return {};
|
||||
if (values[0] == 0 || (values[1] & ~(0x10fffeull | TouchLeftBit | TouchRightBit)) != 0 || values[2] == 0 || values[2] > 5000) return {};
|
||||
Command command;
|
||||
command.sequence = values[0];
|
||||
command.input.buttons = static_cast<std::uint32_t>(values[1]);
|
||||
command.input.buttons = static_cast<std::uint32_t>(values[1] & 0x10fffeull);
|
||||
command.input.touchLeft = (values[1] & TouchLeftBit) != 0;
|
||||
command.input.touchRight = (values[1] & TouchRightBit) != 0;
|
||||
command.durationMs = static_cast<std::uint32_t>(values[2]);
|
||||
for (int i = 3; i < count; ++i) {
|
||||
if (values[i] > 255) return {};
|
||||
@@ -78,6 +82,9 @@ private:
|
||||
return command;
|
||||
}
|
||||
|
||||
static constexpr std::uint64_t TouchLeftBit = 0x200000;
|
||||
static constexpr std::uint64_t TouchRightBit = 0x400000;
|
||||
|
||||
std::filesystem::path path;
|
||||
std::uint64_t lastSequence = 0;
|
||||
std::uint64_t nextPoll = 0;
|
||||
|
||||
@@ -179,10 +179,10 @@ PadData BuildData(const PadInputState& state, std::uint64_t changeTime, std::uin
|
||||
}
|
||||
++touchNum;
|
||||
}
|
||||
if (touchNum == 0 && (state.touchLeft || state.touchRight)) {
|
||||
if (touchNum == 0 && (state.touchLeft || state.touchRight || injected.touchLeft || injected.touchRight)) {
|
||||
data.buttons |= 0x100000;
|
||||
touchNum = 1;
|
||||
data.touch_data_touch0_x = state.touchRight ? 1440 : 480;
|
||||
data.touch_data_touch0_x = state.touchRight || injected.touchRight ? 1440 : 480;
|
||||
data.touch_data_touch0_y = 471;
|
||||
data.touch_data_touch0_id = 0;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
extern "C" {
|
||||
int APS5_VABI scePadOpen_nid_postfix(int, int, int, const void*);
|
||||
@@ -96,8 +97,16 @@ static void CheckInputCommands() {
|
||||
write("7 8192 300 1 2 3 4");
|
||||
const auto accepted = commands.Poll(2601000);
|
||||
Require(accepted.buttons == 0x2000 && accepted.hasSticks && accepted.sticks[3] == 4);
|
||||
write("8 2097152 300");
|
||||
const auto left = commands.Poll(3001000);
|
||||
Require(left.buttons == 0 && left.touchLeft && !left.touchRight && !left.hasSticks);
|
||||
write("9 4210688 300");
|
||||
const auto right = commands.Poll(3401000);
|
||||
Require(right.buttons == 0x4000 && !right.touchLeft && right.touchRight);
|
||||
write("10 8388608 300");
|
||||
Require(commands.Poll(3801000) == none);
|
||||
std::filesystem::remove(path);
|
||||
Require(commands.Buttons(3001000) == 0);
|
||||
Require(commands.Buttons(4201000) == 0);
|
||||
Pad::InputCommandFile disabled(std::filesystem::path{});
|
||||
Require(disabled.Buttons(0) == 0);
|
||||
}
|
||||
@@ -248,6 +257,21 @@ static void CheckInjectedState(const std::filesystem::path& path) {
|
||||
const auto centred = Pad::ReadState();
|
||||
Require(centred.left_stick_x == 42 && centred.right_stick_y == 17);
|
||||
Require(centred.timestamp > moved.timestamp);
|
||||
for (const auto& [command, x] : {std::pair{"3 2097152 300\n", 480}, std::pair{"4 4194304 300\n", 1440}}) {
|
||||
std::ofstream(path) << command;
|
||||
PadData touched{};
|
||||
const auto touchDeadline = std::chrono::steady_clock::now() + std::chrono::seconds(2);
|
||||
do {
|
||||
touched = Pad::ReadState();
|
||||
if (touched.touch_data_touch_num != 0) break;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
} while (std::chrono::steady_clock::now() < touchDeadline);
|
||||
Require(touched.touch_data_touch_num == 1 && touched.touch_data_touch0_x == x && touched.touch_data_touch0_y == 471);
|
||||
Require(touched.buttons == (0x2000 | 0x100000));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(310));
|
||||
const auto lifted = Pad::ReadState();
|
||||
Require(lifted.touch_data_touch_num == 0 && lifted.buttons == 0x2000);
|
||||
}
|
||||
PadPublishInput_nid_postfix(PadInputState{});
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -144,9 +144,10 @@ python3 tools/pad_input.py /tmp/anyps5-pad down --hold-ms 500
|
||||
python3 tools/pad_input.py /tmp/anyps5-pad release
|
||||
python3 tools/pad_input.py /tmp/anyps5-pad release --left-stick 128 0 --hold-ms 2000
|
||||
python3 tools/pad_input.py /tmp/anyps5-pad cross --left-stick 255 128 --right-stick 0 128
|
||||
python3 tools/pad_input.py /tmp/anyps5-pad touch-right
|
||||
```
|
||||
|
||||
Run the helper in a second terminal. Commands are polled at most every 100 ms during controller reads, and their buttons add to physical controller input. A press lasts 300 ms by default, starting when the application reads it, and releases automatically; `--hold-ms` accepts 1–5000 ms. `--left-stick X Y` and `--right-stick X Y` hold the sticks for the same time: each axis is 0-255, 128 is the centre, X grows to the right and Y grows downward. While such a command is active both sticks come from it instead of the physical controller, and a stick that was not named stays centred. Wait for the application to observe a release before sending another press. The file holds only the latest command; rapid commands can replace one another. On POSIX, replacing an existing command file retains its permission mode; a privileged helper also retains its owner and group so the game user can still read it. Commands left over when the application first reads the controller are ignored. Without the environment variable, file input is disabled.
|
||||
Run the helper in a second terminal. Commands are polled at most every 100 ms during controller reads, and their buttons add to physical controller input. A press lasts 300 ms by default, starting when the application reads it, and releases automatically; `--hold-ms` accepts 1–5000 ms. `--left-stick X Y` and `--right-stick X Y` hold the sticks for the same time: each axis is 0-255, 128 is the centre, X grows to the right and Y grows downward. While such a command is active both sticks come from it instead of the physical controller, and a stick that was not named stays centred. `touch-left` and `touch-right` press the touchpad with a finger on its left or right half, as the `TouchLeft` and `TouchRight` keys do; in the command file they are bits `0x200000` and `0x400000` of the button field. Wait for the application to observe a release before sending another press. The file holds only the latest command; rapid commands can replace one another. On POSIX, replacing an existing command file retains its permission mode; a privileged helper also retains its owner and group so the game user can still read it. Commands left over when the application first reads the controller are ignored. Without the environment variable, file input is disabled.
|
||||
|
||||
### System fonts
|
||||
|
||||
|
||||
+3
-2
@@ -12,7 +12,8 @@ BUTTONS = {
|
||||
"up": 0x10, "right": 0x20, "down": 0x40, "left": 0x80,
|
||||
"l2": 0x100, "r2": 0x200, "l1": 0x400, "r1": 0x800,
|
||||
"triangle": 0x1000, "circle": 0x2000, "cross": 0x4000,
|
||||
"square": 0x8000, "touchpad": 0x100000, "release": 0,
|
||||
"square": 0x8000, "touchpad": 0x100000,
|
||||
"touch-left": 0x200000, "touch-right": 0x400000, "release": 0,
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +33,7 @@ def previous_sequence(path):
|
||||
values = [int(token) for token in tokens]
|
||||
if any(value > 2**64 - 1 for value in values):
|
||||
return 0
|
||||
if values[0] == 0 or values[1] & ~0x10fffe or not 1 <= values[2] <= 5000:
|
||||
if values[0] == 0 or values[1] & ~0x70fffe or not 1 <= values[2] <= 5000:
|
||||
return 0
|
||||
if any(axis > 255 for axis in values[3:]):
|
||||
return 0
|
||||
|
||||
@@ -77,6 +77,10 @@ class PadInputTests(unittest.TestCase):
|
||||
self.assertEqual(self.queue(2000, "release", "--right-stick", "0", "255"),
|
||||
[2000, 0, 300, 128, 128, 0, 255])
|
||||
|
||||
def test_touchpad_halves_queue_their_bits_and_preserve_sequence(self):
|
||||
self.assertEqual(self.queue(1000, "touch-left"), [1000, 0x200000, 300])
|
||||
self.assertEqual(self.queue(1000, "touch-right"), [1001, 0x400000, 300])
|
||||
|
||||
def test_valid_stick_command_and_unsigned_tokens_preserve_sequence(self):
|
||||
self.path.write_text("+2000 +16384 +300 +0 +255 +128 +128\n", encoding="utf-8")
|
||||
self.assertEqual(self.queue(1000, "release"), [2001, 0, 300])
|
||||
|
||||
Reference in new issue
Block a user