Merge pull request #8224 from Pokechu22/wiimote-eeprom

Write the entirety of the Wiimote EEPROM, in a per-Wiimote file
This commit is contained in:
JosJuice 2019-11-20 22:03:53 +01:00 committed by GitHub
commit a9cf8670e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 90 additions and 67 deletions

View File

@ -290,6 +290,7 @@ void Stop() // - Hammertime!
g_video_backend->Video_ExitLoop(); g_video_backend->Video_ExitLoop();
} }
Wiimote::ResetAllWiimotes();
ResetRumble(); ResetRumble();
#ifdef USE_MEMORYWATCHER #ifdef USE_MEMORYWATCHER

View File

@ -63,6 +63,8 @@ enum class InitializeMode
// The Real Wii Remote sends report every ~5ms (200 Hz). // The Real Wii Remote sends report every ~5ms (200 Hz).
constexpr int UPDATE_FREQ = 200; constexpr int UPDATE_FREQ = 200;
// Custom channel ID used in ControlChannel to indicate disconnects
constexpr int DOLPHIN_DISCONNET_CONTROL_CHANNEL = 99;
void Shutdown(); void Shutdown();
void Initialize(InitializeMode init_mode); void Initialize(InitializeMode init_mode);

View File

@ -291,18 +291,7 @@ void Wiimote::HandleWriteData(const OutputReportWriteData& wd)
else else
{ {
std::copy_n(wd.data, wd.size, m_eeprom.data.data() + address); std::copy_n(wd.data, wd.size, m_eeprom.data.data() + address);
m_eeprom_dirty = true;
// 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();
}
} }
} }
break; break;
@ -486,18 +475,6 @@ bool Wiimote::ProcessReadDataRequest()
} }
else 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 // Read memory to be sent to Wii
std::copy_n(m_eeprom.data.data() + m_read_request.address, bytes_to_read, reply.data); std::copy_n(m_eeprom.data.data() + m_read_request.address, bytes_to_read, reply.data);
reply.size_minus_one = bytes_to_read - 1; reply.size_minus_one = bytes_to_read - 1;

View File

