Merge pull request #4784 from leoetlino/mios

IOS: Implement MIOS functionality
This commit is contained in:
Pierre Bourdon 2017-02-09 01:57:16 +01:00 committed by GitHub
commit 17e4b450fb
37 changed files with 496 additions and 181 deletions

View File

@ -37,6 +37,7 @@ public:
// Returns true if a map file exists, false if none could be found.
static bool FindMapFile(std::string* existing_map_file, std::string* writable_map_file,
std::string* title_id = nullptr);
static bool LoadMapFromFilename();
private:
static bool DVDRead(u64 dvd_offset, u32 output_address, u32 length, bool decrypt);
@ -44,7 +45,6 @@ private:
static void UpdateDebugger_MapLoaded();
static bool LoadMapFromFilename();
static bool Boot_ELF(const std::string& filename);
static bool Boot_WiiWAD(const std::string& filename);

View File

@ -278,7 +278,7 @@ bool CBoot::SetupWiiMemory(u64 ios_title_id)
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
if (!IOS::HLE::SetupMemory(ios_title_id))
if (!IOS::HLE::Reload(ios_title_id))
{
return false;
}

View File

@ -103,7 +103,7 @@ const char* ElfReader::GetSectionName(int section) const
}
// This is just a simple elf loader, good enough to load elfs generated by devkitPPC
bool ElfReader::LoadIntoMemory()
bool ElfReader::LoadIntoMemory(bool only_in_mem1)
{
INFO_LOG(MASTER_LOG, "String section: %i", header->e_shstrndx);
@ -133,6 +133,9 @@ bool ElfReader::LoadIntoMemory()
u32 srcSize = p->p_filesz;
u32 dstSize = p->p_memsz;
if (only_in_mem1 && p->p_vaddr >= Memory::REALRAM_SIZE)
continue;
Memory::CopyToEmu(writeAddr, src, srcSize);
if (srcSize < dstSize)
Memory::Memset(writeAddr + srcSize, 0, dstSize - srcSize); // zero out bss

View File

@ -40,7 +40,7 @@ public:
ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); }
u32 GetEntryPoint() const { return entryPoint; }
u32 GetFlags() const { return (u32)(header->e_flags); }
bool LoadIntoMemory();
bool LoadIntoMemory(bool only_in_mem1 = false);
bool LoadSymbols();
int GetNumSegments() const { return (int)(header->e_phnum); }

View File

@ -140,6 +140,7 @@ set(SRCS ActionReplay.cpp
IOS/Device.cpp
IOS/DeviceStub.cpp
IOS/IPC.cpp
IOS/MIOS.cpp
IOS/DI/DI.cpp
IOS/ES/ES.cpp
IOS/ES/Formats.cpp

View File

@ -188,6 +188,7 @@ struct SConfig : NonCopyable
BOOT_ELF,
BOOT_DOL,
BOOT_WII_NAND,
BOOT_MIOS,
BOOT_BS2,
BOOT_DFF
};

View File

@ -528,9 +528,11 @@ void EmuThread()
Wiimote::LoadConfig();
// Activate Wiimotes which don't have source set to "None"
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
for (unsigned int i = 0; i != MAX_BBMOTES; ++i)
if (g_wiimote_sources[i])
IOS::HLE::GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(true);
if (g_wiimote_sources[i] && bt)
bt->AccessWiiMote(i | 0x100)->Activate(true);
}
AudioCommon::InitSoundStream();
@ -632,10 +634,6 @@ void EmuThread()
FileMon::Close();
// Stop audio thread - Actually this does nothing when using HLE
// emulation, but stops the DSP Interpreter when using LLE emulation.
DSP::GetDSPEmulator()->DSP_StopSoundStream();
// We must set up this flag before executing HW::Shutdown()
s_hardware_initialized = false;
INFO_LOG(CONSOLE, "%s", StopMessage(false, "Shutting down HW").c_str());

View File

@ -172,6 +172,7 @@
<ClCompile Include="IOS\Device.cpp" />
<ClCompile Include="IOS\DeviceStub.cpp" />
<ClCompile Include="IOS\IPC.cpp" />
<ClCompile Include="IOS\MIOS.cpp" />
<ClCompile Include="IOS\DI\DI.cpp" />
<ClCompile Include="IOS\ES\ES.cpp" />
<ClCompile Include="IOS\ES\Formats.cpp" />
@ -408,6 +409,7 @@
<ClInclude Include="IOS\Device.h" />
<ClInclude Include="IOS\DeviceStub.h" />
<ClInclude Include="IOS\IPC.h" />
<ClInclude Include="IOS\MIOS.h" />
<ClInclude Include="IOS\DI\DI.h" />
<ClInclude Include="IOS\ES\ES.h" />
<ClInclude Include="IOS\ES\Formats.h" />

View File

@ -752,6 +752,9 @@
<ClCompile Include="IOS\IPC.cpp">
<Filter>IOS</Filter>
</ClCompile>
<ClCompile Include="IOS\MIOS.cpp">
<Filter>IOS</Filter>
</ClCompile>
<ClCompile Include="IOS\Network\Net.cpp">
<Filter>IOS\Network</Filter>
</ClCompile>
@ -1419,6 +1422,9 @@
<ClInclude Include="IOS\IPC.h">
<Filter>IOS</Filter>
</ClInclude>
<ClInclude Include="IOS\MIOS.h">
<Filter>IOS</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />

