Skip to content
Permalink
Browse files

WiimoteEmu: Partially emulate i2c bus to more closely simulate the re…

…al thing. Transfer most of IR camera logic to the i2c bus. Temporarily break everything else.
  • Loading branch information...
jordan-woyak committed Nov 22, 2018
1 parent 6c40c47 commit ebc2e58fa480a51c3a44762e9143aa84e230db7c
@@ -261,66 +261,31 @@ void Wiimote::WriteData(const wm_write_data* const wd)
{
// Write to Control Register

// ignore second byte for extension area
if (0xA4 == (address >> 16))
address &= 0xFF00FF;

const u8 region_offset = (u8)address;
void* region_ptr = nullptr;
int region_size = 0;

switch (address >> 16)
{
// speaker
case 0xa2:
region_ptr = &m_reg_speaker;
region_size = WIIMOTE_REG_SPEAKER_SIZE;
break;

// extension register
case 0xa4:
region_ptr = (void*)&m_reg_ext;
region_size = WIIMOTE_REG_EXT_SIZE;
break;

// motion plus
case 0xa6:
region_ptr = &m_reg_motion_plus;
region_size = WIIMOTE_REG_EXT_SIZE;
break;

// ir
case 0xB0:
region_ptr = &m_reg_ir;
region_size = WIIMOTE_REG_IR_SIZE;
break;
}

if (region_ptr && (region_offset + wd->size <= region_size))
{
memcpy((u8*)region_ptr + region_offset, wd->data, wd->size);
}
else
return; // TODO: generate a writedata error reply
// TODO: generate a writedata error reply for wrong number of bytes written..
m_i2c_bus.BusWrite(address >> 17, address & 0xff, wd->size, wd->data);

if (&m_reg_ext == region_ptr)
{
// Run the key generation on all writes in the key area, it doesn't matter
// that we send it parts of a key, only the last full key will have an effect
if (address >= 0xa40040 && address <= 0xa4004c)
WiimoteGenerateKey(&m_ext_key, m_reg_ext.encryption_key);
}
else if (&m_reg_motion_plus == region_ptr)
{
// activate/deactivate motion plus
if (0x55 == m_reg_motion_plus.activated)
{
// maybe hacky
m_reg_motion_plus.activated = 0;
return;

RequestStatus();
}
}
// TODO: extension register stuff..

//if (false)//&m_reg_ext == region_ptr)
//{
// // Run the key generation on all writes in the key area, it doesn't matter
// // that we send it parts of a key, only the last full key will have an effect
// if (address >= 0xa40040 && address <= 0xa4004c)
// WiimoteGenerateKey(&m_ext_key, m_reg_ext.encryption_key);
//}
//else if (&m_reg_motion_plus == region_ptr)
//{
// // activate/deactivate motion plus
// if (0x55 == m_reg_motion_plus.activated)
// {
// // maybe hacky
// m_reg_motion_plus.activated = 0;

// RequestStatus();
// }
//}
}
break;

@@ -386,42 +351,11 @@ void Wiimote::ReadData(const wm_read_data* const rd)

const u8 region_offset = (u8)address;
void* region_ptr = nullptr;
int region_size = 0;
//int region_size = 0;

switch (address >> 16)
{
// speaker
case 0xa2:
region_ptr = &m_reg_speaker;
region_size = WIIMOTE_REG_SPEAKER_SIZE;
break;

// extension
case 0xa4:
region_ptr = (void*)&m_reg_ext;
region_size = WIIMOTE_REG_EXT_SIZE;
break;

// motion plus
case 0xa6:
// reading from 0xa6 returns error when mplus is activated
region_ptr = &m_reg_motion_plus;
region_size = WIIMOTE_REG_EXT_SIZE;
break;

// ir
case 0xb0:
region_ptr = &m_reg_ir;
region_size = WIIMOTE_REG_IR_SIZE;
break;
}
m_i2c_bus.BusRead(address >> 17, address & 0xff, rd->size, block);

if (region_ptr && (region_offset + size <= region_size))
{
memcpy(block, (u8*)region_ptr + region_offset, size);
}
else
size = 0; // generate read error
// TODO: generate read errors

