Skip to content

Commit

Permalink
Merge pull request #499 from magumagu/ipchle-disk-channel
Browse files Browse the repository at this point in the history
ES_LAUNCH fixes for disk channel etc
  • Loading branch information
Sonicadvance1 committed Jun 25, 2014
2 parents f544631 + 31b9503 commit a99ad2d
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 232 deletions.
4 changes: 0 additions & 4 deletions Source/Core/Core/HLE/HLE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 },

Expand Down
200 changes: 0 additions & 200 deletions Source/Core/Core/HLE/HLE_Misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 0 additions & 2 deletions Source/Core/Core/HLE/HLE_Misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,5 @@ namespace HLE_Misc
void HLEPanicAlert();
void UnimplementedFunction();
void HBReload();
void OSBootDol();
void OSGetResetCode();
void HLEGeckoCodehandler();
}
53 changes: 36 additions & 17 deletions Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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()
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/IPC_HLE/WII_IPC_HLE.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
14 changes: 5 additions & 9 deletions Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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)
{
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down

1 comment on commit a99ad2d

@successtheman
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sonicadvance1 can I implement this hang loading fix on dolphin 3.5? It is the only version that runs smoothly on my pc. I am running windows 7 and the only configuration I have found to run Smash Bros Brawl smoothly is with directx11 on Windows. Is there any way you or I could implement this fix into a 3.5 windows build and upload it to Google Drive or something?

Please sign in to comment.