View File

@ -364,6 +364,16 @@ void LogPendingEvents()
}
}
// Should only be called from the CPU thread after the PPC clock has changed
void AdjustEventQueueTimes(u32 new_ppc_clock, u32 old_ppc_clock)
{
for (Event& ev : s_event_queue)
{
const s64 ticks = (ev.time - g_global_timer) * new_ppc_clock / old_ppc_clock;
ev.time = g_global_timer + ticks;
}
}
void Idle()
{
if (SConfig::GetInstance().bSyncGPUOnSkipIdleHack)

View File

@ -91,6 +91,8 @@ void LogPendingEvents();
std::string GetScheduledEventsSummary();
void AdjustEventQueueTimes(u32 new_ppc_clock, u32 old_ppc_clock);
u32 GetFakeDecStartValue();
void SetFakeDecStartValue(u32 val);
u64 GetFakeDecStartTicks();

View File

@ -177,6 +177,13 @@ DSPEmulator* GetDSPEmulator()
}
void Init(bool hle)
{
Reinit(hle);
s_et_GenerateDSPInterrupt = CoreTiming::RegisterEvent("DSPint", GenerateDSPInterrupt);
s_et_CompleteARAM = CoreTiming::RegisterEvent("ARAMint", CompleteARAM);
}
void Reinit(bool hle)
{
s_dsp_emulator = CreateDSPEmulator(hle);
s_dsp_is_lle = s_dsp_emulator->IsLLE();
@ -206,9 +213,6 @@ void Init(bool hle)
s_ARAM_Info.Hex = 0;
s_AR_MODE = 1; // ARAM Controller has init'd
s_AR_REFRESH = 156; // 156MHz
s_et_GenerateDSPInterrupt = CoreTiming::RegisterEvent("DSPint", GenerateDSPInterrupt);
s_et_CompleteARAM = CoreTiming::RegisterEvent("ARAMint", CompleteARAM);
}
void Shutdown()

View File

@ -60,6 +60,7 @@ union UDSPControl
};
void Init(bool hle);
void Reinit(bool hle);
void Shutdown();
void RegisterMMIO(MMIO::Mapping* mmio, u32 base);

View File

