mirror of
https://github.com/jessicanataliagta/PSPRecomp
synced 2026-09-26 16:49:34 -04:00
37e5469cbd
initial release
76 lines
2.6 KiB
C++
76 lines
2.6 KiB
C++
#include "vcs_vehicle_input.hpp"
|
|
|
|
#include "vcs_config.hpp"
|
|
|
|
#include <atomic>
|
|
|
|
namespace vcs {
|
|
namespace {
|
|
|
|
// CPad layout, from ThirteenAG's struct: two bytes of padding, then
|
|
// CControllerState as sixteen-bit fields in a fixed order. Confirmed against
|
|
// the disassembly -- the stock accelerator loads 0x2A and the stock brake loads
|
|
// 0x26, which is exactly where CROSS and SQUARE land.
|
|
constexpr std::uint32_t kPadCross = 0x2Au;
|
|
constexpr std::uint32_t kPadSquare = 0x26u;
|
|
constexpr std::uint32_t kPadRightShoulder1 = 0x0Eu;
|
|
constexpr std::uint32_t kPadLeftShoulder1 = 0x0Au;
|
|
|
|
std::atomic<bool> g_accelerate{false};
|
|
std::atomic<bool> g_brake{false};
|
|
|
|
// Counts reads of the vehicle control accessors; see vcs_player_in_vehicle.
|
|
std::atomic<std::uint64_t> g_vehicle_reads{0u};
|
|
|
|
// Roughly a third of a second at 60 Hz. Long enough to bridge the gap between
|
|
// the guest's pad poll and the host's, short enough that stepping off a bike
|
|
// gives the on-foot mapping back before the player can notice.
|
|
constexpr std::uint64_t kVehicleHoldPolls = 20u;
|
|
|
|
} // namespace
|
|
|
|
bool vcs_modern_control_scheme_enabled() noexcept {
|
|
static const bool value = [] {
|
|
const VcsConfiguration &config = vcs_configuration();
|
|
return config.initialized && config.controls.modern_control_scheme;
|
|
}();
|
|
return value;
|
|
}
|
|
|
|
std::uint32_t vcs_accelerate_pad_offset() noexcept {
|
|
return vcs_modern_control_scheme_enabled() ? kPadRightShoulder1 : kPadCross;
|
|
}
|
|
|
|
std::uint32_t vcs_brake_pad_offset() noexcept {
|
|
return vcs_modern_control_scheme_enabled() ? kPadLeftShoulder1 : kPadSquare;
|
|
}
|
|
|
|
bool vcs_host_accelerate() noexcept { return g_accelerate.load(std::memory_order_relaxed); }
|
|
bool vcs_host_brake() noexcept { return g_brake.load(std::memory_order_relaxed); }
|
|
|
|
void vcs_set_host_drive_inputs(bool accelerate, bool brake) noexcept {
|
|
g_accelerate.store(accelerate, std::memory_order_relaxed);
|
|
g_brake.store(brake, std::memory_order_relaxed);
|
|
}
|
|
|
|
void vcs_note_vehicle_control_read() noexcept {
|
|
g_vehicle_reads.fetch_add(1u, std::memory_order_relaxed);
|
|
}
|
|
|
|
bool vcs_player_in_vehicle() noexcept {
|
|
// Called from the input poll, so the poll itself is the clock: remember the
|
|
// count and how many polls ago it last moved.
|
|
static std::uint64_t last_seen = 0u;
|
|
static std::uint64_t quiet_polls = kVehicleHoldPolls;
|
|
const std::uint64_t reads = g_vehicle_reads.load(std::memory_order_relaxed);
|
|
if (reads != last_seen) {
|
|
last_seen = reads;
|
|
quiet_polls = 0u;
|
|
} else if (quiet_polls < kVehicleHoldPolls) {
|
|
++quiet_polls;
|
|
}
|
|
return quiet_polls < kVehicleHoldPolls;
|
|
}
|
|
|
|
} // namespace vcs
|