mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-06-02 09:16:49 +02:00
Improved DSProtect patches
This commit is contained in:
@@ -2,417 +2,457 @@
|
|||||||
#include "../../../PatchContext.h"
|
#include "../../../PatchContext.h"
|
||||||
#include "thumbInstructions.h"
|
#include "thumbInstructions.h"
|
||||||
#include "gameCode.h"
|
#include "gameCode.h"
|
||||||
#include "DSProtectOverlayPatchv1Asm.h"
|
#include "DSProtectOverlayPatchAsm.h"
|
||||||
#include "DSProtectOverlayPatchv2Asm.h"
|
|
||||||
#include "DSProtectOverlayPatchv2sAsm.h"
|
|
||||||
#include "DSProtectOverlayPatch.h"
|
#include "DSProtectOverlayPatch.h"
|
||||||
|
|
||||||
|
#define FUNCMASK_A1 (0b000001)
|
||||||
|
#define FUNCMASK_NOTA1 (0b000010)
|
||||||
|
#define FUNCMASK_A2 (0b000100)
|
||||||
|
#define FUNCMASK_NOTA2 (0b001000)
|
||||||
|
#define FUNCMASK_A3 (0b010000)
|
||||||
|
#define FUNCMASK_NOTA3 (0b100000)
|
||||||
|
|
||||||
|
#define PATCH_WRITE_WORD (0)
|
||||||
|
#define PATCH_COPY_NEXT (1)
|
||||||
|
|
||||||
|
#define MAGIC_100_102 (0xFFFFFE70)
|
||||||
|
#define MAGIC_105_123 (0xFFFFFCE0)
|
||||||
|
#define MAGIC_200s_205s (0x00000000)
|
||||||
|
|
||||||
|
#define OFFSET_INVALID (0x80000000)
|
||||||
|
|
||||||
const void* DSProtectOverlayPatch::InsertPatch(PatchContext& patchContext)
|
const void* DSProtectOverlayPatch::InsertPatch(PatchContext& patchContext)
|
||||||
{
|
{
|
||||||
if (_version <= DSProtectVersion::v1_28)
|
ConfigurePatch(patchContext);
|
||||||
{
|
|
||||||
return InsertPatchV1(patchContext);
|
u32 patchSize = SECTION_SIZE(dsprotectpatch);
|
||||||
}
|
void* patchAddress = patchContext.GetPatchHeap().Alloc(patchSize);
|
||||||
else if (_version <= DSProtectVersion::v2_05)
|
u32 entryAddress = (u32)&dsprotectpatch_entry - (u32)SECTION_START(dsprotectpatch) + (u32)patchAddress;
|
||||||
{
|
memcpy(patchAddress, SECTION_START(dsprotectpatch), patchSize);
|
||||||
return InsertPatchV2(patchContext);
|
|
||||||
}
|
return (const void*)entryAddress;
|
||||||
else if (_version <= DSProtectVersion::v2_05s)
|
|
||||||
{
|
|
||||||
return InsertPatchV2s(patchContext);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_WARNING("Unsupported DSProtect version\n");
|
|
||||||
return next ? (const void*)next->InsertPatch(patchContext) : nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSProtectOverlayPatch::SetOldV1Offsets(const u16* offsets) const
|
void DSProtectOverlayPatch::ConfigurePatch(PatchContext& patchContext) const
|
||||||
{
|
{
|
||||||
int offsetIdx = 0;
|
// Next patch and target overlay ID
|
||||||
|
dsprotectpatch_nextAddress = next ? (const void*)next->InsertPatch(patchContext) : nullptr;
|
||||||
|
dsprotectpatch_overlayId = _overlayId;
|
||||||
|
|
||||||
if (_functionMask & 0b000001)
|
u32 regionOffset = _overlayOffset;
|
||||||
dsprotectpatchv1_stub_protectb1_offset = offsets[offsetIdx++];
|
|
||||||
else
|
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0; // does not exist
|
|
||||||
|
|
||||||
if (_functionMask & 0b000010)
|
// Default invalid, enable below
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = offsets[offsetIdx++];
|
dsprotectpatch_offsetA1 = OFFSET_INVALID;
|
||||||
else
|
dsprotectpatch_offsetNotA1 = OFFSET_INVALID;
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0; // does not exist
|
|
||||||
|
|
||||||
if (_functionMask & 0b000100)
|
|
||||||
dsprotectpatchv1_stub_protectb2_offset = offsets[offsetIdx++];
|
|
||||||
else
|
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0; // does not exist
|
|
||||||
|
|
||||||
if (_functionMask & 0b001000)
|
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = offsets[offsetIdx++];
|
|
||||||
else
|
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0; // does not exist
|
|
||||||
|
|
||||||
if (_functionMask & 0b010000)
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = offsets[offsetIdx++];
|
|
||||||
else
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0; // does not exist
|
|
||||||
|
|
||||||
if (_functionMask & 0b100000)
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = offsets[offsetIdx++];
|
|
||||||
else
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0; // does not exist
|
|
||||||
}
|
|
||||||
|
|
||||||
const void* DSProtectOverlayPatch::InsertPatchV1(PatchContext& patchContext) const
|
|
||||||
{
|
|
||||||
const void* nextPatch = next ? (const void*)next->InsertPatch(patchContext) : nullptr;
|
|
||||||
|
|
||||||
dsprotectpatchv1_overlay_id = _overlayId;
|
|
||||||
dsprotectpatchv1_base_offset = _overlayOffset;
|
|
||||||
|
|
||||||
switch (_version)
|
switch (_version)
|
||||||
{
|
{
|
||||||
|
case DSProtectVersion::v1_00_2:
|
||||||
|
{
|
||||||
|
dsprotectpatch_patchType = PATCH_WRITE_WORD;
|
||||||
|
dsprotectpatch_writeWord = MAGIC_100_102;
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_A1)
|
||||||
|
{
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0xD8;
|
||||||
|
regionOffset += 0xDC; // __DSprot_DetectFlashcart
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_NOTA1)
|
||||||
|
{
|
||||||
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xD8;
|
||||||
|
regionOffset += 0xDC; // __DSprot_DetectNotFlashcart
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DSProtectVersion::v1_05:
|
case DSProtectVersion::v1_05:
|
||||||
{
|
{
|
||||||
static u16 v105Offsets[] = { 0x858, 0x934, 0xA10, 0xAEC, 0xBC8, 0xC94 };
|
dsprotectpatch_patchType = PATCH_WRITE_WORD;
|
||||||
SetOldV1Offsets(v105Offsets);
|
dsprotectpatch_writeWord = MAGIC_105_123;
|
||||||
|
|
||||||
|
regionOffset += 0x24; // setCacheDisabled
|
||||||
|
regionOffset += 0xB4; // Encryptor_StartRange
|
||||||
|
regionOffset += 0xD4; // Encryptor_EndRange
|
||||||
|
regionOffset += 0x74; // RC4_Init
|
||||||
|
regionOffset += 0x4C; // RC4_Byte
|
||||||
|
regionOffset += 0x24; // RC4_InitSBox
|
||||||
|
regionOffset += 0x9C; // RC4_EncryptInstructions
|
||||||
|
regionOffset += 0xC; // RC4_DecryptInstructions
|
||||||
|
regionOffset += 0x58; // RC4_InitAndEncryptInstructions
|
||||||
|
regionOffset += 0x58; // RC4_InitAndDecryptInstructions
|
||||||
|
|
||||||
|
if (_functionMask & (FUNCMASK_A2 | FUNCMASK_NOTA2))
|
||||||
|
{
|
||||||
|
regionOffset += 0x120; // MACOwner_IsBad
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & (FUNCMASK_A1 | FUNCMASK_NOTA1))
|
||||||
|
{
|
||||||
|
regionOffset += 0x19C; // ROMUtil_Read
|
||||||
|
regionOffset += 0xA4; // ROMUtil_CRC32
|
||||||
|
regionOffset += 0x110; // ROMTest_IsBad
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_A1)
|
||||||
|
{
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0xD8;
|
||||||
|
regionOffset += 0xDC; // __DSProt_DetectFlashcart
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_NOTA1)
|
||||||
|
{
|
||||||
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xD8;
|
||||||
|
regionOffset += 0xDC; // __DSprot_DetectNotFlashcart
|
||||||
|
}
|
||||||
|
|
||||||
dsprotectpatchv1_nitro_static_init_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_protectb1_return_value = 0;
|
|
||||||
dsprotectpatchv1_protectb2_return_value = 0;
|
|
||||||
dsprotectpatchv1_protectb3_return_value = 0;
|
|
||||||
dsprotectpatchv1_notprotectb1_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb2_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb3_return_value = 1;
|
|
||||||
// Remove xor 0x320 from the callback pointer
|
|
||||||
dsprotectpatchv1_moveCallback = 0xE230EE32; // eors lr, r0, #0x320
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DSProtectVersion::v1_06:
|
case DSProtectVersion::v1_06:
|
||||||
{
|
{
|
||||||
static u16 v106Offsets[] = { 0x860, 0x938, 0xA10, 0xAE8, 0xBC0, 0xC88 };
|
dsprotectpatch_patchType = PATCH_WRITE_WORD;
|
||||||
SetOldV1Offsets(v106Offsets);
|
dsprotectpatch_writeWord = MAGIC_105_123;
|
||||||
|
|
||||||
|
regionOffset += 0x24; // setCacheDisabled
|
||||||
|
regionOffset += 0xB4; // Encryptor_StartRange
|
||||||
|
regionOffset += 0xD4; // Encryptor_EndRange
|
||||||
|
regionOffset += 0x74; // RC4_Init
|
||||||
|
regionOffset += 0x4C; // RC4_Byte
|
||||||
|
regionOffset += 0x24; // RC4_InitSBox
|
||||||
|
regionOffset += 0x9C; // RC4_EncryptInstructions
|
||||||
|
regionOffset += 0xC; // RC4_DecryptInstructions
|
||||||
|
regionOffset += 0x58; // RC4_InitAndEncryptInstructions
|
||||||
|
regionOffset += 0x58; // RC4_InitAndDecryptInstructions
|
||||||
|
|
||||||
|
if (_functionMask & (FUNCMASK_A2 | FUNCMASK_NOTA2))
|
||||||
|
{
|
||||||
|
regionOffset += 0x120; // MACOwner_IsBad
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & (FUNCMASK_A1 | FUNCMASK_NOTA1))
|
||||||
|
{
|
||||||
|
regionOffset += 0x1A4; // ROMUtil_Read
|
||||||
|
regionOffset += 0xA4; // ROMUtil_CRC32
|
||||||
|
regionOffset += 0x110; // ROMTest_IsBad
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_A1)
|
||||||
|
{
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0xD4;
|
||||||
|
regionOffset += 0xD8; // DSProt_DetectFlashcart
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_NOTA1)
|
||||||
|
{
|
||||||
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xD4;
|
||||||
|
regionOffset += 0xD8; // DSProt_DetectNotFlashcart
|
||||||
|
}
|
||||||
|
|
||||||
dsprotectpatchv1_nitro_static_init_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_protectb1_return_value = 0;
|
|
||||||
dsprotectpatchv1_protectb2_return_value = 0;
|
|
||||||
dsprotectpatchv1_protectb3_return_value = 0;
|
|
||||||
dsprotectpatchv1_notprotectb1_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb2_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb3_return_value = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DSProtectVersion::v1_08:
|
case DSProtectVersion::v1_08:
|
||||||
{
|
{
|
||||||
static u16 v108Offsets[] = { 0x858, 0x930, 0xA08, 0xAE0, 0xBB8, 0xC94 };
|
dsprotectpatch_patchType = PATCH_WRITE_WORD;
|
||||||
SetOldV1Offsets(v108Offsets);
|
dsprotectpatch_writeWord = MAGIC_105_123;
|
||||||
|
|
||||||
|
regionOffset += 0x24; // setCacheDisabled
|
||||||
|
regionOffset += 0xB4; // Encryptor_StartRange
|
||||||
|
regionOffset += 0xD4; // Encryptor_EndRange
|
||||||
|
regionOffset += 0x74; // RC4_Init
|
||||||
|
regionOffset += 0x4C; // RC4_Byte
|
||||||
|
regionOffset += 0x24; // RC4_InitSBox
|
||||||
|
regionOffset += 0x9C; // RC4_EncryptInstructions
|
||||||
|
regionOffset += 0xC; // RC4_DecryptInstructions
|
||||||
|
regionOffset += 0x58; // RC4_InitAndEncryptInstructions
|
||||||
|
regionOffset += 0x58; // RC4_InitAndDecryptInstructions
|
||||||
|
|
||||||
|
if (_functionMask & (FUNCMASK_A2 | FUNCMASK_NOTA2))
|
||||||
|
{
|
||||||
|
regionOffset += 0x120; // MACOwner_IsBad
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & (FUNCMASK_A1 | FUNCMASK_NOTA1))
|
||||||
|
{
|
||||||
|
regionOffset += 0x19C; // ROMUtil_Read
|
||||||
|
regionOffset += 0xA4; // ROMUtil_CRC32
|
||||||
|
regionOffset += 0x110; // ROMTest_IsBad
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_A1)
|
||||||
|
{
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0xD4;
|
||||||
|
regionOffset += 0xD8; // DSProt_DetectFlashcart
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_NOTA1)
|
||||||
|
{
|
||||||
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xD4;
|
||||||
|
regionOffset += 0xD8; // DSProt_DetectNotFlashcart
|
||||||
|
}
|
||||||
|
|
||||||
dsprotectpatchv1_nitro_static_init_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_protectb1_return_value = 0;
|
|
||||||
dsprotectpatchv1_protectb2_return_value = 0;
|
|
||||||
dsprotectpatchv1_protectb3_return_value = 0;
|
|
||||||
dsprotectpatchv1_notprotectb1_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb2_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb3_return_value = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DSProtectVersion::v1_10:
|
case DSProtectVersion::v1_10:
|
||||||
{
|
{
|
||||||
static u16 v110Offsets[] = { 0x860, 0x940, 0xA20, 0xB00, 0xBE0, 0xCB0 };
|
dsprotectpatch_patchType = PATCH_WRITE_WORD;
|
||||||
SetOldV1Offsets(v110Offsets);
|
dsprotectpatch_writeWord = MAGIC_105_123;
|
||||||
|
|
||||||
|
regionOffset += 0xCC; // Encryptor_StartRange
|
||||||
|
regionOffset += 0xE8; // Encryptor_EndRange
|
||||||
|
regionOffset += 0x74; // RC4_Init
|
||||||
|
regionOffset += 0x4C; // RC4_Byte
|
||||||
|
regionOffset += 0x24; // RC4_InitSBox
|
||||||
|
regionOffset += 0x9C; // RC4_EncryptInstructions
|
||||||
|
regionOffset += 0xC; // RC4_DecryptInstructions
|
||||||
|
regionOffset += 0x58; // RC4_InitAndEncryptInstructions
|
||||||
|
regionOffset += 0x58; // RC4_InitAndDecryptInstructions
|
||||||
|
|
||||||
|
if (_functionMask & (FUNCMASK_A2 | FUNCMASK_NOTA2))
|
||||||
|
{
|
||||||
|
regionOffset += 0x120; // MACOwner_IsBad
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & (FUNCMASK_A1 | FUNCMASK_NOTA1))
|
||||||
|
{
|
||||||
|
regionOffset += 0x19C; // ROMUtil_Read
|
||||||
|
regionOffset += 0xA4; // ROMUtil_CRC32
|
||||||
|
regionOffset += 0x110; // ROMTest_IsBad
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_A1)
|
||||||
|
{
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0xD8;
|
||||||
|
regionOffset += 0xE0; // DSProt_DetectFlashcart
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_NOTA1)
|
||||||
|
{
|
||||||
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xD8;
|
||||||
|
regionOffset += 0xE0; // DSProt_DetectNotFlashcart
|
||||||
|
}
|
||||||
|
|
||||||
dsprotectpatchv1_nitro_static_init_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_protectb1_return_value = 0;
|
|
||||||
dsprotectpatchv1_protectb2_return_value = 0;
|
|
||||||
dsprotectpatchv1_protectb3_return_value = 0;
|
|
||||||
dsprotectpatchv1_notprotectb1_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb2_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb3_return_value = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DSProtectVersion::v1_20:
|
case DSProtectVersion::v1_20:
|
||||||
{
|
{
|
||||||
switch (_functionMask)
|
dsprotectpatch_patchType = PATCH_WRITE_WORD;
|
||||||
|
dsprotectpatch_writeWord = MAGIC_105_123;
|
||||||
|
|
||||||
|
regionOffset += 0xC8; // Encryptor_StartRange
|
||||||
|
regionOffset += 0xE4; // Encryptor_EndRange
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_A2)
|
||||||
{
|
{
|
||||||
case 0b001111:
|
regionOffset += 0x118; // MACOwner_IsBad
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x864;
|
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0x94C;
|
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0xA34;
|
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0xB1C;
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0; // does not exist
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0b010101:
|
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x644;
|
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0x72C;
|
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0x814;
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0; // does not exist
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0b010110:
|
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0x644;
|
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0x72C;
|
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0x814;
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0; // does not exist
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0b011001:
|
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x644;
|
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0;
|
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0x72C;
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0x814;
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0; // does not exist
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0b110101:
|
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x644;
|
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0x72C;
|
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0x814;
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0x8DC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0b111111:
|
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x864;
|
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0x94C;
|
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0xA34;
|
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0xB1C;
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0xC04;
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0xCCC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
LOG_WARNING("Unsupported DSProtect function mask\n");
|
|
||||||
return nextPatch;
|
|
||||||
}
|
}
|
||||||
dsprotectpatchv1_nitro_static_init_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_protectb1_return_value = 0;
|
if (_functionMask & FUNCMASK_NOTA2)
|
||||||
dsprotectpatchv1_protectb2_return_value = 0;
|
{
|
||||||
dsprotectpatchv1_protectb3_return_value = 0;
|
regionOffset += 0x118; // MACOwner_IsGood
|
||||||
dsprotectpatchv1_notprotectb1_return_value = 1;
|
}
|
||||||
dsprotectpatchv1_notprotectb2_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb3_return_value = 1;
|
if (_functionMask & (FUNCMASK_A1 | FUNCMASK_NOTA1))
|
||||||
|
{
|
||||||
|
regionOffset += 0x1D4; // ROMUtil_Read
|
||||||
|
regionOffset += 0xA4; // ROMUtil_CRC32
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_A1)
|
||||||
|
{
|
||||||
|
regionOffset += 0x108; // ROMTest_IsBad
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_NOTA1)
|
||||||
|
{
|
||||||
|
regionOffset += 0x108; // ROMTest_IsGood
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_A1)
|
||||||
|
{
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0xE0;
|
||||||
|
regionOffset += 0xE8; // DSProt_DetectFlashcart
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_NOTA1)
|
||||||
|
{
|
||||||
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xE0;
|
||||||
|
regionOffset += 0xE8; // DSProt_DetectNotFlashcart
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DSProtectVersion::v1_22:
|
case DSProtectVersion::v1_22:
|
||||||
{
|
{
|
||||||
switch (_functionMask)
|
dsprotectpatch_patchType = PATCH_WRITE_WORD;
|
||||||
|
dsprotectpatch_writeWord = MAGIC_105_123;
|
||||||
|
|
||||||
|
regionOffset += 0xC8; // Encryptor_StartRange
|
||||||
|
regionOffset += 0xE4; // Encryptor_EndRange
|
||||||
|
|
||||||
|
if (_functionMask & FUNCMASK_A2)
|
||||||
{
|
{
|
||||||
case 0b010101:
|
regionOffset += 0x120; // MACOwner_IsBad
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x64C;
|
}
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0x734;
|
if (_functionMask & FUNCMASK_NOTA2)
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0; // does not exist
|
{
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0x81C;
|
regionOffset += 0x120; // MACOwner_IsGood
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0; // does not exist
|
}
|
||||||
break;
|
|
||||||
|
if (_functionMask & (FUNCMASK_A1 | FUNCMASK_NOTA1))
|
||||||
case 0b010110:
|
{
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0; // does not exist
|
regionOffset += 0x1D4; // ROMUtil_Read
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0x64C;
|
regionOffset += 0xA4; // ROMUtil_CRC32
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0x734;
|
}
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0x81C;
|
if (_functionMask & FUNCMASK_A1)
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0; // does not exist
|
{
|
||||||
break;
|
regionOffset += 0x108; // ROMTest_IsBad
|
||||||
|
}
|
||||||
case 0b010111:
|
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x754;
|
if (_functionMask & FUNCMASK_NOTA1)
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0x83C;
|
{
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0x924;
|
regionOffset += 0x108; // ROMTest_IsGood
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0; // does not exist
|
}
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0xA0C;
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0; // does not exist
|
if (_functionMask & FUNCMASK_A1)
|
||||||
break;
|
{
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0xE0;
|
||||||
case 0b011111:
|
regionOffset += 0xE8; // DSProt_DetectFlashcart
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x874;
|
}
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0x95C;
|
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0xA44;
|
if (_functionMask & FUNCMASK_NOTA1)
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0xB2C;
|
{
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0xC14;
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xE0;
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0; // does not exist
|
regionOffset += 0xE8; // DSProt_DetectNotFlashcart
|
||||||
break;
|
|
||||||
|
|
||||||
case 0b111111:
|
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x874;
|
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0x95C;
|
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0xA44;
|
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0xB2C;
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0xC14;
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0xCDC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
LOG_WARNING("Unsupported DSProtect function mask\n");
|
|
||||||
return nextPatch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dsprotectpatchv1_nitro_static_init_offset = 0; // does not exist
|
|
||||||
dsprotectpatchv1_protectb1_return_value = 0;
|
|
||||||
dsprotectpatchv1_protectb2_return_value = 0;
|
|
||||||
dsprotectpatchv1_protectb3_return_value = 0;
|
|
||||||
dsprotectpatchv1_notprotectb1_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb2_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb3_return_value = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DSProtectVersion::v1_23:
|
case DSProtectVersion::v1_23:
|
||||||
case DSProtectVersion::v1_23Z:
|
case DSProtectVersion::v1_23Z:
|
||||||
{
|
{
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x410;
|
dsprotectpatch_patchType = PATCH_WRITE_WORD;
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0x500;
|
dsprotectpatch_writeWord = MAGIC_105_123;
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0x5F0;
|
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0x488;
|
dsprotectpatch_offsetA1 = regionOffset + 0x0 + 0xAC;
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0x578;
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xB8 + 0xAC;
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0x668;
|
|
||||||
// this seems to be a decrypt function that is called from 5 static init functions
|
|
||||||
dsprotectpatchv1_nitro_static_init_offset = 0xD78;
|
|
||||||
dsprotectpatchv1_protectb1_return_value = 0;
|
|
||||||
dsprotectpatchv1_protectb2_return_value = 0;
|
|
||||||
dsprotectpatchv1_protectb3_return_value = 0;
|
|
||||||
dsprotectpatchv1_notprotectb1_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb2_return_value = 1;
|
|
||||||
dsprotectpatchv1_notprotectb3_return_value = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DSProtectVersion::v1_25:
|
case DSProtectVersion::v1_25:
|
||||||
|
{
|
||||||
|
dsprotectpatch_patchType = PATCH_COPY_NEXT;
|
||||||
|
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0x0 + 0x90;
|
||||||
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xA4 +0x9C;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DSProtectVersion::v1_26:
|
case DSProtectVersion::v1_26:
|
||||||
{
|
{
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x3DC;
|
dsprotectpatch_patchType = PATCH_COPY_NEXT;
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0x4CC;
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0x5BC;
|
dsprotectpatch_offsetA1 = regionOffset + 0x0 + 0x90;
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0x454;
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xA4 + 0x9C;
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0x544;
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0x634;
|
|
||||||
dsprotectpatchv1_nitro_static_init_offset = 0x6AC;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DSProtectVersion::v1_27:
|
case DSProtectVersion::v1_27:
|
||||||
{
|
{
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x3A0;
|
dsprotectpatch_patchType = PATCH_COPY_NEXT;
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0x418;
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0x490;
|
dsprotectpatch_offsetA1 = regionOffset + 0x0 + 0x8C;
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0x3DC;
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xA0 + 0x8C;
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0x454;
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0x4CC;
|
|
||||||
dsprotectpatchv1_nitro_static_init_offset = 0x508;
|
|
||||||
dsprotectpatchv1_loadReturnValue = 0; // Return the return value of the callback
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DSProtectVersion::v1_28:
|
case DSProtectVersion::v1_28:
|
||||||
{
|
{
|
||||||
dsprotectpatchv1_stub_protectb1_offset = 0x3A0;
|
dsprotectpatch_patchType = PATCH_COPY_NEXT;
|
||||||
dsprotectpatchv1_stub_protectb2_offset = 0x418;
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset = 0x490;
|
dsprotectpatch_offsetA1 = regionOffset + 0x0 + 0x8C;
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset = 0x3DC;
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xA0 + 0x8C;
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset = 0x454;
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset = 0x4CC;
|
break;
|
||||||
dsprotectpatchv1_nitro_static_init_offset = 0x508;
|
}
|
||||||
dsprotectpatchv1_loadReturnValue = 0; // Return the return value of the callback
|
case DSProtectVersion::v2_00:
|
||||||
|
{
|
||||||
|
dsprotectpatch_patchType = PATCH_COPY_NEXT;
|
||||||
|
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0x0 + 0x188;
|
||||||
|
dsprotectpatch_offsetNotA1 = regionOffset + 0x19C + 0x188;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DSProtectVersion::v2_01:
|
||||||
|
{
|
||||||
|
dsprotectpatch_patchType = PATCH_COPY_NEXT;
|
||||||
|
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0xAB0 + 0x188;
|
||||||
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xC4C + 0x188;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DSProtectVersion::v2_03:
|
||||||
|
{
|
||||||
|
dsprotectpatch_patchType = PATCH_COPY_NEXT;
|
||||||
|
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0xC1C + 0x18C;
|
||||||
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xDBC + 0x18C;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DSProtectVersion::v2_05:
|
||||||
|
{
|
||||||
|
dsprotectpatch_patchType = PATCH_COPY_NEXT;
|
||||||
|
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0xCAC + 0x18C;
|
||||||
|
dsprotectpatch_offsetNotA1 = regionOffset + 0xE4C + 0x18C;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Instant versions
|
||||||
|
case DSProtectVersion::v2_00s:
|
||||||
|
{
|
||||||
|
dsprotectpatch_patchType = PATCH_WRITE_WORD;
|
||||||
|
dsprotectpatch_writeWord = MAGIC_200s_205s;
|
||||||
|
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0x94 + 0x118;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DSProtectVersion::v2_01s:
|
||||||
|
{
|
||||||
|
dsprotectpatch_patchType = PATCH_WRITE_WORD;
|
||||||
|
dsprotectpatch_writeWord = MAGIC_200s_205s;
|
||||||
|
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0x94 + 0x118;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DSProtectVersion::v2_03s:
|
||||||
|
{
|
||||||
|
dsprotectpatch_patchType = PATCH_WRITE_WORD;
|
||||||
|
dsprotectpatch_writeWord = MAGIC_200s_205s;
|
||||||
|
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0xE0 + 0x118;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DSProtectVersion::v2_05s:
|
||||||
|
{
|
||||||
|
dsprotectpatch_patchType = PATCH_WRITE_WORD;
|
||||||
|
dsprotectpatch_writeWord = MAGIC_200s_205s;
|
||||||
|
|
||||||
|
dsprotectpatch_offsetA1 = regionOffset + 0x104 + 0x118;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
LOG_WARNING("Unsupported DSProtect version\n");
|
LOG_WARNING("Unsupported DSProtect version\n");
|
||||||
return nextPatch;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dsprotectpatchv1_nextAddress = (u32)nextPatch;
|
|
||||||
|
|
||||||
u32 patch1Size = SECTION_SIZE(dsprotectpatchv1_part1);
|
|
||||||
void* patch1Address = patchContext.GetPatchHeap().Alloc(patch1Size);
|
|
||||||
u32 patch2Size = SECTION_SIZE(dsprotectpatchv1_part2);
|
|
||||||
void* patch2Address = patchContext.GetPatchHeap().Alloc(patch2Size);
|
|
||||||
|
|
||||||
dsprotectpatchv1_part2_address = (u32)&dsprotectpatchv1_entry2 - (u32)SECTION_START(dsprotectpatchv1_part2) + (u32)patch2Address;
|
|
||||||
|
|
||||||
u32 entryAddress1 = (u32)&dsprotectpatchv1_entry1 - (u32)SECTION_START(dsprotectpatchv1_part1) + (u32)patch1Address;
|
|
||||||
memcpy(patch1Address, SECTION_START(dsprotectpatchv1_part1), patch1Size);
|
|
||||||
memcpy(patch2Address, SECTION_START(dsprotectpatchv1_part2), patch2Size);
|
|
||||||
|
|
||||||
return (const void*)entryAddress1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ds_protect_v2_patch_t
|
|
||||||
{
|
|
||||||
u32 checksumFix;
|
|
||||||
u16 stubProtectb1Offset;
|
|
||||||
u16 stubProtectb2Offset;
|
|
||||||
u16 stubProtectb3Offset;
|
|
||||||
u16 stubProtectb4Offset;
|
|
||||||
u16 amInitOffset;
|
|
||||||
u16 storeChecksumFix;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const ds_protect_v2_patch_t sDSProtectV2Patches[] =
|
|
||||||
{
|
|
||||||
{ 0x7CDBA8BD, 0x670, 0x6AC, 0x6E8, 0x724, 0x760, THUMB_STR_IMM(THUMB_R7, THUMB_R0, 0) }, // v2.00
|
|
||||||
{ 0xA6FD7CE1, 0x1120, 0x115C, 0x1198, 0x11D4, 0x1210, THUMB_STR_IMM(THUMB_R7, THUMB_R0, 0) }, // v2.01
|
|
||||||
{ 0x45C535B6, 0x129C, 0x1324, 0x13AC, 0x1434, 0x14BC, THUMB_STR_IMM(THUMB_R7, THUMB_R0, 0) }, // v2.03
|
|
||||||
{ 0x32E120D5, 0x132C, 0x13D8, 0x1484, 0x1530, 0x15DC, THUMB_STR_IMM(THUMB_R7, THUMB_R0, 8) }, // v2.05
|
|
||||||
};
|
|
||||||
|
|
||||||
const void* DSProtectOverlayPatch::InsertPatchV2(PatchContext& patchContext) const
|
|
||||||
{
|
|
||||||
dsprotectpatchv2_nextAddress = next ? (u32)next->InsertPatch(patchContext) : 0u;
|
|
||||||
dsprotectpatchv2_overlay_id = _overlayId;
|
|
||||||
dsprotectpatchv2_base_offset = _overlayOffset;
|
|
||||||
|
|
||||||
const auto& patch = sDSProtectV2Patches[(u32)_version - (u32)DSProtectVersion::v2_00];
|
|
||||||
dsprotectpatchv2_checksum_fix = patch.checksumFix;
|
|
||||||
dsprotectpatchv2_stub_protectb1_offset = patch.stubProtectb1Offset;
|
|
||||||
dsprotectpatchv2_stub_protectb2_offset = patch.stubProtectb2Offset;
|
|
||||||
dsprotectpatchv2_stub_protectb3_offset = patch.stubProtectb3Offset;
|
|
||||||
dsprotectpatchv2_stub_protectb4_offset = patch.stubProtectb4Offset;
|
|
||||||
dsprotectpatchv2_am_init_offset = patch.amInitOffset;
|
|
||||||
dsprotectpatchv2_store_checksum_fix = patch.storeChecksumFix;
|
|
||||||
|
|
||||||
u32 patchSize = SECTION_SIZE(dsprotectpatchv2);
|
|
||||||
void* patchAddress = patchContext.GetPatchHeap().Alloc(patchSize);
|
|
||||||
|
|
||||||
u32 entryAddress = (u32)&dsprotectpatchv2_entry - (u32)SECTION_START(dsprotectpatchv2) + (u32)patchAddress;
|
|
||||||
memcpy(patchAddress, SECTION_START(dsprotectpatchv2), patchSize);
|
|
||||||
|
|
||||||
return (const void*)entryAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ds_protect_v2s_patch_t
|
|
||||||
{
|
|
||||||
u32 checksumFix;
|
|
||||||
u16 instantDetectOffset;
|
|
||||||
u16 storeChecksumFix;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const ds_protect_v2s_patch_t sDSProtectV2sPatches[] =
|
|
||||||
{
|
|
||||||
{ 0xEDEA7F01, 0x1BC, THUMB_STR_IMM(THUMB_R7, THUMB_R0, 0) }, // v2.00s
|
|
||||||
{ 0xEDEA7F1F, 0x1BC, THUMB_STR_IMM(THUMB_R7, THUMB_R0, 0) }, // v2.01s
|
|
||||||
{ 0x167325AA, 0x20C, THUMB_STR_IMM(THUMB_R7, THUMB_R0, 0) }, // v2.03s
|
|
||||||
{ 0x32E120D5, 0x230, THUMB_STR_IMM(THUMB_R7, THUMB_R0, 4) } // v2.05s
|
|
||||||
};
|
|
||||||
|
|
||||||
const void* DSProtectOverlayPatch::InsertPatchV2s(PatchContext& patchContext) const
|
|
||||||
{
|
|
||||||
dsprotectpatchv2s_nextAddress = next ? (u32)next->InsertPatch(patchContext) : 0u;
|
|
||||||
dsprotectpatchv2s_overlay_id = _overlayId;
|
|
||||||
|
|
||||||
const auto& patch = sDSProtectV2sPatches[(u32)_version - (u32)DSProtectVersion::v2_00s];
|
|
||||||
dsprotectpatchv2s_checksum_fix = patch.checksumFix;
|
|
||||||
dsprotectpatchv2s_stub_instantdetect_offset = patch.instantDetectOffset + _overlayOffset;
|
|
||||||
dsprotectpatchv2s_store_checksum_fix = patch.storeChecksumFix;
|
|
||||||
|
|
||||||
u32 patchSize = SECTION_SIZE(dsprotectpatchv2s);
|
|
||||||
void* patchAddress = patchContext.GetPatchHeap().Alloc(patchSize);
|
|
||||||
u32 entryAddress = (u32)&dsprotectpatchv2s_entry - (u32)SECTION_START(dsprotectpatchv2s) + (u32)patchAddress;
|
|
||||||
memcpy(patchAddress, SECTION_START(dsprotectpatchv2s), patchSize);
|
|
||||||
|
|
||||||
return (const void*)entryAddress;
|
|
||||||
}
|
|
||||||
@@ -17,8 +17,5 @@ private:
|
|||||||
DSProtectVersion _version;
|
DSProtectVersion _version;
|
||||||
u32 _functionMask;
|
u32 _functionMask;
|
||||||
|
|
||||||
void SetOldV1Offsets(const u16* offsets) const;
|
void ConfigurePatch(PatchContext& patchContext) const;
|
||||||
const void* InsertPatchV1(PatchContext& patchContext) const;
|
|
||||||
const void* InsertPatchV2(PatchContext& patchContext) const;
|
|
||||||
const void* InsertPatchV2s(PatchContext& patchContext) const;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "sections.h"
|
||||||
|
|
||||||
|
DEFINE_SECTION_SYMBOLS(dsprotectpatch);
|
||||||
|
|
||||||
|
extern "C" void dsprotectpatch_entry();
|
||||||
|
|
||||||
|
extern u32 dsprotectpatch_patchType; // 0=write dsprotectpatch_writeWord, 1=copy subsequent word
|
||||||
|
extern u32 dsprotectpatch_writeWord; // Word to write if dsprotectpatch_patchType=0
|
||||||
|
extern u32 dsprotectpatch_offsetA1; // Target offset for A1 (0xFFFFFFFF=invalid)
|
||||||
|
extern u32 dsprotectpatch_offsetNotA1; // Target offset for NotA1 (0xFFFFFFFF=invalid)
|
||||||
|
|
||||||
|
extern u32 dsprotectpatch_overlayId; // Target overlay ID
|
||||||
|
extern const void* dsprotectpatch_nextAddress; // Next patch address
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
.cpu arm946e-s
|
||||||
|
.syntax unified
|
||||||
|
.section "dsprotectpatch", "ax"
|
||||||
|
.thumb
|
||||||
|
|
||||||
|
.global dsprotectpatch_entry
|
||||||
|
.type dsprotectpatch_entry, %function
|
||||||
|
dsprotectpatch_entry:
|
||||||
|
push {r4-r7, lr}
|
||||||
|
|
||||||
|
// r5 is overlay table entry-- load { ovy_id, ram_start }
|
||||||
|
ldmia r5!, {r6, r7}
|
||||||
|
|
||||||
|
// Bail if this is the wrong overlay
|
||||||
|
ldr r4, dsprotectpatch_overlayId
|
||||||
|
cmp r4, r6
|
||||||
|
bne continue_to_next
|
||||||
|
|
||||||
|
// Try to patch A1
|
||||||
|
ldr r0, dsprotectpatch_offsetA1
|
||||||
|
adds r0, r7
|
||||||
|
bl try_apply_patch
|
||||||
|
|
||||||
|
// Try to patch NotA1
|
||||||
|
ldr r0, dsprotectpatch_offsetNotA1
|
||||||
|
adds r0, r7
|
||||||
|
bl try_apply_patch
|
||||||
|
|
||||||
|
continue_to_next:
|
||||||
|
// Return next patch address
|
||||||
|
ldr r0, dsprotectpatch_nextAddress
|
||||||
|
pop {r4-r7, pc}
|
||||||
|
|
||||||
|
.local try_apply_patch
|
||||||
|
.type try_apply_patch, %function
|
||||||
|
try_apply_patch:
|
||||||
|
// If the high bit is set, this is invalid and we skip it
|
||||||
|
cmp r0, #0x0
|
||||||
|
blt offset_invalid
|
||||||
|
|
||||||
|
// Check what patch type to use
|
||||||
|
ldr r1, dsprotectpatch_patchType
|
||||||
|
cmp r1, #0x0
|
||||||
|
beq load_literal
|
||||||
|
|
||||||
|
// Load next word (+4)
|
||||||
|
ldr r2, [r0, #0x4]
|
||||||
|
b load_done
|
||||||
|
|
||||||
|
load_literal:
|
||||||
|
// Load literal value
|
||||||
|
ldr r2, dsprotectpatch_writeWord
|
||||||
|
|
||||||
|
load_done:
|
||||||
|
// Write to patch location
|
||||||
|
str r2, [r0]
|
||||||
|
|
||||||
|
offset_invalid:
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.balign 4
|
||||||
|
|
||||||
|
.global dsprotectpatch_writeWord
|
||||||
|
dsprotectpatch_writeWord:
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
.global dsprotectpatch_patchType
|
||||||
|
dsprotectpatch_patchType:
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
.global dsprotectpatch_offsetA1
|
||||||
|
dsprotectpatch_offsetA1:
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
.global dsprotectpatch_offsetNotA1
|
||||||
|
dsprotectpatch_offsetNotA1:
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
.global dsprotectpatch_overlayId
|
||||||
|
dsprotectpatch_overlayId:
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
.global dsprotectpatch_nextAddress
|
||||||
|
dsprotectpatch_nextAddress:
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
.pool
|
||||||
|
|
||||||
|
.end
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "sections.h"
|
|
||||||
|
|
||||||
DEFINE_SECTION_SYMBOLS(dsprotectpatchv1_part1);
|
|
||||||
extern "C" void dsprotectpatchv1_entry1();
|
|
||||||
extern u16 dsprotectpatchv1_stub_protectb1_offset;
|
|
||||||
extern u16 dsprotectpatchv1_stub_protectb2_offset;
|
|
||||||
extern u16 dsprotectpatchv1_stub_protectb3_offset;
|
|
||||||
extern u16 dsprotectpatchv1_nitro_static_init_offset;
|
|
||||||
extern u16 dsprotectpatchv1_overlay_id;
|
|
||||||
extern u32 dsprotectpatchv1_base_offset;
|
|
||||||
extern u32 dsprotectpatchv1_part2_address;
|
|
||||||
extern u32 dsprotectpatchv1_protectb1_return_value;
|
|
||||||
extern u32 dsprotectpatchv1_protectb2_return_value;
|
|
||||||
extern u32 dsprotectpatchv1_protectb3_return_value;
|
|
||||||
|
|
||||||
DEFINE_SECTION_SYMBOLS(dsprotectpatchv1_part2);
|
|
||||||
extern "C" void dsprotectpatchv1_entry2();
|
|
||||||
extern u16 dsprotectpatchv1_stub_notprotectb1_offset;
|
|
||||||
extern u16 dsprotectpatchv1_stub_notprotectb2_offset;
|
|
||||||
extern u16 dsprotectpatchv1_stub_notprotectb3_offset;
|
|
||||||
extern u32 dsprotectpatchv1_nextAddress;
|
|
||||||
extern u32 dsprotectpatchv1_notprotectb1_return_value;
|
|
||||||
extern u32 dsprotectpatchv1_notprotectb2_return_value;
|
|
||||||
extern u32 dsprotectpatchv1_notprotectb3_return_value;
|
|
||||||
extern u32 dsprotectpatchv1_loadReturnValue;
|
|
||||||
extern u32 dsprotectpatchv1_moveCallback;
|
|
||||||
@@ -1,168 +0,0 @@
|
|||||||
.cpu arm946e-s
|
|
||||||
.syntax unified
|
|
||||||
.section "dsprotectpatchv1_part1", "ax"
|
|
||||||
|
|
||||||
.thumb
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_entry1
|
|
||||||
.type dsprotectpatchv1_entry1, %function
|
|
||||||
dsprotectpatchv1_entry1:
|
|
||||||
push {r4-r7,lr}
|
|
||||||
adr r0, dsprotectpatchv1_stub_protectb1_offset
|
|
||||||
ldrh r4, [r0, #(dsprotectpatchv1_overlay_id - dsprotectpatchv1_stub_protectb1_offset)]
|
|
||||||
ldmia r5!, {r1, r2} // id, ram address
|
|
||||||
cmp r1, r4
|
|
||||||
bne continue_to_next
|
|
||||||
|
|
||||||
ldr r4, dsprotectpatchv1_base_offset
|
|
||||||
adds r2, r4 // add base offset to overlay address
|
|
||||||
|
|
||||||
ldrh r4, [r0, #(dsprotectpatchv1_nitro_static_init_offset - dsprotectpatchv1_stub_protectb1_offset)]
|
|
||||||
ldr r3,= 0xE12FFF1E // bx lr
|
|
||||||
str r3, [r4, r2]
|
|
||||||
|
|
||||||
adr r4, protectbX_patch
|
|
||||||
ldmia r4!, {r5,r6}
|
|
||||||
|
|
||||||
adds r3, r0, #(dsprotectpatchv1_nitro_static_init_offset - dsprotectpatchv1_stub_protectb1_offset)
|
|
||||||
1:
|
|
||||||
ldmia r4!, {r7}
|
|
||||||
ldrh r1, [r0]
|
|
||||||
adds r1, r2
|
|
||||||
stmia r1!, {r5,r6,r7}
|
|
||||||
adds r0, #2
|
|
||||||
cmp r0, r3
|
|
||||||
bne 1b
|
|
||||||
|
|
||||||
ldr r7, dsprotectpatchv1_part2_address
|
|
||||||
bx r7
|
|
||||||
|
|
||||||
continue_to_next:
|
|
||||||
ldr r7, dsprotectpatchv1_part2_address
|
|
||||||
adds r7, #(dsprotectpatchv1_continue_to_next - dsprotectpatchv1_entry2)
|
|
||||||
bx r7
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_stub_protectb1_offset
|
|
||||||
dsprotectpatchv1_stub_protectb1_offset:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_stub_protectb2_offset
|
|
||||||
dsprotectpatchv1_stub_protectb2_offset:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_stub_protectb3_offset
|
|
||||||
dsprotectpatchv1_stub_protectb3_offset:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_nitro_static_init_offset
|
|
||||||
dsprotectpatchv1_nitro_static_init_offset:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_overlay_id
|
|
||||||
dsprotectpatchv1_overlay_id:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.balign 4
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_base_offset
|
|
||||||
dsprotectpatchv1_base_offset:
|
|
||||||
.word 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_part2_address
|
|
||||||
dsprotectpatchv1_part2_address:
|
|
||||||
.word 0
|
|
||||||
|
|
||||||
.pool
|
|
||||||
|
|
||||||
.arm
|
|
||||||
protectbX_patch:
|
|
||||||
ldr r0, dsprotectpatchv1_protectb1_return_value
|
|
||||||
bx lr
|
|
||||||
.global dsprotectpatchv1_protectb1_return_value
|
|
||||||
dsprotectpatchv1_protectb1_return_value:
|
|
||||||
.word 1830601
|
|
||||||
.global dsprotectpatchv1_protectb2_return_value
|
|
||||||
dsprotectpatchv1_protectb2_return_value:
|
|
||||||
.word 1830203
|
|
||||||
.global dsprotectpatchv1_protectb3_return_value
|
|
||||||
dsprotectpatchv1_protectb3_return_value:
|
|
||||||
.word 1828014
|
|
||||||
|
|
||||||
.section "dsprotectpatchv1_part2", "ax"
|
|
||||||
|
|
||||||
.thumb
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_entry2
|
|
||||||
.type dsprotectpatchv1_entry2, %function
|
|
||||||
dsprotectpatchv1_entry2:
|
|
||||||
adr r0, dsprotectpatchv1_stub_notprotectb1_offset
|
|
||||||
adds r1, r0, #(dsprotectpatchv1_stub_notprotectb3_offset - dsprotectpatchv1_stub_notprotectb1_offset + 2)
|
|
||||||
mov lr, r1
|
|
||||||
2:
|
|
||||||
ldrh r1, [r0]
|
|
||||||
adds r1, r2
|
|
||||||
adr r3, notprotectbX_patch
|
|
||||||
ldmia r3!, {r4,r5,r6,r7}
|
|
||||||
stmia r1!, {r4,r5,r6,r7}
|
|
||||||
ldmia r3!, {r4,r5,r6}
|
|
||||||
stmia r1!, {r4,r5,r6}
|
|
||||||
adds r0, #2
|
|
||||||
cmp r0, lr
|
|
||||||
bne 2b
|
|
||||||
|
|
||||||
ldmia r3!, {r6,r7}
|
|
||||||
|
|
||||||
adds r2, #0x18
|
|
||||||
adr r0, dsprotectpatchv1_stub_notprotectb1_offset
|
|
||||||
ldrh r1, [r0, #(dsprotectpatchv1_stub_notprotectb2_offset - dsprotectpatchv1_stub_notprotectb1_offset)]
|
|
||||||
str r6, [r1, r2]
|
|
||||||
ldrh r1, [r0, #(dsprotectpatchv1_stub_notprotectb3_offset - dsprotectpatchv1_stub_notprotectb1_offset)]
|
|
||||||
str r7, [r1, r2]
|
|
||||||
|
|
||||||
dsprotectpatchv1_continue_to_next:
|
|
||||||
ldr r0, dsprotectpatchv1_nextAddress
|
|
||||||
pop {r4-r7,pc}
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_stub_notprotectb1_offset
|
|
||||||
dsprotectpatchv1_stub_notprotectb1_offset:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_stub_notprotectb2_offset
|
|
||||||
dsprotectpatchv1_stub_notprotectb2_offset:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_stub_notprotectb3_offset
|
|
||||||
dsprotectpatchv1_stub_notprotectb3_offset:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.balign 4
|
|
||||||
|
|
||||||
.global dsprotectpatchv1_nextAddress
|
|
||||||
dsprotectpatchv1_nextAddress:
|
|
||||||
.word 0
|
|
||||||
|
|
||||||
.pool
|
|
||||||
|
|
||||||
.arm
|
|
||||||
notprotectbX_patch:
|
|
||||||
push {lr}
|
|
||||||
.global dsprotectpatchv1_moveCallback
|
|
||||||
dsprotectpatchv1_moveCallback:
|
|
||||||
movs lr, r0
|
|
||||||
movne r0, r1
|
|
||||||
blxne lr
|
|
||||||
.global dsprotectpatchv1_loadReturnValue
|
|
||||||
dsprotectpatchv1_loadReturnValue:
|
|
||||||
ldr r0, dsprotectpatchv1_notprotectb1_return_value
|
|
||||||
pop {pc}
|
|
||||||
.global dsprotectpatchv1_notprotectb1_return_value
|
|
||||||
dsprotectpatchv1_notprotectb1_return_value:
|
|
||||||
.word 1831551
|
|
||||||
.global dsprotectpatchv1_notprotectb2_return_value
|
|
||||||
dsprotectpatchv1_notprotectb2_return_value:
|
|
||||||
.word 1830859
|
|
||||||
.global dsprotectpatchv1_notprotectb3_return_value
|
|
||||||
dsprotectpatchv1_notprotectb3_return_value:
|
|
||||||
.word 1829648
|
|
||||||
|
|
||||||
.end
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "sections.h"
|
|
||||||
|
|
||||||
DEFINE_SECTION_SYMBOLS(dsprotectpatchv2);
|
|
||||||
|
|
||||||
extern "C" void dsprotectpatchv2_entry();
|
|
||||||
extern u16 dsprotectpatchv2_stub_protectb1_offset;
|
|
||||||
extern u16 dsprotectpatchv2_stub_protectb2_offset;
|
|
||||||
extern u16 dsprotectpatchv2_stub_protectb3_offset;
|
|
||||||
extern u16 dsprotectpatchv2_stub_protectb4_offset;
|
|
||||||
extern u16 dsprotectpatchv2_am_init_offset;
|
|
||||||
extern u16 dsprotectpatchv2_overlay_id;
|
|
||||||
extern u32 dsprotectpatchv2_nextAddress;
|
|
||||||
extern u32 dsprotectpatchv2_checksum_fix;
|
|
||||||
extern u32 dsprotectpatchv2_base_offset;
|
|
||||||
|
|
||||||
extern u16 dsprotectpatchv2_store_checksum_fix;
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
.cpu arm946e-s
|
|
||||||
.section "dsprotectpatchv2", "ax"
|
|
||||||
.syntax unified
|
|
||||||
.thumb
|
|
||||||
|
|
||||||
.global dsprotectpatchv2_entry
|
|
||||||
.type dsprotectpatchv2_entry, %function
|
|
||||||
dsprotectpatchv2_entry:
|
|
||||||
push {r4-r7,lr}
|
|
||||||
|
|
||||||
ldmia r5!, {r0,r1,r2}
|
|
||||||
adds r3, r2, r1 // bss address
|
|
||||||
|
|
||||||
adr r2, dsprotectpatchv2_stub_protectb1_offset
|
|
||||||
ldrh r7, [r2, #(dsprotectpatchv2_overlay_id - dsprotectpatchv2_stub_protectb1_offset)]
|
|
||||||
cmp r0, r7
|
|
||||||
bne continue_to_next
|
|
||||||
|
|
||||||
ldr r7, [r2, #(dsprotectpatchv2_base_offset - dsprotectpatchv2_stub_protectb1_offset)]
|
|
||||||
adds r1, r7 // add base offset to overlay address
|
|
||||||
|
|
||||||
ldrh r0, [r2, #(dsprotectpatchv2_am_init_offset - dsprotectpatchv2_stub_protectb1_offset)]
|
|
||||||
ldr r7,= 0xE12FFF1E // bx lr
|
|
||||||
str r7, [r1, r0]
|
|
||||||
|
|
||||||
adr r0, stub_patch_code
|
|
||||||
ldmia r0!, {r4,r5,r6,r7}
|
|
||||||
|
|
||||||
subs r1, #4 // write from 4 bytes before the actual function address
|
|
||||||
adds r0, r2, #(dsprotectpatchv2_stub_protectb4_offset - dsprotectpatchv2_stub_protectb1_offset)
|
|
||||||
mov lr, r0
|
|
||||||
patch_loop:
|
|
||||||
ldrh r0, [r2]
|
|
||||||
adds r2, #2
|
|
||||||
adds r0, r1
|
|
||||||
stmia r0!, {r3,r4,r5,r6} // bss address + code
|
|
||||||
.global dsprotectpatchv2_store_checksum_fix
|
|
||||||
dsprotectpatchv2_store_checksum_fix:
|
|
||||||
str r7, [r0, #0] // checksum fix
|
|
||||||
cmp r2, lr
|
|
||||||
ble patch_loop
|
|
||||||
|
|
||||||
continue_to_next:
|
|
||||||
ldr r0, dsprotectpatchv2_nextAddress
|
|
||||||
pop {r4-r7,pc}
|
|
||||||
|
|
||||||
.balign 4
|
|
||||||
|
|
||||||
.global dsprotectpatchv2_stub_protectb1_offset
|
|
||||||
dsprotectpatchv2_stub_protectb1_offset:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv2_stub_protectb2_offset
|
|
||||||
dsprotectpatchv2_stub_protectb2_offset:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv2_stub_protectb3_offset
|
|
||||||
dsprotectpatchv2_stub_protectb3_offset:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv2_stub_protectb4_offset
|
|
||||||
dsprotectpatchv2_stub_protectb4_offset:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv2_am_init_offset
|
|
||||||
dsprotectpatchv2_am_init_offset:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv2_overlay_id
|
|
||||||
dsprotectpatchv2_overlay_id:
|
|
||||||
.short 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv2_base_offset
|
|
||||||
dsprotectpatchv2_base_offset:
|
|
||||||
.word 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv2_nextAddress
|
|
||||||
dsprotectpatchv2_nextAddress:
|
|
||||||
.word 0
|
|
||||||
|
|
||||||
.pool
|
|
||||||
|
|
||||||
.arm
|
|
||||||
stub_patch_code:
|
|
||||||
ldr r12, (. - 4)
|
|
||||||
ldr r2, [r12], #4
|
|
||||||
ldr pc, [r12, r2, lsl #2]
|
|
||||||
|
|
||||||
.global dsprotectpatchv2_checksum_fix
|
|
||||||
dsprotectpatchv2_checksum_fix:
|
|
||||||
.word 0
|
|
||||||
|
|
||||||
.end
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "sections.h"
|
|
||||||
|
|
||||||
DEFINE_SECTION_SYMBOLS(dsprotectpatchv2s);
|
|
||||||
|
|
||||||
extern "C" void dsprotectpatchv2s_entry();
|
|
||||||
extern u32 dsprotectpatchv2s_stub_instantdetect_offset;
|
|
||||||
extern u32 dsprotectpatchv2s_overlay_id;
|
|
||||||
extern u32 dsprotectpatchv2s_nextAddress;
|
|
||||||
extern u32 dsprotectpatchv2s_checksum_fix;
|
|
||||||
|
|
||||||
extern u16 dsprotectpatchv2s_store_checksum_fix;
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
.cpu arm946e-s
|
|
||||||
.section "dsprotectpatchv2s", "ax"
|
|
||||||
.syntax unified
|
|
||||||
.thumb
|
|
||||||
|
|
||||||
.global dsprotectpatchv2s_entry
|
|
||||||
.type dsprotectpatchv2s_entry, %function
|
|
||||||
dsprotectpatchv2s_entry:
|
|
||||||
push {r4-r7,lr}
|
|
||||||
|
|
||||||
ldmia r5!, {r0,r1,r2,r3,r4}
|
|
||||||
|
|
||||||
ldr r7, dsprotectpatchv2s_overlay_id
|
|
||||||
cmp r0, r7
|
|
||||||
bne continue_to_next
|
|
||||||
|
|
||||||
movs r3, #0
|
|
||||||
movs r7, #0
|
|
||||||
stmia r4!, {r3,r7}
|
|
||||||
stmia r4!, {r3,r7}
|
|
||||||
str r3, [r4]
|
|
||||||
|
|
||||||
adr r0, stub_patch_code
|
|
||||||
ldmia r0!, {r3,r4,r5,r6,r7}
|
|
||||||
|
|
||||||
ldr r0, dsprotectpatchv2s_stub_instantdetect_offset
|
|
||||||
adds r0, r1
|
|
||||||
stmia r0!, {r3,r4,r5,r6} // code
|
|
||||||
.global dsprotectpatchv2s_store_checksum_fix
|
|
||||||
dsprotectpatchv2s_store_checksum_fix:
|
|
||||||
str r7, [r0, #0] // checksum fix
|
|
||||||
|
|
||||||
continue_to_next:
|
|
||||||
ldr r0, dsprotectpatchv2s_nextAddress
|
|
||||||
pop {r4-r7,pc}
|
|
||||||
|
|
||||||
.balign 4
|
|
||||||
|
|
||||||
.global dsprotectpatchv2s_stub_instantdetect_offset
|
|
||||||
dsprotectpatchv2s_stub_instantdetect_offset:
|
|
||||||
.word 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv2s_overlay_id
|
|
||||||
dsprotectpatchv2s_overlay_id:
|
|
||||||
.word 0
|
|
||||||
|
|
||||||
.global dsprotectpatchv2s_nextAddress
|
|
||||||
dsprotectpatchv2s_nextAddress:
|
|
||||||
.word 0
|
|
||||||
|
|
||||||
.pool
|
|
||||||
|
|
||||||
.arm
|
|
||||||
stub_patch_code:
|
|
||||||
movs r3, r0
|
|
||||||
pusheq {r0,r1,lr}
|
|
||||||
pushne {r1,r2,r3}
|
|
||||||
pop {r0,r1,pc}
|
|
||||||
|
|
||||||
.global dsprotectpatchv2s_checksum_fix
|
|
||||||
dsprotectpatchv2s_checksum_fix:
|
|
||||||
.word 0
|
|
||||||
|
|
||||||
.end
|
|
||||||
@@ -30,6 +30,7 @@ void ApListEntry::Dump() const
|
|||||||
const char* dsProtectVersionString;
|
const char* dsProtectVersionString;
|
||||||
switch (GetDSProtectVersion())
|
switch (GetDSProtectVersion())
|
||||||
{
|
{
|
||||||
|
case DSProtectVersion::v1_00_2: dsProtectVersionString = "v1.00_2"; break;
|
||||||
case DSProtectVersion::v1_05: dsProtectVersionString = "v1.05"; break;
|
case DSProtectVersion::v1_05: dsProtectVersionString = "v1.05"; break;
|
||||||
case DSProtectVersion::v1_06: dsProtectVersionString = "v1.06"; break;
|
case DSProtectVersion::v1_06: dsProtectVersionString = "v1.06"; break;
|
||||||
case DSProtectVersion::v1_08: dsProtectVersionString = "v1.08"; break;
|
case DSProtectVersion::v1_08: dsProtectVersionString = "v1.08"; break;
|
||||||
|
|||||||
@@ -22,5 +22,6 @@ enum class DSProtectVersion : u32
|
|||||||
v2_00s,
|
v2_00s,
|
||||||
v2_01s,
|
v2_01s,
|
||||||
v2_03s,
|
v2_03s,
|
||||||
v2_05s
|
v2_05s,
|
||||||
|
v1_00_2
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ gameCode;gameVersion;dsprotVersion;dsprotFuncMask;regularOvlId;regularOffset;sOv
|
|||||||
A3PJ;0;1.10;10101;-2;0x28f34;-1;0x0
|
A3PJ;0;1.10;10101;-2;0x28f34;-1;0x0
|
||||||
A3YK;0;1.08;111111;6;0x39c;-1;0x0
|
A3YK;0;1.08;111111;6;0x39c;-1;0x0
|
||||||
AEYK;0;1.06;10101;-2;0x5ccdc;-1;0x0
|
AEYK;0;1.06;10101;-2;0x5ccdc;-1;0x0
|
||||||
|
ANMK;0;1.00_2;110011;-2;0x105d80;-1;0x0
|
||||||
ARFK;0;1.23;111111;2;0x0;-1;0x0
|
ARFK;0;1.23;111111;2;0x0;-1;0x0
|
||||||
ARMK;0;1.23;111111;28;0x0;-1;0x0
|
ARMK;0;1.23;111111;28;0x0;-1;0x0
|
||||||
AWIK;0;1.06;10101;-2;0xc9074;-1;0x0
|
AWIK;0;1.06;10101;-2;0xc9074;-1;0x0
|
||||||
@@ -519,6 +520,8 @@ YEEI;0;1.28;111111;90;0x0;-1;0x0
|
|||||||
YEEP;0;1.28;111111;90;0x0;-1;0x0
|
YEEP;0;1.28;111111;90;0x0;-1;0x0
|
||||||
YEES;0;1.28;111111;90;0x0;-1;0x0
|
YEES;0;1.28;111111;90;0x0;-1;0x0
|
||||||
YEOK;0;1.20;10101;-2;0x8a820;-1;0x0
|
YEOK;0;1.20;10101;-2;0x8a820;-1;0x0
|
||||||
|
YFTK;0;1.00_2;110011;-2;0x69d40;-1;0x0
|
||||||
|
YFYK;0;1.00_2;110011;-2;0x69d40;-1;0x0
|
||||||
YG4K;0;1.08;10101;2;0x0;-1;0x0
|
YG4K;0;1.08;10101;2;0x0;-1;0x0
|
||||||
YKGE;0;1.10;111111;28;0x0;-1;0x0
|
YKGE;0;1.10;111111;28;0x0;-1;0x0
|
||||||
YKGJ;0;1.08;111111;28;0x0;-1;0x0
|
YKGJ;0;1.08;111111;28;0x0;-1;0x0
|
||||||
@@ -537,7 +540,11 @@ YR4J;0;1.23;111111;1;0xcca0;-1;0x0
|
|||||||
YRBK;0;1.08;10111;64;0x0;-1;0x0
|
YRBK;0;1.08;10111;64;0x0;-1;0x0
|
||||||
YRCK;0;1.20;111111;0;0x0;-1;0x0
|
YRCK;0;1.20;111111;0;0x0;-1;0x0
|
||||||
YROK;0;1.26;111111;0;0x0;-1;0x0
|
YROK;0;1.26;111111;0;0x0;-1;0x0
|
||||||
|
YV5E;0;1.00_2;000001;-2;0x7e74;-1;0x0
|
||||||
|
YV5J;0;1.00_2;000001;-2;0x7e74;-1;0x0
|
||||||
|
YV5P;0;1.00_2;000001;-2;0x7e74;-1;0x0
|
||||||
YVIE;0;1.28;111111;47;0x0;-1;0x0
|
YVIE;0;1.28;111111;47;0x0;-1;0x0
|
||||||
YVIJ;0;1.22;10111;47;0x0;-1;0x0
|
YVIJ;0;1.22;10111;47;0x0;-1;0x0
|
||||||
YVIP;0;1.28;111111;47;0x0;-1;0x0
|
YVIP;0;1.28;111111;47;0x0;-1;0x0
|
||||||
|
YVKK;0;1.00_2;010001;-2;0xf7064;-1;0x0
|
||||||
YW4K;0;1.06;111111;0;0x0;-1;0x0
|
YW4K;0;1.06;111111;0;0x0;-1;0x0
|
||||||
|
|||||||
|
@@ -152,6 +152,7 @@ sealed class ApListFactory
|
|||||||
{
|
{
|
||||||
return dsProtectVersion switch
|
return dsProtectVersion switch
|
||||||
{
|
{
|
||||||
|
"1.00_2" => DSProtectVersion.V1_00_2,
|
||||||
"1.05" => DSProtectVersion.V1_05,
|
"1.05" => DSProtectVersion.V1_05,
|
||||||
"1.06" => DSProtectVersion.V1_06,
|
"1.06" => DSProtectVersion.V1_06,
|
||||||
"1.08" => DSProtectVersion.V1_08,
|
"1.08" => DSProtectVersion.V1_08,
|
||||||
@@ -181,6 +182,7 @@ sealed class ApListFactory
|
|||||||
{
|
{
|
||||||
return dsProtectVersion switch
|
return dsProtectVersion switch
|
||||||
{
|
{
|
||||||
|
DSProtectVersion.V1_00_2 => "1.00_2",
|
||||||
DSProtectVersion.V1_05 => "1.05",
|
DSProtectVersion.V1_05 => "1.05",
|
||||||
DSProtectVersion.V1_06 => "1.06",
|
DSProtectVersion.V1_06 => "1.06",
|
||||||
DSProtectVersion.V1_08 => "1.08",
|
DSProtectVersion.V1_08 => "1.08",
|
||||||
|
|||||||
@@ -21,5 +21,6 @@ enum DSProtectVersion
|
|||||||
V2_00s,
|
V2_00s,
|
||||||
V2_01s,
|
V2_01s,
|
||||||
V2_03s,
|
V2_03s,
|
||||||
V2_05s
|
V2_05s,
|
||||||
|
V1_00_2
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user