2016-03-29 17:43:53 +02:00
|
|
|
#include <3ds.h>
|
|
|
|
#include "patcher.h"
|
2016-09-06 14:09:29 +02:00
|
|
|
#include "memory.h"
|
|
|
|
#include "strings.h"
|
2016-03-29 17:43:53 +02:00
|
|
|
#include "ifile.h"
|
2016-08-29 17:51:03 +02:00
|
|
|
#include "CFWInfo.h"
|
2016-03-29 17:43:53 +02:00
|
|
|
|
2016-08-28 13:49:15 +02:00
|
|
|
static CFWInfo info;
|
2016-03-29 17:43:53 +02:00
|
|
|
|
2016-09-06 13:47:04 +02:00
|
|
|
static void patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, int offset, const void *replace, u32 repSize, u32 count)
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-09-06 13:47:04 +02:00
|
|
|
for(u32 i = 0; i < count; i++)
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-04-02 18:48:31 +02:00
|
|
|
u8 *found = memsearch(start, pattern, size, patSize);
|
2016-04-02 17:58:06 +02:00
|
|
|
|
2016-10-10 15:53:56 +02:00
|
|
|
if(found == NULL) svcBreak(USERBREAK_ASSERT);
|
2016-03-29 17:43:53 +02:00
|
|
|
|
2016-04-02 18:48:31 +02:00
|
|
|
memcpy(found + offset, replace, repSize);
|
2016-03-29 17:43:53 +02:00
|
|
|
|
|
|
|
u32 at = (u32)(found - start);
|
|
|
|
|
2016-04-11 17:57:22 +02:00
|
|
|
if(at + patSize > size) break;
|
2016-03-29 17:43:53 +02:00
|
|
|
|
2016-04-11 17:57:22 +02:00
|
|
|
size -= at + patSize;
|
2016-04-02 18:48:31 +02:00
|
|
|
start = found + patSize;
|
2016-03-29 17:43:53 +02:00
|
|
|
}
|
2016-04-18 20:50:52 +02:00
|
|
|
}
|
|
|
|
|
2016-10-14 18:03:17 +02:00
|
|
|
static Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int flags)
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-09-11 19:17:56 +02:00
|
|
|
FS_Path filePath = {PATH_ASCII, strnlen(path, 255) + 1, path},
|
2016-05-09 03:41:00 +02:00
|
|
|
archivePath = {PATH_EMPTY, 1, (u8 *)""};
|
|
|
|
|
|
|
|
return IFile_Open(file, archiveId, archivePath, filePath, flags);
|
2016-03-29 17:43:53 +02:00
|
|
|
}
|
|
|
|
|
2016-10-14 18:03:17 +02:00
|
|
|
static Result openLumaFile(IFile *file, const char *path)
|
|
|
|
{
|
|
|
|
Result res = fileOpen(file, ARCHIVE_SDMC, path, FS_OPEN_READ);
|
|
|
|
|
|
|
|
if((u32)res == 0xC88044AB) res = fileOpen(file, ARCHIVE_NAND_RW, path, FS_OPEN_READ); //Returned if SD is not mounted
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2016-08-20 18:45:56 +02:00
|
|
|
static void loadCFWInfo(void)
|
|
|
|
{
|
|
|
|
static bool infoLoaded = false;
|
2016-08-26 18:44:39 +02:00
|
|
|
|
2016-08-20 18:45:56 +02:00
|
|
|
if(!infoLoaded)
|
|
|
|
{
|
|
|
|
svcGetCFWInfo(&info);
|
2016-08-28 13:49:15 +02:00
|
|
|
|
2016-08-20 18:45:56 +02:00
|
|
|
IFile file;
|
2016-09-04 14:05:29 +02:00
|
|
|
if(BOOTCFG_SAFEMODE != 0 && R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ))) //Init SD card if SAFE_MODE is being booted
|
2016-08-20 18:45:56 +02:00
|
|
|
IFile_Close(&file);
|
2016-08-26 18:44:39 +02:00
|
|
|
|
|
|
|
infoLoaded = true;
|
2016-08-20 18:45:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-02 14:44:01 +02:00
|
|
|
static bool secureInfoExists(void)
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-07-02 14:44:01 +02:00
|
|
|
static bool exists = false;
|
2016-03-29 17:43:53 +02:00
|
|
|
|
2016-07-02 14:44:01 +02:00
|
|
|
if(!exists)
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-04-18 20:50:52 +02:00
|
|
|
IFile file;
|
|
|
|
if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_READ)))
|
|
|
|
{
|
2016-07-02 14:44:01 +02:00
|
|
|
exists = true;
|
2016-04-18 20:50:52 +02:00
|
|
|
IFile_Close(&file);
|
|
|
|
}
|
2016-03-29 17:43:53 +02:00
|
|
|
}
|
|
|
|
|
2016-07-02 14:44:01 +02:00
|
|
|
return exists;
|
2016-03-29 17:43:53 +02:00
|
|
|
}
|
|
|
|
|
2016-09-23 00:08:15 +02:00
|
|
|
static void loadCustomVerString(u16 *out, u32 *verStringSize, u32 currentNand)
|
2016-09-13 23:01:38 +02:00
|
|
|
{
|
2016-09-23 00:08:15 +02:00
|
|
|
static const char *paths[] = { "/luma/customversion_sys.txt",
|
|
|
|
"/luma/customversion_emu.txt",
|
|
|
|
"/luma/customversion_emu2.txt",
|
|
|
|
"/luma/customversion_emu3.txt",
|
|
|
|
"/luma/customversion_emu4.txt" };
|
2016-09-13 23:01:38 +02:00
|
|
|
|
|
|
|
IFile file;
|
2016-09-15 19:53:51 +02:00
|
|
|
|
2016-10-14 18:03:17 +02:00
|
|
|
if(R_SUCCEEDED(openLumaFile(&file, paths[currentNand])))
|
2016-09-13 23:01:38 +02:00
|
|
|
{
|
|
|
|
u64 fileSize;
|
|
|
|
|
2016-09-20 16:16:18 +02:00
|
|
|
if(R_SUCCEEDED(IFile_GetSize(&file, &fileSize)) && fileSize <= 62)
|
2016-09-13 23:01:38 +02:00
|
|
|
{
|
2016-09-17 00:03:09 +02:00
|
|
|
u8 buf[fileSize];
|
2016-09-13 23:01:38 +02:00
|
|
|
u64 total;
|
|
|
|
|
2016-09-15 19:53:51 +02:00
|
|
|
if(R_SUCCEEDED(IFile_Read(&file, &total, buf, fileSize)))
|
|
|
|
{
|
2016-09-17 00:03:09 +02:00
|
|
|
static const u8 bom[] = {0xEF, 0xBB, 0xBF};
|
2016-09-16 13:29:14 +02:00
|
|
|
u32 finalSize = 0;
|
2016-09-16 03:14:37 +02:00
|
|
|
|
2016-09-17 14:34:25 +02:00
|
|
|
//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++)
|
2016-09-16 03:14:37 +02:00
|
|
|
{
|
2016-09-20 16:16:18 +02:00
|
|
|
if((buf[i] & 0x80) == 0 && !(buf[i] == 0xA || buf[i] == 0xD))
|
2016-09-16 03:14:37 +02:00
|
|
|
{
|
|
|
|
increase = 1;
|
2016-09-17 14:34:25 +02:00
|
|
|
out[finalSize] = (u16)buf[i];
|
2016-09-16 03:14:37 +02:00
|
|
|
}
|
|
|
|
else if((buf[i] & 0xE0) == 0xC0 && i + 1 < fileSizeTmp && (buf[i + 1] & 0xC0) == 0x80)
|
|
|
|
{
|
|
|
|
increase = 2;
|
2016-09-17 14:34:25 +02:00
|
|
|
out[finalSize] = (u16)(((buf[i] & 0x1F) << 6) | (buf[i + 1] & 0x3F));
|
2016-09-16 03:14:37 +02:00
|
|
|
}
|
|
|
|
else if((buf[i] & 0xF0) == 0xE0 && i + 2 < fileSizeTmp && (buf[i + 1] & 0xC0) == 0x80 && (buf[i + 2] & 0xC0) == 0x80)
|
|
|
|
{
|
|
|
|
increase = 3;
|
2016-09-17 14:34:25 +02:00
|
|
|
out[finalSize] = (u16)(((buf[i] & 0xF) << 12) | ((buf[i + 1] & 0x3F) << 6) | (buf[i + 2] & 0x3F));
|
2016-09-16 03:14:37 +02:00
|
|
|
}
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
|
2016-09-18 18:31:16 +02:00
|
|
|
if(finalSize > 0)
|
|
|
|
{
|
|
|
|
if(finalSize > 5 && finalSize < 19) out[finalSize++] = 0;
|
|
|
|
*verStringSize = finalSize * 2;
|
|
|
|
}
|
2016-09-15 19:53:51 +02:00
|
|
|
}
|
2016-09-13 23:01:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
IFile_Close(&file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-01 20:27:28 +02:00
|
|
|
static void loadTitleCodeSection(u64 progId, u8 *code, u32 size)
|
2016-06-05 20:43:49 +02:00
|
|
|
{
|
|
|
|
/* Here we look for "/luma/code_sections/[u64 titleID in hex, uppercase].bin"
|
|
|
|
If it exists it should be a decompressed binary code file */
|
2016-07-01 20:27:28 +02:00
|
|
|
|
2016-06-05 20:43:49 +02:00
|
|
|
char path[] = "/luma/code_sections/0000000000000000.bin";
|
|
|
|
progIdToStr(path + 35, progId);
|
|
|
|
|
|
|
|
IFile file;
|
2016-07-01 20:27:28 +02:00
|
|
|
|
2016-10-14 18:03:17 +02:00
|
|
|
if(R_SUCCEEDED(openLumaFile(&file, path)))
|
2016-06-05 20:43:49 +02:00
|
|
|
{
|
2016-09-03 19:11:44 +02:00
|
|
|
u64 fileSize;
|
2016-07-01 20:27:28 +02:00
|
|
|
|
2016-09-15 19:53:51 +02:00
|
|
|
if(R_SUCCEEDED(IFile_GetSize(&file, &fileSize)) && fileSize <= size)
|
2016-07-01 20:27:28 +02:00
|
|
|
{
|
2016-09-03 19:11:44 +02:00
|
|
|
u64 total;
|
2016-09-15 19:53:51 +02:00
|
|
|
IFile_Read(&file, &total, code, fileSize);
|
2016-10-10 15:53:56 +02:00
|
|
|
|
|
|
|
if(total != fileSize) svcBreak(USERBREAK_ASSERT);
|
2016-07-01 20:27:28 +02:00
|
|
|
}
|
2016-09-13 23:01:38 +02:00
|
|
|
|
|
|
|
IFile_Close(&file);
|
2016-06-05 20:43:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-15 19:53:51 +02:00
|
|
|
static void loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
|
2016-06-05 20:43:49 +02:00
|
|
|
{
|
|
|
|
/* 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";
|
|
|
|
progIdToStr(path + 29, progId);
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
|
|
|
IFile file;
|
2016-09-15 19:53:51 +02:00
|
|
|
|
2016-10-14 18:03:17 +02:00
|
|
|
if(R_SUCCEEDED(openLumaFile(&file, path)))
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-09-13 23:01:38 +02:00
|
|
|
u64 fileSize;
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-09-20 16:16:18 +02:00
|
|
|
if(R_SUCCEEDED(IFile_GetSize(&file, &fileSize)) && fileSize > 5 && fileSize < 9)
|
2016-04-14 17:10:55 +02:00
|
|
|
{
|
2016-09-20 15:16:19 +02:00
|
|
|
char buf[fileSize];
|
2016-09-13 23:01:38 +02:00
|
|
|
u64 total;
|
2016-04-14 17:10:55 +02:00
|
|
|
|
2016-09-20 15:16:19 +02:00
|
|
|
if(R_SUCCEEDED(IFile_Read(&file, &total, buf, fileSize)))
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-09-15 19:53:51 +02:00
|
|
|
for(u32 i = 0; i < 7; i++)
|
2016-09-13 23:01:38 +02:00
|
|
|
{
|
|
|
|
static const char *regions[] = {"JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"};
|
|
|
|
|
|
|
|
if(memcmp(buf, regions[i], 3) == 0)
|
|
|
|
{
|
|
|
|
*regionId = (u8)i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-09-17 14:34:25 +02:00
|
|
|
|
2016-09-15 19:53:51 +02:00
|
|
|
for(u32 i = 0; i < 12; i++)
|
2016-09-13 23:01:38 +02:00
|
|
|
{
|
|
|
|
static const char *languages[] = {"JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"};
|
2016-04-14 17:10:55 +02:00
|
|
|
|
2016-09-13 23:01:38 +02:00
|
|
|
if(memcmp(buf + 4, languages[i], 2) == 0)
|
|
|
|
{
|
|
|
|
*languageId = (u8)i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
}
|
2016-04-14 17:10:55 +02:00
|
|
|
}
|
2016-09-13 23:01:38 +02:00
|
|
|
|
|
|
|
IFile_Close(&file);
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
static u8 *getCfgOffsets(u8 *code, u32 size, u32 *CFGUHandleOffset)
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-04-15 03:34:08 +02:00
|
|
|
/* HANS:
|
|
|
|
Look for error code which is known to be stored near cfg:u handle
|
|
|
|
this way we can find the right candidate
|
|
|
|
(handle should also be stored right after end of candidate function) */
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
u32 n = 0,
|
|
|
|
possible[24];
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
for(u8 *pos = code + 4; n < 24 && pos < code + size - 4; pos += 4)
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-04-15 03:34:08 +02:00
|
|
|
if(*(u32 *)pos == 0xD8A103F9)
|
|
|
|
{
|
|
|
|
for(u32 *l = (u32 *)pos - 4; n < 24 && l < (u32 *)pos + 4; l++)
|
|
|
|
if(*l <= 0x10000000) possible[n++] = *l;
|
|
|
|
}
|
|
|
|
}
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
for(u8 *CFGU_GetConfigInfoBlk2_endPos = code; CFGU_GetConfigInfoBlk2_endPos < code + size - 8; CFGU_GetConfigInfoBlk2_endPos += 4)
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-04-15 03:34:08 +02:00
|
|
|
static const u32 CFGU_GetConfigInfoBlk2_endPattern[] = {0xE8BD8010, 0x00010082};
|
|
|
|
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
//There might be multiple implementations of GetConfigInfoBlk2 but let's search for the one we want
|
2016-04-15 03:34:08 +02:00
|
|
|
u32 *cmp = (u32 *)CFGU_GetConfigInfoBlk2_endPos;
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
if(cmp[0] == CFGU_GetConfigInfoBlk2_endPattern[0] && cmp[1] == CFGU_GetConfigInfoBlk2_endPattern[1])
|
|
|
|
{
|
|
|
|
*CFGUHandleOffset = *((u32 *)CFGU_GetConfigInfoBlk2_endPos + 2);
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
for(u32 i = 0; i < n; i++)
|
|
|
|
if(possible[i] == *CFGUHandleOffset) return CFGU_GetConfigInfoBlk2_endPos;
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
CFGU_GetConfigInfoBlk2_endPos += 4;
|
|
|
|
}
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
}
|
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
return NULL;
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
}
|
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
static void patchCfgGetLanguage(u8 *code, u32 size, u8 languageId, u8 *CFGU_GetConfigInfoBlk2_endPos)
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-04-15 03:34:08 +02:00
|
|
|
u8 *CFGU_GetConfigInfoBlk2_startPos; //Let's find STMFD SP (there might be a NOP before, but nevermind)
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
for(CFGU_GetConfigInfoBlk2_startPos = CFGU_GetConfigInfoBlk2_endPos - 4;
|
|
|
|
CFGU_GetConfigInfoBlk2_startPos >= code && *((u16 *)CFGU_GetConfigInfoBlk2_startPos + 1) != 0xE92D;
|
|
|
|
CFGU_GetConfigInfoBlk2_startPos -= 2);
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
for(u8 *languageBlkIdPos = code; languageBlkIdPos < code + size; languageBlkIdPos += 4)
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-04-15 03:34:08 +02:00
|
|
|
if(*(u32 *)languageBlkIdPos == 0xA0002)
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-04-15 03:34:08 +02:00
|
|
|
for(u8 *instr = languageBlkIdPos - 8; instr >= languageBlkIdPos - 0x1008 && instr >= code + 4; instr -= 4) //Should be enough
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-04-15 17:53:40 +02:00
|
|
|
if(instr[3] == 0xEB) //We're looking for BL
|
2016-04-15 03:34:08 +02:00
|
|
|
{
|
2016-04-15 17:53:40 +02:00
|
|
|
u8 *calledFunction = instr;
|
2016-07-02 14:44:01 +02:00
|
|
|
u32 i = 0;
|
|
|
|
bool found;
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-04-15 17:53:40 +02:00
|
|
|
do
|
|
|
|
{
|
|
|
|
u32 low24 = (*(u32 *)calledFunction & 0x00FFFFFF) << 2;
|
|
|
|
u32 signMask = (u32)(-(low24 >> 25)) & 0xFC000000; //Sign extension
|
|
|
|
s32 offset = (s32)(low24 | signMask) + 8; //Branch offset + 8 for prefetch
|
|
|
|
|
|
|
|
calledFunction += offset;
|
|
|
|
|
|
|
|
found = calledFunction >= CFGU_GetConfigInfoBlk2_startPos - 4 && calledFunction <= CFGU_GetConfigInfoBlk2_endPos;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
while(i < 2 && !found && calledFunction[3] == 0xEA);
|
|
|
|
|
|
|
|
if(found)
|
2016-04-15 03:34:08 +02:00
|
|
|
{
|
|
|
|
*((u32 *)instr - 1) = 0xE3A00000 | languageId; // mov r0, sp => mov r0, =languageId
|
|
|
|
*(u32 *)instr = 0xE5CD0000; // bl CFGU_GetConfigInfoBlk2 => strb r0, [sp]
|
|
|
|
*((u32 *)instr + 1) = 0xE3B00000; // (1 or 2 instructions) => movs r0, 0 (result code)
|
|
|
|
|
|
|
|
//We're done
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
static void patchCfgGetRegion(u8 *code, u32 size, u8 regionId, u32 CFGUHandleOffset)
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-04-15 03:34:08 +02:00
|
|
|
for(u8 *cmdPos = code; cmdPos < code + size - 28; cmdPos += 4)
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-04-15 03:34:08 +02:00
|
|
|
static const u32 cfgSecureInfoGetRegionCmdPattern[] = {0xEE1D4F70, 0xE3A00802, 0xE5A40080};
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
u32 *cmp = (u32 *)cmdPos;
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
if(cmp[0] == cfgSecureInfoGetRegionCmdPattern[0] && cmp[1] == cfgSecureInfoGetRegionCmdPattern[1] &&
|
|
|
|
cmp[2] == cfgSecureInfoGetRegionCmdPattern[2] && *((u16 *)cmdPos + 7) == 0xE59F &&
|
|
|
|
*(u32 *)(cmdPos + 20 + *((u16 *)cmdPos + 6)) == CFGUHandleOffset)
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-04-15 03:34:08 +02:00
|
|
|
*((u32 *)cmdPos + 4) = 0xE3A00000 | regionId; // mov r0, =regionId
|
|
|
|
*((u32 *)cmdPos + 5) = 0xE5C40008; // strb r0, [r4, 8]
|
|
|
|
*((u32 *)cmdPos + 6) = 0xE3B00000; // movs r0, 0 (result code) ('s' not needed but nvm)
|
|
|
|
*((u32 *)cmdPos + 7) = 0xE5840004; // str r0, [r4, 4]
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
|
|
|
//The remaining, not patched, function code will do the rest for us
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-04 18:19:00 +02:00
|
|
|
void patchCode(u64 progId, u8 *code, u32 size)
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-08-17 23:47:30 +02:00
|
|
|
loadCFWInfo();
|
2016-08-26 18:44:39 +02:00
|
|
|
|
2016-04-04 18:19:00 +02:00
|
|
|
switch(progId)
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-03-29 22:43:15 +02:00
|
|
|
case 0x0004003000008F02LL: // USA Menu
|
|
|
|
case 0x0004003000008202LL: // EUR Menu
|
|
|
|
case 0x0004003000009802LL: // JPN Menu
|
|
|
|
case 0x000400300000A102LL: // CHN Menu
|
|
|
|
case 0x000400300000A902LL: // KOR Menu
|
|
|
|
case 0x000400300000B102LL: // TWN Menu
|
|
|
|
{
|
|
|
|
static const u8 regionFreePattern[] = {
|
2016-09-03 15:35:46 +02:00
|
|
|
0x00, 0x00, 0x55, 0xE3, 0x01, 0x10, 0xA0
|
2016-10-10 17:30:53 +02:00
|
|
|
},
|
|
|
|
regionFreePatch[] = {
|
2016-03-29 22:43:15 +02:00
|
|
|
0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1
|
|
|
|
};
|
2016-03-29 17:43:53 +02:00
|
|
|
|
2016-04-02 18:48:31 +02:00
|
|
|
//Patch SMDH region checks
|
|
|
|
patchMemory(code, size,
|
2016-03-29 22:43:15 +02:00
|
|
|
regionFreePattern,
|
|
|
|
sizeof(regionFreePattern), -16,
|
|
|
|
regionFreePatch,
|
|
|
|
sizeof(regionFreePatch), 1
|
2016-03-29 17:43:53 +02:00
|
|
|
);
|
2016-04-02 17:58:06 +02:00
|
|
|
|
2016-03-29 22:43:15 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 0x0004013000002C02LL: // NIM
|
|
|
|
{
|
2016-09-08 13:32:49 +02:00
|
|
|
//Apply only if the user booted with R
|
|
|
|
if((BOOTCFG_NAND != 0) != (BOOTCFG_FIRM != 0))
|
2016-04-26 13:52:30 +02:00
|
|
|
{
|
|
|
|
static const u8 skipEshopUpdateCheckPattern[] = {
|
|
|
|
0x30, 0xB5, 0xF1, 0xB0
|
2016-10-10 17:30:53 +02:00
|
|
|
},
|
|
|
|
skipEshopUpdateCheckPatch[] = {
|
2016-04-26 13:52:30 +02:00
|
|
|
0x00, 0x20, 0x08, 0x60, 0x70, 0x47
|
|
|
|
};
|
|
|
|
|
|
|
|
//Skip update checks to access the EShop
|
|
|
|
patchMemory(code, size,
|
|
|
|
skipEshopUpdateCheckPattern,
|
|
|
|
sizeof(skipEshopUpdateCheckPattern), 0,
|
|
|
|
skipEshopUpdateCheckPatch,
|
|
|
|
sizeof(skipEshopUpdateCheckPatch), 1
|
|
|
|
);
|
|
|
|
}
|
2016-03-31 01:38:28 +02:00
|
|
|
|
2016-03-29 22:43:15 +02:00
|
|
|
break;
|
2016-03-29 17:43:53 +02:00
|
|
|
}
|
2016-03-29 22:43:15 +02:00
|
|
|
|
2016-04-08 23:28:40 +02:00
|
|
|
case 0x0004013000003202LL: // FRIENDS
|
|
|
|
{
|
2016-04-11 17:07:40 +02:00
|
|
|
static const u8 fpdVerPattern[] = {
|
2016-09-03 15:35:46 +02:00
|
|
|
0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x01
|
2016-04-08 23:28:40 +02:00
|
|
|
};
|
2016-09-08 02:12:29 +02:00
|
|
|
|
2016-09-15 19:53:51 +02:00
|
|
|
u8 mostRecentFpdVer = 7;
|
2016-09-08 02:12:29 +02:00
|
|
|
|
2016-05-11 14:43:24 +02:00
|
|
|
u8 *fpdVer = memsearch(code, fpdVerPattern, size, sizeof(fpdVerPattern));
|
2016-04-08 23:28:40 +02:00
|
|
|
|
2016-10-10 15:53:56 +02:00
|
|
|
if(fpdVer == NULL) svcBreak(USERBREAK_ASSERT);
|
|
|
|
|
2016-09-15 19:53:51 +02:00
|
|
|
//Allow online access to work with old friends modules
|
2016-10-10 15:53:56 +02:00
|
|
|
if(fpdVer[9] < mostRecentFpdVer) fpdVer[9] = mostRecentFpdVer;
|
2016-04-08 23:28:40 +02:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2016-10-10 17:30:53 +02:00
|
|
|
|
2016-03-29 22:43:15 +02:00
|
|
|
case 0x0004001000021000LL: // USA MSET
|
|
|
|
case 0x0004001000020000LL: // JPN MSET
|
|
|
|
case 0x0004001000022000LL: // EUR MSET
|
|
|
|
case 0x0004001000026000LL: // CHN MSET
|
|
|
|
case 0x0004001000027000LL: // KOR MSET
|
|
|
|
case 0x0004001000028000LL: // TWN MSET
|
|
|
|
{
|
2016-09-13 23:01:38 +02:00
|
|
|
if(CONFIG(PATCHVERSTRING))
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-03-29 22:43:15 +02:00
|
|
|
static const u16 verPattern[] = u"Ver.";
|
2016-09-13 23:01:38 +02:00
|
|
|
static u16 *verString;
|
2016-10-10 17:30:53 +02:00
|
|
|
u32 verStringSize = 0,
|
|
|
|
currentNand = BOOTCFG_NAND;
|
2016-09-08 00:49:55 +02:00
|
|
|
|
2016-09-16 12:58:03 +02:00
|
|
|
u16 customVerString[19];
|
2016-09-23 00:08:15 +02:00
|
|
|
loadCustomVerString(customVerString, &verStringSize, currentNand);
|
2016-09-15 19:53:51 +02:00
|
|
|
|
2016-09-16 12:58:03 +02:00
|
|
|
if(verStringSize != 0) verString = customVerString;
|
2016-09-13 23:01:38 +02:00
|
|
|
else
|
2016-09-08 00:49:55 +02:00
|
|
|
{
|
2016-09-13 23:01:38 +02:00
|
|
|
verStringSize = 8;
|
2016-09-23 00:08:15 +02:00
|
|
|
u32 currentFirm = BOOTCFG_FIRM;
|
2016-09-13 23:01:38 +02:00
|
|
|
|
2016-09-23 13:58:59 +02:00
|
|
|
static u16 *verStringsNands[] = { u" Sys",
|
|
|
|
u" Emu",
|
|
|
|
u"Emu2",
|
|
|
|
u"Emu3",
|
|
|
|
u"Emu4" },
|
2016-09-13 23:01:38 +02:00
|
|
|
|
2016-09-23 13:58:59 +02:00
|
|
|
*verStringsEmuSys[] = { u"EmuS",
|
|
|
|
u"Em2S",
|
|
|
|
u"Em3S",
|
|
|
|
u"Em4S" },
|
|
|
|
|
|
|
|
*verStringsSysEmu[] = { u"SysE",
|
|
|
|
u"SyE2",
|
|
|
|
u"SyE3",
|
|
|
|
u"SyE4" };
|
|
|
|
|
|
|
|
verString = (currentFirm != 0) == (currentNand != 0) ? verStringsNands[currentNand] :
|
|
|
|
(!currentNand ? verStringsSysEmu[currentFirm - 1] : verStringsEmuSys[currentNand - 1]);
|
2016-09-08 00:49:55 +02:00
|
|
|
}
|
2016-03-29 22:43:15 +02:00
|
|
|
|
2016-04-02 18:48:31 +02:00
|
|
|
//Patch Ver. string
|
|
|
|
patchMemory(code, size,
|
2016-03-29 22:43:15 +02:00
|
|
|
verPattern,
|
2016-09-15 19:53:51 +02:00
|
|
|
sizeof(verPattern) - 2, 0,
|
2016-09-08 00:49:55 +02:00
|
|
|
verString,
|
2016-09-13 23:01:38 +02:00
|
|
|
verStringSize, 1
|
2016-03-29 22:43:15 +02:00
|
|
|
);
|
|
|
|
}
|
2016-04-02 17:58:06 +02:00
|
|
|
|
2016-03-29 22:43:15 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 0x0004013000008002LL: // NS
|
|
|
|
{
|
|
|
|
static const u8 stopCartUpdatesPattern[] = {
|
|
|
|
0x0C, 0x18, 0xE1, 0xD8
|
2016-10-10 17:30:53 +02:00
|
|
|
},
|
|
|
|
stopCartUpdatesPatch[] = {
|
2016-03-29 22:43:15 +02:00
|
|
|
0x0B, 0x18, 0x21, 0xC8
|
|
|
|
};
|
|
|
|
|
2016-04-02 18:48:31 +02:00
|
|
|
//Disable updates from foreign carts (makes carts region-free)
|
|
|
|
patchMemory(code, size,
|
2016-03-29 22:43:15 +02:00
|
|
|
stopCartUpdatesPattern,
|
|
|
|
sizeof(stopCartUpdatesPattern), 0,
|
|
|
|
stopCartUpdatesPatch,
|
|
|
|
sizeof(stopCartUpdatesPatch), 2
|
2016-03-29 17:43:53 +02:00
|
|
|
);
|
2016-04-02 17:58:06 +02:00
|
|
|
|
2016-09-11 19:17:56 +02:00
|
|
|
u32 cpuSetting = MULTICONFIG(NEWCPU);
|
2016-04-19 17:17:39 +02:00
|
|
|
|
2016-09-08 02:12:29 +02:00
|
|
|
if(cpuSetting != 0)
|
2016-04-12 15:25:36 +02:00
|
|
|
{
|
|
|
|
static const u8 cfgN3dsCpuPattern[] = {
|
2016-09-03 15:35:46 +02:00
|
|
|
0x00, 0x40, 0xA0, 0xE1, 0x07
|
2016-04-12 15:25:36 +02:00
|
|
|
};
|
|
|
|
|
2016-04-19 17:17:39 +02:00
|
|
|
u32 *cfgN3dsCpuLoc = (u32 *)memsearch(code, cfgN3dsCpuPattern, size, sizeof(cfgN3dsCpuPattern));
|
2016-04-12 15:25:36 +02:00
|
|
|
|
2016-10-10 15:53:56 +02:00
|
|
|
if(cfgN3dsCpuLoc == NULL) svcBreak(USERBREAK_ASSERT);
|
|
|
|
|
2016-04-12 15:25:36 +02:00
|
|
|
//Patch N3DS CPU Clock and L2 cache setting
|
2016-10-10 15:53:56 +02:00
|
|
|
*(cfgN3dsCpuLoc + 1) = 0xE1A00000;
|
|
|
|
*(cfgN3dsCpuLoc + 8) = 0xE3A00000 | cpuSetting;
|
2016-04-12 15:25:36 +02:00
|
|
|
}
|
|
|
|
|
2016-03-29 22:43:15 +02:00
|
|
|
break;
|
2016-03-29 17:43:53 +02:00
|
|
|
}
|
2016-03-29 22:43:15 +02:00
|
|
|
|
|
|
|
case 0x0004013000001702LL: // CFG
|
|
|
|
{
|
|
|
|
static const u8 secureinfoSigCheckPattern[] = {
|
2016-09-03 15:35:46 +02:00
|
|
|
0x06, 0x46, 0x10, 0x48
|
2016-10-10 17:30:53 +02:00
|
|
|
},
|
|
|
|
secureinfoSigCheckPatch[] = {
|
2016-03-29 22:43:15 +02:00
|
|
|
0x00, 0x26
|
|
|
|
};
|
|
|
|
|
2016-04-02 18:48:31 +02:00
|
|
|
//Disable SecureInfo signature check
|
|
|
|
patchMemory(code, size,
|
2016-03-29 22:43:15 +02:00
|
|
|
secureinfoSigCheckPattern,
|
|
|
|
sizeof(secureinfoSigCheckPattern), 0,
|
|
|
|
secureinfoSigCheckPatch,
|
|
|
|
sizeof(secureinfoSigCheckPatch), 1
|
2016-03-29 17:43:53 +02:00
|
|
|
);
|
2016-03-31 01:38:28 +02:00
|
|
|
|
2016-04-18 20:50:52 +02:00
|
|
|
if(secureInfoExists())
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-10-10 17:30:53 +02:00
|
|
|
static const u16 secureinfoFilenamePattern[] = u"SecureInfo_",
|
|
|
|
secureinfoFilenamePatch[] = u"C";
|
2016-03-31 01:38:28 +02:00
|
|
|
|
2016-04-02 18:48:31 +02:00
|
|
|
//Use SecureInfo_C
|
|
|
|
patchMemory(code, size,
|
2016-03-29 22:43:15 +02:00
|
|
|
secureinfoFilenamePattern,
|
2016-09-15 19:53:51 +02:00
|
|
|
sizeof(secureinfoFilenamePattern) - 2,
|
|
|
|
sizeof(secureinfoFilenamePattern) - 2,
|
2016-03-29 22:43:15 +02:00
|
|
|
secureinfoFilenamePatch,
|
2016-09-15 19:53:51 +02:00
|
|
|
sizeof(secureinfoFilenamePatch) - 2, 2
|
2016-03-29 22:43:15 +02:00
|
|
|
);
|
|
|
|
}
|
2016-04-02 17:58:06 +02:00
|
|
|
|
2016-05-14 15:35:59 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 0x0004013000003702LL: // RO
|
|
|
|
{
|
|
|
|
static const u8 sigCheckPattern[] = {
|
2016-05-27 04:16:49 +02:00
|
|
|
0x30, 0x40, 0x2D, 0xE9, 0x02
|
2016-10-10 17:30:53 +02:00
|
|
|
},
|
|
|
|
sha256ChecksPattern1[] = {
|
2016-05-27 04:16:49 +02:00
|
|
|
0x30, 0x40, 0x2D, 0xE9, 0x24
|
2016-10-10 17:30:53 +02:00
|
|
|
},
|
|
|
|
sha256ChecksPattern2[] = {
|
2016-05-27 04:16:49 +02:00
|
|
|
0xF8, 0x4F, 0x2D, 0xE9, 0x01
|
2016-10-10 17:30:53 +02:00
|
|
|
},
|
|
|
|
stub[] = {
|
2016-05-14 20:26:32 +02:00
|
|
|
0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 // mov r0, #0; bx lr
|
2016-05-14 15:35:59 +02:00
|
|
|
};
|
2016-10-10 17:30:53 +02:00
|
|
|
|
2016-05-14 15:35:59 +02:00
|
|
|
//Disable CRR0 signature (RSA2048 with SHA256) check
|
|
|
|
patchMemory(code, size,
|
|
|
|
sigCheckPattern,
|
|
|
|
sizeof(sigCheckPattern), 0,
|
2016-05-14 20:26:32 +02:00
|
|
|
stub,
|
|
|
|
sizeof(stub), 1
|
|
|
|
);
|
2016-10-10 17:30:53 +02:00
|
|
|
|
2016-05-14 20:26:32 +02:00
|
|
|
//Disable CRO0/CRR0 SHA256 hash checks (section hashes, and hash table)
|
|
|
|
patchMemory(code, size,
|
|
|
|
sha256ChecksPattern1,
|
|
|
|
sizeof(sha256ChecksPattern1), 0,
|
|
|
|
stub,
|
|
|
|
sizeof(stub), 1
|
2016-05-14 15:35:59 +02:00
|
|
|
);
|
2016-10-10 17:30:53 +02:00
|
|
|
|
2016-05-14 15:35:59 +02:00
|
|
|
patchMemory(code, size,
|
2016-05-14 20:26:32 +02:00
|
|
|
sha256ChecksPattern2,
|
|
|
|
sizeof(sha256ChecksPattern2), 0,
|
|
|
|
stub,
|
|
|
|
sizeof(stub), 1
|
2016-05-14 15:35:59 +02:00
|
|
|
);
|
2016-10-10 17:30:53 +02:00
|
|
|
|
2016-03-29 22:43:15 +02:00
|
|
|
break;
|
2016-05-28 16:13:22 +02:00
|
|
|
}
|
2016-09-06 13:43:00 +02:00
|
|
|
|
2016-05-28 16:13:22 +02:00
|
|
|
case 0x0004003000008A02LL: // ErrDisp
|
|
|
|
{
|
2016-09-19 14:03:55 +02:00
|
|
|
if(MULTICONFIG(DEVOPTIONS) == 1)
|
2016-05-28 16:13:22 +02:00
|
|
|
{
|
|
|
|
static const u8 unitinfoCheckPattern1[] = {
|
2016-09-03 15:41:45 +02:00
|
|
|
0x14, 0x00, 0xD0, 0xE5, 0xDB
|
2016-10-10 17:30:53 +02:00
|
|
|
},
|
|
|
|
unitinfoCheckPattern2[] = {
|
2016-09-03 15:41:45 +02:00
|
|
|
0x14, 0x00, 0xD0, 0xE5, 0x01
|
2016-10-10 17:30:53 +02:00
|
|
|
},
|
|
|
|
unitinfoCheckPatch[] = {
|
2016-05-28 16:13:22 +02:00
|
|
|
0x00, 0x00, 0xA0, 0xE3
|
|
|
|
} ;
|
2016-09-03 15:41:45 +02:00
|
|
|
|
2016-05-28 16:13:22 +02:00
|
|
|
patchMemory(code, size,
|
|
|
|
unitinfoCheckPattern1,
|
|
|
|
sizeof(unitinfoCheckPattern1), 0,
|
|
|
|
unitinfoCheckPatch,
|
|
|
|
sizeof(unitinfoCheckPatch), 1
|
|
|
|
);
|
|
|
|
|
|
|
|
patchMemory(code, size,
|
|
|
|
unitinfoCheckPattern2,
|
|
|
|
sizeof(unitinfoCheckPattern2), 0,
|
|
|
|
unitinfoCheckPatch,
|
|
|
|
sizeof(unitinfoCheckPatch), 3
|
|
|
|
);
|
|
|
|
}
|
2016-09-06 13:43:00 +02:00
|
|
|
|
2016-05-28 16:13:22 +02:00
|
|
|
break;
|
2016-03-29 17:43:53 +02:00
|
|
|
}
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
|
|
|
default:
|
2016-09-11 19:17:56 +02:00
|
|
|
if(CONFIG(USELANGEMUANDCODE))
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-09-15 19:53:51 +02:00
|
|
|
if((u32)((progId & 0xFFFFFFF000000000LL) >> 0x24) == 0x0004000)
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-06-05 20:43:49 +02:00
|
|
|
//External .code section loading
|
2016-07-01 20:27:28 +02:00
|
|
|
loadTitleCodeSection(progId, code, size);
|
|
|
|
|
2016-04-15 03:34:08 +02:00
|
|
|
//Language emulation
|
|
|
|
u8 regionId = 0xFF,
|
|
|
|
languageId = 0xFF;
|
2016-09-15 19:53:51 +02:00
|
|
|
loadTitleLocaleConfig(progId, ®ionId, &languageId);
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-09-15 19:53:51 +02:00
|
|
|
if(regionId != 0xFF || regionId != 0xFF)
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
{
|
2016-04-15 03:34:08 +02:00
|
|
|
u32 CFGUHandleOffset;
|
|
|
|
u8 *CFGU_GetConfigInfoBlk2_endPos = getCfgOffsets(code, size, &CFGUHandleOffset);
|
|
|
|
|
|
|
|
if(CFGU_GetConfigInfoBlk2_endPos != NULL)
|
|
|
|
{
|
|
|
|
if(languageId != 0xFF) patchCfgGetLanguage(code, size, languageId, CFGU_GetConfigInfoBlk2_endPos);
|
|
|
|
if(regionId != 0xFF) patchCfgGetRegion(code, size, regionId, CFGUHandleOffset);
|
|
|
|
}
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
}
|
|
|
|
}
|
2016-04-27 04:52:23 +02:00
|
|
|
}
|
Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
2016-04-14 00:46:36 +02:00
|
|
|
|
2016-04-27 04:52:23 +02:00
|
|
|
break;
|
2016-03-29 17:43:53 +02:00
|
|
|
}
|
2016-08-26 18:44:39 +02:00
|
|
|
}
|