#include #include "fs.h" #include "drivers/lgy.h" #include "arm11/keyremix.h" key_remix_t g_keyremixConfig[KEY_REMIX_LIMIT]; static key_remix_t *frozen_start, *frozen_end; static phykey_t prev_status = 0; static conkey_t blind_conkey; static u16 flags_holding = 0; #define VKEY_HOME (1u<<21) #define now_release( now, prev, key ) ((~(now))&(prev)&(key)) #define CON_KEY_MASK (KEY_A|KEY_B|KEY_L|KEY_R|KEY_SELECT|KEY_START|KEY_DUP|KEY_DDOWN|KEY_DLEFT|KEY_DRIGHT) uint16_t keyremix_cheatkey() { for(int i=0; i < KEY_REMIX_LIMIT; ++i) { if( g_keyremixConfig[i].remix_type == REMIX_TYPE_CHEAT ) return g_keyremixConfig[i].game_keys; } return DEFAULT_CHEATKEY; } void keyremix_freeze() { // 空白选项忽略,填充blind_conkey,金手指放首位 key_remix_t temp[KEY_REMIX_LIMIT+1]; int j=1, has_cheat=0; blind_conkey = 0; for( int i=0; i < KEY_REMIX_LIMIT; ++i ) { key_remix_t *p = &g_keyremixConfig[i]; if( p->remix_type == REMIX_TYPE_CHEAT ) { temp[0].remix_type = REMIX_TYPE_CHEAT; temp[0].device_keys = p->device_keys; temp[0].game_keys = p->game_keys; has_cheat = 1; } else if( p->remix_type != REMIX_TYPE_NONE ) { temp[j].remix_type = p->remix_type; temp[j].device_keys = p->device_keys; temp[j].game_keys = p->game_keys; if( p->device_keys & CON_KEY_MASK ) blind_conkey |= p->device_keys; ++j; } } memset( g_keyremixConfig, 0, sizeof(g_keyremixConfig) ); if( has_cheat ) { memcpy( g_keyremixConfig, temp, sizeof(key_remix_t)*j ); frozen_start = &g_keyremixConfig[1]; frozen_end = &g_keyremixConfig[j]; } else { memcpy( g_keyremixConfig, &temp[1], sizeof(key_remix_t)*(j-1) ); frozen_start = &g_keyremixConfig[0]; frozen_end = &g_keyremixConfig[j-1]; } } void keyremix_update( uint16_t active_cheatkey ) { phykey_t now = hidKeysHeld(); vu16 *hid_set = (vu16*)0x10141112; vu16 *hid_mode = (vu16*)0x10141110; if( hidGetExtraKeys(0) & KEY_HOME ) now |= VKEY_HOME; if( active_cheatkey && now_release(now, prev_status, VKEY_HOME) ) { *hid_mode = active_cheatkey; *hid_set = ~active_cheatkey; } else if( frozen_end == frozen_start )// 空白键位设置,走原来流程就好 { LGY_handleOverrides(); } else { conkey_t res = now & CON_KEY_MASK; // LGY_handleOverrides if(now & KEY_CPAD_MASK) res |= (now>>24) & KEY_DPAD_MASK; // unlink the blind console keys res &= ~blind_conkey; int holding_pos = 0; for( key_remix_t *p=frozen_start; p !=frozen_end; ++p ) { if( p->remix_type == REMIX_TYPE_REMAP ) { if( now & p->device_keys ) { res |= p->game_keys; } } else if( p->remix_type == REMIX_TYPE_HOLD ) { uint16_t flag = 1<device_keys) ) flags_holding ^= flag; if( flags_holding & flag ) { // exclude console keys is up res |= now_release(now, prev_status, p->game_keys) ^ p->game_keys; } else if( oldf != flags_holding )// release { res &= ~(p->game_keys); } } } *hid_mode = CON_KEY_MASK; *hid_set = ~res; } prev_status = now; } const char* keyremix_load( char *file ) { FILINFO fi; int len = strlen( file ); file[len-1] = 'm'; file[len-2] = 'r'; file[len-3] = 'k'; const char *retval = NULL; if( fStat(file, &fi) == RES_OK ) { u8 dat[sizeof(g_keyremixConfig)]; if( RES_OK == fsQuickRead(file, dat, 8 ) ) memcpy( g_keyremixConfig, dat, sizeof(g_keyremixConfig) ); else retval = "读文件失败"; } else retval = "文件不存在"; file[len-1] = 'a'; file[len-2] = 'b'; file[len-3] = 'g'; return retval; } const char* keyremix_dump( char *file ) { FILINFO fi; int len = strlen( file ); file[len-1] = 'm'; file[len-2] = 'r'; file[len-3] = 'k'; const char *retval = NULL; if( RES_OK != fsQuickWrite(file, g_keyremixConfig, sizeof(g_keyremixConfig) ) ) retval = "保存失败"; file[len-1] = 'a'; file[len-2] = 'b'; file[len-3] = 'g'; return retval; }