Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3143e7e1d0 | ||
|
|
d03396d272 | ||
|
|
c8aa2e8a89 | ||
|
|
c7a3a0278c | ||
|
|
5924f60d06 | ||
|
|
cd68b66c03 | ||
|
|
44cd3928fb | ||
|
|
8c54613e44 | ||
|
|
7dfa83b8c0 | ||
|
|
b551061264 | ||
|
|
3e228c33c9 | ||
|
|
2b23be8f44 | ||
|
|
ced78cb072 | ||
|
|
fb17850c3d | ||
|
|
7f7c4852cc | ||
|
|
f334e3b951 | ||
|
|
9d62995799 | ||
|
|
1d8b793cf7 | ||
|
|
33431cb939 | ||
|
|
e677e0142c | ||
|
|
b313a4aa2f | ||
|
|
37c5c6f049 | ||
|
|
a6d92ed8fe | ||
|
|
eb37ac4142 | ||
|
|
a0d4b96915 |
2
.github/ISSUE_TEMPLATE/bug-report.md
vendored
2
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@@ -34,7 +34,7 @@ about: Use this to report bugs you encounter with Luma3DS. Make sure you upload
|
||||
|
||||
**Luma3DS version:**
|
||||
|
||||
[e.g. v10.0.1 stable or if using nightly/hourly specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/0543c208fd154e6326ea5da8cbf66ffcbdef010c]
|
||||
[e.g. v10.1.2 stable or if using nightly/hourly specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/0543c208fd154e6326ea5da8cbf66ffcbdef010c]
|
||||
|
||||
**Luma3DS configuration/options:**
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
#include "arm9_exception_handlers.h"
|
||||
#include "large_patches.h"
|
||||
|
||||
#define K11EXT_VA 0x70000000
|
||||
|
||||
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
|
||||
{
|
||||
u8 *temp = memsearch(pos, "NCCH", size, 4);
|
||||
@@ -134,7 +136,7 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32
|
||||
static const u8 patternHook3_4[] = {0x00, 0x00, 0xA0, 0xE1, 0x03, 0xF0, 0x20, 0xE3, 0xFD, 0xFF, 0xFF, 0xEA}; //SGI0 setup code, etc.
|
||||
|
||||
//Our kernel11 extension is initially loaded in VRAM
|
||||
u32 kextTotalSize = *(u32 *)0x18000020 - 0x40000000;
|
||||
u32 kextTotalSize = *(u32 *)0x18000020 - K11EXT_VA;
|
||||
u32 dstKextPA = (ISN3DS ? 0x2E000000 : 0x26C00000) - kextTotalSize;
|
||||
|
||||
u32 *hookVeneers = (u32 *)*freeK11Space;
|
||||
@@ -143,11 +145,11 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32
|
||||
hookVeneers[0] = 0xE51FF004; //ldr pc, [pc, #-8+4]
|
||||
hookVeneers[1] = 0x18000004;
|
||||
hookVeneers[2] = 0xE51FF004;
|
||||
hookVeneers[3] = 0x40000000;
|
||||
hookVeneers[3] = K11EXT_VA;
|
||||
hookVeneers[4] = 0xE51FF004;
|
||||
hookVeneers[5] = 0x40000008;
|
||||
hookVeneers[5] = K11EXT_VA + 8;
|
||||
hookVeneers[6] = 0xE51FF004;
|
||||
hookVeneers[7] = 0x4000000C;
|
||||
hookVeneers[7] = K11EXT_VA + 0xC;
|
||||
|
||||
(*freeK11Space) += 32;
|
||||
|
||||
@@ -175,14 +177,14 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32
|
||||
off += 4;
|
||||
*off = MAKE_BRANCH_LINK(baseK11VA + ((u8 *)off - pos), relocBase + 24);
|
||||
|
||||
struct KExtParameters *p = (struct KExtParameters *)(*(u32 *)0x18000024 - 0x40000000 + 0x18000000);
|
||||
struct KExtParameters *p = (struct KExtParameters *)(*(u32 *)0x18000024 - K11EXT_VA + 0x18000000);
|
||||
p->basePA = dstKextPA;
|
||||
|
||||
for(u32 i = 0; i < 4; i++)
|
||||
{
|
||||
u32 *handlerPos = getKernel11HandlerVAPos(pos, arm11ExceptionsPage, baseK11VA, 1 + i);
|
||||
p->originalHandlers[i] = (void *)*handlerPos;
|
||||
*handlerPos = 0x40000010 + 4 * i;
|
||||
*handlerPos = K11EXT_VA + 0x10 + 4 * i;
|
||||
}
|
||||
|
||||
struct CfwInfo *info = &p->info;
|
||||
@@ -248,14 +250,14 @@ u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm
|
||||
|
||||
//Redirect enableUserExceptionHandlersForCPUExc (= true)
|
||||
for(off = arm11ExceptionsPage; *off != 0x96007F9; off++);
|
||||
off[1] = 0x40000028;
|
||||
off[1] = K11EXT_VA + 0x28;
|
||||
|
||||
off = (u32 *)memsearch(pos, patternKThreadDebugReschedule, size, sizeof(patternKThreadDebugReschedule));
|
||||
if(off == NULL)
|
||||
return 1;
|
||||
|
||||
off[-5] = 0xE51FF004;
|
||||
off[-4] = 0x4000002C;
|
||||
off[-4] = K11EXT_VA + 0x2C;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -57,5 +57,4 @@ void SessionInfo_Add(KSession *session, const char *name);
|
||||
void SessionInfo_Remove(KSession *session);
|
||||
|
||||
bool doLangEmu(Result *res, u32 *cmdbuf);
|
||||
Result doPublishToProcessHook(Handle handle, u32 *cmdbuf);
|
||||
bool doErrfThrowHook(u32 *cmdbuf);
|
||||
|
||||
@@ -5,7 +5,7 @@ ENTRY(_start)
|
||||
MEMORY
|
||||
{
|
||||
vram : ORIGIN = 0x18000000, LENGTH = 0x18180000 - 0x18000000 /* Up to the kernel builtins. */
|
||||
main : ORIGIN = 0x40000000, LENGTH = 1M
|
||||
main : ORIGIN = 0x70000000, LENGTH = 1M
|
||||
}
|
||||
|
||||
PHDRS
|
||||
@@ -15,7 +15,7 @@ PHDRS
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(__start__ = 0x40000000);
|
||||
PROVIDE(__start__ = ORIGIN(main));
|
||||
. = ABSOLUTE(__start__);
|
||||
|
||||
.text :
|
||||
|
||||
@@ -235,48 +235,6 @@ bool doLangEmu(Result *res, u32 *cmdbuf)
|
||||
return skip;
|
||||
}
|
||||
|
||||
Result doPublishToProcessHook(Handle handle, u32 *cmdbuf)
|
||||
{
|
||||
Result res = 0;
|
||||
u32 pid;
|
||||
bool terminateRosalina = cmdbuf[1] == 0x100 && cmdbuf[2] == 0; // cmdbuf[2] to check for well-formed requests
|
||||
u32 savedCmdbuf[4];
|
||||
memcpy(savedCmdbuf, cmdbuf, 16);
|
||||
|
||||
if(!terminateRosalina || GetProcessId(&pid, cmdbuf[3]) != 0)
|
||||
terminateRosalina = false;
|
||||
else
|
||||
{
|
||||
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
|
||||
KProcess *process = KProcessHandleTable__ToKProcess(handleTable, cmdbuf[3]);
|
||||
if((strcmp(codeSetOfProcess(process)->processName, "socket") == 0 && (rosalinaState & 2)) ||
|
||||
strcmp(codeSetOfProcess(process)->processName, "pxi") == 0)
|
||||
terminateRosalina = true;
|
||||
else
|
||||
terminateRosalina = false;
|
||||
((KAutoObject *)process)->vtable->DecrementReferenceCount((KAutoObject *)process);
|
||||
}
|
||||
|
||||
if(terminateRosalina && nbSection0Modules == 6)
|
||||
{
|
||||
Handle rosalinaProcessHandle;
|
||||
res = OpenProcess(&rosalinaProcessHandle, 5);
|
||||
if(res == 0)
|
||||
{
|
||||
cmdbuf[0] = cmdbuf[0];
|
||||
cmdbuf[1] = 0x100;
|
||||
cmdbuf[2] = 0;
|
||||
cmdbuf[3] = rosalinaProcessHandle;
|
||||
|
||||
res = SendSyncRequest(handle);
|
||||
CloseHandle(rosalinaProcessHandle);
|
||||
memcpy(cmdbuf, savedCmdbuf, 16);
|
||||
}
|
||||
}
|
||||
|
||||
return SendSyncRequest(handle);
|
||||
}
|
||||
|
||||
bool doErrfThrowHook(u32 *cmdbuf)
|
||||
{
|
||||
// If fatalErrorInfo->type is "card removed" or "logged", returning from ERRF:Throw is a no-op
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include "svc/ConnectToPort.h"
|
||||
#include "svcHandler.h"
|
||||
|
||||
#define K11EXT_VA 0x70000000
|
||||
|
||||
struct KExtParameters
|
||||
{
|
||||
u32 basePA;
|
||||
@@ -41,13 +43,13 @@ struct KExtParameters
|
||||
CfwInfo cfwInfo;
|
||||
} kExtParameters = { .basePA = 0x12345678 }; // place this in .data
|
||||
|
||||
static ALIGN(1024) u32 L2TableFor0x40000000[256] = {0};
|
||||
static ALIGN(1024) u32 g_L2Table[256] = {0};
|
||||
|
||||
void relocateAndSetupMMU(u32 coreId, u32 *L1Table)
|
||||
{
|
||||
struct KExtParameters *p0 = (struct KExtParameters *)((u32)&kExtParameters - 0x40000000 + 0x18000000);
|
||||
struct KExtParameters *p = (struct KExtParameters *)((u32)&kExtParameters - 0x40000000 + p0->basePA);
|
||||
u32 *L2Table = (u32 *)((u32)L2TableFor0x40000000 - 0x40000000 + p0->basePA);
|
||||
struct KExtParameters *p0 = (struct KExtParameters *)((u32)&kExtParameters - K11EXT_VA + 0x18000000);
|
||||
struct KExtParameters *p = (struct KExtParameters *)((u32)&kExtParameters - K11EXT_VA + p0->basePA);
|
||||
u32 *L2Table = (u32 *)((u32)g_L2Table - K11EXT_VA + p0->basePA);
|
||||
|
||||
if(coreId == 0)
|
||||
{
|
||||
@@ -56,7 +58,7 @@ void relocateAndSetupMMU(u32 coreId, u32 *L1Table)
|
||||
memcpy((void *)p0->basePA, (const void *)0x18000000, __bss_start__ - __start__);
|
||||
memset((u32 *)(p0->basePA + (__bss_start__ - __start__)), 0, __bss_end__ - __bss_start__);
|
||||
|
||||
// Map the kernel ext to 0x40000000
|
||||
// Map the kernel ext at K11EXT_VA
|
||||
// 4KB extended small pages: [SYS:RW USR:-- X TYP:NORMAL SHARED OUTER NOCACHE, INNER CACHED WB WA]
|
||||
for(u32 offset = 0; offset < (u32)(__end__ - __start__); offset += 0x1000)
|
||||
L2Table[offset >> 12] = (p0->basePA + offset) | 0x516;
|
||||
@@ -76,7 +78,7 @@ void relocateAndSetupMMU(u32 coreId, u32 *L1Table)
|
||||
L1Table[i + (VA >> 20)] = PA | attribs;
|
||||
}
|
||||
|
||||
L1Table[0x40000000 >> 20] = (u32)L2Table | 1;
|
||||
L1Table[K11EXT_VA >> 20] = (u32)L2Table | 1;
|
||||
|
||||
p->L1MMUTableAddrs[coreId] = (u32)L1Table;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param)
|
||||
break;
|
||||
|
||||
default:
|
||||
*out = 0;
|
||||
res = 0xF8C007F4; // not implemented
|
||||
break;
|
||||
}
|
||||
@@ -105,13 +106,16 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param)
|
||||
*out = L2C_CTRL & 1;
|
||||
break;
|
||||
default:
|
||||
*out = 0;
|
||||
res = 0xF8C007F4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*out = 0;
|
||||
res = 0xF8C007F4;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -128,7 +132,10 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param)
|
||||
if((u32)param <= getNumberOfCores())
|
||||
*out = L1MMUTableAddrs[param - 1];
|
||||
else
|
||||
{
|
||||
*out = 0;
|
||||
res = 0xF8C007F4;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -136,6 +143,13 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param)
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x20000:
|
||||
{
|
||||
*out = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
default:
|
||||
GetSystemInfo(out, type, param);
|
||||
break;
|
||||
|
||||
@@ -47,12 +47,7 @@ Result SendSyncRequestHook(Handle handle)
|
||||
case 0x10042:
|
||||
{
|
||||
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
|
||||
if(info != NULL && kernelVersion >= SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0)
|
||||
{
|
||||
res = doPublishToProcessHook(handle, cmdbuf);
|
||||
skip = true;
|
||||
}
|
||||
else if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce)
|
||||
if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce)
|
||||
{
|
||||
cmdbuf[0] = 0x10040;
|
||||
cmdbuf[1] = 0;
|
||||
@@ -154,18 +149,6 @@ Result SendSyncRequestHook(Handle handle)
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4010042:
|
||||
{
|
||||
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
|
||||
if(info != NULL && kernelVersion < SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0)
|
||||
{
|
||||
res = doPublishToProcessHook(handle, cmdbuf);
|
||||
skip = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4010082:
|
||||
{
|
||||
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
|
||||
|
||||
@@ -37,7 +37,7 @@ CFLAGS := -std=gnu11 $(COMMON_FLAGS)
|
||||
CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++17 $(COMMON_FLAGS)
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),--section-start,.text=0x14000000
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit,--section-start,.text=0x14000000
|
||||
|
||||
LIBS := -lctru
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "hbldr.h"
|
||||
|
||||
extern u32 config, multiConfig, bootConfig;
|
||||
extern bool isN3DS, needToInitSd, isSdMode;
|
||||
extern bool isN3DS, isSdMode;
|
||||
|
||||
static u8 g_ret_buf[sizeof(ExHeader_Info)];
|
||||
static u64 g_cached_programHandle;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "service_manager.h"
|
||||
|
||||
u32 config, multiConfig, bootConfig;
|
||||
bool isN3DS, needToInitSd, isSdMode;
|
||||
bool isN3DS, isSdMode;
|
||||
|
||||
// MAKE SURE fsreg has been init before calling this
|
||||
static Result fsldrPatchPermissions(void)
|
||||
@@ -29,27 +29,38 @@ static inline void loadCFWInfo(void)
|
||||
{
|
||||
s64 out;
|
||||
|
||||
assertSuccess(svcGetSystemInfo(&out, 0x10000, 3));
|
||||
if(svcGetSystemInfo(&out, 0x20000, 0) != 1) panic(0xDEADCAFE);
|
||||
|
||||
svcGetSystemInfo(&out, 0x10000, 3);
|
||||
config = (u32)out;
|
||||
assertSuccess(svcGetSystemInfo(&out, 0x10000, 4));
|
||||
svcGetSystemInfo(&out, 0x10000, 4);
|
||||
multiConfig = (u32)out;
|
||||
assertSuccess(svcGetSystemInfo(&out, 0x10000, 5));
|
||||
svcGetSystemInfo(&out, 0x10000, 5);
|
||||
bootConfig = (u32)out;
|
||||
|
||||
assertSuccess(svcGetSystemInfo(&out, 0x10000, 0x201));
|
||||
svcGetSystemInfo(&out, 0x10000, 0x201);
|
||||
isN3DS = (bool)out;
|
||||
assertSuccess(svcGetSystemInfo(&out, 0x10000, 0x202));
|
||||
needToInitSd = (bool)out;
|
||||
assertSuccess(svcGetSystemInfo(&out, 0x10000, 0x203));
|
||||
svcGetSystemInfo(&out, 0x10000, 0x203);
|
||||
isSdMode = (bool)out;
|
||||
|
||||
IFile file;
|
||||
if(needToInitSd) fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ); //Init SD card if SAFE_MODE is being booted
|
||||
}
|
||||
|
||||
// this is called before main
|
||||
void __appInit()
|
||||
void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error
|
||||
|
||||
// this is called after main exits
|
||||
void __wrap_exit(int rc)
|
||||
{
|
||||
(void)rc;
|
||||
// Not supposed to terminate... kernel will clean up the handles if it does happen anyway
|
||||
svcExitProcess();
|
||||
}
|
||||
|
||||
void __sync_init();
|
||||
void __libc_init_array(void);
|
||||
|
||||
// called before main
|
||||
void initSystem(void)
|
||||
{
|
||||
__sync_init();
|
||||
loadCFWInfo();
|
||||
|
||||
Result res;
|
||||
@@ -71,42 +82,8 @@ void __appInit()
|
||||
assertSuccess(FSUSER_SetPriority(0));
|
||||
|
||||
assertSuccess(pxiPmInit());
|
||||
}
|
||||
|
||||
// this is called after main exits
|
||||
void __appExit()
|
||||
{
|
||||
pxiPmExit();
|
||||
//fsldrExit();
|
||||
svcCloseHandle(*fsGetSessionHandle());
|
||||
fsRegExit();
|
||||
srvExit();
|
||||
}
|
||||
|
||||
// stubs for non-needed pre-main functions
|
||||
void __sync_init();
|
||||
void __sync_fini();
|
||||
void __system_initSyscalls();
|
||||
|
||||
void __ctru_exit()
|
||||
{
|
||||
void __libc_fini_array(void);
|
||||
|
||||
__libc_fini_array();
|
||||
__appExit();
|
||||
__sync_fini();
|
||||
svcExitProcess();
|
||||
}
|
||||
|
||||
void initSystem()
|
||||
{
|
||||
void __libc_init_array(void);
|
||||
|
||||
__sync_init();
|
||||
__system_initSyscalls();
|
||||
__appInit();
|
||||
|
||||
__libc_init_array();
|
||||
//__libc_init_array();
|
||||
}
|
||||
|
||||
static const ServiceManagerServiceEntry services[] = {
|
||||
|
||||
@@ -39,7 +39,7 @@ enum singleOptions
|
||||
};
|
||||
|
||||
extern u32 config, multiConfig, bootConfig;
|
||||
extern bool isN3DS, needToInitSd, isSdMode;
|
||||
extern bool isN3DS, isSdMode;
|
||||
|
||||
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress);
|
||||
Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int flags);
|
||||
|
||||
@@ -37,7 +37,7 @@ CFLAGS += $(INCLUDE)
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit
|
||||
|
||||
LIBS := -lctru
|
||||
|
||||
|
||||
@@ -117,7 +117,11 @@ AccessControlInfo:
|
||||
ServiceAccessControl:
|
||||
# Note: pm also uses srv:pm and Loader but doesn't list them here.
|
||||
- fs:REG
|
||||
# Custom:
|
||||
- fs:USER
|
||||
FileSystemAccess:
|
||||
# Custom
|
||||
- DirectSdmc
|
||||
|
||||
SystemControlInfo:
|
||||
SaveDataSize: 0KB # It doesn't use any save data.
|
||||
|
||||
@@ -14,10 +14,27 @@
|
||||
#include "service_manager.h"
|
||||
|
||||
static MyThread processMonitorThread, taskRunnerThread;
|
||||
static u8 ALIGN(8) processDataBuffer[0x40 * sizeof(ProcessData)] = {0};
|
||||
static u8 ALIGN(8) exheaderInfoBuffer[6 * sizeof(ExHeader_Info)] = {0};
|
||||
static u8 ALIGN(8) threadStacks[2][THREAD_STACK_SIZE] = {0};
|
||||
|
||||
// this is called before main
|
||||
void __appInit()
|
||||
// this is called after main exits
|
||||
void __wrap_exit(int rc)
|
||||
{
|
||||
(void)rc;
|
||||
// Not supposed to terminate... kernel will clean up the handles if it does happen anyway
|
||||
svcExitProcess();
|
||||
}
|
||||
|
||||
Result __sync_init(void);
|
||||
//void __libc_init_array(void);
|
||||
|
||||
// Called before main
|
||||
void initSystem()
|
||||
{
|
||||
__sync_init();
|
||||
//__libc_init_array();
|
||||
|
||||
// Wait for sm
|
||||
for(Result res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL)) {
|
||||
res = srvPmInit();
|
||||
@@ -28,56 +45,10 @@ void __appInit()
|
||||
loaderInit();
|
||||
fsRegInit();
|
||||
|
||||
static u8 ALIGN(8) processDataBuffer[0x40 * sizeof(ProcessData)] = {0};
|
||||
static u8 ALIGN(8) exheaderInfoBuffer[6 * sizeof(ExHeader_Info)] = {0};
|
||||
static u8 ALIGN(8) threadStacks[2][THREAD_STACK_SIZE] = {0};
|
||||
|
||||
// Init objects
|
||||
Manager_Init(processDataBuffer, 0x40);
|
||||
ExHeaderInfoHeap_Init(exheaderInfoBuffer, 6);
|
||||
TaskRunner_Init();
|
||||
|
||||
// Init the reslimits, register the KIPs and map the firmlaunch parameters
|
||||
initializeReslimits();
|
||||
Manager_RegisterKips();
|
||||
mapFirmlaunchParameters();
|
||||
|
||||
// Create the threads
|
||||
assertSuccess(MyThread_Create(&processMonitorThread, processMonitor, NULL, threadStacks[0], THREAD_STACK_SIZE, 0x17, -2));
|
||||
assertSuccess(MyThread_Create(&taskRunnerThread, TaskRunner_HandleTasks, NULL, threadStacks[1], THREAD_STACK_SIZE, 0x17, -2));
|
||||
|
||||
// Launch NS, etc.
|
||||
autolaunchSysmodules();
|
||||
}
|
||||
|
||||
// this is called after main exits
|
||||
void __appExit()
|
||||
{
|
||||
// We don't clean up g_manager's handles because it could hang the process monitor thread, etc.
|
||||
fsRegExit();
|
||||
loaderExit();
|
||||
srvPmExit();
|
||||
}
|
||||
|
||||
|
||||
Result __sync_init(void);
|
||||
Result __sync_fini(void);
|
||||
void __libc_init_array(void);
|
||||
void __libc_fini_array(void);
|
||||
|
||||
void __ctru_exit()
|
||||
{
|
||||
__libc_fini_array();
|
||||
__appExit();
|
||||
__sync_fini();
|
||||
svcExitProcess();
|
||||
}
|
||||
|
||||
void initSystem()
|
||||
{
|
||||
__sync_init();
|
||||
__appInit();
|
||||
__libc_init_array();
|
||||
}
|
||||
|
||||
static const ServiceManagerServiceEntry services[] = {
|
||||
@@ -90,9 +61,24 @@ static const ServiceManagerNotificationEntry notifications[] = {
|
||||
{ 0x000, NULL },
|
||||
};
|
||||
|
||||
void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Result res = 0;
|
||||
|
||||
// Init the reslimits, register the KIPs and map the firmlaunch parameters
|
||||
initializeReslimits();
|
||||
Manager_RegisterKips();
|
||||
mapFirmlaunchParameters();
|
||||
|
||||
// Create the threads
|
||||
assertSuccess(MyThread_Create(&processMonitorThread, processMonitor, NULL, threadStacks[0], THREAD_STACK_SIZE, 0x17, -2));
|
||||
assertSuccess(MyThread_Create(&taskRunnerThread, TaskRunner_HandleTasks, NULL, threadStacks[1], THREAD_STACK_SIZE, 0x17, -2));
|
||||
|
||||
// Launch NS, etc.
|
||||
autolaunchSysmodules();
|
||||
|
||||
if (R_FAILED(res = ServiceManager_Run(services, notifications, NULL))) {
|
||||
panic(res);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
TaskRunner g_taskRunner;
|
||||
|
||||
static void taskRunnerNoOpFunction(void *args)
|
||||
{
|
||||
(void)args;
|
||||
}
|
||||
|
||||
void TaskRunner_Init(void)
|
||||
{
|
||||
memset(&g_taskRunner, 0, sizeof(TaskRunner));
|
||||
@@ -20,12 +25,23 @@ void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsi
|
||||
LightEvent_Signal(&g_taskRunner.parametersSetEvent);
|
||||
}
|
||||
|
||||
void TaskRunner_Terminate(void)
|
||||
{
|
||||
g_taskRunner.shouldTerminate = true;
|
||||
TaskRunner_RunTask(taskRunnerNoOpFunction, NULL, 0);
|
||||
}
|
||||
|
||||
void TaskRunner_HandleTasks(void *p)
|
||||
{
|
||||
(void)p;
|
||||
for (;;) {
|
||||
while (!g_taskRunner.shouldTerminate) {
|
||||
LightEvent_Signal(&g_taskRunner.readyEvent);
|
||||
LightEvent_Wait(&g_taskRunner.parametersSetEvent);
|
||||
g_taskRunner.task(g_taskRunner.argStorage);
|
||||
}
|
||||
}
|
||||
|
||||
void TaskRunner_WaitReady(void)
|
||||
{
|
||||
LightEvent_Wait(&g_taskRunner.readyEvent);
|
||||
}
|
||||
|
||||
@@ -8,11 +8,15 @@ typedef struct TaskRunner {
|
||||
LightEvent parametersSetEvent;
|
||||
void (*task)(void *argdata);
|
||||
u8 argStorage[0x40];
|
||||
bool shouldTerminate;
|
||||
} TaskRunner;
|
||||
|
||||
extern TaskRunner g_taskRunner;
|
||||
|
||||
void TaskRunner_Init(void);
|
||||
void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsize);
|
||||
void TaskRunner_Terminate(void);
|
||||
|
||||
/// Thread function
|
||||
void TaskRunner_HandleTasks(void *p);
|
||||
void TaskRunner_WaitReady(void);
|
||||
|
||||
@@ -6,6 +6,35 @@
|
||||
#include "exheader_info_heap.h"
|
||||
#include "task_runner.h"
|
||||
|
||||
static Result fsRegSetupPermissions(void)
|
||||
{
|
||||
u32 pid;
|
||||
Result res;
|
||||
FS_ProgramInfo info;
|
||||
|
||||
ExHeader_Arm11StorageInfo storageInfo = {
|
||||
.fs_access_info = FSACCESS_SDMC_RW,
|
||||
};
|
||||
|
||||
info.programId = 0x0004013000001202LL; // PM's TID
|
||||
info.mediaType = MEDIATYPE_NAND;
|
||||
|
||||
if(R_SUCCEEDED(res = svcGetProcessId(&pid, CUR_PROCESS_HANDLE)))
|
||||
res = FSREG_Register(pid, 0xFFFF000000000000LL, &info, &storageInfo);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void forceMountSdCard(void)
|
||||
{
|
||||
FS_Archive sdmcArchive;
|
||||
|
||||
assertSuccess(fsRegSetupPermissions());
|
||||
assertSuccess(fsInit());
|
||||
assertSuccess(FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")));
|
||||
// No need to clean up things as we will firmlaunch straight away
|
||||
}
|
||||
|
||||
static Result terminateUnusedDependencies(const u64 *dependencies, u32 numDeps)
|
||||
{
|
||||
ProcessData *process;
|
||||
@@ -65,6 +94,16 @@ static Result terminateProcessImpl(ProcessData *process, ExHeader_Info *exheader
|
||||
}
|
||||
}
|
||||
|
||||
static void terminateProcessByIdChecked(u32 pid)
|
||||
{
|
||||
ProcessData *process = ProcessList_FindProcessById(&g_manager.processList, pid);
|
||||
if (process != NULL) {
|
||||
ProcessData_SendTerminationNotification(process);
|
||||
} else {
|
||||
panic(0LL);
|
||||
}
|
||||
}
|
||||
|
||||
static Result commitPendingTerminations(s64 timeout)
|
||||
{
|
||||
// Wait for all of the processes that have received notification 0x100 to terminate
|
||||
@@ -247,6 +286,8 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
|
||||
|
||||
u64 dependencies[48];
|
||||
u32 numDeps = 0;
|
||||
s64 numKips = 0;
|
||||
svcGetSystemInfo(&numKips, 26, 0);
|
||||
|
||||
ExHeader_Info *exheaderInfo = ExHeaderInfoHeap_New();
|
||||
|
||||
@@ -269,6 +310,12 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
|
||||
}
|
||||
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
|
||||
// Send custom notification to at least Rosalina to make it relinquish some non-KIP services handles, stop the debugger, etc.
|
||||
if (numKips >= 6) {
|
||||
notifySubscribers(0x2000);
|
||||
}
|
||||
|
||||
// Send notification 0x100 to the currently running application
|
||||
if (g_manager.runningApplicationData != NULL) {
|
||||
g_manager.runningApplicationData->flags &= ~PROCESSFLAG_DEPENDENCIES_LOADED;
|
||||
@@ -302,20 +349,29 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
|
||||
commitPendingTerminations(timeoutTicks >= 0 ? ticksToNs(timeoutTicks) : 0LL);
|
||||
g_manager.waitingForTermination = false;
|
||||
|
||||
// Now, send termination notification to PXI (PID 4)
|
||||
if (callerPid == (u32)-1) {
|
||||
// On firmlaunch, try to force Process9 to mount the SD card to allow the Process9 firmlaunch patch to load boot.firm if needed
|
||||
// Need to do that before we tell PXI to terminate
|
||||
s64 out;
|
||||
if(R_SUCCEEDED(svcGetSystemInfo(&out, 0x10000, 0x203)) && out != 0) {
|
||||
// If boot.firm is on the SD card, then...
|
||||
forceMountSdCard();
|
||||
}
|
||||
}
|
||||
|
||||
// Now, send termination notification to PXI (PID 4). Also do the same for Rosalina.
|
||||
assertSuccess(svcClearEvent(g_manager.allNotifiedTerminationEvent));
|
||||
g_manager.waitingForTermination = true;
|
||||
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
process = ProcessList_FindProcessById(&g_manager.processList, 4);
|
||||
if (process != NULL) {
|
||||
ProcessData_SendTerminationNotification(process);
|
||||
} else {
|
||||
panic(0LL);
|
||||
|
||||
if (numKips >= 6) {
|
||||
terminateProcessByIdChecked(5); // Rosalina
|
||||
}
|
||||
terminateProcessByIdChecked(4); // PXI
|
||||
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
|
||||
// Allow 1.5 extra seconds for PXI (approx 402167783 ticks)
|
||||
// Allow 1.5 extra seconds for PXI and Rosalina (approx 402167783 ticks)
|
||||
timeoutTicks = dstTimePoint - svcGetSystemTick();
|
||||
commitPendingTerminations(1500 * 1000 * 1000LL + (timeoutTicks >= 0 ? ticksToNs(timeoutTicks) : 0LL));
|
||||
g_manager.waitingForTermination = false;
|
||||
|
||||
@@ -37,7 +37,7 @@ CFLAGS += $(INCLUDE)
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit
|
||||
|
||||
LIBS := -lctru
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE fo
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "PXI.h"
|
||||
#include "common.h"
|
||||
#include "MyThread.h"
|
||||
@@ -99,10 +98,40 @@ static inline void exitPXI(void)
|
||||
static u8 ALIGN(8) receiverStack[THREAD_STACK_SIZE];
|
||||
static u8 ALIGN(8) senderStack[THREAD_STACK_SIZE];
|
||||
static u8 ALIGN(8) PXISRV11HandlerStack[THREAD_STACK_SIZE];
|
||||
static MyThread receiverThread = {0}, senderThread = {0}, PXISRV11HandlerThread = {0};
|
||||
|
||||
Result __sync_init(void);
|
||||
Result __sync_fini(void);
|
||||
void __libc_fini_array(void);
|
||||
void __libc_init_array(void);
|
||||
|
||||
void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error
|
||||
|
||||
// this is called after main exits
|
||||
void __wrap_exit(int rc)
|
||||
{
|
||||
(void)rc;
|
||||
|
||||
srvExit();
|
||||
exitPXI();
|
||||
|
||||
svcCloseHandle(terminationRequestedEvent);
|
||||
svcCloseHandle(sessionManager.sendAllBuffersToArm9Event);
|
||||
svcCloseHandle(sessionManager.replySemaphore);
|
||||
svcCloseHandle(sessionManager.PXISRV11CommandReceivedEvent);
|
||||
svcCloseHandle(sessionManager.PXISRV11ReplySentEvent);
|
||||
|
||||
//__libc_fini_array();
|
||||
__sync_fini();
|
||||
svcExitProcess();
|
||||
}
|
||||
|
||||
// this is called before main
|
||||
void __appInit()
|
||||
|
||||
void initSystem(void)
|
||||
{
|
||||
__sync_init();
|
||||
|
||||
assertSuccess(svcCreateEvent(&terminationRequestedEvent, RESET_STICKY));
|
||||
|
||||
assertSuccess(svcCreateEvent(&sessionManager.sendAllBuffersToArm9Event, RESET_ONESHOT));
|
||||
@@ -117,52 +146,13 @@ void __appInit()
|
||||
if(R_FAILED(res) && res != (Result)0xD88007FA)
|
||||
svcBreak(USERBREAK_PANIC);
|
||||
}
|
||||
}
|
||||
|
||||
// this is called after main exits
|
||||
void __appExit()
|
||||
{
|
||||
srvExit();
|
||||
exitPXI();
|
||||
|
||||
svcCloseHandle(terminationRequestedEvent);
|
||||
svcCloseHandle(sessionManager.sendAllBuffersToArm9Event);
|
||||
svcCloseHandle(sessionManager.replySemaphore);
|
||||
svcCloseHandle(sessionManager.PXISRV11CommandReceivedEvent);
|
||||
svcCloseHandle(sessionManager.PXISRV11ReplySentEvent);
|
||||
}
|
||||
|
||||
// stubs for non-needed pre-main functions
|
||||
void __system_initSyscalls(){}
|
||||
|
||||
|
||||
Result __sync_init(void);
|
||||
Result __sync_fini(void);
|
||||
|
||||
void __ctru_exit()
|
||||
{
|
||||
void __libc_fini_array(void);
|
||||
|
||||
__libc_fini_array();
|
||||
__appExit();
|
||||
__sync_fini();
|
||||
svcExitProcess();
|
||||
}
|
||||
|
||||
void initSystem()
|
||||
{
|
||||
void __libc_init_array(void);
|
||||
|
||||
__sync_init();
|
||||
__system_initSyscalls();
|
||||
__appInit();
|
||||
__libc_init_array();
|
||||
//__libc_init_array();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Handle handles[10] = {0}; //notification handle + service handles
|
||||
MyThread receiverThread = {0}, senderThread = {0}, PXISRV11HandlerThread = {0};
|
||||
|
||||
for(u32 i = 0; i < 9; i++)
|
||||
assertSuccess(srvRegisterService(handles + 1 + i, serviceNames[i], 1));
|
||||
|
||||
@@ -37,7 +37,7 @@ CFLAGS += $(INCLUDE)
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),--section-start,.text=0x14000000
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit,--section-start,.text=0x14000000
|
||||
|
||||
LIBS := -lctru
|
||||
|
||||
|
||||
@@ -36,4 +36,5 @@ extern int inputRedirectionStartResult;
|
||||
|
||||
MyThread *inputRedirectionCreateThread(void);
|
||||
void inputRedirectionThreadMain(void);
|
||||
Result InputRedirection_Disable(s64 timeout);
|
||||
Result InputRedirection_DoOrUndoPatches(void);
|
||||
|
||||
@@ -33,4 +33,5 @@
|
||||
#define CHEATS_PER_MENU_PAGE 18
|
||||
|
||||
void RosalinaMenu_Cheats(void);
|
||||
void Cheat_ApplyCheats();
|
||||
void Cheat_SeedRng(u64 seed);
|
||||
void Cheat_ApplyCheats(void);
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
extern Menu debuggerMenu;
|
||||
|
||||
void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata);
|
||||
Result debuggerDisable(s64 timeout);
|
||||
|
||||
void DebuggerMenu_EnableDebugger(void);
|
||||
void DebuggerMenu_DisableDebugger(void);
|
||||
void DebuggerMenu_DebugNextApplicationByForce(void);
|
||||
|
||||
@@ -30,8 +30,12 @@
|
||||
#include "menu.h"
|
||||
|
||||
extern Menu sysconfigMenu;
|
||||
extern bool isConnectionForced;
|
||||
|
||||
void SysConfigMenu_UpdateStatus(bool control);
|
||||
|
||||
void SysConfigMenu_ToggleLEDs(void);
|
||||
void SysConfigMenu_ToggleWireless(void);
|
||||
void SysConfigMenu_TogglePowerButton(void);
|
||||
void SysConfigMenu_ControlWifi(void);
|
||||
void SysConfigMenu_DisableForcedWifiConnection(void);
|
||||
|
||||
@@ -18,13 +18,10 @@
|
||||
#include <errno.h>
|
||||
|
||||
#define SYNC_ERROR ENODEV
|
||||
|
||||
extern Handle SOCU_handle;
|
||||
extern Handle socMemhandle;
|
||||
|
||||
extern bool miniSocEnabled;
|
||||
|
||||
Result miniSocInit();
|
||||
Result miniSocInit(void);
|
||||
Result miniSocExitDirect(void);
|
||||
Result miniSocExit(void);
|
||||
|
||||
s32 _net_convert_error(s32 sock_retval);
|
||||
@@ -37,10 +34,17 @@ int socConnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int socPoll(struct pollfd *fds, nfds_t nfds, int timeout);
|
||||
int socSetsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
|
||||
int socClose(int sockfd);
|
||||
long socGethostid(void);
|
||||
|
||||
ssize_t soc_recv(int sockfd, void *buf, size_t len, int flags);
|
||||
ssize_t soc_send(int sockfd, const void *buf, size_t len, int flags);
|
||||
ssize_t socRecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
|
||||
ssize_t socSendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
|
||||
|
||||
// actually provided by ctrulib
|
||||
ssize_t soc_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
|
||||
ssize_t soc_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
|
||||
static inline ssize_t socRecv(int sockfd, void *buf, size_t len, int flags)
|
||||
{
|
||||
return socRecvfrom(sockfd, buf, len, flags, NULL, 0);
|
||||
}
|
||||
|
||||
static inline ssize_t socSend(int sockfd, const void *buf, size_t len, int flags)
|
||||
{
|
||||
return socSendto(sockfd, buf, len, flags, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -68,10 +68,11 @@ typedef struct sock_server
|
||||
sock_free_func free;
|
||||
|
||||
Handle shall_terminate_event;
|
||||
Result init_result;
|
||||
} sock_server;
|
||||
|
||||
Result server_init(struct sock_server *serv);
|
||||
void server_bind(struct sock_server *serv, u16 port);
|
||||
Result server_bind(struct sock_server *serv, u16 port);
|
||||
void server_run(struct sock_server *serv);
|
||||
void server_kill_connections(struct sock_server *serv);
|
||||
void server_set_should_close_all(struct sock_server *serv);
|
||||
|
||||
@@ -9,6 +9,7 @@ typedef struct TaskRunner {
|
||||
LightEvent parametersSetEvent;
|
||||
void (*task)(void *argdata);
|
||||
u8 argStorage[0x40];
|
||||
bool shouldTerminate;
|
||||
} TaskRunner;
|
||||
|
||||
extern TaskRunner g_taskRunner;
|
||||
@@ -17,6 +18,8 @@ MyThread *taskRunnerCreateThread(void);
|
||||
|
||||
void TaskRunner_Init(void);
|
||||
void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsize);
|
||||
void TaskRunner_Terminate(void);
|
||||
|
||||
/// Thread function
|
||||
void TaskRunner_HandleTasks(void);
|
||||
void TaskRunner_WaitReady(void);
|
||||
@@ -21,7 +21,7 @@ AccessControlInfo:
|
||||
IdealProcessor : 1
|
||||
AffinityMask : 3
|
||||
|
||||
Priority : 20
|
||||
Priority : 25 # 55
|
||||
|
||||
DisableDebug : false
|
||||
EnableForceDebug : true
|
||||
|
||||
@@ -48,7 +48,7 @@ static char staticBuf[0x100 + 1] = {0};
|
||||
|
||||
MyThread *errDispCreateThread(void)
|
||||
{
|
||||
if(R_FAILED(MyThread_Create(&errDispThread, errDispThreadMain, errDispThreadStack, 0xD00, 0x18, CORE_SYSTEM)))
|
||||
if(R_FAILED(MyThread_Create(&errDispThread, errDispThreadMain, errDispThreadStack, 0xD00, 55, CORE_SYSTEM)))
|
||||
svcBreak(USERBREAK_PANIC);
|
||||
return &errDispThread;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ int GDB_ReceivePacket(GDBContext *ctx)
|
||||
memcpy(backupbuf, ctx->buffer, ctx->latestSentPacketSize);
|
||||
memset(ctx->buffer, 0, sizeof(ctx->buffer));
|
||||
|
||||
int r = soc_recv(ctx->super.sockfd, ctx->buffer, sizeof(ctx->buffer), MSG_PEEK);
|
||||
int r = socRecv(ctx->super.sockfd, ctx->buffer, sizeof(ctx->buffer), MSG_PEEK);
|
||||
if(r < 1)
|
||||
return -1;
|
||||
if(ctx->buffer[0] == '+') // GDB sometimes acknowleges TCP acknowledgment packets (yes...). IDA does it properly
|
||||
@@ -186,20 +186,20 @@ int GDB_ReceivePacket(GDBContext *ctx)
|
||||
return -1;
|
||||
|
||||
// Consume it
|
||||
r = soc_recv(ctx->super.sockfd, ctx->buffer, 1, 0);
|
||||
r = socRecv(ctx->super.sockfd, ctx->buffer, 1, 0);
|
||||
if(r != 1)
|
||||
return -1;
|
||||
|
||||
ctx->buffer[0] = 0;
|
||||
|
||||
r = soc_recv(ctx->super.sockfd, ctx->buffer, sizeof(ctx->buffer), MSG_PEEK);
|
||||
r = socRecv(ctx->super.sockfd, ctx->buffer, sizeof(ctx->buffer), MSG_PEEK);
|
||||
|
||||
if(r == -1)
|
||||
goto packet_error;
|
||||
}
|
||||
else if(ctx->buffer[0] == '-')
|
||||
{
|
||||
soc_send(ctx->super.sockfd, backupbuf, ctx->latestSentPacketSize, 0);
|
||||
socSend(ctx->super.sockfd, backupbuf, ctx->latestSentPacketSize, 0);
|
||||
return 0;
|
||||
}
|
||||
int maxlen = r > (int)sizeof(ctx->buffer) ? (int)sizeof(ctx->buffer) : r;
|
||||
@@ -215,7 +215,7 @@ int GDB_ReceivePacket(GDBContext *ctx)
|
||||
else
|
||||
{
|
||||
u8 checksum;
|
||||
r = soc_recv(ctx->super.sockfd, ctx->buffer, 3 + pos - ctx->buffer, 0);
|
||||
r = socRecv(ctx->super.sockfd, ctx->buffer, 3 + pos - ctx->buffer, 0);
|
||||
if(r != 3 + pos - ctx->buffer || GDB_DecodeHex(&checksum, pos + 1, 1) != 1)
|
||||
goto packet_error;
|
||||
else if(GDB_ComputeChecksum(ctx->buffer + 1, pos - ctx->buffer - 1) != checksum)
|
||||
@@ -227,7 +227,7 @@ int GDB_ReceivePacket(GDBContext *ctx)
|
||||
}
|
||||
else if(ctx->buffer[0] == '\x03')
|
||||
{
|
||||
r = soc_recv(ctx->super.sockfd, ctx->buffer, 1, 0);
|
||||
r = socRecv(ctx->super.sockfd, ctx->buffer, 1, 0);
|
||||
if(r != 1)
|
||||
goto packet_error;
|
||||
|
||||
@@ -236,7 +236,7 @@ int GDB_ReceivePacket(GDBContext *ctx)
|
||||
|
||||
if(!(ctx->flags & GDB_FLAG_NOACK))
|
||||
{
|
||||
int r2 = soc_send(ctx->super.sockfd, "+", 1, 0);
|
||||
int r2 = socSend(ctx->super.sockfd, "+", 1, 0);
|
||||
if(r2 != 1)
|
||||
return -1;
|
||||
}
|
||||
@@ -252,7 +252,7 @@ int GDB_ReceivePacket(GDBContext *ctx)
|
||||
packet_error:
|
||||
if(!(ctx->flags & GDB_FLAG_NOACK))
|
||||
{
|
||||
r = soc_send(ctx->super.sockfd, "-", 1, 0);
|
||||
r = socSend(ctx->super.sockfd, "-", 1, 0);
|
||||
if(r != 1)
|
||||
return -1;
|
||||
else
|
||||
@@ -264,7 +264,7 @@ packet_error:
|
||||
|
||||
static int GDB_DoSendPacket(GDBContext *ctx, u32 len)
|
||||
{
|
||||
int r = soc_send(ctx->super.sockfd, ctx->buffer, len, 0);
|
||||
int r = socSend(ctx->super.sockfd, ctx->buffer, len, 0);
|
||||
|
||||
if(r > 0)
|
||||
ctx->latestSentPacketSize = r;
|
||||
|
||||
@@ -262,7 +262,10 @@ GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMemRegions)
|
||||
goto end;
|
||||
}
|
||||
|
||||
while (address < 0x40000000 ///< Limit to check for regions
|
||||
s64 TTBCR;
|
||||
svcGetSystemInfo(&TTBCR, 0x10002, 0);
|
||||
|
||||
while (address < (1u << (32 - (u32)TTBCR)) ///< Limit to check for regions
|
||||
&& posInBuffer < maxPosInBuffer
|
||||
&& R_SUCCEEDED(svcQueryProcessMemory(&memi, &pagei, handle, address)))
|
||||
{
|
||||
|
||||
@@ -74,13 +74,14 @@ void GDB_DecrementServerReferenceCount(GDBServer *server)
|
||||
|
||||
void GDB_RunServer(GDBServer *server)
|
||||
{
|
||||
server_bind(&server->super, GDB_PORT_BASE);
|
||||
server_bind(&server->super, GDB_PORT_BASE + 1);
|
||||
server_bind(&server->super, GDB_PORT_BASE + 2);
|
||||
Result res = server_bind(&server->super, GDB_PORT_BASE);
|
||||
if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 1);
|
||||
if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 2);
|
||||
|
||||
server_bind(&server->super, GDB_PORT_BASE + 3); // next application
|
||||
if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 3); // next application
|
||||
|
||||
server_run(&server->super);
|
||||
if(R_SUCCEEDED(res))
|
||||
server_run(&server->super);
|
||||
}
|
||||
|
||||
void GDB_LockAllContexts(GDBServer *server)
|
||||
|
||||
@@ -279,7 +279,9 @@ void HBLDR_HandleCommands(void *ctx)
|
||||
|
||||
memset(localcaps0->reslimits, 0, sizeof(localcaps0->reslimits));
|
||||
|
||||
localcaps0->reslimits[0] = 0x9E; // Stuff needed to run stuff on core1
|
||||
// Set mode1 preemption mode for core1, max. 89% of CPU time (default 0, requires a APT_SetAppCpuTimeLimit call)
|
||||
// See the big comment in sysmodules/pm/source/reslimit.c for technical details.
|
||||
localcaps0->reslimits[0] = BIT(7) | 89;
|
||||
|
||||
localcaps0->storage_info.fs_access_info = 0xFFFFFFFF; // Give access to everything
|
||||
localcaps0->storage_info.no_romfs = true;
|
||||
|
||||
@@ -55,27 +55,51 @@ int inputRedirectionStartResult;
|
||||
void inputRedirectionThreadMain(void)
|
||||
{
|
||||
Result res = 0;
|
||||
inputRedirectionStartResult = 0;
|
||||
|
||||
res = miniSocInit();
|
||||
if(R_FAILED(res))
|
||||
{
|
||||
// Socket services broken
|
||||
inputRedirectionStartResult = res;
|
||||
|
||||
miniSocExit();
|
||||
// Still signal the event
|
||||
svcSignalEvent(inputRedirectionThreadStartedEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
int sock = socSocket(AF_INET, SOCK_DGRAM, 0);
|
||||
while(sock == -1)
|
||||
u32 tries = 15;
|
||||
while(sock == -1 && --tries > 0)
|
||||
{
|
||||
svcSleepThread(1000 * 0000 * 0000LL);
|
||||
svcSleepThread(100 * 1000 * 1000LL);
|
||||
sock = socSocket(AF_INET, SOCK_DGRAM, 0);
|
||||
}
|
||||
|
||||
if (sock < -10000 || tries == 0) {
|
||||
// Socket services broken
|
||||
inputRedirectionStartResult = -1;
|
||||
|
||||
miniSocExit();
|
||||
// Still signal the event
|
||||
svcSignalEvent(inputRedirectionThreadStartedEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
struct sockaddr_in saddr;
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(4950);
|
||||
saddr.sin_addr.s_addr = gethostid();
|
||||
saddr.sin_addr.s_addr = socGethostid();
|
||||
res = socBind(sock, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));
|
||||
if(res != 0)
|
||||
{
|
||||
socClose(sock);
|
||||
miniSocExit();
|
||||
inputRedirectionStartResult = res;
|
||||
|
||||
// Still signal the event
|
||||
svcSignalEvent(inputRedirectionThreadStartedEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -99,7 +123,7 @@ void inputRedirectionThreadMain(void)
|
||||
int pollres = socPoll(&pfd, 1, 10);
|
||||
if(pollres > 0 && (pfd.revents & POLLIN))
|
||||
{
|
||||
int n = soc_recvfrom(sock, buf, 20, 0, NULL, 0);
|
||||
int n = socRecvfrom(sock, buf, 20, 0, NULL, 0);
|
||||
if(n < 0)
|
||||
break;
|
||||
else if(n < 12)
|
||||
@@ -125,21 +149,40 @@ void inputRedirectionThreadMain(void)
|
||||
srvPublishToSubscriber(0x203, 0);
|
||||
}
|
||||
}
|
||||
else if(pollres < -10000)
|
||||
break;
|
||||
}
|
||||
|
||||
inputRedirectionEnabled = false;
|
||||
struct linger linger;
|
||||
linger.l_onoff = 1;
|
||||
linger.l_linger = 0;
|
||||
|
||||
socSetsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger));
|
||||
|
||||
socClose(sock);
|
||||
|
||||
miniSocExit();
|
||||
}
|
||||
|
||||
void hidCodePatchFunc(void);
|
||||
void irCodePatchFunc(void);
|
||||
|
||||
Result InputRedirection_Disable(s64 timeout)
|
||||
{
|
||||
if(!inputRedirectionEnabled)
|
||||
return 0;
|
||||
|
||||
Result res = InputRedirection_DoOrUndoPatches();
|
||||
if(R_FAILED(res))
|
||||
return res;
|
||||
|
||||
inputRedirectionEnabled = false;
|
||||
res = MyThread_Join(&inputRedirectionThread, timeout);
|
||||
svcCloseHandle(inputRedirectionThreadStartedEvent);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Result InputRedirection_DoOrUndoPatches(void)
|
||||
{
|
||||
s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
|
||||
@@ -147,6 +190,8 @@ Result InputRedirection_DoOrUndoPatches(void)
|
||||
Handle processHandle;
|
||||
|
||||
Result res = OpenProcessByName("hid", &processHandle);
|
||||
static bool hidPatched = false;
|
||||
static bool irPatched = false;
|
||||
|
||||
if(R_SUCCEEDED(res))
|
||||
{
|
||||
@@ -173,11 +218,12 @@ Result InputRedirection_DoOrUndoPatches(void)
|
||||
static u32 *hidRegPatchOffsets[2];
|
||||
static u32 *hidPatchJumpLoc;
|
||||
|
||||
if(inputRedirectionEnabled)
|
||||
if(hidPatched)
|
||||
{
|
||||
memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
|
||||
memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
|
||||
memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode));
|
||||
hidPatched = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -218,6 +264,7 @@ Result InputRedirection_DoOrUndoPatches(void)
|
||||
|
||||
*off = *off2 = hidDataPhys;
|
||||
memcpy(off3, &hidHook, sizeof(hidHook));
|
||||
hidPatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +311,7 @@ Result InputRedirection_DoOrUndoPatches(void)
|
||||
|
||||
static u32 *irHookLoc, *irWaitSyncLoc, *irCppFlagLoc;
|
||||
|
||||
if(inputRedirectionEnabled)
|
||||
if(irPatched)
|
||||
{
|
||||
memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode));
|
||||
if(useOldSyncCode)
|
||||
@@ -272,6 +319,8 @@ Result InputRedirection_DoOrUndoPatches(void)
|
||||
else
|
||||
memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode));
|
||||
memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode));
|
||||
|
||||
irPatched = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -331,6 +380,8 @@ Result InputRedirection_DoOrUndoPatches(void)
|
||||
|
||||
// This NOPs out a flag check in ir:user's CPP emulation
|
||||
*irCppFlagLoc = 0xE3150000; // tst r5, #0
|
||||
|
||||
irPatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,9 +37,15 @@
|
||||
#include "menus/miscellaneous.h"
|
||||
#include "menus/debugger.h"
|
||||
#include "menus/screen_filters.h"
|
||||
#include "menus/cheats.h"
|
||||
#include "menus/sysconfig.h"
|
||||
#include "input_redirection.h"
|
||||
#include "minisoc.h"
|
||||
|
||||
#include "task_runner.h"
|
||||
|
||||
bool isN3DS;
|
||||
|
||||
static Result stealFsReg(void)
|
||||
{
|
||||
Result ret = 0;
|
||||
@@ -73,11 +79,51 @@ static Result fsRegSetupPermissions(void)
|
||||
return res;
|
||||
}
|
||||
|
||||
// this is called before main
|
||||
bool isN3DS;
|
||||
void __appInit()
|
||||
Result __sync_init(void);
|
||||
Result __sync_fini(void);
|
||||
void __libc_init_array(void);
|
||||
void __libc_fini_array(void);
|
||||
|
||||
void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error
|
||||
|
||||
// this is called after main exits
|
||||
void __wrap_exit(int rc)
|
||||
{
|
||||
(void)rc;
|
||||
// TODO: make pm terminate rosalina
|
||||
__libc_fini_array();
|
||||
|
||||
// Kernel will take care of it all
|
||||
/*
|
||||
pmDbgExit();
|
||||
fsExit();
|
||||
svcCloseHandle(*fsRegGetSessionHandle());
|
||||
srvExit();
|
||||
__sync_fini();*/
|
||||
|
||||
svcExitProcess();
|
||||
}
|
||||
|
||||
// this is called before main
|
||||
void initSystem(void)
|
||||
{
|
||||
s64 out;
|
||||
Result res;
|
||||
__sync_init();
|
||||
|
||||
isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0;
|
||||
|
||||
svcGetSystemInfo(&out, 0x10000, 0x100);
|
||||
HBLDR_3DSX_TID = out == 0 ? HBLDR_DEFAULT_3DSX_TID : (u64)out;
|
||||
|
||||
svcGetSystemInfo(&out, 0x10000, 0x101);
|
||||
menuCombo = out == 0 ? DEFAULT_MENU_COMBO : (u32)out;
|
||||
|
||||
miscellaneousMenu.items[0].title = HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID ? "Switch the hb. title to the current app." :
|
||||
"Switch the hb. title to hblauncher_loader";
|
||||
|
||||
ProcessPatchesMenu_PatchUnpatchFSDirectly();
|
||||
|
||||
for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL))
|
||||
{
|
||||
res = srvInit();
|
||||
@@ -91,52 +137,9 @@ void __appInit()
|
||||
if (R_FAILED(pmDbgInit()))
|
||||
svcBreak(USERBREAK_PANIC);
|
||||
|
||||
if (R_FAILED(acInit()))
|
||||
svcBreak(USERBREAK_PANIC);
|
||||
}
|
||||
// **** DO NOT init services that don't come from KIPs here ****
|
||||
// Instead, init the service only where it's actually init (then deinit it).
|
||||
|
||||
// this is called after main exits
|
||||
void __appExit()
|
||||
{
|
||||
acExit();
|
||||
pmDbgExit();
|
||||
fsExit();
|
||||
svcCloseHandle(*fsRegGetSessionHandle());
|
||||
srvExit();
|
||||
}
|
||||
|
||||
|
||||
Result __sync_init(void);
|
||||
Result __sync_fini(void);
|
||||
void __libc_init_array(void);
|
||||
void __libc_fini_array(void);
|
||||
|
||||
void __ctru_exit()
|
||||
{
|
||||
__libc_fini_array();
|
||||
__appExit();
|
||||
__sync_fini();
|
||||
svcExitProcess();
|
||||
}
|
||||
|
||||
|
||||
void initSystem()
|
||||
{
|
||||
s64 out;
|
||||
isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0;
|
||||
|
||||
svcGetSystemInfo(&out, 0x10000, 0x100);
|
||||
HBLDR_3DSX_TID = out == 0 ? HBLDR_DEFAULT_3DSX_TID : (u64)out;
|
||||
|
||||
svcGetSystemInfo(&out, 0x10000, 0x101);
|
||||
menuCombo = out == 0 ? DEFAULT_MENU_COMBO : (u32)out;
|
||||
|
||||
miscellaneousMenu.items[0].title = HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID ? "Switch the hb. title to the current app." :
|
||||
"Switch the hb. title to hblauncher_loader";
|
||||
|
||||
ProcessPatchesMenu_PatchUnpatchFSDirectly();
|
||||
__sync_init();
|
||||
__appInit();
|
||||
__libc_init_array();
|
||||
|
||||
// ROSALINA HACKJOB BEGIN
|
||||
@@ -161,12 +164,31 @@ static void handleTermNotification(u32 notificationId)
|
||||
svcSignalEvent(terminationRequestEvent);
|
||||
}
|
||||
|
||||
static void relinquishConnectionSessions(u32 notificationId)
|
||||
{
|
||||
(void)notificationId;
|
||||
// Might be subject to a race condition, but heh.
|
||||
|
||||
// Disable input redirection
|
||||
InputRedirection_Disable(100 * 1000 * 1000LL);
|
||||
|
||||
// Ask the debugger to terminate in approx 2 * 100ms
|
||||
debuggerDisable(100 * 1000 * 1000LL);
|
||||
|
||||
// Kill the ac session if needed
|
||||
if(isConnectionForced)
|
||||
{
|
||||
acExit();
|
||||
isConnectionForced = false;
|
||||
SysConfigMenu_UpdateStatus(true);
|
||||
}
|
||||
}
|
||||
|
||||
static void handleNextApplicationDebuggedByForce(u32 notificationId)
|
||||
{
|
||||
int dummy;
|
||||
(void)notificationId;
|
||||
// Following call needs to be async because pm -> Loader depends on rosalina hb:ldr, handled in this very thread.
|
||||
TaskRunner_RunTask(debuggerFetchAndSetNextApplicationDebugHandleTask, &dummy, 0);
|
||||
TaskRunner_RunTask(debuggerFetchAndSetNextApplicationDebugHandleTask, NULL, 0);
|
||||
}
|
||||
|
||||
static const ServiceManagerServiceEntry services[] = {
|
||||
@@ -176,7 +198,9 @@ static const ServiceManagerServiceEntry services[] = {
|
||||
|
||||
static const ServiceManagerNotificationEntry notifications[] = {
|
||||
{ 0x100 , handleTermNotification },
|
||||
//{ 0x103 , relinquishConnectionSessions }, // Sleep mode entry <=== causes issues
|
||||
{ 0x1000, handleNextApplicationDebuggedByForce },
|
||||
{ 0x2000, relinquishConnectionSessions },
|
||||
{ 0x000, NULL },
|
||||
};
|
||||
|
||||
@@ -195,6 +219,8 @@ int main(void)
|
||||
if(R_FAILED(svcCreateEvent(&terminationRequestEvent, RESET_STICKY)))
|
||||
svcBreak(USERBREAK_ASSERT);
|
||||
|
||||
Cheat_SeedRng(svcGetSystemTick());
|
||||
|
||||
MyThread *menuThread = menuCreateThread();
|
||||
MyThread *taskRunnerThread = taskRunnerCreateThread();
|
||||
MyThread *errDispThread = errDispCreateThread();
|
||||
@@ -202,6 +228,8 @@ int main(void)
|
||||
if (R_FAILED(ServiceManager_Run(services, notifications, NULL)))
|
||||
svcBreak(USERBREAK_PANIC);
|
||||
|
||||
TaskRunner_Terminate();
|
||||
|
||||
MyThread_Join(menuThread, -1LL);
|
||||
MyThread_Join(taskRunnerThread, -1LL);
|
||||
MyThread_Join(errDispThread, -1LL);
|
||||
|
||||
@@ -245,7 +245,7 @@ static void menuDraw(Menu *menu, u32 selected)
|
||||
if(miniSocEnabled)
|
||||
{
|
||||
char ipBuffer[17];
|
||||
u32 ip = gethostid();
|
||||
u32 ip = socGethostid();
|
||||
u8 *addr = (u8 *)&ip;
|
||||
int n = sprintf(ipBuffer, "%hhu.%hhu.%hhu.%hhu", addr[0], addr[1], addr[2], addr[3]);
|
||||
Draw_DrawString(SCREEN_BOT_WIDTH - 10 - SPACING_X * n, 10, COLOR_WHITE, ipBuffer);
|
||||
|
||||
@@ -33,16 +33,11 @@
|
||||
#include "utils.h"
|
||||
#include "fmt.h"
|
||||
#include "ifile.h"
|
||||
#include "pmdbgext.h"
|
||||
|
||||
#define MAKE_QWORD(hi,low) \
|
||||
((u64) ((((u64)(hi)) << 32) | (low)))
|
||||
|
||||
typedef struct CheatProcessInfo
|
||||
{
|
||||
u32 pid;
|
||||
u64 titleId;
|
||||
} CheatProcessInfo;
|
||||
|
||||
typedef struct CheatDescription
|
||||
{
|
||||
struct {
|
||||
@@ -70,36 +65,6 @@ CheatDescription* cheats[1024] = { 0 };
|
||||
u8 cheatBuffer[32768] = { 0 };
|
||||
u8 cheatPage[0x1000] = { 0 };
|
||||
|
||||
static CheatProcessInfo cheatinfo[0x40] = { 0 };
|
||||
|
||||
static s32 Cheats_FetchProcessInfo(void)
|
||||
{
|
||||
u32 pidList[0x40];
|
||||
s32 processAmount;
|
||||
|
||||
s64 sa, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
|
||||
|
||||
svcGetProcessList(&processAmount, pidList, 0x40);
|
||||
|
||||
for (s32 i = 0; i < processAmount; i++)
|
||||
{
|
||||
Handle processHandle;
|
||||
Result res = svcOpenProcess(&processHandle, pidList[i]);
|
||||
if (R_FAILED(res)) continue;
|
||||
|
||||
cheatinfo[i].pid = pidList[i];
|
||||
svcGetProcessInfo((s64 *) &cheatinfo[i].titleId, processHandle, 0x10001);
|
||||
svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002);
|
||||
svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
|
||||
svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
|
||||
svcGetProcessInfo(&sa, processHandle, 0x10005);
|
||||
|
||||
svcCloseHandle(processHandle);
|
||||
}
|
||||
|
||||
return processAmount;
|
||||
}
|
||||
|
||||
typedef struct CheatState
|
||||
{
|
||||
u32 index;
|
||||
@@ -131,6 +96,7 @@ typedef struct CheatState
|
||||
CheatState cheat_state = { 0 };
|
||||
u8 cheatCount = 0;
|
||||
u64 cheatTitleInfo = -1ULL;
|
||||
u64 cheatRngState = 0;
|
||||
|
||||
static inline u32* activeOffset()
|
||||
{
|
||||
@@ -149,6 +115,12 @@ static inline u32* activeStorage(CheatDescription* desc)
|
||||
|
||||
char failureReason[64];
|
||||
|
||||
static u32 Cheat_GetRandomNumber(void)
|
||||
{
|
||||
cheatRngState = 0x5D588B656C078965ULL * cheatRngState + 0x0000000000269EC3ULL;
|
||||
return (u32)(cheatRngState >> 32);
|
||||
}
|
||||
|
||||
static bool Cheat_IsValidAddress(const Handle processHandle, u32 address, u32 size)
|
||||
{
|
||||
MemInfo info;
|
||||
@@ -1512,7 +1484,7 @@ static u32 Cheat_ApplyCheat(const Handle processHandle, CheatDescription* const
|
||||
case 0xF:
|
||||
{
|
||||
u32 range = arg1 - (arg0 & 0xFFFFFF);
|
||||
u32 number = rand() % range;
|
||||
u32 number = Cheat_GetRandomNumber() % range;
|
||||
*activeData() = (arg0 & 0xFFFFFF) + number;
|
||||
}
|
||||
break;
|
||||
@@ -1886,33 +1858,20 @@ static void Cheat_LoadCheatsIntoMemory(u64 titleId)
|
||||
memset(cheatPage, 0, 0x1000);
|
||||
}
|
||||
|
||||
static u32 Cheat_GetCurrentPID(u64* titleId)
|
||||
static u32 Cheat_GetCurrentProcessAndTitleId(u64* titleId)
|
||||
{
|
||||
s32 processAmount = Cheats_FetchProcessInfo();
|
||||
|
||||
s32 index = -1;
|
||||
|
||||
for (s32 i = 0; i < processAmount; i++)
|
||||
{
|
||||
|
||||
if (((u32) (cheatinfo[i].titleId >> 32)) == 0x00040010 || ((u32) (cheatinfo[i].titleId >> 32) == 0x00040000))
|
||||
{
|
||||
index = i;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
*titleId = cheatinfo[index].titleId;
|
||||
return cheatinfo[index].pid;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 pid;
|
||||
Result res = PMDBG_GetCurrentAppTitleIdAndPid(titleId, &pid);
|
||||
if (R_FAILED(res)) {
|
||||
*titleId = 0;
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
void Cheat_SeedRng(u64 seed)
|
||||
{
|
||||
cheatRngState = seed;
|
||||
}
|
||||
|
||||
void Cheat_ApplyCheats(void)
|
||||
@@ -1923,7 +1882,7 @@ void Cheat_ApplyCheats(void)
|
||||
}
|
||||
|
||||
u64 titleId = 0;
|
||||
u32 pid = Cheat_GetCurrentPID(&titleId);
|
||||
u32 pid = Cheat_GetCurrentProcessAndTitleId(&titleId);
|
||||
|
||||
if (!titleId)
|
||||
{
|
||||
@@ -1949,7 +1908,7 @@ void Cheat_ApplyCheats(void)
|
||||
void RosalinaMenu_Cheats(void)
|
||||
{
|
||||
u64 titleId = 0;
|
||||
u32 pid = Cheat_GetCurrentPID(&titleId);
|
||||
u32 pid = Cheat_GetCurrentProcessAndTitleId(&titleId);
|
||||
|
||||
if (titleId != 0)
|
||||
{
|
||||
|
||||
@@ -84,6 +84,30 @@ void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata)
|
||||
GDB_UnlockAllContexts(&gdbServer);
|
||||
}
|
||||
|
||||
Result debuggerDisable(s64 timeout)
|
||||
{
|
||||
Result res = 0;
|
||||
bool initialized = gdbServer.referenceCount != 0;
|
||||
if(initialized)
|
||||
{
|
||||
svcSignalEvent(gdbServer.super.shall_terminate_event);
|
||||
server_kill_connections(&gdbServer.super);
|
||||
|
||||
res = MyThread_Join(&debuggerDebugThread, timeout);
|
||||
if(res == 0)
|
||||
res = MyThread_Join(&debuggerSocketThread, timeout);
|
||||
|
||||
Handle dummy = 0;
|
||||
PMDBG_RunQueuedProcess(&dummy);
|
||||
svcCloseHandle(dummy);
|
||||
PMDBG_DebugNextApplicationByForce(false);
|
||||
nextApplicationGdbCtx = NULL;
|
||||
svcKernelSetState(0x10000, 2);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void DebuggerMenu_EnableDebugger(void)
|
||||
{
|
||||
bool done = false, alreadyEnabled = gdbServer.super.running;
|
||||
@@ -115,16 +139,18 @@ void DebuggerMenu_EnableDebugger(void)
|
||||
if(!done)
|
||||
{
|
||||
res = GDB_InitializeServer(&gdbServer);
|
||||
Handle handles[3] = { gdbServer.super.started_event, gdbServer.super.shall_terminate_event, terminationRequestEvent };
|
||||
s32 idx;
|
||||
if(R_SUCCEEDED(res))
|
||||
{
|
||||
debuggerCreateSocketThread();
|
||||
debuggerCreateDebugThread();
|
||||
res = svcWaitSynchronization(gdbServer.super.started_event, 10 * 1000 * 1000 * 1000LL);
|
||||
res = svcWaitSynchronizationN(&idx, handles, 3, false, 10 * 1000 * 1000 * 1000LL);
|
||||
if(res == 0) res = gdbServer.super.init_result;
|
||||
}
|
||||
|
||||
if(res != 0)
|
||||
sprintf(buf, "Starting debugger... failed (0x%08lx).", (u32)res);
|
||||
|
||||
done = true;
|
||||
}
|
||||
if(res == 0)
|
||||
@@ -142,27 +168,10 @@ void DebuggerMenu_EnableDebugger(void)
|
||||
void DebuggerMenu_DisableDebugger(void)
|
||||
{
|
||||
bool initialized = gdbServer.referenceCount != 0;
|
||||
Result res = 0;
|
||||
|
||||
Result res = initialized ? debuggerDisable(2 * 1000 * 1000 * 1000LL) : 0;
|
||||
char buf[65];
|
||||
|
||||
if(initialized)
|
||||
{
|
||||
svcSignalEvent(gdbServer.super.shall_terminate_event);
|
||||
server_kill_connections(&gdbServer.super);
|
||||
//server_set_should_close_all(&gdbServer.super);
|
||||
|
||||
res = MyThread_Join(&debuggerDebugThread, 2 * 1000 * 1000 * 1000LL);
|
||||
if(res == 0)
|
||||
res = MyThread_Join(&debuggerSocketThread, 2 * 1000 * 1000 * 1000LL);
|
||||
|
||||
Handle dummy = 0;
|
||||
PMDBG_RunQueuedProcess(&dummy);
|
||||
svcCloseHandle(dummy);
|
||||
PMDBG_DebugNextApplicationByForce(false);
|
||||
nextApplicationGdbCtx = NULL;
|
||||
svcKernelSetState(0x10000, 2);
|
||||
}
|
||||
|
||||
if(res != 0)
|
||||
sprintf(buf, "Failed to disable debugger (0x%08lx).", (u32)res);
|
||||
|
||||
|
||||
@@ -221,7 +221,6 @@ void MiscellaneousMenu_SaveSettings(void)
|
||||
|
||||
void MiscellaneousMenu_InputRedirection(void)
|
||||
{
|
||||
static MyThread *inputRedirectionThread = NULL;
|
||||
bool done = false;
|
||||
|
||||
Result res;
|
||||
@@ -231,11 +230,7 @@ void MiscellaneousMenu_InputRedirection(void)
|
||||
|
||||
if(wasEnabled)
|
||||
{
|
||||
res = InputRedirection_DoOrUndoPatches();
|
||||
inputRedirectionEnabled = false;
|
||||
res = MyThread_Join(inputRedirectionThread, 5 * 1000 * 1000 * 1000LL);
|
||||
svcCloseHandle(inputRedirectionThreadStartedEvent);
|
||||
|
||||
res = InputRedirection_Disable(5 * 1000 * 1000 * 1000LL);
|
||||
if(res != 0)
|
||||
sprintf(buf, "Failed to stop InputRedirection (0x%08lx).", (u32)res);
|
||||
else
|
||||
@@ -282,13 +277,18 @@ void MiscellaneousMenu_InputRedirection(void)
|
||||
res = svcCreateEvent(&inputRedirectionThreadStartedEvent, RESET_STICKY);
|
||||
if(R_SUCCEEDED(res))
|
||||
{
|
||||
inputRedirectionThread = inputRedirectionCreateThread();
|
||||
inputRedirectionCreateThread();
|
||||
res = svcWaitSynchronization(inputRedirectionThreadStartedEvent, 10 * 1000 * 1000 * 1000LL);
|
||||
if(res == 0)
|
||||
res = (Result)inputRedirectionStartResult;
|
||||
|
||||
if(res != 0)
|
||||
{
|
||||
svcCloseHandle(inputRedirectionThreadStartedEvent);
|
||||
InputRedirection_DoOrUndoPatches();
|
||||
inputRedirectionEnabled = false;
|
||||
}
|
||||
inputRedirectionStartResult = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ static void ProcessListMenu_DumpMemory(const char *name, void *start, u32 size)
|
||||
IFile file;
|
||||
Result res;
|
||||
|
||||
char filename[64] = {0};
|
||||
char filename[100] = {0};
|
||||
|
||||
FS_Archive archive;
|
||||
FS_ArchiveID archiveId;
|
||||
@@ -666,7 +666,7 @@ void RosalinaMenu_ProcessList(void)
|
||||
if(gdbServer.super.running)
|
||||
{
|
||||
char ipBuffer[17];
|
||||
u32 ip = gethostid();
|
||||
u32 ip = socGethostid();
|
||||
u8 *addr = (u8 *)&ip;
|
||||
int n = sprintf(ipBuffer, "%hhu.%hhu.%hhu.%hhu", addr[0], addr[1], addr[2], addr[3]);
|
||||
Draw_DrawString(SCREEN_BOT_WIDTH - 10 - SPACING_X * n, 10, COLOR_WHITE, ipBuffer);
|
||||
|
||||
@@ -43,6 +43,8 @@ Menu sysconfigMenu = {
|
||||
}
|
||||
};
|
||||
|
||||
bool isConnectionForced = false;
|
||||
|
||||
void SysConfigMenu_ToggleLEDs(void)
|
||||
{
|
||||
Draw_Lock();
|
||||
@@ -149,9 +151,29 @@ void SysConfigMenu_ToggleWireless(void)
|
||||
while(!terminationRequest);
|
||||
}
|
||||
|
||||
static void SysConfigMenu_ForceWifiConnection(int slot)
|
||||
void SysConfigMenu_UpdateStatus(bool control)
|
||||
{
|
||||
MenuItem *item = &sysconfigMenu.items[3];
|
||||
|
||||
if(control)
|
||||
{
|
||||
item->title = "Control Wireless connection";
|
||||
item->method = &SysConfigMenu_ControlWifi;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->title = "Disable forced wireless connection";
|
||||
item->method = &SysConfigMenu_DisableForcedWifiConnection;
|
||||
}
|
||||
}
|
||||
|
||||
static bool SysConfigMenu_ForceWifiConnection(int slot)
|
||||
{
|
||||
char ssid[0x20 + 1] = {0};
|
||||
isConnectionForced = false;
|
||||
|
||||
if(R_FAILED(acInit()))
|
||||
return false;
|
||||
|
||||
acuConfig config = {0};
|
||||
ACU_CreateDefaultConfig(&config);
|
||||
@@ -165,14 +187,19 @@ static void SysConfigMenu_ForceWifiConnection(int slot)
|
||||
bool forcedConnection = false;
|
||||
if(R_SUCCEEDED(ACU_ConnectAsync(&config, connectEvent)))
|
||||
{
|
||||
if(R_SUCCEEDED(svcWaitSynchronization(connectEvent, -1)))
|
||||
{
|
||||
ACU_GetSSID(ssid);
|
||||
if(R_SUCCEEDED(svcWaitSynchronization(connectEvent, -1)) && R_SUCCEEDED(ACU_GetSSID(ssid)))
|
||||
forcedConnection = true;
|
||||
}
|
||||
}
|
||||
svcCloseHandle(connectEvent);
|
||||
|
||||
if(forcedConnection)
|
||||
{
|
||||
isConnectionForced = true;
|
||||
SysConfigMenu_UpdateStatus(false);
|
||||
}
|
||||
else
|
||||
acExit();
|
||||
|
||||
char infoString[80] = {0};
|
||||
u32 infoStringColor = forcedConnection ? COLOR_GREEN : COLOR_RED;
|
||||
if(forcedConnection)
|
||||
@@ -198,9 +225,11 @@ static void SysConfigMenu_ForceWifiConnection(int slot)
|
||||
u32 pressed = waitInputWithTimeout(1000);
|
||||
|
||||
if(pressed & BUTTON_B)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
while(!terminationRequest);
|
||||
|
||||
return forcedConnection;
|
||||
}
|
||||
|
||||
void SysConfigMenu_TogglePowerButton(void)
|
||||
@@ -269,7 +298,11 @@ void SysConfigMenu_ControlWifi(void)
|
||||
|
||||
if(pressed & BUTTON_A)
|
||||
{
|
||||
SysConfigMenu_ForceWifiConnection(slot);
|
||||
if(SysConfigMenu_ForceWifiConnection(slot))
|
||||
{
|
||||
// Connection successfully forced, return from this menu to prevent ac handle refcount leakage.
|
||||
break;
|
||||
}
|
||||
|
||||
Draw_Lock();
|
||||
Draw_ClearFramebuffer();
|
||||
@@ -301,3 +334,26 @@ void SysConfigMenu_ControlWifi(void)
|
||||
}
|
||||
while(!terminationRequest);
|
||||
}
|
||||
|
||||
void SysConfigMenu_DisableForcedWifiConnection(void)
|
||||
{
|
||||
Draw_Lock();
|
||||
Draw_ClearFramebuffer();
|
||||
Draw_FlushFramebuffer();
|
||||
Draw_Unlock();
|
||||
|
||||
acExit();
|
||||
SysConfigMenu_UpdateStatus(true);
|
||||
|
||||
do
|
||||
{
|
||||
Draw_Lock();
|
||||
Draw_DrawString(10, 10, COLOR_TITLE, "System configuration menu");
|
||||
Draw_DrawString(10, 30, COLOR_WHITE, "Forced connection successfully disabled.\nNote: auto-connection may remain broken.");
|
||||
|
||||
u32 pressed = waitInputWithTimeout(1000);
|
||||
if(pressed & BUTTON_B)
|
||||
return;
|
||||
}
|
||||
while(!terminationRequest);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,16 @@
|
||||
#include <3ds/ipc.h>
|
||||
#include <3ds/os.h>
|
||||
#include <3ds/synchronization.h>
|
||||
#include "memory.h"
|
||||
#include <3ds/result.h>
|
||||
#include <string.h>
|
||||
|
||||
s32 miniSocRefCount = 0;
|
||||
static u32 socContextAddr = 0x08000000;
|
||||
static u32 socContextSize = 0x60000;
|
||||
static Handle miniSocHandle;
|
||||
static Handle miniSocMemHandle;
|
||||
|
||||
bool miniSocEnabled = false;
|
||||
|
||||
s32 _net_convert_error(s32 sock_retval);
|
||||
|
||||
@@ -25,7 +34,7 @@ static Result SOCU_Initialize(Handle memhandle, u32 memsize)
|
||||
cmdbuf[4] = IPC_Desc_SharedHandles(1);
|
||||
cmdbuf[5] = memhandle;
|
||||
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
if(ret != 0)
|
||||
return ret;
|
||||
|
||||
@@ -39,22 +48,14 @@ static Result SOCU_Shutdown(void)
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x19,0,0); // 0x190000
|
||||
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
if(ret != 0)
|
||||
return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
static s32 miniSocRefCount = 0;
|
||||
static u32 socContextAddr = 0x08000000;
|
||||
static u32 socContextSize = 0x60000;
|
||||
// SOCU_handle from ctrulib
|
||||
// socMemhandle from ctrulib
|
||||
|
||||
bool miniSocEnabled = false;
|
||||
|
||||
Result miniSocInit()
|
||||
Result miniSocInit(void)
|
||||
{
|
||||
if(AtomicPostIncrement(&miniSocRefCount))
|
||||
return 0;
|
||||
@@ -71,7 +72,7 @@ Result miniSocInit()
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = srvGetServiceHandle(&SOCU_handle, "soc:U");
|
||||
ret = srvGetServiceHandle(&miniSocHandle, "soc:U");
|
||||
if(ret != 0) goto cleanup;
|
||||
|
||||
ret = svcControlMemory(&tmp, socContextAddr, 0, socContextSize, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE);
|
||||
@@ -79,12 +80,12 @@ Result miniSocInit()
|
||||
|
||||
socContextAddr = tmp;
|
||||
|
||||
ret = svcCreateMemoryBlock(&socMemhandle, (u32)socContextAddr, socContextSize, 0, 3);
|
||||
ret = svcCreateMemoryBlock(&miniSocMemHandle, (u32)socContextAddr, socContextSize, 0, 3);
|
||||
if(ret != 0) goto cleanup;
|
||||
|
||||
|
||||
|
||||
ret = SOCU_Initialize(socMemhandle, socContextSize);
|
||||
ret = SOCU_Initialize(miniSocMemHandle, socContextSize);
|
||||
if(ret != 0) goto cleanup;
|
||||
|
||||
svcKernelSetState(0x10000, 2);
|
||||
@@ -94,17 +95,17 @@ Result miniSocInit()
|
||||
cleanup:
|
||||
AtomicDecrement(&miniSocRefCount);
|
||||
|
||||
if(socMemhandle != 0)
|
||||
if(miniSocMemHandle != 0)
|
||||
{
|
||||
svcCloseHandle(socMemhandle);
|
||||
socMemhandle = 0;
|
||||
svcCloseHandle(miniSocMemHandle);
|
||||
miniSocMemHandle = 0;
|
||||
}
|
||||
|
||||
if(SOCU_handle != 0)
|
||||
if(miniSocHandle != 0)
|
||||
{
|
||||
SOCU_Shutdown();
|
||||
svcCloseHandle(SOCU_handle);
|
||||
SOCU_handle = 0;
|
||||
svcCloseHandle(miniSocHandle);
|
||||
miniSocHandle = 0;
|
||||
}
|
||||
|
||||
if(tmp != 0)
|
||||
@@ -113,21 +114,19 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
Result miniSocExit(void)
|
||||
Result miniSocExitDirect(void)
|
||||
{
|
||||
if(AtomicDecrement(&miniSocRefCount))
|
||||
return 0;
|
||||
|
||||
//if (miniSocRefCount != 0) __builtin_trap();
|
||||
Result ret = 0;
|
||||
u32 tmp;
|
||||
|
||||
svcCloseHandle(socMemhandle);
|
||||
socMemhandle = 0;
|
||||
svcCloseHandle(miniSocMemHandle);
|
||||
miniSocMemHandle = 0;
|
||||
|
||||
ret = SOCU_Shutdown();
|
||||
|
||||
svcCloseHandle(SOCU_handle);
|
||||
SOCU_handle = 0;
|
||||
svcCloseHandle(miniSocHandle);
|
||||
miniSocHandle = 0;
|
||||
|
||||
svcControlMemory(&tmp, socContextAddr, socContextAddr, socContextSize, MEMOP_FREE, MEMPERM_DONTCARE);
|
||||
if(ret == 0)
|
||||
@@ -138,6 +137,14 @@ Result miniSocExit(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
Result miniSocExit(void)
|
||||
{
|
||||
if(!miniSocEnabled || AtomicDecrement(&miniSocRefCount))
|
||||
return 0;
|
||||
|
||||
return miniSocExitDirect();
|
||||
}
|
||||
|
||||
int socSocket(int domain, int type, int protocol)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -163,11 +170,11 @@ int socSocket(int domain, int type, int protocol)
|
||||
cmdbuf[3] = protocol;
|
||||
cmdbuf[4] = IPC_Desc_CurProcessId();
|
||||
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
if(ret != 0)
|
||||
{
|
||||
//errno = SYNC_ERROR;
|
||||
return ret;
|
||||
return R_FAILED(ret) ? ret : -1;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
@@ -213,7 +220,7 @@ int socBind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
|
||||
cmdbuf[6] = (u32)tmpaddr;
|
||||
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
if(ret != 0) {
|
||||
//errno = SYNC_ERROR;
|
||||
return ret;
|
||||
@@ -241,7 +248,7 @@ int socListen(int sockfd, int max_connections)
|
||||
cmdbuf[2] = (u32)max_connections;
|
||||
cmdbuf[3] = IPC_Desc_CurProcessId();
|
||||
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
if(ret != 0)
|
||||
{
|
||||
//errno = SYNC_ERROR;
|
||||
@@ -283,7 +290,7 @@ int socAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
|
||||
staticbufs[1] = (u32)tmpaddr;
|
||||
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
|
||||
staticbufs[0] = saved_threadstorage[0];
|
||||
staticbufs[1] = saved_threadstorage[1];
|
||||
@@ -340,7 +347,7 @@ int socConnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
|
||||
cmdbuf[6] = (u32)tmpaddr;
|
||||
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
if(ret != 0) return -1;
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
@@ -383,13 +390,13 @@ int socPoll(struct pollfd *fds, nfds_t nfds, int timeout)
|
||||
staticbufs[0] = IPC_Desc_StaticBuffer(size,0);
|
||||
staticbufs[1] = (u32)fds;
|
||||
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
|
||||
staticbufs[0] = saved_threadstorage[0];
|
||||
staticbufs[1] = saved_threadstorage[1];
|
||||
|
||||
if(ret != 0) {
|
||||
return ret;
|
||||
return R_FAILED(ret) ? ret : -1;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
@@ -408,7 +415,7 @@ int socClose(int sockfd)
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = IPC_Desc_CurProcessId();
|
||||
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
if(ret != 0) {
|
||||
//errno = SYNC_ERROR;
|
||||
return ret;
|
||||
@@ -440,7 +447,7 @@ int socSetsockopt(int sockfd, int level, int optname, const void *optval, sockle
|
||||
cmdbuf[7] = IPC_Desc_StaticBuffer(optlen,9);
|
||||
cmdbuf[8] = (u32)optval;
|
||||
|
||||
ret = svcSendSyncRequest(SOCU_handle);
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
if(ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -457,12 +464,262 @@ int socSetsockopt(int sockfd, int level, int optname, const void *optval, sockle
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t soc_recv(int sockfd, void *buf, size_t len, int flags)
|
||||
long socGethostid(void)
|
||||
{
|
||||
return soc_recvfrom(sockfd, buf, len, flags, NULL, 0);
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x16,0,0); // 0x160000
|
||||
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
if(ret != 0) {
|
||||
//errno = SYNC_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret == 0)
|
||||
ret = cmdbuf[2];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t soc_send(int sockfd, const void *buf, size_t len, int flags)
|
||||
static ssize_t _socuipc_cmd7(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
|
||||
{
|
||||
return soc_sendto(sockfd, buf, len, flags, NULL, 0);
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 tmp_addrlen = 0;
|
||||
u8 tmpaddr[0x1c];
|
||||
u32 saved_threadstorage[2];
|
||||
|
||||
memset(tmpaddr, 0, 0x1c);
|
||||
|
||||
if(src_addr)
|
||||
tmp_addrlen = 0x1c;
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x7,4,4); // 0x70104
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = (u32)len;
|
||||
cmdbuf[3] = (u32)flags;
|
||||
cmdbuf[4] = (u32)tmp_addrlen;
|
||||
cmdbuf[5] = IPC_Desc_CurProcessId();
|
||||
cmdbuf[7] = IPC_Desc_Buffer(len,IPC_BUFFER_W);
|
||||
cmdbuf[8] = (u32)buf;
|
||||
|
||||
u32 * staticbufs = getThreadStaticBuffers();
|
||||
saved_threadstorage[0] = staticbufs[0];
|
||||
saved_threadstorage[1] = staticbufs[1];
|
||||
|
||||
staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
|
||||
staticbufs[1] = (u32)tmpaddr;
|
||||
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
|
||||
staticbufs[0] = saved_threadstorage[0];
|
||||
staticbufs[1] = saved_threadstorage[1];
|
||||
|
||||
if(ret != 0) {
|
||||
//errno = SYNC_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
//errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(src_addr != NULL) {
|
||||
src_addr->sa_family = tmpaddr[1];
|
||||
if(*addrlen > tmpaddr[0])
|
||||
*addrlen = tmpaddr[0];
|
||||
memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t _socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 tmp_addrlen = 0;
|
||||
u8 tmpaddr[0x1c];
|
||||
u32 saved_threadstorage[4];
|
||||
|
||||
if(src_addr)
|
||||
tmp_addrlen = 0x1c;
|
||||
|
||||
memset(tmpaddr, 0, 0x1c);
|
||||
|
||||
cmdbuf[0] = 0x00080102;
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = (u32)len;
|
||||
cmdbuf[3] = (u32)flags;
|
||||
cmdbuf[4] = (u32)tmp_addrlen;
|
||||
cmdbuf[5] = 0x20;
|
||||
|
||||
saved_threadstorage[0] = cmdbuf[0x100>>2];
|
||||
saved_threadstorage[1] = cmdbuf[0x104>>2];
|
||||
saved_threadstorage[2] = cmdbuf[0x108>>2];
|
||||
saved_threadstorage[3] = cmdbuf[0x10c>>2];
|
||||
|
||||
cmdbuf[0x100>>2] = (((u32)len)<<14) | 2;
|
||||
cmdbuf[0x104>>2] = (u32)buf;
|
||||
cmdbuf[0x108>>2] = (tmp_addrlen<<14) | 2;
|
||||
cmdbuf[0x10c>>2] = (u32)tmpaddr;
|
||||
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
if(ret != 0) {
|
||||
//errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmdbuf[0x100>>2] = saved_threadstorage[0];
|
||||
cmdbuf[0x104>>2] = saved_threadstorage[1];
|
||||
cmdbuf[0x108>>2] = saved_threadstorage[2];
|
||||
cmdbuf[0x10c>>2] = saved_threadstorage[3];
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
//errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(src_addr != NULL) {
|
||||
src_addr->sa_family = tmpaddr[1];
|
||||
if(*addrlen > tmpaddr[0])
|
||||
*addrlen = tmpaddr[0];
|
||||
memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t _socuipc_cmd9(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 tmp_addrlen = 0;
|
||||
u8 tmpaddr[0x1c];
|
||||
|
||||
memset(tmpaddr, 0, 0x1c);
|
||||
|
||||
if(dest_addr) {
|
||||
if(dest_addr->sa_family == AF_INET)
|
||||
tmp_addrlen = 8;
|
||||
else
|
||||
tmp_addrlen = 0x1c;
|
||||
|
||||
if(addrlen < tmp_addrlen) {
|
||||
//errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmpaddr[0] = tmp_addrlen;
|
||||
tmpaddr[1] = dest_addr->sa_family;
|
||||
memcpy(&tmpaddr[2], &dest_addr->sa_data, tmp_addrlen-2);
|
||||
}
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x9,4,6); // 0x90106
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = (u32)len;
|
||||
cmdbuf[3] = (u32)flags;
|
||||
cmdbuf[4] = (u32)tmp_addrlen;
|
||||
cmdbuf[5] = IPC_Desc_CurProcessId();
|
||||
cmdbuf[7] = IPC_Desc_StaticBuffer(tmp_addrlen,1);
|
||||
cmdbuf[8] = (u32)tmpaddr;
|
||||
cmdbuf[9] = IPC_Desc_Buffer(len,IPC_BUFFER_R);
|
||||
cmdbuf[10] = (u32)buf;
|
||||
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
if(ret != 0) {
|
||||
//errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
//errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t _socuipc_cmda(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 tmp_addrlen = 0;
|
||||
u8 tmpaddr[0x1c];
|
||||
|
||||
memset(tmpaddr, 0, 0x1c);
|
||||
|
||||
if(dest_addr) {
|
||||
if(dest_addr->sa_family == AF_INET)
|
||||
tmp_addrlen = 8;
|
||||
else
|
||||
tmp_addrlen = 0x1c;
|
||||
|
||||
if(addrlen < tmp_addrlen) {
|
||||
//errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmpaddr[0] = tmp_addrlen;
|
||||
tmpaddr[1] = dest_addr->sa_family;
|
||||
memcpy(&tmpaddr[2], &dest_addr->sa_data, tmp_addrlen-2);
|
||||
}
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0xA,4,6); // 0xA0106
|
||||
cmdbuf[1] = (u32)sockfd;
|
||||
cmdbuf[2] = (u32)len;
|
||||
cmdbuf[3] = (u32)flags;
|
||||
cmdbuf[4] = (u32)tmp_addrlen;
|
||||
cmdbuf[5] = IPC_Desc_CurProcessId();
|
||||
cmdbuf[7] = IPC_Desc_StaticBuffer(len,2);
|
||||
cmdbuf[8] = (u32)buf;
|
||||
cmdbuf[9] = IPC_Desc_StaticBuffer(tmp_addrlen,1);
|
||||
cmdbuf[10] = (u32)tmpaddr;
|
||||
|
||||
ret = svcSendSyncRequest(miniSocHandle);
|
||||
if(ret != 0) {
|
||||
//errno = SYNC_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = (int)cmdbuf[1];
|
||||
if(ret == 0)
|
||||
ret = _net_convert_error(cmdbuf[2]);
|
||||
|
||||
if(ret < 0) {
|
||||
//errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t socRecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
|
||||
{
|
||||
if(len < 0x2000)
|
||||
return _socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen);
|
||||
return _socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen);
|
||||
}
|
||||
|
||||
ssize_t socSendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
|
||||
{
|
||||
if(len < 0x2000)
|
||||
return _socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen);
|
||||
return _socuipc_cmd9(sockfd, buf, len, flags, dest_addr, addrlen);
|
||||
}
|
||||
|
||||
@@ -104,6 +104,11 @@ Result ntpGetTimeStamp(time_t *outTimestamp)
|
||||
return res;
|
||||
|
||||
int sock = socSocket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < -10000) {
|
||||
// Socket services broken
|
||||
return sock;
|
||||
}
|
||||
|
||||
struct sockaddr_in servAddr = {0}; // Server address data structure.
|
||||
NtpPacket packet = {0};
|
||||
|
||||
@@ -125,10 +130,10 @@ Result ntpGetTimeStamp(time_t *outTimestamp)
|
||||
if(socConnect(sock, (struct sockaddr *)&servAddr, sizeof(struct sockaddr_in)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if(soc_send(sock, &packet, sizeof(NtpPacket), 0) < 0)
|
||||
if(socSend(sock, &packet, sizeof(NtpPacket), 0) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if(soc_recv(sock, &packet, sizeof(NtpPacket), 0) < 0)
|
||||
if(socRecv(sock, &packet, sizeof(NtpPacket), 0) < 0)
|
||||
goto cleanup;
|
||||
|
||||
res = 0;
|
||||
@@ -167,11 +172,8 @@ Result ntpSetTimeDate(const struct tm *localt)
|
||||
if (R_FAILED(res)) goto cleanup;
|
||||
|
||||
// First, set the config RTC offset to 0
|
||||
u8 rtcOff = 0;
|
||||
u8 rtcOff2[8] = {0};
|
||||
res = CFG_SetConfigInfoBlk4(1, 0x10000, &rtcOff);
|
||||
if (R_FAILED(res)) goto cleanup;
|
||||
res = CFG_SetConfigInfoBlk4(8, 0x30001, rtcOff2);
|
||||
u8 rtcOff[8] = {0};
|
||||
res = CFG_SetConfigInfoBlk4(8, 0x30001, rtcOff);
|
||||
if (R_FAILED(res)) goto cleanup;
|
||||
|
||||
u8 yr = (u8)(localt->tm_year - 100);
|
||||
|
||||
@@ -101,29 +101,36 @@ Result server_init(struct sock_server *serv)
|
||||
return svcCreateEvent(&serv->shall_terminate_event, RESET_STICKY);
|
||||
}
|
||||
|
||||
void server_bind(struct sock_server *serv, u16 port)
|
||||
Result server_bind(struct sock_server *serv, u16 port)
|
||||
{
|
||||
int server_sockfd;
|
||||
Handle handles[2] = { terminationRequestEvent, serv->shall_terminate_event };
|
||||
s32 idx = -1;
|
||||
server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0);
|
||||
int res;
|
||||
|
||||
while(server_sockfd == -1)
|
||||
int res;
|
||||
u32 tries = 15;
|
||||
while(server_sockfd == -1 && --tries > 0)
|
||||
{
|
||||
if(svcWaitSynchronizationN(&idx, handles, 2, false, 100 * 1000 * 1000LL) == 0)
|
||||
return;
|
||||
return -1;
|
||||
|
||||
server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0);
|
||||
}
|
||||
|
||||
if (server_sockfd < -10000 || tries == 0) {
|
||||
// Socket services broken
|
||||
serv->init_result = -1;
|
||||
svcSignalEvent(serv->shall_terminate_event);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in saddr;
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(port);
|
||||
saddr.sin_addr.s_addr = gethostid();
|
||||
saddr.sin_addr.s_addr = socGethostid();
|
||||
|
||||
res = socBind(server_sockfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));
|
||||
|
||||
if(res == 0)
|
||||
{
|
||||
res = socListen(server_sockfd, 2);
|
||||
@@ -143,6 +150,15 @@ void server_bind(struct sock_server *serv, u16 port)
|
||||
serv->ctx_ptrs[idx] = new_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
if (res != 0) {
|
||||
// Socket services broken
|
||||
serv->init_result = res;
|
||||
svcSignalEvent(serv->shall_terminate_event);
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool server_should_exit(struct sock_server *serv)
|
||||
@@ -171,7 +187,7 @@ void server_run(struct sock_server *serv)
|
||||
fds[i].revents = 0;
|
||||
int pollres = socPoll(fds, serv->nfds, 50);
|
||||
|
||||
if(server_should_exit(serv))
|
||||
if(server_should_exit(serv) || pollres < -10000)
|
||||
goto abort_connections;
|
||||
|
||||
for(nfds_t i = 0; pollres > 0 && i < serv->nfds; i++)
|
||||
@@ -256,6 +272,7 @@ abort_connections:
|
||||
server_kill_connections(serv);
|
||||
serv->running = false;
|
||||
svcClearEvent(serv->started_event);
|
||||
svcSignalEvent(serv->shall_terminate_event);
|
||||
}
|
||||
|
||||
void server_set_should_close_all(struct sock_server *serv)
|
||||
@@ -284,7 +301,8 @@ void server_kill_connections(struct sock_server *serv)
|
||||
socClose(fds[i].fd);
|
||||
fds[i].fd = -1;
|
||||
|
||||
serv->ctx_ptrs[i]->should_close = true;
|
||||
if(serv->ctx_ptrs[i] != NULL)
|
||||
serv->ctx_ptrs[i]->should_close = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,15 @@ TaskRunner g_taskRunner;
|
||||
static MyThread taskRunnerThread;
|
||||
static u8 ALIGN(8) taskRunnerThreadStack[0x1000];
|
||||
|
||||
static void taskRunnerNoOpFunction(void *args)
|
||||
{
|
||||
(void)args;
|
||||
}
|
||||
|
||||
MyThread *taskRunnerCreateThread(void)
|
||||
{
|
||||
TaskRunner_Init();
|
||||
MyThread_Create(&taskRunnerThread, TaskRunner_HandleTasks, taskRunnerThreadStack, THREAD_STACK_SIZE, 0x20, 1);
|
||||
MyThread_Create(&taskRunnerThread, TaskRunner_HandleTasks, taskRunnerThreadStack, THREAD_STACK_SIZE, 58, 1);
|
||||
return &taskRunnerThread;
|
||||
}
|
||||
|
||||
@@ -30,9 +35,15 @@ void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsi
|
||||
LightEvent_Signal(&g_taskRunner.parametersSetEvent);
|
||||
}
|
||||
|
||||
void TaskRunner_Terminate(void)
|
||||
{
|
||||
g_taskRunner.shouldTerminate = true;
|
||||
TaskRunner_RunTask(taskRunnerNoOpFunction, NULL, 0);
|
||||
}
|
||||
|
||||
void TaskRunner_HandleTasks(void)
|
||||
{
|
||||
for (;;) {
|
||||
while (!g_taskRunner.shouldTerminate) {
|
||||
LightEvent_Signal(&g_taskRunner.readyEvent);
|
||||
LightEvent_Wait(&g_taskRunner.parametersSetEvent);
|
||||
g_taskRunner.task(g_taskRunner.argStorage);
|
||||
|
||||
@@ -37,7 +37,7 @@ CFLAGS += $(INCLUDE)
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit
|
||||
|
||||
LIBS := -lctru
|
||||
|
||||
|
||||
@@ -24,10 +24,27 @@ static ProcessData processDataPool[64];
|
||||
|
||||
static u8 ALIGN(4) serviceAccessListStaticBuffer[0x110];
|
||||
|
||||
void __appInit(void)
|
||||
{
|
||||
s64 out;
|
||||
void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error
|
||||
|
||||
// this is called after main exits
|
||||
void __wrap_exit(int rc)
|
||||
{
|
||||
(void)rc;
|
||||
// Not supposed to terminate... kernel will clean up the handles if it does happen anyway
|
||||
svcExitProcess();
|
||||
}
|
||||
|
||||
void __sync_init();
|
||||
// void __libc_init_array(void);
|
||||
|
||||
// Called before main
|
||||
void initSystem(void)
|
||||
{
|
||||
__sync_init();
|
||||
|
||||
//__libc_init_array();
|
||||
|
||||
s64 out;
|
||||
u32 *staticBuffers = getThreadStaticBuffers();
|
||||
staticBuffers[0] = IPC_Desc_StaticBuffer(0x110, 0);
|
||||
staticBuffers[1] = (u32)serviceAccessListStaticBuffer;
|
||||
@@ -40,28 +57,6 @@ void __appInit(void)
|
||||
buildList(&freeProcessDataList, processDataPool, sizeof(processDataPool) / sizeof(ProcessData), sizeof(ProcessData));
|
||||
}
|
||||
|
||||
|
||||
// this is called after main exits
|
||||
void __appExit(void){}
|
||||
|
||||
void __system_allocateHeaps(void){}
|
||||
|
||||
void __system_initSyscalls(void){}
|
||||
|
||||
Result __sync_init(void);
|
||||
Result __sync_fini(void);
|
||||
|
||||
void __ctru_exit(void){}
|
||||
|
||||
void initSystem(void)
|
||||
{
|
||||
void __libc_init_array(void);
|
||||
__sync_init();
|
||||
__system_allocateHeaps();
|
||||
__appInit();
|
||||
__libc_init_array();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Result res;
|
||||
|
||||
Reference in New Issue
Block a user