summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2017-01-25 11:41:26 +0100
committerGitHub <noreply@github.com>2017-01-25 11:41:26 +0100
commit18968abbd7d76e7b1693fe7e393c6fbecce00a5e (patch)
tree4a85248fda6be017e03879fcb1a808ded738928d /Source
parent54e7d4a3dddc25fb7a24bb6e00d27913bfe3049a (diff)
parentd16ca2e5c877fb2129c38b81a938c5002cf592d8 (diff)
Merge pull request #4723 from booto/ios-init
Set up IOS RAM information area with real values.
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/Boot/Boot.cpp6
-rw-r--r--Source/Core/Core/Boot/Boot.h2
-rw-r--r--Source/Core/Core/Boot/Boot_BS2Emu.cpp232
-rw-r--r--Source/Core/Core/Boot/Boot_WiiWAD.cpp4
-rw-r--r--Source/Core/Core/IOS/ES/ES.cpp39
-rw-r--r--Source/Core/Core/IOS/IPC.cpp346
-rw-r--r--Source/Core/Core/IOS/IPC.h2
7 files changed, 477 insertions, 154 deletions
diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp
index ec5577408f..dd8eeb5c7d 100644
--- a/Source/Core/Core/Boot/Boot.cpp
+++ b/Source/Core/Core/Boot/Boot.cpp
@@ -420,9 +420,13 @@ bool CBoot::BootUp()
// Poor man's bootup
if (_StartupPara.bWii)
- SetupWiiMemory();
+ {
+ SetupWiiMemory(0x0000000100000050ULL);
+ }
else
+ {
EmulatedBS2_GC(true);
+ }
Load_FST(_StartupPara.bWii);
if (!Boot_ELF(_StartupPara.m_strFilename))
diff --git a/Source/Core/Core/Boot/Boot.h b/Source/Core/Core/Boot/Boot.h
index 0388e07f11..6618036e3c 100644
--- a/Source/Core/Core/Boot/Boot.h
+++ b/Source/Core/Core/Boot/Boot.h
@@ -52,5 +52,5 @@ private:
static bool Load_BS2(const std::string& _rBootROMFilename);
static void Load_FST(bool _bIsWii);
- static bool SetupWiiMemory();
+ static bool SetupWiiMemory(u64 ios_title_id);
};
diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp
index d6784b6ec0..78d1b0001d 100644
--- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp
+++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp
@@ -17,6 +17,8 @@
#include "Core/HW/DVDInterface.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/Memmap.h"
+#include "Core/IOS/ES/Formats.h"
+#include "Core/IOS/IPC.h"
#include "Core/MemTools.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/PowerPC.h"
@@ -182,7 +184,7 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
return true;
}
-bool CBoot::SetupWiiMemory()
+bool CBoot::SetupWiiMemory(u64 ios_title_id)
{
static const std::map<DiscIO::Region, const RegionSetting> region_settings = {
{DiscIO::Region::NTSC_J, {"JPN", "NTSC", "JP", "LJ"}},
@@ -280,25 +282,11 @@ bool CBoot::SetupWiiMemory()
Memory::Write_U32(0x00000000, 0x000030d8); // Time
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
- Memory::Write_U32(0x01800000, 0x00003100); // BAT
- Memory::Write_U32(0x01800000, 0x00003104); // BAT
- Memory::Write_U32(0x00000000, 0x0000310c); // Init
- Memory::Write_U32(0x8179d500, 0x00003110); // Init
- Memory::Write_U32(0x04000000, 0x00003118); // Unknown
- Memory::Write_U32(0x04000000, 0x0000311c); // BAT
- Memory::Write_U32(0x93600000, 0x00003120); // BAT
- Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low
- Memory::Write_U32(0x935e0000, 0x00003128); // Init - MEM2 high
- Memory::Write_U32(0x935e0000, 0x00003130); // IOS MEM2 low
- Memory::Write_U32(0x93600000, 0x00003134); // IOS MEM2 high
- Memory::Write_U32(0x00000012, 0x00003138); // Console type
- // 40 is copied from 88 after running apploader
- Memory::Write_U32(0x00090204, 0x00003140); // IOS revision (IOS9, v2.4)
- Memory::Write_U32(0x00062507, 0x00003144); // IOS date in USA format (June 25, 2007)
- Memory::Write_U16(0x0113, 0x0000315e); // Apploader
- Memory::Write_U32(0x0000FF16, 0x00003158); // DDR ram vendor code
- Memory::Write_U32(0x00000000, 0x00003160); // Init semaphore (sysmenu waits for this to clear)
- Memory::Write_U32(0x00090204, 0x00003188); // Expected IOS revision
+
+ if (!IOS::HLE::SetupMemory(ios_title_id))
+ {
+ return false;
+ }
Memory::Write_U8(0x80, 0x0000315c); // OSInit
Memory::Write_U16(0x0000, 0x000030e0); // PADInit
@@ -322,125 +310,119 @@ bool CBoot::SetupWiiMemory()
bool CBoot::EmulatedBS2_Wii()
{
INFO_LOG(BOOT, "Faking Wii BS2...");
+ if (!DVDInterface::VolumeIsValid())
+ return false;
- // Setup Wii memory
- if (!SetupWiiMemory())
+ if (DVDInterface::GetVolume().GetVolumeType() != DiscIO::Platform::WII_DISC)
+ return false;
+
+ // This is some kind of consistency check that is compared to the 0x00
+ // values as the game boots. This location keeps the 4 byte ID for as long
+ // as the game is running. The 6 byte ID at 0x00 is overwritten sometime
+ // after this check during booting.
+ DVDRead(0, 0x3180, 4, true);
+
+ // Set up MSR and the BAT SPR registers.
+ UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
+ m_MSR.FP = 1;
+ m_MSR.DR = 1;
+ m_MSR.IR = 1;
+ m_MSR.EE = 1;
+ PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
+ PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
+ PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff;
+ PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002;
+ PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
+ PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
+ PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
+ PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
+ PowerPC::ppcState.spr[SPR_DBAT4U] = 0x90001fff;
+ PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002;
+ PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
+ PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
+ PowerPC::DBATUpdated();
+ PowerPC::IBATUpdated();
+
+ Memory::Write_U32(0x4c000064, 0x00000300); // Write default DSI Handler: rfi
+ Memory::Write_U32(0x4c000064, 0x00000800); // Write default FPU Handler: rfi
+ Memory::Write_U32(0x4c000064, 0x00000C00); // Write default Syscall Handler: rfi
+
+ HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
+
+ PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
+
+ std::vector<u8> tmd = DVDInterface::GetVolume().GetTMD();
+
+ IOS::HLE::TMDReader tmd_reader{std::move(tmd)};
+
+ if (!SetupWiiMemory(tmd_reader.GetIOSId()))
return false;
// Execute the apploader
- bool apploaderRan = false;
- if (DVDInterface::VolumeIsValid() &&
- DVDInterface::GetVolume().GetVolumeType() == DiscIO::Platform::WII_DISC)
+ const u32 apploader_offset = 0x2440; // 0x1c40;
+
+ // Load Apploader to Memory
+ const DiscIO::IVolume& volume = DVDInterface::GetVolume();
+ u32 apploader_entry, apploader_size;
+ if (!volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, true) ||
+ !volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, true) ||
+ apploader_entry == (u32)-1 || apploader_size == (u32)-1)
{
- // This is some kind of consistency check that is compared to the 0x00
- // values as the game boots. This location keeps the 4 byte ID for as long
- // as the game is running. The 6 byte ID at 0x00 is overwritten sometime
- // after this check during booting.
- DVDRead(0, 0x3180, 4, true);
-
- // Set up MSR and the BAT SPR registers.
- UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
- m_MSR.FP = 1;
- m_MSR.DR = 1;
- m_MSR.IR = 1;
- m_MSR.EE = 1;
- PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
- PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
- PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff;
- PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002;
- PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
- PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
- PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
- PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
- PowerPC::ppcState.spr[SPR_DBAT4U] = 0x90001fff;
- PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002;
- PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
- PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
- PowerPC::DBATUpdated();
- PowerPC::IBATUpdated();
-
- Memory::Write_U32(0x4c000064, 0x00000300); // Write default DSI Handler: rfi
- Memory::Write_U32(0x4c000064, 0x00000800); // Write default FPU Handler: rfi
- Memory::Write_U32(0x4c000064, 0x00000C00); // Write default Syscall Handler: rfi
-
- HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
-
- PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
-
- const u32 apploader_offset = 0x2440; // 0x1c40;
-
- // Load Apploader to Memory
- const DiscIO::IVolume& volume = DVDInterface::GetVolume();
- u32 apploader_entry, apploader_size;
- if (!volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, true) ||
- !volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, true) ||
- apploader_entry == (u32)-1 || apploader_size == (u32)-1)
- {
- ERROR_LOG(BOOT, "Invalid apploader. Probably your image is corrupted.");
- return false;
- }
- DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size, true);
-
- // call iAppLoaderEntry
- DEBUG_LOG(BOOT, "Call iAppLoaderEntry");
-
- u32 iAppLoaderFuncAddr = 0x80004000;
- PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
- PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
- PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
- RunFunction(apploader_entry);
- u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
- u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
- u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
-
- // iAppLoaderInit
- DEBUG_LOG(BOOT, "Run iAppLoaderInit");
- PowerPC::ppcState.gpr[3] = 0x81300000;
- RunFunction(iAppLoaderInit);
-
- // Let the apploader load the exe to memory. At this point I get an unknown IPC command
- // (command zero) when I load Wii Sports or other games a second time. I don't notice
- // any side effects however. It's a little disconcerting however that Start after Stop
- // behaves differently than the first Start after starting Dolphin. It means something
- // was not reset correctly.
- DEBUG_LOG(BOOT, "Run iAppLoaderMain");
- do
- {
- PowerPC::ppcState.gpr[3] = 0x81300004;
- PowerPC::ppcState.gpr[4] = 0x81300008;
- PowerPC::ppcState.gpr[5] = 0x8130000c;
+ ERROR_LOG(BOOT, "Invalid apploader. Probably your image is corrupted.");
+ return false;
+ }
+ DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size, true);
+
+ // call iAppLoaderEntry
+ DEBUG_LOG(BOOT, "Call iAppLoaderEntry");
- RunFunction(iAppLoaderMain);
+ u32 iAppLoaderFuncAddr = 0x80004000;
+ PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
+ PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
+ PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
+ RunFunction(apploader_entry);
+ u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
+ u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
+ u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
- u32 iRamAddress = PowerPC::Read_U32(0x81300004);
- u32 iLength = PowerPC::Read_U32(0x81300008);
- u32 iDVDOffset = PowerPC::Read_U32(0x8130000c) << 2;
+ // iAppLoaderInit
+ DEBUG_LOG(BOOT, "Run iAppLoaderInit");
+ PowerPC::ppcState.gpr[3] = 0x81300000;
+ RunFunction(iAppLoaderInit);
- INFO_LOG(BOOT, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset,
- iRamAddress, iLength);
- DVDRead(iDVDOffset, iRamAddress, iLength, true);
- } while (PowerPC::ppcState.gpr[3] != 0x00);
+ // Let the apploader load the exe to memory. At this point I get an unknown IPC command
+ // (command zero) when I load Wii Sports or other games a second time. I don't notice
+ // any side effects however. It's a little disconcerting however that Start after Stop
+ // behaves differently than the first Start after starting Dolphin. It means something
+ // was not reset correctly.
+ DEBUG_LOG(BOOT, "Run iAppLoaderMain");
+ do
+ {
+ PowerPC::ppcState.gpr[3] = 0x81300004;
+ PowerPC::ppcState.gpr[4] = 0x81300008;
+ PowerPC::ppcState.gpr[5] = 0x8130000c;
- // iAppLoaderClose
- DEBUG_LOG(BOOT, "Run iAppLoaderClose");
- RunFunction(iAppLoaderClose);
+ RunFunction(iAppLoaderMain);
- apploaderRan = true;
+ u32 iRamAddress = PowerPC::Read_U32(0x81300004);
+ u32 iLength = PowerPC::Read_U32(0x81300008);
+ u32 iDVDOffset = PowerPC::Read_U32(0x8130000c) << 2;
- // Pass the "#002 check"
- // Apploader writes the IOS version and revision here, we copy it
- // Fake IOSv9 r2.4 if no version is found (elf loading)
- u32 firmwareVer = PowerPC::Read_U32(0x80003188);
- PowerPC::Write_U32(firmwareVer ? firmwareVer : 0x00090204, 0x80003140);
+ INFO_LOG(BOOT, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress,
+ iLength);
+ DVDRead(iDVDOffset, iRamAddress, iLength, true);
+ } while (PowerPC::ppcState.gpr[3] != 0x00);
- // Load patches and run startup patches
- PatchEngine::LoadPatches();
+ // iAppLoaderClose
+ DEBUG_LOG(BOOT, "Run iAppLoaderClose");
+ RunFunction(iAppLoaderClose);
- // return
- PC = PowerPC::ppcState.gpr[3];
- }
+ // Load patches and run startup patches
+ PatchEngine::LoadPatches();
- return apploaderRan;
+ // return
+ PC = PowerPC::ppcState.gpr[3];
+ return true;
}
// Returns true if apploader has run successfully
diff --git a/Source/Core/Core/Boot/Boot_WiiWAD.cpp b/Source/Core/Core/Boot/Boot_WiiWAD.cpp
index 4869353bf4..0ebc47de6e 100644
--- a/Source/Core/Core/Boot/Boot_WiiWAD.cpp
+++ b/Source/Core/Core/Boot/Boot_WiiWAD.cpp
@@ -89,7 +89,9 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
if (titleID == TITLEID_SYSMENU)
IOS::HLE::HLE_IPC_CreateVirtualFATFilesystem();
// setup Wii memory
- if (!SetupWiiMemory())
+
+ u64 ios_title_id = 0x0000000100000000ULL | ContentLoader.GetIosVersion();
+ if (!SetupWiiMemory(ios_title_id))
return false;
// DOL
const DiscIO::SNANDContent* pContent =
diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp
index 9d069c33e0..1cac5ee73c 100644
--- a/Source/Core/Core/IOS/ES/ES.cpp
+++ b/Source/Core/Core/IOS/ES/ES.cpp
@@ -1030,7 +1030,6 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
_dbg_assert_(IOS_ES, request.in_vectors.size() == 2);
bool bSuccess = false;
bool bReset = false;
- u16 IOSv = 0xffff;
u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
u32 view = Memory::Read_U32(request.in_vectors[1].address);
@@ -1044,12 +1043,20 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
// (supposedly when trying to re-open those files).
DiscIO::CNANDContentManager::Access().ClearCache();
+ u64 ios_to_load = 0;
std::string tContentFile;
- if ((u32)(TitleID >> 32) != 0x00000001 || TitleID == TITLEID_SYSMENU)
+ if ((u32)(TitleID >> 32) == 0x00000001 && TitleID != TITLEID_SYSMENU)
+ {
+ ios_to_load = TitleID;
+ bSuccess = true;
+ }
+ else
{
const DiscIO::CNANDContentLoader& ContentLoader = AccessContentDevice(TitleID);
if (ContentLoader.IsValid())
{
+ ios_to_load = 0x0000000100000000ULL | ContentLoader.GetIosVersion();
+
u32 bootInd = ContentLoader.GetBootIndex();
const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(bootInd);
if (pContent)
@@ -1060,7 +1067,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
if (pDolLoader->IsValid())
{
- pDolLoader->Load(); // TODO: Check why sysmenu does not load the DOL correctly
+ pDolLoader->Load();
+ // TODO: Check why sysmenu does not load the DOL correctly
// NAND titles start with address translation off at 0x3400 (via the PPC bootstub)
//
// The state of other CPU registers (like the BAT registers) doesn't matter much
@@ -1068,27 +1076,15 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
MSR = 0;
PC = 0x3400;
bSuccess = true;
- bReset = true;
}
else
{
PanicAlertT("IOCTL_ES_LAUNCH: The DOL file is invalid!");
- bSuccess = false;
}
-
- IOSv = ContentLoader.GetIosVersion();
}
}
}
- else // IOS, MIOS, BC etc
- {
- // TODO: fixme
- // The following is obviously a hack
- // Lie to mem about loading a different IOS
- // someone with an affected game should test
- IOSv = TitleID & 0xffff;
- bSuccess = true;
- }
+
if (!bSuccess)
{
PanicAlertT(
@@ -1108,6 +1104,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
Reset(true);
Reinit();
+ SetupMemory(ios_to_load);
+ bReset = true;
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
{
@@ -1128,15 +1126,6 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
delete[] wiiMoteConnected;
SetDefaultContentFile(tContentFile);
}
- // Pass the "#002 check"
- // Apploader should write the IOS version and revision to 0x3140, and compare it
- // to 0x3188 to pass the check, but we don't do it, and i don't know where to read the IOS
- // rev...
- // Currently we just write 0xFFFF for the revision, copy manually and it works fine :p
- // TODO : figure it correctly : where should we read the IOS rev that the wad "needs" ?
- Memory::Write_U16(IOSv, 0x00003140);
- Memory::Write_U16(0xFFFF, 0x00003142);
- Memory::Write_U32(Memory::Read_U32(0x00003140), 0x00003188);
// Note: If we just reset the PPC, don't write anything to the command buffer. This
// could clobber the DOL we just loaded.
diff --git a/Source/Core/Core/IOS/IPC.cpp b/Source/Core/Core/IOS/IPC.cpp
index b5b054e707..d309ea5c3a 100644
--- a/Source/Core/Core/IOS/IPC.cpp
+++ b/Source/Core/Core/IOS/IPC.cpp
@@ -16,13 +16,15 @@
// Ioctlv: Depends on the handler
// Replies may be sent immediately or asynchronously for ioctls and ioctlvs.
+#include <algorithm>
+#include <array>
+#include <cinttypes>
#include <deque>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <utility>
-#include <vector>
#include "Common/Assert.h"
#include "Common/ChunkFile.h"
@@ -85,6 +87,306 @@ static u64 s_last_reply_time;
static constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL;
static constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
+
+struct IosMemoryValues
+{
+ u16 ios_number;
+ u32 ios_version;
+ u32 ios_date;
+ u32 mem1_physical_size;
+ u32 mem1_simulated_size;
+ u32 mem1_end;
+ u32 mem1_arena_begin;
+ u32 mem1_arena_end;
+ u32 mem2_physical_size;
+ u32 mem2_simulated_size;
+ u32 mem2_end;
+ u32 mem2_arena_begin;
+ u32 mem2_arena_end;
+ u32 ipc_buffer_begin;
+ u32 ipc_buffer_end;
+ u32 hollywood_revision;
+ u32 ram_vendor;
+ u32 unknown_begin;
+ u32 unknown_end;
+};
+
+constexpr u32 ADDR_MEM1_SIZE = 0x3100;
+constexpr u32 ADDR_MEM1_SIM_SIZE = 0x3104;
+constexpr u32 ADDR_MEM1_END = 0x3108;
+constexpr u32 ADDR_MEM1_ARENA_BEGIN = 0x310c;
+constexpr u32 ADDR_MEM1_ARENA_END = 0x3110;
+constexpr u32 ADDR_PH1 = 0x3114;
+constexpr u32 ADDR_MEM2_SIZE = 0x3118;
+constexpr u32 ADDR_MEM2_SIM_SIZE = 0x311c;
+constexpr u32 ADDR_MEM2_END = 0x3120;
+constexpr u32 ADDR_MEM2_ARENA_BEGIN = 0x3124;
+constexpr u32 ADDR_MEM2_ARENA_END = 0x3128;
+constexpr u32 ADDR_PH2 = 0x312c;
+constexpr u32 ADDR_IPC_BUFFER_BEGIN = 0x3130;
+constexpr u32 ADDR_IPC_BUFFER_END = 0x3134;
+constexpr u32 ADDR_HOLLYWOOD_REVISION = 0x3138;
+constexpr u32 ADDR_PH3 = 0x313c;
+constexpr u32 ADDR_IOS_VERSION = 0x3140;
+constexpr u32 ADDR_IOS_DATE = 0x3144;
+constexpr u32 ADDR_UNKNOWN_BEGIN = 0x3148;
+constexpr u32 ADDR_UNKNOWN_END = 0x314c;
+constexpr u32 ADDR_PH4 = 0x3150;
+constexpr u32 ADDR_PH5 = 0x3154;
+constexpr u32 ADDR_RAM_VENDOR = 0x3158;
+constexpr u32 ADDR_BOOT_FLAG = 0x315c;
+constexpr u32 ADDR_APPLOADER_FLAG = 0x315d;
+constexpr u32 ADDR_DEVKIT_BOOT_PROGRAM_VERSION = 0x315e;
+constexpr u32 ADDR_SYSMENU_SYNC = 0x3160;
+
+constexpr u32 MEM1_SIZE = 0x01800000;
+constexpr u32 MEM1_END = 0x81800000;
+constexpr u32 MEM1_ARENA_BEGIN = 0x00000000;
+constexpr u32 MEM1_ARENA_END = 0x81800000;
+constexpr u32 MEM2_SIZE = 0x4000000;
+constexpr u32 MEM2_ARENA_BEGIN = 0x90000800;
+constexpr u32 HOLLYWOOD_REVISION = 0x00000011;
+constexpr u32 PLACEHOLDER = 0xDEADBEEF;
+constexpr u32 RAM_VENDOR = 0x0000FF01;
+constexpr u32 RAM_VENDOR_MIOS = 0xCAFEBABE;
+
+// These values were manually extracted from the relevant IOS binaries.
+// The writes are usually contained in a single function that
+// mostly writes raw literals to the relevant locations.
+// e.g. IOS9, version 1034, content id 0x00000006, function at 0xffff6884
+constexpr std::array<IosMemoryValues, 31> ios_memory_values = {
+ {{
+ 9, 0x9040a, 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 58, 0x311820, 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 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,
+ },
+ {
+ 257,
+ 0x707,
+ 0x82209,
+ 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_MIOS,
+ PLACEHOLDER,
+ PLACEHOLDER,
+ }}};
+
static void EnqueueEvent(u64 userdata, s64 cycles_late = 0)
{
if (userdata & ENQUEUE_ACKNOWLEDGEMENT_FLAG)
@@ -109,6 +411,48 @@ static void SDIO_EventNotify_CPUThread(u64 userdata, s64 cycles_late)
device->EventNotify();
}
+bool SetupMemory(u64 ios_title_id)
+{
+ auto target_imv = std::find_if(
+ ios_memory_values.begin(), ios_memory_values.end(),
+ [&](const IosMemoryValues& imv) { return imv.ios_number == (ios_title_id & 0xffff); });
+
+ if (target_imv == ios_memory_values.end())
+ {
+ ERROR_LOG(IOS, "Unknown IOS version: %016" PRIx64, ios_title_id);
+ return false;
+ }
+
+ 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);
+ Memory::Write_U32(target_imv->mem1_arena_begin, ADDR_MEM1_ARENA_BEGIN);
+ Memory::Write_U32(target_imv->mem1_arena_end, ADDR_MEM1_ARENA_END);
+ Memory::Write_U32(PLACEHOLDER, ADDR_PH1);
+ Memory::Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE);
+ Memory::Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
+ Memory::Write_U32(target_imv->mem2_end, ADDR_MEM2_END);
+ Memory::Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
+ Memory::Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END);
+ Memory::Write_U32(PLACEHOLDER, ADDR_PH2);
+ Memory::Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
+ Memory::Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END);
+ Memory::Write_U32(target_imv->hollywood_revision, ADDR_HOLLYWOOD_REVISION);
+ Memory::Write_U32(PLACEHOLDER, ADDR_PH3);
+ Memory::Write_U32(target_imv->ios_version, ADDR_IOS_VERSION);
+ Memory::Write_U32(target_imv->ios_date, ADDR_IOS_DATE);
+ Memory::Write_U32(target_imv->unknown_begin, ADDR_UNKNOWN_BEGIN);
+ Memory::Write_U32(target_imv->unknown_end, ADDR_UNKNOWN_END);
+ Memory::Write_U32(PLACEHOLDER, ADDR_PH4);
+ Memory::Write_U32(PLACEHOLDER, ADDR_PH5);
+ Memory::Write_U32(target_imv->ram_vendor, ADDR_RAM_VENDOR);
+ 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);
+ return true;
+}
+
static u32 num_devices;
template <typename T>
diff --git a/Source/Core/Core/IOS/IPC.h b/Source/Core/Core/IOS/IPC.h
index c6cea1ef99..1c6146b793 100644
--- a/Source/Core/Core/IOS/IPC.h
+++ b/Source/Core/Core/IOS/IPC.h
@@ -51,6 +51,8 @@ void Init();
// Needs to be called after Reset(true) to recreate the device tree
void Reinit();
+bool SetupMemory(u64 ios_title_id);
+
// Shutdown
void Shutdown();