@ -37,6 +37,12 @@ static bool s_request_disable_thread;
DSPLLE::DSPLLE() = default;
DSPLLE::~DSPLLE()
{
DSPCore_Shutdown();
DSP_StopSoundStream();
}
void DSPLLE::DoState(PointerWrap& p)
{
bool is_hle = false;

View File

@ -22,6 +22,7 @@ class DSPLLE : public DSPEmulator
{
public:
DSPLLE();
~DSPLLE();
bool Initialize(bool wii, bool dsp_thread) override;
void Shutdown() override;

View File

@ -419,8 +419,24 @@ void Init()
{
DVDThread::Start();
s_DISR.Hex = 0;
Reset();
s_DICVR.Hex = 1; // Disc Channel relies on cover being open when no disc is inserted
s_disc_inside = false;
s_eject_disc = CoreTiming::RegisterEvent("EjectDisc", EjectDiscCallback);
s_insert_disc = CoreTiming::RegisterEvent("InsertDisc", InsertDiscCallback);
s_finish_executing_command =
CoreTiming::RegisterEvent("FinishExecutingCommand", FinishExecutingCommandCallback);
u64 userdata = PackFinishExecutingCommandUserdata(ReplyType::DTK, DIInterruptType::INT_TCINT);
CoreTiming::ScheduleEvent(0, s_finish_executing_command, userdata);
}
// This doesn't reset any inserted disc or the cover state.
void Reset()
{
s_DISR.Hex = 0;
s_DICMDBUF[0].Hex = 0;
s_DICMDBUF[1].Hex = 0;
s_DICMDBUF[2].Hex = 0;
@ -441,7 +457,6 @@ void Init()
s_pending_samples = 0;
s_error_code = 0;
s_disc_inside = false;
// The buffer is empty at start
s_read_buffer_start_offset = 0;
@ -450,15 +465,6 @@ void Init()
s_read_buffer_end_time = 0;
s_disc_path_to_insert.clear();
s_eject_disc = CoreTiming::RegisterEvent("EjectDisc", EjectDiscCallback);
s_insert_disc = CoreTiming::RegisterEvent("InsertDisc", InsertDiscCallback);
s_finish_executing_command =
CoreTiming::RegisterEvent("FinishExecutingCommand", FinishExecutingCommandCallback);
u64 userdata = PackFinishExecutingCommandUserdata(ReplyType::DTK, DIInterruptType::INT_TCINT);
CoreTiming::ScheduleEvent(0, s_finish_executing_command, userdata);
}
void Shutdown()

View File

@ -102,6 +102,7 @@ enum class ReplyType : u32
};
void Init();
void Reset();
void Shutdown();
void DoState(PointerWrap& p);

View File

@ -232,7 +232,10 @@ void CEXIIPL::SetCS(int _iCS)
void CEXIIPL::UpdateRTC()
{
u32 epoch = SConfig::GetInstance().bWii ? WII_EPOCH : GC_EPOCH;
u32 epoch =
(SConfig::GetInstance().bWii || SConfig::GetInstance().m_BootType == SConfig::BOOT_MIOS) ?
WII_EPOCH :
GC_EPOCH;
u32 rtc = Common::swap32(GetEmulatedTime(epoch));
std::memcpy(m_RTC, &rtc, sizeof(u32));
}

View File

@ -61,12 +61,11 @@ void Init()
void Shutdown()
{
// IOS should always be shut down regardless of bWii because it can be running in GC mode (MIOS).
IOS::HLE::Shutdown(); // Depends on Memory
IOS::Shutdown();
if (SConfig::GetInstance().bWii)
{
IOS::HLE::Shutdown(); // Depends on Memory
IOS::Shutdown();
Core::ShutdownWiiRoot();
}
SystemTimers::Shutdown();
CPU::Shutdown();

View File

@ -223,10 +223,17 @@ static void ThrottleCallback(u64 last_time, s64 cyclesLate)
// SystemTimers::Init
void PreInit()
{
if (SConfig::GetInstance().bWii)
ChangePPCClock(SConfig::GetInstance().bWii ? Mode::Wii : Mode::GC);
}
void ChangePPCClock(Mode mode)
{
const u32 previous_clock = s_cpu_core_clock;
if (mode == Mode::Wii)
s_cpu_core_clock = 729000000u;
else
s_cpu_core_clock = 486000000u;
CoreTiming::AdjustEventQueueTimes(s_cpu_core_clock, previous_clock);
}
void Init()

View File

@ -33,10 +33,17 @@ enum
TIMER_RATIO = 12
};
enum class Mode
{
GC,
Wii,
};
u32 GetTicksPerSecond();
void PreInit();
void Init();
void Shutdown();
void ChangePPCClock(Mode mode);
// Notify timing system that somebody wrote to the decrementer
void DecrementerSet();

View File

@ -317,6 +317,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
return Decrypt(request);
case IOCTL_ES_LAUNCH:
return Launch(request);
case IOCTL_ES_LAUNCHBC:
return LaunchBC(request);
case IOCTL_ES_CHECKKOREAREGION:
return CheckKoreaRegion(request);
case IOCTL_ES_GETDEVICECERT:
@ -1103,7 +1105,6 @@ IPCCommandResult ES::Launch(const IOCtlVRequest& request)
{
_dbg_assert_(IOS_ES, request.in_vectors.size() == 2);
bool bSuccess = false;
bool bReset = false;
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
u32 view = Memory::Read_U32(request.in_vectors[1].address);
@ -1112,6 +1113,9 @@ IPCCommandResult ES::Launch(const IOCtlVRequest& request)
u64 titleid = Memory::Read_U64(request.in_vectors[1].address + 16);
u16 access = Memory::Read_U16(request.in_vectors[1].address + 24);
NOTICE_LOG(IOS_ES, "IOCTL_ES_LAUNCH %016" PRIx64 " %08x %016" PRIx64 " %08x %016" PRIx64 " %04x",
TitleID, view, ticketid, devicetype, titleid, access);
// ES_LAUNCH should probably reset thw whole state, which at least means closing all open files.
// leaving them open through ES_LAUNCH may cause hangs and other funky behavior
// (supposedly when trying to re-open those files).
@ -1168,63 +1172,65 @@ IPCCommandResult ES::Launch(const IOCtlVRequest& request)
}
else
{
bool* wiiMoteConnected = new bool[MAX_BBMOTES];
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
{
BluetoothEmu* s_Usb = GetUsbPointer();
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
wiiMoteConnected[i] = s_Usb->m_WiiMotes[i].IsConnected();
}
Reset(true);
Reinit();
SetupMemory(ios_to_load);
bReset = true;
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
{
BluetoothEmu* s_Usb = GetUsbPointer();
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
{
if (wiiMoteConnected[i])
{
s_Usb->m_WiiMotes[i].Activate(false);
s_Usb->m_WiiMotes[i].Activate(true);
}
else
{
s_Usb->m_WiiMotes[i].Activate(false);
}
}
}
delete[] wiiMoteConnected;
ResetAfterLaunch(ios_to_load);
SetDefaultContentFile(tContentFile);
}
// Note: If we just reset the PPC, don't write anything to the command buffer. This
// could clobber the DOL we just loaded.
ERROR_LOG(IOS_ES, "IOCTL_ES_LAUNCH %016" PRIx64 " %08x %016" PRIx64 " %08x %016" PRIx64 " %04x",
TitleID, view, ticketid, devicetype, titleid, access);
// IOCTL_ES_LAUNCH 0001000248414341 00000001 0001c0fef3df2cfa 00000000
// 0001000248414341 ffff
// This is necessary because Reset(true) above deleted this object. Ew.
if (!bReset)
{
// The command type is overwritten with the reply type.
Memory::Write_U32(IPC_REPLY, request.address);
// IOS also writes back the command that was responded to in the FD field.
Memory::Write_U32(IPC_CMD_IOCTLV, request.address + 8);
}
// Generate a "reply" to the IPC command. ES_LAUNCH is unique because it
// involves restarting IOS; IOS generates two acknowledgements in a row.
// Note: If we just reset the PPC, don't write anything to the command buffer. This
// could clobber the DOL we just loaded.
EnqueueCommandAcknowledgement(request.address, 0);
return GetNoReply();
}
IPCCommandResult ES::LaunchBC(const IOCtlVRequest& request)
{
if (request.in_vectors.size() != 0 || request.io_vectors.size() != 0)
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
// Here, IOS checks the clock speed and prevents ioctlv 0x25 from being used in GC mode.
// An alternative way to do this is to check whether the current active IOS is MIOS.
if (GetVersion() == 0x101)
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
ResetAfterLaunch(0x00000001'00000100);
EnqueueCommandAcknowledgement(request.address, 0);
return GetNoReply();
}
void ES::ResetAfterLaunch(const u64 ios_to_load) const
{
auto bt = std::static_pointer_cast<BluetoothEmu>(GetDeviceByName("/dev/usb/oh1/57e/305"));
bool* wiiMoteConnected = new bool[MAX_BBMOTES];
if (!SConfig::GetInstance().m_bt_passthrough_enabled && bt)
{
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
wiiMoteConnected[i] = bt->m_WiiMotes[i].IsConnected();
}
Reload(ios_to_load);
// Get the new Bluetooth device. Note that it is not guaranteed to exist.
bt = std::static_pointer_cast<BluetoothEmu>(GetDeviceByName("/dev/usb/oh1/57e/305"));
if (!SConfig::GetInstance().m_bt_passthrough_enabled && bt)
{
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
{
if (wiiMoteConnected[i])
{
bt->m_WiiMotes[i].Activate(false);
bt->m_WiiMotes[i].Activate(true);
}
else
{
bt->m_WiiMotes[i].Activate(false);
}
}
}
delete[] wiiMoteConnected;
}
IPCCommandResult ES::CheckKoreaRegion(const IOCtlVRequest& request)
{
// note by DacoTaco : name is unknown, I just tried to name it SOMETHING.

View File

@ -90,7 +90,7 @@ private:
IOCTL_ES_DELETETITLECONTENT = 0x22,
IOCTL_ES_SEEKCONTENT = 0x23,
IOCTL_ES_OPENTITLECONTENT = 0x24,
// IOCTL_ES_LAUNCHBC = 0x25,
IOCTL_ES_LAUNCHBC = 0x25,
// IOCTL_ES_EXPORTTITLEINIT = 0x26,
// IOCTL_ES_EXPORTCONTENTBEGIN = 0x27,
// IOCTL_ES_EXPORTCONTENTDATA = 0x28,
@ -182,6 +182,7 @@ private:
IPCCommandResult Encrypt(const IOCtlVRequest& request);
IPCCommandResult Decrypt(const IOCtlVRequest& request);
IPCCommandResult Launch(const IOCtlVRequest& request);
IPCCommandResult LaunchBC(const IOCtlVRequest& request);
IPCCommandResult CheckKoreaRegion(const IOCtlVRequest& request);
IPCCommandResult GetDeviceCertificate(const IOCtlVRequest& request);
IPCCommandResult Sign(const IOCtlVRequest& request);
@ -189,6 +190,8 @@ private:
IPCCommandResult DIGetTicketView(const IOCtlVRequest& request);
IPCCommandResult GetOwnedTitleCount(const IOCtlVRequest& request);
void ResetAfterLaunch(u64 ios_to_load) const;
const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id);
u32 OpenTitleContent(u32 CFD, u64 TitleID, u16 Index);

View File

@ -42,6 +42,7 @@
#include "Core/IOS/FS/FS.h"
#include "Core/IOS/FS/FileIO.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/MIOS.h"
#include "Core/IOS/Network/Net.h"
#include "Core/IOS/Network/SSL.h"
#include "Core/IOS/Network/Socket.h"
@ -111,6 +112,7 @@ struct IosMemoryValues
u32 ram_vendor;
u32 unknown_begin;
u32 unknown_end;
u32 sysmenu_sync;
};
constexpr u32 ADDR_MEM1_SIZE = 0x3100;
@ -162,210 +164,210 @@ constexpr std::array<IosMemoryValues, 31> ios_memory_values = {
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
12, 0xc020e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
13, 0xd0408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
14, 0xe0408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
15, 0xf0408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
17, 0x110408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
21, 0x15040f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
22, 0x16050e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
28, 0x1c070f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93800000, MEM2_ARENA_BEGIN,
0x937E0000, 0x937E0000, 0x93800000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93800000, 0x93820000,
RAM_VENDOR, 0x93800000, 0x93820000, 0,
},
{
31, 0x1f0e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
33, 0x210e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
34, 0x220e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
35, 0x230e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
36, 0x240e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
37, 0x25161f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
38, 0x26101c, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
41, 0x290e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
43, 0x2b0e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
45, 0x2d0e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
46, 0x2e0e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
48, 0x30101c, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
53, 0x35161f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
55, 0x37161f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
56, 0x38161e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
57, 0x39171f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
58, 0x3a1820, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
59, 0x3b1c21, 0x101811, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
61, 0x3d161e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
62, 0x3e191e, 0x022712, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
80, 0x501b20, 0x030310, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
257,
@ -387,6 +389,7 @@ constexpr std::array<IosMemoryValues, 31> ios_memory_values = {
RAM_VENDOR_MIOS,
PLACEHOLDER,
PLACEHOLDER,
PLACEHOLDER,
}}};
static void EnqueueEvent(u64 userdata, s64 cycles_late = 0)
@ -421,7 +424,7 @@ u32 GetVersion()
return static_cast<u32>(s_active_title_id);
}
bool SetupMemory(u64 ios_title_id)
static bool SetupMemory(u64 ios_title_id)
{
auto target_imv = std::find_if(
ios_memory_values.begin(), ios_memory_values.end(),
@ -433,8 +436,6 @@ bool SetupMemory(u64 ios_title_id)
return false;
}
s_active_title_id = ios_title_id;
Memory::Write_U32(target_imv->mem1_physical_size, ADDR_MEM1_SIZE);
Memory::Write_U32(target_imv->mem1_simulated_size, ADDR_MEM1_SIM_SIZE);
Memory::Write_U32(target_imv->mem1_end, ADDR_MEM1_END);
@ -461,7 +462,7 @@ bool SetupMemory(u64 ios_title_id)
Memory::Write_U8(0xDE, ADDR_BOOT_FLAG);
Memory::Write_U8(0xAD, ADDR_APPLOADER_FLAG);
Memory::Write_U16(0xBEEF, ADDR_DEVKIT_BOOT_PROGRAM_VERSION);
Memory::Write_U32(0x00000000, ADDR_SYSMENU_SYNC);
Memory::Write_U32(target_imv->sysmenu_sync, ADDR_SYSMENU_SYNC);
return true;
}
@ -477,7 +478,7 @@ std::shared_ptr<T> AddDevice(const char* device_name)
return device;
}
void Reinit()
static void AddStaticDevices()
{
std::lock_guard<std::mutex> lock(s_device_map_mutex);
_assert_msg_(IOS, s_device_map.empty(), "Reinit called while already initialized");
@ -519,13 +520,11 @@ void Reinit()
void Init()
{
Reinit();
s_event_enqueue = CoreTiming::RegisterEvent("IPCEvent", EnqueueEvent);
s_event_sdio_notify = CoreTiming::RegisterEvent("SDIO_EventNotify", SDIO_EventNotify_CPUThread);
}
void Reset(bool hard)
void Reset(const bool clear_devices)
{
CoreTiming::RemoveAllEvents(s_event_enqueue);
@ -538,7 +537,7 @@ void Reset(bool hard)
device.reset();
}
if (hard)
if (clear_devices)
{
std::lock_guard<std::mutex> lock(s_device_map_mutex);
s_device_map.clear();
@ -555,6 +554,35 @@ void Shutdown()
Reset(true);
}
constexpr u64 BC_TITLE_ID = 0x0000000100000100;
constexpr u64 MIOS_TITLE_ID = 0x0000000100000101;
bool Reload(const u64 ios_title_id)
{
// A real Wii goes through several steps before getting to MIOS.
//
// * The System Menu detects a GameCube disc and launches BC (1-100) instead of the game.
// * BC (similar to boot1) lowers the clock speed to the Flipper's and then launches boot2.
// * boot2 sees the lowered clock speed and launches MIOS (1-101) instead of the System Menu.
//
// Because we currently don't have boot1 and boot2, and BC is only ever used to launch MIOS
// (indirectly via boot2), we can just launch MIOS when BC is launched.
if (ios_title_id == BC_TITLE_ID)
return Reload(MIOS_TITLE_ID);
if (!SetupMemory(ios_title_id))
return false;
s_active_title_id = ios_title_id;
Reset(true);
if (ios_title_id == MIOS_TITLE_ID)
return MIOS::Load();
AddStaticDevices();
return true;
}
void SetDefaultContentFile(const std::string& file_name)
{
std::lock_guard<std::mutex> lock(s_device_map_mutex);
@ -618,6 +646,10 @@ void DoState(PointerWrap& p)
p.Do(s_request_queue);
p.Do(s_reply_queue);
p.Do(s_last_reply_time);
p.Do(s_active_title_id);
if (s_active_title_id == MIOS_TITLE_ID)
return;
// We need to make sure all file handles are closed so IOS::HLE::Device::FS::DoState can
// successfully save or re-create /tmp

View File

@ -45,21 +45,16 @@ enum IPCCommandType : u32
IPC_REPLY = 8,
};
// Init
// Init events and devices
void Init();
// Needs to be called after Reset(true) to recreate the device tree
void Reinit();
u32 GetVersion();
bool SetupMemory(u64 ios_title_id);
// Reset all events and devices (and optionally clear them)
void Reset(bool clear_devices = false);
// Shutdown
void Shutdown();
// Reset
void Reset(bool hard = false);
// Reload IOS (to a possibly different version); set up memory and devices.
bool Reload(u64 ios_title_id);
u32 GetVersion();
// Do State
void DoState(PointerWrap& p);

View File

@ -0,0 +1,195 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <cstring>
#include <utility>
#include <vector>
#include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#include "Common/NandPaths.h"
#include "Core/Boot/Boot.h"
#include "Core/Boot/ElfReader.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/DSPEmulator.h"
#include "Core/HLE/HLE.h"
#include "Core/HW/DSP.h"
#include "Core/HW/DVDInterface.h"
#include "Core/HW/DVDThread.h"
#include "Core/HW/Memmap.h"
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/MIOS.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
#include "DiscIO/NANDContentLoader.h"
#include "DiscIO/Volume.h"
namespace IOS
{
namespace HLE
{
namespace MIOS
{
constexpr u64 MIOS_TITLE_ID = 0x0000000100000101;
// Source: https://wiibrew.org/wiki/ARM_Binaries
struct ARMBinary final
{
explicit ARMBinary(const std::vector<u8>& bytes);
explicit ARMBinary(std::vector<u8>&& bytes);
bool IsValid() const;
std::vector<u8> GetElf() const;
u32 GetHeaderSize() const;
u32 GetElfOffset() const;
u32 GetElfSize() const;
private:
std::vector<u8> m_bytes;
};
ARMBinary::ARMBinary(const std::vector<u8>& bytes) : m_bytes(bytes)
{
}
ARMBinary::ARMBinary(std::vector<u8>&& bytes) : m_bytes(std::move(bytes))
{
}
bool ARMBinary::IsValid() const
{
// The header is at least 0x10.
if (m_bytes.size() < 0x10)
return false;
return m_bytes.size() >= (GetHeaderSize() + GetElfOffset() + GetElfSize());
}
std::vector<u8> ARMBinary::GetElf() const
{
const auto iterator = m_bytes.cbegin() + GetHeaderSize() + GetElfOffset();
return std::vector<u8>(iterator, iterator + GetElfSize());
}
u32 ARMBinary::GetHeaderSize() const
{
return Common::swap32(m_bytes.data());
}
u32 ARMBinary::GetElfOffset() const
{
return Common::swap32(m_bytes.data() + 0x4);
}
u32 ARMBinary::GetElfSize() const
{
return Common::swap32(m_bytes.data() + 0x8);
}
static std::vector<u8> GetMIOSBinary()
{
const auto& loader =
DiscIO::CNANDContentManager::Access().GetNANDLoader(MIOS_TITLE_ID, Common::FROM_SESSION_ROOT);
if (!loader.IsValid())
return {};
const auto* content = loader.GetContentByIndex(loader.GetBootIndex());
if (!content)
return {};
return content->m_Data->Get();
}
static void ReinitHardware()
{
SConfig::GetInstance().bWii = false;
// IOS clears mem2 and overwrites it with pseudo-random data (for security).
std::memset(Memory::m_pEXRAM, 0, Memory::EXRAM_SIZE);
// MIOS appears to only reset the DI and the PPC.
DVDInterface::Reset();
PowerPC::Reset();
// 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);
SystemTimers::ChangePPCClock(SystemTimers::Mode::GC);
}
static void UpdateRunningGame()
{
DVDThread::WaitUntilIdle();
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
SConfig::GetInstance().m_BootType = SConfig::BOOT_MIOS;
SConfig::GetInstance().m_strName = volume.GetInternalName();
SConfig::GetInstance().m_strGameID = volume.GetGameID();
SConfig::GetInstance().m_revision = volume.GetRevision();
g_symbolDB.Clear();
CBoot::LoadMapFromFilename();
::HLE::Clear();
::HLE::PatchFunctions();
NOTICE_LOG(IOS, "Running game: %s (%s)", SConfig::GetInstance().m_strName.c_str(),
SConfig::GetInstance().m_strGameID.c_str());
}
constexpr u32 ADDRESS_INIT_SEMAPHORE = 0x30f8;
bool Load()
{
Memory::Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
Memory::Write_U32(0x09142001, 0x3180);
ARMBinary mios{GetMIOSBinary()};
if (!mios.IsValid())
{
PanicAlertT("Failed to load MIOS. It is required for launching GameCube titles from Wii mode.");
Core::QueueHostJob(Core::Stop);
return false;
}
std::vector<u8> elf_bytes = mios.GetElf();
ElfReader elf{elf_bytes.data()};
if (!elf.LoadIntoMemory(true))
{
PanicAlertT("Failed to load MIOS ELF into memory.");
Core::QueueHostJob(Core::Stop);
return false;
}
ReinitHardware();
NOTICE_LOG(IOS, "Reinitialised hardware.");
// Load symbols for the IPL if they exist.
g_symbolDB.Clear();
if (g_symbolDB.LoadMap(File::GetUserPath(D_MAPS_IDX) + "mios-ipl.map"))
{
::HLE::Clear();
::HLE::PatchFunctions();
}
const PowerPC::CoreMode core_mode = PowerPC::GetMode();
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
MSR = 0;
PC = 0x3400;
NOTICE_LOG(IOS, "Loaded MIOS and bootstrapped PPC.");
// IOS writes 0 to 0x30f8 before bootstrapping the PPC. Once started, the IPL eventually writes
// 0xdeadbeef there, then waits for it to be cleared by IOS before continuing.
while (Memory::Read_U32(ADDRESS_INIT_SEMAPHORE) != 0xdeadbeef)
PowerPC::SingleStep();
PowerPC::SetMode(core_mode);
Memory::Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
NOTICE_LOG(IOS, "IPL ready.");
UpdateRunningGame();
return true;
}
} // namespace MIOS
} // namespace HLE
} // namespace IOS

View File

@ -0,0 +1,16 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
namespace IOS
{
namespace HLE
{
namespace MIOS
{
bool Load();
} // namespace MIOS
} // namespace HLE
} // namespace IOS

View File

@ -50,7 +50,6 @@ BluetoothEmu::BluetoothEmu(u32 device_id, const std::string& device_name)
// Activate only first Wii Remote by default
_conf_pads BT_DINF;
SetUsbPointer(this);
if (!sysconf.GetArrayData("BT.DINF", (u8*)&BT_DINF, sizeof(_conf_pads)))
{
PanicAlertT("Trying to read from invalid SYSCONF\nWii Remote Bluetooth IDs are not available");
@ -103,8 +102,8 @@ BluetoothEmu::BluetoothEmu(u32 device_id, const std::string& device_name)
BluetoothEmu::~BluetoothEmu()
{
Host_SetWiiMoteConnectionState(0);
m_WiiMotes.clear();
SetUsbPointer(nullptr);
}
template <typename T>

View File

@ -25,18 +25,6 @@ namespace IOS
{
namespace HLE
{
static Device::BluetoothEmu* s_Usb = nullptr;
Device::BluetoothEmu* GetUsbPointer()
{
return s_Usb;
}
void SetUsbPointer(Device::BluetoothEmu* ptr)
{
s_Usb = ptr;
}
WiimoteDevice::WiimoteDevice(Device::BluetoothEmu* host, int number, bdaddr_t bd, bool ready)
: m_BD(bd),
m_Name(number == WIIMOTE_BALANCE_BOARD ? "Nintendo RVL-WBC-01" : "Nintendo RVL-CNT-01"),
@ -943,6 +931,9 @@ void Callback_WiimoteInterruptChannel(int _number, u16 _channelID, const void* _
DEBUG_LOG(WIIMOTE, " Data: %s", ArrayToString(pData, _Size, 50).c_str());
DEBUG_LOG(WIIMOTE, " Channel: %x", _channelID);
IOS::HLE::s_Usb->m_WiiMotes[_number].ReceiveL2capData(_channelID, _pData, _Size);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt)
bt->m_WiiMotes[_number].ReceiveL2capData(_channelID, _pData, _Size);
}
}

View File

@ -23,9 +23,6 @@ namespace Device
class BluetoothEmu;
}
Device::BluetoothEmu* GetUsbPointer();
void SetUsbPointer(Device::BluetoothEmu* ptr);
class CBigEndianBuffer
{
public:

View File

@ -521,11 +521,13 @@ void ChangeWiiPads(bool instantly)
if (instantly && (s_controllers >> 4) == controllers)
return;
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
for (int i = 0; i < MAX_WIIMOTES; ++i)
{
g_wiimote_sources[i] = IsUsingWiimote(i) ? WIIMOTE_SRC_EMU : WIIMOTE_SRC_NONE;
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
IOS::HLE::GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(IsUsingWiimote(i));
if (!SConfig::GetInstance().m_bt_passthrough_enabled && bt)
bt->AccessWiiMote(i | 0x100)->Activate(IsUsingWiimote(i));
}
}

View File

@ -189,11 +189,7 @@ void Init(int cpu_core)
s_invalidate_cache_thread_safe =
CoreTiming::RegisterEvent("invalidateEmulatedCache", InvalidateCacheThreadSafe);
ppcState.pagetable_base = 0;
ppcState.pagetable_hashmask = 0;
ppcState.tlb = {};
ResetRegisters();
Reset();
InitializeCPUCore(cpu_core);
ppcState.iCache.Init();
@ -202,6 +198,16 @@ void Init(int cpu_core)
breakpoints.ClearAllTemporary();
}
void Reset()
{
ppcState.pagetable_base = 0;
ppcState.pagetable_hashmask = 0;
ppcState.tlb = {};
ResetRegisters();
ppcState.iCache.Reset();
}
void ScheduleInvalidateCacheThreadSafe(u32 address)
{
if (CPU::GetState() == CPU::State::CPU_RUNNING)

View File

@ -136,6 +136,7 @@ extern MemChecks memchecks;
extern PPCDebugInterface debug_interface;
void Init(int cpu_core);
void Reset();
void Shutdown();
void DoState(PointerWrap& p);
void ScheduleInvalidateCacheThreadSafe(u32 address);

View File

@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system
static const u32 STATE_VERSION = 76; // Last changed in PR 4829
static const u32 STATE_VERSION = 77; // Last changed in PR 4784
// Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list,
@ -156,6 +156,19 @@ static std::string DoState(PointerWrap& p)
return version_created_by;
}
bool is_wii =
SConfig::GetInstance().bWii || SConfig::GetInstance().m_BootType == SConfig::BOOT_MIOS;
const bool is_wii_currently = is_wii;
p.Do(is_wii);
if (is_wii != is_wii_currently)
{
OSD::AddMessage(StringFromFormat("Cannot load a savestate created under %s mode in %s mode",
is_wii ? "Wii" : "GC", is_wii_currently ? "Wii" : "GC"),
OSD::Duration::NORMAL, OSD::Color::RED);
p.SetMode(PointerWrap::MODE_MEASURE);
return version_created_by;
}
// Begin with video backend, so that it gets a chance to clear its caches and writeback modified
// things to RAM
g_video_backend->DoState(p);

