Example #1
0
static inline bool patchRomfsRedirection(u64 progId, u8* code, u32 size)
{
    /* Here we look for "/luma/titles/[u64 titleID in hex, uppercase]/romfs"
       If it exists it should be a decrypted raw RomFS */

    char path[] = "/luma/titles/0000000000000000/romfs";
    progIdToStr(path + 28, progId);

    IFile file;
    u32 archive = openLumaFile(&file, path);

    if(!archive) return true;

    bool ret = false;
    u64 romfsSize;

    if(R_FAILED(IFile_GetSize(&file, &romfsSize))) goto exit;

    u64 total;
    u32 magic;

    if(R_FAILED(IFile_Read(&file, &total, &magic, 4)) || total != 4 || magic != 0x43465649) goto exit;

    u32 fsOpenFileDirectly = findFunctionCommand(code, size, 0x08030204),
        throwFatalError = findThrowFatalError(code, size);

    if(fsOpenFileDirectly == 0xFFFFFFFF || throwFatalError == 0xFFFFFFFF) goto exit;

    //Setup the payload
    u8 *payload = code + throwFatalError;
    memcpy(payload, romfsredir_bin, romfsredir_bin_size);
    memcpy(payload + romfsredir_bin_size, path, sizeof(path));
    *(u32 *)(payload + 0xC) = *(u32 *)(code + fsOpenFileDirectly);

    u32 *payloadSymbols = (u32 *)(payload + romfsredir_bin_size - 0x24);
    payloadSymbols[0] = 0x100000 + fsOpenFileDirectly + 4;
    *(u64 *)(payloadSymbols + 2) = 0x1000ULL;
    *(u64 *)(payloadSymbols + 4) = romfsSize - 0x1000ULL;
    payloadSymbols[6] = archive;
    payloadSymbols[7] = sizeof(path);
    payloadSymbols[8] = 0x100000 + throwFatalError + romfsredir_bin_size; //String pointer

    //Place the hooks
    *(u32 *)(code + fsOpenFileDirectly) = MAKE_BRANCH(fsOpenFileDirectly, throwFatalError);

    u32 fsOpenLinkFile = findFunctionCommand(code, size, 0x80C0000);

    if(fsOpenLinkFile != 0xFFFFFFFF)
    {
        *(u32 *)(code + fsOpenLinkFile) = 0xE3A03003; //mov r3, #3
        *(u32 *)(code + fsOpenLinkFile + 4) = MAKE_BRANCH(fsOpenLinkFile + 4, throwFatalError);
    }

    ret = true;

exit:
    IFile_Close(&file);

    return ret;
}
Example #2
0
static int loadTitleCodeSection(u64 progId, u8 *code, u32 size)
{
    /* Here we look for "/luma/code_sections/[u64 titleID in hex, uppercase].bin"
       If it exists it should be a decompressed binary code file */
    
    char path[] = "/luma/code_sections/0000000000000000.bin";
    progIdToStr(path + 35, progId);

    IFile file;
    Result ret = fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ);
    
    if(R_SUCCEEDED(ret))
    {
        u64 fileSize, total;
        
        ret = IFile_GetSize(&file, &fileSize);
        if(!R_SUCCEEDED(ret) || fileSize > size) return -1;
        
        ret = IFile_Read(&file, &total, code, fileSize);
        IFile_Close(&file);
        if(!R_SUCCEEDED(ret)) return -1;
        else if(total < fileSize) return -2; //Shouldn't happen
    }
    
    return ret;
}
Example #3
0
static inline bool loadTitleCodeSection(u64 progId, u8 *code, u32 size)
{
    /* Here we look for "/luma/titles/[u64 titleID in hex, uppercase]/code.bin"
       If it exists it should be a decrypted and decompressed binary code file */

    char path[] = "/luma/titles/0000000000000000/code.bin";
    progIdToStr(path + 28, progId);

    IFile file;

    if(!openLumaFile(&file, path)) return true;

    bool ret;
    u64 fileSize;

    if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize > size) ret = false;
    else
    {
        u64 total;

        ret = R_SUCCEEDED(IFile_Read(&file, &total, code, fileSize)) && total == fileSize;
    }

    IFile_Close(&file);

    return ret;
}
Example #4
0
static void loadCustomVerString(u16 *out, u32 *verStringSize, u32 currentNand)
{
    static const char *paths[] = { "/puma/customversion_sys.txt",
                                   "/puma/customversion_emu.txt",
                                   "/puma/customversion_emu2.txt",
                                   "/puma/customversion_emu3.txt",
                                   "/puma/customversion_emu4.txt" };

    IFile file;

    if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, paths[currentNand], FS_OPEN_READ)))
    {
        u64 fileSize;

        if(R_SUCCEEDED(IFile_GetSize(&file, &fileSize)) && fileSize <= 62)
        {
            u8 buf[fileSize];
            u64 total;

            if(R_SUCCEEDED(IFile_Read(&file, &total, buf, fileSize)))
            {
                static const u8 bom[] = {0xEF, 0xBB, 0xBF};
                u32 finalSize = 0;

                //Convert from UTF-8 to UTF-16 (Nintendo doesn't support 4-byte UTF-16, so 4-byte UTF-8 is unsupported)
                for(u32 increase, fileSizeTmp = (u32)fileSize, i = (fileSizeTmp > 2 && memcmp(buf, bom, 3) == 0) ? 3 : 0;
                    i < fileSizeTmp && finalSize < 19; i += increase, finalSize++)
                {
                    if((buf[i] & 0x80) == 0 && !(buf[i] == 0xA || buf[i] == 0xD))
                    {
                        increase = 1;
                        out[finalSize] = (u16)buf[i];
                    }
                    else if((buf[i] & 0xE0) == 0xC0 && i + 1 < fileSizeTmp && (buf[i + 1] & 0xC0) == 0x80)
                    {
                        increase = 2;
                        out[finalSize] = (u16)(((buf[i] & 0x1F) << 6) | (buf[i + 1] & 0x3F));
                    }
                    else if((buf[i] & 0xF0) == 0xE0 && i + 2 < fileSizeTmp && (buf[i + 1] & 0xC0) == 0x80 && (buf[i + 2] & 0xC0) == 0x80)
                    {
                        increase = 3;
                        out[finalSize] = (u16)(((buf[i] & 0xF) << 12) | ((buf[i + 1] & 0x3F) << 6) | (buf[i + 2] & 0x3F));
                    }
                    else break;
                }

                if(finalSize > 0)
                {
                    if(finalSize > 5 && finalSize < 19) out[finalSize++] = 0;
                    *verStringSize = finalSize * 2;
                }
            }
        }

        IFile_Close(&file);
    }
}
Example #5
0
static inline bool loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
{
    /* Here we look for "/luma/titles/[u64 titleID in hex, uppercase]/locale.txt"
       If it exists it should contain, for example, "EUR IT" */

    char path[] = "/luma/titles/0000000000000000/locale.txt";
    progIdToStr(path + 28, progId);

    IFile file;

    if(!openLumaFile(&file, path)) return true;

    bool ret = false;
    u64 fileSize;

    if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize < 6 || fileSize > 8) goto exit;

    char buf[8];
    u64 total;

    if(R_FAILED(IFile_Read(&file, &total, buf, fileSize))) goto exit;

    u32 i,
        j;

    for(i = 0; i < 7; i++)
    {
        static const char *regions[] = {"JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"};

        if(memcmp(buf, regions[i], 3) == 0)
        {
            *regionId = (u8)i;
            break;
        }
    }

    for(j = 0; j < 12; j++)
    {
        static const char *languages[] = {"JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"};

        if(memcmp(buf + 4, languages[j], 2) == 0)
        {
            *languageId = (u8)j;
            break;
        }
    }

    ret = i != 7 && j != 12;

