Initial support for title switching + better Wii U menu compatibility (#907)

This commit is contained in:
Exzap 2023-07-21 13:54:07 +02:00 committed by GitHub
parent bfbeeae6f6
commit 2200cc0ddf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
95 changed files with 2549 additions and 746 deletions

View file

@ -0,0 +1,155 @@
#include "iosu_odm.h"
#include "config/ActiveSettings.h"
#include "Common/FileStream.h"
#include "util/helpers/Semaphore.h"
#include "../kernel/iosu_kernel.h"
namespace iosu
{
namespace odm
{
using namespace iosu::kernel;
std::string s_devicePath = "/dev/odm";
std::thread s_serviceThread;
std::atomic_bool s_requestStop{false};
std::atomic_bool s_isRunning{false};
std::atomic_bool s_threadInitialized{ false };
IOSMsgQueueId s_msgQueueId;
SysAllocator<iosu::kernel::IOSMessage, 128> _s_msgBuffer;
enum class ODM_CMD_OPERATION_TYPE
{
CHECK_STATE = 4,
UKN_5 = 5,
};
enum class ODM_STATE
{
NONE = 0,
INITIAL = 1,
AUTHENTICATION = 2,
WAIT_FOR_DISC_READY = 3,
CAFE_DISC = 4,
RVL_DISC = 5,
CLEANING_DISC = 6,
INVALID_DISC = 8,
DIRTY_DISC = 9,
NO_DISC = 10,
INVALID_DRIVE = 11,
FATAL = 12,
HARD_FATAL = 13,
SHUTDOWN = 14,
};
void ODMHandleCommandIoctl(uint32 clientHandle, IPCCommandBody* cmd, ODM_CMD_OPERATION_TYPE operationId, void* ptrIn, uint32 sizeIn, void* ptrOut, uint32 sizeOut)
{
switch(operationId)
{
case ODM_CMD_OPERATION_TYPE::CHECK_STATE:
{
*(uint32be*)ptrOut = (uint32)ODM_STATE::NO_DISC;
break;
}
case ODM_CMD_OPERATION_TYPE::UKN_5:
{
// does this return anything?
break;
}
default:
{
cemuLog_log(LogType::Force, "ODMHandleCommandIoctl: Unknown operationId %d\n", (uint32)operationId);
break;
}
}
IOS_ResourceReply(cmd, IOS_ERROR_OK);
}
uint32 CreateClientHandle()
{
return 1; // we dont care about handles for now
}
void CloseClientHandle(uint32 handle)
{
}
void ODMServiceThread()
{
s_msgQueueId = IOS_CreateMessageQueue(_s_msgBuffer.GetPtr(), _s_msgBuffer.GetCount());
cemu_assert(!IOS_ResultIsError((IOS_ERROR)s_msgQueueId));
IOS_ERROR r = IOS_RegisterResourceManager(s_devicePath.c_str(), s_msgQueueId);
cemu_assert(!IOS_ResultIsError(r));
s_threadInitialized = true;
while (true)
{
IOSMessage msg;
IOS_ERROR r = IOS_ReceiveMessage(s_msgQueueId, &msg, 0);
cemu_assert(!IOS_ResultIsError(r));
if (msg == 0)
{
cemu_assert_debug(s_requestStop);
break;
}
IPCCommandBody* cmd = MEMPTR<IPCCommandBody>(msg).GetPtr();
uint32 clientHandle = (uint32)cmd->devHandle;
if (cmd->cmdId == IPCCommandId::IOS_OPEN)
{
IOS_ResourceReply(cmd, (IOS_ERROR)CreateClientHandle());
continue;
}
else if (cmd->cmdId == IPCCommandId::IOS_CLOSE)
{
CloseClientHandle((IOSDevHandle)(uint32)cmd->devHandle);
IOS_ResourceReply(cmd, IOS_ERROR_OK);
continue;
}
else if (cmd->cmdId == IPCCommandId::IOS_IOCTLV)
{
uint32 requestId = cmd->args[0];
uint32 numIn = cmd->args[1];
uint32 numOut = cmd->args[2];
IPCIoctlVector* vec = MEMPTR<IPCIoctlVector>{ cmd->args[3] }.GetPtr();
IPCIoctlVector* vecIn = vec + numIn;
IPCIoctlVector* vecOut = vec + 0;
cemuLog_log(LogType::Force, "{}: Received unsupported Ioctlv cmd", s_devicePath);
IOS_ResourceReply(cmd, IOS_ERROR_INVALID);
continue;
}
else if (cmd->cmdId == IPCCommandId::IOS_IOCTL)
{
ODMHandleCommandIoctl(clientHandle, cmd, (ODM_CMD_OPERATION_TYPE)cmd->args[0].value(), MEMPTR<void>(cmd->args[1]), cmd->args[2], MEMPTR<void>(cmd->args[3]), cmd->args[4]);
}
else
{
cemuLog_log(LogType::Force, "{}: Unsupported cmdId", s_devicePath);
cemu_assert_unimplemented();
IOS_ResourceReply(cmd, IOS_ERROR_INVALID);
}
}
s_threadInitialized = false;
}
void Initialize()
{
if (s_isRunning.exchange(true))
return;
s_threadInitialized = false;
s_requestStop = false;
s_serviceThread = std::thread(&ODMServiceThread);
while (!s_threadInitialized) std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
void Shutdown()
{
if (!s_isRunning.exchange(false))
return;
s_requestStop = true;
IOS_SendMessage(s_msgQueueId, 0, 0);
s_serviceThread.join();
}
}
}

View file

@ -0,0 +1,10 @@
#pragma once
namespace iosu
{
namespace odm
{
void Initialize();
void Shutdown();
}
}

View file

@ -369,7 +369,8 @@ namespace iosu
{
sPDMRequestExitThread.store(true);
sPDMSem.increment();
sPDMTimeTrackingThread.join();
if(sPDMTimeTrackingThread.joinable())
sPDMTimeTrackingThread.join();
}
};

View file

@ -238,7 +238,7 @@ namespace iosu
nnResult ServiceCall(uint32 serviceId, void* request, void* response) override
{
cemuLog_log(LogType::Force, "Unsupported service call to /dec/act");
cemuLog_log(LogType::Force, "Unsupported service call to /dev/act");
cemu_assert_unimplemented();
return BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_ACT, 0);
}

