Merge branch 'geckoos-fix'

Fixes issue 6551.
This commit is contained in:
comex 2013-09-13 18:18:51 -04:00
commit 0040e66282
8 changed files with 83 additions and 32 deletions

View File

@ -184,14 +184,6 @@ bool CBoot::BootUp()
NOTICE_LOG(BOOT, "Booting %s", _StartupPara.m_strFilename.c_str());
// HLE jump to loader (homebrew). Disabled when Gecko is active as it interferes with the code handler
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats)
{
HLE::Patch(0x80001800, "HBReload");
const u8 stubstr[] = { 'S', 'T', 'U', 'B', 'H', 'A', 'X', 'X' };
Memory::WriteBigEData(stubstr, 0x80001804, 8);
}
g_symbolDB.Clear();
VideoInterface::Preset(_StartupPara.bNTSC);
switch (_StartupPara.m_BootType)
@ -415,6 +407,19 @@ bool CBoot::BootUp()
return false;
}
}
// HLE jump to loader (homebrew). Disabled when Gecko is active as it interferes with the code handler
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats)
{
HLE::Patch(0x80001800, "HBReload");
const u8 stubstr[] = { 'S', 'T', 'U', 'B', 'H', 'A', 'X', 'X' };
Memory::WriteBigEData(stubstr, 0x80001804, 8);
}
// Not part of the binary itself, but either we or Gecko OS might insert
// this, and it doesn't clear the icache properly.
HLE::Patch(0x800018a8, "GeckoCodehandler");
Host_UpdateLogDisplay();
return true;
}

View File

@ -154,8 +154,9 @@ bool InstallCodeHandler()
// Turn off Pause on start
Memory::Write_U32(0, 0x80002774);
// Write the Game ID into the location expected by WiiRD
Memory::WriteBigEData(Memory::GetPointer(0x80000000), 0x80001800, 6);
// Write a magic value to 'gameid' (codehandleronly does not actually read this).
// For the purpose of this, see HLEGeckoCodehandler.
Memory::Write_U32(0xd01f1bad, 0x80001800);
// Create GCT in memory
Memory::Write_U32(0x00d0c0de, codelist_location);
@ -279,10 +280,7 @@ void RunCodeHandler()
{
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats && active_codes.size() > 0)
{
u8 *gameId = Memory::GetPointer(0x80000000);
u8 *wiirdId = Memory::GetPointer(0x80001800);
if (!code_handler_installed || memcmp(gameId, wiirdId, 6))
if (!code_handler_installed || Memory::Read_U32(0x80001800) - 0xd01f1bad > 5)
code_handler_installed = InstallCodeHandler();
if (code_handler_installed)

View File

@ -63,6 +63,7 @@ static const SPatch OSPatches[] =
{ "___blank(char *,...)", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // used for early init things (normally)
{ "___blank", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "__write_console", HLE_OS::HLE_write_console, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // used by sysmenu (+more?)
{ "GeckoCodehandler", HLE_Misc::HLEGeckoCodehandler, HLE_HOOK_START, HLE_TYPE_GENERIC },
};
static const SPatch OSBreakPoints[] =

View File

@ -17,6 +17,7 @@
#include "IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "HLE.h"
#include "PowerPC/PPCAnalyst.h"
#include "PowerPC/PPCCache.h"
#include "PowerPC/SignatureDB.h"
#include "PowerPC/PPCSymbolDB.h"
#include "CommonPaths.h"
@ -242,4 +243,26 @@ void OSBootDol()
NPC = PC;
}
void HLEGeckoCodehandler()
{
// Work around the codehandler not properly invalidating the icache, but
// only the first few frames.
// (Project M uses a conditional to only apply patches after something has
// been read into memory, or such, so we do the first 5 frames. More
// robust alternative would be to actually detect memory writes, but that
// would be even uglier.)
u32 magic = 0xd01f1bad;
u32 existing = Memory::Read_U32(0x80001800);
if (existing - magic == 5)
{
return;
}
else if(existing - magic > 5)
{
existing = magic;
}
Memory::Write_U32(existing + 1, 0x80001800);
PowerPC::ppcState.iCache.Reset();
}
}

View File

@ -12,6 +12,7 @@ namespace HLE_Misc
void HBReload();
void OSBootDol();
void OSGetResetCode();
void HLEGeckoCodehandler();
}
#endif

View File

@ -150,6 +150,12 @@ void Reset(bool _bHard)
g_FdMap[i] = NULL;
}
u32 j;
for (j=0; j<ES_MAX_COUNT; j++)
{
es_inuse[j] = false;
}
TDeviceMap::iterator itr = g_DeviceMap.begin();
while (itr != g_DeviceMap.end())
{
@ -548,17 +554,6 @@ void ExecuteCommand(u32 _Address)
// Generate a reply to the IPC command
EnqReply(_Address, reply_delay);
}
else
{
if (pDevice)
{
INFO_LOG(WII_IPC_HLE, "<<-- Reply Failed to %s IPC Request %i @ 0x%08x ", pDevice->GetDeviceName().c_str(), Command, _Address);
}
else
{
INFO_LOG(WII_IPC_HLE, "<<-- Reply Failed to Unknown (%08x) IPC Request %i @ 0x%08x ", DeviceID, Command, _Address);
}
}
}
// Happens AS SOON AS IPC gets a new pointer!

View File

@ -594,13 +594,18 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
ViewCount = FileSize / DiscIO::INANDContentLoader::TICKET_SIZE;
_dbg_assert_msg_(WII_IPC_ES, (ViewCount>0) && (ViewCount<=4), "IOCTL_ES_GETVIEWCNT ticket count seems to be wrong");
}
else if (TitleID >> 32 == 0x00000001)
{
// Fake a ticket view to make IOS reload work.
ViewCount = 1;
}
else
{
ViewCount = 0;
if (TitleID == TITLEID_SYSMENU)
{
PanicAlertT("There must be a ticket for 00000001/00000002. Your NAND dump is probably incomplete.");
}
ViewCount = 0;
//retVal = ES_NO_TICKET_INSTALLED;
}
}
@ -651,6 +656,19 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
}
}
}
else if (TitleID >> 32 == 0x00000001)
{
// For IOS titles, the ticket view isn't normally parsed by either the
// SDK or libogc, just passed to LaunchTitle, so this
// shouldn't matter at all. Just fill out some fields just
// to be on the safe side.
u32 Address = Buffer.PayloadBuffer[0].m_Address;
memset(Memory::GetPointer(Address), 0, 0xD8);
Memory::Write_U64(TitleID, Address + 4 + (0x1dc - 0x1d0)); // title ID
Memory::Write_U16(0xffff, Address + 4 + (0x1e4 - 0x1d0)); // unnnown
Memory::Write_U32(0xff00, Address + 4 + (0x1ec - 0x1d0)); // access mask
memset(Memory::GetPointer(Address + 4 + (0x222 - 0x1d0)), 0xff, 0x20); // content permissions
}
else
{
//retVal = ES_NO_TICKET_INSTALLED;
@ -916,10 +934,11 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
// Lie to mem about loading a different IOS
// someone with an affected game should test
IOSv = TitleID & 0xffff;
bSuccess = true;
}
if (!bSuccess && IOSv >= 30 && IOSv != 0xffff)
if (!bSuccess)
{
PanicAlertT("IOCTL_ES_LAUNCH: Game tried to reload an IOS or a title that is not available in your NAND dump\n"
PanicAlertT("IOCTL_ES_LAUNCH: Game tried to reload a title that is not available in your NAND dump\n"
"TitleID %016llx.\n Dolphin will likely hang now.", TitleID);
}
else
@ -966,14 +985,13 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
ERROR_LOG(WII_IPC_ES, "IOCTL_ES_LAUNCH %016llx %08x %016llx %08x %016llx %04x", TitleID,view,ticketid,devicetype,titleid,access);
// IOCTL_ES_LAUNCH 0001000248414341 00000001 0001c0fef3df2cfa 00000000 0001000248414341 ffff
//We have to handle the reply ourselves as this handle is not valid anymore
// This is necessary because Reset(true) above deleted this object. Ew.
// It seems that the original hardware overwrites the command after it has been
// executed. We write 8 which is not any valid command, and what IOS does
Memory::Write_U32(8, _CommandAddress);
// IOS seems to write back the command that was responded to
Memory::Write_U32(6, _CommandAddress + 8);
Memory::Write_U32(7, _CommandAddress + 8);
// Generate a reply to the IPC command
WII_IPC_HLE_Interface::EnqReply(_CommandAddress, 0);

View File

@ -106,10 +106,20 @@ int Interpreter::SingleStepInner(void)
if (HLE::IsEnabled(flags))
{
HLEFunction(function);
if (type == HLE::HLE_HOOK_START)
{
// Run the original.
function = 0;
}
}
else
{
function = 0;
}
}
}
else
if (function == 0)
{
#ifdef USE_GDBSTUB
if (gdb_active() && gdb_bp_x(PC)) {