Attempt to increase the compatibility of language emulation with some rare games, add checks for the functions
This commit is contained in:
parent
429488a4ba
commit
4ad6b1c220
@ -138,7 +138,7 @@ static inline void loadCustomVerString(u16 *out, u32 *verStringSize, u32 current
|
||||
}
|
||||
}
|
||||
|
||||
static inline void loadTitleCodeSection(u64 progId, u8 *code, u32 size)
|
||||
static inline u32 loadTitleCodeSection(u64 progId, u8 *code, u32 size)
|
||||
{
|
||||
/* Here we look for "/luma/code_sections/[u64 titleID in hex, uppercase].bin"
|
||||
If it exists it should be a decompressed binary code file */
|
||||
@ -147,24 +147,27 @@ static inline void loadTitleCodeSection(u64 progId, u8 *code, u32 size)
|
||||
progIdToStr(path + 35, progId);
|
||||
|
||||
IFile file;
|
||||
u32 ret = 0;
|
||||
|
||||
if(R_SUCCEEDED(openLumaFile(&file, path)))
|
||||
{
|
||||
u64 fileSize;
|
||||
|
||||
if(R_SUCCEEDED(IFile_GetSize(&file, &fileSize)) && fileSize <= size)
|
||||
if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize > size) ret = 1;
|
||||
else
|
||||
{
|
||||
u64 total;
|
||||
IFile_Read(&file, &total, code, fileSize);
|
||||
|
||||
if(total != fileSize) svcBreak(USERBREAK_ASSERT);
|
||||
if(R_FAILED(IFile_Read(&file, &total, code, fileSize)) || total != fileSize) ret = 1;
|
||||
}
|
||||
|
||||
IFile_Close(&file);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
|
||||
static inline u32 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" */
|
||||
@ -173,17 +176,20 @@ static inline void loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageI
|
||||
progIdToStr(path + 29, progId);
|
||||
|
||||
IFile file;
|
||||
u32 ret = 0;
|
||||
|
||||
if(R_SUCCEEDED(openLumaFile(&file, path)))
|
||||
{
|
||||
u64 fileSize;
|
||||
|
||||
if(R_SUCCEEDED(IFile_GetSize(&file, &fileSize)) && fileSize > 5 && fileSize < 9)
|
||||
if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize < 6 || fileSize > 8) ret = 1;
|
||||
else
|
||||
{
|
||||
char buf[fileSize];
|
||||
u64 total;
|
||||
|
||||
if(R_SUCCEEDED(IFile_Read(&file, &total, buf, fileSize)))
|
||||
if(R_FAILED(IFile_Read(&file, &total, buf, fileSize))) ret = 1;
|
||||
else
|
||||
{
|
||||
for(u32 i = 0; i < 7; i++)
|
||||
{
|
||||
@ -211,6 +217,8 @@ static inline void loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageI
|
||||
|
||||
IFile_Close(&file);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline u8 *getCfgOffsets(u8 *code, u32 size, u32 *CFGUHandleOffset)
|
||||
@ -253,7 +261,7 @@ static inline u8 *getCfgOffsets(u8 *code, u32 size, u32 *CFGUHandleOffset)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void patchCfgGetLanguage(u8 *code, u32 size, u8 languageId, u8 *CFGU_GetConfigInfoBlk2_endPos)
|
||||
static inline u32 patchCfgGetLanguage(u8 *code, u32 size, u8 languageId, u8 *CFGU_GetConfigInfoBlk2_endPos)
|
||||
{
|
||||
u8 *CFGU_GetConfigInfoBlk2_startPos; //Let's find STMFD SP (there might be a NOP before, but nevermind)
|
||||
|
||||
@ -293,35 +301,43 @@ static inline void patchCfgGetLanguage(u8 *code, u32 size, u8 languageId, u8 *CF
|
||||
*((u32 *)instr + 1) = 0xE3B00000; //(1 or 2 instructions) => movs r0, 0 (result code)
|
||||
|
||||
//We're done
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void patchCfgGetRegion(u8 *code, u32 size, u8 regionId, u32 CFGUHandleOffset)
|
||||
static inline u32 patchCfgGetRegion(u8 *code, u32 size, u8 regionId, u32 CFGUHandleOffset)
|
||||
{
|
||||
for(u8 *cmdPos = code; cmdPos < code + size - 28; cmdPos += 4)
|
||||
{
|
||||
static const u32 cfgSecureInfoGetRegionCmdPattern[] = {0xEE1D4F70, 0xE3A00802, 0xE5A40080};
|
||||
static const u32 cfgSecureInfoGetRegionCmdPattern[] = {0xEE1D0F70, 0xE3A00802};
|
||||
|
||||
u32 *cmp = (u32 *)cmdPos;
|
||||
|
||||
if(cmp[0] == cfgSecureInfoGetRegionCmdPattern[0] && cmp[1] == cfgSecureInfoGetRegionCmdPattern[1] &&
|
||||
cmp[2] == cfgSecureInfoGetRegionCmdPattern[2] && *((u16 *)cmdPos + 7) == 0xE59F &&
|
||||
*(u32 *)(cmdPos + 20 + *((u16 *)cmdPos + 6)) == CFGUHandleOffset)
|
||||
if((cmp[0] & 0xFFFF0FFF) == cfgSecureInfoGetRegionCmdPattern[0])
|
||||
{
|
||||
*((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]
|
||||
for(u32 i = 1; i < 4; i++)
|
||||
if(cmp[i] == cfgSecureInfoGetRegionCmdPattern[1] && *((u16 *)cmdPos + 5 + (2 * i)) == 0xE59F &&
|
||||
*(u32 *)(cmdPos + 16 + (4 * i) + *((u16 *)cmdPos + 4 + (2 * i))) == CFGUHandleOffset)
|
||||
{
|
||||
cmp += 3 + i;
|
||||
cmp[0] = 0xE3A00000 | regionId; //mov r0, =regionId
|
||||
cmp[1] = 0xE5C40008; //strb r0, [r4, 8]
|
||||
cmp[2] = 0xE3B00000; //movs r0, 0 (result code) ('s' not needed but nvm)
|
||||
cmp[3] = 0xE5840004; //str r0, [r4, 4]
|
||||
|
||||
//The remaining, not patched, function code will do the rest for us
|
||||
break;
|
||||
//The remaining, not patched, function code will do the rest for us
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
@ -570,12 +586,12 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
else if(CONFIG(USELANGEMUANDCODE) && (u32)((progId & 0xFFFFFFF000000000LL) >> 0x24) == 0x0004000)
|
||||
{
|
||||
//External .code section loading
|
||||
loadTitleCodeSection(progId, code, size);
|
||||
res += loadTitleCodeSection(progId, code, size);
|
||||
|
||||
//Language emulation
|
||||
u8 regionId = 0xFF,
|
||||
languageId = 0xFF;
|
||||
loadTitleLocaleConfig(progId, ®ionId, &languageId);
|
||||
res += loadTitleLocaleConfig(progId, ®ionId, &languageId);
|
||||
|
||||
if(regionId != 0xFF || regionId != 0xFF)
|
||||
{
|
||||
@ -585,8 +601,8 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
if(CFGU_GetConfigInfoBlk2_endPos == NULL) res++;
|
||||
else
|
||||
{
|
||||
if(languageId != 0xFF) patchCfgGetLanguage(code, size, languageId, CFGU_GetConfigInfoBlk2_endPos);
|
||||
if(regionId != 0xFF) patchCfgGetRegion(code, size, regionId, CFGUHandleOffset);
|
||||
if(languageId != 0xFF) res += patchCfgGetLanguage(code, size, languageId, CFGU_GetConfigInfoBlk2_endPos);
|
||||
if(regionId != 0xFF) res += patchCfgGetRegion(code, size, regionId, CFGUHandleOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user