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. // 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, static bool FindMapFile(std::string* existing_map_file, std::string* writable_map_file,
std::string* title_id = nullptr); std::string* title_id = nullptr);
static bool LoadMapFromFilename();
private: private:
static bool DVDRead(u64 dvd_offset, u32 output_address, u32 length, bool decrypt); static bool DVDRead(u64 dvd_offset, u32 output_address, u32 length, bool decrypt);
@ -44,7 +45,6 @@ private:
static void UpdateDebugger_MapLoaded(); static void UpdateDebugger_MapLoaded();
static bool LoadMapFromFilename();
static bool Boot_ELF(const std::string& filename); static bool Boot_ELF(const std::string& filename);
static bool Boot_WiiWAD(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_U16(0x8201, 0x000030e6); // Dev console / debug capable
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
if (!IOS::HLE::SetupMemory(ios_title_id)) if (!IOS::HLE::Reload(ios_title_id))
{ {
return false; 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 // 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); INFO_LOG(MASTER_LOG, "String section: %i", header->e_shstrndx);
@ -133,6 +133,9 @@ bool ElfReader::LoadIntoMemory()
u32 srcSize = p->p_filesz; u32 srcSize = p->p_filesz;
u32 dstSize = p->p_memsz; u32 dstSize = p->p_memsz;
if (only_in_mem1 && p->p_vaddr >= Memory::REALRAM_SIZE)
continue;
Memory::CopyToEmu(writeAddr, src, srcSize); Memory::CopyToEmu(writeAddr, src, srcSize);
if (srcSize < dstSize) if (srcSize < dstSize)
Memory::Memset(writeAddr + srcSize, 0, dstSize - srcSize); // zero out bss 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); } ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); }
u32 GetEntryPoint() const { return entryPoint; } u32 GetEntryPoint() const { return entryPoint; }
u32 GetFlags() const { return (u32)(header->e_flags); } u32 GetFlags() const { return (u32)(header->e_flags); }
bool LoadIntoMemory(); bool LoadIntoMemory(bool only_in_mem1 = false);
bool LoadSymbols(); bool LoadSymbols();
int GetNumSegments() const { return (int)(header->e_phnum); } int GetNumSegments() const { return (int)(header->e_phnum); }

View File

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

View File

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

View File

@ -528,9 +528,11 @@ void EmuThread()
Wiimote::LoadConfig(); Wiimote::LoadConfig();
// Activate Wiimotes which don't have source set to "None" // 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) for (unsigned int i = 0; i != MAX_BBMOTES; ++i)
if (g_wiimote_sources[i]) if (g_wiimote_sources[i] && bt)
IOS::HLE::GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(true); bt->AccessWiiMote(i | 0x100)->Activate(true);
} }
AudioCommon::InitSoundStream(); AudioCommon::InitSoundStream();
@ -632,10 +634,6 @@ void EmuThread()
FileMon::Close(); 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() // We must set up this flag before executing HW::Shutdown()
s_hardware_initialized = false; s_hardware_initialized = false;
INFO_LOG(CONSOLE, "%s", StopMessage(false, "Shutting down HW").c_str()); 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\Device.cpp" />
<ClCompile Include="IOS\DeviceStub.cpp" /> <ClCompile Include="IOS\DeviceStub.cpp" />
<ClCompile Include="IOS\IPC.cpp" /> <ClCompile Include="IOS\IPC.cpp" />
<ClCompile Include="IOS\MIOS.cpp" />
<ClCompile Include="IOS\DI\DI.cpp" /> <ClCompile Include="IOS\DI\DI.cpp" />
<ClCompile Include="IOS\ES\ES.cpp" /> <ClCompile Include="IOS\ES\ES.cpp" />
<ClCompile Include="IOS\ES\Formats.cpp" /> <ClCompile Include="IOS\ES\Formats.cpp" />
@ -408,6 +409,7 @@
<ClInclude Include="IOS\Device.h" /> <ClInclude Include="IOS\Device.h" />
<ClInclude Include="IOS\DeviceStub.h" /> <ClInclude Include="IOS\DeviceStub.h" />
<ClInclude Include="IOS\IPC.h" /> <ClInclude Include="IOS\IPC.h" />
<ClInclude Include="IOS\MIOS.h" />
<ClInclude Include="IOS\DI\DI.h" /> <ClInclude Include="IOS\DI\DI.h" />
<ClInclude Include="IOS\ES\ES.h" /> <ClInclude Include="IOS\ES\ES.h" />
<ClInclude Include="IOS\ES\Formats.h" /> <ClInclude Include="IOS\ES\Formats.h" />

View File

@ -752,6 +752,9 @@
<ClCompile Include="IOS\IPC.cpp"> <ClCompile Include="IOS\IPC.cpp">
<Filter>IOS</Filter> <Filter>IOS</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="IOS\MIOS.cpp">
<Filter>IOS</Filter>
</ClCompile>
<ClCompile Include="IOS\Network\Net.cpp"> <ClCompile Include="IOS\Network\Net.cpp">
<Filter>IOS\Network</Filter> <Filter>IOS\Network</Filter>
</ClCompile> </ClCompile>
@ -1419,6 +1422,9 @@
<ClInclude Include="IOS\IPC.h"> <ClInclude Include="IOS\IPC.h">
<Filter>IOS</Filter> <Filter>IOS</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="IOS\MIOS.h">
<Filter>IOS</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Text Include="CMakeLists.txt" /> <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() void Idle()
{ {
if (SConfig::GetInstance().bSyncGPUOnSkipIdleHack) if (SConfig::GetInstance().bSyncGPUOnSkipIdleHack)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -419,8 +419,24 @@ void Init()
{ {
DVDThread::Start(); DVDThread::Start();
s_DISR.Hex = 0; Reset();
s_DICVR.Hex = 1; // Disc Channel relies on cover being open when no disc is inserted 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[0].Hex = 0;
s_DICMDBUF[1].Hex = 0; s_DICMDBUF[1].Hex = 0;
s_DICMDBUF[2].Hex = 0; s_DICMDBUF[2].Hex = 0;
@ -441,7 +457,6 @@ void Init()
s_pending_samples = 0; s_pending_samples = 0;
s_error_code = 0; s_error_code = 0;
s_disc_inside = false;
// The buffer is empty at start // The buffer is empty at start
s_read_buffer_start_offset = 0; s_read_buffer_start_offset = 0;
@ -450,15 +465,6 @@ void Init()
s_read_buffer_end_time = 0; s_read_buffer_end_time = 0;
s_disc_path_to_insert.clear(); 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() void Shutdown()

View File

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

View File

@ -232,7 +232,10 @@ void CEXIIPL::SetCS(int _iCS)
void CEXIIPL::UpdateRTC() 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)); u32 rtc = Common::swap32(GetEmulatedTime(epoch));
std::memcpy(m_RTC, &rtc, sizeof(u32)); std::memcpy(m_RTC, &rtc, sizeof(u32));
} }

View File

@ -61,12 +61,11 @@ void Init()
void Shutdown() 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) if (SConfig::GetInstance().bWii)
{
IOS::HLE::Shutdown(); // Depends on Memory
IOS::Shutdown();
Core::ShutdownWiiRoot(); Core::ShutdownWiiRoot();
}
SystemTimers::Shutdown(); SystemTimers::Shutdown();
CPU::Shutdown(); CPU::Shutdown();

View File

@ -223,10 +223,17 @@ static void ThrottleCallback(u64 last_time, s64 cyclesLate)
// SystemTimers::Init // SystemTimers::Init
void PreInit() 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; s_cpu_core_clock = 729000000u;
else else
s_cpu_core_clock = 486000000u; s_cpu_core_clock = 486000000u;
CoreTiming::AdjustEventQueueTimes(s_cpu_core_clock, previous_clock);
} }
void Init() void Init()

View File

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

View File

@ -317,6 +317,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
return Decrypt(request); return Decrypt(request);
case IOCTL_ES_LAUNCH: case IOCTL_ES_LAUNCH:
return Launch(request); return Launch(request);
case IOCTL_ES_LAUNCHBC:
return LaunchBC(request);
case IOCTL_ES_CHECKKOREAREGION: case IOCTL_ES_CHECKKOREAREGION:
return CheckKoreaRegion(request); return CheckKoreaRegion(request);
case IOCTL_ES_GETDEVICECERT: case IOCTL_ES_GETDEVICECERT:
@ -1103,7 +1105,6 @@ IPCCommandResult ES::Launch(const IOCtlVRequest& request)
{ {
_dbg_assert_(IOS_ES, request.in_vectors.size() == 2); _dbg_assert_(IOS_ES, request.in_vectors.size() == 2);
bool bSuccess = false; bool bSuccess = false;
bool bReset = false;
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
u32 view = Memory::Read_U32(request.in_vectors[1].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); u64 titleid = Memory::Read_U64(request.in_vectors[1].address + 16);
u16 access = Memory::Read_U16(request.in_vectors[1].address + 24); 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. // 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 // leaving them open through ES_LAUNCH may cause hangs and other funky behavior
// (supposedly when trying to re-open those files). // (supposedly when trying to re-open those files).
@ -1168,63 +1172,65 @@ IPCCommandResult ES::Launch(const IOCtlVRequest& request)
} }
else else
{ {
bool* wiiMoteConnected = new bool[MAX_BBMOTES]; ResetAfterLaunch(ios_to_load);
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;
SetDefaultContentFile(tContentFile); 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 // Generate a "reply" to the IPC command. ES_LAUNCH is unique because it
// involves restarting IOS; IOS generates two acknowledgements in a row. // 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); EnqueueCommandAcknowledgement(request.address, 0);
return GetNoReply(); 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) IPCCommandResult ES::CheckKoreaRegion(const IOCtlVRequest& request)
{ {
// note by DacoTaco : name is unknown, I just tried to name it SOMETHING. // 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_DELETETITLECONTENT = 0x22,
IOCTL_ES_SEEKCONTENT = 0x23, IOCTL_ES_SEEKCONTENT = 0x23,
IOCTL_ES_OPENTITLECONTENT = 0x24, IOCTL_ES_OPENTITLECONTENT = 0x24,
// IOCTL_ES_LAUNCHBC = 0x25, IOCTL_ES_LAUNCHBC = 0x25,
// IOCTL_ES_EXPORTTITLEINIT = 0x26, // IOCTL_ES_EXPORTTITLEINIT = 0x26,
// IOCTL_ES_EXPORTCONTENTBEGIN = 0x27, // IOCTL_ES_EXPORTCONTENTBEGIN = 0x27,
// IOCTL_ES_EXPORTCONTENTDATA = 0x28, // IOCTL_ES_EXPORTCONTENTDATA = 0x28,
@ -182,6 +182,7 @@ private:
IPCCommandResult Encrypt(const IOCtlVRequest& request); IPCCommandResult Encrypt(const IOCtlVRequest& request);
IPCCommandResult Decrypt(const IOCtlVRequest& request); IPCCommandResult Decrypt(const IOCtlVRequest& request);
IPCCommandResult Launch(const IOCtlVRequest& request); IPCCommandResult Launch(const IOCtlVRequest& request);
IPCCommandResult LaunchBC(const IOCtlVRequest& request);
IPCCommandResult CheckKoreaRegion(const IOCtlVRequest& request); IPCCommandResult CheckKoreaRegion(const IOCtlVRequest& request);
IPCCommandResult GetDeviceCertificate(const IOCtlVRequest& request); IPCCommandResult GetDeviceCertificate(const IOCtlVRequest& request);
IPCCommandResult Sign(const IOCtlVRequest& request); IPCCommandResult Sign(const IOCtlVRequest& request);
@ -189,6 +190,8 @@ private:
IPCCommandResult DIGetTicketView(const IOCtlVRequest& request); IPCCommandResult DIGetTicketView(const IOCtlVRequest& request);
IPCCommandResult GetOwnedTitleCount(const IOCtlVRequest& request); IPCCommandResult GetOwnedTitleCount(const IOCtlVRequest& request);
void ResetAfterLaunch(u64 ios_to_load) const;
const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id); const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id);
u32 OpenTitleContent(u32 CFD, u64 TitleID, u16 Index); u32 OpenTitleContent(u32 CFD, u64 TitleID, u16 Index);

View File

@ -42,6 +42,7 @@
#include "Core/IOS/FS/FS.h" #include "Core/IOS/FS/FS.h"
#include "Core/IOS/FS/FileIO.h" #include "Core/IOS/FS/FileIO.h"
#include "Core/IOS/IPC.h" #include "Core/IOS/IPC.h"
#include "Core/IOS/MIOS.h"
#include "Core/IOS/Network/Net.h" #include "Core/IOS/Network/Net.h"
#include "Core/IOS/Network/SSL.h" #include "Core/IOS/Network/SSL.h"
#include "Core/IOS/Network/Socket.h" #include "Core/IOS/Network/Socket.h"
@ -111,6 +112,7 @@ struct IosMemoryValues
u32 ram_vendor; u32 ram_vendor;
u32 unknown_begin; u32 unknown_begin;
u32 unknown_end; u32 unknown_end;
u32 sysmenu_sync;
}; };
constexpr u32 ADDR_MEM1_SIZE = 0x3100; 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, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
}, },
{ {
12, 0xc020e, 0x030110, MEM1_SIZE, 12, 0xc020e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
}, },
{ {
13, 0xd0408, 0x030110, MEM1_SIZE, 13, 0xd0408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
}, },
{ {
14, 0xe0408, 0x030110, MEM1_SIZE, 14, 0xe0408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
}, },
{ {
15, 0xf0408, 0x030110, MEM1_SIZE, 15, 0xf0408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
}, },
{ {
17, 0x110408, 0x030110, MEM1_SIZE, 17, 0x110408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
}, },
{ {
21, 0x15040f, 0x030110, MEM1_SIZE, 21, 0x15040f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
}, },
{ {
22, 0x16050e, 0x030110, MEM1_SIZE, 22, 0x16050e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
}, },
{ {
28, 0x1c070f, 0x030110, MEM1_SIZE, 28, 0x1c070f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93800000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93800000, MEM2_ARENA_BEGIN,
0x937E0000, 0x937E0000, 0x93800000, HOLLYWOOD_REVISION, 0x937E0000, 0x937E0000, 0x93800000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93800000, 0x93820000, RAM_VENDOR, 0x93800000, 0x93820000, 0,
}, },
{ {
31, 0x1f0e18, 0x030110, MEM1_SIZE, 31, 0x1f0e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
33, 0x210e18, 0x030110, MEM1_SIZE, 33, 0x210e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
34, 0x220e18, 0x030110, MEM1_SIZE, 34, 0x220e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
35, 0x230e18, 0x030110, MEM1_SIZE, 35, 0x230e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
36, 0x240e18, 0x030110, MEM1_SIZE, 36, 0x240e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
37, 0x25161f, 0x030110, MEM1_SIZE, 37, 0x25161f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
38, 0x26101c, 0x030110, MEM1_SIZE, 38, 0x26101c, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
41, 0x290e17, 0x030110, MEM1_SIZE, 41, 0x290e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
43, 0x2b0e17, 0x030110, MEM1_SIZE, 43, 0x2b0e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
45, 0x2d0e17, 0x030110, MEM1_SIZE, 45, 0x2d0e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
46, 0x2e0e17, 0x030110, MEM1_SIZE, 46, 0x2e0e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
48, 0x30101c, 0x030110, MEM1_SIZE, 48, 0x30101c, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
53, 0x35161f, 0x030110, MEM1_SIZE, 53, 0x35161f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
55, 0x37161f, 0x030110, MEM1_SIZE, 55, 0x37161f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
56, 0x38161e, 0x030110, MEM1_SIZE, 56, 0x38161e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
57, 0x39171f, 0x030110, MEM1_SIZE, 57, 0x39171f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
58, 0x3a1820, 0x030110, MEM1_SIZE, 58, 0x3a1820, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
59, 0x3b1c21, 0x101811, MEM1_SIZE, 59, 0x3b1c21, 0x101811, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
61, 0x3d161e, 0x030110, MEM1_SIZE, 61, 0x3d161e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
62, 0x3e191e, 0x022712, MEM1_SIZE, 62, 0x3e191e, 0x022712, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
80, 0x501b20, 0x030310, MEM1_SIZE, 80, 0x501b20, 0x030310, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, RAM_VENDOR, 0x93600000, 0x93620000, 0,
}, },
{ {
257, 257,
@ -387,6 +389,7 @@ constexpr std::array<IosMemoryValues, 31> ios_memory_values = {
RAM_VENDOR_MIOS, RAM_VENDOR_MIOS,
PLACEHOLDER, PLACEHOLDER,
PLACEHOLDER, PLACEHOLDER,
PLACEHOLDER,
}}}; }}};
static void EnqueueEvent(u64 userdata, s64 cycles_late = 0) static void EnqueueEvent(u64 userdata, s64 cycles_late = 0)
@ -421,7 +424,7 @@ u32 GetVersion()
return static_cast<u32>(s_active_title_id); 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( auto target_imv = std::find_if(
ios_memory_values.begin(), ios_memory_values.end(), ios_memory_values.begin(), ios_memory_values.end(),
@ -433,8 +436,6 @@ bool SetupMemory(u64 ios_title_id)
return false; 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_physical_size, ADDR_MEM1_SIZE);
Memory::Write_U32(target_imv->mem1_simulated_size, ADDR_MEM1_SIM_SIZE); Memory::Write_U32(target_imv->mem1_simulated_size, ADDR_MEM1_SIM_SIZE);
Memory::Write_U32(target_imv->mem1_end, ADDR_MEM1_END); 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(0xDE, ADDR_BOOT_FLAG);
Memory::Write_U8(0xAD, ADDR_APPLOADER_FLAG); Memory::Write_U8(0xAD, ADDR_APPLOADER_FLAG);
Memory::Write_U16(0xBEEF, ADDR_DEVKIT_BOOT_PROGRAM_VERSION); 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; return true;
} }
@ -477,7 +478,7 @@ std::shared_ptr<T> AddDevice(const char* device_name)
return device; return device;
} }
void Reinit() static void AddStaticDevices()
{ {
std::lock_guard<std::mutex> lock(s_device_map_mutex); std::lock_guard<std::mutex> lock(s_device_map_mutex);
_assert_msg_(IOS, s_device_map.empty(), "Reinit called while already initialized"); _assert_msg_(IOS, s_device_map.empty(), "Reinit called while already initialized");
@ -519,13 +520,11 @@ void Reinit()
void Init() void Init()
{ {
Reinit();
s_event_enqueue = CoreTiming::RegisterEvent("IPCEvent", EnqueueEvent); s_event_enqueue = CoreTiming::RegisterEvent("IPCEvent", EnqueueEvent);
s_event_sdio_notify = CoreTiming::RegisterEvent("SDIO_EventNotify", SDIO_EventNotify_CPUThread); 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); CoreTiming::RemoveAllEvents(s_event_enqueue);
@ -538,7 +537,7 @@ void Reset(bool hard)
device.reset(); device.reset();
} }
if (hard) if (clear_devices)
{ {
std::lock_guard<std::mutex> lock(s_device_map_mutex); std::lock_guard<std::mutex> lock(s_device_map_mutex);
s_device_map.clear(); s_device_map.clear();
@ -555,6 +554,35 @@ void Shutdown()
Reset(true); 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) void SetDefaultContentFile(const std::string& file_name)
{ {
std::lock_guard<std::mutex> lock(s_device_map_mutex); 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_request_queue);
p.Do(s_reply_queue); p.Do(s_reply_queue);
p.Do(s_last_reply_time); 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 // We need to make sure all file handles are closed so IOS::HLE::Device::FS::DoState can
// successfully save or re-create /tmp // successfully save or re-create /tmp

View File

@ -45,21 +45,16 @@ enum IPCCommandType : u32
IPC_REPLY = 8, IPC_REPLY = 8,
}; };
// Init // Init events and devices
void Init(); void Init();
// Reset all events and devices (and optionally clear them)
// Needs to be called after Reset(true) to recreate the device tree void Reset(bool clear_devices = false);
void Reinit();
u32 GetVersion();
bool SetupMemory(u64 ios_title_id);
// Shutdown // Shutdown
void Shutdown(); void Shutdown();
// Reset // Reload IOS (to a possibly different version); set up memory and devices.
void Reset(bool hard = false); bool Reload(u64 ios_title_id);
u32 GetVersion();
// Do State // Do State
void DoState(PointerWrap& p); 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 // Activate only first Wii Remote by default
_conf_pads BT_DINF; _conf_pads BT_DINF;
SetUsbPointer(this);
if (!sysconf.GetArrayData("BT.DINF", (u8*)&BT_DINF, sizeof(_conf_pads))) 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"); 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() BluetoothEmu::~BluetoothEmu()
{ {
Host_SetWiiMoteConnectionState(0);
m_WiiMotes.clear(); m_WiiMotes.clear();
SetUsbPointer(nullptr);
} }
template <typename T> template <typename T>

View File

@ -25,18 +25,6 @@ namespace IOS
{ {
namespace HLE 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) WiimoteDevice::WiimoteDevice(Device::BluetoothEmu* host, int number, bdaddr_t bd, bool ready)
: m_BD(bd), : m_BD(bd),
m_Name(number == WIIMOTE_BALANCE_BOARD ? "Nintendo RVL-WBC-01" : "Nintendo RVL-CNT-01"), 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, " Data: %s", ArrayToString(pData, _Size, 50).c_str());
DEBUG_LOG(WIIMOTE, " Channel: %x", _channelID); 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; class BluetoothEmu;
} }
Device::BluetoothEmu* GetUsbPointer();
void SetUsbPointer(Device::BluetoothEmu* ptr);
class CBigEndianBuffer class CBigEndianBuffer
{ {
public: public:

View File

@ -521,11 +521,13 @@ void ChangeWiiPads(bool instantly)
if (instantly && (s_controllers >> 4) == controllers) if (instantly && (s_controllers >> 4) == controllers)
return; 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) for (int i = 0; i < MAX_WIIMOTES; ++i)
{ {
g_wiimote_sources[i] = IsUsingWiimote(i) ? WIIMOTE_SRC_EMU : WIIMOTE_SRC_NONE; g_wiimote_sources[i] = IsUsingWiimote(i) ? WIIMOTE_SRC_EMU : WIIMOTE_SRC_NONE;
if (!SConfig::GetInstance().m_bt_passthrough_enabled) if (!SConfig::GetInstance().m_bt_passthrough_enabled && bt)
IOS::HLE::GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(IsUsingWiimote(i)); bt->AccessWiiMote(i | 0x100)->Activate(IsUsingWiimote(i));
} }
} }

View File

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

View File

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

View File

@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread; static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system // 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. // Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list, // 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; 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 // Begin with video backend, so that it gets a chance to clear its caches and writeback modified
// things to RAM // things to RAM
g_video_backend->DoState(p); g_video_backend->DoState(p);

View File

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

View File

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

View File

@ -143,7 +143,10 @@ void Host_ConnectWiimote(int wm_idx, bool connect)
{ {
Core::QueueHostJob([=] { Core::QueueHostJob([=] {
bool was_unpaused = Core::PauseAndLock(true); 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(); Host_UpdateMainFrame();
Core::PauseAndLock(false, was_unpaused); Core::PauseAndLock(false, was_unpaused);
}); });