View File

@ -16,6 +16,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/HW/SystemTimers.h"
#include "DolphinWX/DolphinSlider.h"
#include "DolphinWX/WxEventUtils.h"
@ -181,12 +182,12 @@ void AdvancedConfigPane::OnCustomRTCTimeChanged(wxCommandEvent& event)
void AdvancedConfigPane::UpdateCPUClock()
{
bool wii = SConfig::GetInstance().bWii;
int percent = (int)(std::roundf(SConfig::GetInstance().m_OCFactor * 100.f));
int clock = (int)(std::roundf(SConfig::GetInstance().m_OCFactor * (wii ? 729.f : 486.f)));
int core_clock = SystemTimers::GetTicksPerSecond() / pow(10, 6);
int percent = static_cast<int>(std::round(SConfig::GetInstance().m_OCFactor * 100.f));
int clock = static_cast<int>(std::round(SConfig::GetInstance().m_OCFactor * core_clock));
m_clock_override_text->SetLabel(
SConfig::GetInstance().m_OCEnable ? wxString::Format("%d %% (%d mhz)", percent, clock) : "");
SConfig::GetInstance().m_OCEnable ? wxString::Format("%d %% (%d MHz)", percent, clock) : "");
}
void AdvancedConfigPane::LoadCustomRTC()

