diff --git a/source/arm11/acl.c b/source/arm11/acl.c index fb2aaf8..5f1c6c8 100644 --- a/source/arm11/acl.c +++ b/source/arm11/acl.c @@ -398,12 +398,13 @@ acl_error_t acl_select_entry( acl_entryid_t id, acl_elemlen_t *count) if( gblcht.listc == 0 ) return ACHTLIB_INVALID; if( gblcht.setid == 0 ) return ACHTLIB_INVALID; - FHandle fd; - if( RES_OK != fOpen(&fd, gblcht.aclfile, FA_OPEN_EXISTING | FA_READ) ) - return ACHTLIB_INVALID; - + acl_error_t r = ACHTLIB_SUCCESS; if( gblset.entry.entid != id ) { + FHandle fd; + if( RES_OK != fOpen(&fd, gblcht.aclfile, FA_OPEN_EXISTING | FA_READ) ) + return ACHTLIB_INVALID; + // update gblset.entry if( RES_OK != fLseek(fd, gblset.seek + sizeof(uint16_t)) ) { @@ -434,17 +435,17 @@ acl_error_t acl_select_entry( acl_entryid_t id, acl_elemlen_t *count) } if( found ) break; } + + r = load_data(fd); + fClose( fd ); } + if( count!=NULL ) *count = gblset.entry.datasz; - - acl_error_t r = load_data(fd); - fClose( fd ); return r; } acl_error_t acl_entry_get_label( acl_index_t index, acl_text_t *label ) { - if( label == NULL ) return ACHTLIB_SUCCESS; if( gblcht.serc == 0 ) return ACHTLIB_NOT_OPEN; if( gblcht.listc == 0 ) return ACHTLIB_INVALID; if( gblcht.setid == 0 ) return ACHTLIB_INVALID; @@ -452,7 +453,7 @@ acl_error_t acl_entry_get_label( acl_index_t index, acl_text_t *label ) if( index < gblset.entry.datasz ) { uint16_t *d = (uint16_t*)gblset.entdata; - *label = gblset.strings + d[index]; + if( label != NULL ) *label = gblset.strings + d[index]; return ACHTLIB_SUCCESS; } else return ACHTLIB_NOT_FOUND; @@ -460,7 +461,6 @@ acl_error_t acl_entry_get_label( acl_index_t index, acl_text_t *label ) acl_error_t acl_entry_get_armcode( acl_index_t index, acl_armcode_t *code ) { - if( code == NULL ) return ACHTLIB_SUCCESS; if( gblcht.serc == 0 ) return ACHTLIB_NOT_OPEN; if( gblcht.listc == 0 ) return ACHTLIB_INVALID; if( gblcht.setid == 0 ) return ACHTLIB_INVALID; @@ -468,8 +468,8 @@ acl_error_t acl_entry_get_armcode( acl_index_t index, acl_armcode_t *code ) if( index < gblset.entry.datasz ) { uint32_t *d = (uint32_t*)gblset.entdata; - *code = d[index]; + if( code != NULL ) *code = d[index]; return ACHTLIB_SUCCESS; } else return ACHTLIB_NOT_FOUND; -} \ No newline at end of file +} diff --git a/source/arm11/filebrowser.c b/source/arm11/filebrowser.c index a5ed30c..23d581c 100644 --- a/source/arm11/filebrowser.c +++ b/source/arm11/filebrowser.c @@ -307,8 +307,22 @@ static atp_error_t select_holes( atp_callerdata_t, atp_counter_t index, atp_item static atp_error_t select_onoff( atp_callerdata_t data, atp_counter_t index, atp_itemcfg_t *cfg ) { acl_entryid_t eid = (acl_entryid_t)data; - cfg->text = index == 0 ? "不开启" : "开启"; - cfg->value = index << 16 | eid; + eid &= 0xffff; + if( index == 0 ) + { + cfg->text = "不开启"; + cfg->value = eid; + } + else if( index == 1 ) + { + cfg->text = "开启"; + cfg->value = 1<<16 | eid; + } + else + { + cfg->text = "开启中间值[非标]"; + cfg->value = 0; + } // show saved information if( CCHT_OK == include_current_cheat((acl_entryid_t)cfg->value) ) @@ -319,6 +333,87 @@ static atp_error_t select_onoff( atp_callerdata_t data, atp_counter_t index, atp return ATP_SUCCESS; } +ALWAYS_INLINE u16 calc_step( u16 value ) +{ + u16 n = value / 50; + if( n == 0 ) return 1; + else + { + u16 base = 1; + while( n > 10 ) + { + n = n/10; + base *= 10; + } + if( n < 5 ) return base * 5; + else return base * 10; + } +} + +static atp_error_t step_provider( atp_callerdata_t mix, atp_counter_t index, atp_itemcfg_t *cfg ) +{ + static char number[8]; + u16 max = mix & 0xffff; + u16 step = mix >> 16; + u16 res = step * (index+1); + ee_snprintf( number, 8, "%d", res < max ? res : max ); + cfg->text = number; + cfg->value = res; + return ATP_SUCCESS; +} + +static atp_error_t handle_onoff_entry( acl_entryid_t id, atp_itemval_t *item ) +{ +#define DEFAULT_ONOFF_HANDLER atp_select("选择此项目对应的设置", 2, select_onoff, NULL, (atp_callerdata_t)id, 0, 0, item); +#define ONOFF_SAFE_CALLACL( statement ) if( ACHTLIB_SUCCESS != statement ) return DEFAULT_ONOFF_HANDLER; + + acl_elemlen_t codelen; + + if( codelen > 4 )// more than 2 address + return DEFAULT_ONOFF_HANDLER; + + u16 targetval = 0; + acl_armcode_t code; + + // one address + if( codelen == 2 ) + { + ONOFF_SAFE_CALLACL( acl_entry_get_armcode(1, &code) ); + targetval = code & 0xff; + } + // two addresses + else if( codelen == 4 ) + { + u32 addr0, addr1; + ONOFF_SAFE_CALLACL( acl_entry_get_armcode(0, &addr0) ); + ONOFF_SAFE_CALLACL( acl_entry_get_armcode(2, &addr1) ); + if( (addr0 & 1) || (addr0 | 1) != addr1 ) // valid u16 address + return DEFAULT_ONOFF_HANDLER; + + ONOFF_SAFE_CALLACL( acl_entry_get_armcode(1, &code) ); + targetval = code & 0xff; + ONOFF_SAFE_CALLACL( acl_entry_get_armcode(3, &code) ); + targetval |= (code & 0xff) << 8; + } + // more than two address, should not overwrite values + else return DEFAULT_ONOFF_HANDLER; + + atp_error_t res = atp_select( "选择此项目对应的设置", 3, select_onoff, NULL, targetval << 16 | id, 0, 0, item ); + if( res == ATP_SUCCESS && *item == 0 ) + { + char title[24]; + ee_snprintf( title, sizeof(title), "默认值:%d", targetval ); + u16 step = calc_step( targetval ); + atp_counter_t n = (targetval-1+step)/step; + res = atp_select(title, n, step_provider, NULL, (atp_callerdata_t)(step<<16|targetval), n, 0, item ); + if( res == ATP_SUCCESS && *item != targetval ) + overwrite_current_cheat( 1<<16|id, item ); + + *item = 1<<16 | id; + } + else return res; +} + static atp_error_t select_keys( atp_callerdata_t data, atp_counter_t index, atp_itemcfg_t *cfg ) { acl_text_t text; @@ -423,6 +518,11 @@ static atp_pageopt_t serve_on_key( atp_callerdata_t data, atp_counter_t index, a #define DISP_REGION 1 #define DISP_HOLES 2 #define DISP_KEYS 3 +#define SAFE_CALLACL( r ) if( ACHTLIB_SUCCESS!=r ) \ + {\ + res = WAIT_ON_ERRPAGE( display_selcht );\ + break;\ + } uint8_t status = DISP_REGION; atp_counter_t defi = 0; @@ -441,9 +541,10 @@ static atp_pageopt_t serve_on_key( atp_callerdata_t data, atp_counter_t index, a acl_chtid_t sid; acl_elemlen_t len; u32 ccid, cclen; - acl_query_cheat_set((acl_index_t)item, &sid, NULL ); - acl_select_cheat_set( sid ); - acl_select_entry(0, &len); + SAFE_CALLACL( acl_query_cheat_set((acl_index_t)item, &sid, NULL ) ); + SAFE_CALLACL( acl_select_cheat_set( sid ) ); + SAFE_CALLACL( acl_select_entry(0, &len) ); + if( CCHT_OK == info_current_cheat(&ccid, &cclen) ) { // SKIP the init process when id and len is the same @@ -451,6 +552,7 @@ static atp_pageopt_t serve_on_key( atp_callerdata_t data, atp_counter_t index, a init_current_cheat( sid, len ); } else init_current_cheat( sid, len ); + eid = 0; status = DISP_HOLES; } @@ -462,12 +564,11 @@ 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); + SAFE_CALLACL( acl_select_entry(0, &cnt) ); 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; - acl_select_entry(eid, &cnt); status = DISP_KEYS; } else if( res == ATP_NO_ACTION ) @@ -478,7 +579,16 @@ static atp_pageopt_t serve_on_key( atp_callerdata_t data, atp_counter_t index, a } else // DISP_KEYS { - res = atp_select("选择此项目对应的设置", cnt==0 ? 2:cnt, cnt==0 ? select_onoff : select_keys, NULL, (atp_callerdata_t)eid, 0, 0, &item); + SAFE_CALLACL( acl_select_entry( eid, &cnt ) ); + if( cnt == 0 ) + { + SAFE_CALLACL( acl_select_entry( 1<<16 | eid, NULL ) ); + res = handle_onoff_entry( eid, &item ); + } + else + { + res = atp_select("选择此项目对应的设置", cnt, select_keys, NULL, (atp_callerdata_t)eid, 0, 0, &item); + } if( res == ATP_SUCCESS ) { put_current_cheat( (acl_entryid_t)item ); diff --git a/source/arm11/open_agb_firm.c b/source/arm11/open_agb_firm.c index 1f3747e..a65d184 100644 --- a/source/arm11/open_agb_firm.c +++ b/source/arm11/open_agb_firm.c @@ -397,7 +397,8 @@ static Result loadGbaRom(const char *const path, u32 *const romSizeOut) fClose(f); // use the gbaatm cheat - if( g_oafConfig.cheatMode != CHEAT_MODE_DISABLED && info_current_cheat(NULL, NULL) != CCHT_NOT_INIT ) + if( g_oafConfig.cheatMode != CHEAT_MODE_DISABLED + && info_current_cheat(NULL, NULL) == CCHT_OK ) { char gamecode[5]; memcpy( gamecode, ROM_LOC+0xac, 4 );