diff --git a/Source/Core/Common/BitUtils.h b/Source/Core/Common/BitUtils.h index 62b9604fab..8b64a92508 100644 --- a/Source/Core/Common/BitUtils.h +++ b/Source/Core/Common/BitUtils.h @@ -200,13 +200,55 @@ inline To BitCast(const From& source) noexcept return reinterpret_cast(storage); } +template +class BitCastPtrType +{ +public: + static_assert(std::is_trivially_copyable(), + "BitCastPtr source type must be trivially copyable."); + static_assert(std::is_trivially_copyable(), + "BitCastPtr destination type must be trivially copyable."); + + explicit BitCastPtrType(PtrType* ptr) : m_ptr(ptr) {} + + // Enable operator= only for pointers to non-const data + template + inline typename std::enable_if() && !std::is_const()>::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(some_ptr); +// BitCastPtr(some_ptr) = s; +template +inline auto BitCastPtr(PtrType* ptr) noexcept -> BitCastPtrType +{ + return BitCastPtrType{ptr}; +} + template void SetBit(T& value, size_t bit_number, bool bit_value) { + static_assert(std::is_unsigned(), "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 diff --git a/Source/Core/Core/HW/WiimoteCommon/DataReport.cpp b/Source/Core/Core/HW/WiimoteCommon/DataReport.cpp index 47b01d2a65..28f5736153 100644 --- a/Source/Core/Core/HW/WiimoteCommon/DataReport.cpp +++ b/Source/Core/Core/HW/WiimoteCommon/DataReport.cpp @@ -4,6 +4,7 @@ #include +#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(data_ptr); + *result = Common::BitCastPtr(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(data_ptr); + CoreData core = Common::BitCastPtr(data_ptr); // Don't overwrite accel LSBs. core.hex &= ~CoreData::BUTTON_MASK; core.hex |= new_core.hex & CoreData::BUTTON_MASK; + + Common::BitCastPtr(data_ptr) = core; } }; @@ -71,13 +74,13 @@ struct IncludeAccel : virtual DataReportManipulator { void GetAccelData(AccelData* result) const override { - const auto& accel = *reinterpret_cast(data_ptr + 2); + const AccelMSB accel = Common::BitCastPtr(data_ptr + 2); result->x = accel.x << 2; result->y = accel.y << 2; result->z = accel.z << 2; // LSBs - const auto& core = *reinterpret_cast(data_ptr); + const CoreData core = Common::BitCastPtr(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(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(data_ptr + 2) = accel; // LSBs - auto& core = *reinterpret_cast(data_ptr); + CoreData core = Common::BitCastPtr(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(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(data_ptr); + const CoreData core = Common::BitCastPtr(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(data_ptr); + CoreData core = Common::BitCastPtr(data_ptr); core.acc_bits = (accel.z >> 6) & 0b11; core.acc_bits2 = (accel.z >> 8) & 0b11; + Common::BitCastPtr(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(data_ptr); + const CoreData core = Common::BitCastPtr(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(data_ptr); + CoreData core = Common::BitCastPtr(data_ptr); core.acc_bits = (accel.z >> 2) & 0b11; core.acc_bits2 = (accel.z >> 4) & 0b11; + Common::BitCastPtr(data_ptr) = core; } bool HasAccel() const override { return true; } @@ -257,47 +264,47 @@ std::unique_ptr MakeDataReportManipulator(InputReportID r switch (rpt_id) { - case InputReportID::REPORT_CORE: + case InputReportID::ReportCore: // 0x30: Core Buttons ptr = std::make_unique(); break; - case InputReportID::REPORT_CORE_ACCEL: + case InputReportID::ReportCoreAccel: // 0x31: Core Buttons and Accelerometer ptr = std::make_unique(); break; - case InputReportID::REPORT_CORE_EXT8: + case InputReportID::ReportCoreExt8: // 0x32: Core Buttons with 8 Extension bytes ptr = std::make_unique(); break; - case InputReportID::REPORT_CORE_ACCEL_IR12: + case InputReportID::ReportCoreAccelIR12: // 0x33: Core Buttons and Accelerometer with 12 IR bytes ptr = std::make_unique(); break; - case InputReportID::REPORT_CORE_EXT19: + case InputReportID::ReportCoreExt19: // 0x34: Core Buttons with 19 Extension bytes ptr = std::make_unique(); break; - case InputReportID::REPORT_CORE_ACCEL_EXT16: + case InputReportID::ReportCoreAccelExt16: // 0x35: Core Buttons and Accelerometer with 16 Extension Bytes ptr = std::make_unique(); 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(); 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(); break; - case InputReportID::REPORT_EXT21: + case InputReportID::ReportExt21: // 0x3d: 21 Extension Bytes ptr = std::make_unique(); break; - case InputReportID::REPORT_INTERLEAVE1: + case InputReportID::ReportInterleave1: // 0x3e - 0x3f: Interleaved Core Buttons and Accelerometer with 36 IR bytes ptr = std::make_unique(); break; - case InputReportID::REPORT_INTERLEAVE2: + case InputReportID::ReportInterleave2: ptr = std::make_unique(); 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 diff --git a/Source/Core/Core/HW/WiimoteCommon/DataReport.h b/Source/Core/Core/HW/WiimoteCommon/DataReport.h index f48981677b..dd2833728d 100644 --- a/Source/Core/Core/HW/WiimoteCommon/DataReport.h +++ b/Source/Core/Core/HW/WiimoteCommon/DataReport.h @@ -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 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 IRData; - typedef std::vector ExtData; + using CoreData = ButtonData; + using AccelData = DataReportManipulator::AccelData; void SetMode(InputReportID rpt_id); InputReportID GetMode() const; diff --git a/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h b/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h index 7b0e5dc30d..6b57568f9a 100644 --- a/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h +++ b/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h @@ -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 diff --git a/Source/Core/Core/HW/WiimoteCommon/WiimoteHid.h b/Source/Core/Core/HW/WiimoteCommon/WiimoteHid.h index ccd05a9303..fbcbd8b9e2 100644 --- a/Source/Core/Core/HW/WiimoteCommon/WiimoteHid.h +++ b/Source/Core/Core/HW/WiimoteCommon/WiimoteHid.h @@ -54,7 +54,7 @@ struct TypedHIDInputData T data; - static_assert(std::is_pod::value); + static_assert(std::is_pod()); u8* GetData() { return reinterpret_cast(this); } const u8* GetData() const { return reinterpret_cast(this); } diff --git a/Source/Core/Core/HW/WiimoteEmu/Camera.cpp b/Source/Core/Core/HW/WiimoteEmu/Camera.cpp index 0a8d20c67e..b2807e7122 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Camera.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Camera.cpp @@ -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 v; + constexpr int NUM_POINTS = 4; + + std::array 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(lround((v[i].x + 1) / 2 * (camWidth - 1))); y[i] = static_cast(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(data); for (unsigned int i = 0; i < 2; ++i) { - if (x[i * 2] < 1024 && y[i * 2] < 768) - { - irdata[i].x1 = static_cast(x[i * 2]); - irdata[i].x1hi = x[i * 2] >> 8; + IRBasic irdata = {}; - irdata[i].y1 = static_cast(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(x[i * 2 + 1]); - irdata[i].x2hi = x[i * 2 + 1] >> 8; + irdata.x1 = static_cast(x[i * 2]); + irdata.x1hi = x[i * 2] >> 8; + irdata.y1 = static_cast(y[i * 2]); + irdata.y1hi = y[i * 2] >> 8; - irdata[i].y2 = static_cast(y[i * 2 + 1]); - irdata[i].y2hi = y[i * 2 + 1] >> 8; + irdata.x2 = static_cast(x[i * 2 + 1]); + irdata.x2hi = x[i * 2 + 1] >> 8; + irdata.y2 = static_cast(y[i * 2 + 1]); + irdata.y2hi = y[i * 2 + 1] >> 8; + + Common::BitCastPtr(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(x[i]); + irdata.xhi = x[i] >> 8; + + irdata.y = static_cast(y[i]); + irdata.yhi = y[i] >> 8; + + irdata.size = 10; + + Common::BitCastPtr(data + i * sizeof(IRExtended)) = irdata; } } break; - } - case IR_MODE_EXTENDED: - { - auto* const irdata = reinterpret_cast(data); - for (unsigned int i = 0; i < 4; ++i) - if (x[i] < 1024 && y[i] < 768) - { - irdata[i].x = static_cast(x[i]); - irdata[i].xhi = x[i] >> 8; - - irdata[i].y = static_cast(y[i]); - irdata[i].yhi = y[i] >> 8; - - irdata[i].size = 10; - } - break; - } case IR_MODE_FULL: - { - auto* const irdata = reinterpret_cast(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(x[i]); - irdata[i].xhi = x[i] >> 8; + IRFull irdata = {}; - irdata[i].y = static_cast(y[i]); - irdata[i].yhi = y[i] >> 8; + irdata.x = static_cast(x[i]); + irdata.xhi = x[i] >> 8; - irdata[i].size = 10; + irdata.y = static_cast(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(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."); diff --git a/Source/Core/Core/HW/WiimoteEmu/Camera.h b/Source/Core/Core/HW/WiimoteEmu/Camera.h index fdcc48858b..b42dddd6b9 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Camera.h +++ b/Source/Core/Core/HW/WiimoteEmu/Camera.h @@ -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 diff --git a/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp b/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp index 47214ea46b..2d954d36d4 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp @@ -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; + } } } diff --git a/Source/Core/Core/HW/WiimoteEmu/Dynamics.h b/Source/Core/Core/HW/WiimoteEmu/Dynamics.h index 116c03d912..a1258725d1 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Dynamics.h +++ b/Source/Core/Core/HW/WiimoteEmu/Dynamics.h @@ -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 timing; // Hold length in frames for each axis @@ -27,10 +27,8 @@ struct DynamicData std::array 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; diff --git a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp index f989d70576..7a47ccf7d2 100644 --- a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp @@ -2,8 +2,10 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include #include +#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(rpt.data)); + (this->*handler)(Common::BitCastPtr(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(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(&Wiimote::HandleReportLeds, rpt, rpt_size); break; - case OutputReportID::REPORT_MODE: + case OutputReportID::ReportMode: InvokeHandler(&Wiimote::HandleReportMode, rpt, rpt_size); break; - case OutputReportID::IR_PIXEL_CLOCK: + case OutputReportID::IRPixelClock: InvokeHandler(&Wiimote::HandleIRPixelClock, rpt, rpt_size); break; - case OutputReportID::SPEAKER_ENABLE: + case OutputReportID::SpeakerEnable: InvokeHandler(&Wiimote::HandleSpeakerEnable, rpt, rpt_size); break; - case OutputReportID::REQUEST_STATUS: + case OutputReportID::RequestStatus: InvokeHandler(&Wiimote::HandleRequestStatus, rpt, rpt_size); break; - case OutputReportID::WRITE_DATA: + case OutputReportID::WriteData: InvokeHandler(&Wiimote::HandleWriteData, rpt, rpt_size); break; - case OutputReportID::READ_DATA: + case OutputReportID::ReadData: InvokeHandler(&Wiimote::HandleReadData, rpt, rpt_size); break; - case OutputReportID::SPEAKER_DATA: + case OutputReportID::SpeakerData: InvokeHandler(&Wiimote::HandleSpeakerData, rpt, rpt_size); break; - case OutputReportID::SPEAKER_MUTE: + case OutputReportID::SpeakerMute: InvokeHandler(&Wiimote::HandleSpeakerMute, rpt, rpt_size); break; - case OutputReportID::IR_LOGIC: + case OutputReportID::IRLogic: InvokeHandler(&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 rpt(InputReportID::ACK); + TypedHIDInputData 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 rpt(InputReportID::STATUS); + TypedHIDInputData 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(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 rpt(InputReportID::READ_DATA_REPLY); + TypedHIDInputData 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; diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/Classic.cpp b/Source/Core/Core/HW/WiimoteEmu/Extension/Classic.cpp index aa6b7e9ccd..9d1e656b85 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Extension/Classic.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/Classic.cpp @@ -7,6 +7,7 @@ #include #include +#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(&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(&m_reg.controller_data) = classic_data; } bool Classic::IsButtonPressed() const diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/Drums.cpp b/Source/Core/Core/HW/WiimoteEmu/Extension/Drums.cpp index 976038711c..1e98529209 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Extension/Drums.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/Drums.cpp @@ -8,6 +8,7 @@ #include #include +#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(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(&m_reg.controller_data) = drum_data; } bool Drums::IsButtonPressed() const diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/Extension.h b/Source/Core/Core/HW/WiimoteEmu/Extension/Extension.h index b32b1367bd..6392d9d542 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Extension/Extension.h +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/Extension.h @@ -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; diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/Guitar.cpp b/Source/Core/Core/HW/WiimoteEmu/Extension/Guitar.cpp index b3d5ab286b..68454928ce 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Extension/Guitar.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/Guitar.cpp @@ -9,6 +9,7 @@ #include #include +#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(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(&m_reg.controller_data) = guitar_data; } bool Guitar::IsButtonPressed() const diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/Nunchuk.cpp b/Source/Core/Core/HW/WiimoteEmu/Extension/Nunchuk.cpp index 91dd8bf176..184ed25fc7 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Extension/Nunchuk.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/Nunchuk.cpp @@ -8,6 +8,7 @@ #include #include +#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(&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(&m_reg.controller_data) = nc_data; } bool Nunchuk::IsButtonPressed() const diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/Turntable.cpp b/Source/Core/Core/HW/WiimoteEmu/Extension/Turntable.cpp index 2871a73339..30964b91e9 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Extension/Turntable.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/Turntable.cpp @@ -8,6 +8,7 @@ #include #include +#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(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(&m_reg.controller_data) = tt_data; } bool Turntable::IsButtonPressed() const diff --git a/Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h b/Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h index 13dcc0025d..42640b6edb 100644 --- a/Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h +++ b/Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h @@ -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); diff --git a/Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp b/Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp index 6c3787a83e..faa4a90ff2 100644 --- a/Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp @@ -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 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 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(®_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(®_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 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 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 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(data); + DataFormat mplus_data = Common::BitCastPtr(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(data) = mplus_data; } } // namespace WiimoteEmu diff --git a/Source/Core/Core/HW/WiimoteEmu/MotionPlus.h b/Source/Core/Core/HW/WiimoteEmu/MotionPlus.h index 211e666153..06bc21b441 100644 --- a/Source/Core/Core/HW/WiimoteEmu/MotionPlus.h +++ b/Source/Core/Core/HW/WiimoteEmu/MotionPlus.h @@ -96,9 +96,9 @@ private: enum class PassthroughMode : u8 { - DISABLED = 0x04, - NUNCHUK = 0x05, - CLASSIC = 0x07, + Disabled = 0x04, + Nunchuk = 0x05, + Classic = 0x07, }; bool IsActive() const; diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index cd2b10347c..b99b577265 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -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: diff --git a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp index a5f9b569ad..8f6c69c448 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp @@ -449,7 +449,7 @@ bool IsWiimote(const std::basic_string& 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& 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)) diff --git a/Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp b/Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp index 2d5a89672c..e2abdafa80 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp @@ -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) diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp index e930a2b547..b7dab2fefe 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp @@ -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(&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(&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(&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(&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."); diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h index 15c955986f..01e1001f57 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h @@ -25,7 +25,7 @@ namespace WiimoteReal { using WiimoteCommon::MAX_PAYLOAD; -typedef std::vector Report; +using Report = std::vector; constexpr u32 WIIMOTE_DEFAULT_TIMEOUT = 1000; diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index ae12975895..93cc595eb6 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -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(); diff --git a/Source/Core/Core/Movie.h b/Source/Core/Core/Movie.h index aac76fdd84..02acfa6661 100644 --- a/Source/Core/Core/Movie.h +++ b/Source/Core/Core/Movie.h @@ -10,14 +10,22 @@ #include #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 diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 0acee31f3a..9daa698166 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -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( - static_cast( - Wiimote::GetConfig()->GetController(static_cast(i))) - ->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Extension)) - ->switch_extension = netplay_settings.m_WiimoteExtension[i]; + static_cast( + static_cast(Wiimote::GetConfig()->GetController(int(i))) + ->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Attachments)) + ->SetSelectedAttachment(netplay_settings.m_WiimoteExtension[i]); } } } diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 9a96346f0f..c12bafb5b2 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -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( - static_cast( - Wiimote::GetConfig()->GetController(static_cast(i))) - ->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Extension)) - ->switch_extension; + const int extension = + static_cast( + static_cast(Wiimote::GetConfig()->GetController(int(i))) + ->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Attachments)) + ->GetSelectedAttachment(); spac << extension; } diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.h index 746bc523ab..81e76eccfe 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.h +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Attachments.h @@ -32,6 +32,6 @@ public: private: std::vector> m_attachments; - std::atomic m_selected_attachment; + std::atomic m_selected_attachment = {}; }; } // namespace ControllerEmu