From 5be98da0ac5279a4e05eee22f24f3cb807ceb8f5 Mon Sep 17 00:00:00 2001
From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com>
Date: Sat, 27 Apr 2024 15:49:49 +0200
Subject: [PATCH 001/216] OpenGL: Fix a crash when GL_VERSION is null (#1187)
---
src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
index 28e91b8a..cf134a5d 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
@@ -386,7 +386,7 @@ void OpenGLRenderer::GetVendorInformation()
cemuLog_log(LogType::Force, "GL_RENDERER: {}", glRendererString ? glRendererString : "unknown");
cemuLog_log(LogType::Force, "GL_VERSION: {}", glVersionString ? glVersionString : "unknown");
- if(boost::icontains(glVersionString, "Mesa"))
+ if(glVersionString && boost::icontains(glVersionString, "Mesa"))
{
m_vendor = GfxVendor::Mesa;
return;
From fdf239929ff923eb4b28a16fc4754202391cbc3f Mon Sep 17 00:00:00 2001
From: GaryOderNichts <12049776+GaryOderNichts@users.noreply.github.com>
Date: Mon, 29 Apr 2024 00:24:43 +0200
Subject: [PATCH 002/216] nsysnet: Various improvements (#1188)
- Do not raise an assert for unimplemented optnames
- recvfrom: src_addr and addrlen can be NULL
- getsockopt: Implement SO_TYPE
---
src/Cafe/OS/libs/nsysnet/nsysnet.cpp | 86 ++++++++++++++++++++++------
1 file changed, 69 insertions(+), 17 deletions(-)
diff --git a/src/Cafe/OS/libs/nsysnet/nsysnet.cpp b/src/Cafe/OS/libs/nsysnet/nsysnet.cpp
index 128c19a5..88bca8af 100644
--- a/src/Cafe/OS/libs/nsysnet/nsysnet.cpp
+++ b/src/Cafe/OS/libs/nsysnet/nsysnet.cpp
@@ -36,15 +36,46 @@
#define WU_SO_REUSEADDR 0x0004
#define WU_SO_KEEPALIVE 0x0008
+#define WU_SO_DONTROUTE 0x0010
+#define WU_SO_BROADCAST 0x0020
+#define WU_SO_LINGER 0x0080
+#define WU_SO_OOBINLINE 0x0100
+#define WU_SO_TCPSACK 0x0200
#define WU_SO_WINSCALE 0x0400
#define WU_SO_SNDBUF 0x1001
#define WU_SO_RCVBUF 0x1002
+#define WU_SO_SNDLOWAT 0x1003
+#define WU_SO_RCVLOWAT 0x1004
#define WU_SO_LASTERROR 0x1007
+#define WU_SO_TYPE 0x1008
+#define WU_SO_HOPCNT 0x1009
+#define WU_SO_MAXMSG 0x1010
+#define WU_SO_RXDATA 0x1011
+#define WU_SO_TXDATA 0x1012
+#define WU_SO_MYADDR 0x1013
#define WU_SO_NBIO 0x1014
#define WU_SO_BIO 0x1015
#define WU_SO_NONBLOCK 0x1016
+#define WU_SO_UNKNOWN1019 0x1019 // tcp related
+#define WU_SO_UNKNOWN101A 0x101A // tcp related
+#define WU_SO_UNKNOWN101B 0x101B // tcp related
+#define WU_SO_NOSLOWSTART 0x4000
+#define WU_SO_RUSRBUF 0x10000
-#define WU_TCP_NODELAY 0x2004
+#define WU_TCP_ACKDELAYTIME 0x2001
+#define WU_TCP_NOACKDELAY 0x2002
+#define WU_TCP_MAXSEG 0x2003
+#define WU_TCP_NODELAY 0x2004
+#define WU_TCP_UNKNOWN 0x2005 // amount of mss received before sending an ack
+
+#define WU_IP_TOS 3
+#define WU_IP_TTL 4
+#define WU_IP_MULTICAST_IF 9
+#define WU_IP_MULTICAST_TTL 10
+#define WU_IP_MULTICAST_LOOP 11
+#define WU_IP_ADD_MEMBERSHIP 12
+#define WU_IP_DROP_MEMBERSHIP 13
+#define WU_IP_UNKNOWN 14
#define WU_SOL_SOCKET -1 // this constant differs from Win32 socket API
@@ -548,7 +579,7 @@ void nsysnetExport_setsockopt(PPCInterpreter_t* hCPU)
}
else
{
- cemuLog_logDebug(LogType::Force, "setsockopt(): Unsupported optname 0x{:08x}", optname);
+ cemuLog_logDebug(LogType::Force, "setsockopt(WU_SOL_SOCKET): Unsupported optname 0x{:08x}", optname);
}
}
else if (level == WU_IPPROTO_TCP)
@@ -564,18 +595,22 @@ void nsysnetExport_setsockopt(PPCInterpreter_t* hCPU)
assert_dbg();
}
else
- assert_dbg();
+ {
+ cemuLog_logDebug(LogType::Force, "setsockopt(WU_IPPROTO_TCP): Unsupported optname 0x{:08x}", optname);
+ }
}
else if (level == WU_IPPROTO_IP)
{
hostLevel = IPPROTO_IP;
- if (optname == 0xC)
+ if (optname == WU_IP_MULTICAST_IF || optname == WU_IP_MULTICAST_TTL ||
+ optname == WU_IP_MULTICAST_LOOP || optname == WU_IP_ADD_MEMBERSHIP ||
+ optname == WU_IP_DROP_MEMBERSHIP)
{
- // unknown
+ cemuLog_logDebug(LogType::Socket, "todo: setsockopt() for multicast");
}
- else if( optname == 0x4 )
+ else if(optname == WU_IP_TTL || optname == WU_IP_TOS)
{
- cemuLog_logDebug(LogType::Force, "setsockopt with unsupported opname 4 for IPPROTO_IP");
+ cemuLog_logDebug(LogType::Force, "setsockopt(WU_IPPROTO_IP): Unsupported optname 0x{:08x}", optname);
}
else
assert_dbg();
@@ -649,6 +684,16 @@ void nsysnetExport_getsockopt(PPCInterpreter_t* hCPU)
*(uint32*)optval = _swapEndianU32(optvalLE);
// used by Lost Reavers after some loading screens
}
+ else if (optname == WU_SO_TYPE)
+ {
+ if (memory_readU32(optlenMPTR) != 4)
+ assert_dbg();
+ int optvalLE = 0;
+ socklen_t optlenLE = 4;
+ memory_writeU32(optlenMPTR, 4);
+ *(uint32*)optval = _swapEndianU32(vs->type);
+ r = WU_SO_SUCCESS;
+ }
else if (optname == WU_SO_NONBLOCK)
{
if (memory_readU32(optlenMPTR) != 4)
@@ -661,12 +706,12 @@ void nsysnetExport_getsockopt(PPCInterpreter_t* hCPU)
}
else
{
- cemu_assert_debug(false);
+ cemuLog_logDebug(LogType::Force, "getsockopt(WU_SOL_SOCKET): Unsupported optname 0x{:08x}", optname);
}
}
else
{
- cemu_assert_debug(false);
+ cemuLog_logDebug(LogType::Force, "getsockopt(): Unsupported level 0x{:08x}", level);
}
osLib_returnFromFunction(hCPU, r);
@@ -1533,7 +1578,7 @@ void nsysnetExport_getaddrinfo(PPCInterpreter_t* hCPU)
void nsysnetExport_recvfrom(PPCInterpreter_t* hCPU)
{
- cemuLog_log(LogType::Socket, "recvfrom({},0x{:08x},{},0x{:x})", hCPU->gpr[3], hCPU->gpr[4], hCPU->gpr[5], hCPU->gpr[6]);
+ cemuLog_log(LogType::Socket, "recvfrom({},0x{:08x},{},0x{:x},0x{:x},0x{:x})", hCPU->gpr[3], hCPU->gpr[4], hCPU->gpr[5], hCPU->gpr[6], hCPU->gpr[7], hCPU->gpr[8]);
ppcDefineParamS32(s, 0);
ppcDefineParamStr(msg, 1);
ppcDefineParamS32(len, 2);
@@ -1562,8 +1607,8 @@ void nsysnetExport_recvfrom(PPCInterpreter_t* hCPU)
if (vs->isNonBlocking)
requestIsNonBlocking = vs->isNonBlocking;
- socklen_t fromLenHost = *fromLen;
sockaddr fromAddrHost;
+ socklen_t fromLenHost = sizeof(fromAddrHost);
sint32 wsaError = 0;
while( true )
@@ -1605,9 +1650,13 @@ void nsysnetExport_recvfrom(PPCInterpreter_t* hCPU)
if (r < 0)
cemu_assert_debug(false);
cemuLog_logDebug(LogType::Force, "recvfrom returned {} bytes", r);
- *fromLen = fromLenHost;
- fromAddr->sa_family = _swapEndianU16(fromAddrHost.sa_family);
- memcpy(fromAddr->sa_data, fromAddrHost.sa_data, 14);
+
+ // fromAddr and fromLen can be NULL
+ if (fromAddr && fromLen) {
+ *fromLen = fromLenHost;
+ fromAddr->sa_family = _swapEndianU16(fromAddrHost.sa_family);
+ memcpy(fromAddr->sa_data, fromAddrHost.sa_data, 14);
+ }
_setSockError(0);
osLib_returnFromFunction(hCPU, r);
@@ -1657,9 +1706,12 @@ void nsysnetExport_recvfrom(PPCInterpreter_t* hCPU)
assert_dbg();
}
- *fromLen = fromLenHost;
- fromAddr->sa_family = _swapEndianU16(fromAddrHost.sa_family);
- memcpy(fromAddr->sa_data, fromAddrHost.sa_data, 14);
+ // fromAddr and fromLen can be NULL
+ if (fromAddr && fromLen) {
+ *fromLen = fromLenHost;
+ fromAddr->sa_family = _swapEndianU16(fromAddrHost.sa_family);
+ memcpy(fromAddr->sa_data, fromAddrHost.sa_data, 14);
+ }
_translateError(r <= 0 ? -1 : 0, wsaError);
From b2be3c13df58cd6108d090b892d2801a615fd60d Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Fri, 26 Apr 2024 04:19:15 +0200
Subject: [PATCH 003/216] Add example network_services.xml
---
dist/network_services.xml | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 dist/network_services.xml
diff --git a/dist/network_services.xml b/dist/network_services.xml
new file mode 100644
index 00000000..0c0f2e3e
--- /dev/null
+++ b/dist/network_services.xml
@@ -0,0 +1,17 @@
+
+
+ CustomExample
+ 0
+
+ https://account.nintendo.net
+ https://ecs.wup.shop.nintendo.net/ecs/services/ECommerceSOAP
+ https://nus.wup.shop.nintendo.net/nus/services/NetUpdateSOAP
+ https://ias.wup.shop.nintendo.net/ias/services/IdentityAuthenticationSOAP
+ https://ccs.wup.shop.nintendo.net/ccs/download
+ http://ccs.cdn.wup.shop.nintendo.net/ccs/download
+ https://idbe-wup.cdn.nintendo.net/icondata
+ https://npts.app.nintendo.net/p01/tasksheet
+ https://tagaya.wup.shop.nintendo.net/tagaya/versionlist
+ https://discovery.olv.nintendo.net/v1/endpoint
+
+
\ No newline at end of file
From c038e758aeac76ed55f8f92bbc22f4815cc7689a Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Fri, 26 Apr 2024 04:18:17 +0200
Subject: [PATCH 004/216] IOSU: Clean up resource on service shutdown
Also set device-dependent thread name
---
src/Cafe/IOSU/nn/iosu_nn_service.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/Cafe/IOSU/nn/iosu_nn_service.cpp b/src/Cafe/IOSU/nn/iosu_nn_service.cpp
index 1fb5c77a..c888b4fb 100644
--- a/src/Cafe/IOSU/nn/iosu_nn_service.cpp
+++ b/src/Cafe/IOSU/nn/iosu_nn_service.cpp
@@ -155,7 +155,9 @@ namespace iosu
void IPCService::ServiceThread()
{
- SetThreadName("IPCService");
+ std::string serviceName = m_devicePath.substr(m_devicePath.find_last_of('/') == std::string::npos ? 0 : m_devicePath.find_last_of('/') + 1);
+ serviceName.insert(0, "NNsvc_");
+ SetThreadName(serviceName.c_str());
m_msgQueueId = IOS_CreateMessageQueue(_m_msgBuffer.GetPtr(), _m_msgBuffer.GetCount());
cemu_assert(!IOS_ResultIsError((IOS_ERROR)m_msgQueueId));
IOS_ERROR r = IOS_RegisterResourceManager(m_devicePath.c_str(), m_msgQueueId);
@@ -208,6 +210,7 @@ namespace iosu
IOS_ResourceReply(cmd, IOS_ERROR_INVALID);
}
}
+ IOS_DestroyMessageQueue(m_msgQueueId);
m_threadInitialized = false;
}
};
From 1c73dc9e1b824f4618e60704b2c1e6682b749ee0 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Tue, 30 Apr 2024 23:09:00 +0200
Subject: [PATCH 005/216] Implement proc_ui.rpl + stub SYSSwitchToEManual() to
avoid softlocks
- Full reimplementation of proc_ui.rpl with all 19 exports
- Foreground/Background messages now go to the coreinit system message queue as they should (instead of using a hack where proc_ui receives them directly)
- Add missing coreinit API needed by proc_ui: OSGetPFID(), OSGetUPID(), OSGetTitleID(), __OSCreateThreadType()
- Use big-endian types in OSMessage
- Flesh out the stubs for OSDriver_Register and OSDriver_Unregister a bit more since we need to call it from proc_ui. Similiar small tweaks to other coreinit API
- Stub sysapp SYSSwitchToEManual() and _SYSSwitchToEManual() in such a way that they will trigger the expected background/foreground transition, avoiding softlocks in games that call these functions
---
.gitignore | 1 +
src/Cafe/OS/common/OSCommon.cpp | 2 +-
src/Cafe/OS/libs/coreinit/coreinit.cpp | 22 -
src/Cafe/OS/libs/coreinit/coreinit_DynLoad.h | 6 +
src/Cafe/OS/libs/coreinit/coreinit_FS.cpp | 2 +-
src/Cafe/OS/libs/coreinit/coreinit_Memory.cpp | 2 +-
src/Cafe/OS/libs/coreinit/coreinit_Memory.h | 5 +
.../libs/coreinit/coreinit_MessageQueue.cpp | 7 +
.../OS/libs/coreinit/coreinit_MessageQueue.h | 19 +-
src/Cafe/OS/libs/coreinit/coreinit_Misc.cpp | 96 ++
src/Cafe/OS/libs/coreinit/coreinit_Misc.h | 20 +
src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp | 19 +-
src/Cafe/OS/libs/coreinit/coreinit_Thread.h | 8 +-
src/Cafe/OS/libs/coreinit/coreinit_Time.cpp | 7 +-
src/Cafe/OS/libs/coreinit/coreinit_Time.h | 3 +-
src/Cafe/OS/libs/gx2/GX2_Misc.h | 2 +
src/Cafe/OS/libs/nn_olv/nn_olv.cpp | 3 +-
src/Cafe/OS/libs/proc_ui/proc_ui.cpp | 944 +++++++++++++++++-
src/Cafe/OS/libs/proc_ui/proc_ui.h | 45 +-
src/Cafe/OS/libs/sysapp/sysapp.cpp | 23 +
src/Common/CafeString.h | 5 +
21 files changed, 1146 insertions(+), 95 deletions(-)
diff --git a/.gitignore b/.gitignore
index c10b38da..67a268aa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@ bin/sdcard/*
bin/screenshots/*
bin/dump/*
bin/cafeLibs/*
+bin/portable/*
bin/keys.txt
!bin/shaderCache/info.txt
diff --git a/src/Cafe/OS/common/OSCommon.cpp b/src/Cafe/OS/common/OSCommon.cpp
index a4410028..5297f201 100644
--- a/src/Cafe/OS/common/OSCommon.cpp
+++ b/src/Cafe/OS/common/OSCommon.cpp
@@ -221,5 +221,5 @@ void osLib_load()
nsyskbd::nsyskbd_load();
swkbd::load();
camera::load();
- procui_load();
+ proc_ui::load();
}
diff --git a/src/Cafe/OS/libs/coreinit/coreinit.cpp b/src/Cafe/OS/libs/coreinit/coreinit.cpp
index 660f874f..e18d0e8d 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit.cpp
@@ -179,27 +179,6 @@ void coreinitExport_OSGetSharedData(PPCInterpreter_t* hCPU)
osLib_returnFromFunction(hCPU, 1);
}
-typedef struct
-{
- MPTR getDriverName;
- MPTR ukn04;
- MPTR onAcquiredForeground;
- MPTR onReleaseForeground;
- MPTR ukn10;
-}OSDriverCallbacks_t;
-
-void coreinitExport_OSDriver_Register(PPCInterpreter_t* hCPU)
-{
-#ifdef CEMU_DEBUG_ASSERT
- cemuLog_log(LogType::Force, "OSDriver_Register(0x{:08x},0x{:08x},0x{:08x},0x{:08x},0x{:08x},0x{:08x})", hCPU->gpr[3], hCPU->gpr[4], hCPU->gpr[5], hCPU->gpr[6], hCPU->gpr[7], hCPU->gpr[8]);
-#endif
- OSDriverCallbacks_t* driverCallbacks = (OSDriverCallbacks_t*)memory_getPointerFromVirtualOffset(hCPU->gpr[5]);
-
- // todo
-
- osLib_returnFromFunction(hCPU, 0);
-}
-
namespace coreinit
{
sint32 OSGetCoreId()
@@ -379,7 +358,6 @@ void coreinit_load()
coreinit::miscInit();
osLib_addFunction("coreinit", "OSGetSharedData", coreinitExport_OSGetSharedData);
osLib_addFunction("coreinit", "UCReadSysConfig", coreinitExport_UCReadSysConfig);
- osLib_addFunction("coreinit", "OSDriver_Register", coreinitExport_OSDriver_Register);
// async callbacks
InitializeAsyncCallback();
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_DynLoad.h b/src/Cafe/OS/libs/coreinit/coreinit_DynLoad.h
index 0be8226c..2a3172c7 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_DynLoad.h
+++ b/src/Cafe/OS/libs/coreinit/coreinit_DynLoad.h
@@ -2,6 +2,12 @@
namespace coreinit
{
+ enum class RplEntryReason
+ {
+ Loaded = 1,
+ Unloaded = 2,
+ };
+
uint32 OSDynLoad_SetAllocator(MPTR allocFunc, MPTR freeFunc);
void OSDynLoad_SetTLSAllocator(MPTR allocFunc, MPTR freeFunc);
uint32 OSDynLoad_GetAllocator(betype* funcAlloc, betype* funcFree);
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp
index a007f5ee..0ca8fb8e 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp
@@ -837,7 +837,7 @@ namespace coreinit
FSAsyncResult* FSGetAsyncResult(OSMessage* msg)
{
- return (FSAsyncResult*)memory_getPointerFromVirtualOffset(_swapEndianU32(msg->message));
+ return (FSAsyncResult*)memory_getPointerFromVirtualOffset(msg->message);
}
sint32 __FSProcessAsyncResult(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, sint32 fsStatus, uint32 errHandling)
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Memory.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Memory.cpp
index 4b147473..cff4ee2b 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Memory.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Memory.cpp
@@ -126,7 +126,7 @@ namespace coreinit
return physicalAddr;
}
- void OSMemoryBarrier(PPCInterpreter_t* hCPU)
+ void OSMemoryBarrier()
{
// no-op
}
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Memory.h b/src/Cafe/OS/libs/coreinit/coreinit_Memory.h
index cfb3ed06..0a212f61 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Memory.h
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Memory.h
@@ -5,4 +5,9 @@ namespace coreinit
void InitializeMemory();
void OSGetMemBound(sint32 memType, MPTR* offsetOutput, uint32* sizeOutput);
+
+ void* OSBlockMove(MEMPTR dst, MEMPTR src, uint32 size, bool flushDC);
+ void* OSBlockSet(MEMPTR dst, uint32 value, uint32 size);
+
+ void OSMemoryBarrier();
}
\ No newline at end of file
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp b/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp
index 6e6a7bc1..cbcfa4d1 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp
@@ -3,6 +3,8 @@
namespace coreinit
{
+ void UpdateSystemMessageQueue();
+ void HandleReceivedSystemMessage(OSMessage* msg);
SysAllocator g_systemMessageQueue;
SysAllocator _systemMessageQueueArray;
@@ -27,6 +29,9 @@ namespace coreinit
bool OSReceiveMessage(OSMessageQueue* msgQueue, OSMessage* msg, uint32 flags)
{
+ bool isSystemMessageQueue = (msgQueue == g_systemMessageQueue);
+ if(isSystemMessageQueue)
+ UpdateSystemMessageQueue();
__OSLockScheduler(msgQueue);
while (msgQueue->usedCount == (uint32be)0)
{
@@ -50,6 +55,8 @@ namespace coreinit
if (!msgQueue->threadQueueSend.isEmpty())
msgQueue->threadQueueSend.wakeupSingleThreadWaitQueue(true);
__OSUnlockScheduler(msgQueue);
+ if(isSystemMessageQueue)
+ HandleReceivedSystemMessage(msg);
return true;
}
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.h b/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.h
index 6741ab84..35fdc3e7 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.h
+++ b/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.h
@@ -3,12 +3,21 @@
namespace coreinit
{
+ enum class SysMessageId : uint32
+ {
+ MsgAcquireForeground = 0xFACEF000,
+ MsgReleaseForeground = 0xFACEBACC,
+ MsgExit = 0xD1E0D1E0,
+ HomeButtonDenied = 0xCCC0FFEE,
+ NetIoStartOrStop = 0xAAC0FFEE,
+ };
+
struct OSMessage
{
- MPTR message;
- uint32 data0;
- uint32 data1;
- uint32 data2;
+ uint32be message;
+ uint32be data0;
+ uint32be data1;
+ uint32be data2;
};
struct OSMessageQueue
@@ -36,5 +45,7 @@ namespace coreinit
bool OSPeekMessage(OSMessageQueue* msgQueue, OSMessage* msg);
sint32 OSSendMessage(OSMessageQueue* msgQueue, OSMessage* msg, uint32 flags);
+ OSMessageQueue* OSGetSystemMessageQueue();
+
void InitializeMessageQueue();
};
\ No newline at end of file
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Misc.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Misc.cpp
index 2d7468cf..e2b50661 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Misc.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Misc.cpp
@@ -1,5 +1,6 @@
#include "Cafe/OS/common/OSCommon.h"
#include "Cafe/OS/libs/coreinit/coreinit_Misc.h"
+#include "Cafe/OS/libs/coreinit/coreinit_MessageQueue.h"
#include "Cafe/CafeSystem.h"
#include "Cafe/Filesystem/fsc.h"
#include
@@ -371,6 +372,23 @@ namespace coreinit
return true;
}
+ uint32 OSGetPFID()
+ {
+ return 15; // hardcoded as game
+ }
+
+ uint32 OSGetUPID()
+ {
+ return OSGetPFID();
+ }
+
+ uint64 s_currentTitleId;
+
+ uint64 OSGetTitleID()
+ {
+ return s_currentTitleId;
+ }
+
uint32 s_sdkVersion;
uint32 __OSGetProcessSDKVersion()
@@ -470,9 +488,78 @@ namespace coreinit
return 0;
}
+ void OSReleaseForeground()
+ {
+ cemuLog_logDebug(LogType::Force, "OSReleaseForeground not implemented");
+ }
+
+ bool s_transitionToBackground = false;
+ bool s_transitionToForeground = false;
+
+ void StartBackgroundForegroundTransition()
+ {
+ s_transitionToBackground = true;
+ s_transitionToForeground = true;
+ }
+
+ // called at the beginning of OSReceiveMessage if the queue is the system message queue
+ void UpdateSystemMessageQueue()
+ {
+ if(!OSIsInterruptEnabled())
+ return;
+ cemu_assert_debug(!__OSHasSchedulerLock());
+ // normally syscall 0x2E is used to get the next message
+ // for now we just have some preliminary logic here to allow a fake transition to background & foreground
+ if(s_transitionToBackground)
+ {
+ // add transition to background message
+ OSMessage msg{};
+ msg.data0 = stdx::to_underlying(SysMessageId::MsgReleaseForeground);
+ msg.data1 = 0; // 1 -> System is shutting down 0 -> Begin transitioning to background
+ OSMessageQueue* systemMessageQueue = coreinit::OSGetSystemMessageQueue();
+ if(OSSendMessage(systemMessageQueue, &msg, 0))
+ s_transitionToBackground = false;
+ return;
+ }
+ if(s_transitionToForeground)
+ {
+ // add transition to foreground message
+ OSMessage msg{};
+ msg.data0 = stdx::to_underlying(SysMessageId::MsgAcquireForeground);
+ msg.data1 = 1; // ?
+ msg.data2 = 1; // ?
+ OSMessageQueue* systemMessageQueue = coreinit::OSGetSystemMessageQueue();
+ if(OSSendMessage(systemMessageQueue, &msg, 0))
+ s_transitionToForeground = false;
+ return;
+ }
+ }
+
+ // called when OSReceiveMessage returns a message from the system message queue
+ void HandleReceivedSystemMessage(OSMessage* msg)
+ {
+ cemu_assert_debug(!__OSHasSchedulerLock());
+ cemuLog_log(LogType::Force, "Receiving message: {:08x}", (uint32)msg->data0);
+ }
+
+ uint32 OSDriver_Register(uint32 moduleHandle, sint32 priority, OSDriverInterface* driverCallbacks, sint32 driverId, uint32be* outUkn1, uint32be* outUkn2, uint32be* outUkn3)
+ {
+ cemuLog_logDebug(LogType::Force, "OSDriver_Register stubbed");
+ return 0;
+ }
+
+ uint32 OSDriver_Deregister(uint32 moduleHandle, sint32 driverId)
+ {
+ cemuLog_logDebug(LogType::Force, "OSDriver_Deregister stubbed");
+ return 0;
+ }
+
void miscInit()
{
+ s_currentTitleId = CafeSystem::GetForegroundTitleId();
s_sdkVersion = CafeSystem::GetForegroundTitleSDKVersion();
+ s_transitionToBackground = false;
+ s_transitionToForeground = false;
cafeExportRegister("coreinit", __os_snprintf, LogType::Placeholder);
cafeExportRegister("coreinit", OSReport, LogType::Placeholder);
@@ -480,6 +567,10 @@ namespace coreinit
cafeExportRegister("coreinit", COSWarn, LogType::Placeholder);
cafeExportRegister("coreinit", OSLogPrintf, LogType::Placeholder);
cafeExportRegister("coreinit", OSConsoleWrite, LogType::Placeholder);
+
+ cafeExportRegister("coreinit", OSGetPFID, LogType::Placeholder);
+ cafeExportRegister("coreinit", OSGetUPID, LogType::Placeholder);
+ cafeExportRegister("coreinit", OSGetTitleID, LogType::Placeholder);
cafeExportRegister("coreinit", __OSGetProcessSDKVersion, LogType::Placeholder);
g_homeButtonMenuEnabled = true; // enabled by default
@@ -489,6 +580,11 @@ namespace coreinit
cafeExportRegister("coreinit", OSLaunchTitleByPathl, LogType::Placeholder);
cafeExportRegister("coreinit", OSRestartGame, LogType::Placeholder);
+
+ cafeExportRegister("coreinit", OSReleaseForeground, LogType::Placeholder);
+
+ cafeExportRegister("coreinit", OSDriver_Register, LogType::Placeholder);
+ cafeExportRegister("coreinit", OSDriver_Deregister, LogType::Placeholder);
}
};
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Misc.h b/src/Cafe/OS/libs/coreinit/coreinit_Misc.h
index 4a74d490..7abba92f 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Misc.h
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Misc.h
@@ -2,9 +2,29 @@
namespace coreinit
{
+ uint32 OSGetUPID();
+ uint32 OSGetPFID();
+ uint64 OSGetTitleID();
uint32 __OSGetProcessSDKVersion();
uint32 OSLaunchTitleByPathl(const char* path, uint32 pathLength, uint32 argc);
uint32 OSRestartGame(uint32 argc, MEMPTR* argv);
+ void OSReleaseForeground();
+
+ void StartBackgroundForegroundTransition();
+
+ struct OSDriverInterface
+ {
+ MEMPTR getDriverName;
+ MEMPTR init;
+ MEMPTR onAcquireForeground;
+ MEMPTR onReleaseForeground;
+ MEMPTR done;
+ };
+ static_assert(sizeof(OSDriverInterface) == 0x14);
+
+ uint32 OSDriver_Register(uint32 moduleHandle, sint32 priority, OSDriverInterface* driverCallbacks, sint32 driverId, uint32be* outUkn1, uint32be* outUkn2, uint32be* outUkn3);
+ uint32 OSDriver_Deregister(uint32 moduleHandle, sint32 driverId);
+
void miscInit();
};
\ No newline at end of file
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp
index 809d7be4..654e57a8 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp
@@ -294,9 +294,9 @@ namespace coreinit
__OSUnlockScheduler();
}
- bool OSCreateThreadType(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop2, sint32 stackSize, sint32 priority, uint32 attr, OSThread_t::THREAD_TYPE threadType)
+ bool OSCreateThreadType(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop, sint32 stackSize, sint32 priority, uint32 attr, OSThread_t::THREAD_TYPE threadType)
{
- OSCreateThreadInternal(thread, entryPoint, memory_getVirtualOffsetFromPointer(stackTop2) - stackSize, stackSize, attr, threadType);
+ OSCreateThreadInternal(thread, entryPoint, memory_getVirtualOffsetFromPointer(stackTop) - stackSize, stackSize, attr, threadType);
thread->context.gpr[3] = _swapEndianU32(numParam); // num arguments
thread->context.gpr[4] = _swapEndianU32(memory_getVirtualOffsetFromPointer(ptrParam)); // arguments pointer
__OSSetThreadBasePriority(thread, priority);
@@ -317,9 +317,15 @@ namespace coreinit
return true;
}
- bool OSCreateThread(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop2, sint32 stackSize, sint32 priority, uint32 attr)
+ bool OSCreateThread(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop, sint32 stackSize, sint32 priority, uint32 attr)
{
- return OSCreateThreadType(thread, entryPoint, numParam, ptrParam, stackTop2, stackSize, priority, attr, OSThread_t::THREAD_TYPE::TYPE_APP);
+ return OSCreateThreadType(thread, entryPoint, numParam, ptrParam, stackTop, stackSize, priority, attr, OSThread_t::THREAD_TYPE::TYPE_APP);
+ }
+
+ // alias to OSCreateThreadType, similar to OSCreateThread, but with an additional parameter for the thread type
+ bool __OSCreateThreadType(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop, sint32 stackSize, sint32 priority, uint32 attr, OSThread_t::THREAD_TYPE threadType)
+ {
+ return OSCreateThreadType(thread, entryPoint, numParam, ptrParam, stackTop, stackSize, priority, attr, threadType);
}
bool OSRunThread(OSThread_t* thread, MPTR funcAddress, sint32 numParam, void* ptrParam)
@@ -445,12 +451,12 @@ namespace coreinit
return currentThread->specificArray[index].GetPtr();
}
- void OSSetThreadName(OSThread_t* thread, char* name)
+ void OSSetThreadName(OSThread_t* thread, const char* name)
{
thread->threadName = name;
}
- char* OSGetThreadName(OSThread_t* thread)
+ const char* OSGetThreadName(OSThread_t* thread)
{
return thread->threadName.GetPtr();
}
@@ -1371,6 +1377,7 @@ namespace coreinit
{
cafeExportRegister("coreinit", OSCreateThreadType, LogType::CoreinitThread);
cafeExportRegister("coreinit", OSCreateThread, LogType::CoreinitThread);
+ cafeExportRegister("coreinit", __OSCreateThreadType, LogType::CoreinitThread);
cafeExportRegister("coreinit", OSExitThread, LogType::CoreinitThread);
cafeExportRegister("coreinit", OSGetCurrentThread, LogType::CoreinitThread);
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Thread.h b/src/Cafe/OS/libs/coreinit/coreinit_Thread.h
index e619d5b6..b401d96d 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Thread.h
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Thread.h
@@ -449,7 +449,7 @@ struct OSThread_t
/* +0x578 */ sint32 alarmRelatedUkn;
/* +0x57C */ std::array, 16> specificArray;
/* +0x5BC */ betype type;
- /* +0x5C0 */ MEMPTR threadName;
+ /* +0x5C0 */ MEMPTR threadName;
/* +0x5C4 */ MPTR waitAlarm; // used only by OSWaitEventWithTimeout/OSSignalEvent ?
/* +0x5C8 */ uint32 userStackPointer;
@@ -505,6 +505,7 @@ namespace coreinit
void* OSGetDefaultThreadStack(sint32 coreIndex, uint32& size);
bool OSCreateThreadType(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop2, sint32 stackSize, sint32 priority, uint32 attr, OSThread_t::THREAD_TYPE threadType);
+ bool __OSCreateThreadType(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop, sint32 stackSize, sint32 priority, uint32 attr, OSThread_t::THREAD_TYPE threadType);
void OSCreateThreadInternal(OSThread_t* thread, uint32 entryPoint, MPTR stackLowerBaseAddr, uint32 stackSize, uint8 affinityMask, OSThread_t::THREAD_TYPE threadType);
bool OSRunThread(OSThread_t* thread, MPTR funcAddress, sint32 numParam, void* ptrParam);
void OSExitThread(sint32 exitValue);
@@ -519,8 +520,8 @@ namespace coreinit
bool OSSetThreadPriority(OSThread_t* thread, sint32 newPriority);
uint32 OSGetThreadAffinity(OSThread_t* thread);
- void OSSetThreadName(OSThread_t* thread, char* name);
- char* OSGetThreadName(OSThread_t* thread);
+ void OSSetThreadName(OSThread_t* thread, const char* name);
+ const char* OSGetThreadName(OSThread_t* thread);
sint32 __OSResumeThreadInternal(OSThread_t* thread, sint32 resumeCount);
sint32 OSResumeThread(OSThread_t* thread);
@@ -530,6 +531,7 @@ namespace coreinit
void OSSuspendThread(OSThread_t* thread);
void OSSleepThread(OSThreadQueue* threadQueue);
void OSWakeupThread(OSThreadQueue* threadQueue);
+ bool OSJoinThread(OSThread_t* thread, uint32be* exitValue);
void OSTestThreadCancelInternal();
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Time.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Time.cpp
index 5a75b406..d6fc27b2 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Time.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Time.cpp
@@ -22,10 +22,9 @@ namespace coreinit
osLib_returnFromFunction(hCPU, (uint32)osTime);
}
- void export_OSGetTime(PPCInterpreter_t* hCPU)
+ uint64 OSGetTime()
{
- uint64 osTime = coreinit_getOSTime();
- osLib_returnFromFunction64(hCPU, osTime);
+ return coreinit_getOSTime();
}
void export_OSGetSystemTime(PPCInterpreter_t* hCPU)
@@ -360,7 +359,7 @@ namespace coreinit
void InitializeTimeAndCalendar()
{
- osLib_addFunction("coreinit", "OSGetTime", export_OSGetTime);
+ cafeExportRegister("coreinit", OSGetTime, LogType::Placeholder);
osLib_addFunction("coreinit", "OSGetSystemTime", export_OSGetSystemTime);
osLib_addFunction("coreinit", "OSGetTick", export_OSGetTick);
osLib_addFunction("coreinit", "OSGetSystemTick", export_OSGetSystemTick);
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Time.h b/src/Cafe/OS/libs/coreinit/coreinit_Time.h
index f5dcf22e..018e8eb7 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Time.h
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Time.h
@@ -45,7 +45,8 @@ namespace coreinit
};
void OSTicksToCalendarTime(uint64 ticks, OSCalendarTime_t* calenderStruct);
-
+ uint64 OSGetTime();
+
uint64 coreinit_getOSTime();
uint64 coreinit_getTimerTick();
diff --git a/src/Cafe/OS/libs/gx2/GX2_Misc.h b/src/Cafe/OS/libs/gx2/GX2_Misc.h
index e6ac8010..38a728c1 100644
--- a/src/Cafe/OS/libs/gx2/GX2_Misc.h
+++ b/src/Cafe/OS/libs/gx2/GX2_Misc.h
@@ -19,5 +19,7 @@ namespace GX2
void GX2SetTVBuffer(void* imageBuffePtr, uint32 imageBufferSize, E_TVRES tvResolutionMode, uint32 surfaceFormat, E_TVBUFFERMODE bufferMode);
void GX2SetTVGamma(float gamma);
+ void GX2Invalidate(uint32 invalidationFlags, MPTR invalidationAddr, uint32 invalidationSize);
+
void GX2MiscInit();
};
\ No newline at end of file
diff --git a/src/Cafe/OS/libs/nn_olv/nn_olv.cpp b/src/Cafe/OS/libs/nn_olv/nn_olv.cpp
index 99c113c4..1916a18d 100644
--- a/src/Cafe/OS/libs/nn_olv/nn_olv.cpp
+++ b/src/Cafe/OS/libs/nn_olv/nn_olv.cpp
@@ -9,6 +9,7 @@
#include "Cafe/OS/libs/proc_ui/proc_ui.h"
#include "Cafe/OS/libs/coreinit/coreinit_Time.h"
+#include "Cafe/OS/libs/coreinit/coreinit_Misc.h"
namespace nn
{
@@ -37,7 +38,7 @@ namespace nn
void StubPostAppReleaseBackground(PPCInterpreter_t* hCPU)
{
coreinit::OSSleepTicks(ESPRESSO_TIMER_CLOCK * 2); // Sleep 2s
- ProcUI_SendForegroundMessage();
+ coreinit::StartBackgroundForegroundTransition();
}
sint32 StubPostApp(void* pAnyPostParam)
diff --git a/src/Cafe/OS/libs/proc_ui/proc_ui.cpp b/src/Cafe/OS/libs/proc_ui/proc_ui.cpp
index 7de8691a..91d15af4 100644
--- a/src/Cafe/OS/libs/proc_ui/proc_ui.cpp
+++ b/src/Cafe/OS/libs/proc_ui/proc_ui.cpp
@@ -1,57 +1,905 @@
#include "Cafe/OS/common/OSCommon.h"
+#include "Cafe/OS/libs/coreinit/coreinit_Alarm.h"
+#include "Cafe/OS/libs/coreinit/coreinit_Thread.h"
+#include "Cafe/OS/libs/coreinit/coreinit_MessageQueue.h"
+#include "Cafe/OS/libs/coreinit/coreinit_Misc.h"
+#include "Cafe/OS/libs/coreinit/coreinit_Memory.h"
+#include "Cafe/OS/libs/coreinit/coreinit_MEM_ExpHeap.h"
+#include "Cafe/OS/libs/coreinit/coreinit_Time.h"
+#include "Cafe/OS/libs/coreinit/coreinit_FG.h"
+#include "Cafe/OS/libs/coreinit/coreinit_DynLoad.h"
+#include "Cafe/OS/libs/gx2/GX2_Misc.h"
+#include "Cafe/OS/RPL/rpl.h"
+#include "Common/CafeString.h"
#include "proc_ui.h"
-#define PROCUI_STATUS_FOREGROUND 0
-#define PROCUI_STATUS_BACKGROUND 1
-#define PROCUI_STATUS_RELEASING 2
-#define PROCUI_STATUS_EXIT 3
+// proc_ui is a utility wrapper to help apps with the transition between foreground and background
+// some games (like Xenoblades Chronicles X) bypass proc_ui.rpl and listen to OSGetSystemMessageQueue() directly
-uint32 ProcUIProcessMessages()
+using namespace coreinit;
+
+namespace proc_ui
{
- return PROCUI_STATUS_FOREGROUND;
-}
+ enum class ProcUICoreThreadCommand
+ {
+ AcquireForeground = 0x0,
+ ReleaseForeground = 0x1,
+ Exit = 0x2,
+ NetIoStart = 0x3,
+ NetIoStop = 0x4,
+ HomeButtonDenied = 0x5,
+ Initial = 0x6
+ };
+
+ struct ProcUIInternalCallbackEntry
+ {
+ coreinit::OSAlarm_t alarm;
+ uint64be tickDelay;
+ MEMPTR funcPtr;
+ MEMPTR userParam;
+ sint32be priority;
+ MEMPTR next;
+ };
+ static_assert(sizeof(ProcUIInternalCallbackEntry) == 0x70);
+
+ struct ProcUICallbackList
+ {
+ MEMPTR first;
+ };
+ static_assert(sizeof(ProcUICallbackList) == 0x4);
+
+ std::atomic_bool s_isInitialized;
+ bool s_isInForeground;
+ bool s_isInShutdown;
+ bool s_isForegroundProcess;
+ bool s_previouslyWasBlocking;
+ ProcUIStatus s_currentProcUIStatus;
+ MEMPTR s_saveCallback; // no param and no return value, set by ProcUIInit()
+ MEMPTR s_saveCallbackEx; // with custom param and return value, set by ProcUIInitEx()
+ MEMPTR s_saveCallbackExUserParam;
+ MEMPTR s_systemMessageQueuePtr;
+ SysAllocator s_eventStateMessageReceived;
+ SysAllocator s_eventWaitingBeforeReleaseForeground;
+ SysAllocator s_eventBackgroundThreadGotMessage;
+ // procUI core threads
+ uint32 s_coreThreadStackSize;
+ bool s_coreThreadsCreated;
+ std::atomic s_commandForCoreThread;
+ SysAllocator s_coreThreadArray[Espresso::CORE_COUNT];
+ MEMPTR s_coreThreadStackPerCore[Espresso::CORE_COUNT];
+ SysAllocator> s_coreThread0NameBuffer;
+ SysAllocator> s_coreThread1NameBuffer;
+ SysAllocator> s_coreThread2NameBuffer;
+ SysAllocator s_eventCoreThreadsNewCommandReady;
+ SysAllocator s_eventCoreThreadsCommandDone;
+ SysAllocator s_coreThreadRendezvousA;
+ SysAllocator s_coreThreadRendezvousB;
+ SysAllocator s_coreThreadRendezvousC;
+ // background thread
+ MEMPTR s_backgroundThreadStack;
+ SysAllocator s_backgroundThread;
+ // user defined heap
+ MEMPTR s_memoryPoolHeapPtr;
+ MEMPTR s_memAllocPtr;
+ MEMPTR s_memFreePtr;
+ // draw done release
+ bool s_drawDoneReleaseCalled;
+ // memory storage
+ MEMPTR s_bucketStorageBasePtr;
+ MEMPTR s_mem1StorageBasePtr;
+ // callbacks
+ ProcUICallbackList s_callbacksType0_AcquireForeground[Espresso::CORE_COUNT];
+ ProcUICallbackList s_callbacksType1_ReleaseForeground[Espresso::CORE_COUNT];
+ ProcUICallbackList s_callbacksType2_Exit[Espresso::CORE_COUNT];
+ ProcUICallbackList s_callbacksType3_NetIoStart[Espresso::CORE_COUNT];
+ ProcUICallbackList s_callbacksType4_NetIoStop[Espresso::CORE_COUNT];
+ ProcUICallbackList s_callbacksType5_HomeButtonDenied[Espresso::CORE_COUNT];
+ ProcUICallbackList* const s_CallbackTables[stdx::to_underlying(ProcUICallbackId::COUNT)] =
+ {s_callbacksType0_AcquireForeground, s_callbacksType1_ReleaseForeground, s_callbacksType2_Exit, s_callbacksType3_NetIoStart, s_callbacksType4_NetIoStop, s_callbacksType5_HomeButtonDenied};
+ ProcUICallbackList s_backgroundCallbackList;
+ // driver
+ bool s_driverIsActive;
+ uint32be s_driverArgUkn1;
+ uint32be s_driverArgUkn2;
+ bool s_driverInBackground;
+ SysAllocator s_ProcUIDriver;
+ SysAllocator> s_ProcUIDriverName;
-uint32 ProcUIInForeground(PPCInterpreter_t* hCPU)
-{
- return 1; // true means application is in foreground
-}
+ void* _AllocMem(uint32 size)
+ {
+ MEMPTR r{PPCCoreCallback(s_memAllocPtr, size)};
+ return r.GetPtr();
+ }
-struct ProcUICallback
-{
- MPTR callback;
- void* data;
- sint32 priority;
+ void _FreeMem(void* ptr)
+ {
+ PPCCoreCallback(s_memFreePtr.GetMPTR(), ptr);
+ }
+
+ void ClearCallbacksWithoutMemFree()
+ {
+ for (sint32 coreIndex = 0; coreIndex < Espresso::CORE_COUNT; coreIndex++)
+ {
+ for (sint32 i = 0; i < stdx::to_underlying(ProcUICallbackId::COUNT); i++)
+ s_CallbackTables[i][coreIndex].first = nullptr;
+ }
+ s_backgroundCallbackList.first = nullptr;
+ }
+
+ void ShutdownThreads()
+ {
+ if ( !s_coreThreadsCreated)
+ return;
+ s_commandForCoreThread = ProcUICoreThreadCommand::Initial;
+ coreinit::OSMemoryBarrier();
+ OSSignalEvent(&s_eventCoreThreadsNewCommandReady);
+ for (sint32 coreIndex = 0; coreIndex < Espresso::CORE_COUNT; coreIndex++)
+ {
+ coreinit::OSJoinThread(&s_coreThreadArray[coreIndex], nullptr);
+ for (sint32 i = 0; i < stdx::to_underlying(ProcUICallbackId::COUNT); i++)
+ {
+ s_CallbackTables[i][coreIndex].first = nullptr; // memory is not cleanly released?
+ }
+ }
+ OSResetEvent(&s_eventCoreThreadsNewCommandReady);
+ for (sint32 coreIndex = 0; coreIndex < Espresso::CORE_COUNT; coreIndex++)
+ {
+ _FreeMem(s_coreThreadStackPerCore[coreIndex]);
+ s_coreThreadStackPerCore[coreIndex] = nullptr;
+ }
+ _FreeMem(s_backgroundThreadStack);
+ s_backgroundThreadStack = nullptr;
+ s_backgroundCallbackList.first = nullptr; // memory is not cleanly released?
+ s_coreThreadsCreated = false;
+ }
+
+ void DoCallbackChain(ProcUIInternalCallbackEntry* entry)
+ {
+ while (entry)
+ {
+ uint32 r = PPCCoreCallback(entry->funcPtr, entry->userParam);
+ if ( r )
+ cemuLog_log(LogType::APIErrors, "ProcUI: Callback returned error {}\n", r);
+ entry = entry->next;
+ }
+ }
+
+ void AlarmDoBackgroundCallback(PPCInterpreter_t* hCPU)
+ {
+ coreinit::OSAlarm_t* arg = MEMPTR(hCPU->gpr[3]);
+ ProcUIInternalCallbackEntry* entry = (ProcUIInternalCallbackEntry*)arg;
+ uint32 r = PPCCoreCallback(entry->funcPtr, entry->userParam);
+ if ( r )
+ cemuLog_log(LogType::APIErrors, "ProcUI: Background callback returned error {}\n", r);
+ osLib_returnFromFunction(hCPU, 0); // return type is void
+ }
+
+ void StartBackgroundAlarms()
+ {
+ ProcUIInternalCallbackEntry* cb = s_backgroundCallbackList.first;
+ while(cb)
+ {
+ coreinit::OSCreateAlarm(&cb->alarm);
+ uint64 currentTime = coreinit::OSGetTime();
+ coreinit::OSSetPeriodicAlarm(&cb->alarm, currentTime, cb->tickDelay, RPLLoader_MakePPCCallable(AlarmDoBackgroundCallback));
+ cb = cb->next;
+ }
+ }
+
+ void CancelBackgroundAlarms()
+ {
+ ProcUIInternalCallbackEntry* entry = s_backgroundCallbackList.first;
+ while (entry)
+ {
+ OSCancelAlarm(&entry->alarm);
+ entry = entry->next;
+ }
+ }
+
+ void ProcUICoreThread(PPCInterpreter_t* hCPU)
+ {
+ uint32 coreIndex = hCPU->gpr[3];
+ cemu_assert_debug(coreIndex == OSGetCoreId());
+ while (true)
+ {
+ OSWaitEvent(&s_eventCoreThreadsNewCommandReady);
+ ProcUIInternalCallbackEntry* cbChain = nullptr;
+ cemuLog_logDebug(LogType::Force, "ProcUI: Core {} got command {}", coreIndex, (uint32)s_commandForCoreThread.load());
+ auto cmd = s_commandForCoreThread.load();
+ switch(cmd)
+ {
+ case ProcUICoreThreadCommand::Initial:
+ {
+ // signal to shut down thread
+ osLib_returnFromFunction(hCPU, 0);
+ return;
+ }
+ case ProcUICoreThreadCommand::AcquireForeground:
+ cbChain = s_callbacksType0_AcquireForeground[coreIndex].first;
+ break;
+ case ProcUICoreThreadCommand::ReleaseForeground:
+ cbChain = s_callbacksType1_ReleaseForeground[coreIndex].first;
+ break;
+ case ProcUICoreThreadCommand::Exit:
+ cbChain = s_callbacksType2_Exit[coreIndex].first;
+ break;
+ case ProcUICoreThreadCommand::NetIoStart:
+ cbChain = s_callbacksType3_NetIoStart[coreIndex].first;
+ break;
+ case ProcUICoreThreadCommand::NetIoStop:
+ cbChain = s_callbacksType4_NetIoStop[coreIndex].first;
+ break;
+ case ProcUICoreThreadCommand::HomeButtonDenied:
+ cbChain = s_callbacksType5_HomeButtonDenied[coreIndex].first;
+ break;
+ default:
+ cemu_assert_suspicious(); // invalid command
+ }
+ if(cmd == ProcUICoreThreadCommand::AcquireForeground)
+ {
+ if (coreIndex == 2)
+ CancelBackgroundAlarms();
+ cbChain = s_callbacksType0_AcquireForeground[coreIndex].first;
+ }
+ else if(cmd == ProcUICoreThreadCommand::ReleaseForeground)
+ {
+ if (coreIndex == 2)
+ StartBackgroundAlarms();
+ cbChain = s_callbacksType1_ReleaseForeground[coreIndex].first;
+ }
+ DoCallbackChain(cbChain);
+ OSWaitRendezvous(&s_coreThreadRendezvousA, 7);
+ if ( !coreIndex )
+ {
+ OSInitRendezvous(&s_coreThreadRendezvousC);
+ OSResetEvent(&s_eventCoreThreadsNewCommandReady);
+ }
+ OSWaitRendezvous(&s_coreThreadRendezvousB, 7);
+ if ( !coreIndex )
+ {
+ OSInitRendezvous(&s_coreThreadRendezvousA);
+ OSSignalEvent(&s_eventCoreThreadsCommandDone);
+ }
+ OSWaitRendezvous(&s_coreThreadRendezvousC, 7);
+ if ( !coreIndex )
+ OSInitRendezvous(&s_coreThreadRendezvousB);
+ if (cmd == ProcUICoreThreadCommand::ReleaseForeground)
+ {
+ OSWaitEvent(&s_eventWaitingBeforeReleaseForeground);
+ OSReleaseForeground();
+ }
+ }
+ osLib_returnFromFunction(hCPU, 0);
+ }
+
+ void RecreateProcUICoreThreads()
+ {
+ ShutdownThreads();
+ for (sint32 coreIndex = 0; coreIndex < Espresso::CORE_COUNT; coreIndex++)
+ {
+ s_coreThreadStackPerCore[coreIndex] = _AllocMem(s_coreThreadStackSize);
+ }
+ s_backgroundThreadStack = _AllocMem(s_coreThreadStackSize);
+ for (sint32 coreIndex = 0; coreIndex < Espresso::CORE_COUNT; coreIndex++)
+ {
+ __OSCreateThreadType(&s_coreThreadArray[coreIndex], RPLLoader_MakePPCCallable(ProcUICoreThread), coreIndex, nullptr,
+ (uint8*)s_coreThreadStackPerCore[coreIndex].GetPtr() + s_coreThreadStackSize, s_coreThreadStackSize, 16,
+ (1<assign("{SYS ProcUI Core 0}");
+ s_coreThread1NameBuffer->assign("{SYS ProcUI Core 1}");
+ s_coreThread2NameBuffer->assign("{SYS ProcUI Core 2}");
+ OSSetThreadName(&s_coreThreadArray[0], s_coreThread0NameBuffer->c_str());
+ OSSetThreadName(&s_coreThreadArray[1], s_coreThread1NameBuffer->c_str());
+ OSSetThreadName(&s_coreThreadArray[2], s_coreThread2NameBuffer->c_str());
+ s_coreThreadsCreated = true;
+ }
+
+ void _SubmitCommandToCoreThreads(ProcUICoreThreadCommand cmd)
+ {
+ s_commandForCoreThread = cmd;
+ OSMemoryBarrier();
+ OSResetEvent(&s_eventCoreThreadsCommandDone);
+ OSSignalEvent(&s_eventCoreThreadsNewCommandReady);
+ OSWaitEvent(&s_eventCoreThreadsCommandDone);
+ }
+
+ void ProcUIInitInternal()
+ {
+ if( s_isInitialized.exchange(true) )
+ return;
+ if (!s_memoryPoolHeapPtr)
+ {
+ // user didn't specify a custom heap, use default heap instead
+ s_memAllocPtr = gCoreinitData->MEMAllocFromDefaultHeap.GetMPTR();
+ s_memFreePtr = gCoreinitData->MEMFreeToDefaultHeap.GetMPTR();
+ }
+ OSInitEvent(&s_eventStateMessageReceived, OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, OSEvent::EVENT_MODE::MODE_MANUAL);
+ OSInitEvent(&s_eventCoreThreadsNewCommandReady, OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, OSEvent::EVENT_MODE::MODE_MANUAL);
+ OSInitEvent(&s_eventWaitingBeforeReleaseForeground, OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, OSEvent::EVENT_MODE::MODE_MANUAL);
+ OSInitEvent(&s_eventCoreThreadsCommandDone, OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, OSEvent::EVENT_MODE::MODE_MANUAL);
+ OSInitRendezvous(&s_coreThreadRendezvousA);
+ OSInitRendezvous(&s_coreThreadRendezvousB);
+ OSInitRendezvous(&s_coreThreadRendezvousC);
+ OSInitEvent(&s_eventBackgroundThreadGotMessage, OSEvent::EVENT_STATE::STATE_NOT_SIGNALED, OSEvent::EVENT_MODE::MODE_MANUAL);
+ s_currentProcUIStatus = ProcUIStatus::Foreground;
+ s_drawDoneReleaseCalled = false;
+ s_isInForeground = true;
+ s_coreThreadStackSize = 0x2000;
+ s_systemMessageQueuePtr = coreinit::OSGetSystemMessageQueue();
+ uint32 upid = coreinit::OSGetUPID();
+ s_isForegroundProcess = upid == 2 || upid == 15; // either Wii U Menu or game title, both are RAMPID 7 (foreground process)
+ RecreateProcUICoreThreads();
+ ClearCallbacksWithoutMemFree();
+ }
+
+ void ProcUIInit(MEMPTR callbackReadyToRelease)
+ {
+ s_saveCallback = callbackReadyToRelease;
+ s_saveCallbackEx = nullptr;
+ s_saveCallbackExUserParam = nullptr;
+ ProcUIInitInternal();
+ }
+
+ void ProcUIInitEx(MEMPTR callbackReadyToReleaseEx, MEMPTR userParam)
+ {
+ s_saveCallback = nullptr;
+ s_saveCallbackEx = callbackReadyToReleaseEx;
+ s_saveCallbackExUserParam = userParam;
+ ProcUIInitInternal();
+ }
+
+ void ProcUIShutdown()
+ {
+ if (!s_isInitialized.exchange(false))
+ return;
+ if ( !s_isInForeground )
+ CancelBackgroundAlarms();
+ for (sint32 i = 0; i < Espresso::CORE_COUNT; i++)
+ OSSetThreadPriority(&s_coreThreadArray[i], 0);
+ _SubmitCommandToCoreThreads(ProcUICoreThreadCommand::Exit);
+ ProcUIClearCallbacks();
+ ShutdownThreads();
+ }
+
+ bool ProcUIIsRunning()
+ {
+ return s_isInitialized;
+ }
+
+ bool ProcUIInForeground()
+ {
+ return s_isInForeground;
+ }
+
+ bool ProcUIInShutdown()
+ {
+ return s_isInShutdown;
+ }
+
+ void AddCallbackInternal(void* funcPtr, void* userParam, uint64 tickDelay, sint32 priority, ProcUICallbackList& callbackList)
+ {
+ if ( __OSGetProcessSDKVersion() < 21102 )
+ {
+ // in earlier COS versions it was possible/allowed to register a callback before initializing ProcUI
+ s_memAllocPtr = gCoreinitData->MEMAllocFromDefaultHeap.GetMPTR();
+ s_memFreePtr = gCoreinitData->MEMFreeToDefaultHeap.GetMPTR();
+ }
+ else if ( !s_isInitialized )
+ {
+ cemuLog_log(LogType::Force, "ProcUI: Trying to register callback before init");
+ cemu_assert_suspicious();
+ }
+ ProcUIInternalCallbackEntry* entry = (ProcUIInternalCallbackEntry*)_AllocMem(sizeof(ProcUIInternalCallbackEntry));
+ entry->funcPtr = funcPtr;
+ entry->userParam = userParam;
+ entry->tickDelay = tickDelay;
+ entry->priority = priority;
+ ProcUIInternalCallbackEntry* cur = callbackList.first;
+ cur = callbackList.first;
+ if (!cur || cur->priority > priority)
+ {
+ // insert as the first element
+ entry->next = cur;
+ callbackList.first = entry;
+ }
+ else
+ {
+ // find the correct position to insert
+ while (cur->next && cur->next->priority < priority)
+ cur = cur->next;
+ entry->next = cur->next;
+ cur->next = entry;
+ }
+ }
+
+ void ProcUIRegisterCallbackCore(ProcUICallbackId callbackType, void* funcPtr, void* userParam, sint32 priority, uint32 coreIndex)
+ {
+ if(callbackType >= ProcUICallbackId::COUNT)
+ {
+ cemuLog_log(LogType::Force, "ProcUIRegisterCallback: Invalid callback type {}", stdx::to_underlying(callbackType));
+ return;
+ }
+ if(callbackType != ProcUICallbackId::AcquireForeground)
+ priority = -priority;
+ AddCallbackInternal(funcPtr, userParam, priority, 0, s_CallbackTables[stdx::to_underlying(callbackType)][coreIndex]);
+ }
+
+ void ProcUIRegisterCallback(ProcUICallbackId callbackType, void* funcPtr, void* userParam, sint32 priority)
+ {
+ ProcUIRegisterCallbackCore(callbackType, funcPtr, userParam, priority, OSGetCoreId());
+ }
+
+ void ProcUIRegisterBackgroundCallback(void* funcPtr, void* userParam, uint64 tickDelay)
+ {
+ AddCallbackInternal(funcPtr, userParam, 0, tickDelay, s_backgroundCallbackList);
+ }
+
+ void FreeCallbackChain(ProcUICallbackList& callbackList)
+ {
+ ProcUIInternalCallbackEntry* entry = callbackList.first;
+ while (entry)
+ {
+ ProcUIInternalCallbackEntry* next = entry->next;
+ _FreeMem(entry);
+ entry = next;
+ }
+ callbackList.first = nullptr;
+ }
+
+ void ProcUIClearCallbacks()
+ {
+ for (sint32 coreIndex = 0; coreIndex < Espresso::CORE_COUNT; coreIndex++)
+ {
+ for (sint32 i = 0; i < stdx::to_underlying(ProcUICallbackId::COUNT); i++)
+ {
+ FreeCallbackChain(s_CallbackTables[i][coreIndex]);
+ }
+ }
+ if (!s_isInForeground)
+ CancelBackgroundAlarms();
+ FreeCallbackChain(s_backgroundCallbackList);
+ }
+
+ void ProcUISetSaveCallback(void* funcPtr, void* userParam)
+ {
+ s_saveCallback = nullptr;
+ s_saveCallbackEx = funcPtr;
+ s_saveCallbackExUserParam = userParam;
+ }
+
+ void ProcUISetCallbackStackSize(uint32 newStackSize)
+ {
+ s_coreThreadStackSize = newStackSize;
+ if( s_isInitialized )
+ RecreateProcUICoreThreads();
+ }
+
+ uint32 ProcUICalcMemorySize(uint32 numCallbacks)
+ {
+ // each callback entry is 0x70 bytes with 0x14 bytes of allocator overhead (for ExpHeap). But for some reason proc_ui on 5.5.5 seems to reserve 0x8C0 bytes per callback?
+ uint32 stackReserveSize = (Espresso::CORE_COUNT + 1) * s_coreThreadStackSize; // 3 core threads + 1 message receive thread
+ uint32 callbackReserveSize = 0x8C0 * numCallbacks;
+ return stackReserveSize + callbackReserveSize + 100;
+ }
+
+ void _MemAllocFromMemoryPool(PPCInterpreter_t* hCPU)
+ {
+ uint32 size = hCPU->gpr[3];
+ MEMPTR r = MEMAllocFromExpHeapEx((MEMHeapHandle)s_memoryPoolHeapPtr.GetPtr(), size, 4);
+ osLib_returnFromFunction(hCPU, r.GetMPTR());
+ }
+
+ void _FreeToMemoryPoolExpHeap(PPCInterpreter_t* hCPU)
+ {
+ MEMPTR mem{hCPU->gpr[3]};
+ MEMFreeToExpHeap((MEMHeapHandle)s_memoryPoolHeapPtr.GetPtr(), mem.GetPtr());
+ osLib_returnFromFunction(hCPU, 0);
+ }
+
+ sint32 ProcUISetMemoryPool(void* memBase, uint32 size)
+ {
+ s_memAllocPtr = RPLLoader_MakePPCCallable(_MemAllocFromMemoryPool);
+ s_memFreePtr = RPLLoader_MakePPCCallable(_FreeToMemoryPoolExpHeap);
+ s_memoryPoolHeapPtr = MEMCreateExpHeapEx(memBase, size, MEM_HEAP_OPTION_THREADSAFE);
+ return s_memoryPoolHeapPtr ? 0 : -1;
+ }
+
+ void ProcUISetBucketStorage(void* memBase, uint32 size)
+ {
+ MEMPTR fgBase;
+ uint32be fgFreeSize;
+ OSGetForegroundBucketFreeArea((MPTR*)&fgBase, (MPTR*)&fgFreeSize);
+ if(fgFreeSize < size)
+ cemuLog_log(LogType::Force, "ProcUISetBucketStorage: Buffer size too small");
+ s_bucketStorageBasePtr = memBase;
+ }
+
+ void ProcUISetMEM1Storage(void* memBase, uint32 size)
+ {
+ MEMPTR memBound;
+ uint32be memBoundSize;
+ OSGetMemBound(1, (MPTR*)memBound.GetBEPtr(), (uint32*)&memBoundSize);
+ if(memBoundSize < size)
+ cemuLog_log(LogType::Force, "ProcUISetMEM1Storage: Buffer size too small");
+ s_mem1StorageBasePtr = memBase;
+ }
+
+ void ProcUIDrawDoneRelease()
+ {
+ s_drawDoneReleaseCalled = true;
+ }
+
+ OSMessage g_lastMsg;
+
+ void ProcUI_BackgroundThread_ReceiveSingleMessage(PPCInterpreter_t* hCPU)
+ {
+ // the background thread receives messages in a loop until the title is either exited or foreground is acquired
+ while ( true )
+ {
+ OSReceiveMessage(s_systemMessageQueuePtr, &g_lastMsg, OS_MESSAGE_BLOCK); // blocking receive
+ SysMessageId lastMsgId = static_cast((uint32)g_lastMsg.data0);
+ if(lastMsgId == SysMessageId::MsgExit || lastMsgId == SysMessageId::MsgAcquireForeground)
+ break;
+ else if (lastMsgId == SysMessageId::HomeButtonDenied)
+ {
+ cemu_assert_suspicious(); // Home button denied should not be sent to background app
+ }
+ else if ( lastMsgId == SysMessageId::NetIoStartOrStop )
+ {
+ if (g_lastMsg.data1 )
+ {
+ // NetIo start message
+ for (sint32 i = 0; i < Espresso::CORE_COUNT; i++)
+ DoCallbackChain(s_callbacksType3_NetIoStart[i].first);
+ }
+ else
+ {
+ // NetIo stop message
+ for (sint32 i = 0; i < Espresso::CORE_COUNT; i++)
+ DoCallbackChain(s_callbacksType4_NetIoStop[i].first);
+ }
+ }
+ else
+ {
+ cemuLog_log(LogType::Force, "ProcUI: BackgroundThread received invalid message 0x{:08x}", lastMsgId);
+ }
+ }
+ OSSignalEvent(&s_eventBackgroundThreadGotMessage);
+ osLib_returnFromFunction(hCPU, 0);
+ }
+
+ // handle received message
+ // if the message is Exit this function returns false, in all other cases it returns true
+ bool ProcessSysMessage(OSMessage* msg)
+ {
+ SysMessageId lastMsgId = static_cast((uint32)msg->data0);
+ if ( lastMsgId == SysMessageId::MsgAcquireForeground )
+ {
+ cemuLog_logDebug(LogType::Force, "ProcUI: Received Acquire Foreground message");
+ s_isInShutdown = false;
+ _SubmitCommandToCoreThreads(ProcUICoreThreadCommand::AcquireForeground);
+ s_currentProcUIStatus = ProcUIStatus::Foreground;
+ s_isInForeground = true;
+ OSMemoryBarrier();
+ OSSignalEvent(&s_eventStateMessageReceived);
+ return true;
+ }
+ else if (lastMsgId == SysMessageId::MsgExit)
+ {
+ cemuLog_logDebug(LogType::Force, "ProcUI: Received Exit message");
+ s_isInShutdown = true;
+ _SubmitCommandToCoreThreads(ProcUICoreThreadCommand::Exit);
+ for (sint32 i = 0; i < Espresso::CORE_COUNT; i++)
+ FreeCallbackChain(s_callbacksType2_Exit[i]);
+ s_currentProcUIStatus = ProcUIStatus::Exit;
+ OSMemoryBarrier();
+ OSSignalEvent(&s_eventStateMessageReceived);
+ return 0;
+ }
+ if (lastMsgId == SysMessageId::MsgReleaseForeground)
+ {
+ if (msg->data1 != 0)
+ {
+ cemuLog_logDebug(LogType::Force, "ProcUI: Received Release Foreground message as part of shutdown initiation");
+ s_isInShutdown = true;
+ }
+ else
+ {
+ cemuLog_logDebug(LogType::Force, "ProcUI: Received Release Foreground message");
+ }
+ s_currentProcUIStatus = ProcUIStatus::Releasing;
+ OSResetEvent(&s_eventStateMessageReceived);
+ // dont submit a command for the core threads yet, we need to wait for ProcUIDrawDoneRelease()
+ }
+ else if (lastMsgId == SysMessageId::HomeButtonDenied)
+ {
+ cemuLog_logDebug(LogType::Force, "ProcUI: Received Home Button Denied message");
+ _SubmitCommandToCoreThreads(ProcUICoreThreadCommand::HomeButtonDenied);
+ }
+ else if ( lastMsgId == SysMessageId::NetIoStartOrStop )
+ {
+ if (msg->data1 != 0)
+ {
+ cemuLog_logDebug(LogType::Force, "ProcUI: Received Net IO Start message");
+ _SubmitCommandToCoreThreads(ProcUICoreThreadCommand::NetIoStart);
+ }
+ else
+ {
+ cemuLog_logDebug(LogType::Force, "ProcUI: Received Net IO Stop message");
+ _SubmitCommandToCoreThreads(ProcUICoreThreadCommand::NetIoStop);
+ }
+ }
+ else
+ {
+ cemuLog_log(LogType::Force, "ProcUI: Received unknown message 0x{:08x}", (uint32)lastMsgId);
+ }
+ return true;
+ }
+
+ ProcUIStatus ProcUIProcessMessages(bool isBlockingInBackground)
+ {
+ OSMessage msg;
+ if (!s_isInitialized)
+ {
+ cemuLog_logOnce(LogType::Force, "ProcUIProcessMessages: ProcUI not initialized");
+ cemu_assert_suspicious();
+ return ProcUIStatus::Foreground;
+ }
+ if ( !isBlockingInBackground && OSGetCoreId() != 2 )
+ {
+ cemuLog_logOnce(LogType::Force, "ProcUIProcessMessages: Non-blocking call must run on core 2");
+ }
+ if (s_previouslyWasBlocking && isBlockingInBackground )
+ {
+ cemuLog_logOnce(LogType::Force, "ProcUIProcessMessages: Cannot switch to blocking mode when in background");
+ }
+ s_currentProcUIStatus = s_isInForeground ? ProcUIStatus::Foreground : ProcUIStatus::Background;
+ if (s_drawDoneReleaseCalled)
+ {
+ s_isInForeground = false;
+ s_currentProcUIStatus = ProcUIStatus::Background;
+ _SubmitCommandToCoreThreads(ProcUICoreThreadCommand::ReleaseForeground);
+ OSResetEvent(&s_eventWaitingBeforeReleaseForeground);
+ if(s_saveCallback)
+ PPCCoreCallback(s_saveCallback);
+ if(s_saveCallbackEx)
+ PPCCoreCallback(s_saveCallbackEx, s_saveCallbackExUserParam);
+ if (s_isForegroundProcess && isBlockingInBackground)
+ {
+ // start background thread
+ __OSCreateThreadType(&s_backgroundThread, RPLLoader_MakePPCCallable(ProcUI_BackgroundThread_ReceiveSingleMessage),
+ 0, nullptr, (uint8*)s_backgroundThreadStack.GetPtr() + s_coreThreadStackSize, s_coreThreadStackSize,
+ 16, (1<<2), OSThread_t::THREAD_TYPE::TYPE_DRIVER);
+ OSResumeThread(&s_backgroundThread);
+ s_previouslyWasBlocking = true;
+ }
+ cemuLog_logDebug(LogType::Force, "ProcUI: Releasing foreground");
+ OSSignalEvent(&s_eventWaitingBeforeReleaseForeground);
+ s_drawDoneReleaseCalled = false;
+ }
+ if (s_isInForeground || !isBlockingInBackground)
+ {
+ // non-blocking mode
+ if ( OSReceiveMessage(s_systemMessageQueuePtr, &msg, 0) )
+ {
+ s_previouslyWasBlocking = false;
+ if ( !ProcessSysMessage(&msg) )
+ return s_currentProcUIStatus;
+ // continue below, if we are now in background then ProcUIProcessMessages enters blocking mode
+ }
+ }
+ // blocking mode (if in background and param is true)
+ while (!s_isInForeground && isBlockingInBackground)
+ {
+ if ( !s_isForegroundProcess)
+ {
+ OSReceiveMessage(s_systemMessageQueuePtr, &msg, OS_MESSAGE_BLOCK);
+ s_previouslyWasBlocking = false;
+ if ( !ProcessSysMessage(&msg) )
+ return s_currentProcUIStatus;
+ }
+ // this code should only run if the background thread was started? Maybe rearrange the code to make this more clear
+ OSWaitEvent(&s_eventBackgroundThreadGotMessage);
+ OSResetEvent(&s_eventBackgroundThreadGotMessage);
+ OSJoinThread(&s_backgroundThread, nullptr);
+ msg = g_lastMsg; // g_lastMsg is set by the background thread
+ s_previouslyWasBlocking = false;
+ if ( !ProcessSysMessage(&msg) )
+ return s_currentProcUIStatus;
+ }
+ return s_currentProcUIStatus;
+ }
+
+ ProcUIStatus ProcUISubProcessMessages(bool isBlockingInBackground)
+ {
+ if (isBlockingInBackground)
+ {
+ while (s_currentProcUIStatus == ProcUIStatus::Background)
+ OSWaitEvent(&s_eventStateMessageReceived);
+ }
+ return s_currentProcUIStatus;
+ }
+
+ const char* ProcUIDriver_GetName()
+ {
+ s_ProcUIDriverName->assign("ProcUI");
+ return s_ProcUIDriverName->c_str();
+ }
+
+ void ProcUIDriver_Init(/* parameters unknown */)
+ {
+ s_driverIsActive = true;
+ OSMemoryBarrier();
+ }
+
+ void ProcUIDriver_OnDone(/* parameters unknown */)
+ {
+ if (s_driverIsActive)
+ {
+ ProcUIShutdown();
+ s_driverIsActive = false;
+ OSMemoryBarrier();
+ }
+ }
+
+ void StoreMEM1AndFGBucket()
+ {
+ if (s_mem1StorageBasePtr)
+ {
+ MEMPTR memBound;
+ uint32be memBoundSize;
+ OSGetMemBound(1, (MPTR*)memBound.GetBEPtr(), (uint32*)&memBoundSize);
+ OSBlockMove(s_mem1StorageBasePtr.GetPtr(), memBound.GetPtr(), memBoundSize, true);
+ }
+ if (s_bucketStorageBasePtr)
+ {
+ MEMPTR memBound;
+ uint32be memBoundSize;
+ OSGetForegroundBucketFreeArea((MPTR*)memBound.GetBEPtr(), (MPTR*)&memBoundSize);
+ OSBlockMove(s_bucketStorageBasePtr.GetPtr(), memBound.GetPtr(), memBoundSize, true);
+ }
+ }
+
+ void RestoreMEM1AndFGBucket()
+ {
+ if (s_mem1StorageBasePtr)
+ {
+ MEMPTR memBound;
+ uint32be memBoundSize;
+ OSGetMemBound(1, (MPTR*)memBound.GetBEPtr(), (uint32*)&memBoundSize);
+ OSBlockMove(memBound.GetPtr(), s_mem1StorageBasePtr, memBoundSize, true);
+ GX2::GX2Invalidate(0x40, s_mem1StorageBasePtr.GetMPTR(), memBoundSize);
+ }
+ if (s_bucketStorageBasePtr)
+ {
+ MEMPTR memBound;
+ uint32be memBoundSize;
+ OSGetForegroundBucketFreeArea((MPTR*)memBound.GetBEPtr(), (MPTR*)&memBoundSize);
+ OSBlockMove(memBound.GetPtr(), s_bucketStorageBasePtr, memBoundSize, true);
+ GX2::GX2Invalidate(0x40, memBound.GetMPTR(), memBoundSize);
+ }
+ }
+
+ void ProcUIDriver_OnAcquiredForeground(/* parameters unknown */)
+ {
+ if (s_driverInBackground)
+ {
+ ProcUIDriver_Init();
+ s_driverInBackground = false;
+ }
+ else
+ {
+ RestoreMEM1AndFGBucket();
+ s_driverIsActive = true;
+ OSMemoryBarrier();
+ }
+ }
+
+ void ProcUIDriver_OnReleaseForeground(/* parameters unknown */)
+ {
+ StoreMEM1AndFGBucket();
+ s_driverIsActive = false;
+ OSMemoryBarrier();
+ }
+
+ sint32 rpl_entry(uint32 moduleHandle, RplEntryReason reason)
+ {
+ if ( reason == RplEntryReason::Loaded )
+ {
+ s_ProcUIDriver->getDriverName = RPLLoader_MakePPCCallable([](PPCInterpreter_t* hCPU) {MEMPTR namePtr(ProcUIDriver_GetName()); osLib_returnFromFunction(hCPU, namePtr.GetMPTR()); });
+ s_ProcUIDriver->init = RPLLoader_MakePPCCallable([](PPCInterpreter_t* hCPU) {ProcUIDriver_Init(); osLib_returnFromFunction(hCPU, 0); });
+ s_ProcUIDriver->onAcquireForeground = RPLLoader_MakePPCCallable([](PPCInterpreter_t* hCPU) {ProcUIDriver_OnAcquiredForeground(); osLib_returnFromFunction(hCPU, 0); });
+ s_ProcUIDriver->onReleaseForeground = RPLLoader_MakePPCCallable([](PPCInterpreter_t* hCPU) {ProcUIDriver_OnReleaseForeground(); osLib_returnFromFunction(hCPU, 0); });
+ s_ProcUIDriver->done = RPLLoader_MakePPCCallable([](PPCInterpreter_t* hCPU) {ProcUIDriver_OnDone(); osLib_returnFromFunction(hCPU, 0); });
+
+ s_driverIsActive = false;
+ s_driverArgUkn1 = 0;
+ s_driverArgUkn2 = 0;
+ s_driverInBackground = false;
+ uint32be ukn3;
+ OSDriver_Register(moduleHandle, 200, &s_ProcUIDriver, 0, &s_driverArgUkn1, &s_driverArgUkn2, &ukn3);
+ if ( ukn3 )
+ {
+ if ( OSGetForegroundBucket(nullptr, nullptr) )
+ {
+ ProcUIDriver_Init();
+ OSMemoryBarrier();
+ return 0;
+ }
+ s_driverInBackground = true;
+ }
+ OSMemoryBarrier();
+ }
+ else if ( reason == RplEntryReason::Unloaded )
+ {
+ ProcUIDriver_OnDone();
+ OSDriver_Deregister(moduleHandle, 0);
+ }
+ return 0;
+ }
+
+ void reset()
+ {
+ // set variables to their initial state as if the RPL was just loaded
+ s_isInitialized = false;
+ s_isInShutdown = false;
+ s_isInForeground = false; // ProcUIInForeground returns false until ProcUIInit(Ex) is called
+ s_isForegroundProcess = true;
+ s_saveCallback = nullptr;
+ s_saveCallbackEx = nullptr;
+ s_systemMessageQueuePtr = nullptr;
+ ClearCallbacksWithoutMemFree();
+ s_currentProcUIStatus = ProcUIStatus::Foreground;
+ s_bucketStorageBasePtr = nullptr;
+ s_mem1StorageBasePtr = nullptr;
+ s_drawDoneReleaseCalled = false;
+ s_previouslyWasBlocking = false;
+ // core threads
+ s_coreThreadStackSize = 0;
+ s_coreThreadsCreated = false;
+ s_commandForCoreThread = ProcUICoreThreadCommand::Initial;
+ // background thread
+ s_backgroundThreadStack = nullptr;
+ // user defined heap
+ s_memoryPoolHeapPtr = nullptr;
+ s_memAllocPtr = nullptr;
+ s_memFreePtr = nullptr;
+ // driver
+ s_driverIsActive = false;
+ s_driverInBackground = false;
+ }
+
+ void load()
+ {
+ reset();
+
+ cafeExportRegister("proc_ui", ProcUIInit, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUIInitEx, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUIShutdown, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUIIsRunning, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUIInForeground, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUIInShutdown, LogType::ProcUi);
+
+ cafeExportRegister("proc_ui", ProcUIRegisterCallbackCore, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUIRegisterCallback, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUIRegisterBackgroundCallback, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUIClearCallbacks, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUISetSaveCallback, LogType::ProcUi);
+
+ cafeExportRegister("proc_ui", ProcUISetCallbackStackSize, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUICalcMemorySize, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUISetMemoryPool, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUISetBucketStorage, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUISetMEM1Storage, LogType::ProcUi);
+
+ cafeExportRegister("proc_ui", ProcUIDrawDoneRelease, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUIProcessMessages, LogType::ProcUi);
+ cafeExportRegister("proc_ui", ProcUISubProcessMessages, LogType::ProcUi);
+
+ // manually call rpl_entry for now
+ rpl_entry(-1, RplEntryReason::Loaded);
+ }
};
-std::unordered_map g_Callbacks;
-
-uint32 ProcUIRegisterCallback(uint32 message, MPTR callback, void* data, sint32 priority)
-{
- g_Callbacks.insert_or_assign(message, ProcUICallback{ .callback = callback, .data = data, .priority = priority });
- return 0;
-}
-
-void ProcUI_SendBackgroundMessage()
-{
- if (g_Callbacks.contains(PROCUI_STATUS_BACKGROUND))
- {
- ProcUICallback& callback = g_Callbacks[PROCUI_STATUS_BACKGROUND];
- PPCCoreCallback(callback.callback, callback.data);
- }
-}
-
-void ProcUI_SendForegroundMessage()
-{
- if (g_Callbacks.contains(PROCUI_STATUS_FOREGROUND))
- {
- ProcUICallback& callback = g_Callbacks[PROCUI_STATUS_FOREGROUND];
- PPCCoreCallback(callback.callback, callback.data);
- }
-}
-
-void procui_load()
-{
- cafeExportRegister("proc_ui", ProcUIRegisterCallback, LogType::ProcUi);
- cafeExportRegister("proc_ui", ProcUIProcessMessages, LogType::ProcUi);
- cafeExportRegister("proc_ui", ProcUIInForeground, LogType::ProcUi);
-}
\ No newline at end of file
diff --git a/src/Cafe/OS/libs/proc_ui/proc_ui.h b/src/Cafe/OS/libs/proc_ui/proc_ui.h
index 1cd04fb1..8de7bb4d 100644
--- a/src/Cafe/OS/libs/proc_ui/proc_ui.h
+++ b/src/Cafe/OS/libs/proc_ui/proc_ui.h
@@ -1,5 +1,44 @@
-void procui_load();
+namespace proc_ui
+{
+ enum class ProcUIStatus
+ {
+ Foreground = 0,
+ Background = 1,
+ Releasing = 2,
+ Exit = 3
+ };
-void ProcUI_SendForegroundMessage();
-void ProcUI_SendBackgroundMessage();
\ No newline at end of file
+ enum class ProcUICallbackId
+ {
+ AcquireForeground = 0,
+ ReleaseForeground = 1,
+ Exit = 2,
+ NetIoStart = 3,
+ NetIoStop = 4,
+ HomeButtonDenied = 5,
+ COUNT = 6
+ };
+
+ void ProcUIInit(MEMPTR callbackReadyToRelease);
+ void ProcUIInitEx(MEMPTR callbackReadyToReleaseEx, MEMPTR userParam);
+ void ProcUIShutdown();
+ bool ProcUIIsRunning();
+ bool ProcUIInForeground();
+ bool ProcUIInShutdown();
+ void ProcUIRegisterCallback(ProcUICallbackId callbackType, void* funcPtr, void* userParam, sint32 priority);
+ void ProcUIRegisterCallbackCore(ProcUICallbackId callbackType, void* funcPtr, void* userParam, sint32 priority, uint32 coreIndex);
+ void ProcUIRegisterBackgroundCallback(void* funcPtr, void* userParam, uint64 tickDelay);
+ void ProcUIClearCallbacks();
+ void ProcUISetSaveCallback(void* funcPtr, void* userParam);
+ void ProcUISetCallbackStackSize(uint32 newStackSize);
+ uint32 ProcUICalcMemorySize(uint32 numCallbacks);
+ sint32 ProcUISetMemoryPool(void* memBase, uint32 size);
+ void ProcUISetBucketStorage(void* memBase, uint32 size);
+ void ProcUISetMEM1Storage(void* memBase, uint32 size);
+ void ProcUIDrawDoneRelease();
+ ProcUIStatus ProcUIProcessMessages(bool isBlockingInBackground);
+ ProcUIStatus ProcUISubProcessMessages(bool isBlockingInBackground);
+
+ void load();
+}
\ No newline at end of file
diff --git a/src/Cafe/OS/libs/sysapp/sysapp.cpp b/src/Cafe/OS/libs/sysapp/sysapp.cpp
index 413d535a..ecaa940a 100644
--- a/src/Cafe/OS/libs/sysapp/sysapp.cpp
+++ b/src/Cafe/OS/libs/sysapp/sysapp.cpp
@@ -639,11 +639,34 @@ namespace sysapp
return coreinit::OSRestartGame(argc, argv);
}
+ struct EManualArgs
+ {
+ sysStandardArguments_t stdArgs;
+ uint64be titleId;
+ };
+ static_assert(sizeof(EManualArgs) == 0x10);
+
+ void _SYSSwitchToEManual(EManualArgs* args)
+ {
+ // the struct has the titleId at offset 8 and standard args at 0 (total size is most likely 0x10)
+ cemuLog_log(LogType::Force, "SYSSwitchToEManual called. Opening the manual is not supported");
+ coreinit::StartBackgroundForegroundTransition();
+ }
+
+ void SYSSwitchToEManual()
+ {
+ EManualArgs args{};
+ args.titleId = coreinit::OSGetTitleID();
+ _SYSSwitchToEManual(&args);
+ }
+
void load()
{
cafeExportRegisterFunc(SYSClearSysArgs, "sysapp", "SYSClearSysArgs", LogType::Placeholder);
cafeExportRegisterFunc(_SYSLaunchTitleByPathFromLauncher, "sysapp", "_SYSLaunchTitleByPathFromLauncher", LogType::Placeholder);
cafeExportRegisterFunc(SYSRelaunchTitle, "sysapp", "SYSRelaunchTitle", LogType::Placeholder);
+ cafeExportRegister("sysapp", _SYSSwitchToEManual, LogType::Placeholder);
+ cafeExportRegister("sysapp", SYSSwitchToEManual, LogType::Placeholder);
}
}
diff --git a/src/Common/CafeString.h b/src/Common/CafeString.h
index 45a515b1..d902d721 100644
--- a/src/Common/CafeString.h
+++ b/src/Common/CafeString.h
@@ -20,6 +20,11 @@ class CafeString // fixed buffer size, null-terminated, PPC char
return true;
}
+ const char* c_str()
+ {
+ return (const char*)data;
+ }
+
uint8be data[N];
};
From e7c6862e19a277d0d8828c99a6874e69eedbd802 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Wed, 1 May 2024 01:55:55 +0200
Subject: [PATCH 006/216] DownloadManager: Fix missing updates
---
src/Cemu/napi/napi_version.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Cemu/napi/napi_version.cpp b/src/Cemu/napi/napi_version.cpp
index a1f5879c..5a85dde3 100644
--- a/src/Cemu/napi/napi_version.cpp
+++ b/src/Cemu/napi/napi_version.cpp
@@ -31,7 +31,7 @@ namespace NAPI
requestUrl = NintendoURLs::TAGAYAURL;
break;
}
- requestUrl.append(fmt::format(fmt::runtime("/{}/{}/latest_version"), NCrypto::GetRegionAsString(authInfo.region), authInfo.country));
+ requestUrl.append(fmt::format(fmt::runtime("/{}/{}/latest_version"), NCrypto::GetRegionAsString(authInfo.region), authInfo.country.empty() ? "NN" : authInfo.country));
req.initate(authInfo.GetService(), requestUrl, CurlRequestHelper::SERVER_SSL_CONTEXT::TAGAYA);
if (!req.submitRequest(false))
@@ -63,7 +63,7 @@ namespace NAPI
{
NAPI_VersionList_Result result;
CurlRequestHelper req;
- req.initate(authInfo.GetService(), fmt::format("https://{}/tagaya/versionlist/{}/{}/list/{}.versionlist", fqdnURL, NCrypto::GetRegionAsString(authInfo.region), authInfo.country, versionListVersion), CurlRequestHelper::SERVER_SSL_CONTEXT::TAGAYA);
+ req.initate(authInfo.GetService(), fmt::format("https://{}/tagaya/versionlist/{}/{}/list/{}.versionlist", fqdnURL, NCrypto::GetRegionAsString(authInfo.region), authInfo.country.empty() ? "NN" : authInfo.country, versionListVersion), CurlRequestHelper::SERVER_SSL_CONTEXT::TAGAYA);
if (!req.submitRequest(false))
{
cemuLog_log(LogType::Force, fmt::format("Failed to request update list"));
From 379950d185852b3c2da14b40e30a872809ad0ac2 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Wed, 1 May 2024 05:06:50 +0200
Subject: [PATCH 007/216] coreinit+nn_save: Cleanup some legacy code
---
src/Cafe/OS/libs/coreinit/coreinit_FG.cpp | 20 +-
src/Cafe/OS/libs/coreinit/coreinit_FG.h | 2 +-
src/Cafe/OS/libs/coreinit/coreinit_FS.cpp | 243 +++++++------
src/Cafe/OS/libs/coreinit/coreinit_FS.h | 84 ++---
src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp | 10 +-
src/Cafe/OS/libs/coreinit/coreinit_Memory.cpp | 6 +-
src/Cafe/OS/libs/coreinit/coreinit_Memory.h | 2 +-
src/Cafe/OS/libs/nlibcurl/nlibcurl.cpp | 6 +-
src/Cafe/OS/libs/nn_save/nn_save.cpp | 339 ++++++------------
src/Cafe/OS/libs/proc_ui/proc_ui.cpp | 12 +-
src/Common/MemPtr.h | 6 -
src/Common/StackAllocator.h | 1 -
12 files changed, 282 insertions(+), 449 deletions(-)
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FG.cpp b/src/Cafe/OS/libs/coreinit/coreinit_FG.cpp
index 15dcd6da..b751a8fd 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_FG.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_FG.cpp
@@ -55,19 +55,18 @@ namespace coreinit
{
// return full size of foreground bucket area
if (offset)
- *offset = MEMPTR{ (uint32)MEMORY_FGBUCKET_AREA_ADDR };
+ *offset = { (MPTR)MEMORY_FGBUCKET_AREA_ADDR };
if (size)
*size = MEMORY_FGBUCKET_AREA_SIZE;
// return true if in foreground
return true;
}
- bool OSGetForegroundBucketFreeArea(MPTR* offset, MPTR* size)
+ bool OSGetForegroundBucketFreeArea(MEMPTR* offset, uint32be* size)
{
uint8* freeAreaAddr = GetFGMemByArea(FG_BUCKET_AREA_FREE).GetPtr();
-
- *offset = _swapEndianU32(memory_getVirtualOffsetFromPointer(freeAreaAddr));
- *size = _swapEndianU32(FG_BUCKET_AREA_FREE_SIZE);
+ *offset = freeAreaAddr;
+ *size = FG_BUCKET_AREA_FREE_SIZE;
// return true if in foreground
return (fgAddr != nullptr);
}
@@ -82,15 +81,6 @@ namespace coreinit
osLib_returnFromFunction(hCPU, r ? 1 : 0);
}
- void coreinitExport_OSGetForegroundBucketFreeArea(PPCInterpreter_t* hCPU)
- {
- debug_printf("OSGetForegroundBucketFreeArea(0x%x,0x%x)\n", hCPU->gpr[3], hCPU->gpr[4]);
- ppcDefineParamMPTR(areaOutput, 0);
- ppcDefineParamMPTR(areaSize, 1);
- bool r = OSGetForegroundBucketFreeArea((MPTR*)memory_getPointerFromVirtualOffsetAllowNull(areaOutput), (MPTR*)memory_getPointerFromVirtualOffsetAllowNull(areaSize));
- osLib_returnFromFunction(hCPU, r ? 1 : 0);
- }
-
void InitForegroundBucket()
{
uint32be fgSize;
@@ -194,7 +184,7 @@ namespace coreinit
void InitializeFG()
{
osLib_addFunction("coreinit", "OSGetForegroundBucket", coreinitExport_OSGetForegroundBucket);
- osLib_addFunction("coreinit", "OSGetForegroundBucketFreeArea", coreinitExport_OSGetForegroundBucketFreeArea);
+ cafeExportRegister("coreinit", OSGetForegroundBucket, LogType::CoreinitMem);
osLib_addFunction("coreinit", "OSCopyFromClipboard", coreinitExport_OSCopyFromClipboard);
}
}
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FG.h b/src/Cafe/OS/libs/coreinit/coreinit_FG.h
index 846001b9..0c2a3ee3 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_FG.h
+++ b/src/Cafe/OS/libs/coreinit/coreinit_FG.h
@@ -9,7 +9,7 @@ namespace coreinit
bool __OSResizeCopyData(sint32 length);
bool OSGetForegroundBucket(MEMPTR* offset, uint32be* size);
- bool OSGetForegroundBucketFreeArea(MPTR* offset, MPTR* size);
+ bool OSGetForegroundBucketFreeArea(MEMPTR* offset, uint32be* size);
void InitForegroundBucket();
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp
index 0ca8fb8e..0fc8912f 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp
@@ -56,7 +56,7 @@ namespace coreinit
OSUnlockMutex(&s_fsGlobalMutex);
}
- void _debugVerifyCommand(const char* stage, FSCmdBlockBody_t* fsCmdBlockBody);
+ void _debugVerifyCommand(const char* stage, FSCmdBlockBody* fsCmdBlockBody);
bool sFSInitialized = true; // this should be false but it seems like some games rely on FSInit being called before main()? Twilight Princess for example reads files before it calls FSInit
bool sFSShutdown = false;
@@ -194,12 +194,12 @@ namespace coreinit
}
// return the aligned FSClientBody struct inside a FSClient struct
- FSCmdBlockBody_t* __FSGetCmdBlockBody(FSCmdBlock_t* fsCmdBlock)
+ FSCmdBlockBody* __FSGetCmdBlockBody(FSCmdBlock_t* fsCmdBlock)
{
// align pointer to 64 bytes
if (fsCmdBlock == nullptr)
return nullptr;
- FSCmdBlockBody_t* fsCmdBlockBody = (FSCmdBlockBody_t*)(((uintptr_t)fsCmdBlock + 0x3F) & ~0x3F);
+ FSCmdBlockBody* fsCmdBlockBody = (FSCmdBlockBody*)(((uintptr_t)fsCmdBlock + 0x3F) & ~0x3F);
fsCmdBlockBody->selfCmdBlock = fsCmdBlock;
return fsCmdBlockBody;
}
@@ -261,8 +261,8 @@ namespace coreinit
fsCmdQueueBE->numCommandsInFlight = 0;
fsCmdQueueBE->numMaxCommandsInFlight = numMaxCommandsInFlight;
coreinit::OSFastMutex_Init(&fsCmdQueueBE->fastMutex, nullptr);
- fsCmdQueueBE->firstMPTR = _swapEndianU32(0);
- fsCmdQueueBE->lastMPTR = _swapEndianU32(0);
+ fsCmdQueueBE->first = nullptr;
+ fsCmdQueueBE->last = nullptr;
}
void FSInit()
@@ -382,74 +382,71 @@ namespace coreinit
Semaphore g_semaphoreQueuedCmds;
- void __FSQueueCmdByPriority(FSCmdQueue* fsCmdQueueBE, FSCmdBlockBody_t* fsCmdBlockBody, bool stopAtEqualPriority)
+ void __FSQueueCmdByPriority(FSCmdQueue* fsCmdQueueBE, FSCmdBlockBody* fsCmdBlockBody, bool stopAtEqualPriority)
{
- MPTR fsCmdBlockBodyMPTR = memory_getVirtualOffsetFromPointer(fsCmdBlockBody);
- if (_swapEndianU32(fsCmdQueueBE->firstMPTR) == MPTR_NULL)
+ if (!fsCmdQueueBE->first)
{
// queue is currently empty
- cemu_assert(fsCmdQueueBE->lastMPTR == MPTR_NULL);
- fsCmdQueueBE->firstMPTR = _swapEndianU32(fsCmdBlockBodyMPTR);
- fsCmdQueueBE->lastMPTR = _swapEndianU32(fsCmdBlockBodyMPTR);
- fsCmdBlockBody->nextMPTR = _swapEndianU32(MPTR_NULL);
- fsCmdBlockBody->previousMPTR = _swapEndianU32(MPTR_NULL);
+ cemu_assert(!fsCmdQueueBE->last);
+ fsCmdQueueBE->first = fsCmdBlockBody;
+ fsCmdQueueBE->last = fsCmdBlockBody;
+ fsCmdBlockBody->next = nullptr;
+ fsCmdBlockBody->previous = nullptr;
return;
}
// iterate from last to first element as long as iterated priority is lower
- FSCmdBlockBody_t* fsCmdBlockBodyItrPrev = NULL;
- FSCmdBlockBody_t* fsCmdBlockBodyItr = (FSCmdBlockBody_t*)memory_getPointerFromVirtualOffsetAllowNull(_swapEndianU32(fsCmdQueueBE->lastMPTR));
+ FSCmdBlockBody* fsCmdBlockBodyItrPrev = nullptr;
+ FSCmdBlockBody* fsCmdBlockBodyItr = fsCmdQueueBE->last;
while (true)
{
- if (fsCmdBlockBodyItr == NULL)
+ if (!fsCmdBlockBodyItr)
{
// insert at the head of the list
- fsCmdQueueBE->firstMPTR = _swapEndianU32(fsCmdBlockBodyMPTR);
- fsCmdBlockBody->nextMPTR = _swapEndianU32(memory_getVirtualOffsetFromPointer(fsCmdBlockBodyItrPrev));
- fsCmdBlockBody->previousMPTR = _swapEndianU32(MPTR_NULL);
- fsCmdBlockBodyItrPrev->previousMPTR = _swapEndianU32(memory_getVirtualOffsetFromPointer(fsCmdBlockBody));
+ fsCmdQueueBE->first = fsCmdBlockBody;
+ fsCmdBlockBody->next = fsCmdBlockBodyItrPrev;
+ fsCmdBlockBody->previous = nullptr;
+ fsCmdBlockBodyItrPrev->previous = fsCmdBlockBody;
return;
}
// compare priority
if ((stopAtEqualPriority && fsCmdBlockBodyItr->priority >= fsCmdBlockBody->priority) || (stopAtEqualPriority == false && fsCmdBlockBodyItr->priority > fsCmdBlockBody->priority))
{
// insert cmd here
- if (fsCmdBlockBodyItrPrev != NULL)
+ if (fsCmdBlockBodyItrPrev)
{
- fsCmdBlockBody->nextMPTR = _swapEndianU32(memory_getVirtualOffsetFromPointer(fsCmdBlockBodyItrPrev));
+ fsCmdBlockBody->next = fsCmdBlockBodyItrPrev;
}
else
{
- fsCmdBlockBody->nextMPTR = _swapEndianU32(MPTR_NULL);
- fsCmdQueueBE->lastMPTR = _swapEndianU32(fsCmdBlockBodyMPTR);
+ fsCmdBlockBody->next = nullptr;
+ fsCmdQueueBE->last = fsCmdBlockBody;
}
- fsCmdBlockBody->previousMPTR = _swapEndianU32(memory_getVirtualOffsetFromPointer(fsCmdBlockBodyItr));
+ fsCmdBlockBody->previous = fsCmdBlockBodyItr;
if (fsCmdBlockBodyItrPrev)
- fsCmdBlockBodyItrPrev->previousMPTR = _swapEndianU32(memory_getVirtualOffsetFromPointer(fsCmdBlockBody));
- fsCmdBlockBodyItr->nextMPTR = _swapEndianU32(memory_getVirtualOffsetFromPointer(fsCmdBlockBody));
+ fsCmdBlockBodyItrPrev->previous = fsCmdBlockBody;
+ fsCmdBlockBodyItr->next = fsCmdBlockBody;
return;
}
// next
fsCmdBlockBodyItrPrev = fsCmdBlockBodyItr;
- fsCmdBlockBodyItr = (FSCmdBlockBody_t*)memory_getPointerFromVirtualOffsetAllowNull(_swapEndianU32(fsCmdBlockBodyItr->previousMPTR));
+ fsCmdBlockBodyItr = fsCmdBlockBodyItr->previous;
}
}
- FSCmdBlockBody_t* __FSTakeCommandFromQueue(FSCmdQueue* cmdQueue)
+ FSCmdBlockBody* __FSTakeCommandFromQueue(FSCmdQueue* cmdQueue)
{
- FSCmdBlockBody_t* dequeuedCmd = nullptr;
- if (_swapEndianU32(cmdQueue->firstMPTR) != MPTR_NULL)
+ if (!cmdQueue->first)
+ return nullptr;
+ // dequeue cmd
+ FSCmdBlockBody* dequeuedCmd = cmdQueue->first;
+ if (cmdQueue->first == cmdQueue->last)
+ cmdQueue->last = nullptr;
+ cmdQueue->first = dequeuedCmd->next;
+ dequeuedCmd->next = nullptr;
+ if (dequeuedCmd->next)
{
- dequeuedCmd = (FSCmdBlockBody_t*)memory_getPointerFromVirtualOffset(_swapEndianU32(cmdQueue->firstMPTR));
- // dequeue cmd
- if (cmdQueue->firstMPTR == cmdQueue->lastMPTR)
- cmdQueue->lastMPTR = _swapEndianU32(MPTR_NULL);
- cmdQueue->firstMPTR = dequeuedCmd->nextMPTR;
- dequeuedCmd->nextMPTR = _swapEndianU32(MPTR_NULL);
- if (_swapEndianU32(dequeuedCmd->nextMPTR) != MPTR_NULL)
- {
- FSCmdBlockBody_t* fsCmdBodyNext = (FSCmdBlockBody_t*)memory_getPointerFromVirtualOffset(_swapEndianU32(dequeuedCmd->nextMPTR));
- fsCmdBodyNext->previousMPTR = _swapEndianU32(MPTR_NULL);
- }
+ FSCmdBlockBody* fsCmdBodyNext = dequeuedCmd->next;
+ fsCmdBodyNext->previous = nullptr;
}
return dequeuedCmd;
}
@@ -499,7 +496,7 @@ namespace coreinit
FSLockMutex();
if (cmdQueue->numCommandsInFlight < cmdQueue->numMaxCommandsInFlight)
{
- FSCmdBlockBody_t* dequeuedCommand = __FSTakeCommandFromQueue(cmdQueue);
+ FSCmdBlockBody* dequeuedCommand = __FSTakeCommandFromQueue(cmdQueue);
if (dequeuedCommand)
{
cmdQueue->numCommandsInFlight += 1;
@@ -512,7 +509,7 @@ namespace coreinit
FSUnlockMutex();
}
- void __FSQueueDefaultFinishFunc(FSCmdBlockBody_t* fsCmdBlockBody, FS_RESULT result)
+ void __FSQueueDefaultFinishFunc(FSCmdBlockBody* fsCmdBlockBody, FS_RESULT result)
{
switch ((FSA_CMD_OPERATION_TYPE)fsCmdBlockBody->fsaShimBuffer.operationType.value())
{
@@ -594,13 +591,13 @@ namespace coreinit
void export___FSQueueDefaultFinishFunc(PPCInterpreter_t* hCPU)
{
- ppcDefineParamPtr(cmd, FSCmdBlockBody_t, 0);
+ ppcDefineParamPtr(cmd, FSCmdBlockBody, 0);
FS_RESULT result = (FS_RESULT)PPCInterpreter_getCallParamU32(hCPU, 1);
__FSQueueDefaultFinishFunc(cmd, static_cast(result));
osLib_returnFromFunction(hCPU, 0);
}
- void __FSQueueCmd(FSCmdQueue* cmdQueue, FSCmdBlockBody_t* fsCmdBlockBody, MPTR finishCmdFunc)
+ void __FSQueueCmd(FSCmdQueue* cmdQueue, FSCmdBlockBody* fsCmdBlockBody, MPTR finishCmdFunc)
{
fsCmdBlockBody->cmdFinishFuncMPTR = finishCmdFunc;
FSLockMutex();
@@ -676,7 +673,7 @@ namespace coreinit
return FS_RESULT::FATAL_ERROR;
}
- void __FSCmdSubmitResult(FSCmdBlockBody_t* fsCmdBlockBody, FS_RESULT result)
+ void __FSCmdSubmitResult(FSCmdBlockBody* fsCmdBlockBody, FS_RESULT result)
{
_debugVerifyCommand("FSCmdSubmitResult", fsCmdBlockBody);
@@ -720,7 +717,7 @@ namespace coreinit
void __FSAIoctlResponseCallback(PPCInterpreter_t* hCPU)
{
ppcDefineParamU32(iosResult, 0);
- ppcDefineParamPtr(cmd, FSCmdBlockBody_t, 1);
+ ppcDefineParamPtr(cmd, FSCmdBlockBody, 1);
FSA_RESULT fsaStatus = _FSIosErrorToFSAStatus((IOS_ERROR)iosResult);
@@ -754,25 +751,25 @@ namespace coreinit
void FSInitCmdBlock(FSCmdBlock_t* fsCmdBlock)
{
memset(fsCmdBlock, 0x00, sizeof(FSCmdBlock_t));
- FSCmdBlockBody_t* fsCmdBlockBody = __FSGetCmdBlockBody(fsCmdBlock);
+ FSCmdBlockBody* fsCmdBlockBody = __FSGetCmdBlockBody(fsCmdBlock);
fsCmdBlockBody->statusCode = _swapEndianU32(FSA_CMD_STATUS_CODE_D900A21);
fsCmdBlockBody->priority = 0x10;
}
- void __FSAsyncToSyncInit(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSAsyncParamsNew_t* asyncParams)
+ void __FSAsyncToSyncInit(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSAsyncParams* asyncParams)
{
if (fsClient == nullptr || fsCmdBlock == nullptr || asyncParams == nullptr)
assert_dbg();
- FSCmdBlockBody_t* fsCmdBlockBody = __FSGetCmdBlockBody(fsCmdBlock);
+ FSCmdBlockBody* fsCmdBlockBody = __FSGetCmdBlockBody(fsCmdBlock);
coreinit::OSInitMessageQueue(&fsCmdBlockBody->syncTaskMsgQueue, fsCmdBlockBody->_syncTaskMsg, 1);
asyncParams->userCallback = nullptr;
asyncParams->userContext = nullptr;
asyncParams->ioMsgQueue = &fsCmdBlockBody->syncTaskMsgQueue;
}
- void __FSPrepareCmdAsyncResult(FSClientBody_t* fsClientBody, FSCmdBlockBody_t* fsCmdBlockBody, FSAsyncResult* fsCmdBlockAsyncResult, FSAsyncParamsNew_t* fsAsyncParams)
+ void __FSPrepareCmdAsyncResult(FSClientBody_t* fsClientBody, FSCmdBlockBody* fsCmdBlockBody, FSAsyncResult* fsCmdBlockAsyncResult, FSAsyncParams* fsAsyncParams)
{
- memcpy(&fsCmdBlockAsyncResult->fsAsyncParamsNew, fsAsyncParams, sizeof(FSAsyncParamsNew_t));
+ memcpy(&fsCmdBlockAsyncResult->fsAsyncParamsNew, fsAsyncParams, sizeof(FSAsyncParams));
fsCmdBlockAsyncResult->fsClient = fsClientBody->selfClient;
fsCmdBlockAsyncResult->fsCmdBlock = fsCmdBlockBody->selfCmdBlock;
@@ -781,7 +778,7 @@ namespace coreinit
fsCmdBlockAsyncResult->msgUnion.fsMsg.commandType = _swapEndianU32(8);
}
- sint32 __FSPrepareCmd(FSClientBody_t* fsClientBody, FSCmdBlockBody_t* fsCmdBlockBody, uint32 errHandling, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 __FSPrepareCmd(FSClientBody_t* fsClientBody, FSCmdBlockBody* fsCmdBlockBody, uint32 errHandling, FSAsyncParams* fsAsyncParams)
{
if (sFSInitialized == false || sFSShutdown == true)
return -0x400;
@@ -813,18 +810,18 @@ namespace coreinit
#define _FSCmdIntro() \
FSClientBody_t* fsClientBody = __FSGetClientBody(fsClient); \
- FSCmdBlockBody_t* fsCmdBlockBody = __FSGetCmdBlockBody(fsCmdBlock); \
+ FSCmdBlockBody* fsCmdBlockBody = __FSGetCmdBlockBody(fsCmdBlock); \
sint32 fsError = __FSPrepareCmd(fsClientBody, fsCmdBlockBody, errorMask, fsAsyncParams); \
if (fsError != 0) \
return fsError;
- void _debugVerifyCommand(const char* stage, FSCmdBlockBody_t* fsCmdBlockBody)
+ void _debugVerifyCommand(const char* stage, FSCmdBlockBody* fsCmdBlockBody)
{
if (fsCmdBlockBody->asyncResult.msgUnion.fsMsg.commandType != _swapEndianU32(8))
{
cemuLog_log(LogType::Force, "Corrupted FS command detected in stage {}", stage);
cemuLog_log(LogType::Force, "Printing CMD block: ");
- for (uint32 i = 0; i < (sizeof(FSCmdBlockBody_t) + 31) / 32; i++)
+ for (uint32 i = 0; i < (sizeof(FSCmdBlockBody) + 31) / 32; i++)
{
uint8* p = ((uint8*)fsCmdBlockBody) + i * 32;
cemuLog_log(LogType::Force, "{:04x}: {:02x} {:02x} {:02x} {:02x} - {:02x} {:02x} {:02x} {:02x} - {:02x} {:02x} {:02x} {:02x} - {:02x} {:02x} {:02x} {:02x} | {:02x} {:02x} {:02x} {:02x} - {:02x} {:02x} {:02x} {:02x} - {:02x} {:02x} {:02x} {:02x} - {:02x} {:02x} {:02x} {:02x}",
@@ -845,7 +842,7 @@ namespace coreinit
// a positive result (or zero) means success. Most operations return zero in case of success. Read and write operations return the number of transferred units
if (fsStatus >= 0)
{
- FSCmdBlockBody_t* fsCmdBlockBody = __FSGetCmdBlockBody(fsCmdBlock);
+ FSCmdBlockBody* fsCmdBlockBody = __FSGetCmdBlockBody(fsCmdBlock);
OSMessage msg;
OSReceiveMessage(&fsCmdBlockBody->syncTaskMsgQueue, &msg, OS_MESSAGE_BLOCK);
_debugVerifyCommand("handleAsyncResult", fsCmdBlockBody);
@@ -906,12 +903,12 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSOpenFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, FSFileHandleDepr_t* outFileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSOpenFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, FSFileHandlePtr outFileHandle, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
if (outFileHandle == nullptr || path == nullptr || mode == nullptr)
return -0x400;
- fsCmdBlockBody->returnValues.cmdOpenFile.handlePtr = &outFileHandle->fileHandle;
+ fsCmdBlockBody->returnValues.cmdOpenFile.handlePtr = outFileHandle;
fsError = (FSStatus)__FSPrepareCmd_OpenFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, path, mode, 0x660, 0, 0);
if (fsError != (FSStatus)FS_RESULT::SUCCESS)
return fsError;
@@ -919,15 +916,15 @@ namespace coreinit
return (FSStatus)FS_RESULT::SUCCESS;
}
- sint32 FSOpenFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, FSFileHandleDepr_t* fileHandle, uint32 errHandling)
+ sint32 FSOpenFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, FSFileHandlePtr outFileHandle, uint32 errHandling)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
- sint32 fsAsyncRet = FSOpenFileAsync(fsClient, fsCmdBlock, path, mode, fileHandle, errHandling, &asyncParams);
+ sint32 fsAsyncRet = FSOpenFileAsync(fsClient, fsCmdBlock, path, mode, outFileHandle, errHandling, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
}
- sint32 FSOpenFileExAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, uint32 createMode, uint32 openFlag, uint32 preallocSize, FSFileHandleDepr_t* outFileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSOpenFileExAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, uint32 createMode, uint32 openFlag, uint32 preallocSize, FSFileHandlePtr outFileHandle, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
if (openFlag != 0)
{
@@ -938,7 +935,7 @@ namespace coreinit
_FSCmdIntro();
if (outFileHandle == nullptr || path == nullptr || mode == nullptr)
return -0x400;
- fsCmdBlockBody->returnValues.cmdOpenFile.handlePtr = &outFileHandle->fileHandle;
+ fsCmdBlockBody->returnValues.cmdOpenFile.handlePtr = outFileHandle;
FSA_RESULT prepareResult = __FSPrepareCmd_OpenFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, path, mode, createMode, openFlag, preallocSize);
if (prepareResult != FSA_RESULT::OK)
@@ -948,11 +945,11 @@ namespace coreinit
return (FSStatus)FS_RESULT::SUCCESS;
}
- sint32 FSOpenFileEx(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, uint32 createMode, uint32 openFlag, uint32 preallocSize, FSFileHandleDepr_t* fileHandle, uint32 errHandling)
+ sint32 FSOpenFileEx(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, uint32 createMode, uint32 openFlag, uint32 preallocSize, FSFileHandlePtr outFileHandle, uint32 errHandling)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
- sint32 fsAsyncRet = FSOpenFileExAsync(fsClient, fsCmdBlock, path, mode, createMode, openFlag, preallocSize, fileHandle, errHandling, &asyncParams);
+ sint32 fsAsyncRet = FSOpenFileExAsync(fsClient, fsCmdBlock, path, mode, createMode, openFlag, preallocSize, outFileHandle, errHandling, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
}
@@ -970,7 +967,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSCloseFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSCloseFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
@@ -984,7 +981,7 @@ namespace coreinit
sint32 FSCloseFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errHandling)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSCloseFileAsync(fsClient, fsCmdBlock, fileHandle, errHandling, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
@@ -1004,7 +1001,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSFlushFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSFlushFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
@@ -1018,7 +1015,7 @@ namespace coreinit
sint32 FSFlushFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errHandling)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSFlushFileAsync(fsClient, fsCmdBlock, fileHandle, errHandling, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errHandling);
@@ -1060,7 +1057,7 @@ namespace coreinit
SysAllocator _tempFSSpace;
- sint32 __FSReadFileAsyncEx(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dest, uint32 size, uint32 count, bool usePos, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 __FSReadFileAsyncEx(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dest, uint32 size, uint32 count, bool usePos, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
if (size == 0 || count == 0 || dest == NULL)
@@ -1091,7 +1088,7 @@ namespace coreinit
return (FSStatus)FS_RESULT::SUCCESS;
}
- sint32 FSReadFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSReadFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
cemu_assert_debug(flag == 0); // todo
return __FSReadFileAsyncEx(fsClient, fsCmdBlock, dst, size, count, false, 0, fileHandle, flag, errorMask, fsAsyncParams);
@@ -1099,13 +1096,13 @@ namespace coreinit
sint32 FSReadFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSReadFileAsync(fsClient, fsCmdBlock, dst, size, count, fileHandle, flag, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
- sint32 FSReadFileWithPosAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSReadFileWithPosAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
cemu_assert_debug(flag == 0); // todo
sint32 fsStatus = __FSReadFileAsyncEx(fsClient, fsCmdBlock, dst, size, count, true, filePos, fileHandle, flag, errorMask, fsAsyncParams);
@@ -1114,7 +1111,7 @@ namespace coreinit
sint32 FSReadFileWithPos(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSReadFileWithPosAsync(fsClient, fsCmdBlock, dst, size, count, filePos, fileHandle, flag, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1154,7 +1151,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 __FSWriteFileWithPosAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dest, uint32 size, uint32 count, bool useFilePos, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 __FSWriteFileWithPosAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dest, uint32 size, uint32 count, bool useFilePos, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
if (size == 0 || count == 0 || dest == nullptr)
@@ -1185,27 +1182,27 @@ namespace coreinit
return (FSStatus)FS_RESULT::SUCCESS;
}
- sint32 FSWriteFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSWriteFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
return __FSWriteFileWithPosAsync(fsClient, fsCmdBlock, src, size, count, false, 0, fileHandle, flag, errorMask, fsAsyncParams);
}
sint32 FSWriteFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSWriteFileAsync(fsClient, fsCmdBlock, src, size, count, fileHandle, flag, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
- sint32 FSWriteFileWithPosAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSWriteFileWithPosAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
return __FSWriteFileWithPosAsync(fsClient, fsCmdBlock, src, size, count, true, filePos, fileHandle, flag, errorMask, fsAsyncParams);
}
sint32 FSWriteFileWithPos(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSWriteFileWithPosAsync(fsClient, fsCmdBlock, src, size, count, filePos, fileHandle, flag, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1224,7 +1221,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSSetPosFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 filePos, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSSetPosFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 filePos, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
FSA_RESULT prepareResult = __FSPrepareCmd_SetPosFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, fileHandle, filePos);
@@ -1237,7 +1234,7 @@ namespace coreinit
sint32 FSSetPosFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 filePos, uint32 errorMask)
{
// used by games: Mario Kart 8
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSSetPosFileAsync(fsClient, fsCmdBlock, fileHandle, filePos, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1254,7 +1251,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSGetPosFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32be* returnedFilePos, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSGetPosFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32be* returnedFilePos, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
// games using this: Darksiders Warmastered Edition
_FSCmdIntro();
@@ -1268,7 +1265,7 @@ namespace coreinit
sint32 FSGetPosFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32be* returnedFilePos, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSGetPosFileAsync(fsClient, fsCmdBlock, fileHandle, returnedFilePos, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1302,7 +1299,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSOpenDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, FSDirHandlePtr dirHandleOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSOpenDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, FSDirHandlePtr dirHandleOut, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
cemu_assert(dirHandleOut && path);
@@ -1316,7 +1313,7 @@ namespace coreinit
sint32 FSOpenDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, FSDirHandlePtr dirHandleOut, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSOpenDirAsync(fsClient, fsCmdBlock, path, dirHandleOut, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1333,7 +1330,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSReadDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, FSDirEntry_t* dirEntryOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSReadDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, FSDirEntry_t* dirEntryOut, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
FSA_RESULT prepareResult = __FSPrepareCmd_ReadDir(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, dirHandle);
@@ -1344,9 +1341,9 @@ namespace coreinit
return (FSStatus)FS_RESULT::SUCCESS;
}
- sint32 FSReadDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, FSDirEntry_t* dirEntryOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSReadDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, FSDirEntry_t* dirEntryOut, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSReadDirAsync(fsClient, fsCmdBlock, dirHandle, dirEntryOut, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1363,7 +1360,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSCloseDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSCloseDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
FSA_RESULT prepareResult = __FSPrepareCmd_CloseDir(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, dirHandle);
@@ -1376,7 +1373,7 @@ namespace coreinit
sint32 FSCloseDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSCloseDirAsync(fsClient, fsCmdBlock, dirHandle, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1396,7 +1393,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSRewindDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSRewindDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
FSA_RESULT prepareResult = __FSPrepareCmd_RewindDir(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, dirHandle);
@@ -1409,7 +1406,7 @@ namespace coreinit
sint32 FSRewindDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSRewindDirAsync(fsClient, fsCmdBlock, dirHandle, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1431,7 +1428,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSAppendFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 size, uint32 count, uint32 fileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSAppendFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 size, uint32 count, uint32 fileHandle, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
FSA_RESULT prepareResult = __FSPrepareCmd_AppendFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, size, count, fileHandle, 0);
@@ -1444,7 +1441,7 @@ namespace coreinit
sint32 FSAppendFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 size, uint32 count, uint32 fileHandle, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSAppendFileAsync(fsClient, fsCmdBlock, size, count, fileHandle, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1463,7 +1460,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSTruncateFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSTruncateFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
FSA_RESULT prepareResult = __FSPrepareCmd_TruncateFile(&fsCmdBlockBody->fsaShimBuffer, fsClientBody->iosuFSAHandle, fileHandle);
@@ -1476,7 +1473,7 @@ namespace coreinit
sint32 FSTruncateFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSTruncateFileAsync(fsClient, fsCmdBlock, fileHandle, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1521,7 +1518,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSRenameAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* srcPath, char* dstPath, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSRenameAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* srcPath, char* dstPath, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
// used by titles: XCX (via SAVERenameAsync)
_FSCmdIntro();
@@ -1540,7 +1537,7 @@ namespace coreinit
sint32 FSRename(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* srcPath, char* dstPath, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSRenameAsync(fsClient, fsCmdBlock, srcPath, dstPath, errorMask, asyncParams.GetPointer());
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1572,7 +1569,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSRemoveAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* filePath, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSRemoveAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* filePath, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
// used by titles: XCX (via SAVERemoveAsync)
_FSCmdIntro();
@@ -1591,7 +1588,7 @@ namespace coreinit
sint32 FSRemove(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* filePath, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSRemoveAsync(fsClient, fsCmdBlock, filePath, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1624,7 +1621,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSMakeDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* dirPath, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSMakeDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* dirPath, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
// used by titles: XCX (via SAVEMakeDirAsync)
_FSCmdIntro();
@@ -1643,7 +1640,7 @@ namespace coreinit
sint32 FSMakeDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSMakeDirAsync(fsClient, fsCmdBlock, path, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1674,7 +1671,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSChangeDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSChangeDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
if (path == NULL)
@@ -1692,7 +1689,7 @@ namespace coreinit
sint32 FSChangeDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSChangeDirAsync(fsClient, fsCmdBlock, path, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1710,7 +1707,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSGetCwdAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* dirPathOut, sint32 dirPathMaxLen, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSGetCwdAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* dirPathOut, sint32 dirPathMaxLen, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
// used by titles: Super Mario Maker
_FSCmdIntro();
@@ -1727,7 +1724,7 @@ namespace coreinit
sint32 FSGetCwd(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* dirPathOut, sint32 dirPathMaxLen, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSGetCwdAsync(fsClient, fsCmdBlock, dirPathOut, dirPathMaxLen, errorMask, &asyncParams);
auto r = __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1758,7 +1755,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSFlushQuotaAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSFlushQuotaAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
@@ -1772,7 +1769,7 @@ namespace coreinit
sint32 FSFlushQuota(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSFlushQuotaAsync(fsClient, fsCmdBlock, path, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1808,7 +1805,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 __FSQueryInfoAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* queryString, uint32 queryType, void* queryResult, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 __FSQueryInfoAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* queryString, uint32 queryType, void* queryResult, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
cemu_assert(queryString && queryResult); // query string and result must not be null
@@ -1822,7 +1819,7 @@ namespace coreinit
return (FSStatus)FS_RESULT::SUCCESS;
}
- sint32 FSGetStatAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSStat_t* statOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSGetStatAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSStat_t* statOut, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
sint32 fsStatus = __FSQueryInfoAsync(fsClient, fsCmdBlock, (uint8*)path, FSA_QUERY_TYPE_STAT, statOut, errorMask, fsAsyncParams);
return fsStatus;
@@ -1830,7 +1827,7 @@ namespace coreinit
sint32 FSGetStat(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSStat_t* statOut, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSGetStatAsync(fsClient, fsCmdBlock, path, statOut, errorMask, &asyncParams);
sint32 ret = __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1851,7 +1848,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSGetStatFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, FSStat_t* statOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSGetStatFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, FSStat_t* statOut, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
_FSCmdIntro();
cemu_assert(statOut); // statOut must not be null
@@ -1867,13 +1864,13 @@ namespace coreinit
sint32 FSGetStatFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSFileHandle2 fileHandle, FSStat_t* statOut, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSGetStatFileAsync(fsClient, fsCmdBlock, fileHandle, statOut, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
}
- sint32 FSGetFreeSpaceSizeAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSLargeSize* returnedFreeSize, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSGetFreeSpaceSizeAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSLargeSize* returnedFreeSize, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
// used by: Wii U system settings app, Art Academy, Unity (e.g. Snoopy's Grand Adventure), Super Smash Bros
sint32 fsStatus = __FSQueryInfoAsync(fsClient, fsCmdBlock, (uint8*)path, FSA_QUERY_TYPE_FREESPACE, returnedFreeSize, errorMask, fsAsyncParams);
@@ -1882,7 +1879,7 @@ namespace coreinit
sint32 FSGetFreeSpaceSize(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSLargeSize* returnedFreeSize, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSGetFreeSpaceSizeAsync(fsClient, fsCmdBlock, path, returnedFreeSize, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1902,7 +1899,7 @@ namespace coreinit
return FSA_RESULT::OK;
}
- sint32 FSIsEofAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams)
+ sint32 FSIsEofAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask, FSAsyncParams* fsAsyncParams)
{
// used by Paper Monsters Recut
_FSCmdIntro();
@@ -1917,7 +1914,7 @@ namespace coreinit
sint32 FSIsEof(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask)
{
- StackAllocator asyncParams;
+ StackAllocator asyncParams;
__FSAsyncToSyncInit(fsClient, fsCmdBlock, &asyncParams);
sint32 fsAsyncRet = FSIsEofAsync(fsClient, fsCmdBlock, fileHandle, errorMask, &asyncParams);
return __FSProcessAsyncResult(fsClient, fsCmdBlock, fsAsyncRet, errorMask);
@@ -1925,14 +1922,14 @@ namespace coreinit
void FSSetUserData(FSCmdBlock_t* fsCmdBlock, void* userData)
{
- FSCmdBlockBody_t* fsCmdBlockBody = __FSGetCmdBlockBody(fsCmdBlock);
+ FSCmdBlockBody* fsCmdBlockBody = __FSGetCmdBlockBody(fsCmdBlock);
if (fsCmdBlockBody)
fsCmdBlockBody->userData = userData;
}
void* FSGetUserData(FSCmdBlock_t* fsCmdBlock)
{
- FSCmdBlockBody_t* fsCmdBlockBody = __FSGetCmdBlockBody(fsCmdBlock);
+ FSCmdBlockBody* fsCmdBlockBody = __FSGetCmdBlockBody(fsCmdBlock);
void* userData = nullptr;
if (fsCmdBlockBody)
userData = fsCmdBlockBody->userData.GetPtr();
@@ -1956,7 +1953,7 @@ namespace coreinit
FSClientBody_t* fsClientBody = __FSGetClientBody(fsClient);
if (!fsClientBody)
return nullptr;
- FSCmdBlockBody_t* cmdBlockBody = fsClientBody->currentCmdBlockBody;
+ FSCmdBlockBody* cmdBlockBody = fsClientBody->currentCmdBlockBody;
if (!cmdBlockBody)
return nullptr;
return cmdBlockBody->selfCmdBlock;
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FS.h b/src/Cafe/OS/libs/coreinit/coreinit_FS.h
index 2a57f7da..bf12e33c 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_FS.h
+++ b/src/Cafe/OS/libs/coreinit/coreinit_FS.h
@@ -5,33 +5,23 @@
#include "Cafe/IOSU/fsa/iosu_fsa.h"
#include "coreinit_MessageQueue.h"
-typedef struct
-{
- uint32be fileHandle;
-} FSFileHandleDepr_t;
-
+typedef MEMPTR> FSFileHandlePtr;
typedef MEMPTR> FSDirHandlePtr;
typedef uint32 FSAClientHandle;
-typedef struct
+struct FSAsyncParams
{
MEMPTR userCallback;
MEMPTR userContext;
MEMPTR ioMsgQueue;
-} FSAsyncParamsNew_t;
-
-static_assert(sizeof(FSAsyncParamsNew_t) == 0xC);
-
-typedef struct
-{
- MPTR userCallback; // 0x96C
- MPTR userContext;
- MPTR ioMsgQueue;
-} FSAsyncParams_t; // legacy struct. Replace with FSAsyncParamsNew_t
+};
+static_assert(sizeof(FSAsyncParams) == 0xC);
namespace coreinit
{
+ struct FSCmdBlockBody;
+
struct FSCmdQueue
{
enum class QUEUE_FLAG : uint32
@@ -40,8 +30,8 @@ namespace coreinit
CANCEL_ALL = (1 << 4),
};
- /* +0x00 */ MPTR firstMPTR;
- /* +0x04 */ MPTR lastMPTR;
+ /* +0x00 */ MEMPTR first;
+ /* +0x04 */ MEMPTR last;
/* +0x08 */ OSFastMutex fastMutex;
/* +0x34 */ MPTR dequeueHandlerFuncMPTR;
/* +0x38 */ uint32be numCommandsInFlight;
@@ -108,7 +98,7 @@ namespace coreinit
uint8 ukn1460[0x10];
uint8 ukn1470[0x10];
FSCmdQueue fsCmdQueue;
- /* +0x14C4 */ MEMPTR currentCmdBlockBody; // set to currently active cmd
+ /* +0x14C4 */ MEMPTR currentCmdBlockBody; // set to currently active cmd
uint32 ukn14C8;
uint32 ukn14CC;
uint8 ukn14D0[0x10];
@@ -128,7 +118,7 @@ namespace coreinit
struct FSAsyncResult
{
- /* +0x00 */ FSAsyncParamsNew_t fsAsyncParamsNew;
+ /* +0x00 */ FSAsyncParams fsAsyncParamsNew;
// fs message storage
struct FSMessage
@@ -159,7 +149,7 @@ namespace coreinit
uint8 ukn0[0x14];
struct
{
- MEMPTR handlePtr;
+ MEMPTR> handlePtr;
} cmdOpenFile;
struct
{
@@ -205,7 +195,7 @@ namespace coreinit
static_assert(sizeof(FSCmdBlockReturnValues_t) == 0x14);
- struct FSCmdBlockBody_t
+ struct FSCmdBlockBody
{
iosu::fsa::FSAShimBuffer fsaShimBuffer;
/* +0x0938 */ MEMPTR fsClientBody;
@@ -213,9 +203,8 @@ namespace coreinit
/* +0x0940 */ uint32be cancelState; // bitmask. Bit 0 -> If set command has been canceled
FSCmdBlockReturnValues_t returnValues;
// link for cmd queue
- MPTR nextMPTR; // points towards FSCmdQueue->first
- MPTR previousMPTR; // points towards FSCmdQueue->last
-
+ MEMPTR next;
+ MEMPTR previous;
/* +0x960 */ betype lastFSAStatus;
uint32 ukn0964;
/* +0x0968 */ uint8 errHandling; // return error flag mask
@@ -235,7 +224,6 @@ namespace coreinit
uint32 ukn9FC;
};
- static_assert(sizeof(FSAsyncParams_t) == 0xC);
static_assert(sizeof(FSCmdBlock_t) == 0xA80);
#define FSA_CMD_FLAG_SET_POS (1 << 0)
@@ -251,7 +239,7 @@ namespace coreinit
};
// internal interface
- sint32 __FSQueryInfoAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* queryString, uint32 queryType, void* queryResult, uint32 errHandling, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 __FSQueryInfoAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* queryString, uint32 queryType, void* queryResult, uint32 errHandling, FSAsyncParams* fsAsyncParams);
// coreinit exports
FS_RESULT FSAddClientEx(FSClient_t* fsClient, uint32 uknR4, uint32 errHandling);
@@ -260,52 +248,52 @@ namespace coreinit
void FSInitCmdBlock(FSCmdBlock_t* fsCmdBlock);
- sint32 FSOpenFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, FSFileHandleDepr_t* fileHandle, uint32 errHandling, FSAsyncParamsNew_t* asyncParams);
- sint32 FSOpenFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, FSFileHandleDepr_t* fileHandle, uint32 errHandling);
+ sint32 FSOpenFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, FSFileHandlePtr outFileHandle, uint32 errHandling, FSAsyncParams* asyncParams);
+ sint32 FSOpenFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, char* mode, FSFileHandlePtr outFileHandle, uint32 errHandling);
- sint32 FSReadFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSReadFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSReadFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask);
- sint32 FSReadFileWithPosAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSReadFileWithPosAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSReadFileWithPos(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dst, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask);
- sint32 FSWriteFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSWriteFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSWriteFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 fileHandle, uint32 flag, uint32 errorMask);
- sint32 FSWriteFileWithPosAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSWriteFileWithPosAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSWriteFileWithPos(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* src, uint32 size, uint32 count, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask);
- sint32 FSSetPosFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 filePos, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSSetPosFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 filePos, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSSetPosFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 filePos, uint32 errorMask);
- sint32 FSGetPosFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32be* returnedFilePos, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSGetPosFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32be* returnedFilePos, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSGetPosFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32be* returnedFilePos, uint32 errorMask);
- sint32 FSAppendFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 size, uint32 count, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSAppendFileAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 size, uint32 count, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSAppendFile(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 size, uint32 count, uint32 errorMask);
- sint32 FSIsEofAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSIsEofAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSIsEof(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint32 fileHandle, uint32 errorMask);
- sint32 FSRenameAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* srcPath, char* dstPath, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSRenameAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* srcPath, char* dstPath, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSRename(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* srcPath, char* dstPath, uint32 errorMask);
- sint32 FSRemoveAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* filePath, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSRemoveAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* filePath, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSRemove(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, uint8* filePath, uint32 errorMask);
- sint32 FSMakeDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* dirPath, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSMakeDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* dirPath, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSMakeDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, uint32 errorMask);
- sint32 FSChangeDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSChangeDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSChangeDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask);
- sint32 FSGetCwdAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* dirPathOut, sint32 dirPathMaxLen, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSGetCwdAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* dirPathOut, sint32 dirPathMaxLen, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSGetCwd(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* dirPathOut, sint32 dirPathMaxLen, uint32 errorMask);
- sint32 FSGetFreeSpaceSizeAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSLargeSize* returnedFreeSize, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSGetFreeSpaceSizeAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSLargeSize* returnedFreeSize, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSGetFreeSpaceSize(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, const char* path, FSLargeSize* returnedFreeSize, uint32 errorMask);
- sint32 FSOpenDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, FSDirHandlePtr dirHandleOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSOpenDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, FSDirHandlePtr dirHandleOut, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSOpenDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, FSDirHandlePtr dirHandleOut, uint32 errorMask);
- sint32 FSReadDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, FSDirEntry_t* dirEntryOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
- sint32 FSReadDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, FSDirEntry_t* dirEntryOut, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
- sint32 FSCloseDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSReadDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, FSDirEntry_t* dirEntryOut, uint32 errorMask, FSAsyncParams* fsAsyncParams);
+ sint32 FSReadDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, FSDirEntry_t* dirEntryOut, uint32 errorMask, FSAsyncParams* fsAsyncParams);
+ sint32 FSCloseDirAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSCloseDir(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, FSDirHandle2 dirHandle, uint32 errorMask);
- sint32 FSFlushQuotaAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask, FSAsyncParamsNew_t* fsAsyncParams);
+ sint32 FSFlushQuotaAsync(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask, FSAsyncParams* fsAsyncParams);
sint32 FSFlushQuota(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, char* path, uint32 errorMask);
FS_VOLSTATE FSGetVolumeState(FSClient_t* fsClient);
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp b/src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp
index dc82f772..83658f3c 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp
@@ -128,7 +128,7 @@ namespace coreinit
{
MEMPTR memBound;
uint32be memBoundSize;
- OSGetMemBound(1, (MPTR*)memBound.GetBEPtr(), (uint32*)&memBoundSize);
+ OSGetMemBound(1, &memBound, &memBoundSize);
MEMPTR bucket;
uint32be bucketSize;
@@ -257,7 +257,7 @@ namespace coreinit
{
MEMPTR memBound;
uint32be memBoundSize;
- OSGetMemBound(1, (MPTR*)memBound.GetBEPtr(), (uint32*)&memBoundSize);
+ OSGetMemBound(1, &memBound, &memBoundSize);
MEMPTR bucket;
uint32be bucketSize;
@@ -593,16 +593,16 @@ namespace coreinit
{
MEMPTR memBound;
uint32be memBoundSize;
- OSGetMemBound(1, (MPTR*)memBound.GetBEPtr(), (uint32*)&memBoundSize);
+ OSGetMemBound(1, &memBound, &memBoundSize);
mem1Heap = MEMCreateFrmHeapEx(memBound.GetPtr(), (uint32)memBoundSize, 0);
- OSGetForegroundBucketFreeArea((MPTR*)memBound.GetBEPtr(), (MPTR*)&memBoundSize);
+ OSGetForegroundBucketFreeArea(&memBound, &memBoundSize);
memFGHeap = MEMCreateFrmHeapEx(memBound.GetPtr(), (uint32)memBoundSize, 0);
}
MEMPTR memBound;
uint32be memBoundSize;
- OSGetMemBound(2, (MPTR*)memBound.GetBEPtr(), (uint32*)&memBoundSize);
+ OSGetMemBound(2, &memBound, &memBoundSize);
mem2Heap = MEMDefaultHeap_Init(memBound.GetPtr(), (uint32)memBoundSize);
// set DynLoad allocators
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Memory.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Memory.cpp
index cff4ee2b..80ec212d 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Memory.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Memory.cpp
@@ -131,7 +131,7 @@ namespace coreinit
// no-op
}
- void OSGetMemBound(sint32 memType, MPTR* offsetOutput, uint32* sizeOutput)
+ void OSGetMemBound(sint32 memType, MEMPTR* offsetOutput, uint32be* sizeOutput)
{
MPTR memAddr = MPTR_NULL;
uint32 memSize = 0;
@@ -195,9 +195,9 @@ namespace coreinit
cemu_assert_debug(false);
}
if (offsetOutput)
- *offsetOutput = _swapEndianU32(memAddr);
+ *offsetOutput = memAddr;
if (sizeOutput)
- *sizeOutput = _swapEndianU32(memSize);
+ *sizeOutput = memSize;
}
void InitializeMemory()
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Memory.h b/src/Cafe/OS/libs/coreinit/coreinit_Memory.h
index 0a212f61..62c9f135 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Memory.h
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Memory.h
@@ -4,7 +4,7 @@ namespace coreinit
{
void InitializeMemory();
- void OSGetMemBound(sint32 memType, MPTR* offsetOutput, uint32* sizeOutput);
+ void OSGetMemBound(sint32 memType, MEMPTR* offsetOutput, uint32be* sizeOutput);
void* OSBlockMove(MEMPTR dst, MEMPTR src, uint32 size, bool flushDC);
void* OSBlockSet(MEMPTR dst, uint32 value, uint32 size);
diff --git a/src/Cafe/OS/libs/nlibcurl/nlibcurl.cpp b/src/Cafe/OS/libs/nlibcurl/nlibcurl.cpp
index 0268c7df..7a8eacb7 100644
--- a/src/Cafe/OS/libs/nlibcurl/nlibcurl.cpp
+++ b/src/Cafe/OS/libs/nlibcurl/nlibcurl.cpp
@@ -1401,12 +1401,10 @@ void export_curl_easy_getinfo(PPCInterpreter_t* hCPU)
}
case CURLINFO_CONTENT_TYPE:
{
- //cemuLog_logDebug(LogType::Force, "CURLINFO_CONTENT_TYPE not supported");
- //*(uint32*)parameter.GetPtr() = MPTR_NULL;
char* contentType = nullptr;
result = curl_easy_getinfo(curlObj, CURLINFO_REDIRECT_URL, &contentType);
_updateGuestString(curl.GetPtr(), curl->info_contentType, contentType);
- *(uint32*)parameter.GetPtr() = curl->info_contentType.GetMPTRBE();
+ *(MEMPTR*)parameter.GetPtr() = curl->info_contentType;
break;
}
case CURLINFO_REDIRECT_URL:
@@ -1414,7 +1412,7 @@ void export_curl_easy_getinfo(PPCInterpreter_t* hCPU)
char* redirectUrl = nullptr;
result = curl_easy_getinfo(curlObj, CURLINFO_REDIRECT_URL, &redirectUrl);
_updateGuestString(curl.GetPtr(), curl->info_redirectUrl, redirectUrl);
- *(uint32*)parameter.GetPtr() = curl->info_redirectUrl.GetMPTRBE();
+ *(MEMPTR*)parameter.GetPtr() = curl->info_redirectUrl;
break;
}
default:
diff --git a/src/Cafe/OS/libs/nn_save/nn_save.cpp b/src/Cafe/OS/libs/nn_save/nn_save.cpp
index 05e49438..518e4195 100644
--- a/src/Cafe/OS/libs/nn_save/nn_save.cpp
+++ b/src/Cafe/OS/libs/nn_save/nn_save.cpp
@@ -320,7 +320,7 @@ namespace save
return SAVE_STATUS_OK;
}
- SAVEStatus SAVERemoveAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVERemoveAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
SAVEStatus result = (FSStatus)(FS_RESULT::FATAL_ERROR);
@@ -331,7 +331,7 @@ namespace save
{
char fullPath[SAVE_MAX_PATH_SIZE];
if (GetAbsoluteFullPath(persistentId, path, fullPath))
- result = coreinit::FSRemoveAsync(client, block, (uint8*)fullPath, errHandling, (FSAsyncParamsNew_t*)asyncParams);
+ result = coreinit::FSRemoveAsync(client, block, (uint8*)fullPath, errHandling, (FSAsyncParams*)asyncParams);
}
else
result = (FSStatus)FS_RESULT::NOT_FOUND;
@@ -340,7 +340,7 @@ namespace save
return result;
}
- SAVEStatus SAVEMakeDirAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEMakeDirAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
SAVEStatus result = (FSStatus)(FS_RESULT::FATAL_ERROR);
@@ -351,7 +351,7 @@ namespace save
{
char fullPath[SAVE_MAX_PATH_SIZE];
if (GetAbsoluteFullPath(persistentId, path, fullPath))
- result = coreinit::FSMakeDirAsync(client, block, fullPath, errHandling, (FSAsyncParamsNew_t*)asyncParams);
+ result = coreinit::FSMakeDirAsync(client, block, fullPath, errHandling, (FSAsyncParams*)asyncParams);
}
else
result = (FSStatus)FS_RESULT::NOT_FOUND;
@@ -361,7 +361,7 @@ namespace save
return result;
}
- SAVEStatus SAVEOpenDirAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FSDirHandlePtr hDir, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEOpenDirAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FSDirHandlePtr hDir, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
SAVEStatus result = (FSStatus)(FS_RESULT::FATAL_ERROR);
@@ -372,7 +372,7 @@ namespace save
{
char fullPath[SAVE_MAX_PATH_SIZE];
if (GetAbsoluteFullPath(persistentId, path, fullPath))
- result = coreinit::FSOpenDirAsync(client, block, fullPath, hDir, errHandling, (FSAsyncParamsNew_t*)asyncParams);
+ result = coreinit::FSOpenDirAsync(client, block, fullPath, hDir, errHandling, (FSAsyncParams*)asyncParams);
}
else
@@ -383,7 +383,7 @@ namespace save
return result;
}
- SAVEStatus SAVEOpenFileAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, const char* mode, FSFileHandleDepr_t* hFile, FS_ERROR_MASK errHandling, const FSAsyncParamsNew_t* asyncParams)
+ SAVEStatus SAVEOpenFileAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, const char* mode, FSFileHandlePtr outFileHandle, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
SAVEStatus result = (FSStatus)(FS_RESULT::FATAL_ERROR);
@@ -394,7 +394,7 @@ namespace save
{
char fullPath[SAVE_MAX_PATH_SIZE];
if (GetAbsoluteFullPath(persistentId, path, fullPath))
- result = coreinit::FSOpenFileAsync(client, block, fullPath, (char*)mode, hFile, errHandling, (FSAsyncParamsNew_t*)asyncParams);
+ result = coreinit::FSOpenFileAsync(client, block, fullPath, (char*)mode, outFileHandle, errHandling, (FSAsyncParams*)asyncParams);
}
else
result = (FSStatus)FS_RESULT::NOT_FOUND;
@@ -404,7 +404,7 @@ namespace save
return result;
}
- SAVEStatus SAVEOpenFileOtherApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint64 titleId, uint8 accountSlot, const char* path, const char* mode, FSFileHandleDepr_t* hFile, FS_ERROR_MASK errHandling, const FSAsyncParamsNew_t* asyncParams)
+ SAVEStatus SAVEOpenFileOtherApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint64 titleId, uint8 accountSlot, const char* path, const char* mode, FSFileHandlePtr outFileHandle, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
if (strcmp(mode, "r") != 0)
return (SAVEStatus)(FS_RESULT::PERMISSION_ERROR);
@@ -418,7 +418,7 @@ namespace save
{
char fullPath[SAVE_MAX_PATH_SIZE];
if (GetAbsoluteFullPathOtherApplication(persistentId, titleId, path, fullPath))
- result = coreinit::FSOpenFileAsync(client, block, fullPath, (char*)mode, hFile, errHandling, (FSAsyncParamsNew_t*)asyncParams);
+ result = coreinit::FSOpenFileAsync(client, block, fullPath, (char*)mode, outFileHandle, errHandling, (FSAsyncParams*)asyncParams);
}
else
result = (FSStatus)FS_RESULT::NOT_FOUND;
@@ -428,26 +428,10 @@ namespace save
return result;
}
- void export_SAVEOpenFileOtherApplicationAsync(PPCInterpreter_t* hCPU)
- {
- ppcDefineParamMEMPTR(fsClient, coreinit::FSClient_t, 0);
- ppcDefineParamMEMPTR(fsCmdBlock, coreinit::FSCmdBlock_t, 1);
- ppcDefineParamU64(titleId, 2);
- ppcDefineParamU8(accountSlot, 4);
- ppcDefineParamMEMPTR(path, const char, 5);
- ppcDefineParamMEMPTR(mode, const char, 6);
- ppcDefineParamMEMPTR(hFile, FSFileHandleDepr_t, 7);
- ppcDefineParamU32(errHandling, 8);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParamsNew_t, 9);
-
- const SAVEStatus result = SAVEOpenFileOtherApplicationAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), titleId, accountSlot, path.GetPtr(), mode.GetPtr(), hFile.GetPtr(), errHandling, asyncParams.GetPtr());
- osLib_returnFromFunction(hCPU, result);
- }
-
- SAVEStatus SAVEOpenFileOtherApplication(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint64 titleId, uint8 accountSlot, const char* path, const char* mode, FSFileHandleDepr_t* hFile, FS_ERROR_MASK errHandling)
+ SAVEStatus SAVEOpenFileOtherApplication(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint64 titleId, uint8 accountSlot, const char* path, const char* mode, FSFileHandlePtr outFileHandle, FS_ERROR_MASK errHandling)
{
MEMPTR currentThread{coreinit::OSGetCurrentThread()};
- FSAsyncParamsNew_t asyncParams;
+ FSAsyncParams asyncParams;
asyncParams.ioMsgQueue = nullptr;
asyncParams.userCallback = PPCInterpreter_makeCallableExportDepr(AsyncCallback);
@@ -456,7 +440,7 @@ namespace save
param->returnStatus = (FSStatus)FS_RESULT::SUCCESS;
asyncParams.userContext = param.GetPointer();
- SAVEStatus status = SAVEOpenFileOtherApplicationAsync(client, block, titleId, accountSlot, path, mode, hFile, errHandling, &asyncParams);
+ SAVEStatus status = SAVEOpenFileOtherApplicationAsync(client, block, titleId, accountSlot, path, mode, outFileHandle, errHandling, &asyncParams);
if (status == (FSStatus)FS_RESULT::SUCCESS)
{
coreinit_suspendThread(currentThread, 1000);
@@ -467,113 +451,31 @@ namespace save
return status;
}
- void export_SAVEOpenFileOtherApplication(PPCInterpreter_t* hCPU)
- {
- ppcDefineParamMEMPTR(fsClient, coreinit::FSClient_t, 0);
- ppcDefineParamMEMPTR(fsCmdBlock, coreinit::FSCmdBlock_t, 1);
- ppcDefineParamU64(titleId, 2);
- ppcDefineParamU8(accountSlot, 4);
- ppcDefineParamMEMPTR(path, const char, 5);
- ppcDefineParamMEMPTR(mode, const char, 6);
- ppcDefineParamMEMPTR(hFile, FSFileHandleDepr_t, 7);
- ppcDefineParamU32(errHandling, 8);
-
- const SAVEStatus result = SAVEOpenFileOtherApplication(fsClient.GetPtr(), fsCmdBlock.GetPtr(), titleId, accountSlot, path.GetPtr(), mode.GetPtr(), hFile.GetPtr(), errHandling);
- osLib_returnFromFunction(hCPU, result);
- }
-
- SAVEStatus SAVEOpenFileOtherNormalApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 accountSlot, const char* path, const char* mode, FSFileHandleDepr_t* hFile, FS_ERROR_MASK errHandling, const FSAsyncParamsNew_t* asyncParams)
+ SAVEStatus SAVEOpenFileOtherNormalApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 accountSlot, const char* path, const char* mode, FSFileHandlePtr outFileHandle, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
uint64 titleId = SAVE_UNIQUE_TO_TITLE_ID(uniqueId);
- return SAVEOpenFileOtherApplicationAsync(client, block, titleId, accountSlot, path, mode, hFile, errHandling, asyncParams);
+ return SAVEOpenFileOtherApplicationAsync(client, block, titleId, accountSlot, path, mode, outFileHandle, errHandling, asyncParams);
}
- void export_SAVEOpenFileOtherNormalApplicationAsync(PPCInterpreter_t* hCPU)
+ SAVEStatus SAVEOpenFileOtherNormalApplication(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 accountSlot, const char* path, const char* mode, FSFileHandlePtr outFileHandle, FS_ERROR_MASK errHandling)
{
- ppcDefineParamMEMPTR(fsClient, coreinit::FSClient_t, 0);
- ppcDefineParamMEMPTR(fsCmdBlock, coreinit::FSCmdBlock_t, 1);
- ppcDefineParamU32(uniqueId, 2);
- ppcDefineParamU8(accountSlot, 3);
- ppcDefineParamMEMPTR(path, const char, 4);
- ppcDefineParamMEMPTR(mode, const char, 5);
- ppcDefineParamMEMPTR(hFile, FSFileHandleDepr_t, 6);
- ppcDefineParamU32(errHandling, 7);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParamsNew_t, 8);
-
- const SAVEStatus result = SAVEOpenFileOtherNormalApplicationAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), uniqueId, accountSlot, path.GetPtr(), mode.GetPtr(), hFile.GetPtr(), errHandling, asyncParams.GetPtr());
- osLib_returnFromFunction(hCPU, result);
- }
- SAVEStatus SAVEOpenFileOtherNormalApplication(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 accountSlot, const char* path, const char* mode, FSFileHandleDepr_t* hFile, FS_ERROR_MASK errHandling)
- {
- //peterBreak();
-
uint64 titleId = SAVE_UNIQUE_TO_TITLE_ID(uniqueId);
- return SAVEOpenFileOtherApplication(client, block, titleId, accountSlot, path, mode, hFile, errHandling);
+ return SAVEOpenFileOtherApplication(client, block, titleId, accountSlot, path, mode, outFileHandle, errHandling);
}
- void export_SAVEOpenFileOtherNormalApplication(PPCInterpreter_t* hCPU)
- {
- ppcDefineParamMEMPTR(fsClient, coreinit::FSClient_t, 0);
- ppcDefineParamMEMPTR(fsCmdBlock, coreinit::FSCmdBlock_t, 1);
- ppcDefineParamU32(uniqueId, 2);
- ppcDefineParamU8(accountSlot, 3);
- ppcDefineParamMEMPTR(path, const char, 4);
- ppcDefineParamMEMPTR(mode, const char, 5);
- ppcDefineParamMEMPTR(hFile, FSFileHandleDepr_t, 6);
- ppcDefineParamU32(errHandling, 7);
-
- const SAVEStatus result = SAVEOpenFileOtherNormalApplication(fsClient.GetPtr(), fsCmdBlock.GetPtr(), uniqueId, accountSlot, path.GetPtr(), mode.GetPtr(), hFile.GetPtr(), errHandling);
- osLib_returnFromFunction(hCPU, result);
- }
-
- SAVEStatus SAVEOpenFileOtherNormalApplicationVariationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 variation, uint8 accountSlot, const char* path, const char* mode, FSFileHandleDepr_t* hFile, FS_ERROR_MASK errHandling, const FSAsyncParamsNew_t* asyncParams)
- {
- //peterBreak();
-
- uint64 titleId = SAVE_UNIQUE_TO_TITLE_ID_VARIATION(uniqueId, variation);
- return SAVEOpenFileOtherApplicationAsync(client, block, titleId, accountSlot, path, mode, hFile, errHandling, asyncParams);
- }
-
- void export_SAVEOpenFileOtherNormalApplicationVariationAsync(PPCInterpreter_t* hCPU)
- {
- ppcDefineParamMEMPTR(fsClient, coreinit::FSClient_t, 0);
- ppcDefineParamMEMPTR(fsCmdBlock, coreinit::FSCmdBlock_t, 1);
- ppcDefineParamU32(uniqueId, 2);
- ppcDefineParamU8(variation, 3);
- ppcDefineParamU8(accountSlot, 4);
- ppcDefineParamMEMPTR(path, const char, 5);
- ppcDefineParamMEMPTR(mode, const char, 6);
- ppcDefineParamMEMPTR(hFile, FSFileHandleDepr_t, 7);
- ppcDefineParamU32(errHandling, 8);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParamsNew_t, 9);
-
- const SAVEStatus result = SAVEOpenFileOtherNormalApplicationVariationAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), uniqueId, variation, accountSlot, path.GetPtr(), mode.GetPtr(), hFile.GetPtr(), errHandling, asyncParams.GetPtr());
- osLib_returnFromFunction(hCPU, result);
- }
-
- SAVEStatus SAVEOpenFileOtherNormalApplicationVariation(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 variation, uint8 accountSlot, const char* path, const char* mode, FSFileHandleDepr_t* hFile, FS_ERROR_MASK errHandling)
+ SAVEStatus SAVEOpenFileOtherNormalApplicationVariationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 variation, uint8 accountSlot, const char* path, const char* mode, FSFileHandlePtr outFileHandle, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
uint64 titleId = SAVE_UNIQUE_TO_TITLE_ID_VARIATION(uniqueId, variation);
- return SAVEOpenFileOtherApplication(client, block, titleId, accountSlot, path, mode, hFile, errHandling);
+ return SAVEOpenFileOtherApplicationAsync(client, block, titleId, accountSlot, path, mode, outFileHandle, errHandling, asyncParams);
}
- void export_SAVEOpenFileOtherNormalApplicationVariation(PPCInterpreter_t* hCPU)
+ SAVEStatus SAVEOpenFileOtherNormalApplicationVariation(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 variation, uint8 accountSlot, const char* path, const char* mode, FSFileHandlePtr outFileHandle, FS_ERROR_MASK errHandling)
{
- ppcDefineParamMEMPTR(fsClient, coreinit::FSClient_t, 0);
- ppcDefineParamMEMPTR(fsCmdBlock, coreinit::FSCmdBlock_t, 1);
- ppcDefineParamU32(uniqueId, 2);
- ppcDefineParamU8(variation, 3);
- ppcDefineParamU8(accountSlot, 4);
- ppcDefineParamMEMPTR(path, const char, 5);
- ppcDefineParamMEMPTR(mode, const char, 6);
- ppcDefineParamMEMPTR(hFile, FSFileHandleDepr_t, 7);
- ppcDefineParamU32(errHandling, 8);
-
- const SAVEStatus result = SAVEOpenFileOtherNormalApplicationVariation(fsClient.GetPtr(), fsCmdBlock.GetPtr(), uniqueId, variation, accountSlot, path.GetPtr(), mode.GetPtr(), hFile.GetPtr(), errHandling);
- osLib_returnFromFunction(hCPU, result);
+ uint64 titleId = SAVE_UNIQUE_TO_TITLE_ID_VARIATION(uniqueId, variation);
+ return SAVEOpenFileOtherApplication(client, block, titleId, accountSlot, path, mode, outFileHandle, errHandling);
}
- SAVEStatus SAVEGetFreeSpaceSizeAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, FSLargeSize* freeSize, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEGetFreeSpaceSizeAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, FSLargeSize* freeSize, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
SAVEStatus result = (FSStatus)(FS_RESULT::FATAL_ERROR);
@@ -583,9 +485,8 @@ namespace save
if (GetPersistentIdEx(accountSlot, &persistentId))
{
char fullPath[SAVE_MAX_PATH_SIZE];
- // usually a pointer with '\0' instead of nullptr, but it's basically the same
if (GetAbsoluteFullPath(persistentId, nullptr, fullPath))
- result = coreinit::FSGetFreeSpaceSizeAsync(client, block, fullPath, freeSize, errHandling, (FSAsyncParamsNew_t*)asyncParams);
+ result = coreinit::FSGetFreeSpaceSizeAsync(client, block, fullPath, freeSize, errHandling, (FSAsyncParams*)asyncParams);
}
else
result = (FSStatus)FS_RESULT::NOT_FOUND;
@@ -595,7 +496,7 @@ namespace save
return result;
}
- SAVEStatus SAVEGetStatAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEGetStatAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
SAVEStatus result = (FSStatus)(FS_RESULT::FATAL_ERROR);
@@ -606,7 +507,7 @@ namespace save
{
char fullPath[SAVE_MAX_PATH_SIZE];
if (GetAbsoluteFullPath(persistentId, path, fullPath))
- result = coreinit::__FSQueryInfoAsync(client, block, (uint8*)fullPath, FSA_QUERY_TYPE_STAT, stat, errHandling, (FSAsyncParamsNew_t*)asyncParams); // FSGetStatAsync(...)
+ result = coreinit::__FSQueryInfoAsync(client, block, (uint8*)fullPath, FSA_QUERY_TYPE_STAT, stat, errHandling, (FSAsyncParams*)asyncParams); // FSGetStatAsync(...)
}
else
result = (FSStatus)FS_RESULT::NOT_FOUND;
@@ -616,7 +517,7 @@ namespace save
return result;
}
- SAVEStatus SAVEGetStatOtherApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint64 titleId, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEGetStatOtherApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint64 titleId, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
SAVEStatus result = (FSStatus)(FS_RESULT::FATAL_ERROR);
@@ -627,7 +528,7 @@ namespace save
{
char fullPath[SAVE_MAX_PATH_SIZE];
if (GetAbsoluteFullPathOtherApplication(persistentId, titleId, path, fullPath) == (FSStatus)FS_RESULT::SUCCESS)
- result = coreinit::__FSQueryInfoAsync(client, block, (uint8*)fullPath, FSA_QUERY_TYPE_STAT, stat, errHandling, (FSAsyncParamsNew_t*)asyncParams); // FSGetStatAsync(...)
+ result = coreinit::__FSQueryInfoAsync(client, block, (uint8*)fullPath, FSA_QUERY_TYPE_STAT, stat, errHandling, (FSAsyncParams*)asyncParams); // FSGetStatAsync(...)
}
else
result = (FSStatus)FS_RESULT::NOT_FOUND;
@@ -637,25 +538,25 @@ namespace save
return result;
}
- SAVEStatus SAVEGetStatOtherNormalApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEGetStatOtherNormalApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
uint64 titleId = SAVE_UNIQUE_TO_TITLE_ID(uniqueId);
return SAVEGetStatOtherApplicationAsync(client, block, titleId, accountSlot, path, stat, errHandling, asyncParams);
}
- SAVEStatus SAVEGetStatOtherDemoApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEGetStatOtherDemoApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
uint64 titleId = SAVE_UNIQUE_DEMO_TO_TITLE_ID(uniqueId);
return SAVEGetStatOtherApplicationAsync(client, block, titleId, accountSlot, path, stat, errHandling, asyncParams);
}
- SAVEStatus SAVEGetStatOtherNormalApplicationVariationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 variation, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEGetStatOtherNormalApplicationVariationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 variation, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
uint64 titleId = SAVE_UNIQUE_TO_TITLE_ID_VARIATION(uniqueId, variation);
return SAVEGetStatOtherApplicationAsync(client, block, titleId, accountSlot, path, stat, errHandling, asyncParams);
}
- SAVEStatus SAVEGetStatOtherDemoApplicationVariationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 variation, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEGetStatOtherDemoApplicationVariationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 variation, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
uint64 titleId = SAVE_UNIQUE_DEMO_TO_TITLE_ID_VARIATION(uniqueId, variation);
return SAVEGetStatOtherApplicationAsync(client, block, titleId, accountSlot, path, stat, errHandling, asyncParams);
@@ -682,14 +583,14 @@ namespace save
SAVEStatus SAVEGetFreeSpaceSize(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, FSLargeSize* freeSize, FS_ERROR_MASK errHandling)
{
MEMPTR currentThread{coreinit::OSGetCurrentThread()};
- FSAsyncParams_t asyncParams;
- asyncParams.ioMsgQueue = MPTR_NULL;
- asyncParams.userCallback = _swapEndianU32(PPCInterpreter_makeCallableExportDepr(AsyncCallback));
+ FSAsyncParams asyncParams;
+ asyncParams.ioMsgQueue = nullptr;
+ asyncParams.userCallback = RPLLoader_MakePPCCallable(AsyncCallback);
StackAllocator param;
param->thread = currentThread;
param->returnStatus = (FSStatus)FS_RESULT::SUCCESS;
- asyncParams.userContext = param.GetMPTRBE();
+ asyncParams.userContext = ¶m;
SAVEStatus status = SAVEGetFreeSpaceSizeAsync(client, block, accountSlot, freeSize, errHandling, &asyncParams);
if (status == (FSStatus)FS_RESULT::SUCCESS)
@@ -722,7 +623,7 @@ namespace save
ppcDefineParamU8(accountSlot, 2);
ppcDefineParamMEMPTR(returnedFreeSize, FSLargeSize, 3);
ppcDefineParamU32(errHandling, 4);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 5);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 5);
const SAVEStatus result = SAVEGetFreeSpaceSizeAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), accountSlot, returnedFreeSize.GetPtr(), errHandling, asyncParams.GetPtr());
cemuLog_log(LogType::Save, "SAVEGetFreeSpaceSizeAsync(0x{:08x}, 0x{:08x}, {:x}, {:x}) -> {:x}", fsClient.GetMPTR(), fsCmdBlock.GetMPTR(), accountSlot, errHandling, result);
@@ -743,7 +644,7 @@ namespace save
ppcDefineParamU8(accountSlot, 2);
ppcDefineParamMEMPTR(path, const char, 3);
ppcDefineParamU32(errHandling, 4);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 5);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 5);
const SAVEStatus result = SAVERemoveAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), accountSlot, path.GetPtr(), errHandling, asyncParams.GetPtr());
osLib_returnFromFunction(hCPU, result);
@@ -752,14 +653,14 @@ namespace save
SAVEStatus SAVERemove(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FS_ERROR_MASK errHandling)
{
MEMPTR currentThread{coreinit::OSGetCurrentThread()};
- FSAsyncParams_t asyncParams;
- asyncParams.ioMsgQueue = MPTR_NULL;
- asyncParams.userCallback = _swapEndianU32(PPCInterpreter_makeCallableExportDepr(AsyncCallback));
+ FSAsyncParams asyncParams;
+ asyncParams.ioMsgQueue = nullptr;
+ asyncParams.userCallback = RPLLoader_MakePPCCallable(AsyncCallback);
StackAllocator param;
param->thread = currentThread;
param->returnStatus = (FSStatus)FS_RESULT::SUCCESS;
- asyncParams.userContext = param.GetMPTRBE();
+ asyncParams.userContext = ¶m;
SAVEStatus status = SAVERemoveAsync(client, block, accountSlot, path, errHandling, &asyncParams);
if (status == (FSStatus)FS_RESULT::SUCCESS)
@@ -784,7 +685,7 @@ namespace save
osLib_returnFromFunction(hCPU, result);
}
- SAVEStatus SAVERenameAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* oldPath, const char* newPath, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVERenameAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* oldPath, const char* newPath, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
SAVEStatus result = (FSStatus)(FS_RESULT::FATAL_ERROR);
@@ -798,7 +699,7 @@ namespace save
{
char fullNewPath[SAVE_MAX_PATH_SIZE];
if (GetAbsoluteFullPath(persistentId, newPath, fullNewPath))
- result = coreinit::FSRenameAsync(client, block, fullOldPath, fullNewPath, errHandling, (FSAsyncParamsNew_t*)asyncParams);
+ result = coreinit::FSRenameAsync(client, block, fullOldPath, fullNewPath, errHandling, (FSAsyncParams*)asyncParams);
}
}
else
@@ -817,7 +718,7 @@ namespace save
ppcDefineParamMEMPTR(oldPath, const char, 3);
ppcDefineParamMEMPTR(newPath, const char, 4);
ppcDefineParamU32(errHandling, 5);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 6);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 6);
const SAVEStatus result = SAVERenameAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), accountSlot, oldPath.GetPtr(), newPath.GetPtr(), errHandling, asyncParams.GetPtr());
cemuLog_log(LogType::Save, "SAVERenameAsync(0x{:08x}, 0x{:08x}, {:x}, {}, {}, {:x}) -> {:x}", fsClient.GetMPTR(), fsCmdBlock.GetMPTR(), accountSlot, oldPath.GetPtr(), newPath.GetPtr(), errHandling, result);
@@ -855,7 +756,7 @@ namespace save
ppcDefineParamMEMPTR(path, const char, 3);
ppcDefineParamMEMPTR(hDir, betype, 4);
ppcDefineParamU32(errHandling, 5);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 6);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 6);
const SAVEStatus result = SAVEOpenDirAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), accountSlot, path.GetPtr(), hDir, errHandling, asyncParams.GetPtr());
cemuLog_log(LogType::Save, "SAVEOpenDirAsync(0x{:08x}, 0x{:08x}, {:x}, {}, 0x{:08x} ({:x}), {:x}) -> {:x}", fsClient.GetMPTR(), fsCmdBlock.GetMPTR(), accountSlot, path.GetPtr(), hDir.GetMPTR(),
@@ -866,14 +767,14 @@ namespace save
SAVEStatus SAVEOpenDir(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FSDirHandlePtr hDir, FS_ERROR_MASK errHandling)
{
MEMPTR currentThread{coreinit::OSGetCurrentThread()};
- FSAsyncParams_t asyncParams;
- asyncParams.ioMsgQueue = MPTR_NULL;
- asyncParams.userCallback = _swapEndianU32(PPCInterpreter_makeCallableExportDepr(AsyncCallback));
+ FSAsyncParams asyncParams;
+ asyncParams.ioMsgQueue = nullptr;
+ asyncParams.userCallback = RPLLoader_MakePPCCallable(AsyncCallback);
StackAllocator param;
param->thread = currentThread;
param->returnStatus = (FSStatus)FS_RESULT::SUCCESS;
- asyncParams.userContext = param.GetMPTRBE();
+ asyncParams.userContext = ¶m;
SAVEStatus status = SAVEOpenDirAsync(client, block, accountSlot, path, hDir, errHandling, &asyncParams);
if (status == (FSStatus)FS_RESULT::SUCCESS)
@@ -901,7 +802,7 @@ namespace save
osLib_returnFromFunction(hCPU, result);
}
- SAVEStatus SAVEOpenDirOtherApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint64 titleId, uint8 accountSlot, const char* path, FSDirHandlePtr hDir, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEOpenDirOtherApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint64 titleId, uint8 accountSlot, const char* path, FSDirHandlePtr hDir, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
SAVEStatus result = (FSStatus)(FS_RESULT::FATAL_ERROR);
@@ -911,7 +812,7 @@ namespace save
{
char fullPath[SAVE_MAX_PATH_SIZE];
if (GetAbsoluteFullPathOtherApplication(persistentId, titleId, path, fullPath))
- result = coreinit::FSOpenDirAsync(client, block, fullPath, hDir, errHandling, (FSAsyncParamsNew_t*)asyncParams);
+ result = coreinit::FSOpenDirAsync(client, block, fullPath, hDir, errHandling, (FSAsyncParams*)asyncParams);
}
else
result = (FSStatus)FS_RESULT::NOT_FOUND;
@@ -929,7 +830,7 @@ namespace save
ppcDefineParamMEMPTR(path, const char, 4);
ppcDefineParamMEMPTR(hDir, betype, 5);
ppcDefineParamU32(errHandling, 6);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 7);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 7);
const SAVEStatus result = SAVEOpenDirOtherApplicationAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), titleId, accountSlot, path.GetPtr(), hDir, errHandling, asyncParams.GetPtr());
cemuLog_log(LogType::Save, "SAVEOpenDirOtherApplicationAsync(0x{:08x}, 0x{:08x}, {:x}, {:x}, {}, 0x{:08x} ({:x}), {:x}) -> {:x}", fsClient.GetMPTR(), fsCmdBlock.GetMPTR(), titleId, accountSlot, path.GetPtr(), hDir.GetMPTR(),
@@ -940,14 +841,14 @@ namespace save
SAVEStatus SAVEOpenDirOtherApplication(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint64 titleId, uint8 accountSlot, const char* path, FSDirHandlePtr hDir, FS_ERROR_MASK errHandling)
{
MEMPTR currentThread{coreinit::OSGetCurrentThread()};
- FSAsyncParams_t asyncParams;
- asyncParams.ioMsgQueue = MPTR_NULL;
- asyncParams.userCallback = _swapEndianU32(PPCInterpreter_makeCallableExportDepr(AsyncCallback));
+ FSAsyncParams asyncParams;
+ asyncParams.ioMsgQueue = nullptr;
+ asyncParams.userCallback = RPLLoader_MakePPCCallable(AsyncCallback);
StackAllocator param;
param->thread = currentThread;
param->returnStatus = (FSStatus)FS_RESULT::SUCCESS;
- asyncParams.userContext = param.GetMPTRBE();
+ asyncParams.userContext = ¶m;
SAVEStatus status = SAVEOpenDirOtherApplicationAsync(client, block, titleId, accountSlot, path, hDir, errHandling, &asyncParams);
if (status == (FSStatus)FS_RESULT::SUCCESS)
@@ -976,7 +877,7 @@ namespace save
osLib_returnFromFunction(hCPU, result);
}
- SAVEStatus SAVEOpenDirOtherNormalApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 accountSlot, const char* path, FSDirHandlePtr hDir, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEOpenDirOtherNormalApplicationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 accountSlot, const char* path, FSDirHandlePtr hDir, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
uint64 titleId = SAVE_UNIQUE_TO_TITLE_ID(uniqueId);
return SAVEOpenDirOtherApplicationAsync(client, block, titleId, accountSlot, path, hDir, errHandling, asyncParams);
@@ -991,7 +892,7 @@ namespace save
ppcDefineParamMEMPTR(path, const char, 4);
ppcDefineParamMEMPTR(hDir, betype, 5);
ppcDefineParamU32(errHandling, 6);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 7);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 7);
const SAVEStatus result = SAVEOpenDirOtherNormalApplicationAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), uniqueId, accountSlot, path.GetPtr(), hDir, errHandling, asyncParams.GetPtr());
osLib_returnFromFunction(hCPU, result);
@@ -1017,7 +918,7 @@ namespace save
osLib_returnFromFunction(hCPU, result);
}
- SAVEStatus SAVEOpenDirOtherNormalApplicationVariationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 variation, uint8 accountSlot, const char* path, FSDirHandlePtr hDir, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEOpenDirOtherNormalApplicationVariationAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 variation, uint8 accountSlot, const char* path, FSDirHandlePtr hDir, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
uint64 titleId = SAVE_UNIQUE_TO_TITLE_ID_VARIATION(uniqueId, variation);
return SAVEOpenDirOtherApplicationAsync(client, block, titleId, accountSlot, path, hDir, errHandling, asyncParams);
@@ -1033,7 +934,7 @@ namespace save
ppcDefineParamMEMPTR(path, const char, 5);
ppcDefineParamMEMPTR(hDir, betype, 6);
ppcDefineParamU32(errHandling, 7);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 8);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 8);
const SAVEStatus result = SAVEOpenDirOtherNormalApplicationVariationAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), uniqueId, variation, accountSlot, path.GetPtr(), hDir, errHandling, asyncParams.GetPtr());
osLib_returnFromFunction(hCPU, result);
@@ -1067,7 +968,7 @@ namespace save
ppcDefineParamU8(accountSlot, 2);
ppcDefineParamMEMPTR(path, const char, 3);
ppcDefineParamU32(errHandling, 4);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 5);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 5);
const SAVEStatus result = SAVEMakeDirAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), accountSlot, path.GetPtr(), errHandling, asyncParams.GetPtr());
cemuLog_log(LogType::Save, "SAVEMakeDirAsync(0x{:08x}, 0x{:08x}, {:x}, {}, {:x}) -> {:x}", fsClient.GetMPTR(), fsCmdBlock.GetMPTR(), accountSlot, path.GetPtr(), errHandling, result);
@@ -1077,14 +978,14 @@ namespace save
SAVEStatus SAVEMakeDir(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FS_ERROR_MASK errHandling)
{
MEMPTR currentThread{coreinit::OSGetCurrentThread()};
- FSAsyncParams_t asyncParams;
- asyncParams.ioMsgQueue = MPTR_NULL;
- asyncParams.userCallback = _swapEndianU32(PPCInterpreter_makeCallableExportDepr(AsyncCallback));
+ FSAsyncParams asyncParams;
+ asyncParams.ioMsgQueue = nullptr;
+ asyncParams.userCallback = RPLLoader_MakePPCCallable(AsyncCallback);
StackAllocator param;
param->thread = currentThread;
param->returnStatus = (FSStatus)FS_RESULT::SUCCESS;
- asyncParams.userContext = param.GetMPTRBE();
+ asyncParams.userContext = ¶m;
SAVEStatus status = SAVEMakeDirAsync(client, block, accountSlot, path, errHandling, &asyncParams);
if (status == (FSStatus)FS_RESULT::SUCCESS)
@@ -1110,26 +1011,10 @@ namespace save
osLib_returnFromFunction(hCPU, result);
}
- void export_SAVEOpenFileAsync(PPCInterpreter_t* hCPU)
- {
- ppcDefineParamMEMPTR(fsClient, coreinit::FSClient_t, 0);
- ppcDefineParamMEMPTR(fsCmdBlock, coreinit::FSCmdBlock_t, 1);
- ppcDefineParamU8(accountSlot, 2);
- ppcDefineParamMEMPTR(path, const char, 3);
- ppcDefineParamMEMPTR(mode, const char, 4);
- ppcDefineParamMEMPTR(hFile, FSFileHandleDepr_t, 5);
- ppcDefineParamU32(errHandling, 6);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParamsNew_t, 7);
-
- const SAVEStatus result = SAVEOpenFileAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), accountSlot, path.GetPtr(), mode.GetPtr(), hFile.GetPtr(), errHandling, asyncParams.GetPtr());
- cemuLog_log(LogType::Save, "SAVEOpenFileAsync(0x{:08x}, 0x{:08x}, {:x}, {}, {}, 0x{:08x}, {:x}) -> {:x}", fsClient.GetMPTR(), fsCmdBlock.GetMPTR(), accountSlot, path.GetPtr(), mode.GetPtr(), hFile.GetMPTR(), errHandling, result);
- osLib_returnFromFunction(hCPU, result);
- }
-
- SAVEStatus SAVEOpenFile(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, const char* mode, FSFileHandleDepr_t* hFile, FS_ERROR_MASK errHandling)
+ SAVEStatus SAVEOpenFile(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, const char* mode, FSFileHandlePtr outFileHandle, FS_ERROR_MASK errHandling)
{
MEMPTR currentThread{coreinit::OSGetCurrentThread()};
- FSAsyncParamsNew_t asyncParams;
+ FSAsyncParams asyncParams;
asyncParams.ioMsgQueue = nullptr;
asyncParams.userCallback = PPCInterpreter_makeCallableExportDepr(AsyncCallback);
@@ -1138,7 +1023,7 @@ namespace save
param->returnStatus = (FSStatus)FS_RESULT::SUCCESS;
asyncParams.userContext = param.GetPointer();
- SAVEStatus status = SAVEOpenFileAsync(client, block, accountSlot, path, mode, hFile, errHandling, &asyncParams);
+ SAVEStatus status = SAVEOpenFileAsync(client, block, accountSlot, path, mode, outFileHandle, errHandling, &asyncParams);
if (status == (FSStatus)FS_RESULT::SUCCESS)
{
coreinit_suspendThread(currentThread, 1000);
@@ -1149,21 +1034,6 @@ namespace save
return status;
}
- void export_SAVEOpenFile(PPCInterpreter_t* hCPU)
- {
- ppcDefineParamMEMPTR(fsClient, coreinit::FSClient_t, 0);
- ppcDefineParamMEMPTR(fsCmdBlock, coreinit::FSCmdBlock_t, 1);
- ppcDefineParamU8(accountSlot, 2);
- ppcDefineParamMEMPTR(path, const char, 3);
- ppcDefineParamMEMPTR(mode, const char, 4);
- ppcDefineParamMEMPTR(hFile, FSFileHandleDepr_t, 5);
- ppcDefineParamU32(errHandling, 6);
-
- const SAVEStatus result = SAVEOpenFile(fsClient.GetPtr(), fsCmdBlock.GetPtr(), accountSlot, path.GetPtr(), mode.GetPtr(), hFile.GetPtr(), errHandling);
- cemuLog_log(LogType::Save, "SAVEOpenFile(0x{:08x}, 0x{:08x}, {:x}, {}, {}, 0x{:08x}, {:x}) -> {:x}", fsClient.GetMPTR(), fsCmdBlock.GetMPTR(), accountSlot, path.GetPtr(), mode.GetPtr(), hFile.GetMPTR(), errHandling, result);
- osLib_returnFromFunction(hCPU, result);
- }
-
void export_SAVEInitSaveDir(PPCInterpreter_t* hCPU)
{
ppcDefineParamU8(accountSlot, 0);
@@ -1180,7 +1050,7 @@ namespace save
ppcDefineParamMEMPTR(path, const char, 3);
ppcDefineParamMEMPTR(stat, FSStat_t, 4);
ppcDefineParamU32(errHandling, 5);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 6);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 6);
const SAVEStatus result = SAVEGetStatAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), accountSlot, path.GetPtr(), stat.GetPtr(), errHandling, asyncParams.GetPtr());
cemuLog_log(LogType::Save, "SAVEGetStatAsync(0x{:08x}, 0x{:08x}, {:x}, {}, 0x{:08x}, {:x}) -> {:x}", fsClient.GetMPTR(), fsCmdBlock.GetMPTR(), accountSlot, path.GetPtr(), stat.GetMPTR(), errHandling, result);
@@ -1190,14 +1060,14 @@ namespace save
SAVEStatus SAVEGetStat(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling)
{
MEMPTR currentThread{coreinit::OSGetCurrentThread()};
- FSAsyncParams_t asyncParams;
- asyncParams.ioMsgQueue = MPTR_NULL;
- asyncParams.userCallback = _swapEndianU32(PPCInterpreter_makeCallableExportDepr(AsyncCallback));
+ FSAsyncParams asyncParams;
+ asyncParams.ioMsgQueue = nullptr;
+ asyncParams.userCallback = RPLLoader_MakePPCCallable(AsyncCallback);
StackAllocator param;
param->thread = currentThread;
param->returnStatus = (FSStatus)FS_RESULT::SUCCESS;
- asyncParams.userContext = param.GetMPTRBE();
+ asyncParams.userContext = ¶m;
SAVEStatus status = SAVEGetStatAsync(client, block, accountSlot, path, stat, errHandling, &asyncParams);
if (status == (FSStatus)FS_RESULT::SUCCESS)
@@ -1233,7 +1103,7 @@ namespace save
ppcDefineParamMEMPTR(path, const char, 5);
ppcDefineParamMEMPTR(stat, FSStat_t, 6);
ppcDefineParamU32(errHandling, 7);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 8);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 8);
const SAVEStatus result = SAVEGetStatOtherApplicationAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), titleId, accountSlot, path.GetPtr(), stat.GetPtr(), errHandling, asyncParams.GetPtr());
osLib_returnFromFunction(hCPU, result);
@@ -1242,14 +1112,14 @@ namespace save
SAVEStatus SAVEGetStatOtherApplication(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint64 titleId, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling)
{
MEMPTR currentThread{coreinit::OSGetCurrentThread()};
- FSAsyncParams_t asyncParams;
- asyncParams.ioMsgQueue = MPTR_NULL;
- asyncParams.userCallback = _swapEndianU32(PPCInterpreter_makeCallableExportDepr(AsyncCallback));
+ FSAsyncParams asyncParams;
+ asyncParams.ioMsgQueue = nullptr;
+ asyncParams.userCallback = RPLLoader_MakePPCCallable(AsyncCallback);
StackAllocator param;
param->thread = currentThread;
param->returnStatus = (FSStatus)FS_RESULT::SUCCESS;
- asyncParams.userContext = param.GetMPTRBE();
+ asyncParams.userContext = ¶m;
SAVEStatus status = SAVEGetStatOtherApplicationAsync(client, block, titleId, accountSlot, path, stat, errHandling, &asyncParams);
if (status == (FSStatus)FS_RESULT::SUCCESS)
@@ -1286,7 +1156,7 @@ namespace save
ppcDefineParamMEMPTR(path, const char, 4);
ppcDefineParamMEMPTR(stat, FSStat_t, 5);
ppcDefineParamU32(errHandling, 6);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 8);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 8);
const SAVEStatus result = SAVEGetStatOtherNormalApplicationAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), uniqueId, accountSlot, path.GetPtr(), stat.GetPtr(), errHandling, asyncParams.GetPtr());
osLib_returnFromFunction(hCPU, result);
@@ -1294,8 +1164,6 @@ namespace save
SAVEStatus SAVEGetStatOtherNormalApplication(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint32 uniqueId, uint8 accountSlot, const char* path, FSStat_t* stat, FS_ERROR_MASK errHandling)
{
- //peterBreak();
-
uint64 titleId = SAVE_UNIQUE_TO_TITLE_ID(uniqueId);
return SAVEGetStatOtherApplication(client, block, titleId, accountSlot, path, stat, errHandling);
}
@@ -1326,7 +1194,7 @@ namespace save
ppcDefineParamMEMPTR(path, const char, 5);
ppcDefineParamMEMPTR(stat, FSStat_t, 6);
ppcDefineParamU32(errHandling, 7);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 8);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 8);
const SAVEStatus result = SAVEGetStatOtherNormalApplicationVariationAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), uniqueId, variation, accountSlot, path.GetPtr(), stat.GetPtr(), errHandling, asyncParams.GetPtr());
osLib_returnFromFunction(hCPU, result);
@@ -1397,7 +1265,7 @@ namespace save
osLib_returnFromFunction(hCPU, result);
}
- SAVEStatus SAVEChangeDirAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEChangeDirAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
SAVEStatus result = (FSStatus)(FS_RESULT::FATAL_ERROR);
@@ -1407,7 +1275,7 @@ namespace save
{
char fullPath[SAVE_MAX_PATH_SIZE];
if (GetAbsoluteFullPath(persistentId, path, fullPath))
- result = coreinit::FSChangeDirAsync(client, block, fullPath, errHandling, (FSAsyncParamsNew_t*)asyncParams);
+ result = coreinit::FSChangeDirAsync(client, block, fullPath, errHandling, (FSAsyncParams*)asyncParams);
}
else
result = (FSStatus)FS_RESULT::NOT_FOUND;
@@ -1423,7 +1291,7 @@ namespace save
ppcDefineParamU8(accountSlot, 2);
ppcDefineParamMEMPTR(path, const char, 3);
ppcDefineParamU32(errHandling, 4);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 5);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 5);
const SAVEStatus result = SAVEChangeDirAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), accountSlot, path.GetPtr(), errHandling, asyncParams.GetPtr());
cemuLog_log(LogType::Save, "SAVEChangeDirAsync(0x{:08x}, 0x{:08x}, {:x}, {}, {:x}) -> {:x}", fsClient.GetMPTR(), fsCmdBlock.GetMPTR(), accountSlot, path.GetPtr(), errHandling, result);
osLib_returnFromFunction(hCPU, result);
@@ -1432,14 +1300,14 @@ namespace save
SAVEStatus SAVEChangeDir(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, const char* path, FS_ERROR_MASK errHandling)
{
MEMPTR currentThread{coreinit::OSGetCurrentThread()};
- FSAsyncParams_t asyncParams;
- asyncParams.ioMsgQueue = MPTR_NULL;
- asyncParams.userCallback = _swapEndianU32(PPCInterpreter_makeCallableExportDepr(AsyncCallback));
+ FSAsyncParams asyncParams;
+ asyncParams.ioMsgQueue = nullptr;
+ asyncParams.userCallback = RPLLoader_MakePPCCallable(AsyncCallback);
StackAllocator param;
param->thread = currentThread;
param->returnStatus = (FSStatus)FS_RESULT::SUCCESS;
- asyncParams.userContext = param.GetMPTRBE();
+ asyncParams.userContext = ¶m;
SAVEStatus status = SAVEChangeDirAsync(client, block, accountSlot, path, errHandling, &asyncParams);
if (status == (FSStatus)FS_RESULT::SUCCESS)
@@ -1464,7 +1332,7 @@ namespace save
osLib_returnFromFunction(hCPU, result);
}
- SAVEStatus SAVEFlushQuotaAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, FS_ERROR_MASK errHandling, const FSAsyncParams_t* asyncParams)
+ SAVEStatus SAVEFlushQuotaAsync(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, FS_ERROR_MASK errHandling, const FSAsyncParams* asyncParams)
{
SAVEStatus result = (FSStatus)(FS_RESULT::FATAL_ERROR);
@@ -1475,7 +1343,7 @@ namespace save
char fullPath[SAVE_MAX_PATH_SIZE];
if (GetAbsoluteFullPath(persistentId, nullptr, fullPath))
{
- result = coreinit::FSFlushQuotaAsync(client, block, fullPath, errHandling, (FSAsyncParamsNew_t*)asyncParams);
+ result = coreinit::FSFlushQuotaAsync(client, block, fullPath, errHandling, (FSAsyncParams*)asyncParams);
// if(OSGetUPID != 0xF)
UpdateSaveTimeStamp(persistentId);
}
@@ -1493,7 +1361,7 @@ namespace save
ppcDefineParamMEMPTR(fsCmdBlock, coreinit::FSCmdBlock_t, 1);
ppcDefineParamU8(accountSlot, 2);
ppcDefineParamU32(errHandling, 3);
- ppcDefineParamMEMPTR(asyncParams, FSAsyncParams_t, 4);
+ ppcDefineParamMEMPTR(asyncParams, FSAsyncParams, 4);
const SAVEStatus result = SAVEFlushQuotaAsync(fsClient.GetPtr(), fsCmdBlock.GetPtr(), accountSlot, errHandling, asyncParams.GetPtr());
cemuLog_log(LogType::Save, "SAVEFlushQuotaAsync(0x{:08x}, 0x{:08x}, {:x}, {:x}) -> {:x}", fsClient.GetMPTR(), fsCmdBlock.GetMPTR(), accountSlot, errHandling, result);
osLib_returnFromFunction(hCPU, result);
@@ -1502,14 +1370,14 @@ namespace save
SAVEStatus SAVEFlushQuota(coreinit::FSClient_t* client, coreinit::FSCmdBlock_t* block, uint8 accountSlot, FS_ERROR_MASK errHandling)
{
MEMPTR currentThread{coreinit::OSGetCurrentThread()};
- FSAsyncParams_t asyncParams;
- asyncParams.ioMsgQueue = MPTR_NULL;
- asyncParams.userCallback = _swapEndianU32(PPCInterpreter_makeCallableExportDepr(AsyncCallback));
+ FSAsyncParams asyncParams;
+ asyncParams.ioMsgQueue = nullptr;
+ asyncParams.userCallback = RPLLoader_MakePPCCallable(AsyncCallback);
StackAllocator param;
param->thread = currentThread;
param->returnStatus = (FSStatus)FS_RESULT::SUCCESS;
- asyncParams.userContext = param.GetMPTRBE();
+ asyncParams.userContext = ¶m;
SAVEStatus status = SAVEFlushQuotaAsync(client, block, accountSlot, errHandling, &asyncParams);
if (status == (FSStatus)FS_RESULT::SUCCESS)
@@ -1553,10 +1421,14 @@ namespace save
osLib_addFunction("nn_save", "SAVEGetStatOtherNormalApplication", export_SAVEGetStatOtherNormalApplication);
osLib_addFunction("nn_save", "SAVEGetStatOtherNormalApplicationVariation", export_SAVEGetStatOtherNormalApplicationVariation);
- osLib_addFunction("nn_save", "SAVEOpenFile", export_SAVEOpenFile);
- osLib_addFunction("nn_save", "SAVEOpenFileOtherApplication", export_SAVEOpenFileOtherApplication);
- osLib_addFunction("nn_save", "SAVEOpenFileOtherNormalApplication", export_SAVEOpenFileOtherNormalApplication);
- osLib_addFunction("nn_save", "SAVEOpenFileOtherNormalApplicationVariation", export_SAVEOpenFileOtherNormalApplicationVariation);
+ cafeExportRegister("nn_save", SAVEOpenFile, LogType::Save);
+ cafeExportRegister("nn_save", SAVEOpenFileAsync, LogType::Save);
+ cafeExportRegister("nn_save", SAVEOpenFileOtherApplication, LogType::Save);
+ cafeExportRegister("nn_save", SAVEOpenFileOtherApplicationAsync, LogType::Save);
+ cafeExportRegister("nn_save", SAVEOpenFileOtherNormalApplication, LogType::Save);
+ cafeExportRegister("nn_save", SAVEOpenFileOtherNormalApplicationAsync, LogType::Save);
+ cafeExportRegister("nn_save", SAVEOpenFileOtherNormalApplicationVariation, LogType::Save);
+ cafeExportRegister("nn_save", SAVEOpenFileOtherNormalApplicationVariationAsync, LogType::Save);
osLib_addFunction("nn_save", "SAVEOpenDir", export_SAVEOpenDir);
osLib_addFunction("nn_save", "SAVEOpenDirOtherApplication", export_SAVEOpenDirOtherApplication);
@@ -1578,11 +1450,6 @@ namespace save
osLib_addFunction("nn_save", "SAVEGetStatOtherNormalApplicationAsync", export_SAVEGetStatOtherNormalApplicationAsync);
osLib_addFunction("nn_save", "SAVEGetStatOtherNormalApplicationVariationAsync", export_SAVEGetStatOtherNormalApplicationVariationAsync);
- osLib_addFunction("nn_save", "SAVEOpenFileAsync", export_SAVEOpenFileAsync);
- osLib_addFunction("nn_save", "SAVEOpenFileOtherApplicationAsync", export_SAVEOpenFileOtherApplicationAsync);
- osLib_addFunction("nn_save", "SAVEOpenFileOtherNormalApplicationAsync", export_SAVEOpenFileOtherNormalApplicationAsync);
- osLib_addFunction("nn_save", "SAVEOpenFileOtherNormalApplicationVariationAsync", export_SAVEOpenFileOtherNormalApplicationVariationAsync);
-
osLib_addFunction("nn_save", "SAVEOpenDirAsync", export_SAVEOpenDirAsync);
osLib_addFunction("nn_save", "SAVEOpenDirOtherApplicationAsync", export_SAVEOpenDirOtherApplicationAsync);
osLib_addFunction("nn_save", "SAVEOpenDirOtherNormalApplicationAsync", export_SAVEOpenDirOtherNormalApplicationAsync);
diff --git a/src/Cafe/OS/libs/proc_ui/proc_ui.cpp b/src/Cafe/OS/libs/proc_ui/proc_ui.cpp
index 91d15af4..5560568d 100644
--- a/src/Cafe/OS/libs/proc_ui/proc_ui.cpp
+++ b/src/Cafe/OS/libs/proc_ui/proc_ui.cpp
@@ -511,7 +511,7 @@ namespace proc_ui
{
MEMPTR fgBase;
uint32be fgFreeSize;
- OSGetForegroundBucketFreeArea((MPTR*)&fgBase, (MPTR*)&fgFreeSize);
+ OSGetForegroundBucketFreeArea(&fgBase, &fgFreeSize);
if(fgFreeSize < size)
cemuLog_log(LogType::Force, "ProcUISetBucketStorage: Buffer size too small");
s_bucketStorageBasePtr = memBase;
@@ -521,7 +521,7 @@ namespace proc_ui
{
MEMPTR memBound;
uint32be memBoundSize;
- OSGetMemBound(1, (MPTR*)memBound.GetBEPtr(), (uint32*)&memBoundSize);
+ OSGetMemBound(1, &memBound, &memBoundSize);
if(memBoundSize < size)
cemuLog_log(LogType::Force, "ProcUISetMEM1Storage: Buffer size too small");
s_mem1StorageBasePtr = memBase;
@@ -751,14 +751,14 @@ namespace proc_ui
{
MEMPTR memBound;
uint32be memBoundSize;
- OSGetMemBound(1, (MPTR*)memBound.GetBEPtr(), (uint32*)&memBoundSize);
+ OSGetMemBound(1, &memBound, &memBoundSize);
OSBlockMove(s_mem1StorageBasePtr.GetPtr(), memBound.GetPtr(), memBoundSize, true);
}
if (s_bucketStorageBasePtr)
{
MEMPTR memBound;
uint32be memBoundSize;
- OSGetForegroundBucketFreeArea((MPTR*)memBound.GetBEPtr(), (MPTR*)&memBoundSize);
+ OSGetForegroundBucketFreeArea(&memBound, &memBoundSize);
OSBlockMove(s_bucketStorageBasePtr.GetPtr(), memBound.GetPtr(), memBoundSize, true);
}
}
@@ -769,7 +769,7 @@ namespace proc_ui
{
MEMPTR memBound;
uint32be memBoundSize;
- OSGetMemBound(1, (MPTR*)memBound.GetBEPtr(), (uint32*)&memBoundSize);
+ OSGetMemBound(1, &memBound, &memBoundSize);
OSBlockMove(memBound.GetPtr(), s_mem1StorageBasePtr, memBoundSize, true);
GX2::GX2Invalidate(0x40, s_mem1StorageBasePtr.GetMPTR(), memBoundSize);
}
@@ -777,7 +777,7 @@ namespace proc_ui
{
MEMPTR memBound;
uint32be memBoundSize;
- OSGetForegroundBucketFreeArea((MPTR*)memBound.GetBEPtr(), (MPTR*)&memBoundSize);
+ OSGetForegroundBucketFreeArea(&memBound, &memBoundSize);
OSBlockMove(memBound.GetPtr(), s_bucketStorageBasePtr, memBoundSize, true);
GX2::GX2Invalidate(0x40, memBound.GetMPTR(), memBoundSize);
}
diff --git a/src/Common/MemPtr.h b/src/Common/MemPtr.h
index de787cc1..b2362d0b 100644
--- a/src/Common/MemPtr.h
+++ b/src/Common/MemPtr.h
@@ -136,16 +136,10 @@ public:
C* GetPtr() const { return (C*)(GetPtr()); }
constexpr uint32 GetMPTR() const { return m_value.value(); }
- constexpr uint32 GetRawValue() const { return m_value.bevalue(); } // accesses value using host-endianness
-
constexpr const uint32be& GetBEValue() const { return m_value; }
constexpr bool IsNull() const { return m_value == 0; }
- constexpr uint32 GetMPTRBE() const { return m_value.bevalue(); }
-
- uint32be* GetBEPtr() { return &m_value; }
-
private:
uint32be m_value;
};
diff --git a/src/Common/StackAllocator.h b/src/Common/StackAllocator.h
index a69b7aaa..1dc52d51 100644
--- a/src/Common/StackAllocator.h
+++ b/src/Common/StackAllocator.h
@@ -28,7 +28,6 @@ public:
T* GetPointer() const { return m_ptr; }
uint32 GetMPTR() const { return MEMPTR(m_ptr).GetMPTR(); }
- uint32 GetMPTRBE() const { return MEMPTR(m_ptr).GetMPTRBE(); }
T* operator&() { return GetPointer(); }
explicit operator T*() const { return GetPointer(); }
From c11d83e9d8980bdc8978001583ddaa5ca0b6529b Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Fri, 3 May 2024 02:41:05 +0200
Subject: [PATCH 008/216] coreinit: Implement MCP_GetTitleId
---
src/Cafe/OS/libs/coreinit/coreinit_MCP.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MCP.cpp b/src/Cafe/OS/libs/coreinit/coreinit_MCP.cpp
index 14d7a645..330663ac 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_MCP.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_MCP.cpp
@@ -415,6 +415,12 @@ namespace coreinit
return 0;
}
+ uint32 MCP_GetTitleId(uint32 mcpHandle, uint64be* outTitleId)
+ {
+ *outTitleId = CafeSystem::GetForegroundTitleId();
+ return 0;
+ }
+
void InitializeMCP()
{
osLib_addFunction("coreinit", "MCP_Open", coreinitExport_MCP_Open);
@@ -442,6 +448,8 @@ namespace coreinit
cafeExportRegister("coreinit", MCP_RightCheckLaunchable, LogType::Placeholder);
cafeExportRegister("coreinit", MCP_GetEcoSettings, LogType::Placeholder);
+
+ cafeExportRegister("coreinit", MCP_GetTitleId, LogType::Placeholder);
}
}
From 1b5c885621c8a2e6057cc6c6c0bd557f6da5a327 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Fri, 3 May 2024 02:41:39 +0200
Subject: [PATCH 009/216] nn_acp: Implement ACPGetTitleMetaXml
---
src/Cafe/OS/libs/nn_acp/nn_acp.cpp | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/src/Cafe/OS/libs/nn_acp/nn_acp.cpp b/src/Cafe/OS/libs/nn_acp/nn_acp.cpp
index 61640ae7..37ea471f 100644
--- a/src/Cafe/OS/libs/nn_acp/nn_acp.cpp
+++ b/src/Cafe/OS/libs/nn_acp/nn_acp.cpp
@@ -289,6 +289,18 @@ namespace acp
osLib_returnFromFunction(hCPU, acpRequest->returnCode);
}
+ uint32 ACPGetTitleMetaXml(uint64 titleId, acpMetaXml_t* acpMetaXml)
+ {
+ acpPrepareRequest();
+ acpRequest->requestCode = IOSU_ACP_GET_TITLE_META_XML;
+ acpRequest->ptr = acpMetaXml;
+ acpRequest->titleId = titleId;
+
+ __depr__IOS_Ioctlv(IOS_DEVICE_ACP_MAIN, IOSU_ACP_REQUEST_CEMU, 1, 1, acpBufferVector);
+
+ return acpRequest->returnCode;
+ }
+
void export_ACPIsOverAgeEx(PPCInterpreter_t* hCPU)
{
ppcDefineParamU32(age, 0);
@@ -341,6 +353,7 @@ namespace acp
osLib_addFunction("nn_acp", "ACPGetTitleMetaDirByDevice", export_ACPGetTitleMetaDirByDevice);
osLib_addFunction("nn_acp", "ACPGetTitleMetaXmlByDevice", export_ACPGetTitleMetaXmlByDevice);
+ cafeExportRegister("nn_acp", ACPGetTitleMetaXml, LogType::Placeholder);
cafeExportRegister("nn_acp", ACPGetApplicationBox, LogType::Placeholder);
From 041f29a914b0e0ef88b4dad863cf71a6fdcca84f Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Fri, 3 May 2024 02:43:51 +0200
Subject: [PATCH 010/216] nn_act: Implement GetTimeZoneId placeholder
---
src/Cafe/OS/libs/nn_act/nn_act.cpp | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/Cafe/OS/libs/nn_act/nn_act.cpp b/src/Cafe/OS/libs/nn_act/nn_act.cpp
index 2a9f61bc..af53edd7 100644
--- a/src/Cafe/OS/libs/nn_act/nn_act.cpp
+++ b/src/Cafe/OS/libs/nn_act/nn_act.cpp
@@ -5,6 +5,7 @@
#include "nn_act.h"
#include "Cafe/OS/libs/nn_common.h"
#include "Cafe/CafeSystem.h"
+#include "Common/CafeString.h"
sint32 numAccounts = 1;
@@ -140,6 +141,14 @@ namespace act
return 0;
}
+ nnResult GetTimeZoneId(CafeString<65>* outTimezoneId)
+ {
+ // return a placeholder timezone id for now
+ // in the future we should emulated this correctly and read the timezone from the account via IOSU
+ outTimezoneId->assign("Europe/London");
+ return 0;
+ }
+
sint32 g_initializeCount = 0; // inc in Initialize and dec in Finalize
uint32 Initialize()
{
@@ -162,7 +171,6 @@ namespace act
NN_ERROR_CODE errCode = NNResultToErrorCode(*nnResult, NN_RESULT_MODULE_NN_ACT);
return errCode;
}
-
}
}
@@ -691,6 +699,8 @@ void nnAct_load()
osLib_addFunction("nn_act", "GetPersistentIdEx__Q2_2nn3actFUc", nnActExport_GetPersistentIdEx);
// country
osLib_addFunction("nn_act", "GetCountry__Q2_2nn3actFPc", nnActExport_GetCountry);
+ // timezone
+ cafeExportRegisterFunc(nn::act::GetTimeZoneId, "nn_act", "GetTimeZoneId__Q2_2nn3actFPc", LogType::Placeholder);
// parental
osLib_addFunction("nn_act", "EnableParentalControlCheck__Q2_2nn3actFb", nnActExport_EnableParentalControlCheck);
From a16c37f0c5b2435a829fc5348c66297d9c762347 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Sat, 4 May 2024 07:05:59 +0200
Subject: [PATCH 011/216] coreinit: Rework thread creation
New implementation is much closer to console behavior. For example we didn't align the stack which would cause crashes in the Miiverse applet
---
src/Cafe/HW/Latte/Core/LatteThread.cpp | 2 +-
src/Cafe/OS/libs/coreinit/coreinit.cpp | 10 +-
src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp | 4 +-
src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp | 2 +-
src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp | 315 ++++++++++++++----
src/Cafe/OS/libs/coreinit/coreinit_Thread.h | 69 ++--
src/Cafe/OS/libs/nsysnet/nsysnet.cpp | 4 +-
src/Cafe/OS/libs/snd_core/ax_ist.cpp | 2 +-
.../ExceptionHandler/ExceptionHandler.cpp | 2 +-
.../DebugPPCThreadsWindow.cpp | 4 +-
10 files changed, 297 insertions(+), 117 deletions(-)
diff --git a/src/Cafe/HW/Latte/Core/LatteThread.cpp b/src/Cafe/HW/Latte/Core/LatteThread.cpp
index a23bd5be..8874ecf4 100644
--- a/src/Cafe/HW/Latte/Core/LatteThread.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteThread.cpp
@@ -187,7 +187,7 @@ int Latte_ThreadEntry()
rule.overwrite_settings.width >= 0 || rule.overwrite_settings.height >= 0 || rule.overwrite_settings.depth >= 0)
{
LatteGPUState.allowFramebufferSizeOptimization = false;
- cemuLog_log(LogType::Force, "Graphic pack {} prevents rendertarget size optimization.", pack->GetName());
+ cemuLog_log(LogType::Force, "Graphic pack \"{}\" prevents rendertarget size optimization. This warning can be ignored and is intended for graphic pack developers", pack->GetName());
break;
}
}
diff --git a/src/Cafe/OS/libs/coreinit/coreinit.cpp b/src/Cafe/OS/libs/coreinit/coreinit.cpp
index e18d0e8d..49d232f8 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit.cpp
@@ -35,12 +35,12 @@
#include "Cafe/OS/libs/coreinit/coreinit_MEM_BlockHeap.h"
#include "Cafe/OS/libs/coreinit/coreinit_MEM_ExpHeap.h"
-CoreinitSharedData* gCoreinitData = NULL;
+CoreinitSharedData* gCoreinitData = nullptr;
sint32 ScoreStackTrace(OSThread_t* thread, MPTR sp)
{
- uint32 stackMinAddr = _swapEndianU32(thread->stackEnd);
- uint32 stackMaxAddr = _swapEndianU32(thread->stackBase);
+ uint32 stackMinAddr = thread->stackEnd.GetMPTR();
+ uint32 stackMaxAddr = thread->stackBase.GetMPTR();
sint32 score = 0;
uint32 currentStackPtr = sp;
@@ -95,8 +95,8 @@ void DebugLogStackTrace(OSThread_t* thread, MPTR sp)
// print stack trace
uint32 currentStackPtr = highestScoreSP;
- uint32 stackMinAddr = _swapEndianU32(thread->stackEnd);
- uint32 stackMaxAddr = _swapEndianU32(thread->stackBase);
+ uint32 stackMinAddr = thread->stackEnd.GetMPTR();
+ uint32 stackMaxAddr = thread->stackBase.GetMPTR();
for (sint32 i = 0; i < 20; i++)
{
uint32 nextStackPtr = memory_readU32(currentStackPtr);
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp b/src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp
index 5699e3e7..e2864fb9 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp
@@ -22,7 +22,7 @@ namespace coreinit
MPTR _iob_lock[GHS_FOPEN_MAX];
uint16be __gh_FOPEN_MAX;
MEMPTR ghs_environ;
- uint32 ghs_Errno; // exposed by __gh_errno_ptr() or via 'errno' data export
+ uint32 ghs_Errno; // exposed as 'errno' data export
};
SysAllocator g_ghs_data;
@@ -159,7 +159,7 @@ namespace coreinit
void* __gh_errno_ptr()
{
OSThread_t* currentThread = coreinit::OSGetCurrentThread();
- return ¤tThread->context.error;
+ return ¤tThread->context.ghs_errno;
}
void* __get_eh_store_globals()
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp b/src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp
index be3cb300..12d83afc 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp
@@ -204,7 +204,7 @@ namespace coreinit
// and a message queue large enough to hold the maximum number of commands (IPC_NUM_RESOURCE_BUFFERS)
OSInitMessageQueue(gIPCThreadMsgQueue.GetPtr() + coreIndex, _gIPCThreadSemaphoreStorage.GetPtr() + coreIndex * IPC_NUM_RESOURCE_BUFFERS, IPC_NUM_RESOURCE_BUFFERS);
OSThread_t* ipcThread = gIPCThread.GetPtr() + coreIndex;
- OSCreateThreadType(ipcThread, PPCInterpreter_makeCallableExportDepr(__IPCDriverThreadFunc), 0, nullptr, _gIPCThreadStack.GetPtr() + 0x4000 * coreIndex + 0x4000, 0x4000, 15, (1 << coreIndex), OSThread_t::THREAD_TYPE::TYPE_DRIVER);
+ __OSCreateThreadType(ipcThread, PPCInterpreter_makeCallableExportDepr(__IPCDriverThreadFunc), 0, nullptr, _gIPCThreadStack.GetPtr() + 0x4000 * coreIndex + 0x4000, 0x4000, 15, (1 << coreIndex), OSThread_t::THREAD_TYPE::TYPE_DRIVER);
sprintf((char*)_gIPCThreadNameStorage.GetPtr()+coreIndex*0x18, "{SYS IPC Core %d}", coreIndex);
OSSetThreadName(ipcThread, (char*)_gIPCThreadNameStorage.GetPtr() + coreIndex * 0x18);
OSResumeThread(ipcThread);
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp
index 654e57a8..533360aa 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp
@@ -215,14 +215,171 @@ namespace coreinit
hCPU->spr.LR = lr;
hCPU->gpr[3] = r3;
hCPU->gpr[4] = r4;
- hCPU->instructionPointer = _swapEndianU32(currentThread->entrypoint);
+ hCPU->instructionPointer = currentThread->entrypoint.GetMPTR();
}
void coreinitExport_OSExitThreadDepr(PPCInterpreter_t* hCPU);
- void OSCreateThreadInternal(OSThread_t* thread, uint32 entryPoint, MPTR stackLowerBaseAddr, uint32 stackSize, uint8 affinityMask, OSThread_t::THREAD_TYPE threadType)
+ void __OSInitContext(OSContext_t* ctx, MEMPTR initialIP, MEMPTR initialStackPointer)
+ {
+ ctx->SetContextMagic();
+ ctx->gpr[0] = 0; // r0 is left uninitialized on console?
+ for(auto& it : ctx->gpr)
+ it = 0;
+ ctx->gpr[1] = _swapEndianU32(initialStackPointer.GetMPTR());
+ ctx->gpr[2] = _swapEndianU32(RPLLoader_GetSDA2Base());
+ ctx->gpr[13] = _swapEndianU32(RPLLoader_GetSDA1Base());
+ ctx->srr0 = initialIP.GetMPTR();
+ ctx->cr = 0;
+ ctx->ukn0A8 = 0;
+ ctx->ukn0AC = 0;
+ ctx->gqr[0] = 0;
+ ctx->gqr[1] = 0;
+ ctx->gqr[2] = 0;
+ ctx->gqr[3] = 0;
+ ctx->gqr[4] = 0;
+ ctx->gqr[5] = 0;
+ ctx->gqr[6] = 0;
+ ctx->gqr[7] = 0;
+ ctx->dsi_dar = 0;
+ ctx->srr1 = 0x9032;
+ ctx->xer = 0;
+ ctx->dsi_dsisr = 0;
+ ctx->upir = 0;
+ ctx->boostCount = 0;
+ ctx->state = 0;
+ for(auto& it : ctx->coretime)
+ it = 0;
+ ctx->starttime = 0;
+ ctx->ghs_errno = 0;
+ ctx->upmc1 = 0;
+ ctx->upmc2 = 0;
+ ctx->upmc3 = 0;
+ ctx->upmc4 = 0;
+ ctx->ummcr0 = 0;
+ ctx->ummcr1 = 0;
+ }
+
+ void __OSThreadInit(OSThread_t* thread, MEMPTR entrypoint, uint32 argInt, MEMPTR argPtr, MEMPTR stackTop, uint32 stackSize, sint32 priority, uint32 upirCoreIndex, OSThread_t::THREAD_TYPE threadType)
+ {
+ thread->effectivePriority = priority;
+ thread->type = threadType;
+ thread->basePriority = priority;
+ thread->SetThreadMagic();
+ thread->id = 0x8000;
+ thread->waitAlarm = nullptr;
+ thread->entrypoint = entrypoint;
+ thread->quantumTicks = 0;
+ if(entrypoint)
+ {
+ thread->state = OSThread_t::THREAD_STATE::STATE_READY;
+ thread->suspendCounter = 1;
+ }
+ else
+ {
+ thread->state = OSThread_t::THREAD_STATE::STATE_NONE;
+ thread->suspendCounter = 0;
+ }
+ thread->exitValue = (uint32)-1;
+ thread->requestFlags = OSThread_t::REQUEST_FLAG_BIT::REQUEST_FLAG_NONE;
+ thread->pendingSuspend = 0;
+ thread->suspendResult = 0xFFFFFFFF;
+ thread->coretimeSumQuantumStart = 0;
+ thread->deallocatorFunc = nullptr;
+ thread->cleanupCallback = nullptr;
+ thread->waitingForFastMutex = nullptr;
+ thread->stateFlags = 0;
+ thread->waitingForMutex = nullptr;
+ memset(&thread->crt, 0, sizeof(thread->crt));
+ static_assert(sizeof(thread->crt) == 0x1D8);
+ thread->tlsBlocksMPTR = 0;
+ thread->numAllocatedTLSBlocks = 0;
+ thread->tlsStatus = 0;
+ OSInitThreadQueueEx(&thread->joinQueue, thread);
+ OSInitThreadQueueEx(&thread->suspendQueue, thread);
+ thread->mutexQueue.ukn08 = thread;
+ thread->mutexQueue.ukn0C = 0;
+ thread->mutexQueue.tail = nullptr;
+ thread->mutexQueue.head = nullptr;
+ thread->ownedFastMutex.next = nullptr;
+ thread->ownedFastMutex.prev = nullptr;
+ thread->contendedFastMutex.next = nullptr;
+ thread->contendedFastMutex.prev = nullptr;
+
+ MEMPTR alignedStackTop{MEMPTR(stackTop).GetMPTR() & 0xFFFFFFF8};
+ MEMPTR alignedStackTop32{alignedStackTop};
+ alignedStackTop32[-1] = 0;
+ alignedStackTop32[-2] = 0;
+
+ __OSInitContext(&thread->context, MEMPTR(PPCInterpreter_makeCallableExportDepr(threadEntry)), (void*)(alignedStackTop32.GetPtr() - 2));
+ thread->stackBase = stackTop; // without alignment
+ thread->stackEnd = ((uint8*)stackTop.GetPtr() - stackSize);
+ thread->context.upir = upirCoreIndex;
+ thread->context.lr = _swapEndianU32(PPCInterpreter_makeCallableExportDepr(coreinitExport_OSExitThreadDepr));
+ thread->context.gpr[3] = _swapEndianU32(argInt);
+ thread->context.gpr[4] = _swapEndianU32(argPtr.GetMPTR());
+
+ *(uint32be*)((uint8*)stackTop.GetPtr() - stackSize) = 0xDEADBABE;
+ thread->alarmRelatedUkn = 0;
+ for(auto& it : thread->specificArray)
+ it = nullptr;
+ thread->context.fpscr.fpscr = 4;
+ for(sint32 i=0; i<32; i++)
+ {
+ thread->context.fp_ps0[i] = 0.0;
+ thread->context.fp_ps1[i] = 0.0;
+ }
+ thread->context.gqr[2] = 0x40004;
+ thread->context.gqr[3] = 0x50005;
+ thread->context.gqr[4] = 0x60006;
+ thread->context.gqr[5] = 0x70007;
+
+ for(sint32 i=0; icontext.coretime[i] = 0;
+
+ // currentRunQueue and waitQueueLink is not initialized by COS and instead overwritten without validation
+ // since we already have integrity checks in other functions, lets initialize it here
+ for(sint32 i=0; icurrentRunQueue[i] = nullptr;
+ thread->waitQueueLink.prev = nullptr;
+ thread->waitQueueLink.next = nullptr;
+
+ thread->wakeTimeRelatedUkn2 = 0;
+ thread->wakeUpCount = 0;
+ thread->wakeUpTime = 0;
+ thread->wakeTimeRelatedUkn1 = 0x7FFFFFFFFFFFFFFF;
+ thread->quantumTicks = 0;
+ thread->coretimeSumQuantumStart = 0;
+ thread->totalCycles = 0;
+
+ for(auto& it : thread->padding68C)
+ it = 0;
+ }
+
+ void SetThreadAffinityToCore(OSThread_t* thread, uint32 coreIndex)
+ {
+ cemu_assert_debug(coreIndex < 3);
+ thread->attr &= ~(OSThread_t::ATTR_BIT::ATTR_AFFINITY_CORE0 | OSThread_t::ATTR_BIT::ATTR_AFFINITY_CORE1 | OSThread_t::ATTR_BIT::ATTR_AFFINITY_CORE2 | OSThread_t::ATTR_BIT::ATTR_UKN_010);
+ thread->context.affinity &= 0xFFFFFFF8;
+ if (coreIndex == 0)
+ {
+ thread->attr |= OSThread_t::ATTR_BIT::ATTR_AFFINITY_CORE0;
+ thread->context.affinity |= (1<<0);
+ }
+ else if (coreIndex == 1)
+ {
+ thread->attr |= OSThread_t::ATTR_BIT::ATTR_AFFINITY_CORE1;
+ thread->context.affinity |= (1<<1);
+ }
+ else // if (coreIndex == 2)
+ {
+ thread->attr |= OSThread_t::ATTR_BIT::ATTR_AFFINITY_CORE2;
+ thread->context.affinity |= (1<<2);
+ }
+ }
+
+ void __OSCreateThreadOnActiveThreadWorkaround(OSThread_t* thread)
{
- cemu_assert_debug(thread != nullptr); // make thread struct mandatory. Caller can always use SysAllocator
__OSLockScheduler();
bool isThreadStillActive = __OSIsThreadActive(thread);
if (isThreadStillActive)
@@ -248,84 +405,97 @@ namespace coreinit
}
cemu_assert_debug(__OSIsThreadActive(thread) == false);
__OSUnlockScheduler();
- memset(thread, 0x00, sizeof(OSThread_t));
- // init signatures
- thread->SetMagic();
- thread->type = threadType;
- thread->state = (entryPoint != MPTR_NULL) ? OSThread_t::THREAD_STATE::STATE_READY : OSThread_t::THREAD_STATE::STATE_NONE;
- thread->entrypoint = _swapEndianU32(entryPoint);
- __OSSetThreadBasePriority(thread, 0);
- __OSUpdateThreadEffectivePriority(thread);
- // untested, but seems to work (Batman Arkham City uses these values to calculate the stack size for duplicated threads)
- thread->stackBase = _swapEndianU32(stackLowerBaseAddr + stackSize); // these fields are quite important and lots of games rely on them being accurate (Examples: Darksiders 2, SMW3D, Batman Arkham City)
- thread->stackEnd = _swapEndianU32(stackLowerBaseAddr);
- // init stackpointer
- thread->context.gpr[GPR_SP] = _swapEndianU32(stackLowerBaseAddr + stackSize - 0x20); // how many free bytes should there be at the beginning of the stack?
- // init misc stuff
- thread->attr = affinityMask;
- thread->context.setAffinity(affinityMask);
- thread->context.srr0 = PPCInterpreter_makeCallableExportDepr(threadEntry);
- thread->context.lr = _swapEndianU32(PPCInterpreter_makeCallableExportDepr(coreinitExport_OSExitThreadDepr));
- thread->id = 0x8000; // Warriors Orochi 3 softlocks if this is zero due to confusing threads (_OSActivateThread should set this?)
- // init ugqr
- thread->context.gqr[0] = 0x00000000;
- thread->context.gqr[1] = 0x00000000;
- thread->context.gqr[2] = 0x00040004;
- thread->context.gqr[3] = 0x00050005;
- thread->context.gqr[4] = 0x00060006;
- thread->context.gqr[5] = 0x00070007;
- thread->context.gqr[6] = 0x00000000;
- thread->context.gqr[7] = 0x00000000;
- // init r2 (SDA2) and r3 (SDA)
- thread->context.gpr[2] = _swapEndianU32(RPLLoader_GetSDA2Base());
- thread->context.gpr[13] = _swapEndianU32(RPLLoader_GetSDA1Base());
- // GHS related thread init?
+ }
- __OSLockScheduler();
- // if entrypoint is non-zero then put the thread on the active list and suspend it
- if (entryPoint != MPTR_NULL)
+ bool __OSCreateThreadInternal2(OSThread_t* thread, MEMPTR entrypoint, uint32 argInt, MEMPTR argPtr, MEMPTR stackBase, uint32 stackSize, sint32 priority, uint32 attrBits, OSThread_t::THREAD_TYPE threadType)
+ {
+ __OSCreateThreadOnActiveThreadWorkaround(thread);
+ OSThread_t* currentThread = OSGetCurrentThread();
+ if (priority < 0 || priority >= 32)
{
- thread->suspendCounter = 1;
- __OSActivateThread(thread);
- thread->state = OSThread_t::THREAD_STATE::STATE_READY;
+ cemuLog_log(LogType::APIErrors, "OSCreateThreadInternal: Thread priority must be in range 0-31");
+ return false;
+ }
+ if (threadType == OSThread_t::THREAD_TYPE::TYPE_IO)
+ {
+ priority = priority + 0x20;
+ }
+ else if (threadType == OSThread_t::THREAD_TYPE::TYPE_APP)
+ {
+ priority = priority + 0x40;
+ }
+ if(attrBits >= 0x20 || stackBase == nullptr || stackSize == 0)
+ {
+ cemuLog_logDebug(LogType::APIErrors, "OSCreateThreadInternal: Invalid attributes, stack base or size");
+ return false;
+ }
+ uint32 im = OSDisableInterrupts();
+ __OSLockScheduler(thread);
+
+ uint32 coreIndex = PPCInterpreter_getCurrentInstance() ? OSGetCoreId() : 1;
+ __OSThreadInit(thread, entrypoint, argInt, argPtr, stackBase, stackSize, priority, coreIndex, threadType);
+ thread->threadName = nullptr;
+ thread->context.affinity = attrBits & 7;
+ thread->attr = attrBits;
+ if ((attrBits & 7) == 0) // if no explicit affinity is given, use the current core
+ SetThreadAffinityToCore(thread, OSGetCoreId());
+ if(currentThread)
+ {
+ for(sint32 i=0; idsiCallback[i] = currentThread->dsiCallback[i];
+ thread->isiCallback[i] = currentThread->isiCallback[i];
+ thread->programCallback[i] = currentThread->programCallback[i];
+ thread->perfMonCallback[i] = currentThread->perfMonCallback[i];
+ thread->alignmentExceptionCallback[i] = currentThread->alignmentExceptionCallback[i];
+ }
+ thread->context.srr1 = thread->context.srr1 | (currentThread->context.srr1 & 0x900);
+ thread->context.fpscr.fpscr = thread->context.fpscr.fpscr | (currentThread->context.fpscr.fpscr & 0xF8);
}
else
- thread->suspendCounter = 0;
- __OSUnlockScheduler();
+ {
+ for(sint32 i=0; idsiCallback[i] = 0;
+ thread->isiCallback[i] = 0;
+ thread->programCallback[i] = 0;
+ thread->perfMonCallback[i] = 0;
+ thread->alignmentExceptionCallback[i] = nullptr;
+ }
+ }
+ if (entrypoint)
+ {
+ thread->id = 0x8000;
+ __OSActivateThread(thread); // also handles adding the thread to g_activeThreadQueue
+ }
+ __OSUnlockScheduler(thread);
+ OSRestoreInterrupts(im);
+ // recompile entry point function
+ if (entrypoint)
+ PPCRecompiler_recompileIfUnvisited(entrypoint.GetMPTR());
+ return true;
}
bool OSCreateThreadType(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop, sint32 stackSize, sint32 priority, uint32 attr, OSThread_t::THREAD_TYPE threadType)
{
- OSCreateThreadInternal(thread, entryPoint, memory_getVirtualOffsetFromPointer(stackTop) - stackSize, stackSize, attr, threadType);
- thread->context.gpr[3] = _swapEndianU32(numParam); // num arguments
- thread->context.gpr[4] = _swapEndianU32(memory_getVirtualOffsetFromPointer(ptrParam)); // arguments pointer
- __OSSetThreadBasePriority(thread, priority);
- __OSUpdateThreadEffectivePriority(thread);
- // set affinity
- uint8 affinityMask = 0;
- affinityMask = attr & 0x7;
- // if no core is selected -> set current one
- if (affinityMask == 0)
- affinityMask |= (1 << PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance()));
- // set attr
- // todo: Support for other attr bits
- thread->attr = (affinityMask & 0xFF) | (attr & OSThread_t::ATTR_BIT::ATTR_DETACHED);
- thread->context.setAffinity(affinityMask);
- // recompile entry point function
- if (entryPoint != MPTR_NULL)
- PPCRecompiler_recompileIfUnvisited(entryPoint);
- return true;
+ if(threadType != OSThread_t::THREAD_TYPE::TYPE_APP && threadType != OSThread_t::THREAD_TYPE::TYPE_IO)
+ {
+ cemuLog_logDebug(LogType::APIErrors, "OSCreateThreadType: Invalid thread type");
+ cemu_assert_suspicious();
+ return false;
+ }
+ return __OSCreateThreadInternal2(thread, MEMPTR(entryPoint), numParam, ptrParam, stackTop, stackSize, priority, attr, threadType);
}
bool OSCreateThread(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop, sint32 stackSize, sint32 priority, uint32 attr)
{
- return OSCreateThreadType(thread, entryPoint, numParam, ptrParam, stackTop, stackSize, priority, attr, OSThread_t::THREAD_TYPE::TYPE_APP);
+ return __OSCreateThreadInternal2(thread, MEMPTR(entryPoint), numParam, ptrParam, stackTop, stackSize, priority, attr, OSThread_t::THREAD_TYPE::TYPE_APP);
}
- // alias to OSCreateThreadType, similar to OSCreateThread, but with an additional parameter for the thread type
+ // similar to OSCreateThreadType, but can be used to create any type of thread
bool __OSCreateThreadType(OSThread_t* thread, MPTR entryPoint, sint32 numParam, void* ptrParam, void* stackTop, sint32 stackSize, sint32 priority, uint32 attr, OSThread_t::THREAD_TYPE threadType)
{
- return OSCreateThreadType(thread, entryPoint, numParam, ptrParam, stackTop, stackSize, priority, attr, threadType);
+ return __OSCreateThreadInternal2(thread, MEMPTR(entryPoint), numParam, ptrParam, stackTop, stackSize, priority, attr, threadType);
}
bool OSRunThread(OSThread_t* thread, MPTR funcAddress, sint32 numParam, void* ptrParam)
@@ -352,7 +522,7 @@ namespace coreinit
// set thread state
// todo - this should fully reinitialize the thread?
- thread->entrypoint = _swapEndianU32(funcAddress);
+ thread->entrypoint = funcAddress;
thread->context.srr0 = PPCInterpreter_makeCallableExportDepr(threadEntry);
thread->context.lr = _swapEndianU32(PPCInterpreter_makeCallableExportDepr(coreinitExport_OSExitThreadDepr));
thread->context.gpr[3] = _swapEndianU32(numParam);
@@ -378,10 +548,10 @@ namespace coreinit
OSThread_t* currentThread = coreinit::OSGetCurrentThread();
// thread cleanup callback
- if (!currentThread->cleanupCallback2.IsNull())
+ if (currentThread->cleanupCallback)
{
currentThread->stateFlags = _swapEndianU32(_swapEndianU32(currentThread->stateFlags) | 0x00000001);
- PPCCoreCallback(currentThread->cleanupCallback2.GetMPTR(), currentThread, _swapEndianU32(currentThread->stackEnd));
+ PPCCoreCallback(currentThread->cleanupCallback.GetMPTR(), currentThread, currentThread->stackEnd);
}
// cpp exception cleanup
if (gCoreinitData->__cpp_exception_cleanup_ptr != 0 && currentThread->crt.eh_globals != nullptr)
@@ -602,7 +772,10 @@ namespace coreinit
sint32 previousSuspendCount = thread->suspendCounter;
cemu_assert_debug(previousSuspendCount >= 0);
if (previousSuspendCount == 0)
+ {
+ cemuLog_log(LogType::APIErrors, "OSResumeThread: Resuming thread 0x{:08x} which isn't suspended", MEMPTR(thread).GetMPTR());
return 0;
+ }
thread->suspendCounter = previousSuspendCount - resumeCount;
if (thread->suspendCounter < 0)
thread->suspendCounter = 0;
@@ -732,8 +905,8 @@ namespace coreinit
void* OSSetThreadCleanupCallback(OSThread_t* thread, void* cleanupCallback)
{
__OSLockScheduler();
- void* previousFunc = thread->cleanupCallback2.GetPtr();
- thread->cleanupCallback2 = cleanupCallback;
+ void* previousFunc = thread->cleanupCallback.GetPtr();
+ thread->cleanupCallback = cleanupCallback;
__OSUnlockScheduler();
return previousFunc;
}
@@ -1341,7 +1514,7 @@ namespace coreinit
void __OSQueueThreadDeallocation(OSThread_t* thread)
{
uint32 coreIndex = OSGetCoreId();
- TerminatorThread::DeallocatorQueueEntry queueEntry(thread, memory_getPointerFromVirtualOffset(_swapEndianU32(thread->stackEnd)), thread->deallocatorFunc);
+ TerminatorThread::DeallocatorQueueEntry queueEntry(thread, thread->stackEnd, thread->deallocatorFunc);
s_terminatorThreads[coreIndex].queueDeallocators.push(queueEntry);
OSSignalSemaphoreInternal(s_terminatorThreads[coreIndex].semaphoreQueuedDeallocators.GetPtr(), false); // do not reschedule here! Current thread must not be interrupted otherwise deallocator will run too early
}
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Thread.h b/src/Cafe/OS/libs/coreinit/coreinit_Thread.h
index b401d96d..fdbcfea7 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Thread.h
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Thread.h
@@ -2,9 +2,6 @@
#include "Cafe/HW/Espresso/Const.h"
#include "Cafe/OS/libs/coreinit/coreinit_Scheduler.h"
-#define OS_CONTEXT_MAGIC_0 'OSCo'
-#define OS_CONTEXT_MAGIC_1 'ntxt'
-
struct OSThread_t;
struct OSContextRegFPSCR_t
@@ -16,6 +13,9 @@ struct OSContextRegFPSCR_t
struct OSContext_t
{
+ static constexpr uint32 OS_CONTEXT_MAGIC_0 = 0x4f53436f; // "OSCo"
+ static constexpr uint32 OS_CONTEXT_MAGIC_1 = 0x6e747874; // "ntxt"
+
/* +0x000 */ betype magic0;
/* +0x004 */ betype magic1;
/* +0x008 */ uint32 gpr[32];
@@ -36,24 +36,29 @@ struct OSContext_t
/* +0x1BC */ uint32 gqr[8]; // GQR/UGQR
/* +0x1DC */ uint32be upir; // set to current core index
/* +0x1E0 */ uint64be fp_ps1[32];
- /* +0x2E0 */ uint64 uknTime2E0;
- /* +0x2E8 */ uint64 uknTime2E8;
- /* +0x2F0 */ uint64 uknTime2F0;
- /* +0x2F8 */ uint64 uknTime2F8;
- /* +0x300 */ uint32 error; // returned by __gh_errno_ptr() (used by socketlasterr)
+ /* +0x2E0 */ uint64be coretime[3];
+ /* +0x2F8 */ uint64be starttime;
+ /* +0x300 */ uint32be ghs_errno; // returned by __gh_errno_ptr() (used by socketlasterr)
/* +0x304 */ uint32be affinity;
- /* +0x308 */ uint32 ukn0308;
- /* +0x30C */ uint32 ukn030C;
- /* +0x310 */ uint32 ukn0310;
- /* +0x314 */ uint32 ukn0314;
- /* +0x318 */ uint32 ukn0318;
- /* +0x31C */ uint32 ukn031C;
+ /* +0x308 */ uint32be upmc1;
+ /* +0x30C */ uint32be upmc2;
+ /* +0x310 */ uint32be upmc3;
+ /* +0x314 */ uint32be upmc4;
+ /* +0x318 */ uint32be ummcr0;
+ /* +0x31C */ uint32be ummcr1;
bool checkMagic()
{
return magic0 == (uint32)OS_CONTEXT_MAGIC_0 && magic1 == (uint32)OS_CONTEXT_MAGIC_1;
}
+ void SetContextMagic()
+ {
+ magic0 = OS_CONTEXT_MAGIC_0;
+ magic1 = OS_CONTEXT_MAGIC_1;
+ }
+
+
bool hasCoreAffinitySet(uint32 coreIndex) const
{
return (((uint32)affinity >> coreIndex) & 1) != 0;
@@ -361,6 +366,8 @@ namespace coreinit
struct OSThread_t
{
+ static constexpr uint32 MAGIC_THREAD = 0x74487244; // "tHrD"
+
enum class THREAD_TYPE : uint32
{
TYPE_DRIVER = 0,
@@ -383,7 +390,7 @@ struct OSThread_t
ATTR_AFFINITY_CORE1 = 0x2,
ATTR_AFFINITY_CORE2 = 0x4,
ATTR_DETACHED = 0x8,
- // more flags?
+ ATTR_UKN_010 = 0x10,
};
enum REQUEST_FLAG_BIT : uint32
@@ -404,23 +411,21 @@ struct OSThread_t
return 0;
}
- void SetMagic()
+ void SetThreadMagic()
{
- context.magic0 = OS_CONTEXT_MAGIC_0;
- context.magic1 = OS_CONTEXT_MAGIC_1;
- magic = 'tHrD';
+ magic = MAGIC_THREAD;
}
bool IsValidMagic() const
{
- return magic == 'tHrD' && context.magic0 == OS_CONTEXT_MAGIC_0 && context.magic1 == OS_CONTEXT_MAGIC_1;
+ return magic == MAGIC_THREAD && context.magic0 == OSContext_t::OS_CONTEXT_MAGIC_0 && context.magic1 == OSContext_t::OS_CONTEXT_MAGIC_1;
}
/* +0x000 */ OSContext_t context;
- /* +0x320 */ uint32be magic; // 'tHrD'
+ /* +0x320 */ uint32be magic; // "tHrD" (0x74487244)
/* +0x324 */ betype state;
/* +0x325 */ uint8 attr;
- /* +0x326 */ uint16be id; // Warriors Orochi 3 uses this to identify threads. Seems like this is always set to 0x8000 ?
+ /* +0x326 */ uint16be id; // Warriors Orochi 3 uses this to identify threads
/* +0x328 */ betype suspendCounter;
/* +0x32C */ sint32be effectivePriority; // effective priority (lower is higher)
/* +0x330 */ sint32be basePriority; // base priority (lower is higher)
@@ -440,21 +445,21 @@ struct OSThread_t
/* +0x38C */ coreinit::OSThreadLink activeThreadChain; // queue of active threads (g_activeThreadQueue)
- /* +0x394 */ MPTR stackBase; // upper limit of stack
- /* +0x398 */ MPTR stackEnd; // lower limit of stack
+ /* +0x394 */ MEMPTR stackBase; // upper limit of stack
+ /* +0x398 */ MEMPTR stackEnd; // lower limit of stack
- /* +0x39C */ MPTR entrypoint;
+ /* +0x39C */ MEMPTR entrypoint;
/* +0x3A0 */ crt_t crt;
/* +0x578 */ sint32 alarmRelatedUkn;
/* +0x57C */ std::array, 16> specificArray;
/* +0x5BC */ betype type;
/* +0x5C0 */ MEMPTR threadName;
- /* +0x5C4 */ MPTR waitAlarm; // used only by OSWaitEventWithTimeout/OSSignalEvent ?
+ /* +0x5C4 */ MEMPTR waitAlarm; // used only by OSWaitEventWithTimeout/OSSignalEvent ?
/* +0x5C8 */ uint32 userStackPointer;
- /* +0x5CC */ MEMPTR cleanupCallback2;
+ /* +0x5CC */ MEMPTR cleanupCallback;
/* +0x5D0 */ MEMPTR deallocatorFunc;
/* +0x5D4 */ uint32 stateFlags; // 0x5D4 | various flags? Controls if canceling/suspension is allowed (at cancel points) or not? If 1 -> Cancel/Suspension not allowed, if 0 -> Cancel/Suspension allowed
@@ -480,19 +485,21 @@ struct OSThread_t
/* +0x660 */ uint32 ukn660;
+ // todo - some of the members towards the end of the struct were only added in later COS versions. Figure out the mapping between version and members
+
// TLS
/* +0x664 */ uint16 numAllocatedTLSBlocks;
/* +0x666 */ sint16 tlsStatus;
/* +0x668 */ MPTR tlsBlocksMPTR;
-
+
/* +0x66C */ MEMPTR waitingForFastMutex;
/* +0x670 */ coreinit::OSFastMutexLink contendedFastMutex;
/* +0x678 */ coreinit::OSFastMutexLink ownedFastMutex;
+ /* +0x680 */ MEMPTR alignmentExceptionCallback[Espresso::CORE_COUNT];
- /* +0x680 */ uint32 padding680[28 / 4];
+ /* +0x68C */ uint32 padding68C[20 / 4];
};
-
-static_assert(sizeof(OSThread_t) == 0x6A0-4); // todo - determine correct size
+static_assert(sizeof(OSThread_t) == 0x6A0);
namespace coreinit
{
diff --git a/src/Cafe/OS/libs/nsysnet/nsysnet.cpp b/src/Cafe/OS/libs/nsysnet/nsysnet.cpp
index 88bca8af..dd7c9189 100644
--- a/src/Cafe/OS/libs/nsysnet/nsysnet.cpp
+++ b/src/Cafe/OS/libs/nsysnet/nsysnet.cpp
@@ -117,10 +117,10 @@ void nsysnetExport_socket_lib_finish(PPCInterpreter_t* hCPU)
osLib_returnFromFunction(hCPU, 0); // 0 -> Success
}
-uint32* __gh_errno_ptr()
+static uint32be* __gh_errno_ptr()
{
OSThread_t* osThread = coreinit::OSGetCurrentThread();
- return &osThread->context.error;
+ return &osThread->context.ghs_errno;
}
void _setSockError(sint32 errCode)
diff --git a/src/Cafe/OS/libs/snd_core/ax_ist.cpp b/src/Cafe/OS/libs/snd_core/ax_ist.cpp
index 30cbdbb1..17f247e0 100644
--- a/src/Cafe/OS/libs/snd_core/ax_ist.cpp
+++ b/src/Cafe/OS/libs/snd_core/ax_ist.cpp
@@ -963,7 +963,7 @@ namespace snd_core
OSInitMessageQueue(__AXIstThreadMsgQueue.GetPtr(), __AXIstThreadMsgArray.GetPtr(), 0x10);
// create thread
uint8 istThreadAttr = 0;
- coreinit::OSCreateThreadType(__AXIstThread.GetPtr(), PPCInterpreter_makeCallableExportDepr(AXIst_ThreadEntry), 0, &__AXIstThreadMsgQueue, __AXIstThreadStack.GetPtr() + 0x4000, 0x4000, 14, istThreadAttr, OSThread_t::THREAD_TYPE::TYPE_DRIVER);
+ coreinit::__OSCreateThreadType(__AXIstThread.GetPtr(), PPCInterpreter_makeCallableExportDepr(AXIst_ThreadEntry), 0, &__AXIstThreadMsgQueue, __AXIstThreadStack.GetPtr() + 0x4000, 0x4000, 14, istThreadAttr, OSThread_t::THREAD_TYPE::TYPE_DRIVER);
coreinit::OSResumeThread(__AXIstThread.GetPtr());
}
diff --git a/src/Common/ExceptionHandler/ExceptionHandler.cpp b/src/Common/ExceptionHandler/ExceptionHandler.cpp
index 5fefc8ca..b6755fd8 100644
--- a/src/Common/ExceptionHandler/ExceptionHandler.cpp
+++ b/src/Common/ExceptionHandler/ExceptionHandler.cpp
@@ -155,7 +155,7 @@ void ExceptionHandler_LogGeneralInfo()
const char* threadName = "NULL";
if (!threadItrBE->threadName.IsNull())
threadName = threadItrBE->threadName.GetPtr();
- sprintf(dumpLine, "%08x Ent %08x IP %08x LR %08x %-9s Aff %d%d%d Pri %2d Name %s", threadItrMPTR, _swapEndianU32(threadItrBE->entrypoint), threadItrBE->context.srr0, _swapEndianU32(threadItrBE->context.lr), threadStateStr, (affinity >> 0) & 1, (affinity >> 1) & 1, (affinity >> 2) & 1, effectivePriority, threadName);
+ sprintf(dumpLine, "%08x Ent %08x IP %08x LR %08x %-9s Aff %d%d%d Pri %2d Name %s", threadItrMPTR, threadItrBE->entrypoint.GetMPTR(), threadItrBE->context.srr0, _swapEndianU32(threadItrBE->context.lr), threadStateStr, (affinity >> 0) & 1, (affinity >> 1) & 1, (affinity >> 2) & 1, effectivePriority, threadName);
// write line to log
CrashLog_WriteLine(dumpLine);
}
diff --git a/src/gui/windows/PPCThreadsViewer/DebugPPCThreadsWindow.cpp b/src/gui/windows/PPCThreadsViewer/DebugPPCThreadsWindow.cpp
index bd71942f..dfbaf76e 100644
--- a/src/gui/windows/PPCThreadsViewer/DebugPPCThreadsWindow.cpp
+++ b/src/gui/windows/PPCThreadsViewer/DebugPPCThreadsWindow.cpp
@@ -195,10 +195,10 @@ void DebugPPCThreadsWindow::RefreshThreadList()
m_thread_list->InsertItem(item);
m_thread_list->SetItemData(item, (long)threadItrMPTR);
// entry point
- sprintf(tempStr, "%08X", _swapEndianU32(cafeThread->entrypoint));
+ sprintf(tempStr, "%08X", cafeThread->entrypoint.GetMPTR());
m_thread_list->SetItem(i, 1, tempStr);
// stack base (low)
- sprintf(tempStr, "%08X - %08X", _swapEndianU32(cafeThread->stackEnd), _swapEndianU32(cafeThread->stackBase));
+ sprintf(tempStr, "%08X - %08X", cafeThread->stackEnd.GetMPTR(), cafeThread->stackBase.GetMPTR());
m_thread_list->SetItem(i, 2, tempStr);
// pc
RPLStoredSymbol* symbol = rplSymbolStorage_getByAddress(cafeThread->context.srr0);
From 91a010fbdd023b3cac85f455fb3c32de3d2c3784 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Sat, 4 May 2024 08:05:10 +0200
Subject: [PATCH 012/216] proc_ui: Fix crash due to incorrect version handling
Resolves a crash in NEX Remix
---
src/Cafe/OS/libs/proc_ui/proc_ui.cpp | 3 +++
src/Cafe/TitleList/TitleInfo.cpp | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/Cafe/OS/libs/proc_ui/proc_ui.cpp b/src/Cafe/OS/libs/proc_ui/proc_ui.cpp
index 5560568d..dd9a460f 100644
--- a/src/Cafe/OS/libs/proc_ui/proc_ui.cpp
+++ b/src/Cafe/OS/libs/proc_ui/proc_ui.cpp
@@ -391,6 +391,9 @@ namespace proc_ui
{
cemuLog_log(LogType::Force, "ProcUI: Trying to register callback before init");
cemu_assert_suspicious();
+ // this shouldn't happen but lets set the memory pointers anyway to prevent a crash in case the user has incorrect meta info
+ s_memAllocPtr = gCoreinitData->MEMAllocFromDefaultHeap.GetMPTR();
+ s_memFreePtr = gCoreinitData->MEMFreeToDefaultHeap.GetMPTR();
}
ProcUIInternalCallbackEntry* entry = (ProcUIInternalCallbackEntry*)_AllocMem(sizeof(ProcUIInternalCallbackEntry));
entry->funcPtr = funcPtr;
diff --git a/src/Cafe/TitleList/TitleInfo.cpp b/src/Cafe/TitleList/TitleInfo.cpp
index 6d21929e..2f295811 100644
--- a/src/Cafe/TitleList/TitleInfo.cpp
+++ b/src/Cafe/TitleList/TitleInfo.cpp
@@ -563,7 +563,7 @@ bool TitleInfo::ParseAppXml(std::vector& appXmlData)
else if (name == "group_id")
m_parsedAppXml->group_id = (uint32)std::stoull(child.text().as_string(), nullptr, 16);
else if (name == "sdk_version")
- m_parsedAppXml->sdk_version = (uint32)std::stoull(child.text().as_string(), nullptr, 16);
+ m_parsedAppXml->sdk_version = (uint32)std::stoull(child.text().as_string(), nullptr, 10);
}
return true;
}
From 48d2a8371b3b35b2a4439e1475c694856728f4ec Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Sun, 5 May 2024 01:27:39 +0200
Subject: [PATCH 013/216] sndcore: Write log message instead of asserting in
AXSetDeviceRemixMatrix
Fixes a crash in Watch Dogs due to the non-debug assert
---
src/Cafe/OS/libs/snd_core/ax_ist.cpp | 33 ++++++++++++++++++++--------
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/src/Cafe/OS/libs/snd_core/ax_ist.cpp b/src/Cafe/OS/libs/snd_core/ax_ist.cpp
index 17f247e0..2ea27cbb 100644
--- a/src/Cafe/OS/libs/snd_core/ax_ist.cpp
+++ b/src/Cafe/OS/libs/snd_core/ax_ist.cpp
@@ -218,21 +218,36 @@ namespace snd_core
// validate parameters
if (deviceId == AX_DEV_TV)
{
- cemu_assert(inputChannelCount <= AX_TV_CHANNEL_COUNT);
- cemu_assert(outputChannelCount == 1 || outputChannelCount == 2 || outputChannelCount == 6);
+ if(inputChannelCount > AX_TV_CHANNEL_COUNT)
+ {
+ cemuLog_log(LogType::APIErrors, "AXSetDeviceRemixMatrix: Input channel count must be smaller or equal to 6 for TV device");
+ return -7;
+ }
+ if(outputChannelCount != 1 && outputChannelCount != 2 && outputChannelCount != 6)
+ {
+ // seems like Watch Dogs uses 4 as outputChannelCount for some reason?
+ cemuLog_log(LogType::APIErrors, "AXSetDeviceRemixMatrix: Output channel count must be 1, 2 or 6 for TV device");
+ return -8;
+ }
}
else if (deviceId == AX_DEV_DRC)
{
- cemu_assert(inputChannelCount <= AX_DRC_CHANNEL_COUNT);
- cemu_assert(outputChannelCount == 1 || outputChannelCount == 2 || outputChannelCount == 4);
- }
- else if (deviceId == AX_DEV_RMT)
- {
- cemu_assert(false);
+ if(inputChannelCount > AX_DRC_CHANNEL_COUNT)
+ {
+ cemuLog_log(LogType::APIErrors, "AXSetDeviceRemixMatrix: Input channel count must be smaller or equal to 4 for DRC device");
+ return -7;
+ }
+ if(outputChannelCount != 1 && outputChannelCount != 2 && outputChannelCount != 4)
+ {
+ cemuLog_log(LogType::APIErrors, "AXSetDeviceRemixMatrix: Output channel count must be 1, 2 or 4 for DRC device");
+ return -8;
+ }
}
else
+ {
+ cemuLog_log(LogType::APIErrors, "AXSetDeviceRemixMatrix: Only TV (0) and DRC (1) device are supported");
return -1;
-
+ }
auto matrices = g_remix_matrices.GetPtr();
// test if we already have an entry and just need to update the matrix data
From a744670486cf27e14dd884d3a1b2ee04dc05a8cb Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Sun, 5 May 2024 01:28:08 +0200
Subject: [PATCH 014/216] coreinit: Add export for
OSGetForegroundBucketFreeArea
---
src/Cafe/OS/libs/coreinit/coreinit_FG.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FG.cpp b/src/Cafe/OS/libs/coreinit/coreinit_FG.cpp
index b751a8fd..e22c3eb3 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_FG.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_FG.cpp
@@ -185,6 +185,7 @@ namespace coreinit
{
osLib_addFunction("coreinit", "OSGetForegroundBucket", coreinitExport_OSGetForegroundBucket);
cafeExportRegister("coreinit", OSGetForegroundBucket, LogType::CoreinitMem);
+ cafeExportRegister("coreinit", OSGetForegroundBucketFreeArea, LogType::CoreinitMem);
osLib_addFunction("coreinit", "OSCopyFromClipboard", coreinitExport_OSCopyFromClipboard);
}
}
From f28043e0e969f5ff5e8ad1e5eea8964ebf6f2523 Mon Sep 17 00:00:00 2001
From: qurious-pixel <62252937+qurious-pixel@users.noreply.github.com>
Date: Sat, 4 May 2024 16:34:36 -0700
Subject: [PATCH 015/216] Linux/Mac Auto-Updater (#1145)
---
.github/workflows/build.yml | 20 ++++++------
src/CMakeLists.txt | 1 +
src/gui/CemuUpdateWindow.cpp | 56 +++++++++++++++++++++++++++-----
src/gui/GeneralSettings2.cpp | 10 +++---
src/gui/GettingStartedDialog.cpp | 7 ++--
src/gui/MainWindow.cpp | 8 +++--
src/resource/update.sh | 8 +++++
7 files changed, 82 insertions(+), 28 deletions(-)
create mode 100755 src/resource/update.sh
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 58a8508d..d188b4a1 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: "Checkout repo"
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
submodules: "recursive"
fetch-depth: 0
@@ -91,7 +91,7 @@ jobs:
run: mv bin/Cemu_release bin/Cemu
- name: Upload artifact
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: ${{ inputs.deploymode == 'release' }}
with:
name: cemu-bin-linux-x64
@@ -102,9 +102,9 @@ jobs:
needs: build-ubuntu
steps:
- name: Checkout Upstream Repo
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- - uses: actions/download-artifact@v3
+ - uses: actions/download-artifact@v4
with:
name: cemu-bin-linux-x64
path: bin
@@ -121,7 +121,7 @@ jobs:
dist/linux/appimage.sh
- name: Upload artifact
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: cemu-appimage-x64
path: artifacts
@@ -130,7 +130,7 @@ jobs:
runs-on: windows-2022
steps:
- name: "Checkout repo"
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
submodules: "recursive"
@@ -200,7 +200,7 @@ jobs:
run: Rename-Item bin/Cemu_release.exe Cemu.exe
- name: Upload artifact
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: ${{ inputs.deploymode == 'release' }}
with:
name: cemu-bin-windows-x64
@@ -210,7 +210,7 @@ jobs:
runs-on: macos-12
steps:
- name: "Checkout repo"
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
submodules: "recursive"
@@ -289,14 +289,14 @@ jobs:
mv bin/Cemu_release.app bin/Cemu_app/Cemu.app
mv bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu_release bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu
sed -i '' 's/Cemu_release/Cemu/g' bin/Cemu_app/Cemu.app/Contents/Info.plist
- chmod a+x bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu
+ chmod a+x bin/Cemu_app/Cemu.app/Contents/MacOS/{Cemu,update.sh}
ln -s /Applications bin/Cemu_app/Applications
hdiutil create ./bin/tmp.dmg -ov -volname "Cemu" -fs HFS+ -srcfolder "./bin/Cemu_app"
hdiutil convert ./bin/tmp.dmg -format UDZO -o bin/Cemu.dmg
rm bin/tmp.dmg
- name: Upload artifact
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: ${{ inputs.deploymode == 'release' }}
with:
name: cemu-bin-macos-x64
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7442e37c..1b78b1fb 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -98,6 +98,7 @@ if (MACOS_BUNDLE)
add_custom_command (TARGET CemuBin POST_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy "/usr/local/lib/libMoltenVK.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib"
COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_BINARY_DIR}/vcpkg_installed/x64-osx/lib/libusb-1.0.0.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libusb-1.0.0.dylib"
+ COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_SOURCE_DIR}/src/resource/update.sh" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/update.sh"
COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}"
COMMAND bash -c "install_name_tool -change /usr/local/opt/libusb/lib/libusb-1.0.0.dylib @executable_path/../Frameworks/libusb-1.0.0.dylib ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}")
endif()
diff --git a/src/gui/CemuUpdateWindow.cpp b/src/gui/CemuUpdateWindow.cpp
index 91394ee2..445c7c17 100644
--- a/src/gui/CemuUpdateWindow.cpp
+++ b/src/gui/CemuUpdateWindow.cpp
@@ -12,6 +12,11 @@
#include
#include
+#ifndef BOOST_OS_WINDOWS
+#include
+#include
+#endif
+
#include
#include
#include
@@ -105,11 +110,11 @@ bool CemuUpdateWindow::QueryUpdateInfo(std::string& downloadUrlOut, std::string&
auto* curl = curl_easy_init();
urlStr.append(_curlUrlEscape(curl, BUILD_VERSION_STRING));
#if BOOST_OS_LINUX
- urlStr.append("&platform=linux");
+ urlStr.append("&platform=linux_appimage_x86");
#elif BOOST_OS_WINDOWS
urlStr.append("&platform=windows");
#elif BOOST_OS_MACOS
- urlStr.append("&platform=macos_x86");
+ urlStr.append("&platform=macos_bundle_x86");
#elif
#error Name for current platform is missing
@@ -407,7 +412,13 @@ void CemuUpdateWindow::WorkerThread()
if (!exists(tmppath))
create_directory(tmppath);
+#if BOOST_OS_WINDOWS
const auto update_file = tmppath / L"update.zip";
+#elif BOOST_OS_LINUX
+ const auto update_file = tmppath / L"Cemu.AppImage";
+#elif BOOST_OS_MACOS
+ const auto update_file = tmppath / L"cemu.dmg";
+#endif
if (DownloadCemuZip(url, update_file))
{
auto* event = new wxCommandEvent(wxEVT_RESULT);
@@ -427,6 +438,7 @@ void CemuUpdateWindow::WorkerThread()
// extract
std::string cemuFolderName;
+#if BOOST_OS_WINDOWS
if (!ExtractUpdate(update_file, tmppath, cemuFolderName))
{
cemuLog_log(LogType::Force, "Extracting Cemu zip failed");
@@ -437,7 +449,7 @@ void CemuUpdateWindow::WorkerThread()
cemuLog_log(LogType::Force, "Cemu folder not found in zip");
break;
}
-
+#endif
const auto expected_path = tmppath / cemuFolderName;
if (exists(expected_path))
{
@@ -472,6 +484,7 @@ void CemuUpdateWindow::WorkerThread()
// apply update
fs::path exePath = ActiveSettings::GetExecutablePath();
+#if BOOST_OS_WINDOWS
std::wstring target_directory = exePath.parent_path().generic_wstring();
if (target_directory[target_directory.size() - 1] == '/')
target_directory = target_directory.substr(0, target_directory.size() - 1); // remove trailing /
@@ -480,8 +493,19 @@ void CemuUpdateWindow::WorkerThread()
const auto exec = ActiveSettings::GetExecutablePath();
const auto target_exe = fs::path(exec).replace_extension("exe.backup");
fs::rename(exec, target_exe);
- m_restartFile = exec;
-
+ m_restartFile = exec;
+#elif BOOST_OS_LINUX
+ const char* appimage_path = std::getenv("APPIMAGE");
+ const auto target_exe = fs::path(appimage_path).replace_extension("AppImage.backup");
+ const char* filePath = update_file.c_str();
+ mode_t permissions = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+ fs::rename(appimage_path, target_exe);
+ m_restartFile = appimage_path;
+ chmod(filePath, permissions);
+ wxString wxAppPath = wxString::FromUTF8(appimage_path);
+ wxCopyFile (wxT("/tmp/cemu_update/Cemu.AppImage"), wxAppPath);
+#endif
+#if BOOST_OS_WINDOWS
const auto index = expected_path.wstring().size();
int counter = 0;
for (const auto& it : fs::recursive_directory_iterator(expected_path))
@@ -516,7 +540,7 @@ void CemuUpdateWindow::WorkerThread()
wxQueueEvent(this, event);
}
}
-
+#endif
auto* event = new wxCommandEvent(wxEVT_PROGRESS);
event->SetInt(m_gaugeMaxValue);
wxQueueEvent(this, event);
@@ -565,8 +589,24 @@ void CemuUpdateWindow::OnClose(wxCloseEvent& event)
exit(0);
}
-#else
- cemuLog_log(LogType::Force, "unimplemented - restart on update");
+#elif BOOST_OS_LINUX
+ if (m_restartRequired && !m_restartFile.empty() && fs::exists(m_restartFile))
+ {
+ const char* appimage_path = std::getenv("APPIMAGE");
+ execlp(appimage_path, appimage_path, (char *)NULL);
+
+ exit(0);
+ }
+#elif BOOST_OS_MACOS
+ if (m_restartRequired)
+ {
+ const auto tmppath = fs::temp_directory_path() / L"cemu_update/Cemu.dmg";
+ fs::path exePath = ActiveSettings::GetExecutablePath().parent_path();
+ const auto apppath = exePath / L"update.sh";
+ execlp("sh", "sh", apppath.c_str(), NULL);
+
+ exit(0);
+ }
#endif
}
diff --git a/src/gui/GeneralSettings2.cpp b/src/gui/GeneralSettings2.cpp
index 27ce37fa..dab30981 100644
--- a/src/gui/GeneralSettings2.cpp
+++ b/src/gui/GeneralSettings2.cpp
@@ -166,9 +166,11 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook)
m_auto_update = new wxCheckBox(box, wxID_ANY, _("Automatically check for updates"));
m_auto_update->SetToolTip(_("Automatically checks for new cemu versions on startup"));
second_row->Add(m_auto_update, 0, botflag, 5);
-#if BOOST_OS_LINUX || BOOST_OS_MACOS
- m_auto_update->Disable();
-#endif
+#if BOOST_OS_LINUX
+ if (!std::getenv("APPIMAGE")) {
+ m_auto_update->Disable();
+ }
+#endif
second_row->AddSpacer(10);
m_save_screenshot = new wxCheckBox(box, wxID_ANY, _("Save screenshot"));
m_save_screenshot->SetToolTip(_("Pressing the screenshot key (F12) will save a screenshot directly to the screenshots folder"));
@@ -2055,4 +2057,4 @@ wxString GeneralSettings2::GetOnlineAccountErrorMessage(OnlineAccountError error
default:
return "no error";
}
-}
\ No newline at end of file
+}
diff --git a/src/gui/GettingStartedDialog.cpp b/src/gui/GettingStartedDialog.cpp
index 91cc3a11..bfd206b1 100644
--- a/src/gui/GettingStartedDialog.cpp
+++ b/src/gui/GettingStartedDialog.cpp
@@ -146,10 +146,11 @@ wxPanel* GettingStartedDialog::CreatePage2()
m_update = new wxCheckBox(sizer->GetStaticBox(), wxID_ANY, _("Automatically check for updates"));
option_sizer->Add(m_update, 0, wxALL, 5);
-#if BOOST_OS_LINUX || BOOST_OS_MACOS
- m_update->Disable();
+#if BOOST_OS_LINUX
+ if (!std::getenv("APPIMAGE")) {
+ m_update->Disable();
+ }
#endif
-
sizer->Add(option_sizer, 1, wxEXPAND, 5);
page2_sizer->Add(sizer, 0, wxALL | wxEXPAND, 5);
}
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index da57870c..e8103f9a 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -2292,9 +2292,11 @@ void MainWindow::RecreateMenu()
// help menu
wxMenu* helpMenu = new wxMenu();
m_check_update_menu = helpMenu->Append(MAINFRAME_MENU_ID_HELP_UPDATE, _("&Check for updates"));
-#if BOOST_OS_LINUX || BOOST_OS_MACOS
- m_check_update_menu->Enable(false);
-#endif
+#if BOOST_OS_LINUX
+ if (!std::getenv("APPIMAGE")) {
+ m_check_update_menu->Enable(false);
+ }
+#endif
helpMenu->Append(MAINFRAME_MENU_ID_HELP_GETTING_STARTED, _("&Getting started"));
helpMenu->AppendSeparator();
helpMenu->Append(MAINFRAME_MENU_ID_HELP_ABOUT, _("&About Cemu"));
diff --git a/src/resource/update.sh b/src/resource/update.sh
new file mode 100755
index 00000000..5ff22160
--- /dev/null
+++ b/src/resource/update.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+APP=$(cd "$(dirname "0")"/;pwd)
+hdiutil attach $TMPDIR/cemu_update/cemu.dmg
+cp -rf /Volumes/Cemu/Cemu.app "$APP"
+hdiutil detach /Volumes/Cemu/
+
+open -n -a "$APP/Cemu.app"
From dc480ac00bc6367f9272c490fbf2a7e4cacee218 Mon Sep 17 00:00:00 2001
From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com>
Date: Sun, 5 May 2024 02:35:01 +0200
Subject: [PATCH 016/216] Add support for WUHB file format (#1190)
---
src/Cafe/CMakeLists.txt | 4 +
src/Cafe/Filesystem/WUHB/RomFSStructs.h | 40 ++++
src/Cafe/Filesystem/WUHB/WUHBReader.cpp | 224 ++++++++++++++++++++++
src/Cafe/Filesystem/WUHB/WUHBReader.h | 45 +++++
src/Cafe/Filesystem/fsc.h | 3 +
src/Cafe/Filesystem/fscDeviceWuhb.cpp | 151 +++++++++++++++
src/Cafe/TitleList/TitleInfo.cpp | 82 ++++++++
src/Cafe/TitleList/TitleInfo.h | 3 +
src/Cafe/TitleList/TitleList.cpp | 3 +-
src/gui/MainWindow.cpp | 6 +-
src/gui/components/wxGameList.cpp | 10 +
src/gui/components/wxTitleManagerList.cpp | 5 +
src/gui/components/wxTitleManagerList.h | 1 +
src/util/helpers/helpers.cpp | 41 ++++
src/util/helpers/helpers.h | 2 +
15 files changed, 617 insertions(+), 3 deletions(-)
create mode 100644 src/Cafe/Filesystem/WUHB/RomFSStructs.h
create mode 100644 src/Cafe/Filesystem/WUHB/WUHBReader.cpp
create mode 100644 src/Cafe/Filesystem/WUHB/WUHBReader.h
create mode 100644 src/Cafe/Filesystem/fscDeviceWuhb.cpp
diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt
index d64a5998..851854fc 100644
--- a/src/Cafe/CMakeLists.txt
+++ b/src/Cafe/CMakeLists.txt
@@ -10,6 +10,7 @@ add_library(CemuCafe
Filesystem/fscDeviceRedirect.cpp
Filesystem/fscDeviceWua.cpp
Filesystem/fscDeviceWud.cpp
+ Filesystem/fscDeviceWuhb.cpp
Filesystem/fsc.h
Filesystem/FST/FST.cpp
Filesystem/FST/FST.h
@@ -18,6 +19,9 @@ add_library(CemuCafe
Filesystem/FST/KeyCache.h
Filesystem/WUD/wud.cpp
Filesystem/WUD/wud.h
+ Filesystem/WUHB/RomFSStructs.h
+ Filesystem/WUHB/WUHBReader.cpp
+ Filesystem/WUHB/WUHBReader.h
GamePatch.cpp
GamePatch.h
GameProfile/GameProfile.cpp
diff --git a/src/Cafe/Filesystem/WUHB/RomFSStructs.h b/src/Cafe/Filesystem/WUHB/RomFSStructs.h
new file mode 100644
index 00000000..59ef503f
--- /dev/null
+++ b/src/Cafe/Filesystem/WUHB/RomFSStructs.h
@@ -0,0 +1,40 @@
+#pragma once
+
+struct romfs_header_t
+{
+ uint32 header_magic;
+ uint32be header_size;
+ uint64be dir_hash_table_ofs;
+ uint64be dir_hash_table_size;
+ uint64be dir_table_ofs;
+ uint64be dir_table_size;
+ uint64be file_hash_table_ofs;
+ uint64be file_hash_table_size;
+ uint64be file_table_ofs;
+ uint64be file_table_size;
+ uint64be file_partition_ofs;
+};
+
+struct romfs_direntry_t
+{
+ uint32be parent;
+ uint32be listNext; // offset to next directory entry in linked list of parent directory (aka "sibling")
+ uint32be dirListHead; // offset to first entry in linked list of directory entries (aka "child")
+ uint32be fileListHead; // offset to first entry in linked list of file entries (aka "file")
+ uint32be hash;
+ uint32be name_size;
+ std::string name;
+};
+
+struct romfs_fentry_t
+{
+ uint32be parent;
+ uint32be listNext; // offset to next file entry in linked list of parent directory (aka "sibling")
+ uint64be offset;
+ uint64be size;
+ uint32be hash;
+ uint32be name_size;
+ std::string name;
+};
+
+#define ROMFS_ENTRY_EMPTY 0xFFFFFFFF
diff --git a/src/Cafe/Filesystem/WUHB/WUHBReader.cpp b/src/Cafe/Filesystem/WUHB/WUHBReader.cpp
new file mode 100644
index 00000000..e7a4c9be
--- /dev/null
+++ b/src/Cafe/Filesystem/WUHB/WUHBReader.cpp
@@ -0,0 +1,224 @@
+#include "WUHBReader.h"
+WUHBReader* WUHBReader::FromPath(const fs::path& path)
+{
+ FileStream* fileIn{FileStream::openFile2(path)};
+ if (!fileIn)
+ return nullptr;
+
+ WUHBReader* ret = new WUHBReader(fileIn);
+ if (!ret->CheckMagicValue())
+ {
+ delete ret;
+ return nullptr;
+ }
+
+ if (!ret->ReadHeader())
+ {
+ delete ret;
+ return nullptr;
+ }
+
+ return ret;
+}
+
+static const romfs_direntry_t fallbackDirEntry{
+ .parent = ROMFS_ENTRY_EMPTY,
+ .listNext = ROMFS_ENTRY_EMPTY,
+ .dirListHead = ROMFS_ENTRY_EMPTY,
+ .fileListHead = ROMFS_ENTRY_EMPTY,
+ .hash = ROMFS_ENTRY_EMPTY,
+ .name_size = 0,
+ .name = ""
+};
+static const romfs_fentry_t fallbackFileEntry{
+ .parent = ROMFS_ENTRY_EMPTY,
+ .listNext = ROMFS_ENTRY_EMPTY,
+ .offset = 0,
+ .size = 0,
+ .hash = ROMFS_ENTRY_EMPTY,
+ .name_size = 0,
+ .name = ""
+};
+template
+const WUHBReader::EntryType& WUHBReader::GetFallback()
+{
+ if constexpr (File)
+ return fallbackFileEntry;
+ else
+ return fallbackDirEntry;
+}
+
+template
+WUHBReader::EntryType WUHBReader::GetEntry(uint32 offset) const
+{
+ auto fallback = GetFallback();
+ if(offset == ROMFS_ENTRY_EMPTY)
+ return fallback;
+
+ const char* typeName = File ? "fentry" : "direntry";
+ EntryType ret;
+ if (offset >= (File ? m_header.file_table_size : m_header.dir_table_size))
+ {
+ cemuLog_log(LogType::Force, "WUHB {} offset exceeds table size declared in header", typeName);
+ return fallback;
+ }
+
+ // read the entry
+ m_fileIn->SetPosition((File ? m_header.file_table_ofs : m_header.dir_table_ofs) + offset);
+ auto read = m_fileIn->readData(&ret, offsetof(EntryType, name));
+ if (read != offsetof(EntryType, name))
+ {
+ cemuLog_log(LogType::Force, "failed to read WUHB {} at offset: {}", typeName, offset);
+ return fallback;
+ }
+
+ // read the name
+ ret.name.resize(ret.name_size);
+ read = m_fileIn->readData(ret.name.data(), ret.name_size);
+ if (read != ret.name_size)
+ {
+ cemuLog_log(LogType::Force, "failed to read WUHB {} name", typeName);
+ return fallback;
+ }
+
+ return ret;
+}
+
+romfs_direntry_t WUHBReader::GetDirEntry(uint32 offset) const
+{
+ return GetEntry(offset);
+}
+romfs_fentry_t WUHBReader::GetFileEntry(uint32 offset) const
+{
+ return GetEntry(offset);
+}
+
+uint64 WUHBReader::GetFileSize(uint32 entryOffset) const
+{
+ return GetFileEntry(entryOffset).size;
+}
+
+uint64 WUHBReader::ReadFromFile(uint32 entryOffset, uint64 fileOffset, uint64 length, void* buffer) const
+{
+ const auto fileEntry = GetFileEntry(entryOffset);
+ if (fileOffset >= fileEntry.size)
+ return 0;
+ const uint64 readAmount = std::min(length, fileEntry.size - fileOffset);
+ const uint64 wuhbOffset = m_header.file_partition_ofs + fileEntry.offset + fileOffset;
+ m_fileIn->SetPosition(wuhbOffset);
+ return m_fileIn->readData(buffer, readAmount);
+}
+
+uint32 WUHBReader::GetHashTableEntryOffset(uint32 hash, bool isFile) const
+{
+ const uint64 hash_table_size = (isFile ? m_header.file_hash_table_size : m_header.dir_hash_table_size);
+ const uint64 hash_table_ofs = (isFile ? m_header.file_hash_table_ofs : m_header.dir_hash_table_ofs);
+
+ const uint64 hash_table_entry_count = hash_table_size / sizeof(uint32);
+ const uint64 hash_table_entry_offset = hash_table_ofs + (hash % hash_table_entry_count) * sizeof(uint32);
+
+ m_fileIn->SetPosition(hash_table_entry_offset);
+ uint32 tableOffset;
+ if (!m_fileIn->readU32(tableOffset))
+ {
+ cemuLog_log(LogType::Force, "failed to read WUHB hash table entry at file offset: {}", hash_table_entry_offset);
+ return ROMFS_ENTRY_EMPTY;
+ }
+
+ return uint32be::from_bevalue(tableOffset);
+}
+
+template
+bool WUHBReader::SearchHashList(uint32& entryOffset, const fs::path& targetName) const
+{
+ for (;;)
+ {
+ if (entryOffset == ROMFS_ENTRY_EMPTY)
+ return false;
+ auto entry = GetEntry(entryOffset);
+
+ if (entry.name == targetName)
+ return true;
+ entryOffset = entry.hash;
+ }
+ return false;
+}
+
+uint32 WUHBReader::Lookup(const std::filesystem::path& path, bool isFile) const
+{
+ uint32 currentEntryOffset = 0;
+ auto look = [&](const fs::path& part, bool lookInFileHT) {
+ const auto partString = part.string();
+ currentEntryOffset = GetHashTableEntryOffset(CalcPathHash(currentEntryOffset, partString.c_str(), 0, partString.size()), lookInFileHT);
+ if (lookInFileHT)
+ return SearchHashList(currentEntryOffset, part);
+ else
+ return SearchHashList(currentEntryOffset, part);
+ };
+ // look for the root entry
+ if (!look("", false))
+ return ROMFS_ENTRY_EMPTY;
+
+ auto it = path.begin();
+ while (it != path.end())
+ {
+ fs::path part = *it;
+ ++it;
+ // no need to recurse after trailing forward slash (e.g. directory/)
+ if (part.empty() && !isFile)
+ break;
+ // skip leading forward slash
+ if (part == "/")
+ continue;
+
+ // if the lookup target is a file and this is the last iteration, look in the file hash table instead.
+ if (!look(part, it == path.end() && isFile))
+ return ROMFS_ENTRY_EMPTY;
+ }
+ return currentEntryOffset;
+}
+bool WUHBReader::CheckMagicValue() const
+{
+ uint8 magic[4];
+ m_fileIn->SetPosition(0);
+ int read = m_fileIn->readData(magic, 4);
+ if (read != 4)
+ {
+ cemuLog_log(LogType::Force, "Failed to read WUHB magic numbers");
+ return false;
+ }
+ static_assert(sizeof(magic) == s_headerMagicValue.size());
+ return std::memcmp(&magic, s_headerMagicValue.data(), sizeof(magic)) == 0;
+}
+bool WUHBReader::ReadHeader()
+{
+ m_fileIn->SetPosition(0);
+ auto read = m_fileIn->readData(&m_header, sizeof(m_header));
+ auto readSuccess = read == sizeof(m_header);
+ if (!readSuccess)
+ cemuLog_log(LogType::Force, "Failed to read WUHB header");
+ return readSuccess;
+}
+unsigned char WUHBReader::NormalizeChar(unsigned char c)
+{
+ if (c >= 'a' && c <= 'z')
+ {
+ return c + 'A' - 'a';
+ }
+ else
+ {
+ return c;
+ }
+}
+uint32 WUHBReader::CalcPathHash(uint32 parent, const char* path, uint32 start, size_t path_len)
+{
+ cemu_assert(path != nullptr || path_len == 0);
+ uint32 hash = parent ^ 123456789;
+ for (uint32 i = 0; i < path_len; i++)
+ {
+ hash = (hash >> 5) | (hash << 27);
+ hash ^= NormalizeChar(path[start + i]);
+ }
+
+ return hash;
+}
diff --git a/src/Cafe/Filesystem/WUHB/WUHBReader.h b/src/Cafe/Filesystem/WUHB/WUHBReader.h
new file mode 100644
index 00000000..9187f05a
--- /dev/null
+++ b/src/Cafe/Filesystem/WUHB/WUHBReader.h
@@ -0,0 +1,45 @@
+#pragma once
+#include
+#include "RomFSStructs.h"
+class WUHBReader
+{
+ public:
+ static WUHBReader* FromPath(const fs::path& path);
+
+ romfs_direntry_t GetDirEntry(uint32 offset) const;
+ romfs_fentry_t GetFileEntry(uint32 offset) const;
+
+ uint64 GetFileSize(uint32 entryOffset) const;
+
+ uint64 ReadFromFile(uint32 entryOffset, uint64 fileOffset, uint64 length, void* buffer) const;
+
+ uint32 Lookup(const std::filesystem::path& path, bool isFile) const;
+
+ private:
+ WUHBReader(FileStream* file)
+ : m_fileIn(file)
+ {
+ cemu_assert_debug(file != nullptr);
+ };
+ WUHBReader() = delete;
+
+ romfs_header_t m_header;
+ std::unique_ptr m_fileIn;
+ constexpr static std::string_view s_headerMagicValue = "WUHB";
+ bool ReadHeader();
+ bool CheckMagicValue() const;
+
+ static inline unsigned char NormalizeChar(unsigned char c);
+ static uint32 CalcPathHash(uint32 parent, const char* path, uint32 start, size_t path_len);
+
+ template
+ using EntryType = std::conditional_t;
+ template
+ static const EntryType& GetFallback();
+ template