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

@@ -17,8 +17,5 @@ private:
DSProtectVersion _version;
u32 _functionMask;
void SetOldV1Offsets(const u16* offsets) const;
const void* InsertPatchV1(PatchContext& patchContext) const;
const void* InsertPatchV2(PatchContext& patchContext) const;
const void* InsertPatchV2s(PatchContext& patchContext) const;
void ConfigurePatch(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;
switch (GetDSProtectVersion())
{
case DSProtectVersion::v1_00_2: dsProtectVersionString = "v1.00_2"; break;
case DSProtectVersion::v1_05: dsProtectVersionString = "v1.05"; break;
case DSProtectVersion::v1_06: dsProtectVersionString = "v1.06"; break;
case DSProtectVersion::v1_08: dsProtectVersionString = "v1.08"; break;

View File

@@ -22,5 +22,6 @@ enum class DSProtectVersion : u32
v2_00s,
v2_01s,
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
A3YK;0;1.08;111111;6;0x39c;-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
ARMK;0;1.23;111111;28;0x0;-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
YEES;0;1.28;111111;90;0x0;-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
YKGE;0;1.10;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
YRCK;0;1.20;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
YVIJ;0;1.22;10111;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
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
{
"1.00_2" => DSProtectVersion.V1_00_2,
"1.05" => DSProtectVersion.V1_05,
"1.06" => DSProtectVersion.V1_06,
"1.08" => DSProtectVersion.V1_08,
@@ -181,6 +182,7 @@ sealed class ApListFactory
{
return dsProtectVersion switch
{
DSProtectVersion.V1_00_2 => "1.00_2",
DSProtectVersion.V1_05 => "1.05",
DSProtectVersion.V1_06 => "1.06",
DSProtectVersion.V1_08 => "1.08",

View File

@@ -21,5 +21,6 @@ enum DSProtectVersion
V2_00s,
V2_01s,
V2_03s,
V2_05s
V2_05s,
V1_00_2
}