Skip to content
Permalink
Browse files

WiimoteEmu: Code cleanups.

  • Loading branch information...
jordan-woyak committed Jan 5, 2019
1 parent 3945aa6 commit 9c1a8891e5e33955781b1f07abd290742644586d
Showing with 346 additions and 291 deletions.
  1. +44 −2 Source/Core/Common/BitUtils.h
  2. +32 −26 Source/Core/Core/HW/WiimoteCommon/DataReport.cpp
  3. +4 −7 Source/Core/Core/HW/WiimoteCommon/DataReport.h
  4. +33 −36 Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h
  5. +1 −1 Source/Core/Core/HW/WiimoteCommon/WiimoteHid.h
  6. +56 −45 Source/Core/Core/HW/WiimoteEmu/Camera.cpp
  7. +9 −9 Source/Core/Core/HW/WiimoteEmu/Camera.h
  8. +2 −0 Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp
  9. +4 −6 Source/Core/Core/HW/WiimoteEmu/Dynamics.h
  10. +44 −40 Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp
  11. +4 −2 Source/Core/Core/HW/WiimoteEmu/Extension/Classic.cpp
  12. +4 −2 Source/Core/Core/HW/WiimoteEmu/Extension/Drums.cpp
  13. +1 −1 Source/Core/Core/HW/WiimoteEmu/Extension/Extension.h
  14. +4 −2 Source/Core/Core/HW/WiimoteEmu/Extension/Guitar.cpp
  15. +4 −2 Source/Core/Core/HW/WiimoteEmu/Extension/Nunchuk.cpp
  16. +4 −2 Source/Core/Core/HW/WiimoteEmu/Extension/Turntable.cpp
  17. +1 −1 Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h
  18. +16 −11 Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp
  19. +3 −3 Source/Core/Core/HW/WiimoteEmu/MotionPlus.h
  20. +10 −10 Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp
  21. +5 −5 Source/Core/Core/HW/WiimoteReal/IOWin.cpp
  22. +1 −1 Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp
  23. +34 −59 Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp
  24. +1 −1 Source/Core/Core/HW/WiimoteReal/WiimoteReal.h
  25. +3 −2 Source/Core/Core/Movie.cpp
  26. +10 −2 Source/Core/Core/Movie.h
  27. +5 −6 Source/Core/Core/NetPlayClient.cpp
  28. +6 −6 Source/Core/Core/NetPlayServer.cpp
  29. +1 −1 Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.h
@@ -200,13 +200,55 @@ inline To BitCast(const From& source) noexcept
return reinterpret_cast<To&>(storage);
}

template <typename T, typename PtrType>
class BitCastPtrType
{
public:
static_assert(std::is_trivially_copyable<PtrType>(),
"BitCastPtr source type must be trivially copyable.");
static_assert(std::is_trivially_copyable<T>(),
"BitCastPtr destination type must be trivially copyable.");

explicit BitCastPtrType(PtrType* ptr) : m_ptr(ptr) {}

// Enable operator= only for pointers to non-const data
template <typename S>
inline typename std::enable_if<std::is_same<S, T>() && !std::is_const<PtrType>()>::type
operator=(const S& source)
{
std::memcpy(m_ptr, &source, sizeof(source));
}

inline operator T() const
{
T result;
std::memcpy(&result, m_ptr, sizeof(result));
return result;
}

private:
PtrType* m_ptr;
};

// Provides an aliasing-safe alternative to reinterpret_cast'ing pointers to structs
// Conversion constructor and operator= provided for a convenient syntax.
// Usage: MyStruct s = BitCastPtr<MyStruct>(some_ptr);
// BitCastPtr<MyStruct>(some_ptr) = s;
template <typename T, typename PtrType>
inline auto BitCastPtr(PtrType* ptr) noexcept -> BitCastPtrType<T, PtrType>
{
return BitCastPtrType<T, PtrType>{ptr};
}

template <typename T>
void SetBit(T& value, size_t bit_number, bool bit_value)
{
static_assert(std::is_unsigned<T>(), "SetBit is only sane on unsigned types.");

if (bit_value)
value |= (1 << bit_number);
value |= (T{1} << bit_number);
else
value &= ~(1 << bit_number);
value &= ~(T{1} << bit_number);
}

} // namespace Common
@@ -4,6 +4,7 @@

