mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-01-10 08:29:29 +01:00
137 lines
5.8 KiB
C++
137 lines
5.8 KiB
C++
#include "common.h"
|
|
#include "gameCode.h"
|
|
#include <algorithm>
|
|
#include "patches/PatchHeap.h"
|
|
#include "thumbInstructions.h"
|
|
#include "SecureSysCallsUnusedSpaceLocator.h"
|
|
|
|
#define THUMB_MOVS_R0_R1 THUMB_MOVS_REG(0, 1)
|
|
#define THUMB_MOVS_R2_0 THUMB_MOVS_IMM(2, 0)
|
|
|
|
static const u16 sSvcSoftResetPattern[] = { THUMB_SVC(0), THUMB_BX_LR };
|
|
static const u16 sSvcWaitByLoopPattern[] = { THUMB_SVC(3), THUMB_BX_LR };
|
|
static const u16 sSvcWaitIntrPattern[] = { THUMB_MOVS_R2_0, THUMB_SVC(4), THUMB_BX_LR };
|
|
static const u16 sSvcWaitVBlankIntrPattern[] = { THUMB_MOVS_R2_0, THUMB_SVC(5), THUMB_BX_LR };
|
|
static const u16 sSvcHaltPattern[] = { THUMB_SVC(6), THUMB_BX_LR };
|
|
static const u16 sSvcDivPattern[] = { THUMB_SVC(9), THUMB_BX_LR };
|
|
static const u16 sSvcDivRemPattern[] = { THUMB_SVC(9), THUMB_MOVS_R0_R1, THUMB_BX_LR };
|
|
static const u16 sSvcCpuSetPattern[] = { THUMB_SVC(0xB), THUMB_BX_LR };
|
|
static const u16 sSvcCpuSetFastPattern[] = { THUMB_SVC(0xC), THUMB_BX_LR };
|
|
static const u16 sSvcSqrtPattern[] = { THUMB_SVC(0xD), THUMB_BX_LR };
|
|
static const u16 sSvcGetCrc16Pattern[] = { THUMB_SVC(0xE), THUMB_BX_LR };
|
|
static const u16 sSvcIsMainMemExpandedPattern[] = { THUMB_SVC(0xF), THUMB_BX_LR };
|
|
static const u16 sSvcUnpackBitsPattern[] = { THUMB_SVC(0x10), THUMB_BX_LR };
|
|
static const u16 sSvcUncompressLz8Pattern[] = { THUMB_SVC(0x11), THUMB_BX_LR };
|
|
static const u16 sSvcUncompressLz16FromDevicePattern[] = { THUMB_SVC(0x12), THUMB_BX_LR };
|
|
static const u16 sSvcUncompressHuffmanFromDevicePattern[] = { THUMB_SVC(0x13), THUMB_BX_LR };
|
|
static const u16 sSvcUncompressRl8Pattern[] = { THUMB_SVC(0x14), THUMB_BX_LR };
|
|
static const u16 sSvcUncompressRl16FromDevicePattern[] = { THUMB_SVC(0x15), THUMB_BX_LR };
|
|
|
|
struct svc_pattern_t
|
|
{
|
|
const u16* pattern;
|
|
u32 length;
|
|
};
|
|
|
|
static const std::array<const svc_pattern_t, 18> sSvcPatterns
|
|
{
|
|
svc_pattern_t { sSvcSoftResetPattern, sizeof(sSvcSoftResetPattern) },
|
|
svc_pattern_t { sSvcWaitByLoopPattern, sizeof(sSvcWaitByLoopPattern) },
|
|
svc_pattern_t { sSvcWaitIntrPattern, sizeof(sSvcWaitIntrPattern) },
|
|
svc_pattern_t { sSvcWaitVBlankIntrPattern, sizeof(sSvcWaitVBlankIntrPattern) },
|
|
svc_pattern_t { sSvcHaltPattern, sizeof(sSvcHaltPattern) },
|
|
svc_pattern_t { sSvcDivPattern, sizeof(sSvcDivPattern) },
|
|
svc_pattern_t { sSvcDivRemPattern, sizeof(sSvcDivRemPattern) },
|
|
svc_pattern_t { sSvcCpuSetPattern, sizeof(sSvcCpuSetPattern) },
|
|
svc_pattern_t { sSvcCpuSetFastPattern, sizeof(sSvcCpuSetFastPattern) },
|
|
svc_pattern_t { sSvcSqrtPattern, sizeof(sSvcSqrtPattern) },
|
|
svc_pattern_t { sSvcGetCrc16Pattern, sizeof(sSvcGetCrc16Pattern) },
|
|
svc_pattern_t { sSvcIsMainMemExpandedPattern, sizeof(sSvcIsMainMemExpandedPattern) },
|
|
svc_pattern_t { sSvcUnpackBitsPattern, sizeof(sSvcUnpackBitsPattern) },
|
|
svc_pattern_t { sSvcUncompressLz8Pattern, sizeof(sSvcUncompressLz8Pattern) },
|
|
svc_pattern_t { sSvcUncompressLz16FromDevicePattern, sizeof(sSvcUncompressLz16FromDevicePattern) },
|
|
svc_pattern_t { sSvcUncompressHuffmanFromDevicePattern, sizeof(sSvcUncompressHuffmanFromDevicePattern) },
|
|
svc_pattern_t { sSvcUncompressRl8Pattern, sizeof(sSvcUncompressRl8Pattern) },
|
|
svc_pattern_t { sSvcUncompressRl16FromDevicePattern, sizeof(sSvcUncompressRl16FromDevicePattern) }
|
|
};
|
|
|
|
const u16* SecureSysCallsUnusedSpaceLocator::FindPattern(const u16* data, u32 length, const u16* pattern, u32 patternLength) const
|
|
{
|
|
length >>= 1;
|
|
patternLength >>= 1;
|
|
for (u32 i = 0; i < length - patternLength; i++)
|
|
{
|
|
bool ok = true;
|
|
for (u32 j = 0; j < patternLength; j++)
|
|
{
|
|
if (data[i + j] != pattern[j])
|
|
{
|
|
ok = false;
|
|
break;
|
|
}
|
|
}
|
|
if (ok)
|
|
return &data[i];
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void SecureSysCallsUnusedSpaceLocator::FindUnusedSpace(const nds_header_ntr_t* romHeader, PatchHeap& patchHeap) const
|
|
{
|
|
if (romHeader->arm9RomOffset != 0x4000)
|
|
return;
|
|
|
|
u32 secureStart = romHeader->arm9LoadAddress;
|
|
|
|
if (*(u32*)(secureStart + 0x800) == 0x4770DF00)
|
|
{
|
|
// secure area for development purposes has this area empty
|
|
patchHeap.AddFreeSpace((void*)secureStart, 0x800);
|
|
LOG_DEBUG("Added free space starting at 0x%x with size 0x%x\n", secureStart, 0x800);
|
|
return;
|
|
}
|
|
|
|
std::array<svc_pattern_t, sSvcPatterns.size()> patternLocations;
|
|
|
|
for (u32 i = 0; i < sSvcPatterns.size(); i++)
|
|
{
|
|
patternLocations[i].pattern = FindPattern((const u16*)secureStart, 0x800, sSvcPatterns[i].pattern, sSvcPatterns[i].length);
|
|
patternLocations[i].length = sSvcPatterns[i].length;
|
|
}
|
|
|
|
std::qsort(patternLocations.begin(), patternLocations.size(), sizeof(svc_pattern_t), [](const void* a, const void* b)
|
|
{
|
|
const auto cmp = static_cast<const svc_pattern_t*>(a)->pattern <=> static_cast<const svc_pattern_t*>(b)->pattern;
|
|
if (cmp < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
if (cmp > 0)
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
});
|
|
|
|
u32 current = secureStart;
|
|
for (u32 i = 0; i < sSvcPatterns.size(); i++)
|
|
{
|
|
if (!patternLocations[i].pattern)
|
|
continue;
|
|
u32 freeSpaceEnd = (u32)patternLocations[i].pattern & ~3;
|
|
if (current < freeSpaceEnd)
|
|
{
|
|
u32 freeSpace = freeSpaceEnd - current;
|
|
patchHeap.AddFreeSpace((void*)current, freeSpace);
|
|
LOG_DEBUG("Added free space starting at 0x%x with size 0x%x\n", current, freeSpace);
|
|
}
|
|
current = ((u32)patternLocations[i].pattern + patternLocations[i].length + 3) & ~3;
|
|
}
|
|
if (current < secureStart + 0x800)
|
|
{
|
|
u32 freeSpace = secureStart + 0x800 - current;
|
|
patchHeap.AddFreeSpace((void*)current, freeSpace);
|
|
LOG_DEBUG("Added free space starting at 0x%x with size 0x%x\n", current, freeSpace);
|
|
}
|
|
}
|