mirror of
https://gitee.com/anod/open_agb_firm.git
synced 2025-05-06 22:04:10 +08:00
175 lines
5.1 KiB
C
175 lines
5.1 KiB
C
#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_status = 0;
|
||
static conkey_t blind_conkey;
|
||
static u16 flags_holding = 0;
|
||
|
||
#define OUTPUT_DIR "keymaps/"
|
||
|
||
#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<<holding_pos++;
|
||
uint16_t oldf = flags_holding;
|
||
if( now_release(now, prev_status, p->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( 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;
|
||
} |