Merge pull request #4468 from marcan/master

Make the neutered version of HBC work in Dolphin
This commit is contained in:
Anthony 2016-11-30 16:39:53 -06:00 committed by GitHub
commit a3d2dead76
7 changed files with 44 additions and 15 deletions

View File

@ -381,6 +381,8 @@ bool CBoot::BootUp()
PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002; PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002;
PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff; PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a; PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
if (dolLoader.IsWii())
HID4.SBE = 1;
PowerPC::DBATUpdated(); PowerPC::DBATUpdated();
PowerPC::IBATUpdated(); PowerPC::IBATUpdated();

View File

@ -35,12 +35,12 @@ bool CBoot::IsElfWii(const std::string& filename)
u32 HID4_mask = Common::swap32(0xfc1fffff); u32 HID4_mask = Common::swap32(0xfc1fffff);
ElfReader reader(elf.get()); ElfReader reader(elf.get());
for (int i = 0; i < reader.GetNumSections(); ++i) for (int i = 0; i < reader.GetNumSegments(); ++i)
{ {
if (reader.IsCodeSection(i)) if (reader.IsCodeSegment(i))
{ {
u32* code = (u32*)reader.GetSectionDataPtr(i); u32* code = (u32*)reader.GetSegmentPtr(i);
for (u32 j = 0; j < reader.GetSectionSize(i) / sizeof(u32); ++j) for (u32 j = 0; j < reader.GetSegmentSize(i) / sizeof(u32); ++j)
{ {
if ((code[j] & HID4_mask) == HID4_pattern) if ((code[j] & HID4_mask) == HID4_pattern)
return true; return true;
@ -85,6 +85,8 @@ bool CBoot::Boot_ELF(const std::string& filename)
PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002; PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002;
PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff; PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a; PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
if (IsElfWii(filename))
HID4.SBE = 1;
PowerPC::DBATUpdated(); PowerPC::DBATUpdated();
PowerPC::IBATUpdated(); PowerPC::IBATUpdated();

View File

@ -109,7 +109,11 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
return false; return false;
pDolLoader->Load(); pDolLoader->Load();
PC = pDolLoader->GetEntryPoint(); // 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
// because the realmode code at 0x3400 initializes everything itself anyway.
MSR = 0;
PC = 0x3400;
// Pass the "#002 check" // Pass the "#002 check"
// Apploader should write the IOS version and revision to 0x3140, and compare it // Apploader should write the IOS version and revision to 0x3140, and compare it

View File

@ -55,8 +55,9 @@ public:
else else
return nullptr; return nullptr;
} }
bool IsCodeSection(int section) const { return sections[section].sh_type == SHT_PROGBITS; } bool IsCodeSegment(int segment) const { return segments[segment].p_flags & PF_X; }
const u8* GetSegmentPtr(int segment) { return GetPtr(segments[segment].p_offset); } const u8* GetSegmentPtr(int segment) { return GetPtr(segments[segment].p_offset); }
int GetSegmentSize(int segment) const { return segments[segment].p_filesz; }
u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; } u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; }
int GetSectionSize(SectionID section) const { return sections[section].sh_size; } int GetSectionSize(SectionID section) const { return sections[section].sh_size; }
SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found

View File

@ -533,6 +533,11 @@ void ExecuteCommand(u32 address)
{ {
result = device->IOCtl(address); result = device->IOCtl(address);
} }
else
{
Memory::Write_U32(FS_EINVAL, address + 4);
result = IWII_IPC_HLE_Device::GetDefaultReply();
}
break; break;
} }
case IPC_CMD_IOCTLV: case IPC_CMD_IOCTLV:
@ -541,6 +546,11 @@ void ExecuteCommand(u32 address)
{ {
result = device->IOCtlV(address); result = device->IOCtlV(address);
} }
else
{
Memory::Write_U32(FS_EINVAL, address + 4);
result = IWII_IPC_HLE_Device::GetDefaultReply();
}
break; break;
} }
default: default:

View File

@ -937,6 +937,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
{ {
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 2); _dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 2);
bool bSuccess = false; bool bSuccess = false;
bool bReset = false;
u16 IOSv = 0xffff; u16 IOSv = 0xffff;
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
@ -968,13 +969,14 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
if (pDolLoader->IsValid()) 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
// WADs start with address translation off at the given entry point. // 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 // The state of other CPU registers (like the BAT registers) doesn't matter much
// because the WAD initializes everything itself anyway. // because the realmode code at 0x3400 initializes everything itself anyway.
MSR = 0; MSR = 0;
PC = pDolLoader->GetEntryPoint(); PC = 0x3400;
bSuccess = true; bSuccess = true;
bReset = true;
} }
else else
{ {
@ -1045,7 +1047,12 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
Memory::Write_U32(Memory::Read_U32(0x00003140), 0x00003188); Memory::Write_U32(Memory::Read_U32(0x00003140), 0x00003188);
// TODO: provide correct return code when bSuccess= false // TODO: provide correct return code when bSuccess= false
Memory::Write_U32(0, _CommandAddress + 0x4); // Note: If we just reset the PPC, don't write anything to the command buffer. This
// could clobber the DOL we just loaded.
if (!bReset)
{
Memory::Write_U32(0, _CommandAddress + 0x4);
}
ERROR_LOG(WII_IPC_ES, ERROR_LOG(WII_IPC_ES,
"IOCTL_ES_LAUNCH %016" PRIx64 " %08x %016" PRIx64 " %08x %016" PRIx64 " %04x", "IOCTL_ES_LAUNCH %016" PRIx64 " %08x %016" PRIx64 " %08x %016" PRIx64 " %04x",
@ -1055,10 +1062,13 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
// This is necessary because Reset(true) above deleted this object. Ew. // This is necessary because Reset(true) above deleted this object. Ew.
// The original hardware overwrites the command type with the async reply type. if (!bReset)
Memory::Write_U32(IPC_REP_ASYNC, _CommandAddress); {
// IOS also seems to write back the command that was responded to in the FD field. // The original hardware overwrites the command type with the async reply type.
Memory::Write_U32(IPC_CMD_IOCTLV, _CommandAddress + 8); Memory::Write_U32(IPC_REP_ASYNC, _CommandAddress);
// IOS also seems to write back the command that was responded to in the FD field.
Memory::Write_U32(IPC_CMD_IOCTLV, _CommandAddress + 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.

View File

@ -50,7 +50,7 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_ven::IOCtlV(u32 command_address)
IPCCommandResult CWII_IPC_HLE_Device_usb_ven::IOCtl(u32 command_address) IPCCommandResult CWII_IPC_HLE_Device_usb_ven::IOCtl(u32 command_address)
{ {
IPCCommandResult reply = GetNoReply(); IPCCommandResult reply = GetDefaultReply();
u32 command = Memory::Read_U32(command_address + 0x0c); u32 command = Memory::Read_U32(command_address + 0x0c);
u32 buffer_in = Memory::Read_U32(command_address + 0x10); u32 buffer_in = Memory::Read_U32(command_address + 0x10);
u32 buffer_in_size = Memory::Read_U32(command_address + 0x14); u32 buffer_in_size = Memory::Read_U32(command_address + 0x14);