@ -12,6 +12,7 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Config/Config.h" #include "Common/Config/Config.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Common/MathUtil.h" #include "Common/MathUtil.h"
#include "Common/MsgHandler.h" #include "Common/MsgHandler.h"
@ -77,50 +78,86 @@ void Wiimote::Reset()
m_speaker_mute = false; m_speaker_mute = false;
// EEPROM // 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 = {}; m_eeprom = {};
// IR calibration: if (File::Exists(eeprom_file))
std::array<u8, 11> ir_calibration = { {
// Point 1 // Read existing EEPROM
IR_LOW_X & 0xFF, std::ifstream file;
IR_LOW_Y & 0xFF, File::OpenFStream(file, eeprom_file, std::ios::binary | std::ios::in);
// Mix file.read(reinterpret_cast<char*>(m_eeprom.data.data()), EEPROM_FREE_SIZE);
((IR_LOW_Y & 0x300) >> 2) | ((IR_LOW_X & 0x300) >> 4) | ((IR_LOW_Y & 0x300) >> 6) | file.close();
((IR_HIGH_X & 0x300) >> 8), }
// Point 2 else
IR_HIGH_X & 0xFF, {
IR_LOW_Y & 0xFF, // Load some default data.
// 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: // IR calibration:
// Last byte is a checksum. std::array<u8, 11> ir_calibration = {
std::array<u8, 10> accel_calibration = { // Point 1
ACCEL_ZERO_G, ACCEL_ZERO_G, ACCEL_ZERO_G, 0, ACCEL_ONE_G, ACCEL_ONE_G, ACCEL_ONE_G, 0, 0, 0, IR_LOW_X & 0xFF,
}; IR_LOW_Y & 0xFF,
UpdateCalibrationDataChecksum(accel_calibration, 1); // Mix
m_eeprom.accel_calibration_1 = accel_calibration; ((IR_LOW_Y & 0x300) >> 2) | ((IR_LOW_X & 0x300) >> 4) | ((IR_LOW_Y & 0x300) >> 6) |
m_eeprom.accel_calibration_2 = accel_calibration; ((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;
// TODO: Is this needed? // Accel calibration:
// Data of unknown purpose: // Last byte is a checksum.
constexpr std::array<u8, 24> EEPROM_DATA_16D0 = {0x00, 0x00, 0x00, 0xFF, 0x11, 0xEE, 0x00, 0x00, std::array<u8, 10> accel_calibration = {
0x33, 0xCC, 0x44, 0xBB, 0x00, 0x00, 0x66, 0x99, ACCEL_ZERO_G, ACCEL_ZERO_G, ACCEL_ZERO_G, 0, ACCEL_ONE_G, ACCEL_ONE_G, ACCEL_ONE_G, 0, 0, 0,
0x77, 0x88, 0x00, 0x00, 0x2B, 0x01, 0xE8, 0x13}; };
m_eeprom.unk_2 = EEPROM_DATA_16D0; 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 = {}; m_read_request = {};
@ -245,6 +282,8 @@ Wiimote::Wiimote(const unsigned int index) : m_index(index)
std::string Wiimote::GetName() const std::string Wiimote::GetName() const
{ {
if (m_index == WIIMOTE_BALANCE_BOARD)
return "BalanceBoard";
return fmt::format("Wiimote{}", 1 + m_index); 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) void Wiimote::ControlChannel(const u16 channel_id, const void* data, u32 size)
{ {
// Check for custom communication // Check for custom communication
if (99 == channel_id) if (channel_id == ::Wiimote::DOLPHIN_DISCONNET_CONTROL_CHANNEL)
{ {
// Wii Remote disconnected. // Wii Remote disconnected.
Reset(); Reset();

View File

@ -291,6 +291,7 @@ private:
bool m_is_motion_plus_attached; bool m_is_motion_plus_attached;
bool m_eeprom_dirty = false;
ReadRequest m_read_request; ReadRequest m_read_request;
UsableEEPROMData m_eeprom; UsableEEPROMData m_eeprom;

View File

@ -143,7 +143,7 @@ void Wiimote::ClearReadQueue()
void Wiimote::ControlChannel(const u16 channel, const void* const data, const u32 size) void Wiimote::ControlChannel(const u16 channel, const void* const data, const u32 size)
{ {
// Check for custom communication // Check for custom communication
if (channel == 99) if (channel == ::Wiimote::DOLPHIN_DISCONNET_CONTROL_CHANNEL)
{ {
if (m_really_disconnect) if (m_really_disconnect)
{ {

View File

@ -20,6 +20,7 @@
#include "Core/HW/DVD/DVDInterface.h" #include "Core/HW/DVD/DVDInterface.h"
#include "Core/HW/Memmap.h" #include "Core/HW/Memmap.h"
#include "Core/HW/SystemTimers.h" #include "Core/HW/SystemTimers.h"
#include "Core/HW/Wiimote.h"
#include "Core/Host.h" #include "Core/Host.h"
#include "Core/PowerPC/PPCSymbolDB.h" #include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
@ -35,6 +36,7 @@ static void ReinitHardware()
// MIOS appears to only reset the DI and the PPC. // MIOS appears to only reset the DI and the PPC.
DVDInterface::Reset(); DVDInterface::Reset();
PowerPC::Reset(); PowerPC::Reset();
Wiimote::ResetAllWiimotes();
// Note: this is specific to Dolphin and is required because we initialised it in Wii mode. // Note: this is specific to Dolphin and is required because we initialised it in Wii mode.
DSP::Reinit(SConfig::GetInstance().bDSPHLE); DSP::Reinit(SConfig::GetInstance().bDSPHLE);
DSP::GetDSPEmulator()->Initialize(SConfig::GetInstance().bWii, SConfig::GetInstance().bDSPThread); DSP::GetDSPEmulator()->Initialize(SConfig::GetInstance().bWii, SConfig::GetInstance().bDSPThread);

View File

@ -218,7 +218,8 @@ void WiimoteDevice::EventConnectionAccepted()
void WiimoteDevice::EventDisconnect() void WiimoteDevice::EventDisconnect()
{ {
// Send disconnect message to plugin // 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; m_connection_state = ConnectionState::Inactive;