Merge pull request #5406 from JosJuice/refactor-emulatedbs2

Boot: Refactor EmulatedBS2
This commit is contained in:
Leo Lam 2017-05-13 00:31:11 +02:00 committed by GitHub
commit f4e115b322
3 changed files with 100 additions and 169 deletions

View File

@ -353,28 +353,9 @@ bool CBoot::BootUp()
if (!EmulatedBS2(dolWii))
{
// 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;
if (dolLoader.IsWii())
HID4.SBE = 1;
PowerPC::DBATUpdated();
PowerPC::IBATUpdated();
SetupBAT(/*is_wii*/ true);
// Because there is no TMD to get the requested system (IOS) version from,
// we default to IOS58, which is the version used by the Homebrew Channel.

View File

@ -48,6 +48,8 @@ private:
static bool Boot_ELF(const std::string& filename);
static bool Boot_WiiWAD(const std::string& filename);
static void SetupBAT(bool is_wii);
static bool RunApploader(bool is_wii);
static bool EmulatedBS2_GC(bool skip_app_loader = false);
static bool EmulatedBS2_Wii();
static bool EmulatedBS2(bool is_wii);

View File

@ -52,15 +52,8 @@ void CBoot::RunFunction(u32 address)
PowerPC::SingleStep();
}
// __________________________________________________________________________________________________
// GameCube Bootstrap 2 HLE:
// copy the apploader to 0x81200000
// execute the apploader, function by function, using the above utility.
bool CBoot::EmulatedBS2_GC(bool skip_app_loader)
void CBoot::SetupBAT(bool is_wii)
{
INFO_LOG(BOOT, "Faking GC BS2...");
// 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;
@ -72,8 +65,99 @@ bool CBoot::EmulatedBS2_GC(bool skip_app_loader)
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
if (is_wii)
{
PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff;
PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002;
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();
}
bool CBoot::RunApploader(bool is_wii)
{
// Load Apploader to Memory - The apploader is hardcoded to begin at 0x2440 on the disc,
// but the size can differ between discs. Compare with YAGCD chap 13.
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
const u32 apploader_offset = 0x2440;
u32 apploader_entry = 0;
u32 apploader_size = 0;
u32 apploader_trailer = 0;
if (!volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, is_wii) ||
!volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, is_wii) ||
!volume.ReadSwapped(apploader_offset + 0x18, &apploader_trailer, is_wii) ||
apploader_entry == (u32)-1 || apploader_size + apploader_trailer == (u32)-1)
{
INFO_LOG(BOOT, "Invalid apploader. Your disc image is probably corrupted.");
return false;
}
DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size + apploader_trailer, is_wii);
// TODO - Make Apploader(or just RunFunction()) debuggable!!!
// Call iAppLoaderEntry.
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderEntry");
const u32 iAppLoaderFuncAddr = is_wii ? 0x80004000 : 0x80003100;
PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
RunFunction(apploader_entry);
const u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
const u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
const u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
// iAppLoaderInit
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderInit");
HLE::Patch(0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader
PowerPC::ppcState.gpr[3] = 0x81300000;
RunFunction(iAppLoaderInit);
// iAppLoaderMain - Here we load the apploader, the DOL (the exe) and the FST (filesystem).
// To give you an idea about where the stuff is located on the disc take a look at yagcd
// ch 13.
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderMain");
do
{
PowerPC::ppcState.gpr[3] = 0x81300004;
PowerPC::ppcState.gpr[4] = 0x81300008;
PowerPC::ppcState.gpr[5] = 0x8130000c;
RunFunction(iAppLoaderMain);
u32 iRamAddress = PowerPC::Read_U32(0x81300004);
u32 iLength = PowerPC::Read_U32(0x81300008);
u32 iDVDOffset = PowerPC::Read_U32(0x8130000c) << (is_wii ? 2 : 0);
INFO_LOG(MASTER_LOG, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset,
iRamAddress, iLength);
DVDRead(iDVDOffset, iRamAddress, iLength, is_wii);
} while (PowerPC::ppcState.gpr[3] != 0x00);
// iAppLoaderClose
DEBUG_LOG(MASTER_LOG, "call iAppLoaderClose");
RunFunction(iAppLoaderClose);
HLE::UnPatch("AppLoaderReport");
// return
PC = PowerPC::ppcState.gpr[3];
return true;
}
// __________________________________________________________________________________________________
// GameCube Bootstrap 2 HLE:
// copy the apploader to 0x81200000
// execute the apploader, function by function, using the above utility.
bool CBoot::EmulatedBS2_GC(bool skip_app_loader)
{
INFO_LOG(BOOT, "Faking GC BS2...");
SetupBAT(/*is_wii*/ false);
// Write necessary values
// Here we write values to memory that the apploader does not take care of. Game info goes
@ -114,21 +198,6 @@ bool CBoot::EmulatedBS2_GC(bool skip_app_loader)
if (!DVDInterface::IsDiscInside())
return false;
// Load Apploader to Memory - The apploader is hardcoded to begin at 0x2440 on the disc,
// but the size can differ between discs. Compare with YAGCD chap 13.
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
const u32 apploader_offset = 0x2440;
u32 apploader_entry, apploader_size, apploader_trailer;
if (skip_app_loader || !volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, false) ||
!volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, false) ||
!volume.ReadSwapped(apploader_offset + 0x18, &apploader_trailer, false) ||
apploader_entry == (u32)-1 || apploader_size + apploader_trailer == (u32)-1)
{
INFO_LOG(BOOT, "GC BS2: Not running apploader!");
return false;
}
DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size + apploader_trailer, false);
// Setup pointers like real BS2 does
if (ntsc)
{
@ -146,56 +215,10 @@ bool CBoot::EmulatedBS2_GC(bool skip_app_loader)
PowerPC::ppcState.gpr[13] = 0x814b4fc0;
}
// TODO - Make Apploader(or just RunFunction()) debuggable!!!
if (skip_app_loader)
return false;
// Call iAppLoaderEntry.
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderEntry");
u32 iAppLoaderFuncAddr = 0x80003100;
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(MASTER_LOG, "Call iAppLoaderInit");
HLE::Patch(0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader
PowerPC::ppcState.gpr[3] = 0x81300000;
RunFunction(iAppLoaderInit);
// iAppLoaderMain - Here we load the apploader, the DOL (the exe) and the FST (filesystem).
// To give you an idea about where the stuff is located on the disc take a look at yagcd
// ch 13.
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderMain");
do
{
PowerPC::ppcState.gpr[3] = 0x81300004;
PowerPC::ppcState.gpr[4] = 0x81300008;
PowerPC::ppcState.gpr[5] = 0x8130000c;
RunFunction(iAppLoaderMain);
u32 iRamAddress = PowerPC::Read_U32(0x81300004);
u32 iLength = PowerPC::Read_U32(0x81300008);
u32 iDVDOffset = PowerPC::Read_U32(0x8130000c);
INFO_LOG(MASTER_LOG, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset,
iRamAddress, iLength);
DVDRead(iDVDOffset, iRamAddress, iLength, false);
} while (PowerPC::ppcState.gpr[3] != 0x00);
// iAppLoaderClose
DEBUG_LOG(MASTER_LOG, "call iAppLoaderClose");
RunFunction(iAppLoaderClose);
HLE::UnPatch("AppLoaderReport");
// return
PC = PowerPC::ppcState.gpr[3];
return true;
return RunApploader(/*is_wii*/ false);
}
bool CBoot::SetupWiiMemory(u64 ios_title_id)
@ -333,26 +356,7 @@ bool CBoot::EmulatedBS2_Wii()
// 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();
SetupBAT(/*is_wii*/ true);
Memory::Write_U32(0x4c000064, 0x00000300); // Write default DSI Handler: rfi
Memory::Write_U32(0x4c000064, 0x00000800); // Write default FPU Handler: rfi
@ -360,67 +364,11 @@ bool CBoot::EmulatedBS2_Wii()
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
// Execute the apploader
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.");
if (!RunApploader(/*is_wii*/ true))
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");
HLE::Patch(0x81300000, "AppLoaderReport"); // HLE OSReport for Apploader
PowerPC::ppcState.gpr[3] = 0x81300000;
RunFunction(iAppLoaderInit);
// Let the apploader load the exe to memory
DEBUG_LOG(BOOT, "Run iAppLoaderMain");
do
{
PowerPC::ppcState.gpr[3] = 0x81300004;
PowerPC::ppcState.gpr[4] = 0x81300008;
PowerPC::ppcState.gpr[5] = 0x8130000c;
RunFunction(iAppLoaderMain);
u32 iRamAddress = PowerPC::Read_U32(0x81300004);
u32 iLength = PowerPC::Read_U32(0x81300008);
u32 iDVDOffset = PowerPC::Read_U32(0x8130000c) << 2;
INFO_LOG(BOOT, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress,
iLength);
DVDRead(iDVDOffset, iRamAddress, iLength, true);
} while (PowerPC::ppcState.gpr[3] != 0x00);
// iAppLoaderClose
DEBUG_LOG(BOOT, "Run iAppLoaderClose");
RunFunction(iAppLoaderClose);
HLE::UnPatch("AppLoaderReport");
IOS::HLE::Device::ES::DIVerify(tmd, DVDInterface::GetVolume().GetTicket());
// return
PC = PowerPC::ppcState.gpr[3];
return true;
}