WiimoteEmu: Code cleanups.

This commit is contained in:
Jordan Woyak 2019-01-05 07:09:11 -06:00
parent 3945aa6242
commit 9c1a8891e5
29 changed files with 352 additions and 297 deletions

View File

@ -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

View File

@ -4,6 +4,7 @@
#include <cassert>
#include "Common/BitUtils.h"
#include "Core/HW/WiimoteCommon/DataReport.h"
namespace WiimoteCommon
@ -34,7 +35,7 @@ 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;
@ -42,11 +43,13 @@ struct IncludeCore : virtual DataReportManipulator
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,13 +74,13 @@ 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;
@ -85,16 +88,18 @@ struct IncludeAccel : virtual DataReportManipulator
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,10 +201,10 @@ 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);
}
@ -207,9 +212,10 @@ struct ReportInterleave1 : IncludeCore, IncludeIR<3, 18, 0>, NoExt
{
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,10 +232,10 @@ 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);
}
@ -237,9 +243,10 @@ struct ReportInterleave2 : IncludeCore, IncludeIR<3, 18, 18>, NoExt
{
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

View File

@ -27,7 +27,7 @@ public:
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;

View File

@ -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

View File

@ -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); }

View File

@ -4,6 +4,7 @@
#include "Core/HW/WiimoteEmu/Camera.h"
#include "Common/BitUtils.h"
#include "Common/ChunkFile.h"
#include "Core/HW/WiimoteCommon/WiimoteReport.h"
#include "Core/HW/WiimoteEmu/MatrixMath.h"
@ -39,9 +40,6 @@ int CameraLogic::BusWrite(u8 slave_addr, u8 addr, int count, const u8* data_in)
void CameraLogic::Update(const ControllerEmu::Cursor::StateData& cursor,
const NormalizedAccelData& accel, bool sensor_bar_on_top)
{
u16 x[4], y[4];
memset(x, 0xFF, sizeof(x));
double nsin, ncos;
// Ugly code to figure out the wiimote's current angle.
@ -73,7 +71,10 @@ void CameraLogic::Update(const ControllerEmu::Cursor::StateData& cursor,
static constexpr double dist1 = 100.0 / camWidth; // this seems the optimal distance for zelda
static constexpr double dist2 = 1.2 * dist1;
std::array<Vertex, 4> v;
constexpr int NUM_POINTS = 4;
std::array<Vertex, NUM_POINTS> v;
for (auto& vtx : v)
{
vtx.x = cursor.x * (bndright - bndleft) / 2 + (bndleft + bndright) / 2;
@ -104,6 +105,10 @@ void CameraLogic::Update(const ControllerEmu::Cursor::StateData& cursor,
MatrixRotationByZ(rot, ir_sin, ir_cos);
MatrixMultiply(tot, scale, rot);
u16 x[NUM_POINTS], y[NUM_POINTS];
memset(x, 0xFF, sizeof(x));
memset(y, 0xFF, sizeof(y));
for (std::size_t i = 0; i < v.size(); i++)
{
MatrixTransformVertex(tot, v[i]);
@ -113,6 +118,12 @@ void CameraLogic::Update(const ControllerEmu::Cursor::StateData& cursor,
x[i] = static_cast<u16>(lround((v[i].x + 1) / 2 * (camWidth - 1)));
y[i] = static_cast<u16>(lround((v[i].y + 1) / 2 * (camHeight - 1)));
if (x[i] >= camWidth || y[i] >= camHeight)
{
x[i] = -1;
y[i] = -1;
}
}
// IR data is read from offset 0x37 on real hardware
@ -127,70 +138,70 @@ void CameraLogic::Update(const ControllerEmu::Cursor::StateData& cursor,
switch (reg_data.mode)
{
case IR_MODE_BASIC:
{
auto* const irdata = reinterpret_cast<IRBasic*>(data);
for (unsigned int i = 0; i < 2; ++i)
{
if (x[i * 2] < 1024 && y[i * 2] < 768)
{
irdata[i].x1 = static_cast<u8>(x[i * 2]);
irdata[i].x1hi = x[i * 2] >> 8;
IRBasic irdata = {};
irdata[i].y1 = static_cast<u8>(y[i * 2]);
irdata[i].y1hi = y[i * 2] >> 8;
}
if (x[i * 2 + 1] < 1024 && y[i * 2 + 1] < 768)
{
irdata[i].x2 = static_cast<u8>(x[i * 2 + 1]);
irdata[i].x2hi = x[i * 2 + 1] >> 8;
irdata.x1 = static_cast<u8>(x[i * 2]);
irdata.x1hi = x[i * 2] >> 8;
irdata.y1 = static_cast<u8>(y[i * 2]);
irdata.y1hi = y[i * 2] >> 8;
irdata[i].y2 = static_cast<u8>(y[i * 2 + 1]);
irdata[i].y2hi = y[i * 2 + 1] >> 8;
irdata.x2 = static_cast<u8>(x[i * 2 + 1]);
irdata.x2hi = x[i * 2 + 1] >> 8;
irdata.y2 = static_cast<u8>(y[i * 2 + 1]);
irdata.y2hi = y[i * 2 + 1] >> 8;
Common::BitCastPtr<IRBasic>(data + i * sizeof(IRBasic)) = irdata;
}
break;
case IR_MODE_EXTENDED:
for (unsigned int i = 0; i < 4; ++i)
{
if (x[i] < camWidth)
{
IRExtended irdata = {};
irdata.x = static_cast<u8>(x[i]);
irdata.xhi = x[i] >> 8;
irdata.y = static_cast<u8>(y[i]);
irdata.yhi = y[i] >> 8;
irdata.size = 10;
Common::BitCastPtr<IRExtended>(data + i * sizeof(IRExtended)) = irdata;
}
}
break;
}
case IR_MODE_EXTENDED:
{
auto* const irdata = reinterpret_cast<IRExtended*>(data);
for (unsigned int i = 0; i < 4; ++i)
if (x[i] < 1024 && y[i] < 768)
{
irdata[i].x = static_cast<u8>(x[i]);
irdata[i].xhi = x[i] >> 8;
irdata[i].y = static_cast<u8>(y[i]);
irdata[i].yhi = y[i] >> 8;
irdata[i].size = 10;
}
break;
}
case IR_MODE_FULL:
{
auto* const irdata = reinterpret_cast<IRFull*>(data);
for (unsigned int i = 0; i < 4; ++i)
if (x[i] < 1024 && y[i] < 768)
{
if (x[i] < camWidth)
{
irdata[i].x = static_cast<u8>(x[i]);
irdata[i].xhi = x[i] >> 8;
IRFull irdata = {};
irdata[i].y = static_cast<u8>(y[i]);
irdata[i].yhi = y[i] >> 8;
irdata.x = static_cast<u8>(x[i]);
irdata.xhi = x[i] >> 8;
irdata[i].size = 10;
irdata.y = static_cast<u8>(y[i]);
irdata.yhi = y[i] >> 8;
irdata.size = 10;
// TODO: implement these sensibly:
// TODO: do high bits of x/y min/max need to be set to zero?
irdata[i].xmin = 0;
irdata[i].ymin = 0;
irdata[i].xmax = 0;
irdata[i].ymax = 0;
irdata[i].zero = 0;
irdata[i].intensity = 0;
irdata.xmin = 0;
irdata.ymin = 0;
irdata.xmax = 0;
irdata.ymax = 0;
irdata.zero = 0;
irdata.intensity = 0;
Common::BitCastPtr<IRFull>(data + i * sizeof(IRFull)) = irdata;
}
}
break;
}
default:
// This seems to be fairly common, 0xff data is sent in this case:
// WARN_LOG(WIIMOTE, "Game is requesting IR data before setting IR mode.");

View File

@ -64,6 +64,13 @@ public:
IR_MODE_FULL = 5,
};
void Reset();
void DoState(PointerWrap& p);
void Update(const ControllerEmu::Cursor::StateData& cursor, const NormalizedAccelData& accel,
bool sensor_bar_on_top);
static constexpr u8 I2C_ADDR = 0x58;
private:
// TODO: some of this memory is write-only and should return error 7.
#pragma pack(push, 1)
@ -85,20 +92,13 @@ private:
static_assert(0x100 == sizeof(Register));
public:
static constexpr u8 I2C_ADDR = 0x58;
// The real wiimote reads camera data from the i2c bus at offset 0x37:
static const u8 REPORT_DATA_OFFSET = offsetof(Register, camera_data);
void Reset();
void DoState(PointerWrap& p);
void Update(const ControllerEmu::Cursor::StateData& cursor, const NormalizedAccelData& accel,
bool sensor_bar_on_top);
private:
Register reg_data;
int BusRead(u8 slave_addr, u8 addr, int count, u8* data_out) override;
int BusWrite(u8 slave_addr, u8 addr, int count, const u8* data_in) override;
Register reg_data;
};
} // namespace WiimoteEmu

View File

@ -37,7 +37,9 @@ void EmulateShake(NormalizedAccelData* const accel, ControllerEmu::Buttons* cons
shake_step[i] = (shake_step[i] + 1) % SHAKE_STEP_MAX;
}
else
{
shake_step[i] = 0;
}
}
}

View File

@ -15,11 +15,11 @@ namespace WiimoteEmu
{
struct NormalizedAccelData
{
// Unit is 1G
double x, y, z;
};
// Used for a dynamic swing or
// shake
// Used for a dynamic swing or shake
struct DynamicData
{
std::array<int, 3> timing; // Hold length in frames for each axis
@ -27,10 +27,8 @@ struct DynamicData
std::array<int, 3> executing_frames_left; // Number of frames to execute the intensity operation
};
// Used for a dynamic swing or
// shake. This is used to pass
// in data that defines the dynamic
// action
// Used for a dynamic swing or shake.
// This is used to pass in data that defines the dynamic action
struct DynamicConfiguration
{
double low_intensity;

View File

@ -2,8 +2,10 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <cmath>
#include <fstream>
#include "Common/BitUtils.h"
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
@ -43,7 +45,7 @@ void Wiimote::HandleReportMode(const OutputReportMode& dr)
m_reporting_continuous = dr.continuous;
m_reporting_mode = dr.mode;
SendAck(OutputReportID::REPORT_MODE, ErrorCode::SUCCESS);
SendAck(OutputReportID::ReportMode, ErrorCode::Success);
}
// Tests that we have enough bytes for the report before we run the handler.
@ -53,9 +55,10 @@ void Wiimote::InvokeHandler(H&& handler, const WiimoteCommon::OutputReportGeneri
if (size < sizeof(T))
{
ERROR_LOG(WIIMOTE, "InvokeHandler: report: 0x%02x invalid size: %d", int(rpt.rpt_id), size);
return;
}
(this->*handler)(*reinterpret_cast<const T*>(rpt.data));
(this->*handler)(Common::BitCastPtr<T>(rpt.data));
}
// Here we process the Output Reports that the Wii sends. Our response will be
@ -77,7 +80,7 @@ void Wiimote::HIDOutputReport(const void* data, u32 size)
}
auto& rpt = *static_cast<const OutputReportGeneric*>(data);
const int rpt_size = size - rpt.HEADER_SIZE;
const int rpt_size = size - OutputReportGeneric::HEADER_SIZE;
DEBUG_LOG(WIIMOTE, "HIDOutputReport (page: %i, cid: 0x%02x, wm: 0x%02x)", m_index,
m_reporting_channel, int(rpt.rpt_id));
@ -88,37 +91,37 @@ void Wiimote::HIDOutputReport(const void* data, u32 size)
switch (rpt.rpt_id)
{
case OutputReportID::RUMBLE:
case OutputReportID::Rumble:
// This is handled above.
break;
case OutputReportID::LEDS:
case OutputReportID::LED:
InvokeHandler<OutputReportLeds>(&Wiimote::HandleReportLeds, rpt, rpt_size);
break;
case OutputReportID::REPORT_MODE:
case OutputReportID::ReportMode:
InvokeHandler<OutputReportMode>(&Wiimote::HandleReportMode, rpt, rpt_size);
break;
case OutputReportID::IR_PIXEL_CLOCK:
case OutputReportID::IRPixelClock:
InvokeHandler<OutputReportEnableFeature>(&Wiimote::HandleIRPixelClock, rpt, rpt_size);
break;
case OutputReportID::SPEAKER_ENABLE:
case OutputReportID::SpeakerEnable:
InvokeHandler<OutputReportEnableFeature>(&Wiimote::HandleSpeakerEnable, rpt, rpt_size);
break;
case OutputReportID::REQUEST_STATUS:
case OutputReportID::RequestStatus:
InvokeHandler<OutputReportRequestStatus>(&Wiimote::HandleRequestStatus, rpt, rpt_size);
break;
case OutputReportID::WRITE_DATA:
case OutputReportID::WriteData:
InvokeHandler<OutputReportWriteData>(&Wiimote::HandleWriteData, rpt, rpt_size);
break;
case OutputReportID::READ_DATA:
case OutputReportID::ReadData:
InvokeHandler<OutputReportReadData>(&Wiimote::HandleReadData, rpt, rpt_size);
break;
case OutputReportID::SPEAKER_DATA:
case OutputReportID::SpeakerData:
InvokeHandler<OutputReportSpeakerData>(&Wiimote::HandleSpeakerData, rpt, rpt_size);
break;
case OutputReportID::SPEAKER_MUTE:
case OutputReportID::SpeakerMute:
InvokeHandler<OutputReportEnableFeature>(&Wiimote::HandleSpeakerMute, rpt, rpt_size);
break;
case OutputReportID::IR_LOGIC:
case OutputReportID::IRLogic:
InvokeHandler<OutputReportEnableFeature>(&Wiimote::HandleIRLogic, rpt, rpt_size);
break;
default:
@ -134,7 +137,7 @@ void Wiimote::CallbackInterruptChannel(const u8* data, u32 size)
void Wiimote::SendAck(OutputReportID rpt_id, ErrorCode error_code)
{
TypedHIDInputData<InputReportAck> rpt(InputReportID::ACK);
TypedHIDInputData<InputReportAck> rpt(InputReportID::Ack);
auto& ack = rpt.data;
ack.buttons = m_status.buttons;
@ -229,7 +232,7 @@ void Wiimote::HandleRequestStatus(const OutputReportRequestStatus&)
// Max battery level seems to be 0xc8 (decimal 200)
constexpr u8 MAX_BATTERY_LEVEL = 0xc8;
m_status.battery = (u8)(m_battery_setting->GetValue() * MAX_BATTERY_LEVEL);
m_status.battery = u8(std::lround(m_battery_setting->GetValue() * MAX_BATTERY_LEVEL));
if (Core::WantsDeterminism())
{
@ -240,7 +243,7 @@ void Wiimote::HandleRequestStatus(const OutputReportRequestStatus&)
// Less than 0x20 triggers the low-battery flag:
m_status.battery_low = m_status.battery < 0x20;
TypedHIDInputData<InputReportStatus> rpt(InputReportID::STATUS);
TypedHIDInputData<InputReportStatus> rpt(InputReportID::Status);
rpt.data = m_status;
CallbackInterruptChannel(rpt.GetData(), rpt.GetSize());
}
@ -261,7 +264,7 @@ void Wiimote::HandleWriteData(const OutputReportWriteData& wd)
return;
}
ErrorCode error_code = ErrorCode::SUCCESS;
ErrorCode error_code = ErrorCode::Success;
switch (static_cast<AddressSpace>(wd.space))
{
@ -270,7 +273,7 @@ void Wiimote::HandleWriteData(const OutputReportWriteData& wd)
if (address + wd.size > EEPROM_FREE_SIZE)
{
WARN_LOG(WIIMOTE, "WriteData: address + size out of bounds!");
error_code = ErrorCode::INVALID_ADDRESS;
error_code = ErrorCode::InvalidAddress;
}
else
{
@ -279,7 +282,8 @@ void Wiimote::HandleWriteData(const OutputReportWriteData& wd)
// Write mii data to file
if (address >= 0x0FCA && address < 0x12C0)
{
// TODO: Only write parts of the Mii block
// TODO: Only write parts of the Mii block.
// TODO: Use fifferent files for different wiimote numbers.
std::ofstream file;
File::OpenFStream(file, File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/mii.bin",
std::ios::binary | std::ios::out);
@ -290,14 +294,14 @@ void Wiimote::HandleWriteData(const OutputReportWriteData& wd)
}
break;
case AddressSpace::I2C_BUS:
case AddressSpace::I2C_BUS_ALT:
case AddressSpace::I2CBus:
case AddressSpace::I2CBusAlt:
{
// Attempting to access the EEPROM directly over i2c results in error 8.
if (EEPROM_I2C_ADDR == m_read_request.slave_address)
{
WARN_LOG(WIIMOTE, "Attempt to write EEPROM directly.");
error_code = ErrorCode::INVALID_ADDRESS;
error_code = ErrorCode::InvalidAddress;
break;
}
@ -306,7 +310,7 @@ void Wiimote::HandleWriteData(const OutputReportWriteData& wd)
if (bytes_written != wd.size)
{
// A real wiimote gives error 7 for failed write to i2c bus (mainly a non-existant slave)
error_code = ErrorCode::NACK;
error_code = ErrorCode::Nack;
}
}
break;
@ -314,11 +318,11 @@ void Wiimote::HandleWriteData(const OutputReportWriteData& wd)
default:
WARN_LOG(WIIMOTE, "WriteData: invalid address space: 0x%x", wd.space);
// A real wiimote gives error 6:
error_code = ErrorCode::INVALID_SPACE;
error_code = ErrorCode::InvalidSpace;
break;
}
SendAck(OutputReportID::WRITE_DATA, error_code);
SendAck(OutputReportID::WriteData, error_code);
}
void Wiimote::HandleReportRumble(const WiimoteCommon::OutputReportRumble& rpt)
@ -333,7 +337,7 @@ void Wiimote::HandleReportLeds(const WiimoteCommon::OutputReportLeds& rpt)
m_status.leds = rpt.leds;
if (rpt.ack)
SendAck(OutputReportID::LEDS, ErrorCode::SUCCESS);
SendAck(OutputReportID::LED, ErrorCode::Success);
}
void Wiimote::HandleIRPixelClock(const WiimoteCommon::OutputReportEnableFeature& rpt)
@ -343,7 +347,7 @@ void Wiimote::HandleIRPixelClock(const WiimoteCommon::OutputReportEnableFeature&
// FYI: Camera data is currently always updated. Ignoring pixel clock status.
if (rpt.ack)
SendAck(OutputReportID::IR_PIXEL_CLOCK, ErrorCode::SUCCESS);
SendAck(OutputReportID::IRPixelClock, ErrorCode::Success);
}
void Wiimote::HandleIRLogic(const WiimoteCommon::OutputReportEnableFeature& rpt)
@ -353,7 +357,7 @@ void Wiimote::HandleIRLogic(const WiimoteCommon::OutputReportEnableFeature& rpt)
m_status.ir = rpt.enable;
if (rpt.ack)
SendAck(OutputReportID::IR_LOGIC, ErrorCode::SUCCESS);
SendAck(OutputReportID::IRLogic, ErrorCode::Success);
}
void Wiimote::HandleSpeakerMute(const WiimoteCommon::OutputReportEnableFeature& rpt)
@ -361,7 +365,7 @@ void Wiimote::HandleSpeakerMute(const WiimoteCommon::OutputReportEnableFeature&
m_speaker_mute = rpt.enable;
if (rpt.ack)
SendAck(OutputReportID::SPEAKER_MUTE, ErrorCode::SUCCESS);
SendAck(OutputReportID::SpeakerMute, ErrorCode::Success);
}
void Wiimote::HandleSpeakerEnable(const WiimoteCommon::OutputReportEnableFeature& rpt)
@ -370,7 +374,7 @@ void Wiimote::HandleSpeakerEnable(const WiimoteCommon::OutputReportEnableFeature
m_status.speaker = rpt.enable;
if (rpt.ack)
SendAck(OutputReportID::SPEAKER_ENABLE, ErrorCode::SUCCESS);
SendAck(OutputReportID::SpeakerEnable, ErrorCode::Success);
}
void Wiimote::HandleSpeakerData(const WiimoteCommon::OutputReportSpeakerData& rpt)
@ -437,7 +441,7 @@ bool Wiimote::ProcessReadDataRequest()
return false;
}
TypedHIDInputData<InputReportReadDataReply> rpt(InputReportID::READ_DATA_REPLY);
TypedHIDInputData<InputReportReadDataReply> rpt(InputReportID::ReadDataReply);
auto& reply = rpt.data;
reply.buttons = m_status.buttons;
@ -446,7 +450,7 @@ bool Wiimote::ProcessReadDataRequest()
// Pre-fill with zeros in case of read-error or read < 16-bytes:
std::fill(std::begin(reply.data), std::end(reply.data), 0x00);
ErrorCode error_code = ErrorCode::SUCCESS;
ErrorCode error_code = ErrorCode::Success;
switch (m_read_request.space)
{
@ -460,7 +464,7 @@ bool Wiimote::ProcessReadDataRequest()
// The real Wiimote generate an error for the first
// request to 0x1770 if we dont't replicate that the game will never
// read the calibration data at the beginning of Eeprom.
error_code = ErrorCode::INVALID_ADDRESS;
error_code = ErrorCode::InvalidAddress;
}
else
{
@ -483,14 +487,14 @@ bool Wiimote::ProcessReadDataRequest()
}
break;
case AddressSpace::I2C_BUS:
case AddressSpace::I2C_BUS_ALT:
case AddressSpace::I2CBus:
case AddressSpace::I2CBusAlt:
{
// Attempting to access the EEPROM directly over i2c results in error 8.
if (EEPROM_I2C_ADDR == m_read_request.slave_address)
{
WARN_LOG(WIIMOTE, "Attempt to read EEPROM directly.");
error_code = ErrorCode::INVALID_ADDRESS;
error_code = ErrorCode::InvalidAddress;
break;
}
@ -502,7 +506,7 @@ bool Wiimote::ProcessReadDataRequest()
{
DEBUG_LOG(WIIMOTE, "Responding with read error 7 @ 0x%x @ 0x%x (%d)",
m_read_request.slave_address, m_read_request.address, m_read_request.size);
error_code = ErrorCode::NACK;
error_code = ErrorCode::Nack;
break;
}
@ -513,11 +517,11 @@ bool Wiimote::ProcessReadDataRequest()
default:
WARN_LOG(WIIMOTE, "ReadData: invalid address space: 0x%x", int(m_read_request.space));
// A real wiimote gives error 6:
error_code = ErrorCode::INVALID_SPACE;
error_code = ErrorCode::InvalidSpace;
break;
}
if (ErrorCode::SUCCESS != error_code)
if (ErrorCode::Success != error_code)
{
// Stop processing request on read error:
m_read_request.size = 0;

View File

@ -7,6 +7,7 @@
#include <array>
#include <cassert>
#include "Common/BitUtils.h"
#include "Common/Common.h"
#include "Common/CommonTypes.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
@ -108,8 +109,7 @@ Classic::Classic() : EncryptedExtension(_trans("Classic"))
void Classic::Update()
{
auto& classic_data = *reinterpret_cast<DataFormat*>(&m_reg.controller_data);
classic_data = {};
DataFormat classic_data = {};
// left stick
{
@ -156,6 +156,8 @@ void Classic::Update()
// flip button bits
classic_data.bt.hex ^= 0xFFFF;
Common::BitCastPtr<DataFormat>(&m_reg.controller_data) = classic_data;
}
bool Classic::IsButtonPressed() const

View File

@ -8,6 +8,7 @@
#include <cassert>
#include <cstring>
#include "Common/BitUtils.h"
#include "Common/Common.h"
#include "Common/CommonTypes.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
@ -66,8 +67,7 @@ Drums::Drums() : EncryptedExtension(_trans("Drums"))
void Drums::Update()
{
auto& drum_data = reinterpret_cast<DataFormat&>(m_reg.controller_data);
drum_data = {};
DataFormat drum_data = {};
// stick
{
@ -92,6 +92,8 @@ void Drums::Update()
// flip button bits
drum_data.bt ^= 0xFFFF;
Common::BitCastPtr<DataFormat>(&m_reg.controller_data) = drum_data;
}
bool Drums::IsButtonPressed() const

View File

@ -20,7 +20,7 @@ namespace WiimoteEmu
class Extension : public ControllerEmu::EmulatedController, public I2CSlave
{
public:
Extension(const char* name);
explicit Extension(const char* name);
std::string GetName() const override;

View File

@ -9,6 +9,7 @@
#include <cstring>
#include <map>
#include "Common/BitUtils.h"
#include "Common/Common.h"
#include "Common/CommonTypes.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
@ -98,8 +99,7 @@ Guitar::Guitar() : EncryptedExtension(_trans("Guitar"))
void Guitar::Update()
{
auto& guitar_data = reinterpret_cast<DataFormat&>(m_reg.controller_data);
guitar_data = {};
DataFormat guitar_data = {};
// stick
{
@ -137,6 +137,8 @@ void Guitar::Update()
// flip button bits
guitar_data.bt ^= 0xFFFF;
Common::BitCastPtr<DataFormat>(&m_reg.controller_data) = guitar_data;
}
bool Guitar::IsButtonPressed() const

View File

@ -8,6 +8,7 @@
#include <cassert>
#include <cstring>
#include "Common/BitUtils.h"
#include "Common/Common.h"
#include "Common/CommonTypes.h"
#include "Common/MathUtil.h"
@ -72,8 +73,7 @@ Nunchuk::Nunchuk() : EncryptedExtension(_trans("Nunchuk"))
void Nunchuk::Update()
{
auto& nc_data = *reinterpret_cast<DataFormat*>(&m_reg.controller_data);
nc_data = {};
DataFormat nc_data = {};
// stick
const ControllerEmu::AnalogStick::StateData stick_state = m_stick->GetState();
@ -129,6 +129,8 @@ void Nunchuk::Update()
nc_data.bt.acc_x_lsb = acc.x & 0x3;
nc_data.bt.acc_y_lsb = acc.y & 0x3;
nc_data.bt.acc_z_lsb = acc.z & 0x3;
Common::BitCastPtr<DataFormat>(&m_reg.controller_data) = nc_data;
}
bool Nunchuk::IsButtonPressed() const

View File

@ -8,6 +8,7 @@
#include <cassert>
#include <cstring>
#include "Common/BitUtils.h"
#include "Common/Common.h"
#include "Common/CommonTypes.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
@ -84,8 +85,7 @@ Turntable::Turntable() : EncryptedExtension(_trans("Turntable"))
void Turntable::Update()
{
auto& tt_data = reinterpret_cast<DataFormat&>(m_reg.controller_data);
tt_data = {};
DataFormat tt_data = {};
// stick
{
@ -137,6 +137,8 @@ void Turntable::Update()
// flip button bits :/
tt_data.bt ^= (BUTTON_L_GREEN | BUTTON_L_RED | BUTTON_L_BLUE | BUTTON_R_GREEN | BUTTON_R_RED |
BUTTON_R_BLUE | BUTTON_MINUS | BUTTON_PLUS | BUTTON_EUPHORIA);
Common::BitCastPtr<DataFormat>(&m_reg.controller_data) = tt_data;
}
bool Turntable::IsButtonPressed() const

View File

@ -30,7 +30,7 @@ public:
static constexpr u8 REPORT_I2C_SLAVE = 0x52;
static constexpr u8 REPORT_I2C_ADDR = 0x00;
ExtensionPort(I2CBus* i2c_bus);
explicit ExtensionPort(I2CBus* i2c_bus);
bool IsDeviceConnected() const;
void AttachExtension(Extension* dev);

View File

@ -25,7 +25,7 @@ void MotionPlus::Reset()
std::copy(std::begin(initial_id), std::end(initial_id), reg_data.ext_identifier);
// TODO: determine meaning of calibration data:
static const u8 cdata[32] = {
constexpr std::array<u8, 32> cdata = {
0x78, 0xd9, 0x78, 0x38, 0x77, 0x9d, 0x2f, 0x0c, 0xcf, 0xf0, 0x31,
0xad, 0xc8, 0x0b, 0x5e, 0x39, 0x6f, 0x81, 0x7b, 0x89, 0x78, 0x51,
0x33, 0x60, 0xc9, 0xf5, 0x37, 0xc1, 0x2d, 0xe9, 0x15, 0x8d,
@ -34,7 +34,7 @@ void MotionPlus::Reset()
std::copy(std::begin(cdata), std::end(cdata), reg_data.calibration_data);
// TODO: determine the meaning behind this:
static const u8 cert[64] = {
constexpr std::array<u8, 64> cert = {
0x99, 0x1a, 0x07, 0x1b, 0x97, 0xf1, 0x11, 0x78, 0x0c, 0x42, 0x2b, 0x68, 0xdf,
0x44, 0x38, 0x0d, 0x2b, 0x7e, 0xd6, 0x84, 0x84, 0x58, 0x65, 0xc9, 0xf2, 0x95,
0xd9, 0xaf, 0xb6, 0xc4, 0x87, 0xd5, 0x18, 0xdb, 0x67, 0x3a, 0xc0, 0x71, 0xec,
@ -52,7 +52,7 @@ void MotionPlus::DoState(PointerWrap& p)
bool MotionPlus::IsActive() const
{
return ACTIVE_DEVICE_ADDR << 1 == reg_data.ext_identifier[2];
return (ACTIVE_DEVICE_ADDR << 1) == reg_data.ext_identifier[2];
}
MotionPlus::PassthroughMode MotionPlus::GetPassthroughMode() const
@ -69,7 +69,8 @@ int MotionPlus::BusRead(u8 slave_addr, u8 addr, int count, u8* data_out)
{
if (IsActive())
{
// Motion plus does not respond to 0x53 when activated
// FYI: Motion plus does not respond to 0x53 when activated
if (ACTIVE_DEVICE_ADDR == slave_addr)
return RawRead(&reg_data, addr, count, data_out);
else
@ -78,7 +79,9 @@ int MotionPlus::BusRead(u8 slave_addr, u8 addr, int count, u8* data_out)
else
{
if (INACTIVE_DEVICE_ADDR == slave_addr)
{
return RawRead(&reg_data, addr, count, data_out);
}
else
{
// Passthrough to the connected extension (if any)
@ -200,7 +203,7 @@ void MotionPlus::Update()
// It even works when removing the is_mp_data bit in the last byte
// My M+ non-inside gives: 61,46,45,aa,0,2 or b6,46,45,9a,0,2
// static const u8 init_data[6] = {0x8e, 0xb0, 0x4f, 0x5a, 0xfc | 0x01, 0x02};
static const u8 init_data[6] = {0x81, 0x46, 0x46, 0xb6, 0x01, 0x02};
constexpr std::array<u8, 6> init_data = {0x81, 0x46, 0x46, 0xb6, 0x01, 0x02};
std::copy(std::begin(init_data), std::end(init_data), data);
reg_data.cert_ready = 0x2;
return;
@ -208,7 +211,7 @@ void MotionPlus::Update()
if (0x2 == reg_data.cert_ready)
{
static const u8 init_data[6] = {0x7f, 0xcf, 0xdf, 0x8b, 0x4f, 0x82};
constexpr std::array<u8, 6> init_data = {0x7f, 0xcf, 0xdf, 0x8b, 0x4f, 0x82};
std::copy(std::begin(init_data), std::end(init_data), data);
reg_data.cert_ready = 0x8;
return;
@ -223,7 +226,7 @@ void MotionPlus::Update()
if (0x18 == reg_data.cert_ready)
{
// TODO: determine the meaning of this
const u8 mp_cert2[64] = {
constexpr std::array<u8, 64> mp_cert2 = {
0xa5, 0x84, 0x1f, 0xd6, 0xbd, 0xdc, 0x7a, 0x4c, 0xf3, 0xc0, 0x24, 0xe0, 0x92,
0xef, 0x19, 0x28, 0x65, 0xe0, 0x62, 0x7c, 0x9b, 0x41, 0x6f, 0x12, 0xc3, 0xac,
0x78, 0xe4, 0xfc, 0x6b, 0x7b, 0x0a, 0xb4, 0x50, 0xd6, 0xf2, 0x45, 0xf7, 0x93,
@ -267,7 +270,7 @@ void MotionPlus::Update()
constexpr u8 EXT_ADDR = ExtensionPort::REPORT_I2C_ADDR;
// Try to alternate between M+ and EXT data:
auto& mplus_data = *reinterpret_cast<DataFormat*>(data);
DataFormat mplus_data = Common::BitCastPtr<DataFormat>(data);
mplus_data.is_mp_data ^= true;
// hax!!!
@ -282,13 +285,13 @@ void MotionPlus::Update()
{
switch (GetPassthroughMode())
{
case PassthroughMode::DISABLED:
case PassthroughMode::Disabled:
{
// Passthrough disabled, always send M+ data:
mplus_data.is_mp_data = true;
break;
}
case PassthroughMode::NUNCHUK:
case PassthroughMode::Nunchuk:
{
if (EXT_AMT == i2c_bus.BusRead(EXT_SLAVE, EXT_ADDR, EXT_AMT, data))
{
@ -315,7 +318,7 @@ void MotionPlus::Update()
}
break;
}
case PassthroughMode::CLASSIC:
case PassthroughMode::Classic:
{
if (EXT_AMT == i2c_bus.BusRead(EXT_SLAVE, EXT_ADDR, EXT_AMT, data))
{
@ -371,6 +374,8 @@ void MotionPlus::Update()
mplus_data.extension_connected = m_extension_port.IsDeviceConnected();
mplus_data.zero = 0;
Common::BitCastPtr<DataFormat>(data) = mplus_data;
}
} // namespace WiimoteEmu

View File

@ -96,9 +96,9 @@ private:
enum class PassthroughMode : u8
{
DISABLED = 0x04,
NUNCHUK = 0x05,
CLASSIC = 0x07,
Disabled = 0x04,
Nunchuk = 0x05,
Classic = 0x07,
};
bool IsActive() const;

View File

@ -71,7 +71,7 @@ void Wiimote::Reset()
// Wiimote starts in non-continuous CORE mode:
m_reporting_channel = 0;
m_reporting_mode = InputReportID::REPORT_CORE;
m_reporting_mode = InputReportID::ReportCore;
m_reporting_continuous = false;
m_speaker_mute = false;
@ -325,7 +325,7 @@ bool Wiimote::ProcessExtensionPortEvent()
return false;
// FYI: This happens even during a read request which continues after the status report is sent.
m_reporting_mode = InputReportID::REPORT_DISABLED;
m_reporting_mode = InputReportID::ReportDisabled;
DEBUG_LOG(WIIMOTE, "Sending status report due to extension status change.");
@ -382,14 +382,14 @@ void Wiimote::SendDataReport()
{
Movie::SetPolledDevice();
if (InputReportID::REPORT_DISABLED == m_reporting_mode)
if (InputReportID::ReportDisabled == m_reporting_mode)
{
// The wiimote is in this disabled after an extension change.
// Input reports are not sent, even on button change.
return;
}
if (InputReportID::REPORT_CORE == m_reporting_mode && !m_reporting_continuous)
if (InputReportID::ReportCore == m_reporting_mode && !m_reporting_continuous)
{
// TODO: we only need to send a report if the data changed when m_reporting_continuous is
// disabled. It's probably only sensible to check this with REPORT_CORE
@ -497,10 +497,10 @@ void Wiimote::SendDataReport()
CallbackInterruptChannel(rpt_builder.GetDataPtr(), rpt_builder.GetDataSize());
// The interleaved reporting modes toggle back and forth:
if (InputReportID::REPORT_INTERLEAVE1 == m_reporting_mode)
m_reporting_mode = InputReportID::REPORT_INTERLEAVE2;
else if (InputReportID::REPORT_INTERLEAVE2 == m_reporting_mode)
m_reporting_mode = InputReportID::REPORT_INTERLEAVE1;
if (InputReportID::ReportInterleave1 == m_reporting_mode)
m_reporting_mode = InputReportID::ReportInterleave2;
else if (InputReportID::ReportInterleave2 == m_reporting_mode)
m_reporting_mode = InputReportID::ReportInterleave1;
}
void Wiimote::ControlChannel(const u16 channel_id, const void* data, u32 size)
@ -550,7 +550,7 @@ void Wiimote::ControlChannel(const u16 channel_id, const void* data, u32 size)
{
// AyuanX: My experiment shows Control Channel is never used
// shuffle2: but lwbt uses this, so we'll do what we must :)
HIDOutputReport(hidp.data, size - hidp.HEADER_SIZE);
HIDOutputReport(hidp.data, size - HIDPacket::HEADER_SIZE);
// TODO: Should this be above the previous?
u8 handshake = HID_HANDSHAKE_SUCCESS;
@ -594,7 +594,7 @@ void Wiimote::InterruptChannel(const u16 channel_id, const void* data, u32 size)
switch (hidp.param)
{
case HID_PARAM_OUTPUT:
HIDOutputReport(hidp.data, size - hidp.HEADER_SIZE);
HIDOutputReport(hidp.data, size - HIDPacket::HEADER_SIZE);
break;
default:

View File

@ -449,7 +449,7 @@ bool IsWiimote(const std::basic_string<TCHAR>& device_path, WinWriteMethod& meth
Common::ScopeGuard handle_guard{[&dev_handle] { CloseHandle(dev_handle); }};
u8 buf[MAX_PAYLOAD];
u8 const req_status_report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::REQUEST_STATUS), 0};
u8 const req_status_report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::RequestStatus), 0};
int invalid_report_count = 0;
int rc = WriteToHandle(dev_handle, method, req_status_report, sizeof(req_status_report));
while (rc > 0)
@ -460,7 +460,7 @@ bool IsWiimote(const std::basic_string<TCHAR>& device_path, WinWriteMethod& meth
switch (InputReportID(buf[1]))
{
case InputReportID::STATUS:
case InputReportID::Status:
return true;
default:
WARN_LOG(WIIMOTE, "IsWiimote(): Received unexpected report %02x", buf[1]);
@ -703,11 +703,11 @@ size_t GetReportSize(u8 rid)
switch (report_id)
{
case InputReportID::STATUS:
case InputReportID::Status:
return sizeof(InputReportStatus);
case InputReportID::READ_DATA_REPLY:
case InputReportID::ReadDataReply:
return sizeof(InputReportReadDataReply);
case InputReportID::ACK:
case InputReportID::Ack:
return sizeof(InputReportAck);
default:
if (DataReportBuilder::IsValidMode(report_id))

View File

@ -27,7 +27,7 @@ static bool IsDeviceUsable(const std::string& device_path)
// Some third-party adapters (DolphinBar) always expose all four Wii Remotes as HIDs
// even when they are not connected, which causes an endless error loop when we try to use them.
// Try to write a report to the device to see if this Wii Remote is really usable.
static const u8 report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::REQUEST_STATUS), 0};
static const u8 report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::RequestStatus), 0};
const int result = hid_write(handle, report, sizeof(report));
// The DolphinBar uses EPIPE to signal the absence of a Wii Remote connected to this HID.
if (result == -1 && errno != EPIPE)

View File

@ -71,7 +71,7 @@ void Wiimote::WriteReport(Report rpt)
bool const new_rumble_state = (rpt[2] & 0x1) != 0;
// If this is a rumble report and the rumble state didn't change, ignore.
if (rpt[1] == u8(OutputReportID::RUMBLE) && new_rumble_state == m_rumble_state)
if (rpt[1] == u8(OutputReportID::Rumble) && new_rumble_state == m_rumble_state)
return;
m_rumble_state = new_rumble_state;
@ -99,10 +99,10 @@ void Wiimote::DisableDataReporting()
// This accomplishes very little:
OutputReportMode rpt = {};
rpt.mode = InputReportID::REPORT_CORE;
rpt.mode = InputReportID::ReportCore;
rpt.continuous = 0;
rpt.rumble = 0;
QueueReport(u8(OutputReportID::REPORT_MODE), &rpt, sizeof(rpt));
QueueReport(u8(OutputReportID::ReportMode), &rpt, sizeof(rpt));
}
void Wiimote::EnableDataReporting(u8 mode)
@ -112,7 +112,7 @@ void Wiimote::EnableDataReporting(u8 mode)
OutputReportMode rpt = {};
rpt.mode = InputReportID(mode);
rpt.continuous = 1;
QueueReport(u8(OutputReportID::REPORT_MODE), &rpt, sizeof(rpt));
QueueReport(u8(OutputReportID::ReportMode), &rpt, sizeof(rpt));
}
void Wiimote::SetChannel(u16 channel)
@ -177,7 +177,7 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const
// Disallow games from turning off all of the LEDs.
// It makes Wiimote connection status confusing.
if (rpt[1] == u8(OutputReportID::LEDS))
if (rpt[1] == u8(OutputReportID::LED))
{
auto& leds_rpt = *reinterpret_cast<OutputReportLeds*>(&rpt[2]);
if (0 == leds_rpt.leds)
@ -186,12 +186,12 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const
leds_rpt.leds = 0xf;
}
}
else if (rpt[1] == u8(OutputReportID::SPEAKER_DATA) &&
else if (rpt[1] == u8(OutputReportID::SpeakerData) &&
(!SConfig::GetInstance().m_WiimoteEnableSpeaker ||
(!wm->m_status.speaker || wm->m_speaker_mute)))
{
// Translate speaker data reports into rumble reports.
rpt[1] = u8(OutputReportID::RUMBLE);
rpt[1] = u8(OutputReportID::Rumble);
// Keep only the rumble bit.
rpt[2] &= 0x1;
rpt.resize(3);
@ -255,23 +255,11 @@ bool Wiimote::IsBalanceBoard()
return false;
// Initialise the extension by writing 0x55 to 0xa400f0, then writing 0x00 to 0xa400fb.
// TODO: Use the structs for building these reports..
static const u8 init_extension_rpt1[MAX_PAYLOAD] = {WR_SET_REPORT | BT_OUTPUT,
u8(OutputReportID::WRITE_DATA),
0x04,
0xa4,
0x00,
0xf0,
0x01,
0x55};
static const u8 init_extension_rpt2[MAX_PAYLOAD] = {WR_SET_REPORT | BT_OUTPUT,
u8(OutputReportID::WRITE_DATA),
0x04,
0xa4,
0x00,
0xfb,
0x01,
0x00};
static const u8 status_report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::REQUEST_STATUS),
static const u8 init_extension_rpt1[MAX_PAYLOAD] = {
WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::WriteData), 0x04, 0xa4, 0x00, 0xf0, 0x01, 0x55};
static const u8 init_extension_rpt2[MAX_PAYLOAD] = {
WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::WriteData), 0x04, 0xa4, 0x00, 0xfb, 0x01, 0x00};
static const u8 status_report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::RequestStatus),
0};
if (!IOWrite(init_extension_rpt1, sizeof(init_extension_rpt1)) ||
!IOWrite(init_extension_rpt2, sizeof(init_extension_rpt2)))
@ -290,7 +278,7 @@ bool Wiimote::IsBalanceBoard()
switch (InputReportID(buf[1]))
{
case InputReportID::STATUS:
case InputReportID::Status:
{
const auto* status = reinterpret_cast<InputReportStatus*>(&buf[2]);
// A Balance Board has a Balance Board extension.
@ -298,7 +286,7 @@ bool Wiimote::IsBalanceBoard()
return false;
// Read two bytes from 0xa400fe to identify the extension.
static const u8 identify_ext_rpt[] = {WR_SET_REPORT | BT_OUTPUT,
u8(OutputReportID::READ_DATA),
u8(OutputReportID::ReadData),
0x04,
0xa4,
0x00,
@ -308,7 +296,7 @@ bool Wiimote::IsBalanceBoard()
ret = IOWrite(identify_ext_rpt, sizeof(identify_ext_rpt));
break;
}
case InputReportID::READ_DATA_REPLY:
case InputReportID::ReadDataReply:
{
const auto* reply = reinterpret_cast<InputReportReadDataReply*>(&buf[2]);
if (Common::swap16(reply->address) != 0x00fe)
@ -320,10 +308,10 @@ bool Wiimote::IsBalanceBoard()
// A Balance Board ext can be identified by checking for 0x0402.
return reply->data[0] == 0x04 && reply->data[1] == 0x02;
}
case InputReportID::ACK:
case InputReportID::Ack:
{
const auto* ack = reinterpret_cast<InputReportAck*>(&buf[2]);
if (ack->rpt_id == OutputReportID::READ_DATA && ack->error_code != ErrorCode::SUCCESS)
if (ack->rpt_id == OutputReportID::ReadData && ack->error_code != ErrorCode::Success)
{
WARN_LOG(WIIMOTE, "Failed to read from 0xa400fe, assuming Wiimote is not a Balance Board.");
return false;
@ -338,7 +326,7 @@ bool Wiimote::IsBalanceBoard()
static bool IsDataReport(const Report& rpt)
{
return rpt.size() >= 2 && rpt[1] >= u8(InputReportID::REPORT_CORE);
return rpt.size() >= 2 && rpt[1] >= u8(InputReportID::ReportCore);
}
// Returns the next report that should be sent
@ -387,30 +375,17 @@ void Wiimote::Update()
bool Wiimote::CheckForButtonPress()
{
const Report& rpt = ProcessReadQueue();
Report& rpt = ProcessReadQueue();
if (rpt.size() >= 4)
{
switch (InputReportID(rpt[1]))
const auto mode = InputReportID(rpt[1]);
if (DataReportBuilder::IsValidMode(mode))
{
case InputReportID::REPORT_CORE:
case InputReportID::REPORT_CORE_ACCEL:
case InputReportID::REPORT_CORE_EXT8:
case InputReportID::REPORT_CORE_ACCEL_IR12:
case InputReportID::REPORT_CORE_EXT19:
case InputReportID::REPORT_CORE_ACCEL_EXT16:
case InputReportID::REPORT_CORE_IR10_EXT9:
case InputReportID::REPORT_CORE_ACCEL_IR10_EXT6:
case InputReportID::REPORT_INTERLEAVE1:
case InputReportID::REPORT_INTERLEAVE2:
// check any button without checking accelerometer data
// TODO: use the structs!
if ((rpt[2] & 0x1F) != 0 || (rpt[3] & 0x9F) != 0)
{
return true;
}
break;
default:
break;
auto builder = MakeDataReportManipulator(mode, rpt.data() + 2);
ButtonData buttons = {};
builder->GetCoreData(&buttons);
return buttons.hex != 0;
}
}
return false;
@ -426,19 +401,19 @@ bool Wiimote::PrepareOnThread()
{
// core buttons, no continuous reporting
// TODO: use the structs..
u8 static const mode_report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::REPORT_MODE), 0,
u8(InputReportID::REPORT_CORE)};
u8 static const mode_report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::ReportMode), 0,
u8(InputReportID::ReportCore)};
// Set the active LEDs and turn on rumble.
u8 static led_report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::LEDS), 0};
u8 static led_report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::LED), 0};
led_report[2] = u8(u8(LED::LED_1) << (m_index % WIIMOTE_BALANCE_BOARD) | 0x1);
// Turn off rumble
u8 static const rumble_report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::RUMBLE), 0};
u8 static const rumble_report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::Rumble), 0};
// Request status report
u8 static const req_status_report[] = {WR_SET_REPORT | BT_OUTPUT,
u8(OutputReportID::REQUEST_STATUS), 0};
u8(OutputReportID::RequestStatus), 0};
// TODO: check for sane response?
return (IOWrite(mode_report, sizeof(mode_report)) && IOWrite(led_report, sizeof(led_report)) &&
@ -473,7 +448,7 @@ void Wiimote::EmuResume()
OutputReportMode rpt = {};
rpt.mode = wm->m_reporting_mode;
rpt.continuous = 1;
QueueReport(u8(OutputReportID::REPORT_MODE), &rpt, sizeof(rpt));
QueueReport(u8(OutputReportID::ReportMode), &rpt, sizeof(rpt));
NOTICE_LOG(WIIMOTE, "Resuming Wiimote data reporting.");
@ -485,9 +460,9 @@ void Wiimote::EmuPause()
m_last_input_report.clear();
OutputReportMode rpt = {};
rpt.mode = InputReportID::REPORT_CORE;
rpt.mode = InputReportID::ReportCore;
rpt.continuous = 0;
QueueReport(u8(OutputReportID::REPORT_MODE), &rpt, sizeof(rpt));
QueueReport(u8(OutputReportID::ReportMode), &rpt, sizeof(rpt));
NOTICE_LOG(WIIMOTE, "Pausing Wiimote data reporting.");

View File

@ -25,7 +25,7 @@ namespace WiimoteReal
{
using WiimoteCommon::MAX_PAYLOAD;
typedef std::vector<u8> Report;
using Report = std::vector<u8>;
constexpr u32 WIIMOTE_DEFAULT_TIMEOUT = 1000;

View File

@ -51,6 +51,7 @@
#include "Core/HW/WiimoteEmu/Encryption.h"
#include "Core/HW/WiimoteEmu/Extension/Classic.h"
#include "Core/HW/WiimoteEmu/Extension/Nunchuk.h"
#include "Core/HW/WiimoteEmu/ExtensionPort.h"
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
@ -706,7 +707,7 @@ static void SetWiiInputDisplayString(int remoteID, const DataReportBuilder& rpt,
}
// Nunchuk
if (rpt.HasExt() && ext == 1)
if (rpt.HasExt() && ext == ExtensionNumber::NUNCHUK)
{
const u8* const extData = rpt.GetExtDataPtr();
@ -728,7 +729,7 @@ static void SetWiiInputDisplayString(int remoteID, const DataReportBuilder& rpt,
}
// Classic controller
if (rpt.HasExt() && ext == 2)
if (rpt.HasExt() && ext == ExtensionNumber::CLASSIC)
{
const u8* const extData = rpt.GetExtDataPtr();

View File

@ -10,14 +10,22 @@
#include <string>
#include "Common/CommonTypes.h"
#include "Core/HW/WiimoteCommon/DataReport.h"
#include "Core/HW/WiimoteEmu/Encryption.h"
struct BootParameters;
struct GCPadStatus;
class PointerWrap;
namespace WiimoteCommon
{
class DataReportBuilder;
}
namespace WiimoteEmu
{
class EncryptionKey;
}
// Per-(video )Movie actions
namespace Movie

View File

@ -53,7 +53,7 @@
#include "Core/Movie.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/WiiRoot.h"
#include "InputCommon/ControllerEmu/ControlGroup/Extension.h"
#include "InputCommon/ControllerEmu/ControlGroup/Attachments.h"
#include "InputCommon/GCAdapter.h"
#include "InputCommon/InputConfig.h"
#include "UICommon/GameFile.h"
@ -2191,11 +2191,10 @@ void SetupWiimotes()
{
if (wiimote_map[i] > 0)
{
static_cast<ControllerEmu::Extension*>(
static_cast<WiimoteEmu::Wiimote*>(
Wiimote::GetConfig()->GetController(static_cast<int>(i)))
->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Extension))
->switch_extension = netplay_settings.m_WiimoteExtension[i];
static_cast<ControllerEmu::Attachments*>(
static_cast<WiimoteEmu::Wiimote*>(Wiimote::GetConfig()->GetController(int(i)))
->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Attachments))
->SetSelectedAttachment(netplay_settings.m_WiimoteExtension[i]);
}
}
}

View File

@ -49,7 +49,7 @@
#include "Core/IOS/IOS.h"
#include "Core/NetPlayClient.h" //for NetPlayUI
#include "DiscIO/Enums.h"
#include "InputCommon/ControllerEmu/ControlGroup/Extension.h"
#include "InputCommon/ControllerEmu/ControlGroup/Attachments.h"
#include "InputCommon/GCPadStatus.h"
#include "InputCommon/InputConfig.h"
#include "UICommon/GameFile.h"
@ -1217,11 +1217,11 @@ bool NetPlayServer::StartGame()
for (size_t i = 0; i < m_settings.m_WiimoteExtension.size(); i++)
{
const int extension = static_cast<ControllerEmu::Extension*>(
static_cast<WiimoteEmu::Wiimote*>(
Wiimote::GetConfig()->GetController(static_cast<int>(i)))
->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Extension))
->switch_extension;
const int extension =
static_cast<ControllerEmu::Attachments*>(
static_cast<WiimoteEmu::Wiimote*>(Wiimote::GetConfig()->GetController(int(i)))
->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Attachments))
->GetSelectedAttachment();
spac << extension;
}

View File

@ -32,6 +32,6 @@ public:
private:
std::vector<std::unique_ptr<EmulatedController>> m_attachments;
std::atomic<u32> m_selected_attachment;
std::atomic<u32> m_selected_attachment = {};
};
} // namespace ControllerEmu