WiimoteEmu: Get rid of pointer casting in extension GetState() functions

We can just memcpy the data instead of pointer-casting data, which is
alignment-safe and doesn't run afoul of aliasing rules.

Previously it also made it seem as if data itself pointed to valid
usable data, but it doesn't, it simply functions as an out parameter
where we push data built up from the GetState() functions into it.
This commit is contained in:
Lioncash 2018-05-27 21:57:50 -04:00
parent 686e29f2d3
commit 6ad6781bd3
5 changed files with 83 additions and 78 deletions

View File

@ -131,8 +131,7 @@ Classic::Classic(ExtensionReg& reg) : Attachment(_trans("Classic"), reg)
void Classic::GetState(u8* const data) void Classic::GetState(u8* const data)
{ {
wm_classic_extension* const ccdata = reinterpret_cast<wm_classic_extension*>(data); wm_classic_extension classic_data = {};
ccdata->bt.hex = 0;
// not using calibration data, o well // not using calibration data, o well
@ -141,48 +140,50 @@ void Classic::GetState(u8* const data)
ControlState x, y; ControlState x, y;
m_left_stick->GetState(&x, &y); m_left_stick->GetState(&x, &y);
ccdata->regular_data.lx = classic_data.regular_data.lx =
static_cast<u8>(Classic::LEFT_STICK_CENTER_X + (x * Classic::LEFT_STICK_RADIUS)); static_cast<u8>(Classic::LEFT_STICK_CENTER_X + (x * Classic::LEFT_STICK_RADIUS));
ccdata->regular_data.ly = classic_data.regular_data.ly =
static_cast<u8>(Classic::LEFT_STICK_CENTER_Y + (y * Classic::LEFT_STICK_RADIUS)); static_cast<u8>(Classic::LEFT_STICK_CENTER_Y + (y * Classic::LEFT_STICK_RADIUS));
} }
// right stick // right stick
{ {
ControlState x, y; ControlState x, y;
u8 x_, y_;
m_right_stick->GetState(&x, &y); m_right_stick->GetState(&x, &y);
x_ = static_cast<u8>(Classic::RIGHT_STICK_CENTER_X + (x * Classic::RIGHT_STICK_RADIUS)); const u8 x_ =
y_ = static_cast<u8>(Classic::RIGHT_STICK_CENTER_Y + (y * Classic::RIGHT_STICK_RADIUS)); static_cast<u8>(Classic::RIGHT_STICK_CENTER_X + (x * Classic::RIGHT_STICK_RADIUS));
const u8 y_ =
static_cast<u8>(Classic::RIGHT_STICK_CENTER_Y + (y * Classic::RIGHT_STICK_RADIUS));
ccdata->rx1 = x_; classic_data.rx1 = x_;
ccdata->rx2 = x_ >> 1; classic_data.rx2 = x_ >> 1;
ccdata->rx3 = x_ >> 3; classic_data.rx3 = x_ >> 3;
ccdata->ry = y_; classic_data.ry = y_;
} }
// triggers // triggers
{ {
ControlState trigs[2] = {0, 0}; ControlState trigs[2] = {0, 0};
u8 lt, rt; m_triggers->GetState(&classic_data.bt.hex, classic_trigger_bitmasks.data(), trigs);
m_triggers->GetState(&ccdata->bt.hex, classic_trigger_bitmasks.data(), trigs);
lt = static_cast<u8>(trigs[0] * Classic::LEFT_TRIGGER_RANGE); const u8 lt = static_cast<u8>(trigs[0] * Classic::LEFT_TRIGGER_RANGE);
rt = static_cast<u8>(trigs[1] * Classic::RIGHT_TRIGGER_RANGE); const u8 rt = static_cast<u8>(trigs[1] * Classic::RIGHT_TRIGGER_RANGE);
ccdata->lt1 = lt; classic_data.lt1 = lt;
ccdata->lt2 = lt >> 3; classic_data.lt2 = lt >> 3;
ccdata->rt = rt; classic_data.rt = rt;
} }
// buttons // buttons
m_buttons->GetState(&ccdata->bt.hex, classic_button_bitmasks.data()); m_buttons->GetState(&classic_data.bt.hex, classic_button_bitmasks.data());
// dpad // dpad
m_dpad->GetState(&ccdata->bt.hex, classic_dpad_bitmasks.data()); m_dpad->GetState(&classic_data.bt.hex, classic_dpad_bitmasks.data());
// flip button bits // flip button bits
ccdata->bt.hex ^= 0xFFFF; classic_data.bt.hex ^= 0xFFFF;
std::memcpy(data, &classic_data, sizeof(wm_classic_extension));
} }
bool Classic::IsButtonPressed() const bool Classic::IsButtonPressed() const