View file

@ -53,8 +53,10 @@ namespace iosu
std::string titlePath = CafeSystem::GetMlcStoragePath(titleId);
strcpy(titleOut.appPath, titlePath.c_str());
strcpy((char*)titleOut.deviceName, "mlc");
titleOut.osVersion = 0; // todo
titleOut.sdkVersion = 0;
titleOut.sdkVersion = it->GetAppSDKVersion();
}
numTitlesCopied++;
@ -73,7 +75,8 @@ namespace iosu
sint32 mcpGetTitleList(MCPTitleInfo* titleList, uint32 titleListBufferSize, uint32be* titleCount)
{
std::unique_lock _lock(sTitleInfoMutex);
*titleCount = mcpBuildTitleList(titleList, *titleCount, [](const TitleInfo& titleInfo) -> bool { return true; });
uint32 maxEntryCount = titleListBufferSize / sizeof(MCPTitleInfo);
*titleCount = mcpBuildTitleList(titleList, maxEntryCount, [](const TitleInfo& titleInfo) -> bool { return true; });
return 0;
}
@ -86,7 +89,7 @@ namespace iosu
sint32 mcpGetTitleListByAppType(MCPTitleInfo* titleList, uint32 titleListBufferSize, uint32be* titleCount, uint32 appType)
{
std::unique_lock _lock(sTitleInfoMutex);
uint32 maxEntryCount = (uint32)*titleCount;
uint32 maxEntryCount = titleListBufferSize / sizeof(MCPTitleInfo);
*titleCount = mcpBuildTitleList(titleList, maxEntryCount, [appType](const TitleInfo& titleInfo) -> bool { return titleInfo.GetAppType() == appType; });
return 0;
}
@ -94,7 +97,7 @@ namespace iosu
sint32 mcpGetTitleListByTitleId(MCPTitleInfo* titleList, uint32 titleListBufferSize, uint32be* titleCount, uint64 titleId)
{
std::unique_lock _lock(sTitleInfoMutex);
uint32 maxEntryCount = (uint32)*titleCount;
uint32 maxEntryCount = titleListBufferSize / sizeof(MCPTitleInfo);
*titleCount = mcpBuildTitleList(titleList, maxEntryCount, [titleId](const TitleInfo& titleInfo) -> bool { return titleInfo.GetAppTitleId() == titleId; });
return 0;
}
@ -143,11 +146,11 @@ namespace iosu
return 0;
}
// deprecated
void iosuMcp_init()
{
if (iosuMcp.isInitialized)
return;
// start the act thread
std::thread t(iosuMcp_thread);
t.detach();
iosuMcp.isInitialized = true;

View file

@ -13,7 +13,8 @@ struct MCPTitleInfo
// everything below is uncertain
/* +0x4A */ uint64be osVersion; // app.xml
/* +0x52 */ uint32be sdkVersion; // app.xml
/* +0x56 */ uint8 ukn[0x61 - 0x56];
/* +0x56 */ uint8 deviceName[10];
/* +0x60 */ uint8 uknPadding; // possibly the index of the device?
//move this and the stuff below
};

View file

@ -8,11 +8,9 @@
#include "openssl/x509.h"
#include "openssl/ssl.h"
#include "util/helpers/helpers.h"
#include <thread>
#include "Cemu/napi/napi.h"
#include "Cemu/ncrypto/ncrypto.h"
#include "Cafe/CafeSystem.h"
namespace iosu
{
@ -47,6 +45,13 @@ namespace iosu
bool backgroundThreadStarted;
} g_nim = {};
bool nim_CheckDownloadsDisabled()
{
// currently for the Wii U menu we disable NIM to speed up boot times
uint64 tid = CafeSystem::GetForegroundTitleId();
return tid == 0x0005001010040000 || tid == 0x0005001010040100 || tid == 0x0005001010040200;
}
bool nim_getLatestVersion()
{
g_nim.latestVersion = -1;
@ -101,6 +106,13 @@ namespace iosu
void nim_buildDownloadList()
{
if(nim_CheckDownloadsDisabled())
{
cemuLog_logDebug(LogType::Force, "nim_buildDownloadList: Downloads are disabled for this title");
g_nim.packages.clear();
return;
}
sint32 titleCount = mcpGetTitleCount();
MCPTitleInfo* titleList = (MCPTitleInfo*)malloc(titleCount * sizeof(MCPTitleInfo));
memset(titleList, 0, titleCount * sizeof(MCPTitleInfo));
@ -141,6 +153,8 @@ namespace iosu
void nim_getPackagesInfo(uint64* titleIdList, sint32 count, titlePackageInfo_t* packageInfoList)
{
memset(packageInfoList, 0, sizeof(titlePackageInfo_t)*count);
if(nim_CheckDownloadsDisabled())
return;
for (sint32 i = 0; i < count; i++)
{
uint64 titleId = _swapEndianU64(titleIdList[i]);