oaf-boost/source/arm11/keyremix.c
anod 72fdff8858 尝试修复一个模拟长按的问题:
条件:互换L/R的映射 + 模拟长按绑定游戏内L,启用后,按L会激发而不是R,但是L和R互换了,应该是R激发
2023-05-04 14:23:51 +08:00

206 lines
6.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <string.h>
#include "fs.h"
#include "fsutil.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_phykey = 0;
static conkey_t prev_conkey = 0;
static conkey_t blind_conkey;
static u16 flags_holding = 0;
#define DIR_SEPARATOR "/"
#define OUTPUT_DIR (KEYREMIX_OUTPUT_DIR DIR_SEPARATOR)
#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金手指放首位REMAP紧跟金手指HOLD在后面
key_remix_t temp[KEY_REMIX_LIMIT+1];
// 第一次循环扫描得到各remix_type数量用于定位在数组的位置
int has_cheat=0, rem_count=0, valid_count=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
&& p->device_keys != 0
&& p->game_keys != 0 )
{
valid_count++;
if( p->remix_type == REMIX_TYPE_REMAP ) rem_count++;
if( p->device_keys & CON_KEY_MASK )
blind_conkey |= p->device_keys;
}
}
// 第二次循环根据remix_type放置到数组特定位置
int j=has_cheat;
int k=j+rem_count;
for( int i=0; i < KEY_REMIX_LIMIT; ++i )
{
key_remix_t *p = &g_keyremixConfig[i];
if( p->remix_type == REMIX_TYPE_CHEAT )
{
continue;
}
else if( p->remix_type == REMIX_TYPE_REMAP
&& p->device_keys != 0
&& p->game_keys != 0 )
{
temp[j].remix_type = p->remix_type;
temp[j].device_keys = p->device_keys;
temp[j].game_keys = p->game_keys;
++j;
}
else if( p->remix_type == REMIX_TYPE_HOLD
&& p->device_keys != 0
&& p->game_keys != 0 )
{
temp[k].remix_type = p->remix_type;
temp[k].device_keys = p->device_keys;
temp[k].game_keys = p->game_keys;
++k;
}
}
memcpy( g_keyremixConfig, temp, sizeof(g_keyremixConfig) );
frozen_start = &g_keyremixConfig[has_cheat];
frozen_end = &g_keyremixConfig[has_cheat+valid_count];
}
void keyremix_update( uint16_t active_cheatkey )
{
phykey_t now = hidKeysHeld();
conkey_t cur = 0;
u8 init_cur = 0;
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_phykey, 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 )
{
if( init_cur == 0 )
{
init_cur = 1;
cur = res;
}
uint16_t flag = 1<<holding_pos++;
uint16_t oldf = flags_holding;
if( now_release(now, prev_phykey, p->device_keys) )
flags_holding ^= flag;
if( flags_holding & flag )
{
// exclude console keys is up
res |= now_release(cur, prev_conkey, 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_phykey = now;
prev_conkey = cur;
}
const char* keyremix_load( const char *file )
{
char output[512];
int len = strlen( file ) + strlen(OUTPUT_DIR);
if( len+1 > 512 ) return "文件名太长,无法保存";
strcpy( output, OUTPUT_DIR );
strcpy( &output[strlen(OUTPUT_DIR)], file );
output[len] = '\0';
output[len-1] = 'm';
output[len-2] = 'r';
output[len-3] = 'k';
FILINFO fi;
const char *retval = NULL;
if( fStat(output, &fi) == RES_OK )
{
u8 dat[sizeof(g_keyremixConfig)];
if( RES_OK == fsQuickRead(output, dat, sizeof(dat) ) )
memcpy( g_keyremixConfig, dat, sizeof(g_keyremixConfig) );
else retval = "读文件失败";
}
else retval = "文件不存在";
return retval;
}
const char* keyremix_dump( const char *file )
{
char output[512];
int len = strlen( file ) + strlen(OUTPUT_DIR);
if( len+1 > 512 ) return "文件名太长,无法保存";
strcpy( output, OUTPUT_DIR );
strcpy( &output[strlen(OUTPUT_DIR)], file );
output[len] = '\0';
output[len-1] = 'm';
output[len-2] = 'r';
output[len-3] = 'k';
const char *retval = NULL;
if( RES_OK != fsQuickWrite(output, g_keyremixConfig, sizeof(g_keyremixConfig)) )
retval = "保存失败";
return retval;
}