View File

@ -6,6 +6,7 @@
#include <array> #include <array>
#include <cassert> #include <cassert>
#include <cstring>
#include "Common/Common.h" #include "Common/Common.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
@ -67,8 +68,7 @@ Drums::Drums(ExtensionReg& reg) : Attachment(_trans("Drums"), reg)
void Drums::GetState(u8* const data) void Drums::GetState(u8* const data)
{ {
wm_drums_extension* const ddata = reinterpret_cast<wm_drums_extension*>(data); wm_drums_extension drum_data = {};
ddata->bt = 0;
// calibration data not figured out yet? // calibration data not figured out yet?
@ -77,8 +77,8 @@ void Drums::GetState(u8* const data)
ControlState x, y; ControlState x, y;
m_stick->GetState(&x, &y); m_stick->GetState(&x, &y);
ddata->sx = static_cast<u8>((x * 0x1F) + 0x20); drum_data.sx = static_cast<u8>((x * 0x1F) + 0x20);
ddata->sy = static_cast<u8>((y * 0x1F) + 0x20); drum_data.sy = static_cast<u8>((y * 0x1F) + 0x20);
} }
// TODO: softness maybe // TODO: softness maybe
@ -86,12 +86,14 @@ void Drums::GetState(u8* const data)
data[3] = 0xFF; data[3] = 0xFF;
// buttons // buttons
m_buttons->GetState(&ddata->bt, drum_button_bitmasks.data()); m_buttons->GetState(&drum_data.bt, drum_button_bitmasks.data());
// pads // pads
m_pads->GetState(&ddata->bt, drum_pad_bitmasks.data()); m_pads->GetState(&drum_data.bt, drum_pad_bitmasks.data());
// flip button bits // flip button bits
ddata->bt ^= 0xFFFF; drum_data.bt ^= 0xFFFF;
std::memcpy(data, &drum_data, sizeof(wm_drums_extension));
} }
bool Drums::IsButtonPressed() const bool Drums::IsButtonPressed() const

View File

@ -6,7 +6,7 @@
#include <array> #include <array>
#include <cassert> #include <cassert>
#include <cstring>
#include <map> #include <map>
#include "Common/Common.h" #include "Common/Common.h"
@ -100,8 +100,7 @@ Guitar::Guitar(ExtensionReg& reg) : Attachment(_trans("Guitar"), reg)
void Guitar::GetState(u8* const data) void Guitar::GetState(u8* const data)
{ {
wm_guitar_extension* const gdata = reinterpret_cast<wm_guitar_extension*>(data); wm_guitar_extension guitar_data = {};
gdata->bt = 0;
// calibration data not figured out yet? // calibration data not figured out yet?
@ -110,8 +109,8 @@ void Guitar::GetState(u8* const data)
ControlState x, y; ControlState x, y;
m_stick->GetState(&x, &y); m_stick->GetState(&x, &y);
gdata->sx = static_cast<u8>((x * 0x1F) + 0x20); guitar_data.sx = static_cast<u8>((x * 0x1F) + 0x20);
gdata->sy = static_cast<u8>((y * 0x1F) + 0x20); guitar_data.sy = static_cast<u8>((y * 0x1F) + 0x20);
} }
// slider bar // slider bar
@ -119,28 +118,30 @@ void Guitar::GetState(u8* const data)
{ {
ControlState slider_bar; ControlState slider_bar;
m_slider_bar->GetState(&slider_bar); m_slider_bar->GetState(&slider_bar);
gdata->sb = s_slider_bar_control_codes.lower_bound(slider_bar)->second; guitar_data.sb = s_slider_bar_control_codes.lower_bound(slider_bar)->second;
} }
else else
{ {
// if user has not mapped controls for slider bar, tell game it's untouched // if user has not mapped controls for slider bar, tell game it's untouched
gdata->sb = 0x0F; guitar_data.sb = 0x0F;
} }
// whammy bar // whammy bar
ControlState whammy; ControlState whammy;
m_whammy->GetState(&whammy); m_whammy->GetState(&whammy);
gdata->whammy = static_cast<u8>(whammy * 0x1F); guitar_data.whammy = static_cast<u8>(whammy * 0x1F);
// buttons // buttons
m_buttons->GetState(&gdata->bt, guitar_button_bitmasks.data()); m_buttons->GetState(&guitar_data.bt, guitar_button_bitmasks.data());
// frets // frets
m_frets->GetState(&gdata->bt, guitar_fret_bitmasks.data()); m_frets->GetState(&guitar_data.bt, guitar_fret_bitmasks.data());
// strum // strum
m_strum->GetState(&gdata->bt, guitar_strum_bitmasks.data()); m_strum->GetState(&guitar_data.bt, guitar_strum_bitmasks.data());
// flip button bits // flip button bits
gdata->bt ^= 0xFFFF; guitar_data.bt ^= 0xFFFF;
std::memcpy(data, &guitar_data, sizeof(wm_guitar_extension));
} }
bool Guitar::IsButtonPressed() const bool Guitar::IsButtonPressed() const

