Skip to content
Permalink
Browse files

Merge pull request #8224 from Pokechu22/wiimote-eeprom

Write the entirety of the Wiimote EEPROM, in a per-Wiimote file
  • Loading branch information
JosJuice committed Nov 20, 2019
2 parents 9ef526c + 4d4a095 commit a9cf8670e00bf272df8db55ea55ed365505b86cd
@@ -290,6 +290,7 @@ void Stop() // - Hammertime!
g_video_backend->Video_ExitLoop();
}

Wiimote::ResetAllWiimotes();
ResetRumble();

#ifdef USE_MEMORYWATCHER
@@ -63,6 +63,8 @@ enum class InitializeMode

// The Real Wii Remote sends report every ~5ms (200 Hz).
constexpr int UPDATE_FREQ = 200;
// Custom channel ID used in ControlChannel to indicate disconnects
constexpr int DOLPHIN_DISCONNET_CONTROL_CHANNEL = 99;

void Shutdown();
void Initialize(InitializeMode init_mode);
@@ -291,18 +291,7 @@ void Wiimote::HandleWriteData(const OutputReportWriteData& wd)
else
{
std::copy_n(wd.data, wd.size, m_eeprom.data.data() + address);

// Write mii data to file
if (address >= 0x0FCA && address < 0x12C0)
{
// TODO: Only write parts of the Mii block.
// TODO: Use different 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);
file.write((char*)m_eeprom.data.data() + 0x0FCA, 0x02f0);
file.close();
}
m_eeprom_dirty = true;
}
}
break;
@@ -486,18 +475,6 @@ bool Wiimote::ProcessReadDataRequest()
}
else
{
// Mii block handling:
// TODO: different filename for each wiimote?
if (m_read_request.address >= 0x0FCA && m_read_request.address < 0x12C0)
{
// TODO: Only read the Mii block parts required
std::ifstream file;
File::OpenFStream(file, (File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/mii.bin").c_str(),
std::ios::binary | std::ios::in);
file.read((char*)m_eeprom.data.data() + 0x0FCA, 0x02f0);
file.close();
}

// Read memory to be sent to Wii
std::copy_n(m_eeprom.data.data() + m_read_request.address, bytes_to_read, reply.data);
reply.size_minus_one = bytes_to_read - 1;
@@ -12,6 +12,7 @@

#include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Common/MathUtil.h"
#include "Common/MsgHandler.h"
@@ -77,50 +78,86 @@ void Wiimote::Reset()
m_speaker_mute = false;

// EEPROM
std::string eeprom_file = (File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/" + GetName() + ".bin");
if (m_eeprom_dirty)
{
// Write out existing EEPROM
INFO_LOG(WIIMOTE, "Wrote EEPROM for %s", GetName().c_str());
std::ofstream file;
File::OpenFStream(file, eeprom_file, std::ios::binary | std::ios::out);
file.write(reinterpret_cast<char*>(m_eeprom.data.data()), EEPROM_FREE_SIZE);
file.close();

m_eeprom_dirty = false;
}
m_eeprom = {};

// IR calibration:
std::array<u8, 11> ir_calibration = {
// Point 1
IR_LOW_X & 0xFF,
IR_LOW_Y & 0xFF,
// Mix
((IR_LOW_Y & 0x300) >> 2) | ((IR_LOW_X & 0x300) >> 4) | ((IR_LOW_Y & 0x300) >> 6) |
((IR_HIGH_X & 0x300) >> 8),
// Point 2
IR_HIGH_X & 0xFF,
IR_LOW_Y & 0xFF,
// Point 3
IR_HIGH_X & 0xFF,
IR_HIGH_Y & 0xFF,
// Mix
((IR_HIGH_Y & 0x300) >> 2) | ((IR_HIGH_X & 0x300) >> 4) | ((IR_HIGH_Y & 0x300) >> 6) |
((IR_LOW_X & 0x300) >> 8),
// Point 4
IR_LOW_X & 0xFF,
IR_HIGH_Y & 0xFF,
// Checksum
0x00,
};
UpdateCalibrationDataChecksum(ir_calibration, 1);
m_eeprom.ir_calibration_1 = ir_calibration;
m_eeprom.ir_calibration_2 = ir_calibration;

// Accel calibration:
// Last byte is a checksum.
std::array<u8, 10> accel_calibration = {
ACCEL_ZERO_G, ACCEL_ZERO_G, ACCEL_ZERO_G, 0, ACCEL_ONE_G, ACCEL_ONE_G, ACCEL_ONE_G, 0, 0, 0,
};
UpdateCalibrationDataChecksum(accel_calibration, 1);
m_eeprom.accel_calibration_1 = accel_calibration;
m_eeprom.accel_calibration_2 = accel_calibration;

// TODO: Is this needed?
// Data of unknown purpose:
constexpr std::array<u8, 24> EEPROM_DATA_16D0 = {0x00, 0x00, 0x00, 0xFF, 0x11, 0xEE, 0x00, 0x00,
0x33, 0xCC, 0x44, 0xBB, 0x00, 0x00, 0x66, 0x99,
0x77, 0x88, 0x00, 0x00, 0x2B, 0x01, 0xE8, 0x13};
m_eeprom.unk_2 = EEPROM_DATA_16D0;
if (File::Exists(eeprom_file))
{
// Read existing EEPROM
std::ifstream file;
File::OpenFStream(file, eeprom_file, std::ios::binary | std::ios::in);
file.read(reinterpret_cast<char*>(m_eeprom.data.data()), EEPROM_FREE_SIZE);
file.close();
}
else
{
// Load some default data.

// IR calibration:
std::array<u8, 11> ir_calibration = {
// Point 1
IR_LOW_X & 0xFF,
IR_LOW_Y & 0xFF,
// Mix
((IR_LOW_Y & 0x300) >> 2) | ((IR_LOW_X & 0x300) >> 4) | ((IR_LOW_Y & 0x300) >> 6) |
((IR_HIGH_X & 0x300) >> 8),
// Point 2
IR_HIGH_X & 0xFF,
IR_LOW_Y & 0xFF,
// Point 3
IR_HIGH_X & 0xFF,
IR_HIGH_Y & 0xFF,
// Mix
((IR_HIGH_Y & 0x300) >> 2) | ((IR_HIGH_X & 0x300) >> 4) | ((IR_HIGH_Y & 0x300) >> 6) |
((IR_LOW_X & 0x300) >> 8),
// Point 4
IR_LOW_X & 0xFF,
IR_HIGH_Y & 0xFF,
// Checksum
0x00,
};
UpdateCalibrationDataChecksum(ir_calibration, 1);
m_eeprom.ir_calibration_1 = ir_calibration;
m_eeprom.ir_calibration_2 = ir_calibration;

// Accel calibration:
// Last byte is a checksum.
std::array<u8, 10> accel_calibration = {
ACCEL_ZERO_G, ACCEL_ZERO_G, ACCEL_ZERO_G, 0, ACCEL_ONE_G, ACCEL_ONE_G, ACCEL_ONE_G, 0, 0, 0,
};
UpdateCalibrationDataChecksum(accel_calibration, 1);
m_eeprom.accel_calibration_1 = accel_calibration;
m_eeprom.accel_calibration_2 = accel_calibration;

// TODO: Is this needed?
// Data of unknown purpose:
constexpr std::array<u8, 24> EEPROM_DATA_16D0 = {
0x00, 0x00, 0x00, 0xFF, 0x11, 0xEE, 0x00, 0x00, 0x33, 0xCC, 0x44, 0xBB,
0x00, 0x00, 0x66, 0x99, 0x77, 0x88, 0x00, 0x00, 0x2B, 0x01, 0xE8, 0x13};
m_eeprom.unk_2 = EEPROM_DATA_16D0;

std::string mii_file = File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/mii.bin";
if (File::Exists(mii_file))
{
// Import from the existing mii.bin file, if present
std::ifstream file;
File::OpenFStream(file, mii_file, std::ios::binary | std::ios::in);
file.read(reinterpret_cast<char*>(m_eeprom.mii_data_1.data()), m_eeprom.mii_data_1.size());
m_eeprom.mii_data_2 = m_eeprom.mii_data_1;
file.close();
}
}

m_read_request = {};

@@ -245,6 +282,8 @@ Wiimote::Wiimote(const unsigned int index) : m_index(index)

std::string Wiimote::GetName() const
{
if (m_index == WIIMOTE_BALANCE_BOARD)
return "BalanceBoard";
return fmt::format("Wiimote{}", 1 + m_index);
}

@@ -533,7 +572,7 @@ void Wiimote::SendDataReport()
void Wiimote::ControlChannel(const u16 channel_id, const void* data, u32 size)
{
// Check for custom communication
if (99 == channel_id)
if (channel_id == ::Wiimote::DOLPHIN_DISCONNET_CONTROL_CHANNEL)
{
// Wii Remote disconnected.
Reset();
@@ -291,6 +291,7 @@ class Wiimote : public ControllerEmu::EmulatedController

bool m_is_motion_plus_attached;

bool m_eeprom_dirty = false;
ReadRequest m_read_request;
UsableEEPROMData m_eeprom;

@@ -143,7 +143,7 @@ void Wiimote::ClearReadQueue()
void Wiimote::ControlChannel(const u16 channel, const void* const data, const u32 size)
{
// Check for custom communication
if (channel == 99)
if (channel == ::Wiimote::DOLPHIN_DISCONNET_CONTROL_CHANNEL)
{
if (m_really_disconnect)
{
@@ -20,6 +20,7 @@
#include "Core/HW/DVD/DVDInterface.h"
#include "Core/HW/Memmap.h"
#include "Core/HW/SystemTimers.h"
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
@@ -35,6 +36,7 @@ static void ReinitHardware()
// MIOS appears to only reset the DI and the PPC.
DVDInterface::Reset();
PowerPC::Reset();
Wiimote::ResetAllWiimotes();
// Note: this is specific to Dolphin and is required because we initialised it in Wii mode.
DSP::Reinit(SConfig::GetInstance().bDSPHLE);
DSP::GetDSPEmulator()->Initialize(SConfig::GetInstance().bWii, SConfig::GetInstance().bDSPThread);
@@ -218,7 +218,8 @@ void WiimoteDevice::EventConnectionAccepted()
void WiimoteDevice::EventDisconnect()
{
// Send disconnect message to plugin
Wiimote::ControlChannel(m_connection_handle & 0xFF, 99, nullptr, 0);
Wiimote::ControlChannel(m_connection_handle & 0xFF, Wiimote::DOLPHIN_DISCONNET_CONTROL_CHANNEL,
nullptr, 0);

m_connection_state = ConnectionState::Inactive;

0 comments on commit a9cf867

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