Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #11070 from AdmiralCurtiss/netplay-wiimotes
Netplay: Redesign Wiimote data exchange.
  • Loading branch information
JMC47 committed Oct 2, 2022
2 parents 15393f0 + e137f7f commit 23806f8
Show file tree
Hide file tree
Showing 52 changed files with 1,280 additions and 420 deletions.
3 changes: 3 additions & 0 deletions Source/Core/Core/CMakeLists.txt
Expand Up @@ -279,13 +279,16 @@ add_library(core
HW/WiimoteCommon/WiimoteReport.h
HW/WiimoteEmu/Camera.cpp
HW/WiimoteEmu/Camera.h
HW/WiimoteEmu/DesiredWiimoteState.cpp
HW/WiimoteEmu/DesiredWiimoteState.h
HW/WiimoteEmu/Dynamics.cpp
HW/WiimoteEmu/Dynamics.h
HW/WiimoteEmu/EmuSubroutines.cpp
HW/WiimoteEmu/Encryption.cpp
HW/WiimoteEmu/Encryption.h
HW/WiimoteEmu/Extension/Classic.cpp
HW/WiimoteEmu/Extension/Classic.h
HW/WiimoteEmu/Extension/DesiredExtensionState.h
HW/WiimoteEmu/Extension/DrawsomeTablet.cpp
HW/WiimoteEmu/Extension/DrawsomeTablet.h
HW/WiimoteEmu/Extension/Drums.cpp
Expand Down
3 changes: 0 additions & 3 deletions Source/Core/Core/Core.cpp
Expand Up @@ -498,9 +498,6 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
if (core_parameter.bWii && !Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_ENABLED))
{
Wiimote::LoadConfig();

if (NetPlay::IsNetPlayRunning())
NetPlay::SetupWiimotes();
}

FreeLook::LoadInputConfig();
Expand Down
2 changes: 0 additions & 2 deletions Source/Core/Core/HW/Wiimote.h
Expand Up @@ -94,8 +94,6 @@ ControllerEmu::ControlGroup* GetDrawsomeTabletGroup(int number,
WiimoteEmu::DrawsomeTabletGroup group);
ControllerEmu::ControlGroup* GetTaTaConGroup(int number, WiimoteEmu::TaTaConGroup group);
ControllerEmu::ControlGroup* GetShinkansenGroup(int number, WiimoteEmu::ShinkansenGroup group);

bool NetPlay_GetButtonPress(int wiimote, bool pressed);
} // namespace Wiimote

namespace WiimoteReal
Expand Down
17 changes: 14 additions & 3 deletions Source/Core/Core/HW/WiimoteCommon/WiimoteHid.h
Expand Up @@ -7,6 +7,11 @@
#include "Core/HW/WiimoteCommon/WiimoteConstants.h"
#include "Core/HW/WiimoteCommon/WiimoteReport.h"

namespace WiimoteEmu
{
struct DesiredWiimoteState;
}

namespace WiimoteCommon
{
// Source: HID_010_SPC_PFL/1.0 (official HID specification)
Expand All @@ -30,17 +35,23 @@ class HIDWiimote
virtual void EventLinked() = 0;
virtual void EventUnlinked() = 0;

virtual u8 GetWiimoteDeviceIndex() const = 0;
virtual void SetWiimoteDeviceIndex(u8 index) = 0;

// Called every ~200hz after HID channels are established.
virtual void Update() = 0;
virtual void PrepareInput(WiimoteEmu::DesiredWiimoteState* target_state) = 0;
virtual void Update(const WiimoteEmu::DesiredWiimoteState& target_state) = 0;

void SetInterruptCallback(InterruptCallbackType callback) { m_callback = std::move(callback); }

// HID report type:0xa2 (data output) payloads sent to the wiimote interrupt channel.
// Does not include HID-type header.
virtual void InterruptDataOutput(const u8* data, u32 size) = 0;

// Used to connect a disconnected wii remote on button press.
virtual bool IsButtonPressed() = 0;
// Get a snapshot of the current state of the Wiimote's buttons.
// Note that only the button bits of the return value are meaningful, the rest should be ignored.
// This is used to query a disconnected Wiimote whether it wants to reconnect.
virtual ButtonData GetCurrentlyPressedButtons() = 0;

protected:
void InterruptDataInputCallback(const u8* data, u32 size)
Expand Down
57 changes: 24 additions & 33 deletions Source/Core/Core/HW/WiimoteEmu/Camera.cpp
Expand Up @@ -52,36 +52,14 @@ int CameraLogic::BusWrite(u8 slave_addr, u8 addr, int count, const u8* data_in)
return RawWrite(&m_reg_data, addr, count, data_in);
}

