mirror of
https://github.com/ApacheThunder/NTR_Launcher.git
synced 2025-06-18 19:15:40 -04:00

Initialising Git repo with source for NitroHax version 0.92. Future changes will be added to Git, instead of stored in source tarballs.
485 lines
10 KiB
ArmAsm
Executable File
485 lines
10 KiB
ArmAsm
Executable File
@ NitroHax -- Cheat tool for the Nintendo DS
|
|
@ Copyright (C) 2008 Michael "Chishm" Chisholm
|
|
@
|
|
@ This program is free software: you can redistribute it and/or modify
|
|
@ it under the terms of the GNU General Public License as published by
|
|
@ the Free Software Foundation, either version 3 of the License, or
|
|
@ (at your option) any later version.
|
|
@
|
|
@ This program is distributed in the hope that it will be useful,
|
|
@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
@ GNU General Public License for more details.
|
|
@
|
|
@ You should have received a copy of the GNU General Public License
|
|
@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
.arm
|
|
|
|
.global cheat_engine_start
|
|
.global cheat_engine_end
|
|
.global intr_orig_return_offset
|
|
.global cheat_engine_size
|
|
|
|
|
|
cheat_engine_size:
|
|
.word cheat_engine_end - cheat_engine_start
|
|
|
|
intr_orig_return_offset:
|
|
.word intr_orig_return - cheat_engine_start
|
|
|
|
|
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
|
|
cheat_engine_start:
|
|
@ Hook the return address, then go back to the original function
|
|
stmdb sp!, {lr}
|
|
adr lr, code_handler_start
|
|
ldr r0, intr_orig_return
|
|
bx r0
|
|
|
|
code_handler_start:
|
|
stmdb sp!, {r0-r12}
|
|
mov r9, #0x00000000 @ offset register
|
|
mov r8, #0x00000000 @ execution status. bit0: 1 = no exec, 0 = exec. allows nested ifs 32 deep
|
|
mov r7, #0x00000000 @ Dx loop start
|
|
mov r6, #0x00000000 @ Dx repeat ammount
|
|
mov r5, #0x00000000 @ DX data
|
|
mov r4, #0x00000000 @ Dx execution status
|
|
|
|
@ increment counter
|
|
ldrh r0, counter_value
|
|
add r0, r0, #1
|
|
strh r0, counter_value
|
|
|
|
@ r0-r3 are generic registers for the code processor to use
|
|
@ 0xCF000000 0x00000000 indicates the end of the code list
|
|
@ r12 points to the next code to load
|
|
|
|
adr r12, cheat_data
|
|
|
|
main_loop:
|
|
ldmia r12!, {r10, r11} @ load a code
|
|
cmp r10, #0xCF000000
|
|
beq exit
|
|
|
|
mov r0, r10, lsr #28
|
|
cmp r0, #0xE
|
|
beq patch_code
|
|
cmp r0, #0xD
|
|
beq dx_codes
|
|
cmp r0, #0xC
|
|
beq type_c
|
|
|
|
@ check execution status
|
|
tst r8, #0x00000001
|
|
bne main_loop
|
|
|
|
@ check code group
|
|
cmp r0, #0x3
|
|
blt raw_write
|
|
cmp r0, #0x6
|
|
ble if_32bit
|
|
cmp r0, #0xB
|
|
blt if_16bit_mask
|
|
beq offset_load
|
|
b mem_copy_code
|
|
|
|
|
|
counter_value:
|
|
.word 0x00000000
|
|
|
|
|
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
@ type 0-2
|
|
|
|
raw_write:
|
|
cmp r0, #0x1
|
|
bic r10, r10, #0xf0000000
|
|
strlt r11, [r10, r9] @ type 0
|
|
streqh r11, [r10, r9] @ type 1
|
|
strgtb r11, [r10, r9] @ type 2
|
|
b main_loop
|
|
|
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
@ type 3-6
|
|
@ r0 still contains the code type
|
|
|
|
if_32bit:
|
|
bic r1, r10, #0xf0000001
|
|
tst r10, #0x00000001
|
|
addne r1, r1, r9 @ add offset to the address if the lowest bit is set
|
|
cmp r1, #0x00000000
|
|
moveq r1, r9 @ if address is 0, set address to offset
|
|
ldr r1, [r1] @ load word from [0XXXXXXX]
|
|
mov r8, r8, lsl #1 @ push execution status
|
|
cmp r0, #0x3
|
|
beq if_32bit_bhi
|
|
cmp r0, #0x5
|
|
blt if_32bit_bcc
|
|
beq if_32bit_beq
|
|
@ fall through to if_32bit_bne
|
|
|
|
@ type 6
|
|
if_32bit_bne:
|
|
cmp r11, r1
|
|
orreq r8, r8, #0x00000001
|
|
b main_loop
|
|
|
|
@ type 3
|
|
if_32bit_bhi:
|
|
cmp r11, r1
|
|
orrls r8, r8, #0x00000001
|
|
b main_loop
|
|
|
|
@ type 4
|
|
if_32bit_bcc:
|
|
cmp r11, r1
|
|
orrcs r8, r8, #0x00000001
|
|
b main_loop
|
|
|
|
@ type 5
|
|
if_32bit_beq:
|
|
cmp r11, r1
|
|
orrne r8, r8, #0x00000001
|
|
b main_loop
|
|
|
|
|
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
@ type 7-A
|
|
@ r0 still contains the code type
|
|
|
|
if_16bit_mask:
|
|
bic r1, r10, #0xf0000001
|
|
tst r10, #0x00000001
|
|
addne r1, r1, r9 @ add offset to the address if the lowest bit is set
|
|
cmp r1, #0x00000000
|
|
moveq r1, r9 @ if address is 0, set address to offset
|
|
ldrh r1, [r1] @ load halfword from [0XXXXXXX]
|
|
mov r2, r11, lsr #16 @ bit mask
|
|
mov r3, r11, lsl #16 @ compare data
|
|
mov r3, r3, lsr #16
|
|
bic r1, r1, r2 @ clear any bit that is set in the mask
|
|
|
|
mov r8, r8, lsl #1 @ push execution status
|
|
cmp r0, #0x7
|
|
beq if_16bit_bhi
|
|
cmp r0, #0x9
|
|
blt if_16bit_bcc
|
|
beq if_16bit_beq
|
|
@ fall through to if_16bit_bne
|
|
|
|
@ type A
|
|
if_16bit_bne:
|
|
cmp r3, r1
|
|
orreq r8, r8, #0x00000001
|
|
b main_loop
|
|
|
|
@ type 7
|
|
if_16bit_bhi:
|
|
cmp r3, r1
|
|
orrls r8, r8, #0x00000001
|
|
b main_loop
|
|
|
|
@ type 8
|
|
if_16bit_bcc:
|
|
cmp r3, r1
|
|
orrcs r8, r8, #0x00000001
|
|
b main_loop
|
|
|
|
@ type 9
|
|
if_16bit_beq:
|
|
cmp r3, r1
|
|
orrne r8, r8, #0x00000001
|
|
b main_loop
|
|
|
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
@ type B
|
|
|
|
offset_load:
|
|
bic r10, r10, #0xf0000000
|
|
ldr r9, [r10, r9]
|
|
b main_loop
|
|
|
|
|
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
@ type C
|
|
|
|
type_c:
|
|
mov r0, r10, lsr #24
|
|
cmp r0, #0xC1
|
|
beq exec_remote_function
|
|
cmp r0, #0xC2
|
|
beq exec_custom_function
|
|
|
|
tst r8, #0x00000001 @ make sure execution is enabled
|
|
bne main_loop
|
|
|
|
cmp r0, #0xC0
|
|
beq loop_start
|
|
cmp r0, #0xC5
|
|
beq execution_counter @ type C5
|
|
|
|
offset_data_store: @ type C4
|
|
sublt r9, r12, #0x08 @ Offset = Two words back from current code pointer (ie, word at C4000000 code)
|
|
|
|
save_offset: @ type C6
|
|
strgt r9, [r11] @ Save offset to [XXXXXXXX] in C6000000 XXXXXXXX
|
|
b main_loop
|
|
|
|
loop_start:
|
|
mov r4, r8 @ execution status
|
|
mov r6, r11 @ loop repeat amount
|
|
mov r7, r12 @ loop start
|
|
b main_loop
|
|
|
|
exec_remote_function:
|
|
ldmia r12, {r0, r1, r2, r3} @ load arguments
|
|
and r10, r10, #0x00000007
|
|
add r12, r12, r10 @ move code pointer to where it should be
|
|
tst r8, #0x00000001
|
|
bne align_cheat_list @ execution disabled
|
|
stmdb sp!, {r12}
|
|
adr lr, exec_function_return
|
|
bx r11
|
|
|
|
exec_custom_function:
|
|
and r0, r10, #0x00000001 @ thumb mode?
|
|
add r0, r0, r12 @ custom function location
|
|
add r12, r12, r11
|
|
tst r8, #0x00000001
|
|
bne align_cheat_list @ execution disabled
|
|
stmdb sp!, {r12}
|
|
adr lr, exec_function_return
|
|
bx r0
|
|
|
|
exec_function_return:
|
|
ldmia sp!, {r12}
|
|
b align_cheat_list
|
|
|
|
|
|
execution_counter:
|
|
ldr r0, counter_value @ we only need the low 16 bits but counter_value is out of immediate range for ldrh
|
|
mov r1, r11, lsl #16
|
|
and r0, r0, r1, lsr #16 @ mask off counter
|
|
mov r8, r8, lsl #1 @ push execution status
|
|
cmp r0, r11, lsr #16 @ Compare against compare value component of code
|
|
orrne r8, r8, #0x00000001 @ set execution to false
|
|
b main_loop
|
|
|
|
|
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
@ type D
|
|
|
|
dx_codes:
|
|
mov r0, r10, lsr #24
|
|
cmp r0, #0xD3
|
|
bcs dx_conditional_exec
|
|
|
|
cmp r0, #0xD1
|
|
bgt end_loop_clear
|
|
beq end_loop_no_clear
|
|
@ fall through to end_if
|
|
|
|
@ type D0
|
|
end_if:
|
|
mov r8, r8, lsr #1 @ pop exec status
|
|
b main_loop
|
|
|
|
@ type D2
|
|
end_loop_clear:
|
|
mov r8, r4 @ restore the old execution status
|
|
cmp r6, #0 @ end of a loop?
|
|
@ no
|
|
subgt r6, r6, #1
|
|
movgt r12, r7 @ load the Dx loop start
|
|
bgt main_loop
|
|
@ yes
|
|
mov r5, #0 @ clear Dx data register
|
|
mov r8, #0 @ clear execution status
|
|
mov r9, #0 @ clear offset
|
|
b main_loop
|
|
|
|
@ type D1
|
|
end_loop_no_clear:
|
|
mov r8, r4 @ restore the old execution status
|
|
cmp r6, #0 @ end of a loop?
|
|
@ no
|
|
subgt r6, r6, #1
|
|
movgt r12, r7 @ load the Dx loop start
|
|
@ yes
|
|
b main_loop
|
|
|
|
dx_conditional_exec:
|
|
tst r8, #0x00000001
|
|
bne main_loop
|
|
|
|
cmp r0, #0xD6
|
|
bcs dx_write
|
|
|
|
cmp r0, #0xD4
|
|
@ type D3 - Offset Set
|
|
movlt r9, r11
|
|
beq dx_data_op
|
|
@ type D5 - Dx Data set
|
|
movgt r5, r11
|
|
b main_loop
|
|
|
|
dx_write:
|
|
cmp r0, #0xD9
|
|
bcs dx_load
|
|
|
|
cmp r0, #0xD7
|
|
@ type D6 - Dx Data write 32 bits
|
|
strlt r5, [r11, r9]
|
|
addlt r9, r9, #4
|
|
@ type D7 - Dx Data write 16 bits
|
|
streqh r5, [r11, r9]
|
|
addeq r9, r9, #2
|
|
@ type D8 - Dx Data write 8 bits
|
|
strgtb r5, [r11, r9]
|
|
addgt r9, r9, #1
|
|
b main_loop
|
|
|
|
dx_load:
|
|
cmp r0, #0xDC
|
|
bcs dx_offset_add_addr
|
|
|
|
cmp r0, #0xDA
|
|
@ type D9 - Dx Data load 32 bits
|
|
ldrlt r5, [r11, r9]
|
|
@ type DA - Dx Data load 16 bits
|
|
ldreqh r5, [r11, r9]
|
|
@ type DB - Dx Data load 8 bits
|
|
ldrgtb r5, [r11, r9]
|
|
b main_loop
|
|
|
|
@ type DC
|
|
dx_offset_add_addr:
|
|
add r9, r9, r11
|
|
b main_loop
|
|
|
|
@ type D4
|
|
dx_data_op:
|
|
and r0, r10, #0x000000ff
|
|
cmp r0, #0x01
|
|
@ type D4000000 - add, use negative values for sub
|
|
addlt r5, r5, r11
|
|
@ type D4000001 - or
|
|
orreq r5, r5, r11
|
|
ble main_loop
|
|
|
|
cmp r0, #0x03
|
|
@ type D4000002 - and
|
|
andlt r5, r5, r11
|
|
@ type D4000003 - xor
|
|
eoreq r5, r5, r11
|
|
ble main_loop
|
|
|
|
cmp r0, #0x05
|
|
@ type D4000004 - lsl
|
|
movlt r5, r5, lsl r11
|
|
@ type D4000005 - lsr
|
|
moveq r5, r5, lsr r11
|
|
ble main_loop
|
|
|
|
cmp r0, #0x07
|
|
@ type D4000006 - ror
|
|
movlt r5, r5, ror r11
|
|
@ type D4000007 - asr
|
|
moveq r5, r5, asr r11
|
|
ble main_loop
|
|
|
|
cmp r0, #0x09
|
|
@ type D4000008 - mul
|
|
mullt r5, r11, r5
|
|
|
|
b main_loop
|
|
|
|
|
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
@ type E
|
|
|
|
patch_code:
|
|
@ check execution status
|
|
tst r8, #0x00000001
|
|
addne r12, r12, r11 @ skip the data section
|
|
bne align_cheat_list
|
|
|
|
bic r10, r10, #0xf0000000 @ destination address
|
|
add r10, r10, r9 @ add offset to dest
|
|
@ r11 is bytes remaining
|
|
@ r12 is source
|
|
|
|
patch_code_word_loop:
|
|
cmp r11, #4
|
|
blt patch_code_byte_loop
|
|
ldr r1, [r12], #4
|
|
str r1, [r10], #4
|
|
sub r11, r11, #4
|
|
b patch_code_word_loop
|
|
|
|
patch_code_byte_loop:
|
|
cmp r11, #1
|
|
blt align_cheat_list @ patch_code_end
|
|
ldrb r1, [r12], #1
|
|
strb r1, [r10], #1
|
|
sub r11, r11, #1
|
|
b patch_code_byte_loop
|
|
|
|
align_cheat_list:
|
|
add r12, r12, #0x7
|
|
bic r12, r12, #0x00000007 @ round up to nearest multiple of 8
|
|
b main_loop
|
|
|
|
|
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
@ type F
|
|
|
|
mem_copy_code:
|
|
bic r10, r10, #0xf0000000 @ destination address
|
|
@ r11 is bytes remaining
|
|
mov r2, r9 @ source address
|
|
|
|
mem_copy_code_word_loop:
|
|
cmp r11, #4
|
|
blt mem_copy_code_byte_loop
|
|
ldr r1, [r2], #4
|
|
str r1, [r10], #4
|
|
sub r11, r11, #4
|
|
b mem_copy_code_word_loop
|
|
|
|
mem_copy_code_byte_loop:
|
|
cmp r11, #1
|
|
blt main_loop @ mem_copy_code_end
|
|
ldrb r1, [r2], #1
|
|
strb r1, [r10], #1
|
|
sub r11, r11, #1
|
|
b mem_copy_code_byte_loop
|
|
|
|
|
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
|
|
exit:
|
|
ldmia sp!, {r0-r12}
|
|
ldmia sp!, {lr}
|
|
bx lr
|
|
|
|
intr_orig_return:
|
|
.word 0x00000000
|
|
|
|
.pool
|
|
|
|
cheat_data:
|
|
|
|
cheat_engine_end:
|
|
|
|
@ Cheat data goes here
|
|
|
|
.word 0xCF000000, 0x00000000
|
|
.word 0x00000000, 0x00000000
|
|
.word 0x00000000, 0x00000000
|
|
.word 0x00000000, 0x00000000
|
|
|
|
|