Skip to content
Permalink
Browse files

Merge pull request #4723 from booto/ios-init

Set up IOS RAM information area with real values.
  • Loading branch information
delroth committed Jan 25, 2017
2 parents 54e7d4a + d16ca2e commit 18968abbd7d76e7b1693fe7e393c6fbecce00a5e
@@ -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))
@@ -52,5 +52,5 @@ class CBoot
static bool Load_BS2(const std::string& _rBootROMFilename);
static void Load_FST(bool _bIsWii);

static bool SetupWiiMemory();
static bool SetupWiiMemory(u64 ios_title_id);
};
@@ -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
@@ -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 =

0 comments on commit 18968ab

Please sign in to comment.
You can’t perform that action at this time.