void CameraLogic::Update(const Common::Matrix44& transform, Common::Vec2 field_of_view)
std::array<CameraPoint, CameraLogic::NUM_POINTS>
CameraLogic::GetCameraPoints(const Common::Matrix44& transform, Common::Vec2 field_of_view)
{
// IR data is read from offset 0x37 on real hardware.
auto& data = m_reg_data.camera_data;
data.fill(0xff);

constexpr u8 OBJECT_TRACKING_ENABLE = 0x08;

// If Address 0x30 is not 0x08 the camera will return 0xFFs.
// The Wii seems to write 0x01 here before changing modes/sensitivities.
if (m_reg_data.enable_object_tracking != OBJECT_TRACKING_ENABLE)
return;

// If the sensor bar is off the camera will see no LEDs and return 0xFFs.
if (!IOS::g_gpio_out[IOS::GPIO::SENSOR_BAR])
return;

using Common::Matrix33;
using Common::Matrix44;
using Common::Vec3;
using Common::Vec4;

// FYI: A real wiimote normally only returns 1 point for each LED cluster (2 total).
// Sending all 4 points can actually cause some stuttering issues.
constexpr int NUM_POINTS = 2;

// Range from 0-15. Small values (2-4) seem to be very typical.
// This is reduced based on distance from sensor bar.
constexpr int MAX_POINT_SIZE = 15;

const std::array<Vec3, NUM_POINTS> leds{
Vec3{-SENSOR_BAR_LED_SEPARATION / 2, 0, 0},
Vec3{SENSOR_BAR_LED_SEPARATION / 2, 0, 0},
Expand All @@ -91,12 +69,6 @@ void CameraLogic::Update(const Common::Matrix44& transform, Common::Vec2 field_o
Matrix44::Perspective(field_of_view.y, field_of_view.x / field_of_view.y, 0.001f, 1000) *
Matrix44::FromMatrix33(Matrix33::RotateX(float(MathUtil::TAU / 4))) * transform;

struct CameraPoint
{
IRBasic::IRObject position;
u8 size = 0;
};

std::array<CameraPoint, leds.size()> camera_points;

std::transform(leds.begin(), leds.end(), camera_points.begin(), [&](const Vec3& v) {
Expand All @@ -112,13 +84,32 @@ void CameraLogic::Update(const Common::Matrix44& transform, Common::Vec2 field_o
const auto point_size = std::lround(MAX_POINT_SIZE / point.w / 2);

if (x >= 0 && y >= 0 && x < CAMERA_RES_X && y < CAMERA_RES_Y)
return CameraPoint{{u16(x), u16(y)}, u8(point_size)};
return CameraPoint({u16(x), u16(y)}, u8(point_size));
}

// 0xFFFFs are interpreted as "not visible".
return CameraPoint{{0xffff, 0xffff}, 0xff};
return CameraPoint();
});

return camera_points;
}

void CameraLogic::Update(const std::array<CameraPoint, NUM_POINTS>& camera_points)
{
// IR data is read from offset 0x37 on real hardware.
auto& data = m_reg_data.camera_data;
data.fill(0xff);

constexpr u8 OBJECT_TRACKING_ENABLE = 0x08;

// If Address 0x30 is not 0x08 the camera will return 0xFFs.
// The Wii seems to write 0x01 here before changing modes/sensitivities.
if (m_reg_data.enable_object_tracking != OBJECT_TRACKING_ENABLE)
return;

// If the sensor bar is off the camera will see no LEDs and return 0xFFs.
if (!IOS::g_gpio_out[IOS::GPIO::SENSOR_BAR])
return;

switch (m_reg_data.mode)
{
case IR_MODE_BASIC:
Expand Down
35 changes: 30 additions & 5 deletions Source/Core/Core/HW/WiimoteEmu/Camera.h
Expand Up @@ -16,11 +16,26 @@ class Matrix44;

namespace WiimoteEmu
{
using IRObject = Common::TVec2<u16>;

struct CameraPoint
{
IRObject position;
u8 size;

// 0xFFFFs are interpreted as "not visible".
constexpr CameraPoint() : position({0xffff, 0xffff}), size(0xff) {}
constexpr CameraPoint(IRObject position_, u8 size_) : position(position_), size(size_) {}
constexpr bool operator==(const CameraPoint& other) const
{
return this->position == other.position && this->size == other.size;
}
constexpr bool operator!=(const CameraPoint& other) const { return !(*this == other); }
};

// Four bytes for two objects. Filled with 0xFF if empty
struct IRBasic
{
using IRObject = Common::TVec2<u16>;

u8 x1;
u8 y1;
u8 x2hi : 2;
Expand Down Expand Up @@ -59,8 +74,8 @@ struct IRExtended
u8 xhi : 2;
u8 yhi : 2;

auto GetPosition() const { return IRBasic::IRObject(xhi << 8 | x, yhi << 8 | y); }
void SetPosition(const IRBasic::IRObject& obj)
auto GetPosition() const { return IRObject(xhi << 8 | x, yhi << 8 | y); }
void SetPosition(const IRObject& obj)
{
x = obj.x;
xhi = obj.x >> 8;
Expand Down Expand Up @@ -109,9 +124,19 @@ class CameraLogic : public I2CSlave
IR_MODE_FULL = 5,
};

// FYI: A real wiimote normally only returns 1 point for each LED cluster (2 total).
// Sending all 4 points can actually cause some stuttering issues.
static constexpr int NUM_POINTS = 2;

// Range from 0-15. Small values (2-4) seem to be very typical.
// This is reduced based on distance from sensor bar.
static constexpr int MAX_POINT_SIZE = 15;

void Reset();
void DoState(PointerWrap& p);
void Update(const Common::Matrix44& transform, Common::Vec2 field_of_view);
static std::array<CameraPoint, NUM_POINTS> GetCameraPoints(const Common::Matrix44& transform,
Common::Vec2 field_of_view);
void Update(const std::array<CameraPoint, NUM_POINTS>& camera_points);
void SetEnabled(bool is_enabled);

static constexpr u8 I2C_ADDR = 0x58;
Expand Down

0 comments on commit 23806f8

Please sign in to comment.