View File

@ -6,6 +6,7 @@
#include <array> #include <array>
#include <cassert> #include <cassert>
#include <cstring>
#include "Common/Common.h" #include "Common/Common.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
@ -59,15 +60,14 @@ Nunchuk::Nunchuk(ExtensionReg& reg) : Attachment(_trans("Nunchuk"), reg)
void Nunchuk::GetState(u8* const data) void Nunchuk::GetState(u8* const data)
{ {
wm_nc* const ncdata = reinterpret_cast<wm_nc*>(data); wm_nc nc_data = {};
ncdata->bt.hex = 0;
// stick // stick
double jx, jy; double jx, jy;
m_stick->GetState(&jx, &jy); m_stick->GetState(&jx, &jy);
ncdata->jx = u8(STICK_CENTER + jx * STICK_RADIUS); nc_data.jx = u8(STICK_CENTER + jx * STICK_RADIUS);
ncdata->jy = u8(STICK_CENTER + jy * STICK_RADIUS); nc_data.jy = u8(STICK_CENTER + jy * STICK_RADIUS);
// Some terribly coded games check whether to move with a check like // Some terribly coded games check whether to move with a check like
// //
@ -77,12 +77,12 @@ void Nunchuk::GetState(u8* const data)
// With keyboard controls, these games break if you simply hit // With keyboard controls, these games break if you simply hit
// of the axes. Adjust this if you're hitting one of the axes so that // of the axes. Adjust this if you're hitting one of the axes so that
// we slightly tweak the other axis. // we slightly tweak the other axis.
if (ncdata->jx != STICK_CENTER || ncdata->jy != STICK_CENTER) if (nc_data.jx != STICK_CENTER || nc_data.jy != STICK_CENTER)
{ {
if (ncdata->jx == STICK_CENTER) if (nc_data.jx == STICK_CENTER)
++ncdata->jx; ++nc_data.jx;
if (ncdata->jy == STICK_CENTER) if (nc_data.jy == STICK_CENTER)
++ncdata->jy; ++nc_data.jy;
} }
AccelData accel; AccelData accel;
@ -95,10 +95,10 @@ void Nunchuk::GetState(u8* const data)
// shake // shake
EmulateShake(&accel, m_shake, m_shake_step.data()); EmulateShake(&accel, m_shake, m_shake_step.data());
// buttons // buttons
m_buttons->GetState(&ncdata->bt.hex, nunchuk_button_bitmasks.data()); m_buttons->GetState(&nc_data.bt.hex, nunchuk_button_bitmasks.data());
// flip the button bits :/ // flip the button bits :/
ncdata->bt.hex ^= 0x03; nc_data.bt.hex ^= 0x03;
// We now use 2 bits more precision, so multiply by 4 before converting to int // We now use 2 bits more precision, so multiply by 4 before converting to int
s16 accel_x = (s16)(4 * (accel.x * ACCEL_RANGE + ACCEL_ZERO_G)); s16 accel_x = (s16)(4 * (accel.x * ACCEL_RANGE + ACCEL_ZERO_G));
@ -109,12 +109,14 @@ void Nunchuk::GetState(u8* const data)
accel_y = MathUtil::Clamp<s16>(accel_y, 0, 1024); accel_y = MathUtil::Clamp<s16>(accel_y, 0, 1024);
accel_z = MathUtil::Clamp<s16>(accel_z, 0, 1024); accel_z = MathUtil::Clamp<s16>(accel_z, 0, 1024);
ncdata->ax = (accel_x >> 2) & 0xFF; nc_data.ax = (accel_x >> 2) & 0xFF;
ncdata->ay = (accel_y >> 2) & 0xFF; nc_data.ay = (accel_y >> 2) & 0xFF;
ncdata->az = (accel_z >> 2) & 0xFF; nc_data.az = (accel_z >> 2) & 0xFF;
ncdata->bt.acc_x_lsb = accel_x & 0x3; nc_data.bt.acc_x_lsb = accel_x & 0x3;
ncdata->bt.acc_y_lsb = accel_y & 0x3; nc_data.bt.acc_y_lsb = accel_y & 0x3;
ncdata->bt.acc_z_lsb = accel_z & 0x3; nc_data.bt.acc_z_lsb = accel_z & 0x3;
std::memcpy(data, &nc_data, sizeof(wm_nc));
} }
bool Nunchuk::IsButtonPressed() const bool Nunchuk::IsButtonPressed() const

