Merge pull request #499 from magumagu/ipchle-disk-channel
ES_LAUNCH fixes for disk channel etc
This commit is contained in:
commit
a99ad2db7c
|
@ -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 },
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -9,7 +9,5 @@ namespace HLE_Misc
|
|||
void HLEPanicAlert();
|
||||
void UnimplementedFunction();
|
||||
void HBReload();
|
||||
void OSBootDol();
|
||||
void OSGetResetCode();
|
||||
void HLEGeckoCodehandler();
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue