Improved DSProtect patches

This commit is contained in:
Mow
2025-12-03 10:22:06 -05:00
committed by GitHub
parent 7aba420201
commit a8f5d880b2
15 changed files with 503 additions and 732 deletions

View File

@@ -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;
}

View File

@@ -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;
}; };

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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
}; };

View File

@@ -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
1 gameCode gameVersion dsprotVersion dsprotFuncMask regularOvlId regularOffset sOvlId sOffset
2 A3PJ 0 1.10 10101 -2 0x28f34 -1 0x0
3 A3YK 0 1.08 111111 6 0x39c -1 0x0
4 AEYK 0 1.06 10101 -2 0x5ccdc -1 0x0
5 ANMK 0 1.00_2 110011 -2 0x105d80 -1 0x0
6 ARFK 0 1.23 111111 2 0x0 -1 0x0
7 ARMK 0 1.23 111111 28 0x0 -1 0x0
8 AWIK 0 1.06 10101 -2 0xc9074 -1 0x0
520 YEEP 0 1.28 111111 90 0x0 -1 0x0
521 YEES 0 1.28 111111 90 0x0 -1 0x0
522 YEOK 0 1.20 10101 -2 0x8a820 -1 0x0
523 YFTK 0 1.00_2 110011 -2 0x69d40 -1 0x0
524 YFYK 0 1.00_2 110011 -2 0x69d40 -1 0x0
525 YG4K 0 1.08 10101 2 0x0 -1 0x0
526 YKGE 0 1.10 111111 28 0x0 -1 0x0
527 YKGJ 0 1.08 111111 28 0x0 -1 0x0
540 YRBK 0 1.08 10111 64 0x0 -1 0x0
541 YRCK 0 1.20 111111 0 0x0 -1 0x0
542 YROK 0 1.26 111111 0 0x0 -1 0x0
543 YV5E 0 1.00_2 000001 -2 0x7e74 -1 0x0
544 YV5J 0 1.00_2 000001 -2 0x7e74 -1 0x0
545 YV5P 0 1.00_2 000001 -2 0x7e74 -1 0x0
546 YVIE 0 1.28 111111 47 0x0 -1 0x0
547 YVIJ 0 1.22 10111 47 0x0 -1 0x0
548 YVIP 0 1.28 111111 47 0x0 -1 0x0
549 YVKK 0 1.00_2 010001 -2 0xf7064 -1 0x0
550 YW4K 0 1.06 111111 0 0x0 -1 0x0

View File

@@ -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",

View File

@@ -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
} }