diff --git a/include/arm11/cheat.h b/include/arm11/cheat.h index 55640be..29f27fe 100644 --- a/include/arm11/cheat.h +++ b/include/arm11/cheat.h @@ -21,10 +21,13 @@ typedef int cheat_error_t; #define CHEAT_MODE_SIZE 3 #define MAKE_ENTID(hole, key) ((key+1)<<16|(hole+1)) +#define ENT_USING(entid) ((entid) > 0xffff) cheat_error_t init_current_cheat( u32 id, u16 len ); cheat_error_t put_current_cheat( acl_entryid_t entry_id ); -cheat_error_t get_current_cheat( u32 *id, u32 *len, void **entry_array ); +cheat_error_t info_current_cheat( u32 *id, u32 *len ); +cheat_error_t get_current_cheat( u32 index, acl_entryid_t *id ); +cheat_error_t include_current_cheat( acl_entryid_t entry_id ); cheat_error_t fini_current_cheat(); cheat_error_t push_current_cheat( const char *filename, int is_using ); @@ -32,6 +35,6 @@ cheat_error_t pop_current_cheat( const char *filename, u32 chtid ); cheat_error_t chtid_current_cheat( const char *filename, u32 *pointer_id ); cheat_error_t chtlst_current_cheat( const char *filename, u8 pointer_data[256] ); -cheat_error_t apply_cheat( int mode, int szrom ); +cheat_error_t apply_cheat( int mode, u32 szrom, u16 bindkey, u32 varaddr, u32 *outsize ); #endif//_CHEAT_H_ diff --git a/source/arm11/cheat.c b/source/arm11/cheat.c index f6c2cf4..97867aa 100644 --- a/source/arm11/cheat.c +++ b/source/arm11/cheat.c @@ -1,8 +1,14 @@ #include "arm11/acl.h" #include "arm11/cheat.h" #include "util.h" +#include +#include +#include -#define ROM_LOC (0x20000000u) + +#define MAKE_ENT(hole,key) ((key<<16) | hole) +#define ROM_LOC (0x20000000u) +#define GBA_KEYCODE(k) (0x3ff & (~(k))) #define SIZE_32M (32*1024*1024) #define MAX_HOOKPOINT 10 @@ -48,15 +54,41 @@ cheat_error_t put_current_cheat( acl_entryid_t entid ) else return CCHT_INVALID; } -cheat_error_t get_current_cheat( u32 *id, u32 *len, void **entry_array ) +cheat_error_t info_current_cheat( u32 *id, u32 *len ) { if( setting.chtId == 0 ) return CCHT_NOT_INIT; - *id = setting.chtId; - *len = setting.entLen; - *entry_array = setting.entArr; + if( id != NULL ) *id = setting.chtId; + if( len != NULL ) *len = setting.entLen; return CCHT_OK; } +cheat_error_t get_current_cheat( u32 index, acl_entryid_t *id ) +{ + if( setting.chtId == 0 ) return CCHT_NOT_INIT; + if( index < setting.entLen ) + { + acl_index_t val = setting.entArr[index]; + if( id != NULL ) *id = MAKE_ENT( index+1, val ); + return CCHT_OK; + } + else return CCHT_INVALID; +} + +cheat_error_t include_current_cheat( acl_entryid_t id ) +{ + if( setting.chtId == 0 ) return CCHT_NOT_INIT; + + int index = id & 0xffff; + if( index == 0 ) return CCHT_OK; + else if( index < setting.entLen ) + { + acl_index_t val = setting.entArr[index-1]; + if( val != 0 ) return CCHT_OK; + else return CCHT_INVALID; + } + else return CCHT_INVALID; +} + cheat_error_t fini_current_cheat() { if( setting.entArr ) free( setting.entArr ); @@ -67,7 +99,7 @@ cheat_error_t fini_current_cheat() } typedef instruction_t* CodeLocation; -#define CodeAtLocation(p) (*p) +#define CodeAtLocation(p) (*(p)) // ******************************************* // code for patch rom with cheat instruction @@ -75,7 +107,6 @@ typedef instruction_t* CodeLocation; #define GBACPU_PREFETCH 2 #define GBACPU_PREFETCH_BYTE (sizeof(instruction_t)*GBACPU_PREFETCH) -#define MAKE_ENT(hole,key) ((key<<16) | hole) const instruction_t HOOKPOINT_INSTR[] = { 0xe92d8000, // STMDB sp!, {pc} @@ -116,7 +147,7 @@ const instruction_t KEY_ONOFF_INSTR[] = { 0xe1df12b4, // ldrh r1, [pc, #36] ; 0x34 0xe1df22b2, // ldrh r2, [pc, #34] ; 0x36 0xe0000002, // and r0, r0, r2 - 0xe59f2010, // ldr r2, [pc, #16] ; 0x2c + 0xe59f201c, // ldr r2, [pc, #28] ; 0x38 0xe5d23000, // ldrb r3, [r2] 0xe1500001, // cmp r0, r1 0x02233001, // eoreq r3, r3, #1 ; 0x1 @@ -177,16 +208,16 @@ static int end_of_rom( CodeLocation addr, u32 size ) return sizeof(instruction_t) * (prom + 2 - addr); // consider the first 0x00000000/0xffffffff as in-using } -#define MASK_PC0( m ) (pc[0]&mask) -#define MASK_PC1( m ) (pc[1]&mask) -#define MASK_PC2( m ) (pc[2]&mask) -#define MASK_PC3( m ) (pc[3]&mask) -#define MASK_PC4( m ) (pc[4]&mask) -#define MASK_PC5( m ) (pc[5]&mask) -#define MASK_PC6( m ) (pc[6]&mask) -#define MASK_PC7( m ) (pc[7]&mask) -#define MASK_PC8( m ) (pc[8]&mask) -#define MASK_PC9( m ) (pc[9]&mask) +#define MASK_PC0( m ) (pc[0]&m) +#define MASK_PC1( m ) (pc[1]&m) +#define MASK_PC2( m ) (pc[2]&m) +#define MASK_PC3( m ) (pc[3]&m) +#define MASK_PC4( m ) (pc[4]&m) +#define MASK_PC5( m ) (pc[5]&m) +#define MASK_PC6( m ) (pc[6]&m) +#define MASK_PC7( m ) (pc[7]&m) +#define MASK_PC8( m ) (pc[8]&m) +#define MASK_PC9( m ) (pc[9]&m) static int rom_search_hookpoint( CodeLocation addr, int addrlen, CodeLocation hookpoint[MAX_HOOKPOINT] ) { @@ -270,7 +301,7 @@ static int cht_calc_needsize( int mode, int numirq ) return total + 1; } -static CodeLocation rom_fit_newsize( CodeLocation *rom, int realend, int totalsize ) +static CodeLocation rom_fit_newsize( CodeLocation rom, int realend, int totalsize, u32 *newsize ) { u32 size = realend + totalsize; if( size > SIZE_32M ) @@ -306,6 +337,7 @@ static CodeLocation rom_fit_newsize( CodeLocation *rom, int realend, int totalsi else if( nextPow2(size) != nextPow2(realend) ) { // 似乎没什么要动的 + *newsize = size + 1; // reserve a word for padding return rom + realend / sizeof(instruction_t); } @@ -319,7 +351,7 @@ static void rom_patch_hookpoint( CodeLocation start, CodeLocation hookpoint[MAX_ { CodeLocation hook_point = hookpoint[i]; memcpy( hook_point, HOOKPOINT_INSTR, HP_INSTR_SIZE ); - CodeAtLocation(hook_point[HP_WRAPPER_ADDR]) = addr + IW_INSTR_SIZE * i; + hook_point[HP_WRAPPER_ADDR] = addr + IW_INSTR_SIZE * i; } } @@ -361,7 +393,7 @@ static void rom_append_cheatproc( int mode, CodeLocation start, u16 bindkey, u32 if( val != 0 ) { acl_elemlen_t len; - acl_select_entry( MAKE_ENT(i, val), &len ); + acl_select_entry( MAKE_ENT(i+1, val), &len ); for( int j=0; j < len; ++j ) { acl_entry_get_armcode(j, start++); @@ -371,7 +403,7 @@ static void rom_append_cheatproc( int mode, CodeLocation start, u16 bindkey, u32 *start++ = 0; } -cheat_error_t apply_cheat( int mode, u32 szrom, u16 bindkey, u32 storagemem ) +cheat_error_t apply_cheat( int mode, u32 szrom, u16 bindkey, u32 storagemem, u32 *outsize ) { // try ignore patch if( mode == CHEAT_MODE_DISABLED ) return CCHT_OK; @@ -379,7 +411,7 @@ cheat_error_t apply_cheat( int mode, u32 szrom, u16 bindkey, u32 storagemem ) if( ACHTLIB_SUCCESS != acl_select_cheat_set( setting.chtId ) ) return CCHT_NO_CHEAT; - u32 romdata = (u32*)ROM_LOC; + CodeLocation romdata = ROM_LOC; int realend = end_of_rom(romdata, szrom); // find hook point @@ -390,12 +422,12 @@ cheat_error_t apply_cheat( int mode, u32 szrom, u16 bindkey, u32 storagemem ) // find free space to put new code int total_size = cht_calc_needsize( mode, n_hookpoint ); - CodeLocation page = rom_fit_newsize( romdata, realend, total_size ); + CodeLocation page = rom_fit_newsize( romdata, realend, total_size, outsize ); if( page == NULL ) return CCHT_NO_SPACE; // patching the rom rom_append_newirq( page, hookpoint, n_hookpoint ); rom_patch_hookpoint( page, hookpoint, n_hookpoint ); - rom_append_cheatproc( mode, page + n_hookpoint * IW_INSTR_LEN, bindkey, storagemem ); + rom_append_cheatproc( mode, page + n_hookpoint * IW_INSTR_LEN, GBA_KEYCODE(bindkey), storagemem ); return CCHT_OK; } \ No newline at end of file diff --git a/source/arm11/filebrowser.c b/source/arm11/filebrowser.c index 69b8d17..a1ac4e8 100644 --- a/source/arm11/filebrowser.c +++ b/source/arm11/filebrowser.c @@ -234,17 +234,13 @@ static atp_error_t disp_str( atp_callerdata_t data, atp_counter_t, atp_linecfg_t cfg->text = (atp_text_t)data; return ATP_SUCCESS; } -#define DEBUG( str ) atp_show(1, disp_str, str) -static atp_error_t select_region( atp_callerdata_t *dat, atp_counter_t index, atp_itemcfg_t *config ) +static atp_error_t select_region( atp_callerdata_t, atp_counter_t index, atp_itemcfg_t *config ) { - typedef u8 trunk[256]; static char text[16]; - trunk data = (trunk)dat; - u32 id = *(u32*)&data[sizeof(trunk) - sizeof(u32)]; - u32 *list = (u32*)&data[0]; + acl_region_t sreg; - acl_chtid_t sid; + acl_chtid_t sid, id; if( ACHTLIB_SUCCESS != acl_query_cheat_set(index, &sid, &sreg) ) { config->text = "无效数据"; @@ -266,20 +262,19 @@ static atp_error_t select_region( atp_callerdata_t *dat, atp_counter_t index, at default: t = "其他语种"; break; } ee_sprintf(text, "%c-%s", 'A'+(char)index, t); - u8 inlist = 0; - for( int i=0; i+1 < sizeof(trunk)/sizeof(u32); ++i ) - { - u32 t = list[i]; - if( t==0 ) break; - if( t == sid ){ - inlist = 1; - break; - } - } + + if( CCHT_NOT_INIT == info_current_cheat( &id, NULL ) ) + id = 0; + config->text = text; config->value = index; - config->extra_text = sid == id ? "已启用" : (inlist ? "未启用" : "未设置"); - config->extra_text_color = sid == id ? ATP_COLOR_GREEN : ATP_COLOR_LIGHT; + + // show saved information + if( sid == id ) + { + config->extra_text = "已启用"; + config->extra_text_color = ATP_COLOR_GREEN; + } return ATP_SUCCESS; } @@ -291,6 +286,15 @@ static atp_error_t select_holes( atp_callerdata_t, atp_counter_t index, atp_item cfg->text = text; else cfg->text = "无效数据"; cfg->value = 1+index; + + // show saved information + acl_entryid_t id; + if( CCHT_OK == get_current_cheat( index, &id ) && ENT_USING(id) ) + { + cfg->extra_text = "开"; + cfg->extra_text_color = ATP_COLOR_GREEN; + } + return ATP_SUCCESS; } @@ -299,6 +303,13 @@ static atp_error_t select_onoff( atp_callerdata_t data, atp_counter_t index, atp acl_entryid_t eid = (acl_entryid_t)data; cfg->text = index == 0 ? "不开启" : "开启"; cfg->value = index << 16 | eid; + + // show saved information + if( CCHT_OK == include_current_cheat((acl_entryid_t)cfg->value) ) + { + cfg->extra_text = "选中"; + cfg->extra_text_color = ATP_COLOR_GREEN; + } return ATP_SUCCESS; } @@ -318,6 +329,12 @@ static atp_error_t select_keys( atp_callerdata_t data, atp_counter_t index, atp_ } acl_entryid_t eid = (acl_entryid_t)data; cfg->value = index<<16 | eid; + + if( CCHT_OK == include_current_cheat((acl_entryid_t)cfg->value) ) + { + cfg->extra_text = "选中"; + cfg->extra_text_color = ATP_COLOR_GREEN; + } return ATP_SUCCESS; } @@ -399,25 +416,27 @@ static atp_pageopt_t serve_on_key( atp_callerdata_t data, atp_counter_t index, a uint8_t status = DISP_REGION; atp_counter_t defi = 0; acl_entryid_t eid = 0; - char cheat_cfg_file[9]; - strncpy(cheat_cfg_file, serial, 4); - strcpy(cheat_cfg_file+4, ".cht"); - cheat_cfg_file[8] = '\0'; + while( status != DISP_DONE ) { if( status == DISP_REGION ) { - u8 all_cheat_ids[256]; - chtlst_current_cheat( cheat_cfg_file, all_cheat_ids ); - chtid_current_cheat( cheat_cfg_file, all_cheat_ids + sizeof(all_cheat_ids)-sizeof(u32) ); - res = atp_select("选择一个金手指配置", len, select_region, NULL, all_cheat_ids, defi, 0, &item ); + res = atp_select("选择一个金手指配置", len, select_region, NULL, NULL, defi, 0, &item ); if( res == ATP_SUCCESS ) { defi = item; - acl_chtid_t sid; + acl_chtid_t sid, ccid; + acl_elemlen_t len, cclen; acl_query_cheat_set((acl_index_t)item, &sid, NULL ); acl_select_cheat_set( sid ); - pop_current_cheat( cheat_cfg_file, sid ); + acl_select_entry(0, len); + if( CCHT_OK == info_current_cheat(&ccid, &cclen) ) + { + // SKIP the init process when id and len is the same + if( ccid != sid || cclen != len ) + init_current_cheat( sid, len ); + } + else init_current_cheat( sid, len ); eid = 0; status = DISP_HOLES; } @@ -430,7 +449,7 @@ static atp_pageopt_t serve_on_key( atp_callerdata_t data, atp_counter_t index, a else if( status == DISP_HOLES ) { acl_select_entry(0, &cnt); - res = atp_select("选择一个金手指项目", cnt, select_holes, NULL, NULL, eid > 0 ? (eid&0xff)-1 : 0, 0, &item); + res = atp_select("选择一个金手指项目", cnt, select_holes, NULL, NULL, eid > 0 ? (eid&0xffff)-1 : 0, 0, &item); if( res == ATP_SUCCESS ) { eid = (acl_entryid_t)item; @@ -448,9 +467,7 @@ static atp_pageopt_t serve_on_key( atp_callerdata_t data, atp_counter_t index, a res = atp_select("选择此项目对应的设置", cnt==0 ? 2:cnt, cnt==0 ? select_onoff : select_keys, NULL, (atp_callerdata_t)eid, 0, 0, &item); if( res == ATP_SUCCESS ) { - char tmp[20]; - ee_sprintf(tmp, "sel %08lx", item); - DEBUG(tmp); + put_current_cheat( (acl_entryid_t)item ); status = DISP_HOLES; } else if( res == ATP_NO_ACTION ) diff --git a/source/arm11/open_agb_firm.c b/source/arm11/open_agb_firm.c index 9217d82..3070457 100644 --- a/source/arm11/open_agb_firm.c +++ b/source/arm11/open_agb_firm.c @@ -66,6 +66,7 @@ #define SAVE_POLICY_SRAM 2 #define SAVE_POLICY_POPUP 3 #define SAVE_POLICY_SIZE 4 +#define CHEAT_INUSE_ADDR (0x3007FE0u) typedef struct { @@ -128,7 +129,7 @@ static OafConfig g_oafConfig = // [by-anod] , SAVE_POLICY_GBADB // savePolicy , 0 // cheatMode - , KEY_L|KEY_R|KEY_DOWN|KEY_SELECT + , KEY_L|KEY_R|KEY_DDOWN|KEY_SELECT }; static KHandle g_frameReadyEvent = 0; @@ -389,6 +390,10 @@ static Result loadGbaRom(const char *const path, u32 *const romSizeOut) while((res = fRead(f, ptr, 0x100000u, &read)) == RES_OK && read == 0x100000u) ptr += 0x100000u; + if( g_oafConfig.cheatMode != CHEAT_MODE_DISABLED ) + { + apply_cheat( g_oafConfig.cheatMode, fileSize, g_oafConfig.cheatKeys, CHEAT_INUSE_ADDR, &filesize ); + } *romSizeOut = fixRomPadding(fileSize); } else res = RES_ROM_TOO_BIG;