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:
commit
a9cf8670e0
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue