Merge pull request #499 from magumagu/ipchle-disk-channel

ES_LAUNCH fixes for disk channel etc
This commit is contained in:
Ryan Houdek 2014-06-25 04:00:57 -05:00
commit a99ad2db7c
6 changed files with 42 additions and 232 deletions

View File

@ -46,10 +46,6 @@ static const SPatch OSPatches[] =
// Name doesn't matter, installed in CBoot::BootUp()
{ "HBReload", HLE_Misc::HBReload, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// ES_LAUNCH
{ "__OSBootDol", HLE_Misc::OSBootDol, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
{ "OSGetResetCode", HLE_Misc::OSGetResetCode, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// Debug/OS Support
{ "OSPanic", HLE_OS::HLE_OSPanic, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },

View File

@ -54,206 +54,6 @@ void HBReload()
Host_Message(WM_USER_STOP);
}
void ExecuteDOL(u8* dolFile, u32 fileSize)
{
// Clear memory before loading the dol
for (u32 i = 0x80004000; i < Memory::Read_U32(0x00000034); i += 4)
{
// TODO: Should not write over the "save region"
Memory::Write_U32(0x00000000, i);
}
CDolLoader dolLoader(dolFile, fileSize);
dolLoader.Load();
// Scan for common HLE functions
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging)
{
g_symbolDB.Clear();
PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB);
SignatureDB db;
if (db.Load(File::GetSysDirectory() + TOTALDB))
{
db.Apply(&g_symbolDB);
HLE::PatchFunctions();
db.Clear();
}
}
PowerPC::ppcState.iCache.Reset();
TextureCache::RequestInvalidateTextureCache();
CWII_IPC_HLE_Device_usb_oh1_57e_305* s_Usb = GetUsbPointer();
size_t size = s_Usb->m_WiiMotes.size();
bool* wiiMoteConnected = new bool[size];
for (unsigned int i = 0; i < size; i++)
wiiMoteConnected[i] = s_Usb->m_WiiMotes[i].IsConnected();
WII_IPC_HLE_Interface::Reset(true);
WII_IPC_HLE_Interface::Init();
s_Usb = GetUsbPointer();
for (unsigned int i = 0; i < s_Usb->m_WiiMotes.size(); i++)
{
if (wiiMoteConnected[i])
{
s_Usb->m_WiiMotes[i].Activate(false);
s_Usb->m_WiiMotes[i].Activate(true);
}
else
{
s_Usb->m_WiiMotes[i].Activate(false);
}
}
delete[] wiiMoteConnected;
if (argsPtr)
{
u32 args_base = Memory::Read_U32(0x800000f4);
u32 ptr_to_num_args = 0xc;
u32 num_args = 1;
u32 hi_ptr = args_base + ptr_to_num_args + 4;
u32 new_args_ptr = args_base + ptr_to_num_args + 8;
Memory::Write_U32(ptr_to_num_args, args_base + 8);
Memory::Write_U32(num_args, args_base + ptr_to_num_args);
Memory::Write_U32(0x14, hi_ptr);
for (unsigned int i = 0; i < args.length(); i++)
Memory::WriteUnchecked_U8(args[i], new_args_ptr+i);
}
NPC = dolLoader.GetEntryPoint() | 0x80000000;
}
void LoadDOLFromDisc(std::string dol)
{
DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename);
DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume);
if (dol.length() > 1 && dol.compare(0, 1, "/") == 0)
dol = dol.substr(1);
u32 fileSize = (u32) pFileSystem->GetFileSize(dol);
u8* dolFile = new u8[fileSize];
if (fileSize > 0)
{
pFileSystem->ReadFile(dol, dolFile, fileSize);
ExecuteDOL(dolFile, fileSize);
}
delete[] dolFile;
}
void LoadBootDOLFromDisc()
{
DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename);
DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume);
u32 fileSize = pFileSystem->GetBootDOLSize();
u8* dolFile = new u8[fileSize];
if (fileSize > 0)
{
pFileSystem->GetBootDOL(dolFile, fileSize);
ExecuteDOL(dolFile, fileSize);
}
delete[] dolFile;
}
u32 GetDolFileSize(std::string dol)
{
DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename);
DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume);
std::string dolFile;
if (dol.length() > 1 && dol.compare(0, 1, "/") == 0)
dolFile = dol.substr(1);
else
dolFile = dol;
return (u32)pFileSystem->GetFileSize(dolFile);
}
u16 GetIOSVersion()
{
return Memory::Read_U16(0x00003140);
}
void OSGetResetCode()
{
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
{
u32 resetCode = Memory::Read_U32(0xCC003024);
if ((resetCode & 0x1fffffff) != 0)
{
GPR(3) = resetCode | 0x80000000;
}
else
{
GPR(3) = 0;
}
NPC = LR;
}
else
{
HLE::UnPatch("OSGetResetCode");
NPC = PC;
}
}
void OSBootDol()
{
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && GetIOSVersion() >= 30)
{
if ((GPR(4) >> 28) == 0x8)
{
u32 resetCode = GPR(30);
// Reset game
Memory::Write_U32(resetCode, 0xCC003024);
LoadBootDOLFromDisc();
return;
}
else if ((GPR(4) >> 28) == 0xA)
{
// Boot from disc partition
PanicAlert("Boot Partition: %08x", GPR(26));
}
else if ((GPR(4) >> 28) == 0xC)
{
std::string dol;
// Boot DOL from disc
u32 ptr = GPR(28);
Memory::GetString(dol, ptr);
if (GetDolFileSize(dol) == 0)
{
ptr = GPR(30);
Memory::GetString(dol, ptr);
if (GetDolFileSize(dol) == 0)
{
// Cannot locate the dol file, exit.
HLE::UnPatch("__OSBootDol");
NPC = PC;
return;
}
}
argsPtr = Memory::Read_U32(GPR(5));
Memory::GetString(args, argsPtr);
LoadDOLFromDisc(dol);
return;
}
else
{
PanicAlert("Unknown boot type: %08x", GPR(4));
}
}
HLE::UnPatch("__OSBootDol");
NPC = PC;
}
void HLEGeckoCodehandler()
{
// Work around the codehandler not properly invalidating the icache, but

View File

@ -9,7 +9,5 @@ namespace HLE_Misc
void HLEPanicAlert();
void UnimplementedFunction();
void HBReload();
void OSBootDol();
void OSGetResetCode();
void HLEGeckoCodehandler();
}

View File

@ -76,21 +76,28 @@ IWII_IPC_HLE_Device* es_handles[ES_MAX_COUNT];
typedef std::deque<u32> ipc_msg_queue;
static ipc_msg_queue request_queue; // ppc -> arm
static ipc_msg_queue reply_queue; // arm -> ppc
static ipc_msg_queue ack_queue; // arm -> ppc
static int event_enqueue_reply;
static int event_enqueue_request;
static int event_enqueue;
static u64 last_reply_time;
static void EnqueueReplyCallback(u64 userdata, int)
static const u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL;
static const u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
static void EnqueueEventCallback(u64 userdata, int)
{
reply_queue.push_back((u32)userdata);
Update();
}
static void EnqueueRequestCallback(u64 userdata, int)
{
request_queue.push_back((u32)userdata);
if (userdata & ENQUEUE_ACKNOWLEDGEMENT_FLAG)
{
ack_queue.push_back((u32)userdata);
}
else if (userdata & ENQUEUE_REQUEST_FLAG)
{
request_queue.push_back((u32)userdata);
}
else
{
reply_queue.push_back((u32)userdata);
}
Update();
}
@ -136,14 +143,12 @@ void Init()
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, "/dev/usb/oh1"); i++;
g_DeviceMap[i] = new IWII_IPC_HLE_Device(i, "_Unimplemented_Device_"); i++;
event_enqueue_reply = CoreTiming::RegisterEvent("IPCReply", EnqueueReplyCallback);
event_enqueue_request = CoreTiming::RegisterEvent("IPCRequest", EnqueueRequestCallback);
event_enqueue = CoreTiming::RegisterEvent("IPCEvent", EnqueueEventCallback);
}
void Reset(bool _bHard)
{
CoreTiming::RemoveAllEvents(event_enqueue_reply);
CoreTiming::RemoveAllEvents(event_enqueue_request);
CoreTiming::RemoveAllEvents(event_enqueue);
for (IWII_IPC_HLE_Device*& dev : g_FdMap)
{
@ -559,7 +564,7 @@ void ExecuteCommand(u32 _Address)
// Happens AS SOON AS IPC gets a new pointer!
void EnqueueRequest(u32 address)
{
CoreTiming::ScheduleEvent(1000, event_enqueue_request, address);
CoreTiming::ScheduleEvent(1000, event_enqueue, address | ENQUEUE_REQUEST_FLAG);
}
// Called when IOS module has some reply
@ -568,12 +573,18 @@ void EnqueueRequest(u32 address)
// Please search for examples of this being called elsewhere.
void EnqueueReply(u32 address, int cycles_in_future)
{
CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue_reply, address);
CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue, address);
}
void EnqueueReply_Threadsafe(u32 address, int cycles_in_future)
{
CoreTiming::ScheduleEvent_Threadsafe(cycles_in_future, event_enqueue_reply, address);
CoreTiming::ScheduleEvent_Threadsafe(cycles_in_future, event_enqueue, address);
}
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future)
{
CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue,
address | ENQUEUE_ACKNOWLEDGEMENT_FLAG);
}
// This is called every IPC_HLE_PERIOD from SystemTimers.cpp
@ -600,6 +611,14 @@ void Update()
reply_queue.pop_front();
return;
}
if (ack_queue.size())
{
WII_IPCInterface::GenerateAck(ack_queue.front());
WARN_LOG(WII_IPC_HLE, "<<-- Double-ack to IPC Request @ 0x%08x", ack_queue.front());
ack_queue.pop_front();
return;
}
}
void UpdateDevices()

View File

@ -65,5 +65,6 @@ void ExecuteCommand(u32 _Address);
void EnqueueRequest(u32 address);
void EnqueueReply(u32 address, int cycles_in_future = 0);
void EnqueueReply_Threadsafe(u32 address, int cycles_in_future = 0);
void EnqueueCommandAcknowledgement(u32 _Address, int cycles_in_future = 0);
} // end of namespace WII_IPC_HLE_Interface

View File

@ -394,8 +394,6 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
}
SContentAccess& rContent = itr->second;
_dbg_assert_(WII_IPC_ES, rContent.m_pContent->m_pData != nullptr);
u8* pDest = Memory::GetPointer(Addr);
if (rContent.m_Position + Size > rContent.m_pContent->m_Size)
@ -905,7 +903,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
u64 titleid = Memory::Read_U64(Buffer.InBuffer[1].m_Address+16);
u16 access = Memory::Read_U16(Buffer.InBuffer[1].m_Address+24);
std::string tContentFile;
if ((u32)(TitleID>>32) != 0x00000001 || TitleID == TITLEID_SYSMENU)
{
const DiscIO::INANDContentLoader& ContentLoader = AccessContentDevice(TitleID);
@ -915,7 +913,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(bootInd);
if (pContent)
{
LoadWAD(Common::GetTitleContentPath(TitleID));
tContentFile = Common::GetTitleContentPath(TitleID);
std::unique_ptr<CDolLoader> pDolLoader;
if (pContent->m_pData)
{
@ -954,8 +952,6 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
for (unsigned int i = 0; i < size; i++)
wiiMoteConnected[i] = s_Usb->m_WiiMotes[i].IsConnected();
std::string tContentFile(m_ContentFile);
WII_IPC_HLE_Interface::Reset(true);
WII_IPC_HLE_Interface::Init();
s_Usb = GetUsbPointer();
@ -997,9 +993,9 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _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
WII_IPC_HLE_Interface::EnqueueReply(_CommandAddress, 0);
// Generate a "reply" to the IPC command. ES_LAUNCH is unique because it
// involves restarting IOS; IOS generates two acknowledgements in a row.
WII_IPC_HLE_Interface::EnqueueCommandAcknowledgement(_CommandAddress, 0);
return false;
}
break;