2016-03-29 17:43:53 +02:00
|
|
|
#include <3ds.h>
|
2016-04-18 20:50:52 +02:00
|
|
|
#include "memory.h"
|
2016-03-29 17:43:53 +02:00
|
|
|
#include "patcher.h"
|
|
|
|
#include "ifile.h"
|
|
|
|
|
|
|
|
#ifndef PATH_MAX
|
|
|
|
#define PATH_MAX 255
|
2016-07-02 14:44:01 +02:00
|
|
|
#define CONFIG(a) (((loadConfig() >> (a + 16)) & 1) != 0)
|
2016-04-18 20:50:52 +02:00
|
|
|
#define MULTICONFIG(a) ((loadConfig() >> (a * 2 + 6)) & 3)
|
|
|
|
#define BOOTCONFIG(a, b) ((loadConfig() >> a) & b)
|
2016-03-29 17:43:53 +02:00
|
|
|
#endif
|
|
|
|
|
2016-04-18 20:50:52 +02:00
|
|
|
static int memcmp(const void *buf1, const void *buf2, u32 size)
|
|
|
|
{
|
|
|
|
const u8 *buf1c = (const u8 *)buf1;
|
|
|
|
const u8 *buf2c = (const u8 *)buf2;
|
|
|
|
|
|
|
|
for(u32 i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
int cmp = buf1c[i] - buf2c[i];
|
|
|
|
if(cmp) return cmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2016-03-29 17:43:53 +02:00
|
|
|
|
|
|
|
//Quick Search algorithm, adapted from http://igm.univ-mlv.fr/~lecroq/string/node19.html#SECTION00190
|
2016-04-02 17:58:06 +02:00
|
|
|
static u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize)
|
|
|
|
{
|
2016-03-29 17:43:53 +02:00
|
|
|
const u8 *patternc = (const u8 *)pattern;
|
|
|
|
|
|
|
|
//Preprocessing
|
2016-03-29 18:47:30 +02:00
|
|
|
u32 table[256];
|
2016-03-29 17:43:53 +02:00
|
|
|
|
|
|
|
for(u32 i = 0; i < 256; ++i)
|
|
|
|
table[i] = patternSize + 1;
|
|
|
|
for(u32 i = 0; i < patternSize; ++i)
|
|
|
|
table[patternc[i]] = patternSize - i;
|
|
|
|
|
|
|
|
//Searching
|
|
|
|
u32 j = 0;
|
|
|
|
|
2016-04-02 17:58:06 +02:00
|
|
|
while(j <= size - patternSize)
|
|
|
|
{
|
2016-03-29 17:43:53 +02:00
|
|
|
if(memcmp(patternc, startPos + j, patternSize) == 0)
|
|
|
|
return startPos + j;
|
|
|
|
j += table[startPos[j + patternSize]];
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-04-02 18:48:31 +02:00
|
|
|
static u32 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-03-29 17:43:53 +02:00
|
|
|
u32 i;
|
|
|
|
|
2016-04-02 17:58:06 +02:00
|
|
|
for(i = 0; i < count; i++)
|
|
|
|
{
|
2016-04-02 18:48:31 +02:00
|
|
|
u8 *found = memsearch(start, pattern, size, patSize);
|
2016-04-02 17:58:06 +02:00
|
|
|
|
2016-04-11 17:57:22 +02:00
|
|
|
if(found == NULL) break;
|
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
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2016-04-19 17:17:39 +02:00
|
|
|
static inline size_t strnlen(const char *string, size_t maxlen)
|
2016-04-18 20:50:52 +02:00
|
|
|
{
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
for(size = 0; *string && size < maxlen; string++, size++);
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2016-05-09 03:41:00 +02:00
|
|
|
static int fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int flags)
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-05-09 03:41:00 +02:00
|
|
|
FS_Path filePath = {PATH_ASCII, strnlen(path, PATH_MAX) + 1, path},
|
|
|
|
archivePath = {PATH_EMPTY, 1, (u8 *)""};
|
|
|
|
|
|
|
|
return IFile_Open(file, archiveId, archivePath, filePath, flags);
|
2016-03-29 17:43:53 +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-04-18 20:50:52 +02:00
|
|
|
static u32 loadConfig(void)
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-04-18 20:50:52 +02:00
|
|
|
static u32 config = 0;
|
2016-03-29 17:43:53 +02:00
|
|
|
|
2016-04-18 20:50:52 +02:00
|
|
|
if(!config)
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-04-18 20:50:52 +02:00
|
|
|
IFile file;
|
2016-04-23 01:43:11 +02:00
|
|
|
if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, "/luma/config.bin", FS_OPEN_READ)))
|
2016-04-18 20:50:52 +02:00
|
|
|
{
|
|
|
|
u64 total;
|
|
|
|
if(R_SUCCEEDED(IFile_Read(&file, &total, &config, 4))) config |= 1 << 4;
|
|
|
|
IFile_Close(&file);
|
|
|
|
}
|
2016-03-29 17:43:53 +02:00
|
|
|
}
|
|
|
|
|
2016-04-18 20:50:52 +02:00
|
|
|
return config;
|
2016-03-29 17:43:53 +02:00
|
|
|
}
|
|
|
|
|
2016-06-05 20:43:49 +02:00
|
|
|
static void progIdToStr(char *strEnd, u64 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
|
|
|
{
|
2016-04-26 01:30:03 +02:00
|
|
|
while(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
|
|
|
{
|
|
|
|
static const char hexDigits[] = "0123456789ABCDEF";
|
2016-06-05 20:43:49 +02:00
|
|
|
*strEnd-- = hexDigits[(u32)(progId & 0xF)];
|
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
|
|
|
progId >>= 4;
|
|
|
|
}
|
2016-06-05 20:43:49 +02:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
Result ret = fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ);
|
2016-07-01 20:27:28 +02:00
|
|
|
|
2016-06-05 20:43:49 +02:00
|
|
|
if(R_SUCCEEDED(ret))
|
|
|
|
{
|
|
|
|
u64 fileSize, total;
|
2016-07-01 20:27:28 +02:00
|
|
|
|
2016-06-05 20:43:49 +02:00
|
|
|
ret = IFile_GetSize(&file, &fileSize);
|
2016-07-01 20:27:28 +02:00
|
|
|
|
|
|
|
if(R_SUCCEEDED(ret) && fileSize <= size)
|
|
|
|
{
|
|
|
|
ret = IFile_Read(&file, &total, code, fileSize);
|
|
|
|
IFile_Close(&file);
|
|
|
|
}
|
2016-06-05 20:43:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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";
|
|
|
|
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;
|
|
|
|
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)
|
2016-04-14 17:10:55 +02:00
|
|
|
{
|
|
|
|
static const char *regions[] = {"JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"};
|
|
|
|
|
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
|
|
|
if(memcmp(buf, regions[i], 3) == 0)
|
|
|
|
{
|
|
|
|
*regionId = (u8)i;
|
|
|
|
break;
|
|
|
|
}
|
2016-04-14 17:10:55 +02:00
|
|
|
}
|
2016-05-14 15:35:59 +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
|
|
|
for(u32 i = 0; i < 12; ++i)
|
2016-04-14 17:10:55 +02:00
|
|
|
{
|
|
|
|
static const char *languages[] = {"JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"};
|
|
|
|
|
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
|
|
|
if(memcmp(buf + 4, languages[i], 2) == 0)
|
|
|
|
{
|
|
|
|
*languageId = (u8)i;
|
|
|
|
break;
|
|
|
|
}
|
2016-04-14 17:10:55 +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
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
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-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[] = {
|
|
|
|
0x00, 0x00, 0x55, 0xE3, 0x01, 0x10, 0xA0, 0xE3
|
|
|
|
};
|
|
|
|
static const u8 regionFreePatch[] = {
|
|
|
|
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
|
|
|
|
{
|
|
|
|
static const u8 blockAutoUpdatesPattern[] = {
|
|
|
|
0x25, 0x79, 0x0B, 0x99
|
|
|
|
};
|
|
|
|
static const u8 blockAutoUpdatesPatch[] = {
|
|
|
|
0xE3, 0xA0
|
|
|
|
};
|
|
|
|
|
2016-04-02 18:48:31 +02:00
|
|
|
//Block silent auto-updates
|
|
|
|
patchMemory(code, size,
|
2016-03-29 22:43:15 +02:00
|
|
|
blockAutoUpdatesPattern,
|
|
|
|
sizeof(blockAutoUpdatesPattern), 0,
|
|
|
|
blockAutoUpdatesPatch,
|
|
|
|
sizeof(blockAutoUpdatesPatch), 1
|
2016-03-29 17:43:53 +02:00
|
|
|
);
|
2016-04-02 18:48:31 +02:00
|
|
|
|
2016-04-26 13:52:30 +02:00
|
|
|
//Apply only if the updated NAND hasn't been booted
|
2016-07-01 20:27:28 +02:00
|
|
|
if((BOOTCONFIG(0, 3) != 0) == (BOOTCONFIG(2, 1) && CONFIG(1)))
|
2016-04-26 13:52:30 +02:00
|
|
|
{
|
|
|
|
static const u8 skipEshopUpdateCheckPattern[] = {
|
|
|
|
0x30, 0xB5, 0xF1, 0xB0
|
|
|
|
};
|
|
|
|
static const u8 skipEshopUpdateCheckPatch[] = {
|
|
|
|
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[] = {
|
|
|
|
0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x01, 0x01
|
2016-04-08 23:28:40 +02:00
|
|
|
};
|
2016-05-11 14:43:24 +02:00
|
|
|
|
|
|
|
static const u8 mostRecentFpdVer = 0x06;
|
|
|
|
|
|
|
|
u8 *fpdVer = memsearch(code, fpdVerPattern, size, sizeof(fpdVerPattern));
|
2016-04-08 23:28:40 +02:00
|
|
|
|
2016-05-11 14:43:24 +02:00
|
|
|
//Allow online access to work with old friends modules, without breaking newer firmwares
|
|
|
|
if(fpdVer != NULL && fpdVer[9] < mostRecentFpdVer) fpdVer[9] = mostRecentFpdVer;
|
2016-04-08 23:28:40 +02:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
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-04-26 21:51:57 +02:00
|
|
|
if(CONFIG(5))
|
2016-04-02 17:58:06 +02:00
|
|
|
{
|
2016-03-29 22:43:15 +02:00
|
|
|
static const u16 verPattern[] = u"Ver.";
|
2016-04-12 23:18:07 +02:00
|
|
|
const u32 currentNand = BOOTCONFIG(0, 3);
|
|
|
|
const u32 matchingFirm = BOOTCONFIG(2, 1) == (currentNand != 0);
|
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,
|
|
|
|
sizeof(verPattern) - sizeof(u16), 0,
|
2016-04-17 18:57:25 +02:00
|
|
|
!currentNand ? ((matchingFirm) ? u" Sys" : u"SysE") :
|
|
|
|
((currentNand == 1) ? (matchingFirm ? u" Emu" : u"EmuS") : ((matchingFirm) ? u"Emu2" : u"Em2S")),
|
2016-03-29 22:43:15 +02:00
|
|
|
sizeof(verPattern) - sizeof(u16), 1
|
|
|
|
);
|
|
|
|
}
|
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
|
|
|
|
};
|
|
|
|
static const u8 stopCartUpdatesPatch[] = {
|
|
|
|
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-04-19 17:17:39 +02:00
|
|
|
u32 cpuSetting = MULTICONFIG(1);
|
|
|
|
|
|
|
|
if(cpuSetting)
|
2016-04-12 15:25:36 +02:00
|
|
|
{
|
|
|
|
static const u8 cfgN3dsCpuPattern[] = {
|
2016-04-19 17:17:39 +02:00
|
|
|
0x00, 0x40, 0xA0, 0xE1, 0x07, 0x00
|
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
|
|
|
|
|
|
|
//Patch N3DS CPU Clock and L2 cache setting
|
|
|
|
if(cfgN3dsCpuLoc != NULL)
|
|
|
|
{
|
2016-04-19 17:17:39 +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[] = {
|
|
|
|
0x06, 0x46, 0x10, 0x48, 0xFC
|
|
|
|
};
|
|
|
|
static const u8 secureinfoSigCheckPatch[] = {
|
|
|
|
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-03-31 01:38:28 +02:00
|
|
|
static const u16 secureinfoFilenamePattern[] = u"SecureInfo_";
|
|
|
|
static const u16 secureinfoFilenamePatch[] = u"C";
|
|
|
|
|
2016-04-02 18:48:31 +02:00
|
|
|
//Use SecureInfo_C
|
|
|
|
patchMemory(code, size,
|
2016-03-29 22:43:15 +02:00
|
|
|
secureinfoFilenamePattern,
|
|
|
|
sizeof(secureinfoFilenamePattern) - sizeof(u16),
|
|
|
|
sizeof(secureinfoFilenamePattern) - sizeof(u16),
|
|
|
|
secureinfoFilenamePatch,
|
|
|
|
sizeof(secureinfoFilenamePatch) - sizeof(u16), 2
|
|
|
|
);
|
|
|
|
}
|
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-05-14 15:35:59 +02:00
|
|
|
};
|
2016-05-14 20:26:32 +02:00
|
|
|
static const u8 sha256ChecksPattern1[] = {
|
2016-05-27 04:16:49 +02:00
|
|
|
0x30, 0x40, 0x2D, 0xE9, 0x24
|
2016-05-14 15:35:59 +02:00
|
|
|
};
|
2016-05-14 20:26:32 +02:00
|
|
|
static const u8 sha256ChecksPattern2[] = {
|
2016-05-27 04:16:49 +02:00
|
|
|
0xF8, 0x4F, 0x2D, 0xE9, 0x01
|
2016-05-14 15:35:59 +02:00
|
|
|
};
|
|
|
|
|
2016-05-14 20:26:32 +02:00
|
|
|
static const u8 stub[] = {
|
|
|
|
0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 // mov r0, #0; bx lr
|
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
|
|
|
|
);
|
|
|
|
|
|
|
|
//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
|
|
|
);
|
|
|
|
|
|
|
|
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-03-29 22:43:15 +02:00
|
|
|
break;
|
2016-05-28 16:13:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
case 0x0004003000008A02LL: // ErrDisp
|
|
|
|
{
|
|
|
|
if(MULTICONFIG(2) == 1)
|
|
|
|
{
|
|
|
|
static const u8 unitinfoCheckPattern1[] = {
|
|
|
|
0x14, 0x00, 0xD0, 0xE5, 0xDB, 0x9A, 0x9F, 0xED
|
|
|
|
};
|
|
|
|
|
|
|
|
static const u8 unitinfoCheckPattern2[] = {
|
|
|
|
0x14, 0x00, 0xD0, 0xE5, 0x01, 0x00, 0x10, 0xE3
|
|
|
|
} ;
|
|
|
|
|
|
|
|
static const u8 unitinfoCheckPatch[] = {
|
|
|
|
0x00, 0x00, 0xA0, 0xE3
|
|
|
|
} ;
|
|
|
|
|
|
|
|
patchMemory(code, size,
|
|
|
|
unitinfoCheckPattern1,
|
|
|
|
sizeof(unitinfoCheckPattern1), 0,
|
|
|
|
unitinfoCheckPatch,
|
|
|
|
sizeof(unitinfoCheckPatch), 1
|
|
|
|
);
|
|
|
|
|
|
|
|
patchMemory(code, size,
|
|
|
|
unitinfoCheckPattern2,
|
|
|
|
sizeof(unitinfoCheckPattern2), 0,
|
|
|
|
unitinfoCheckPatch,
|
|
|
|
sizeof(unitinfoCheckPatch), 3
|
|
|
|
);
|
|
|
|
}
|
|
|
|
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-04-18 20:50:52 +02:00
|
|
|
if(CONFIG(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
|
|
|
u32 tidHigh = (progId & 0xFFFFFFF000000000LL) >> 0x24;
|
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(tidHigh == 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;
|
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-18 20:50:52 +02:00
|
|
|
if(R_SUCCEEDED(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-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-05-10 02:12:44 +02:00
|
|
|
}
|