49 lines
1.7 KiB
C
49 lines
1.7 KiB
C
// Startet die App nach einem Update selbst neu.
|
|
//
|
|
// CIA: aptSetChainloaderToSelf() - das System startet beim Beenden denselben Titel
|
|
// (jetzt die neue Version) wieder.
|
|
// 3DSX: Die App läuft im Homebrew-Titel von Luma (Rosalina). Über dessen Dienst "hb:ldr"
|
|
// legen wir fest, welche .3dsx beim nächsten Start geladen wird - genau so macht es
|
|
// auch der Homebrew Launcher. Danach den Homebrew-Titel neu starten lassen.
|
|
#include <3ds.h>
|
|
#include <string.h>
|
|
|
|
#include "relaunch.h"
|
|
|
|
static Result hbldr_call(Handle h, u32 cmd, const void *buf, u32 size, int staticId)
|
|
{
|
|
u32 *cmdbuf = getThreadCommandBuffer();
|
|
cmdbuf[0] = IPC_MakeHeader(cmd, 0, 2);
|
|
cmdbuf[1] = IPC_Desc_StaticBuffer(size, staticId);
|
|
cmdbuf[2] = (u32)buf;
|
|
Result rc = svcSendSyncRequest(h);
|
|
return R_SUCCEEDED(rc) ? (Result)cmdbuf[1] : rc;
|
|
}
|
|
|
|
static bool set_homebrew_target(const char *selfPath)
|
|
{
|
|
Handle h;
|
|
if (R_FAILED(svcConnectToPort(&h, "hb:ldr"))) return false;
|
|
|
|
// hb:ldr erwartet den Pfad ohne "sdmc:"
|
|
const char *path = strncmp(selfPath, "sdmc:/", 6) == 0 ? selfPath + 5 : selfPath;
|
|
Result rc = hbldr_call(h, 2, path, strlen(path) + 1, 0); // SetTarget
|
|
|
|
// argv wie beim Homebrew Launcher: u32 Anzahl, dann die Texte
|
|
static u32 argBuf[0x400 / 4];
|
|
memset(argBuf, 0, sizeof(argBuf));
|
|
argBuf[0] = 1;
|
|
strncpy((char *)&argBuf[1], selfPath, sizeof(argBuf) - 5);
|
|
if (R_SUCCEEDED(rc)) rc = hbldr_call(h, 3, argBuf, sizeof(argBuf), 1); // SetArgv
|
|
|
|
svcCloseHandle(h);
|
|
return R_SUCCEEDED(rc);
|
|
}
|
|
|
|
bool relaunch_prepare(const char *selfPath)
|
|
{
|
|
if (envIsHomebrew() && !set_homebrew_target(selfPath)) return false;
|
|
aptSetChainloaderToSelf();
|
|
return true;
|
|
}
|