mirror of
https://gitee.com/anod/open_agb_firm.git
synced 2025-05-07 06:14:12 +08:00
232 lines
7.1 KiB
C
232 lines
7.1 KiB
C
#include <string.h>
|
||
#include "fs.h"
|
||
#include "fsutil.h"
|
||
#include "drivers/gfx.h"
|
||
#include "arm11/drivers/mcu.h"
|
||
// @MERGE 231006 START
|
||
#include "drivers/lgy11.h"
|
||
// @MERGE 231006 END
|
||
#include "arm11/anopatch.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 u8 val_3dslider;
|
||
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|KEY_ZL|KEY_ZR)
|
||
|
||
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;
|
||
}
|
||
|
||
static void update_brightness()
|
||
{
|
||
u16 backlightNow;
|
||
u16 val = (u16)MCU_get3dSliderPosition();
|
||
u16 n = val < val_3dslider ? val_3dslider - val : val - val_3dslider;
|
||
if( n > 5 ) // 峰哥反馈说有精度问题,所以改下,给个最小精度范围,范围外才进行修改
|
||
{
|
||
val_3dslider = val;
|
||
backlightNow = 48000 * val / 256;
|
||
backlightNow = (backlightNow%50) > 50 ? 101+backlightNow/100 : 100+backlightNow/100;
|
||
setBrightness(backlightNow);
|
||
}
|
||
}
|
||
|
||
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_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];
|
||
|
||
val_3dslider = MCU_get3dSliderPosition();
|
||
}
|
||
|
||
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 )// 空白键位设置,走原来流程就好
|
||
{
|
||
// @MERGE 231006 START
|
||
if( now & KEY_CPAD_MASK ){
|
||
*hid_set = (now>>24) ^ KEY_DPAD_MASK;
|
||
*hid_mode = KEY_DPAD_MASK;
|
||
}
|
||
else *hid_mode = 0;
|
||
// @MERGE 231006 END
|
||
}
|
||
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;
|
||
|
||
update_brightness();
|
||
}
|
||
|
||
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;
|
||
} |