mirror of
https://github.com/Swordpdf/ProsperoEden.git
synced 2026-10-18 19:59:46 -05:00
63 lines
2.4 KiB
C++
63 lines
2.4 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
#pragma once
|
|
#include <atomic>
|
|
#include <cstdint>
|
|
#include <istream>
|
|
#include <optional>
|
|
#include "ps5_pad.hpp"
|
|
|
|
namespace Eden {
|
|
// Development-only file commands: "id mask duration [lx ly rx ry]" (sticks 0-255, 128 is
|
|
// centre; absent means centred). A pulse expires even if its sender disappears.
|
|
//
|
|
// A command fires once in the process: the launcher and every game session read the same file
|
|
// with a reader of their own, and a file a run left behind once ended every game its owner
|
|
// started (it held the "end game" shortcut). IgnoreExisting, called when the process starts,
|
|
// counts what is already in the file as taken.
|
|
struct DevelopmentInput {
|
|
static inline std::atomic<std::uint64_t> taken{0};
|
|
static void IgnoreExisting(std::istream& input) {
|
|
std::uint64_t id{};
|
|
if (input >> id && id > taken.load(std::memory_order_relaxed)) taken.store(id, std::memory_order_relaxed);
|
|
}
|
|
|
|
std::uint64_t sequence{}, until{};
|
|
std::uint32_t buttons{};
|
|
ps5::pad::Stick left{128, 128}, right{128, 128};
|
|
bool active{};
|
|
bool Read(std::istream& input, std::uint64_t now) {
|
|
std::uint64_t id{}, mask{}, duration{};
|
|
if (!(input >> id >> mask >> duration) || id <= taken.load(std::memory_order_relaxed) ||
|
|
(mask & ~std::uint64_t(0x10FFFF)) ||
|
|
duration == 0 || duration > 3000) return false;
|
|
unsigned lx = 128, ly = 128, rx = 128, ry = 128;
|
|
if (!(input >> lx >> ly >> rx >> ry)) {
|
|
lx = ly = rx = ry = 128;
|
|
} else if (lx > 255 || ly > 255 || rx > 255 || ry > 255) {
|
|
return false;
|
|
}
|
|
taken.store(id, std::memory_order_relaxed);
|
|
sequence = id;
|
|
buttons = static_cast<std::uint32_t>(mask);
|
|
left = {static_cast<std::uint8_t>(lx), static_cast<std::uint8_t>(ly)};
|
|
right = {static_cast<std::uint8_t>(rx), static_cast<std::uint8_t>(ry)};
|
|
until = now + duration;
|
|
active = true;
|
|
return true;
|
|
}
|
|
std::optional<ps5::pad::Data> Sample(std::uint64_t now) {
|
|
if (!active) return {};
|
|
auto sample = ps5::pad::neutral_data();
|
|
sample.connected = 1;
|
|
if (now < until) {
|
|
sample.buttons = buttons;
|
|
sample.left_stick = left;
|
|
sample.right_stick = right;
|
|
} else {
|
|
active = false; // One final neutral sample releases the pulse.
|
|
}
|
|
return sample;
|
|
}
|
|
};
|
|
}
|