#include <cassert>

#include "Common/BitUtils.h"
#include "Core/HW/WiimoteCommon/DataReport.h"

namespace WiimoteCommon
@@ -34,19 +35,21 @@ struct IncludeCore : virtual DataReportManipulator

void GetCoreData(CoreData* result) const override
{
*result = *reinterpret_cast<const CoreData*>(data_ptr);
*result = Common::BitCastPtr<CoreData>(data_ptr);

// Remove accel LSBs.
result->hex &= CoreData::BUTTON_MASK;
}

void SetCoreData(const CoreData& new_core) override
{
auto& core = *reinterpret_cast<CoreData*>(data_ptr);
CoreData core = Common::BitCastPtr<CoreData>(data_ptr);

// Don't overwrite accel LSBs.
core.hex &= ~CoreData::BUTTON_MASK;
core.hex |= new_core.hex & CoreData::BUTTON_MASK;

Common::BitCastPtr<CoreData>(data_ptr) = core;
}
};

@@ -71,30 +74,32 @@ struct IncludeAccel : virtual DataReportManipulator
{
void GetAccelData(AccelData* result) const override
{
const auto& accel = *reinterpret_cast<AccelMSB*>(data_ptr + 2);
const AccelMSB accel = Common::BitCastPtr<AccelMSB>(data_ptr + 2);
result->x = accel.x << 2;
result->y = accel.y << 2;
result->z = accel.z << 2;

// LSBs
const auto& core = *reinterpret_cast<CoreData*>(data_ptr);
const CoreData core = Common::BitCastPtr<CoreData>(data_ptr);
result->x |= core.acc_bits & 0b11;
result->y |= (core.acc_bits2 & 0b1) << 1;
result->z |= core.acc_bits2 & 0b10;
}

void SetAccelData(const AccelData& new_accel) override
{
auto& accel = *reinterpret_cast<AccelMSB*>(data_ptr + 2);
AccelMSB accel = {};
accel.x = new_accel.x >> 2;
accel.y = new_accel.y >> 2;
accel.z = new_accel.z >> 2;
Common::BitCastPtr<AccelMSB>(data_ptr + 2) = accel;

// LSBs
auto& core = *reinterpret_cast<CoreData*>(data_ptr);
CoreData core = Common::BitCastPtr<CoreData>(data_ptr);
core.acc_bits = (new_accel.x >> 0) & 0b11;
core.acc_bits2 = (new_accel.y >> 1) & 0x1;
core.acc_bits2 |= (new_accel.z & 0xb10);
Common::BitCastPtr<CoreData>(data_ptr) = core;
}

bool HasAccel() const override { return true; }
@@ -196,20 +201,21 @@ struct ReportInterleave1 : IncludeCore, IncludeIR<3, 18, 0>, NoExt
{
accel->x = data_ptr[2] << 2;

// Retain lower 6LSBs.
// Retain lower 6 bits.
accel->z &= 0b111111;

const auto& core = *reinterpret_cast<CoreData*>(data_ptr);
const CoreData core = Common::BitCastPtr<CoreData>(data_ptr);
accel->z |= (core.acc_bits << 6) | (core.acc_bits2 << 8);
}

void SetAccelData(const AccelData& accel) override
{
data_ptr[2] = accel.x >> 2;

auto& core = *reinterpret_cast<CoreData*>(data_ptr);
CoreData core = Common::BitCastPtr<CoreData>(data_ptr);
core.acc_bits = (accel.z >> 6) & 0b11;
core.acc_bits2 = (accel.z >> 8) & 0b11;
Common::BitCastPtr<CoreData>(data_ptr) = core;
}

bool HasAccel() const override { return true; }
@@ -226,20 +232,21 @@ struct ReportInterleave2 : IncludeCore, IncludeIR<3, 18, 18>, NoExt
{
accel->y = data_ptr[2] << 2;

// Retain upper 4MSBs.
// Retain upper 4 bits.
accel->z &= ~0b111111;

const auto& core = *reinterpret_cast<CoreData*>(data_ptr);
const CoreData core = Common::BitCastPtr<CoreData>(data_ptr);
accel->z |= (core.acc_bits << 2) | (core.acc_bits2 << 4);
}

void SetAccelData(const AccelData& accel) override
{
data_ptr[2] = accel.y >> 2;

auto& core = *reinterpret_cast<CoreData*>(data_ptr);
CoreData core = Common::BitCastPtr<CoreData>(data_ptr);
core.acc_bits = (accel.z >> 2) & 0b11;
core.acc_bits2 = (accel.z >> 4) & 0b11;
Common::BitCastPtr<CoreData>(data_ptr) = core;
}

bool HasAccel() const override { return true; }
@@ -257,47 +264,47 @@ std::unique_ptr<DataReportManipulator> MakeDataReportManipulator(InputReportID r

switch (rpt_id)
{
case InputReportID::REPORT_CORE:
case InputReportID::ReportCore:
// 0x30: Core Buttons
ptr = std::make_unique<ReportCore>();
break;
case InputReportID::REPORT_CORE_ACCEL:
case InputReportID::ReportCoreAccel:
// 0x31: Core Buttons and Accelerometer
ptr = std::make_unique<ReportCoreAccel>();
break;
case InputReportID::REPORT_CORE_EXT8:
case InputReportID::ReportCoreExt8:
// 0x32: Core Buttons with 8 Extension bytes
ptr = std::make_unique<ReportCoreExt8>();
break;
case InputReportID::REPORT_CORE_ACCEL_IR12:
case InputReportID::ReportCoreAccelIR12:
// 0x33: Core Buttons and Accelerometer with 12 IR bytes
ptr = std::make_unique<ReportCoreAccelIR12>();
break;
case InputReportID::REPORT_CORE_EXT19:
case InputReportID::ReportCoreExt19:
// 0x34: Core Buttons with 19 Extension bytes
ptr = std::make_unique<ReportCoreExt19>();
break;
case InputReportID::REPORT_CORE_ACCEL_EXT16:
case InputReportID::ReportCoreAccelExt16:
// 0x35: Core Buttons and Accelerometer with 16 Extension Bytes
ptr = std::make_unique<ReportCoreAccelExt16>();
break;
case InputReportID::REPORT_CORE_IR10_EXT9:
case InputReportID::ReportCoreIR10Ext9:
// 0x36: Core Buttons with 10 IR bytes and 9 Extension Bytes
ptr = std::make_unique<ReportCoreIR10Ext9>();
break;
case InputReportID::REPORT_CORE_ACCEL_IR10_EXT6:
case InputReportID::ReportCoreAccelIR10Ext6:
// 0x37: Core Buttons and Accelerometer with 10 IR bytes and 6 Extension Bytes
ptr = std::make_unique<ReportCoreAccelIR10Ext6>();
break;
case InputReportID::REPORT_EXT21:
case InputReportID::ReportExt21:
// 0x3d: 21 Extension Bytes
ptr = std::make_unique<ReportExt21>();
break;
case InputReportID::REPORT_INTERLEAVE1:
case InputReportID::ReportInterleave1:
// 0x3e - 0x3f: Interleaved Core Buttons and Accelerometer with 36 IR bytes
ptr = std::make_unique<ReportInterleave1>();
break;
case InputReportID::REPORT_INTERLEAVE2:
case InputReportID::ReportInterleave2:
ptr = std::make_unique<ReportInterleave2>();
break;
default:
@@ -327,9 +334,8 @@ InputReportID DataReportBuilder::GetMode() const

bool DataReportBuilder::IsValidMode(InputReportID mode)
{
return (mode >= InputReportID::REPORT_CORE &&
mode <= InputReportID::REPORT_CORE_ACCEL_IR10_EXT6) ||
(mode >= InputReportID::REPORT_EXT21 && InputReportID::REPORT_INTERLEAVE2 <= mode);
return (mode >= InputReportID::ReportCore && mode <= InputReportID::ReportCoreAccelIR10Ext6) ||
(mode >= InputReportID::ReportExt21 && InputReportID::ReportInterleave2 <= mode);
}

bool DataReportBuilder::HasCore() const
@@ -27,7 +27,7 @@ class DataReportManipulator
u16 x, y, z;
};

typedef ButtonData CoreData;
using CoreData = ButtonData;

virtual bool HasCore() const = 0;
virtual bool HasAccel() const = 0;
@@ -63,13 +63,10 @@ std::unique_ptr<DataReportManipulator> MakeDataReportManipulator(InputReportID r
class DataReportBuilder
{
public:
DataReportBuilder(InputReportID rpt_id);
explicit DataReportBuilder(InputReportID rpt_id);

typedef ButtonData CoreData;
typedef DataReportManipulator::AccelData AccelData;

typedef std::vector<u8> IRData;
typedef std::vector<u8> ExtData;
using CoreData = ButtonData;
using AccelData = DataReportManipulator::AccelData;

void SetMode(InputReportID rpt_id);
InputReportID GetMode() const;
@@ -12,45 +12,45 @@ constexpr u8 MAX_PAYLOAD = 23;

enum class InputReportID : u8
{
STATUS = 0x20,
READ_DATA_REPLY = 0x21,
ACK = 0x22,
Status = 0x20,
ReadDataReply = 0x21,
Ack = 0x22,

// Not a real value on the wiimote, just a state to disable reports:
REPORT_DISABLED = 0x00,
ReportDisabled = 0x00,

REPORT_CORE = 0x30,
REPORT_CORE_ACCEL = 0x31,
REPORT_CORE_EXT8 = 0x32,
REPORT_CORE_ACCEL_IR12 = 0x33,
REPORT_CORE_EXT19 = 0x34,
REPORT_CORE_ACCEL_EXT16 = 0x35,
REPORT_CORE_IR10_EXT9 = 0x36,
REPORT_CORE_ACCEL_IR10_EXT6 = 0x37,
ReportCore = 0x30,
ReportCoreAccel = 0x31,
ReportCoreExt8 = 0x32,
ReportCoreAccelIR12 = 0x33,
ReportCoreExt19 = 0x34,
ReportCoreAccelExt16 = 0x35,
ReportCoreIR10Ext9 = 0x36,
ReportCoreAccelIR10Ext6 = 0x37,

REPORT_EXT21 = 0x3d,
REPORT_INTERLEAVE1 = 0x3e,
REPORT_INTERLEAVE2 = 0x3f,
ReportExt21 = 0x3d,
ReportInterleave1 = 0x3e,
ReportInterleave2 = 0x3f,
};

enum class OutputReportID : u8
{
RUMBLE = 0x10,
LEDS = 0x11,
REPORT_MODE = 0x12,
IR_PIXEL_CLOCK = 0x13,
SPEAKER_ENABLE = 0x14,
REQUEST_STATUS = 0x15,
WRITE_DATA = 0x16,
READ_DATA = 0x17,
SPEAKER_DATA = 0x18,
SPEAKER_MUTE = 0x19,
IR_LOGIC = 0x1A,
Rumble = 0x10,
LED = 0x11,
ReportMode = 0x12,
IRPixelClock = 0x13,
SpeakerEnable = 0x14,
RequestStatus = 0x15,
WriteData = 0x16,
ReadData = 0x17,
SpeakerData = 0x18,
SpeakerMute = 0x19,
IRLogic = 0x1a,
};

enum class LED : u8
{
NONE = 0x00,
None = 0x00,
LED_1 = 0x10,
LED_2 = 0x20,
LED_3 = 0x40,
@@ -63,19 +63,16 @@ enum class AddressSpace : u8
// However attempting to access this device directly results in an error.
EEPROM = 0x00,
// 0x01 is never used but it does function on a real wiimote:
I2C_BUS_ALT = 0x01,
I2C_BUS = 0x02,
I2CBusAlt = 0x01,
I2CBus = 0x02,
};

enum class ErrorCode : u8
{
SUCCESS = 0,
INVALID_SPACE = 6,
NACK = 7,
INVALID_ADDRESS = 8,

// Not a real value:
DO_NOT_SEND_ACK = 0xff,
Success = 0,
InvalidSpace = 6,
Nack = 7,
InvalidAddress = 8,
};

} // namespace WiimoteCommon
@@ -54,7 +54,7 @@ struct TypedHIDInputData

T data;

static_assert(std::is_pod<T>::value);
static_assert(std::is_pod<T>());

u8* GetData() { return reinterpret_cast<u8*>(this); }
const u8* GetData() const { return reinterpret_cast<const u8*>(this); }

0 comments on commit 9c1a889

Please sign in to comment.
You can’t perform that action at this time.