exit:
    IFile_Close(&file);

    return ret;
}
Example #6
0
static int loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
{
    /* Here we look for "/luma/locales/[u64 titleID in hex, uppercase].txt"
       If it exists it should contain, for example, "EUR IT" */

    char path[] = "/luma/locales/0000000000000000.txt";

    u32 i = 29;

    while(progId)
    {
        static const char hexDigits[] = "0123456789ABCDEF";
        path[i--] = hexDigits[(u32)(progId & 0xF)];
        progId >>= 4;
    }

    IFile file;
    Result ret = fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ);
    if(R_SUCCEEDED(ret))
    {
        char buf[6];
        u64 total;

        ret = IFile_Read(&file, &total, buf, 6);
        IFile_Close(&file);

        if(!R_SUCCEEDED(ret) || total < 6) return -1;

        for(u32 i = 0; i < 7; ++i)
        {
            static const char *regions[] = {"JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"};

            if(memcmp(buf, regions[i], 3) == 0)
            {
                *regionId = (u8)i;
                break;
            }
        }
        
        for(u32 i = 0; i < 12; ++i)
        {
            static const char *languages[] = {"JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"};

            if(memcmp(buf + 4, languages[i], 2) == 0)
            {
                *languageId = (u8)i;
                break;
            }
        }
    }

    return ret;
}
Example #7
0
static inline void loadCFWInfo(void)
{
    static bool infoLoaded = false;

    if(infoLoaded) return;

    svcGetCFWInfo(&info);

    IFile file;
    if(LOADERFLAG(ISSAFEMODE) && R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ))) //Init SD card if SAFE_MODE is being booted
        IFile_Close(&file);

    infoLoaded = true;
}
Example #8
0
static inline bool secureInfoExists(void)
{
    static bool exists = false;

    if(exists) return true;

    IFile file;
    if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_READ)))
    {
        exists = true;
        IFile_Close(&file);
    }

    return exists;
}
Example #9
0
static void loadCFWInfo(void)
{
    static bool infoLoaded = false;

    if(!infoLoaded)
    {
        svcGetCFWInfo(&info);

        IFile file;
        if(BOOTCFG_SAFEMODE != 0 && R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ))) //Init SD card if SAFE_MODE is being booted
            IFile_Close(&file);

        infoLoaded = true;
    }
}
Example #10
0
static void loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
{
    /* Here we look for "/puma/locales/[u64 titleID in hex, uppercase].txt"
       If it exists it should contain, for example, "EUR IT" */

    char path[] = "/puma/locales/0000000000000000.txt";
    progIdToStr(path + 29, progId);

    IFile file;

    if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ)))
    {
        u64 fileSize;

        if(R_SUCCEEDED(IFile_GetSize(&file, &fileSize)) && fileSize > 5 && fileSize < 9)
        {
            char buf[fileSize];
            u64 total;

            if(R_SUCCEEDED(IFile_Read(&file, &total, buf, fileSize)))
            {
                for(u32 i = 0; i < 7; i++)
                {
                    static const char *regions[] = {"JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"};

                    if(memcmp(buf, regions[i], 3) == 0)
                    {
                        *regionId = (u8)i;
                        break;
                    }
                }

                for(u32 i = 0; i < 12; i++)
                {
                    static const char *languages[] = {"JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"};

                    if(memcmp(buf + 4, languages[i], 2) == 0)
                    {
                        *languageId = (u8)i;
                        break;
                    }
                }
            }
        }

        IFile_Close(&file);
    }
}
Example #11
0
static u32 secureInfoExists(void)
{
    static u32 secureInfoExists = 0;

    if(!secureInfoExists)
    {
        IFile file;
        if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_READ)))
        {
            secureInfoExists = 1;
            IFile_Close(&file);
        }
    }

    return secureInfoExists;
}
Example #12
0
static u32 loadConfig(void)
{
    static u32 config = 0;

    if(!config)
    {
        IFile file;
        if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, "/luma/config.bin", FS_OPEN_READ)))
        {
            u64 total;
            if(R_SUCCEEDED(IFile_Read(&file, &total, &config, 4))) config |= 1 << 4;
            IFile_Close(&file);
        }
    }

    return config;
}
Example #13
0
static int loadCountryConfig(char *countryString)
{
    /* Here we look for "/puma/locales/country.txt"
       If it exists it should contain, for example, "GB" */
    char path[] = "/puma/locales/country.txt";

    IFile file;
    Result ret = fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ);
    if(R_SUCCEEDED(ret))
    {
        u64 total;

        ret = IFile_Read(&file, &total, countryString, 2);
        IFile_Close(&file);

        if(!R_SUCCEEDED(ret) || total < 2) return -1;
		return 0;
	}
    return ret;
}
Example #14
0
static void loadTitleCodeSection(u64 progId, u8 *code, u32 size)
{
    /* Here we look for "/puma/code_sections/[u64 titleID in hex, uppercase].bin"
       If it exists it should be a decompressed binary code file */

    char path[] = "/puma/code_sections/0000000000000000.bin";
    progIdToStr(path + 35, progId);

    IFile file;

    if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ)))
    {
        u64 fileSize;

        if(R_SUCCEEDED(IFile_GetSize(&file, &fileSize)) && fileSize <= size)
        {
            u64 total;
            IFile_Read(&file, &total, code, fileSize);
        }

        IFile_Close(&file);
    }
}