View File

@ -6,6 +6,7 @@
#include <array> #include <array>
#include <cassert> #include <cassert>
#include <cstring>
#include "Common/Common.h" #include "Common/Common.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
@ -85,54 +86,50 @@ Turntable::Turntable(ExtensionReg& reg) : Attachment(_trans("Turntable"), reg)
void Turntable::GetState(u8* const data) void Turntable::GetState(u8* const data)
{ {
wm_turntable_extension* const ttdata = reinterpret_cast<wm_turntable_extension*>(data); wm_turntable_extension tt_data = {};
ttdata->bt = 0;
// stick // stick
{ {
ControlState x, y; ControlState x, y;
m_stick->GetState(&x, &y); m_stick->GetState(&x, &y);
ttdata->sx = static_cast<u8>((x * 0x1F) + 0x20); tt_data.sx = static_cast<u8>((x * 0x1F) + 0x20);
ttdata->sy = static_cast<u8>((y * 0x1F) + 0x20); tt_data.sy = static_cast<u8>((y * 0x1F) + 0x20);
} }
// left table // left table
{ {
ControlState tt; ControlState tt;
s8 tt_;
m_left_table->GetState(&tt); m_left_table->GetState(&tt);
tt_ = static_cast<s8>(tt * 0x1F); const s8 tt_ = static_cast<s8>(tt * 0x1F);
ttdata->ltable1 = tt_; tt_data.ltable1 = tt_;
ttdata->ltable2 = tt_ >> 5; tt_data.ltable2 = tt_ >> 5;
} }
// right table // right table
{ {
ControlState tt; ControlState tt;
s8 tt_;
m_right_table->GetState(&tt); m_right_table->GetState(&tt);
tt_ = static_cast<s8>(tt * 0x1F); const s8 tt_ = static_cast<s8>(tt * 0x1F);
ttdata->rtable1 = tt_; tt_data.rtable1 = tt_;
ttdata->rtable2 = tt_ >> 1; tt_data.rtable2 = tt_ >> 1;
ttdata->rtable3 = tt_ >> 3; tt_data.rtable3 = tt_ >> 3;
ttdata->rtable4 = tt_ >> 5; tt_data.rtable4 = tt_ >> 5;
} }
// effect dial // effect dial
{ {
ControlState dial; ControlState dial;
u8 dial_;
m_effect_dial->GetState(&dial); m_effect_dial->GetState(&dial);
dial_ = static_cast<u8>(dial * 0x0F); const u8 dial_ = static_cast<u8>(dial * 0x0F);
ttdata->dial1 = dial_; tt_data.dial1 = dial_;
ttdata->dial2 = dial_ >> 3; tt_data.dial2 = dial_ >> 3;
} }
// crossfade slider // crossfade slider
@ -140,15 +137,17 @@ void Turntable::GetState(u8* const data)
ControlState cfs; ControlState cfs;
m_crossfade->GetState(&cfs); m_crossfade->GetState(&cfs);
ttdata->slider = static_cast<u8>((cfs * 0x07) + 0x08); tt_data.slider = static_cast<u8>((cfs * 0x07) + 0x08);
} }
// buttons // buttons
m_buttons->GetState(&ttdata->bt, turntable_button_bitmasks.data()); m_buttons->GetState(&tt_data.bt, turntable_button_bitmasks.data());
// flip button bits :/ // flip button bits :/
ttdata->bt ^= (BUTTON_L_GREEN | BUTTON_L_RED | BUTTON_L_BLUE | BUTTON_R_GREEN | BUTTON_R_RED | 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); BUTTON_R_BLUE | BUTTON_MINUS | BUTTON_PLUS | BUTTON_EUPHORIA);
std::memcpy(data, &tt_data, sizeof(wm_turntable_extension));
} }
bool Turntable::IsButtonPressed() const bool Turntable::IsButtonPressed() const