View File

@ -1245,7 +1245,10 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect)
!SConfig::GetInstance().m_bt_passthrough_enabled)
{
bool was_unpaused = Core::PauseAndLock(true);
IOS::HLE::GetUsbPointer()->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt)
bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
const char* message = connect ? "Wii Remote %i connected" : "Wii Remote %i disconnected";
Core::DisplayMessage(StringFromFormat(message, wm_idx + 1), 3000);
Host_UpdateMainFrame();
@ -1258,10 +1261,11 @@ void CFrame::OnConnectWiimote(wxCommandEvent& event)
if (SConfig::GetInstance().m_bt_passthrough_enabled)
return;
bool was_unpaused = Core::PauseAndLock(true);
ConnectWiimote(event.GetId() - IDM_CONNECT_WIIMOTE1,
!IOS::HLE::GetUsbPointer()
->AccessWiiMote((event.GetId() - IDM_CONNECT_WIIMOTE1) | 0x100)
->IsConnected());
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
const bool is_connected =
bt && bt->AccessWiiMote((event.GetId() - IDM_CONNECT_WIIMOTE1) | 0x100)->IsConnected();
ConnectWiimote(event.GetId() - IDM_CONNECT_WIIMOTE1, !is_connected);
Core::PauseAndLock(false, was_unpaused);
}
@ -1416,8 +1420,9 @@ void CFrame::UpdateGUI()
// Tools
GetMenuBar()->FindItem(IDM_CHEATS)->Enable(SConfig::GetInstance().bEnableCheats);
bool ShouldEnableWiimotes =
Running && SConfig::GetInstance().bWii && !SConfig::GetInstance().m_bt_passthrough_enabled;
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
bool ShouldEnableWiimotes = Running && bt && !SConfig::GetInstance().m_bt_passthrough_enabled;
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Enable(ShouldEnableWiimotes);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Enable(ShouldEnableWiimotes);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->Enable(ShouldEnableWiimotes);
@ -1426,21 +1431,13 @@ void CFrame::UpdateGUI()
if (ShouldEnableWiimotes)
{
bool was_unpaused = Core::PauseAndLock(true);
GetMenuBar()
->FindItem(IDM_CONNECT_WIIMOTE1)
->Check(IOS::HLE::GetUsbPointer()->AccessWiiMote(0x0100)->IsConnected());
GetMenuBar()
->FindItem(IDM_CONNECT_WIIMOTE2)
->Check(IOS::HLE::GetUsbPointer()->AccessWiiMote(0x0101)->IsConnected());
GetMenuBar()
->FindItem(IDM_CONNECT_WIIMOTE3)
->Check(IOS::HLE::GetUsbPointer()->AccessWiiMote(0x0102)->IsConnected());
GetMenuBar()
->FindItem(IDM_CONNECT_WIIMOTE4)
->Check(IOS::HLE::GetUsbPointer()->AccessWiiMote(0x0103)->IsConnected());
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Check(bt->AccessWiiMote(0x0100)->IsConnected());
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Check(bt->AccessWiiMote(0x0101)->IsConnected());
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->Check(bt->AccessWiiMote(0x0102)->IsConnected());
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->Check(bt->AccessWiiMote(0x0103)->IsConnected());
GetMenuBar()
->FindItem(IDM_CONNECT_BALANCEBOARD)
->Check(IOS::HLE::GetUsbPointer()->AccessWiiMote(0x0104)->IsConnected());
->Check(bt->AccessWiiMote(0x0104)->IsConnected());
Core::PauseAndLock(false, was_unpaused);
}

View File

@ -143,7 +143,10 @@ void Host_ConnectWiimote(int wm_idx, bool connect)
{
Core::QueueHostJob([=] {
bool was_unpaused = Core::PauseAndLock(true);
IOS::HLE::GetUsbPointer()->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt)
bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
Host_UpdateMainFrame();
Core::PauseAndLock(false, was_unpaused);
});