Emunand self patching; found solution for some hard coded stuff/FS more flexible; got rid of screenShot; implemented PoC RAM dumper using txt file; changed location of arm9 thread; fixed ver string; tons of organization and cleaning up for easier to read and modify code.
This commit is contained in:
parent
2465cb0fa9
commit
62d8d582c1
4
Makefile
4
Makefile
@ -64,9 +64,9 @@ $(dir_out)/3ds/$(name):
|
|||||||
@mv $(dir_out)/$(name).3dsx $@
|
@mv $(dir_out)/$(name).3dsx $@
|
||||||
@mv $(dir_out)/$(name).smdh $@
|
@mv $(dir_out)/$(name).smdh $@
|
||||||
|
|
||||||
$(dir_out)/rei/: $(dir_data)/firmware.bin $(dir_data)/splash.bin
|
$(dir_out)/rei/: $(dir_data)/firmware.bin $(dir_data)/splash.bin $(dir_data)/RAM.txt
|
||||||
@mkdir -p "$(dir_out)/rei"
|
@mkdir -p "$(dir_out)/rei"
|
||||||
@cp -av $(dir_data)/*bin $@
|
@cp -av $(dir_data)/* $@
|
||||||
|
|
||||||
$(dir_out)/rei/thread/arm9.bin: $(dir_thread)
|
$(dir_out)/rei/thread/arm9.bin: $(dir_thread)
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_thread)
|
@$(MAKE) $(FLAGS) -C $(dir_thread)
|
||||||
|
1
data/RAM.txt
Normal file
1
data/RAM.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
536870912
|
@ -1,6 +1,6 @@
|
|||||||
.nds
|
.nds
|
||||||
|
|
||||||
sdmmc equ 0x080F0AB0
|
sdmmc equ 0x434D4453 ;dummy
|
||||||
|
|
||||||
.create "emunand.bin", 0x0801A5C0
|
.create "emunand.bin", 0x0801A5C0
|
||||||
.org 0x0801A5C0
|
.org 0x0801A5C0
|
||||||
|
@ -5,12 +5,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "emunand.h"
|
#include "emunand.h"
|
||||||
|
#include "memory.h"
|
||||||
#include "fatfs/ff.h"
|
#include "fatfs/ff.h"
|
||||||
#include "fatfs/sdmmc/sdmmc.h"
|
#include "fatfs/sdmmc/sdmmc.h"
|
||||||
|
|
||||||
static u8 *temp = (u8*)0x24300000;
|
static u8 *temp = (u8*)0x24300000;
|
||||||
|
|
||||||
void getEmunand(u32 *off, u32 *head){
|
void getEmunandSect(u32 *off, u32 *head){
|
||||||
u32 nandSize = getMMCDevice(0)->total_size;
|
u32 nandSize = getMMCDevice(0)->total_size;
|
||||||
if (sdmmc_sdcard_readsectors(nandSize, 1, temp) == 0) {
|
if (sdmmc_sdcard_readsectors(nandSize, 1, temp) == 0) {
|
||||||
if (*(u32*)(temp + 0x100) == NCSD_MAGIC) {
|
if (*(u32*)(temp + 0x100) == NCSD_MAGIC) {
|
||||||
@ -18,4 +19,30 @@ void getEmunand(u32 *off, u32 *head){
|
|||||||
*head = nandSize;
|
*head = nandSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getSDMMC(void *offset, u32 *off, u32 size){
|
||||||
|
//Look for struct code
|
||||||
|
unsigned char pattern[] = {0x01, 0x21, 0x20, 0x18, 0x20, 0x30};
|
||||||
|
*off = memsearch(offset, pattern, size, 6);
|
||||||
|
|
||||||
|
//Get DCD values
|
||||||
|
unsigned char buf[4];
|
||||||
|
int p;
|
||||||
|
u32 addr = 0;
|
||||||
|
u32 additive = 0;
|
||||||
|
memcpy((void*)buf, (void*)(*off+0x0A), 4);
|
||||||
|
for (p = 0; p < 4; p++) addr |= ((u32) buf[p]) << (8 * p);
|
||||||
|
memcpy((void*)buf, (void*)(*off+0x0E), 4);
|
||||||
|
for (p = 0; p < 4; p++) additive |= ((u32) buf[p]) << (8 * p);
|
||||||
|
|
||||||
|
//Return result
|
||||||
|
*off = addr + additive;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
|
||||||
|
//Look for read/write code
|
||||||
|
unsigned char pattern[] = {0x04, 0x00, 0x0D, 0x00, 0x17, 0x00, 0x1E, 0x00, 0xC8, 0x05};
|
||||||
|
*writeOff = memsearch(pos, pattern, size, 10);
|
||||||
|
*readOff = *writeOff - 0x40; //TODO: Maybe make memsearch work properly for this.
|
||||||
}
|
}
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#define NCSD_MAGIC (0x4453434E)
|
#define NCSD_MAGIC (0x4453434E)
|
||||||
|
|
||||||
void getEmunand(u32 *off, u32 *head);
|
void getEmunandSect(u32 *off, u32 *head);
|
||||||
|
void getSDMMC(void *offset, u32 *off, u32 size);
|
||||||
|
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -13,13 +13,19 @@
|
|||||||
|
|
||||||
const firmHeader *firmLocation = (firmHeader *)0x24000000;
|
const firmHeader *firmLocation = (firmHeader *)0x24000000;
|
||||||
firmSectionHeader *section;
|
firmSectionHeader *section;
|
||||||
u32 emuOffset = 0;
|
u32 emuOffset = 0,
|
||||||
u32 emuHeader = 0;
|
emuHeader = 0,
|
||||||
|
emuRead = 0,
|
||||||
|
emuWrite = 0,
|
||||||
|
sdmmcOffset = 0,
|
||||||
|
firmSize = 0;
|
||||||
|
|
||||||
//Load firm into FCRAM
|
//Load firm into FCRAM
|
||||||
void loadFirm(void){
|
void loadFirm(void){
|
||||||
//Read FIRM from SD card and write to FCRAM
|
//Read FIRM from SD card and write to FCRAM
|
||||||
fileRead((u8*)firmLocation, "/rei/firmware.bin", 0);
|
const char firmPath[] = "/rei/firmware.bin";
|
||||||
|
firmSize = fileSize(firmPath);
|
||||||
|
fileRead((u8*)firmLocation, firmPath, firmSize);
|
||||||
section = firmLocation->section;
|
section = firmLocation->section;
|
||||||
arm9loader((u8*)firmLocation + section[2].offset);
|
arm9loader((u8*)firmLocation + section[2].offset);
|
||||||
}
|
}
|
||||||
@ -29,31 +35,35 @@ void loadEmu(void){
|
|||||||
|
|
||||||
//Read emunand code from SD
|
//Read emunand code from SD
|
||||||
u32 code = emuCode();
|
u32 code = emuCode();
|
||||||
fileRead(code, "/rei/emunand/emunand.bin", 0);
|
const char path[] = "/rei/emunand/emunand.bin";
|
||||||
u32 *pos_offset = memsearch(code, "NAND", 0x218, 4);
|
u32 size = fileSize(path);
|
||||||
u32 *pos_header = memsearch(code, "NCSD", 0x218, 4);
|
fileRead(code, path, size);
|
||||||
getEmunand(&emuOffset, &emuHeader);
|
|
||||||
if (pos_offset && pos_header) {
|
//Find and patch emunand related offsets
|
||||||
*pos_offset = emuOffset;
|
u32 *pos_sdmmc = memsearch(code, "SDMC", size, 4);
|
||||||
*pos_header = emuHeader;
|
u32 *pos_offset = memsearch(code, "NAND", size, 4);
|
||||||
}
|
u32 *pos_header = memsearch(code, "NCSD", size, 4);
|
||||||
|
getSDMMC(firmLocation, &sdmmcOffset, firmSize);
|
||||||
|
getEmunandSect(&emuOffset, &emuHeader);
|
||||||
|
getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite);
|
||||||
|
*pos_sdmmc = sdmmcOffset;
|
||||||
|
*pos_offset = emuOffset;
|
||||||
|
*pos_header = emuHeader;
|
||||||
|
|
||||||
//Add emunand hooks
|
//Add emunand hooks
|
||||||
memcpy((u8*)emuHook(1), nandRedir, sizeof(nandRedir));
|
memcpy((u8*)emuRead, nandRedir, sizeof(nandRedir));
|
||||||
memcpy((u8*)emuHook(2), nandRedir, sizeof(nandRedir));
|
memcpy((u8*)emuWrite, nandRedir, sizeof(nandRedir));
|
||||||
|
memcpy((u8*)mpuCode(), mpu, sizeof(mpu));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Patches
|
//Patches
|
||||||
void patchFirm(){
|
void patchFirm(){
|
||||||
|
|
||||||
//Part1: Set MPU for payload area
|
//Disable signature checks
|
||||||
memcpy((u8*)mpuCode(), mpu, sizeof(mpu));
|
|
||||||
|
|
||||||
//Part2: Disable signature checks
|
|
||||||
memcpy((u8*)sigPatch(1), sigPat1, sizeof(sigPat1));
|
memcpy((u8*)sigPatch(1), sigPat1, sizeof(sigPat1));
|
||||||
memcpy((u8*)sigPatch(2), sigPat2, sizeof(sigPat2));
|
memcpy((u8*)sigPatch(2), sigPat2, sizeof(sigPat2));
|
||||||
|
|
||||||
//Part3: Create arm9 thread
|
//Create arm9 thread
|
||||||
fileRead((u8*)threadCode(), "/rei/thread/arm9.bin", 0);
|
fileRead((u8*)threadCode(), "/rei/thread/arm9.bin", 0);
|
||||||
memcpy((u8*)threadHook(1), th1, sizeof(th1));
|
memcpy((u8*)threadHook(1), th1, sizeof(th1));
|
||||||
memcpy((u8*)threadHook(2), th2, sizeof(th2));
|
memcpy((u8*)threadHook(2), th2, sizeof(th2));
|
||||||
|
14
source/fs.c
14
source/fs.c
@ -69,4 +69,18 @@ int fileWrite(const u8 *buffer, const char *path, u32 size){
|
|||||||
if (fr == FR_OK && br == size) return 0;
|
if (fr == FR_OK && br == size) return 0;
|
||||||
}
|
}
|
||||||
return fr;
|
return fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fileSize(const char* path){
|
||||||
|
FRESULT fr;
|
||||||
|
FIL fp;
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
fr = f_open(&fp, path, FA_READ);
|
||||||
|
if (fr != FR_OK)goto error;
|
||||||
|
|
||||||
|
size = f_size(&fp);
|
||||||
|
error:
|
||||||
|
f_close(&fp);
|
||||||
|
return size;
|
||||||
}
|
}
|
@ -12,5 +12,6 @@ int unmountSD();
|
|||||||
int fileReadOffset(u8 *dest, const char *path, u32 size, u32 offset);
|
int fileReadOffset(u8 *dest, const char *path, u32 size, u32 offset);
|
||||||
int fileRead(u8 *dest, const char *path, u32 size);
|
int fileRead(u8 *dest, const char *path, u32 size);
|
||||||
int fileWrite(const u8 *buffer, const char *path, u32 size);
|
int fileWrite(const u8 *buffer, const char *path, u32 size);
|
||||||
|
int fileSize(const char* path);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,14 +19,13 @@
|
|||||||
**************************************************/
|
**************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Emunand
|
* MPU
|
||||||
*/
|
*/
|
||||||
u8 mpu[0x2C] = { //MPU shit
|
u8 mpu[0x2C] = { //MPU shit
|
||||||
0x03, 0x00, 0x36, 0x00, 0x00, 0x00, 0x10, 0x10, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x36, 0x00,
|
0x03, 0x00, 0x36, 0x00, 0x00, 0x00, 0x10, 0x10, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x36, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08,
|
0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08,
|
||||||
0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x08
|
0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x08
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0xC0, 0xA5, 0x01, 0x08}; //Branch to emunand function
|
u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0xC0, 0xA5, 0x01, 0x08}; //Branch to emunand function
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -38,8 +37,8 @@ u8 sigPat2[4] = {0x00, 0x20, 0x70, 0x47};
|
|||||||
/*
|
/*
|
||||||
* Arm9 thread
|
* Arm9 thread
|
||||||
*/
|
*/
|
||||||
u8 th1[4] = {0x2C, 0xF0, 0x9F, 0xE5}; //ldr pc, =0x0801A7E0
|
u8 th1[4] = {0x2C, 0xF0, 0x9F, 0xE5}; //ldr pc, =0x08006070
|
||||||
u8 th2[4] = {0xE0, 0xA7, 0x01, 0x08}; //0x0801A7E0
|
u8 th2[4] = {0x70, 0x60, 0x00, 0x08}; //0x08006070
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ u32 emuCode(void){
|
|||||||
|
|
||||||
//Where thread code is stored in firm
|
//Where thread code is stored in firm
|
||||||
u32 threadCode(void){
|
u32 threadCode(void){
|
||||||
return KERNEL9 + (0x0801A7E0 - K9_ADDR);
|
return KERNEL9 + (0x08006070 - K9_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Area of MPU setting code
|
//Area of MPU setting code
|
||||||
@ -69,13 +68,6 @@ u32 threadHook(u8 val){
|
|||||||
PROC9 + (0x080851CC - P9_ADDR);
|
PROC9 + (0x080851CC - P9_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Offsets to redirect to Emunand code
|
|
||||||
u32 emuHook(u8 val){ //latest only
|
|
||||||
return val == 1 ?
|
|
||||||
PROC9 + (0x08077B40 - P9_ADDR):
|
|
||||||
PROC9 + (0x08077B80 - P9_ADDR);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Offsets to redirect to thread code
|
//Offsets to redirect to thread code
|
||||||
u32 sigPatch(u8 val){
|
u32 sigPatch(u8 val){
|
||||||
return val == 1 ?
|
return val == 1 ?
|
||||||
|
@ -6,7 +6,7 @@ ENTRY(_start)
|
|||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0x0801A7E0;
|
. = 0x08006070;
|
||||||
start_addr = .;
|
start_addr = .;
|
||||||
.text.start : { *(.text.start) }
|
.text.start : { *(.text.start) }
|
||||||
.text : { *(.text) *(.text*) }
|
.text : { *(.text) *(.text*) }
|
||||||
|
@ -13,8 +13,8 @@ _start:
|
|||||||
ldr r1, =thread @ thread_addr
|
ldr r1, =thread @ thread_addr
|
||||||
mov r2, #0x0 @ arg
|
mov r2, #0x0 @ arg
|
||||||
ldr r3, =0x08000c00 @ StackTop
|
ldr r3, =0x08000c00 @ StackTop
|
||||||
ldr r4, =0x1
|
ldr r4, =0xFFFFFFFE
|
||||||
svc 0x8
|
svc 0x8
|
||||||
pop {r0-r12 , lr}
|
pop {r0-r12 , lr}
|
||||||
ldr r0, =0x80E3408
|
ldr r0, =0x080E3408
|
||||||
ldr pc, =0x0808519C
|
ldr pc, =0x0808519C
|
@ -31,6 +31,24 @@ int memcmp(void* buf1, void* buf2, int size){
|
|||||||
return equal;
|
return equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int atoi(const char* nptr){
|
||||||
|
int result = 0,
|
||||||
|
position = 1;
|
||||||
|
const char* p = nptr;
|
||||||
|
|
||||||
|
while(*p) ++p;
|
||||||
|
|
||||||
|
for(--p; p >= nptr; p--){
|
||||||
|
if(*p < 0x30 || *p > 0x39) break;
|
||||||
|
else{
|
||||||
|
result += (position) * (*p - 0x30);
|
||||||
|
position *= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = ((nptr[0] == '-')? -result : result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned isPressed(unsigned bitfield){
|
unsigned isPressed(unsigned bitfield){
|
||||||
return ((~*(unsigned *)0x10146000) & 0xFFF) == (bitfield & 0xFFF) ? 1 : 0;
|
return ((~*(unsigned *)0x10146000) & 0xFFF) == (bitfield & 0xFFF) ? 1 : 0;
|
||||||
}
|
}
|
@ -20,6 +20,7 @@ void* memset(void * ptr, int value, unsigned int num);
|
|||||||
int strcomp(char* s1, char*s2, unsigned int size);
|
int strcomp(char* s1, char*s2, unsigned int size);
|
||||||
void strcopy(char* dest, char* source, unsigned int size);
|
void strcopy(char* dest, char* source, unsigned int size);
|
||||||
int memcmp(void* buf1, void* buf2, int size);
|
int memcmp(void* buf1, void* buf2, int size);
|
||||||
|
int atoi(const char* nptr);
|
||||||
unsigned isPressed(unsigned bitfield);
|
unsigned isPressed(unsigned bitfield);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -10,78 +10,48 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
|
|
||||||
|
//ram stuff
|
||||||
#define VRAM (unsigned char*)0x18000000
|
#define VRAM (unsigned char*)0x18000000
|
||||||
#define FCRAM (unsigned char*)0x20000000
|
#define FCRAM (unsigned char*)0x20000000
|
||||||
#define FCRAM_EXT (unsigned char*)0x28000000
|
#define FCRAM_EXT (unsigned char*)0x28000000
|
||||||
#define ARM9_MEM (unsigned char*)0x8000000
|
|
||||||
#define AXIWRAM (unsigned char*)0x1FF80000
|
//file stuff
|
||||||
#define TOP_FRAME 0
|
#define READ 0
|
||||||
#define BOT_FRAME 1
|
#define WRITE 1
|
||||||
|
|
||||||
unsigned char handle[32];
|
unsigned char handle[32];
|
||||||
unsigned char bmpHead[] = {
|
|
||||||
0x42, 0x4D, 0x36, 0x65, 0x04, 0x00, 0x00, 0x00,
|
void fileReadWrite(void *buf, void *path, int size, char rw){
|
||||||
0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
|
unsigned int br = 0;
|
||||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xF0, 0x00,
|
memset(&handle, 0, 32);
|
||||||
0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
|
fopen9(&handle, path, 6);
|
||||||
0x00, 0x00, 0x00, 0x65, 0x04, 0x00, 0x00, 0x00,
|
if(rw == 0) fread9(&handle, &br, buf, size);
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
else fwrite9(&handle, &br, buf, size);
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
fclose9(&handle);
|
||||||
};
|
}
|
||||||
|
|
||||||
void memdump(void* filename, void* buf, unsigned int size){
|
void memdump(void* filename, void* buf, unsigned int size){
|
||||||
unsigned int br = 0;
|
fileReadWrite(buf, filename, size, WRITE);
|
||||||
memset(&handle, 0, 32);
|
|
||||||
fopen9(&handle, filename, 6);
|
|
||||||
fwrite9(&handle, &br, buf, size);
|
|
||||||
fclose9(&handle);
|
|
||||||
memset(VRAM+0x1E6000, 0xFF, 0x46500);
|
memset(VRAM+0x1E6000, 0xFF, 0x46500);
|
||||||
}
|
}
|
||||||
|
|
||||||
void transpose (void * dst, const void * src, unsigned dim1, unsigned dim2, unsigned item_length) {
|
|
||||||
char * ptr_write;
|
|
||||||
const char * ptr_read;
|
|
||||||
unsigned x, y, z;
|
|
||||||
for (x = 0; x < dim1; x ++) for (y = 0; y < dim2; y ++) {
|
|
||||||
ptr_write = ((char *) dst) + item_length * (y * dim1 + x);
|
|
||||||
ptr_read = ((const char *) src) + item_length * (x * dim2 + y);
|
|
||||||
for (z = 0; z < item_length; z ++) *(ptr_write ++) = *(ptr_read ++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void screenShot(int frame){
|
|
||||||
unsigned int br;
|
|
||||||
short width = frame == 0 ? 400 : 320;
|
|
||||||
short height = 240;
|
|
||||||
int frameOff = frame == 0 ? 0x1E6000 : 0x48F000; //<- Defaults
|
|
||||||
int length = frame == 0 ? 0x46500 : 0x38400;
|
|
||||||
memset(&handle, 0, 32);
|
|
||||||
fopen9(&handle, frame == 0 ? L"sdmc:/screen_top.bmp" : L"sdmc:/screen_bot.bmp", 6);
|
|
||||||
transpose(FCRAM+0xF80000, VRAM+frameOff, width, height, 3);
|
|
||||||
bmpHead[18] = frame == 0 ? 0x90 : 0x40;
|
|
||||||
fwrite9(&handle, &br, bmpHead, 0x36);
|
|
||||||
fwrite9(&handle, &br, FCRAM+0xF80000, length);
|
|
||||||
fclose9(&handle);
|
|
||||||
memset(VRAM+frameOff, 0xFF, 0x46500);
|
|
||||||
}
|
|
||||||
|
|
||||||
void patches(void){
|
void patches(void){
|
||||||
//Change version string
|
//Change version string
|
||||||
for(int i = 0; i < 0x600000; i+=4){
|
for(int i = 0; i < 0x600000; i+=4){
|
||||||
if(strcomp((void*)0x27B00000 - i, (void*)L"Ver.", 4)){
|
if(strcomp((void*)0x27B00000 - i, (void*)L"Ver.", 4)){
|
||||||
if(strcomp((void*)0x27B00000 - i + 0x28, (void*)"T_ver_00", 4)) strcopy((void*)0x27B00000 - i, (void*)L"\uE024Rei", 4);
|
if(strcomp((void*)0x27B00000 - i + 0x0A, (void*)L"%d.%d.%d-%d", 11)) strcopy((void*)0x27B00000 - i, (void*)L"\uE024Rei", 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread(void){
|
void thread(void){
|
||||||
while(1){
|
while(1){
|
||||||
if(isPressed(BUTTON_SELECT | BUTTON_X)){
|
if(isPressed(BUTTON_START | BUTTON_X)){
|
||||||
screenShot(TOP_FRAME);
|
unsigned char buf[0x10] = {0};
|
||||||
screenShot(BOT_FRAME);
|
int loc = 0;
|
||||||
}
|
fileReadWrite(buf, L"sdmc:/rei/RAM.txt", 0x20, READ);
|
||||||
if(isPressed(BUTTON_START | BUTTON_X)){
|
loc = atoi(buf);
|
||||||
memdump(L"sdmc:/FCRAM.bin", (void*)0x27500000, 0x600000);
|
memdump(L"sdmc:/RAMdmp.bin", (void*)loc, 0x500000);
|
||||||
}
|
}
|
||||||
patches();
|
patches();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user