if (&m_reg_ext == region_ptr)
{
@@ -527,7 +461,7 @@ void Wiimote::DoState(PointerWrap& p)
p.Do(m_ext_key);
p.DoArray(m_eeprom);
p.Do(m_reg_motion_plus);
p.Do(m_reg_ir);
p.Do(m_camera_logic.reg_data);
p.Do(m_reg_ext);
p.Do(m_reg_speaker);

@@ -82,27 +82,28 @@ static const u8 eeprom_data_16D0[] = {0x00, 0x00, 0x00, 0xFF, 0x11, 0xEE, 0x00,
0x33, 0xCC, 0x44, 0xBB, 0x00, 0x00, 0x66, 0x99,
0x77, 0x88, 0x00, 0x00, 0x2B, 0x01, 0xE8, 0x13};

// Counts are how many bytes of each feature are in a particular report
static const ReportFeatures reporting_mode_features[] = {
// 0x30: Core Buttons
{2, 0, 0, 0, 4},
// 0x31: Core Buttons and Accelerometer
{2, 4, 0, 0, 7},
{2, 3, 0, 0, 7},
// 0x32: Core Buttons with 8 Extension bytes
{2, 0, 0, 4, 12},
{2, 0, 0, 8, 12},
// 0x33: Core Buttons and Accelerometer with 12 IR bytes
{2, 4, 7, 0, 19},
{2, 3, 12, 0, 19},
// 0x34: Core Buttons with 19 Extension bytes
{2, 0, 0, 4, 23},
{2, 0, 0, 19, 23},
// 0x35: Core Buttons and Accelerometer with 16 Extension Bytes
{2, 4, 0, 7, 23},
{2, 3, 0, 16, 23},
// 0x36: Core Buttons with 10 IR bytes and 9 Extension Bytes
{2, 0, 4, 14, 23},
{2, 0, 10, 9, 23},
// 0x37: Core Buttons and Accelerometer with 10 IR bytes and 6 Extension Bytes
{2, 4, 7, 17, 23},
{2, 3, 10, 6, 23},
// 0x3d: 21 Extension Bytes
{0, 0, 0, 21, 23},

// UNSUPPORTED:
// 0x3d: 21 Extension Bytes
{0, 0, 0, 2, 23},
// 0x3e / 0x3f: Interleaved Core Buttons and Accelerometer with 36 IR bytes
{0, 0, 0, 0, 23},
};
@@ -328,7 +329,8 @@ void Wiimote::Reset()

// set up the register
memset(&m_reg_speaker, 0, sizeof(m_reg_speaker));
memset(&m_reg_ir, 0, sizeof(m_reg_ir));
// TODO: kill/move this
memset(&m_camera_logic.reg_data, 0, sizeof(m_camera_logic.reg_data));
memset(&m_reg_ext, 0, sizeof(m_reg_ext));
memset(&m_reg_motion_plus, 0, sizeof(m_reg_motion_plus));

@@ -359,6 +361,9 @@ void Wiimote::Reset()
// Yamaha ADPCM state initialize
m_adpcm_state.predictor = 0;
m_adpcm_state.step = 127;

// Initialize i2c bus
m_i2c_bus.AddSlave(0x58, &m_camera_logic);
}

Wiimote::Wiimote(const unsigned int index) : m_index(index), ir_sin(0), ir_cos(1)
@@ -602,7 +607,7 @@ void Wiimote::GetButtonData(u8* const data)
reinterpret_cast<wm_buttons*>(data)->hex |= m_status.buttons.hex;
}

void Wiimote::GetAccelData(u8* const data, const ReportFeatures& rptf)
void Wiimote::GetAccelData(u8* const data)
{
const bool sideways_modifier_toggle = m_hotkeys->getSettingsModifier()[0];
const bool upright_modifier_toggle = m_hotkeys->getSettingsModifier()[1];
@@ -653,8 +658,9 @@ void Wiimote::GetAccelData(u8* const data, const ReportFeatures& rptf)
EmulateDynamicShake(&m_accel, m_shake_dynamic_data, m_shake_dynamic, shake_config,
m_shake_dynamic_step.data());

wm_accel& accel = *reinterpret_cast<wm_accel*>(data + rptf.accel);
wm_buttons& core = *reinterpret_cast<wm_buttons*>(data + rptf.core);
// TODO: kill these ugly looking offsets
wm_accel& accel = *reinterpret_cast<wm_accel*>(data + 4);
wm_buttons& core = *reinterpret_cast<wm_buttons*>(data + 2);

// We now use 2 bits more precision, so multiply by 4 before converting to int
s16 x = (s16)(4 * (m_accel.x * ACCEL_RANGE + ACCEL_ZERO_G));
@@ -683,8 +689,11 @@ inline void LowPassFilter(double& var, double newval, double period)
var = newval * alpha + var * (1.0 - alpha);
}

void Wiimote::GetIRData(u8* const data, bool use_accel)
void Wiimote::UpdateIRData(bool use_accel)
{
// IR data is stored at offset 0x37
u8* const data = m_camera_logic.reg_data.camera_data;

u16 x[4], y[4];
memset(x, 0xFF, sizeof(x));

@@ -770,9 +779,9 @@ void Wiimote::GetIRData(u8* const data, bool use_accel)
}

// Fill report with valid data when full handshake was done
if (m_reg_ir.data[0x30])
if (m_camera_logic.reg_data.data[0x30])
// ir mode
switch (m_reg_ir.mode)
switch (m_camera_logic.reg_data.mode)
{
// basic
case 1:
@@ -877,21 +886,40 @@ void Wiimote::Update()
// hotkey/settings modifier
m_hotkeys->GetState(); // data is later accessed in UpdateButtonsStatus and GetAccelData

// Data starts at byte 2 in the report
u8* feature_ptr = data + 2;

// core buttons
if (rptf.core)
GetButtonData(data + rptf.core);
{
GetButtonData(feature_ptr);
feature_ptr += rptf.core;
}

// acceleration
if (rptf.accel)
GetAccelData(data, rptf);
{
// TODO: GetAccelData has hardcoded payload offsets..
GetAccelData(data);
feature_ptr += rptf.accel;
}

// IR
// IR Camera
// TODO: kill use_accel param
// TODO: call only if camera logic is enabled?
UpdateIRData(rptf.accel != 0);
if (rptf.ir)
GetIRData(data + rptf.ir, (rptf.accel != 0));
{
m_i2c_bus.BusRead(0x58, 0x37, rptf.ir, feature_ptr);
feature_ptr += rptf.ir;
}

// extension
if (rptf.ext)
GetExtData(data + rptf.ext);
{
// GetExtData(feature_ptr, rptf.ext);
feature_ptr += rptf.ext;
}

Movie::CallWiiInputManip(data, rptf, m_index, m_extension->active_extension, m_ext_key);
}

0 comments on commit ebc2e58

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