mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-10 08:51:19 +12:00
Initial support for title switching + better Wii U menu compatibility (#907)
This commit is contained in:
parent
bfbeeae6f6
commit
2200cc0ddf
95 changed files with 2549 additions and 746 deletions
155
src/Cafe/IOSU/ODM/iosu_odm.cpp
Normal file
155
src/Cafe/IOSU/ODM/iosu_odm.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
10
src/Cafe/IOSU/ODM/iosu_odm.h
Normal file
10
src/Cafe/IOSU/ODM/iosu_odm.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
namespace iosu
|
||||
{
|
||||
namespace odm
|
||||
{
|
||||
void Initialize();
|
||||
void Shutdown();
|
||||
}
|
||||
}
|
|
@ -369,7 +369,8 @@ namespace iosu
|
|||
{
|
||||
sPDMRequestExitThread.store(true);
|
||||
sPDMSem.increment();
|
||||
sPDMTimeTrackingThread.join();
|
||||
if(sPDMTimeTrackingThread.joinable())
|
||||
sPDMTimeTrackingThread.join();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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]);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue