Compare commits

..

No commits in common. "master" and "v13.3.2" have entirely different histories.

27 changed files with 3197 additions and 544 deletions

View File

@ -195,28 +195,6 @@ static void deinitScreens(void)
*(vu32 *)0x10202014 = 0;
}
static void zerofillN3dsAblRegisters(void)
{
// It should be fine to write to these regs even on O3DS as they
// are RAZ/WI
// TODO: read from calibration, but null values should do just
// fine. From testing, LUT explicitly ignores null values, and
// it is probably the case of reg @ 0x54 as well.
*(vu32 *)0x10202250 = 0; // unknown 24-bit value, seen: 0
*(vu32 *)0x10202254 = 0; // unknown 24-bit value, seen: nonzero
*(vu32 *)0x10202A50 = 0; // unknown 24-bit value, seen: 0
*(vu32 *)0x10202A54 = 0; // unknown 24-bit value, seen: nonzero
for (u32 i = 0; i < 64; i++) {
// Blend colors (w/ color multiplication) for each group
// of 4 relative-luminance Rs
*(vu32 *)(0x10202300 + 4*i) = 0;
*(vu32 *)(0x10202B00 + 4*i) = 0;
}
}
void main(void)
{
operation = ARM11_READY;
@ -245,9 +223,6 @@ void main(void)
case DEINIT_SCREENS:
deinitScreens();
break;
case ZEROFILL_N3DS_ABL_REGISTERS:
zerofillN3dsAblRegisters();
break;
case PREPARE_ARM11_FOR_FIRMLAUNCH:
memcpy((void *)0x1FFFFC00, (void *)prepareForFirmlaunch, prepareForFirmlaunchSize);
*(vu32 *)0x1FFFFFFC = 0;

View File

@ -60,7 +60,6 @@ typedef enum
SWAP_FRAMEBUFFERS,
UPDATE_BRIGHTNESS,
DEINIT_SCREENS,
ZEROFILL_N3DS_ABL_REGISTERS,
PREPARE_ARM11_FOR_FIRMLAUNCH,
ARM11_READY,
} Arm11Operation;

View File

@ -694,7 +694,7 @@ static size_t saveLumaIniConfigToStr(char *out)
return n < 0 ? 0 : (size_t)n;
}
static char tmpIniBuffer[0x2000 + 0x400]; // eyeballed. TODO use #embed
static char tmpIniBuffer[0x2000];
static bool readLumaIniConfig(void)
{
@ -709,13 +709,6 @@ static bool readLumaIniConfig(void)
static bool writeLumaIniConfig(void)
{
size_t n = saveLumaIniConfigToStr(tmpIniBuffer);
// FIXME: this is UB we should port snprintf sometime (as well as fix other tech debt)
if (n + 1 >= sizeof(tmpIniBuffer)) {
error("Configuration data buffer overflow, please report this issue");
__builtin_unreachable();
}
return n != 0 && fileWrite(tmpIniBuffer, "config.ini", n);
}

View File

@ -30,7 +30,6 @@
#include "config.h"
#include "fs.h"
#include "i2c.h"
#include "screen.h"
u8 *loadDeliverArg(void)
{
@ -72,7 +71,7 @@ u8 *loadDeliverArg(void)
bool hasMagic = memcmp(tlnc, "TLNC", 4) == 0;
u8 crcLen = tlnc[5];
u16 crc = *(u16 *)(tlnc + 6);
if (!hasMagic || (8 + crcLen) > 0x100 || crc != crc16(tlnc + 8, crcLen, 0xFFFF))
if (!hasMagic || crcLen <= 248 || crc != crc16(tlnc + 8, crcLen, 0xFFFF))
memset(tlnc, 0, 0x100);
memset(deliverArg + 0x400, 0, 0xC00);
@ -142,8 +141,6 @@ static bool configureHomebrewAutobootCtr(u8 *deliverArg)
return false;
u8 memtype = configData.autobootCtrAppmemtype;
// autobootCtrAppmemtype already checked, but it doesn't hurt to check again
memtype = memtype >= 5 ? 0 : memtype;
deliverArg[0x400] = ISN3DS ? appmemtypesN3ds[memtype] : appmemtypesO3ds[memtype];
// Determine whether to load from the SD card or from NAND. We don't support gamecards for this
@ -201,29 +198,6 @@ static bool configureHomebrewAutobootTwl(u8 *deliverArg)
*(u16 *)(tlnc + 6) = crc16(tlnc + 8, 0x18, 0xFFFF);
// Even though (when running TWL/AGB FIRM) the SoC is in O3DS mode, and the GPU also is,
// as well as most other components behaving as such (external RAM, L2C not usable, etc.),
// this is NOT the case for the LCD and adaptive backlight logic which retains FULL N3DS
// functionality, including a feature where the window is blended with a given color depending
// on the overall relative luminance of that window.
// However, Nintendo's own code mistakenly assumes the opposite, and clearly so ("if GPU in N3DS mode"
// checks, not passing N3DS extra adaptive backlight (ABL) to TWL/AGB_FIRM). This has implications:
// - Powersaving (ABL) settings in TWL/AGB_FIRM is inconsistent with *both* O3DS (because the new RGB blend LUT
// has been set to its current value by NATIVE_FIRM) and N3DS (because "pwn_cnt" and "inertia" are missing
// their N3DS-only bits)
// - "rave party" when booting into TWL/AGB_FIRM or O3DS NATIVE_FIRM without these regs (well, the LUT) initialized.
// Easiest way to do so is by leveraging the "DSi autooboot" feature Luma provides. It is worth noting at least
// the LUT survives hardware reboots (if Nintendo were using DSi software that was using TLNC-based reboots,
// they wouldn't have noticed).
// As such, zerofill these registers (from testing, hardware explicitly discards null values, so this
// should be fine). For now, only touch the Luma-initiated autoboot path
if (ISN3DS)
zerofillN3dsAblRegisters();
CFG_BOOTENV = 3;
return true;

View File

@ -40,8 +40,6 @@ typedef enum
I2C_DEV_CAMERA = 1, // Unconfirmed
I2C_DEV_CAMERA2 = 2, // Unconfirmed
I2C_DEV_MCU = 3,
I2C_DEV_LCD_TOP = 5,
I2C_DEV_LCD_BOT = 6,
I2C_DEV_GYRO = 10,
I2C_DEV_DEBUG_PAD = 12,
I2C_DEV_IR = 13,

View File

@ -843,24 +843,6 @@ u32 patchLgyK11(u8 *section1, u32 section1Size, u8 *section2, u32 section2Size)
return 1;
*off2 = 0xE01A;
// Patch kernelpanic to skip devunit check, so that it sets the LCD fill regs
// which are useful to detect such panics
u16 *off3;
for (off3 = (u16 *)section1; (u8 *)off3 <= section1 + section1Size && (off3[0] != 0x481D || off3[1] != 0xB570); off3++);
if ((u8 *)off3 >= section1 + section1Size)
return 1;
off3[2] = 0x2001; // movs r0, #1
// Patch kernel to avoid allocating the two "configuration memory" pages, freeing
// 0x2000 bytes of kernel "heap" (which is 0xD000 AXIWRAM bytes on LGY K11 instead
// of the entire FCRAM on NFIRM). This is indeed a bug because if prevents two of the
// 12 KThread objects from being created
u16 *off4;
for (off4 = (u16 *)section1; (u8 *)off4 <= section1 + section1Size && (off4[0] != 0xB570 || off4[1] != 0x2200); off4++);
if ((u8 *)off4 >= section1 + section1Size)
return 1;
*off4 = 0x4770; // bx lr
return 0;
}

View File

@ -70,14 +70,6 @@ void prepareArm11ForFirmlaunch(void)
void deinitScreens(void)
{
if(ARESCREENSINITIALIZED) invokeArm11Function(DEINIT_SCREENS);
// Backlight voltage off
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x14);
wait(50);
// LCD panel voltage off
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x01);
wait(50);
}
void updateBrightness(u32 brightnessIndex)
@ -110,31 +102,8 @@ void initScreens(void)
memcpy((void *)(ARM11_PARAMETERS_ADDRESS + 4), fbs, sizeof(fbs));
invokeArm11Function(INIT_SCREENS);
// Fragile code, needs proper fix/total rewrite of the baremetal components anyway
// Assume controller revision is not 0x00 for either screen (this revision is extremely
// old and shouldn't be seen in retail units nor normal devunits)
// Controller reset off
I2C_writeReg(I2C_DEV_LCD_TOP, 0xFE, 0xAA);
I2C_writeReg(I2C_DEV_LCD_BOT, 0xFE, 0xAA);
wait(5);
// Controller power on
I2C_writeReg(I2C_DEV_LCD_TOP, 0x01, 0x10);
I2C_writeReg(I2C_DEV_LCD_BOT, 0x01, 0x10);
wait(5);
// Clear error flag
I2C_writeReg(I2C_DEV_LCD_TOP, 0x60, 0x00);
I2C_writeReg(I2C_DEV_LCD_BOT, 0x60, 0x00);
wait(5);
// LCD panel (bias ?) voltage on
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x02);
wait(50);
// Backlight voltage on
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x28);
//Turn on backlight
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x2A);
wait(5);
}
else updateBrightness(MULTICONFIG(BRIGHTNESS));
@ -149,8 +118,3 @@ void initScreens(void)
clearScreens(false);
swapFramebuffers(false);
}
void zerofillN3dsAblRegisters(void)
{
invokeArm11Function(ZEROFILL_N3DS_ABL_REGISTERS);
}

View File

@ -59,7 +59,6 @@ typedef enum
SWAP_FRAMEBUFFERS,
UPDATE_BRIGHTNESS,
DEINIT_SCREENS,
ZEROFILL_N3DS_ABL_REGISTERS,
PREPARE_ARM11_FOR_FIRMLAUNCH,
ARM11_READY,
} Arm11Operation;
@ -74,4 +73,3 @@ void swapFramebuffers(bool isAlternate);
void updateBrightness(u32 brightnessIndex);
void clearScreens(bool isAlternate);
void initScreens(void);
void zerofillN3dsAblRegisters(void);

View File

@ -158,44 +158,23 @@ void error(const char *fmt, ...)
mcuPowerOff();
}
// CRC-16/MODBUS
u16 crc16(const void *data, size_t size, u16 initialValue)
{
static const u16 lut[256] = {
0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,
0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,
0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,
0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,
0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,
0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,
0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,
0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,
0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,
0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,
0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,
0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,
0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,
0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,
0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,
0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,
0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,
0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,
0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,
0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,
0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,
0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,
0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,
0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,
0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,
0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,
0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,
0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,
0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,
0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,
0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,
0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040,
};
static u16 lut[256] = {0};
static bool lutInitialized = false;
if (!lutInitialized)
{
static const u16 poly = 0xA001;
for (u32 i = 0; i < 256; i++)
{
u16 r = i;
for (u32 j = 0; j < 8; j++)
r = (r >> 1) ^ ((r & 1) != 0 ? poly : 0);
lut[i] = r;
}
lutInitialized = true;
}
u16 r = initialValue;
const u8 *data8 = (const u8 *)data;
@ -207,40 +186,21 @@ u16 crc16(const void *data, size_t size, u16 initialValue)
u32 crc32(const void *data, size_t size, u32 initialValue)
{
static const u32 lut[256] = {
0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,
0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,
0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,
0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,
0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,
0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,
0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,
0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,
0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,
0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,
0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,
0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,
0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,
0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,
0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,
0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,
0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,
0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,
0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,
0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,
0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,
0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,
0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,
0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D,
};
static u32 lut[256] = {0};
static bool lutInitialized = false;
if (!lutInitialized)
{
static const u32 poly = 0xEDB88320;
for (u32 i = 0; i < 256; i++)
{
u32 r = i;
for (u32 j = 0; j < 8; j++)
r = (r >> 1) ^ ((r & 1) != 0 ? poly : 0);
lut[i] = r;
}
lutInitialized = true;
}
u32 r = initialValue;
const u8 *data8 = (const u8 *)data;

View File

@ -34,12 +34,6 @@
extern bool isN3DS;
// Note: just switch to [[attribute]] once we use clangd and cmake
// vscode-cpptools has (or had?) some issues with C23 support
#if __GNUC__ >= 15
// Required by GCC 15+ but ignored (with warning) before
__attribute__((nonstring))
#endif
static const char serviceList[34][8] =
{
"APT:U",

View File

@ -148,7 +148,7 @@ static u32 findFunctionStart(u8 *code, u32 pos)
return 0xFFFFFFFF;
}
static inline bool findLayeredFsSymbols(u8 *code, u32 size, u32 *fsMountArchive, u32 *fsRegisterArchive, u32 *fsTryOpenFile, u32 *fsOpenFileDirectly, u32 *fsUnMountArchive)
static inline bool findLayeredFsSymbols(u8 *code, u32 size, u32 *fsMountArchive, u32 *fsRegisterArchive, u32 *fsTryOpenFile, u32 *fsOpenFileDirectly)
{
u32 found = 0,
*temp = NULL;
@ -165,12 +165,6 @@ static inline bool findLayeredFsSymbols(u8 *code, u32 size, u32 *fsMountArchive,
case 0xE24DD028:
if(addr <= size - 16 && *fsMountArchive == 0xFFFFFFFF && addr32[1] == 0xE1A04000 && addr32[2] == 0xE59F60A8 && addr32[3] == 0xE3A0C001) temp = fsMountArchive;
break;
case 0xE2844001:
if(addr <= size - 12 && *fsUnMountArchive == 0xFFFFFFFF && addr32[1] == 0xE3540020 && addr32[2] == 0x3AFFFFF0) temp = fsUnMountArchive;
break;
case 0xE353003A:
if(addr <= size - 12 && *fsUnMountArchive == 0xFFFFFFFF && (addr32[1] & 0xFFFFFF0F) == 0x0A000009 && (addr32[2] & 0xFFFF0FF0) == 0xE1A00400) temp = fsUnMountArchive;
break;
case 0xE3500008:
if(addr <= size - 12 && *fsRegisterArchive == 0xFFFFFFFF && (addr32[1] & 0xFFF00FF0) == 0xE1800400 && (addr32[2] & 0xFFF00FF0) == 0xE1800FC0) temp = fsRegisterArchive;
break;
@ -189,14 +183,14 @@ static inline bool findLayeredFsSymbols(u8 *code, u32 size, u32 *fsMountArchive,
if(*temp != 0xFFFFFFFF)
{
found++;
if(found == 5) break;
if(found == 4) break;
}
temp = NULL;
}
}
return found == 5;
return found == 4;
}
static inline bool findLayeredFsPayloadOffset(u8 *code, u32 size, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress, u32 *payloadOffset, u32 *pathOffset, u32 *pathAddress)
@ -484,7 +478,7 @@ static inline bool loadTitleLocaleConfig(u64 progId, u8 *mask, u8 *regionId, u8
if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize < 3) goto exit;
if(fileSize >= 12) fileSize = 12;
char buf[12+1] = "------------";
char buf[12] = "------------";
u64 total;
if(R_FAILED(IFile_Read(&file, &total, buf, fileSize))) goto exit;
@ -575,7 +569,6 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize,
if(!archiveId) return true;
u32 fsMountArchive = 0xFFFFFFFF,
fsUnMountArchive = 0xFFFFFFFF,
fsRegisterArchive = 0xFFFFFFFF,
fsTryOpenFile = 0xFFFFFFFF,
fsOpenFileDirectly = 0xFFFFFFFF,
@ -583,7 +576,7 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize,
pathOffset = 0,
pathAddress = 0xDEADCAFE;
if(!findLayeredFsSymbols(code, textSize, &fsMountArchive, &fsRegisterArchive, &fsTryOpenFile, &fsOpenFileDirectly, &fsUnMountArchive) ||
if(!findLayeredFsSymbols(code, textSize, &fsMountArchive, &fsRegisterArchive, &fsTryOpenFile, &fsOpenFileDirectly) ||
!findLayeredFsPayloadOffset(code, textSize, roSize, dataSize, roAddress, dataAddress, &payloadOffset, &pathOffset, &pathAddress)) return false;
static const char *updateRomFsMounts[] = { "ro2:",
@ -631,9 +624,8 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize,
romfsRedirPatchSubstituted2 = *(u32 *)(code + fsTryOpenFile);
romfsRedirPatchHook2 = MAKE_BRANCH(payloadOffset + (u32)&romfsRedirPatchHook2 - (u32)romfsRedirPatch, fsTryOpenFile + 4);
romfsRedirPatchCustomPath = pathAddress;
romfsRedirPatchFsMountArchive = MAKE_BRANCH_LINK(payloadOffset + (u32)&romfsRedirPatchFsMountArchive - (u32)romfsRedirPatch, fsMountArchive);
romfsRedirPatchFsUnMountArchive = MAKE_BRANCH_LINK(payloadOffset + (u32)&romfsRedirPatchFsUnMountArchive - (u32)romfsRedirPatch, fsUnMountArchive);
romfsRedirPatchFsRegisterArchive = MAKE_BRANCH_LINK(payloadOffset + (u32)&romfsRedirPatchFsRegisterArchive - (u32)romfsRedirPatch, fsRegisterArchive);
romfsRedirPatchFsMountArchive = 0x100000 + fsMountArchive;
romfsRedirPatchFsRegisterArchive = 0x100000 + fsRegisterArchive;
romfsRedirPatchArchiveId = archiveId;
memcpy(&romfsRedirPatchUpdateRomFsMount, updateRomFsMount, 4);
@ -734,65 +726,33 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 ro
progId == 0x0004001000022000LL || //EUR MSET
progId == 0x0004001000026000LL || //CHN MSET
progId == 0x0004001000027000LL || //KOR MSET
progId == 0x0004001000028000LL)) //TWN MSET
progId == 0x0004001000028000LL) //TWN MSET
&& CONFIG(PATCHVERSTRING))
{
if (CONFIG(PATCHVERSTRING))
static const u16 pattern[] = u"Ve";
const u16 *patch;
u32 patchSize = 0,
currentNand = BOOTCFG_NAND;
u16 customVerString[19];
loadCustomVerString(customVerString, &patchSize, currentNand);
if(patchSize != 0) patch = customVerString;
else
{
static const u16 pattern[] = u"Ve";
const u16 *patch;
u32 patchSize = 0,
currentNand = BOOTCFG_NAND;
patchSize = 8;
u16 customVerString[19];
loadCustomVerString(customVerString, &patchSize, currentNand);
if(patchSize != 0) patch = customVerString;
else
{
patchSize = 8;
static const u16 *const verStringNandEmu[] = { u" Emu", u"Emu2", u"Emu3", u"Emu4" };
patch = currentNand == 0 ? u" Sys" : verStringNandEmu[BOOTCFG_EMUINDEX];
}
//Patch Ver. string
if(!patchMemory(code, textSize,
pattern,
sizeof(pattern) - 2, 0,
patch,
patchSize, 1
)) goto error;
static const u16 *const verStringNandEmu[] = { u" Emu", u"Emu2", u"Emu3", u"Emu4" };
patch = currentNand == 0 ? u" Sys" : verStringNandEmu[BOOTCFG_EMUINDEX];
}
// Allow date picker to select year up to 2099, not just 2050.
// NNID user's year-of-birth seems to have a similar restriction,
// I'm not removing that as long as any NNID stuff is still active.
// Patch date picker check on entry (date load):
// Look for:
// 32 00 5x E3 CMP Rx, #0x32
// ...
// 32 x0 A0 C3 MOVGT Rx, #0x32
u32 *off = (u32 *)code;
for (; (u8 *)off < code + textSize && ((off[0] & 0xFFF0FFFF) != 0xE3500032 || (off[2] & 0xFFFF0FFF) != 0xC3A00032); off++)
{
if (((off[0] >> 16) & 0xF) != ((off[2] >> 12) & 0xF)) // ensure same register used
continue;
}
if ((u8 *)off >= code + textSize) goto error;
off[0] = (off[0] & ~0xFF) | 99;
off[2] = (off[2] & ~0xFF) | 99;
// Patch date picker actions:
// Look for:
// 01 00 80 E2 ADD R0, R0, #1
// 32 00 50 E3 CMP R0, #0x32
off = (u32 *)code;
for (; (u8 *)off < code + textSize && (off[0] != 0xE2800001 || off[1] != 0xE3500032); off++);
if ((u8 *)off >= code + textSize) goto error;
off[1] = (off[1] & ~0xFF) | 99; // patch increment wrap-around compare instruction
off[9] = (off[9] & ~0xFF) | 99; // patch decrement wrap-around conditional move instruction
//Patch Ver. string
if(!patchMemory(code, textSize,
pattern,
sizeof(pattern) - 2, 0,
patch,
patchSize, 1
)) goto error;
}
else if(progId == 0x0004013000008002LL) //NS

View File

@ -10,7 +10,6 @@ extern u32 romfsRedirPatchSubstituted2, romfsRedirPatchHook2;
extern u32 romfsRedirPatchArchiveName;
extern u32 romfsRedirPatchFsMountArchive;
extern u32 romfsRedirPatchFsUnMountArchive;
extern u32 romfsRedirPatchFsRegisterArchive;
extern u32 romfsRedirPatchArchiveId;
extern u32 romfsRedirPatchRomFsMount;

View File

@ -30,23 +30,17 @@ romfsRedirPatch:
cmp r3, #3
bne romfsRedirPatchSubstituted1
stmfd sp!, {r0-r4, lr}
adr r0, romfsRedirPatchArchiveName
.global romfsRedirPatchFsUnMountArchive
romfsRedirPatchFsUnMountArchive:
.word 0xdead0004
sub sp, sp, #4
ldr r1, romfsRedirPatchArchiveId
mov r0, sp
.global romfsRedirPatchFsMountArchive
romfsRedirPatchFsMountArchive:
.word 0xdead0005
ldr r4, romfsRedirPatchFsMountArchive
blx r4
mov r3, #0
mov r2, #0
ldr r1, [sp]
adr r0, romfsRedirPatchArchiveName
.global romfsRedirPatchFsRegisterArchive
romfsRedirPatchFsRegisterArchive:
.word 0xdead0006
ldr r4, romfsRedirPatchFsRegisterArchive
blx r4
add sp, sp, #4
ldmfd sp!, {r0-r4, lr}
b romfsRedirPatchSubstituted1
@ -114,16 +108,20 @@ romfsRedirPatch:
.balign 4
.global romfsRedirPatchArchiveName
.global romfsRedirPatchFsMountArchive
.global romfsRedirPatchFsRegisterArchive
.global romfsRedirPatchArchiveId
.global romfsRedirPatchRomFsMount
.global romfsRedirPatchUpdateRomFsMount
.global romfsRedirPatchCustomPath
romfsRedirPatchArchiveName : .ascii "lf:\0"
romfsRedirPatchFsMountArchive : .word 0xdead0005
romfsRedirPatchFsRegisterArchive : .word 0xdead0006
romfsRedirPatchArchiveId : .word 0xdead0007
romfsRedirPatchRomFsMount : .ascii "rom:"
romfsRedirPatchUpdateRomFsMount : .word 0xdead0008
romfsRedirPatchCustomPath : .word 0xdead0009
romfsRedirPatchCustomPath : .word 0xdead0004
_romfsRedirPatchEnd:

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,7 @@ typedef struct MenuItem {
typedef struct Menu {
const char *title;
MenuItem items[25];
MenuItem items[24];
} Menu;
extern u32 menuCombo;

View File

@ -36,7 +36,6 @@ void RosalinaMenu_TakeScreenshot(void);
void RosalinaMenu_ShowCredits(void);
void RosalinaMenu_ProcessList(void);
void RosalinaMenu_SaveSettings(void);
void RosalinaMenu_ReturnToHomeMenu(void);
void RosalinaMenu_Cheats(void);
void RosalinaMenu_PowerOffOrReboot(void);

View File

@ -56,12 +56,10 @@ typedef struct
s32* plgldrEvent; ///< Used for synchronization
s32* plgldrReply; ///< Used for synchronization
u8 notifyHomeEvent;
u8 padding[7];
u64 waitForReplyTimeout;
u32 reserved[20];
u8 padding[3];
u32 reserved[23];
u32 config[32];
} PluginHeader;
_Static_assert(sizeof(PluginHeader) == 0x100, "Invalid PluginHeader size");
} PluginHeader;
typedef void (*OnPlgLdrEventCb_t)(s32 eventType);

View File

@ -30,7 +30,6 @@
#include <3ds/srv.h>
#include <3ds/result.h>
#include <3ds/ipc.h>
#include <assert.h>
#include "csvc.h"
#include "luma_shared_config.h"

View File

@ -268,18 +268,14 @@ static inline void Draw_WriteUnaligned(u8 *dst, u32 tmp, u32 size)
void Draw_CreateBitmapHeader(u8 *dst, u32 width, u32 heigth)
{
static const u8 bmpHeaderTemplate[54] = {
// BITMAPFILEHEADER
0x42, 0x4D, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x40 /* data offset */, 0x00, 0x00, 0x00,
// BITMAPINFOHEADER
0x28, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x01, 0x00, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x12, 0x0B, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x00, 0x00,
0x42, 0x4D, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x12, 0x0B, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
memcpy(dst, bmpHeaderTemplate, 54);
memset(dst + 54, 0, 64 - 54);
Draw_WriteUnaligned(dst + 2, 64 + 3 * width * heigth, 4);
Draw_WriteUnaligned(dst + 2, 54 + 3 * width * heigth, 4);
Draw_WriteUnaligned(dst + 0x12, width, 4);
Draw_WriteUnaligned(dst + 0x16, heigth, 4);
Draw_WriteUnaligned(dst + 0x22, 3 * width * heigth, 4);

View File

@ -204,7 +204,7 @@ void LumaConfig_RequestSaveSettings(void) {
Result LumaConfig_SaveSettings(void)
{
char inibuf[0x2000 + 0x400]; // eyeballed. TODO use #embed
char inibuf[0x2000];
Result res;
@ -259,12 +259,6 @@ Result LumaConfig_SaveSettings(void)
configData.autobootCtrAppmemtype = autobootCtrAppmemtype;
size_t n = LumaConfig_SaveLumaIniConfigToStr(inibuf, &configData);
// FIXME: this is UB we should port snprintf sometime (as well as fix other tech debt in Rosalina)
if (n + 1 >= sizeof(inibuf)) {
__builtin_trap();
}
FS_ArchiveID archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW;
if (n > 0)
res = IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, "/luma/config.ini"), FS_OPEN_CREATE | FS_OPEN_WRITE);

View File

@ -104,13 +104,8 @@ u32 getMinLuminancePreset(void)
u32 getMaxLuminancePreset(void)
{
// Unlike SetLuminanceLevel, SetLuminance doesn't
// check if preset <= 5, and actually allows the lumiance
// levels provisioned for the "brightness boost mode" (brighter
// when adapter is plugged in), even when the feature is disabled
// (it is disabled for anything but the OG model, iirc)
readCalibration();
return s_blPwmData.luminanceLevels[6];
return s_blPwmData.luminanceLevels[s_blPwmData.numLevels - 1];
}
u32 getCurrentLuminance(bool top)
@ -119,8 +114,7 @@ u32 getCurrentLuminance(bool top)
readCalibration();
bool is3d = (REG32(0x10202000 + 0x000) & 1) != 0;
const float *coeffs = s_blPwmData.coeffs[top ? (is3d ? 2 : 1) : 0];
const float *coeffs = s_blPwmData.coeffs[top ? (isN3DS ? 2 : 1) : 0];
u32 brightness = REG32(regbase + 0x40);
float ratio = getPwmRatio(s_blPwmData.brightnessMax, REG32(regbase + 0x44));

View File

@ -55,7 +55,6 @@ Menu rosalinaMenu = {
{ "System configuration...", MENU, .menu = &sysconfigMenu },
{ "Miscellaneous options...", MENU, .menu = &miscellaneousMenu },
{ "Save settings", METHOD, .method = &RosalinaMenu_SaveSettings },
{ "Return To Home Menu", METHOD, .method = &RosalinaMenu_ReturnToHomeMenu },
{ "Power off / reboot", METHOD, .method = &RosalinaMenu_PowerOffOrReboot },
{ "System info", METHOD, .method = &RosalinaMenu_ShowSystemInfo },
{ "Credits", METHOD, .method = &RosalinaMenu_ShowCredits },
@ -228,7 +227,7 @@ void RosalinaMenu_ShowCredits(void)
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina -- Luma3DS credits");
u32 posY = Draw_DrawString(10, 30, COLOR_WHITE, "Luma3DS (c) 2016-2025 AuroraWright, TuxSH") + SPACING_Y;
u32 posY = Draw_DrawString(10, 30, COLOR_WHITE, "Luma3DS (c) 2016-2024 AuroraWright, TuxSH") + SPACING_Y;
posY = Draw_DrawString(10, posY + SPACING_Y, COLOR_WHITE, "3DSX loading code by fincs");
posY = Draw_DrawString(10, posY + SPACING_Y, COLOR_WHITE, "Networking code & basic GDB functionality by Stary");
@ -274,8 +273,7 @@ static Result RosalinaMenu_WriteScreenshot(IFile *file, u32 width, bool top, boo
u8 *buf = framebufferCache;
Draw_CreateBitmapHeader(framebufferCache, width, numLinesScaled);
const u32 headerSize = 0x40;
buf += headerSize;
buf += 54;
u32 y = 0;
// Our buffer might be smaller than the size of the screenshot...
@ -289,7 +287,7 @@ static Result RosalinaMenu_WriteScreenshot(IFile *file, u32 width, bool top, boo
s64 t1 = svcGetSystemTick();
timeSpentConvertingScreenshot += t1 - t0;
TRY(IFile_Write(file, &total, framebufferCache, (y == 0 ? headerSize : 0) + lineSize * nlines * scaleFactorY, 0)); // don't forget to write the header
TRY(IFile_Write(file, &total, framebufferCache, (y == 0 ? 54 : 0) + lineSize * nlines * scaleFactorY, 0)); // don't forget to write the header
timeSpentWritingScreenshot += svcGetSystemTick() - t1;
y += nlines;
@ -302,35 +300,6 @@ static Result RosalinaMenu_WriteScreenshot(IFile *file, u32 width, bool top, boo
return res;
}
void RosalinaMenu_ReturnToHomeMenu(void)
{
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
Draw_Unlock();
do
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Return to Home Menu");
Draw_DrawString(10, 30, COLOR_WHITE, "Press A to confirm.\nPress B to go back.");
Draw_FlushFramebuffer();
Draw_Unlock();
u32 pressed = waitInputWithTimeout(1000);
if(pressed & KEY_A)
{
menuLeave();
srvPublishToSubscriber(0x204, 0);
return;
}
else if(pressed & KEY_B)
return;
}
while(!menuShouldExit);
}
void RosalinaMenu_TakeScreenshot(void)
{
IFile file = {0};

View File

@ -367,6 +367,11 @@ void MiscellaneousMenu_UpdateTimeDateNtp(void)
}
}
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
Draw_Unlock();
do
{
Draw_Lock();

View File

@ -420,30 +420,8 @@ static Result SysConfigMenu_ApplyVolumeOverride(void)
s8 i2s2Volume;
if (currVolumeSliderOverride >= 0)
{
// Considering I found this table inside MCU fw bin (at around offset 0x1200 in the raw bin):
// 127, 126, 125, ... 56
// which corresponds to round(127 - 71 * (i/63)) modulo some rounding error, it is certain
// that the MCU writes to "Page 0/Register 117: VOL/MICDET-Pin Gain" using linear interpolation
// to map the slider position (0..63) to the raw gain values, using 127 ("reserved") as "mute".
// Indeed, the value used in all calibration data for shutter volume is -10 dB, which maps to 56.
// However, if you look at the definition of reg 0,117 closely, you will notice that the mapping
// to the 7-bit value is piecewise, with half the resolution (double the slope) for values mapping
// to -28 dB or lower, which means that the slider increases volume twice as fast below 50% position.
// LERP like MCU does, round to nearest integer
u8 rawPinGain = 127 - (71 * currVolumeSliderOverride + 50) / 100;
s8 volume;
if (rawPinGain <= 90)
volume = 36 - rawPinGain;
else if (rawPinGain >= 91 && rawPinGain <= 126)
volume = 126 - 2 * rawPinGain;
else
volume = -128; // mute
i2s1Volume = volume;
i2s2Volume = volume;
i2s1Volume = -128 + (((float)currVolumeSliderOverride/100.f) * 108);
i2s2Volume = i2s1Volume;
}
else
{
@ -582,7 +560,7 @@ void SysConfigMenu_ChangeScreenBrightness(void)
posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press A to start, B to exit.\n\n");
posY = Draw_DrawString(10, posY, COLOR_RED, "WARNING: \n");
posY = Draw_DrawString(10, posY, COLOR_WHITE, " * value will be limited by calibration.\n");
posY = Draw_DrawString(10, posY, COLOR_WHITE, " * value will be limited by the presets.\n");
posY = Draw_DrawString(10, posY, COLOR_WHITE, " * bottom framebuffer will be restored until\nyou exit.");
Draw_FlushFramebuffer();
Draw_Unlock();

View File

@ -270,7 +270,6 @@ bool TryToLoadPlugin(Handle process, bool isHomebrew)
}
pluginHeader->version = header->version;
pluginHeader->waitForReplyTimeout = 10000000000ULL;
// Code size must be page aligned
exeHdr = &header->executable;
pluginHeader->exeSize = (sizeof(PluginHeader) + exeHdr->codeSize + exeHdr->rodataSize + exeHdr->dataSize + exeHdr->bssSize + 0x1000) & ~0xFFF;

View File

@ -113,7 +113,7 @@ Result PLGLDR__SetPluginLoadParameters(PluginLoadParameters *parameters)
}
return res;
}
void Flash(u32 color);
Result PLGLDR__DisplayMenu(PluginMenu *menu)
{
Result res = 0;
@ -136,6 +136,7 @@ Result PLGLDR__DisplayMenu(PluginMenu *menu)
{
res = cmdbuf[1];
}
else Flash(0xFF0000);
return res;
}

View File

@ -20,6 +20,9 @@ static const char *g_title = "Plugin loader";
PluginLoaderContext PluginLoaderCtx;
extern u32 g_blockMenuOpen;
void IR__Patch(void);
void IR__Unpatch(void);
void PluginLoader__Init(void)
{
PluginLoaderContext *ctx = &PluginLoaderCtx;
@ -93,7 +96,7 @@ void PluginLoader__UpdateMenu(void)
static ControlApplicationMemoryModeOverrideConfig g_memorymodeoverridebackup = { 0 };
Result PluginLoader__SetMode3AppMode(bool enable)
{
Handle loaderHandle;
Handle loaderHandle;
Result res = srvGetServiceHandle(&loaderHandle, "Loader");
if (R_FAILED(res)) return res;
@ -102,7 +105,7 @@ Result PluginLoader__SetMode3AppMode(bool enable)
if (enable) {
ControlApplicationMemoryModeOverrideConfig* mode = (ControlApplicationMemoryModeOverrideConfig*)&cmdbuf[1];
memset(mode, 0, sizeof(ControlApplicationMemoryModeOverrideConfig));
mode->query = true;
cmdbuf[0] = IPC_MakeHeader(0x101, 1, 0); // ControlApplicationMemoryModeOverride
@ -127,12 +130,16 @@ Result PluginLoader__SetMode3AppMode(bool enable)
res = cmdbuf[1];
}
}
svcCloseHandle(loaderHandle);
svcCloseHandle(loaderHandle);
return res;
}
static void j_PluginLoader__SetMode3AppMode(void* arg) {(void)arg; PluginLoader__SetMode3AppMode(false);}
void CheckMemory(void);
void PLG__NotifyEvent(PLG_Event event, bool signal);
void PluginLoader__HandleCommands(void *_ctx)
{
(void)_ctx;
@ -169,6 +176,8 @@ void PluginLoader__HandleCommands(void *_ctx)
}
REG32(0x10202204) = 0;
}
//if (!ctx->userLoadParameters.noIRPatch)
// IR__Patch();
PLG__SetConfigMemoryStatus(PLG_CFG_RUNNING);
}
else
@ -231,14 +240,14 @@ void PluginLoader__HandleCommands(void *_ctx)
params->pluginMemoryStrategy = (cmdbuf[1] >> 8) & 0xFF;
params->persistent = (cmdbuf[1] >> 16) & 0x1;
params->lowTitleId = cmdbuf[2];
strncpy(params->path, (const char *)cmdbuf[4], 255);
memcpy(params->config, (void *)cmdbuf[6], 32 * sizeof(u32));
if (params->persistent)
{
IFile file;
if (R_SUCCEEDED(IFile_Open(&file, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, "/luma/plugins/user_param.bin"),
if (R_SUCCEEDED(IFile_Open(&file, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, "/luma/plugins/user_param.bin"),
FS_OPEN_CREATE | FS_OPEN_READ | FS_OPEN_WRITE))) {
u64 tempWritten;
u32 magic = PERS_USER_FILE_MAGIC;
@ -367,9 +376,9 @@ void PluginLoader__HandleCommands(void *_ctx)
error(cmdbuf, 0xD9001830);
break;
}
g_blockMenuOpen = cmdbuf[1];
cmdbuf[0] = IPC_MakeHeader(11, 1, 0);
cmdbuf[1] = 0;
break;
@ -433,7 +442,7 @@ void PluginLoader__HandleCommands(void *_ctx)
Reset_3gx_LoadParams();
break;
}
ctx->isExeLoadFunctionset = true;
svcInvalidateEntireInstructionCache(); // Could use the range one
@ -507,7 +516,7 @@ void PLG__WaitForReply(void)
{
if (PluginLoaderCtx.eventsSelfManaged) return;
__strex__(PluginLoaderCtx.plgReplyPA, PLG_WAIT);
svcArbitrateAddress(PluginLoaderCtx.arbiter, (u32)PluginLoaderCtx.plgReplyPA, ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT, PLG_OK, MemoryBlock__GetMappedPluginHeader()->waitForReplyTimeout);
svcArbitrateAddress(PluginLoaderCtx.arbiter, (u32)PluginLoaderCtx.plgReplyPA, ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT, PLG_OK, 10000000000ULL);
}
void PLG__SetConfigMemoryStatus(u32 status)
@ -532,7 +541,7 @@ static void WaitForProcessTerminated(void *arg)
// Wait until all threads of the process have finished (svcWaitSynchronization == 0) or 2.5 seconds have passed.
for (u32 i = 0; svcWaitSynchronization(ctx->target, 0) != 0 && i < 50; i++) svcSleepThread(50000000); // 50ms
// Unmap plugin's memory before closing the process
if (!ctx->pluginIsSwapped) {
MemoryBlock__UnmountFromProcess();
@ -552,6 +561,8 @@ static void WaitForProcessTerminated(void *arg)
ctx->isMemPrivate = false;
g_blockMenuOpen = 0;
MemoryBlock__ResetSwapSettings();
//if (!ctx->userLoadParameters.noIRPatch)
// IR__Unpatch();
}
void PluginLoader__HandleKernelEvent(u32 notifId)
@ -632,11 +643,12 @@ void PluginLoader__HandleKernelEvent(u32 notifId)
PLG__NotifyEvent(PLG_HOME_ENTER, false);
// Wait for plugin reply
PLG__WaitForReply();
}
}
PLG__SetConfigMemoryStatus(PLG_CFG_INHOME);
}
ctx->pluginIsHome = !ctx->pluginIsHome;
}
}
srvPublishToSubscriber(0x1002, 0);
}