From 7832b9979c18171c69b1d23a03b25d3cd6178eed Mon Sep 17 00:00:00 2001
From: sin365 <353374337@qq.com>
Date: Wed, 5 Mar 2025 13:11:36 +0800
Subject: [PATCH] =?UTF-8?q?XMB=E7=95=8C=E9=9D=A2Input=E4=B9=9F=E7=BB=9F?=
 =?UTF-8?q?=E4=B8=80=E8=AE=BE=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../Assets/Script/AppMain/App.cs              |   3 +-
 .../Script/AppMain/AxiInput.Settings.meta     |   8 +
 .../GamingMultiKeysSetting.cs                 | 124 ++++++++++++
 .../GamingMultiKeysSetting.cs.meta            |   2 +
 .../UMAMEMultiKeysSetting.cs                  | 174 ++++++++++++++++
 .../UMAMEMultiKeysSetting.cs.meta             |   2 +
 .../AxiInput.Settings/XMBMultiKeysSetting.cs  | 154 ++++++++++++++
 .../XMBMultiKeysSetting.cs.meta               |   2 +
 .../AppMain/AxiInput/AxiInput.Struct.cs       |   1 +
 .../Script/AppMain/Common/PC_XBOXKEY.cs       |   1 +
 .../MameEmulator/UniInterface/UniKeyboard.cs  |  29 ++-
 .../IkeyMapperChanger/CommandChanger.cs       |   9 +-
 .../IkeyMapperChanger/GamingChanger.cs        |  41 ++--
 .../IkeyMapperChanger/NormalChanger.cs        |  94 +++++----
 .../Assets/Script/AppMain/Manager/AppInput.cs | 189 +-----------------
 .../UI/CommandDispatcher/CommandListener.cs   |  41 +++-
 .../UI/CommandDispatcher/ICommandListener.cs  |   6 +-
 17 files changed, 616 insertions(+), 264 deletions(-)
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings.meta
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/GamingMultiKeysSetting.cs
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/GamingMultiKeysSetting.cs.meta
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/UMAMEMultiKeysSetting.cs
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/UMAMEMultiKeysSetting.cs.meta
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/XMBMultiKeysSetting.cs
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/XMBMultiKeysSetting.cs.meta

diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs
index 12984eaf..b04e8c44 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs
@@ -72,19 +72,18 @@ namespace AxibugEmuOnline.Client.ClientCore
         public static void Init(bool isTest = false, string testSrvIP = "", bool bUseLocalWebApi = false, string mLocalWebApi = "")
         {
             log = new LogManager(OnLogOut);
-
             //其他平台必要的初始化
             if (UnityEngine.Application.platform == RuntimePlatform.PSP2)
             {
                 PSP2Init();
             }
+            input = new AppInput();
             FileDownloader = new FileDownloader();
             settings = new AppSettings();
             network = new NetworkHelper();
             login = new AppLogin();
             chat = new AppChat();
             user = new UserDataManager();
-            input = new AppInput();
             emu = new AppEmu();
             httpAPI = new HttpAPI();
             if (bUseLocalWebApi)
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings.meta b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings.meta
new file mode 100644
index 00000000..a924eaef
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 91746af636f351140a4796dc4e98be6d
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/GamingMultiKeysSetting.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/GamingMultiKeysSetting.cs
new file mode 100644
index 00000000..8aac4e3f
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/GamingMultiKeysSetting.cs
@@ -0,0 +1,124 @@
+using AxibugEmuOnline.Client;
+using AxibugEmuOnline.Client.Common;
+using AxibugEmuOnline.Client.Manager;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+namespace Assets.Script.AppMain.AxiInput.Settings
+{
+    public class GamingMultiKeysSetting : MultiKeysSetting
+    {
+        public GamingSingleKeysSeting[] controllers;
+
+        public GamingMultiKeysSetting()
+        {
+            controllers = new GamingSingleKeysSeting[1];
+            for (int i = 0; i < controllers.Length; i++)
+                controllers[i] = new GamingSingleKeysSeting();
+        }
+
+        public bool HadAnyKeyDown(int index)
+        {
+            if (index >= controllers.Length)
+                return false;
+            return controllers[index].HadAnyKeyDown();
+        }
+        public void ClearAll()
+        {
+            for (int i = 0; i < controllers.Length; i++)
+            {
+                controllers[i].ClearAll();
+            }
+        }
+
+        public void LoadDefaultSetting()
+        {
+            ClearAll();
+
+#if UNITY_PSP2 && !UNITY_EDITOR
+            if (Application.platform == RuntimePlatform.PSP2)
+            {
+                controllers[0].SetKey((ulong)EnumCommand.OptionMenu, AxiInputEx.ByKeyCode(PSVitaKey.L));
+                controllers[0].SetKey((ulong)EnumCommand.OptionMenu, AxiInputEx.ByKeyCode(PSVitaKey.R));
+                controllers[0].ColletAllKey();
+            }
+#endif
+            controllers[0].SetKey((ulong)EnumCommand.OptionMenu, AxiInputEx.ByKeyCode(KeyCode.Escape));
+
+            //TODO 待补全
+            controllers[0].SetKey((ulong)EnumCommand.OptionMenu, AxiInputEx.ByKeyCode(PC_XBOXKEY.L));
+            controllers[0].SetKey((ulong)EnumCommand.OptionMenu, AxiInputEx.ByKeyCode(PC_XBOXKEY.R));
+
+            controllers[0].ColletAllKey();
+        }
+    }
+
+    public class GamingSingleKeysSeting : SingleKeysSetting
+    {
+        Dictionary<EnumCommand, List<AxiInput>> DictSkey2AxiInput = new Dictionary<EnumCommand, List<AxiInput>>();
+        AxiInput[] AxiInputArr = null;
+
+        public void SetKey(ulong Key, AxiInput input)
+        {
+            List<AxiInput> list;
+            if (!DictSkey2AxiInput.TryGetValue((EnumCommand)Key, out list))
+                list = DictSkey2AxiInput[(EnumCommand)Key] = ObjectPoolAuto.AcquireList<AxiInput>();
+            list.Add(input);
+        }
+
+        public bool GetKey(EnumCommand Key)
+        {
+            List<AxiInput> list;
+            if (!DictSkey2AxiInput.TryGetValue(Key, out list))
+                return false;
+            for (int i = 0; i < list.Count; i++)
+            {
+                if (list[i].IsKey())
+                    return true;
+            }
+            return false;
+        }
+
+        public void ClearAll()
+        {
+            foreach (List<AxiInput> singlelist in DictSkey2AxiInput.Values)
+                ObjectPoolAuto.Release(singlelist);
+            DictSkey2AxiInput.Clear();
+            AxiInputArr = null;
+        }
+
+        public void ColletAllKey()
+        {
+            List<AxiInput> list = ObjectPoolAuto.AcquireList<AxiInput>();
+            foreach (List<AxiInput> singlelist in DictSkey2AxiInput.Values)
+                list.AddRange(singlelist);
+            AxiInputArr = list.ToArray();
+            ObjectPoolAuto.Release(list);
+        }
+
+        public bool HadAnyKeyDown()
+        {
+            if (AxiInputArr == null)
+                return false;
+
+            for (int i = 0; AxiInputArr.Length > 0; i++)
+            {
+                if (AxiInputArr[i].IsKey())
+                    return true;
+            }
+            return false;
+        }
+
+        public bool GetKey(ulong Key)
+        {
+            return GetKey((EnumCommand)Key);
+        }
+
+        internal EnumCommand[] GetAllCmd()
+        {
+            return DictSkey2AxiInput.Keys.ToArray();
+        }
+
+    }
+}
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/GamingMultiKeysSetting.cs.meta b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/GamingMultiKeysSetting.cs.meta
new file mode 100644
index 00000000..5a6854ca
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/GamingMultiKeysSetting.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 47f6f518d357c334c802a7aac4d507dc
\ No newline at end of file
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/UMAMEMultiKeysSetting.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/UMAMEMultiKeysSetting.cs
new file mode 100644
index 00000000..518a52e5
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/UMAMEMultiKeysSetting.cs
@@ -0,0 +1,174 @@
+using AxibugEmuOnline.Client.Common;
+using AxibugEmuOnline.Client.Manager;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Assets.Script.AppMain.AxiInput.Settings
+{
+    public enum UMAMEKSingleKey
+    {
+        INSERT_COIN,
+        GAMESTART,
+        UP,
+        DOWN,
+        LEFT,
+        RIGHT,
+        BTN_A,
+        BTN_B,
+        BTN_C,
+        BTN_D,
+        BTN_E,
+        BTN_F
+    }
+    public class UMAMEMultiKeysSetting : MultiKeysSetting
+    {
+        public UMAMEKSingleKeysSeting[] controllers;
+
+        public UMAMEMultiKeysSetting()
+        {
+            controllers = new UMAMEKSingleKeysSeting[4];
+            for (int i = 0; i < controllers.Length; i++)
+                controllers[i] = new UMAMEKSingleKeysSeting();
+        }
+
+        public bool HadAnyKeyDown(int index)
+        {
+            if (index >= controllers.Length)
+                return false;
+            return controllers[index].HadAnyKeyDown();
+        }
+        public void ClearAll()
+        {
+            for (int i = 0; i < controllers.Length; i++)
+            {
+                controllers[i].ClearAll();
+            }
+        }
+
+        public void LoadDefaultSetting()
+        {
+            ClearAll();
+#if UNITY_PSP2 && !UNITY_EDITOR
+            //PSV 摇杆
+            controllers[0].SetKey((ulong)MAMEKSingleKey.GAMESTART, AxiInputEx.ByKeyCode(PSVitaKey.Start));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.INSERT_COIN, AxiInputEx.ByKeyCode(PSVitaKey.Select));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.UP, AxiInputEx.ByKeyCode(PSVitaKey.Up));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.DOWN, AxiInputEx.ByKeyCode(PSVitaKey.Down));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.LEFT, AxiInputEx.ByKeyCode(PSVitaKey.Left));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.RIGHT, AxiInputEx.ByKeyCode(PSVitaKey.Right));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_A, AxiInputEx.ByKeyCode(PSVitaKey.Block));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_B, AxiInputEx.ByKeyCode(PSVitaKey.Cross));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_C, AxiInputEx.ByKeyCode(PSVitaKey.Circle));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_D, AxiInputEx.ByKeyCode(PSVitaKey.Triangle));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_E, AxiInputEx.ByKeyCode(PSVitaKey.L));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_F, AxiInputEx.ByKeyCode(PSVitaKey.R));
+            //PSV 摇杆
+            controllers[0].SetKey((ulong)MAMEKSingleKey.UP, AxiInputEx.ByAxis(AxiInputAxisType.UP));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.DOWN, AxiInputEx.ByAxis(AxiInputAxisType.DOWN));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.LEFT, AxiInputEx.ByAxis(AxiInputAxisType.LEFT));
+            controllers[0].SetKey((ulong)MAMEKSingleKey.RIGHT, AxiInputEx.ByAxis(AxiInputAxisType.RIGHT));
+            controllers[0].ColletAllKey();
+            return;
+#endif
+            #region P1
+            //P1 键盘
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.GAMESTART, AxiInputEx.ByKeyCode(KeyCode.Alpha1));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.INSERT_COIN, AxiInputEx.ByKeyCode(KeyCode.Alpha5));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.UP, AxiInputEx.ByKeyCode(KeyCode.W));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.DOWN, AxiInputEx.ByKeyCode(KeyCode.S));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.LEFT, AxiInputEx.ByKeyCode(KeyCode.A));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.RIGHT, AxiInputEx.ByKeyCode(KeyCode.D));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.BTN_A, AxiInputEx.ByKeyCode(KeyCode.J));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.BTN_B, AxiInputEx.ByKeyCode(KeyCode.K));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.BTN_C, AxiInputEx.ByKeyCode(KeyCode.L));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.BTN_D, AxiInputEx.ByKeyCode(KeyCode.U));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.BTN_E, AxiInputEx.ByKeyCode(KeyCode.I));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.BTN_F, AxiInputEx.ByKeyCode(KeyCode.O));
+
+            //Axis
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.UP, AxiInputEx.ByAxis(AxiInputAxisType.UP));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.DOWN, AxiInputEx.ByAxis(AxiInputAxisType.DOWN));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.LEFT, AxiInputEx.ByAxis(AxiInputAxisType.LEFT));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.RIGHT, AxiInputEx.ByAxis(AxiInputAxisType.RIGHT));
+
+            //P1 UGUI
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.GAMESTART, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.POTION_1));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.INSERT_COIN, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.POTION_2));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.UP, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.UP));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.DOWN, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.DOWN));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.LEFT, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.LEFT));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.RIGHT, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.RIGHT));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.BTN_A, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_1));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.BTN_B, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_2));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.BTN_C, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_3));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.BTN_D, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_4));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.BTN_E, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_5));
+            controllers[0].SetKey((ulong)UMAMEKSingleKey.BTN_F, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_6));
+
+            controllers[0].ColletAllKey();
+            #endregion
+        }
+    }
+    public class UMAMEKSingleKeysSeting : SingleKeysSetting
+    {
+        Dictionary<UMAMEKSingleKey, List<AxiInput>> DictSkey2AxiInput = new Dictionary<UMAMEKSingleKey, List<AxiInput>>();
+        AxiInput[] AxiInputArr = null;
+
+        public void SetKey(ulong Key, AxiInput input)
+        {
+            List<AxiInput> list;
+            if (!DictSkey2AxiInput.TryGetValue((UMAMEKSingleKey)Key, out list))
+                list = DictSkey2AxiInput[(UMAMEKSingleKey)Key] = ObjectPoolAuto.AcquireList<AxiInput>();
+            list.Add(input);
+        }
+
+        public bool GetKey(UMAMEKSingleKey Key)
+        {
+            List<AxiInput> list;
+            if (!DictSkey2AxiInput.TryGetValue(Key, out list))
+                return false;
+            for (int i = 0; i < list.Count; i++)
+            {
+                if (list[i].IsKey())
+                    return true;
+            }
+            return false;
+        }
+
+        public bool GetKey(ulong Key)
+        {
+            return GetKey((UMAMEKSingleKey)Key);
+        }
+
+        public void ClearAll()
+        {
+            foreach (List<AxiInput> singlelist in DictSkey2AxiInput.Values)
+                ObjectPoolAuto.Release(singlelist);
+            DictSkey2AxiInput.Clear();
+            AxiInputArr = null;
+        }
+
+        public void ColletAllKey()
+        {
+            List<AxiInput> list = ObjectPoolAuto.AcquireList<AxiInput>();
+            foreach (List<AxiInput> singlelist in DictSkey2AxiInput.Values)
+                list.AddRange(singlelist);
+            AxiInputArr = list.ToArray();
+            ObjectPoolAuto.Release(list);
+        }
+
+        public bool HadAnyKeyDown()
+        {
+            if (AxiInputArr == null)
+                return false;
+
+            for (int i = 0; AxiInputArr.Length > 0; i++)
+            {
+                if (AxiInputArr[i].IsKey())
+                    return true;
+            }
+            return false;
+        }
+
+    }
+}
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/UMAMEMultiKeysSetting.cs.meta b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/UMAMEMultiKeysSetting.cs.meta
new file mode 100644
index 00000000..31eefb9e
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/UMAMEMultiKeysSetting.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 486aed2afcba6b94f86c1ae4e4aeaf02
\ No newline at end of file
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/XMBMultiKeysSetting.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/XMBMultiKeysSetting.cs
new file mode 100644
index 00000000..ef1b6294
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/XMBMultiKeysSetting.cs
@@ -0,0 +1,154 @@
+using AxibugEmuOnline.Client;
+using AxibugEmuOnline.Client.Common;
+using AxibugEmuOnline.Client.Manager;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using UnityEngine;
+
+namespace Assets.Script.AppMain.AxiInput.Settings
+{
+    public class XMBMultiKeysSetting : MultiKeysSetting
+    {
+        public XMBSingleKeysSeting[] controllers;
+
+        public XMBMultiKeysSetting()
+        {
+            controllers = new XMBSingleKeysSeting[1];
+            for (int i = 0; i < controllers.Length; i++)
+                controllers[i] = new XMBSingleKeysSeting();
+        }
+
+        public bool HadAnyKeyDown(int index)
+        {
+            if (index >= controllers.Length)
+                return false;
+            return controllers[index].HadAnyKeyDown();
+        }
+        public void ClearAll()
+        {
+            for (int i = 0; i < controllers.Length; i++)
+            {
+                controllers[i].ClearAll();
+            }
+        }
+
+        public void LoadDefaultSetting()
+        {
+            ClearAll();
+
+#if UNITY_PSP2 && !UNITY_EDITOR
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemUp, AxiInputEx.ByKeyCode(PSVitaKey.Up));
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemDown, AxiInputEx.ByKeyCode(PSVitaKey.Down));
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemLeft, AxiInputEx.ByKeyCode(PSVitaKey.Left));
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemRight, AxiInputEx.ByKeyCode(PSVitaKey.Right));
+            controllers[0].SetKey((ulong)EnumCommand.Enter, AxiInputEx.ByKeyCode(PSVitaKey.Circle));
+            controllers[0].SetKey((ulong)EnumCommand.Back, AxiInputEx.ByKeyCode(PSVitaKey.Cross));
+            controllers[0].SetKey((ulong)EnumCommand.OptionMenu, AxiInputEx.ByKeyCode(PSVitaKey.Triangle));
+            controllers[0].ColletAllKey();
+            return;
+#endif
+            //键盘
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemUp, AxiInputEx.ByKeyCode(KeyCode.W));
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemDown, AxiInputEx.ByKeyCode(KeyCode.S));
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemLeft, AxiInputEx.ByKeyCode(KeyCode.A));
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemRight, AxiInputEx.ByKeyCode(KeyCode.D));
+            controllers[0].SetKey((ulong)EnumCommand.Enter, AxiInputEx.ByKeyCode(KeyCode.J));
+            controllers[0].SetKey((ulong)EnumCommand.Back, AxiInputEx.ByKeyCode(KeyCode.K));
+            controllers[0].SetKey((ulong)EnumCommand.OptionMenu, AxiInputEx.ByKeyCode(KeyCode.I));
+
+            //Axis
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemUp, AxiInputEx.ByAxis(AxiInputAxisType.UP));
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemDown, AxiInputEx.ByAxis(AxiInputAxisType.DOWN));
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemLeft, AxiInputEx.ByAxis(AxiInputAxisType.LEFT));
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemRight, AxiInputEx.ByAxis(AxiInputAxisType.RIGHT));
+
+            //P1 UGUI
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemUp, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.UP));
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemDown, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.DOWN));
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemLeft, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.LEFT));
+            controllers[0].SetKey((ulong)EnumCommand.SelectItemRight, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.RIGHT));
+            controllers[0].SetKey((ulong)EnumCommand.Enter, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_1));
+            controllers[0].SetKey((ulong)EnumCommand.Back, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_2));
+            controllers[0].SetKey((ulong)EnumCommand.OptionMenu, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.HOME));
+
+            //PC XBOX
+
+            //TODO 待补全
+            controllers[0].SetKey((ulong)EnumCommand.Enter, AxiInputEx.ByKeyCode(PC_XBOXKEY.MenuBtn));
+            controllers[0].SetKey((ulong)EnumCommand.Back, AxiInputEx.ByKeyCode(PC_XBOXKEY.ViewBtn));
+            controllers[0].SetKey((ulong)EnumCommand.OptionMenu, AxiInputEx.ByKeyCode(PC_XBOXKEY.Y));
+
+            controllers[0].ColletAllKey();
+        }
+    }
+
+    public class XMBSingleKeysSeting : SingleKeysSetting
+    {
+        Dictionary<EnumCommand, List<AxiInput>> DictSkey2AxiInput = new Dictionary<EnumCommand, List<AxiInput>>();
+        AxiInput[] AxiInputArr = null;
+
+        public void SetKey(ulong Key, AxiInput input)
+        {
+            List<AxiInput> list;
+            if (!DictSkey2AxiInput.TryGetValue((EnumCommand)Key, out list))
+                list = DictSkey2AxiInput[(EnumCommand)Key] = ObjectPoolAuto.AcquireList<AxiInput>();
+            list.Add(input);
+        }
+
+        public bool GetKey(EnumCommand Key)
+        {
+            List<AxiInput> list;
+            if (!DictSkey2AxiInput.TryGetValue(Key, out list))
+                return false;
+            for (int i = 0; i < list.Count; i++)
+            {
+                if (list[i].IsKey())
+                    return true;
+            }
+            return false;
+        }
+
+        public void ClearAll()
+        {
+            foreach (List<AxiInput> singlelist in DictSkey2AxiInput.Values)
+                ObjectPoolAuto.Release(singlelist);
+            DictSkey2AxiInput.Clear();
+            AxiInputArr = null;
+        }
+
+        public void ColletAllKey()
+        {
+            List<AxiInput> list = ObjectPoolAuto.AcquireList<AxiInput>();
+            foreach (List<AxiInput> singlelist in DictSkey2AxiInput.Values)
+                list.AddRange(singlelist);
+            AxiInputArr = list.ToArray();
+            ObjectPoolAuto.Release(list);
+        }
+
+        public bool HadAnyKeyDown()
+        {
+            if (AxiInputArr == null)
+                return false;
+
+            for (int i = 0; AxiInputArr.Length > 0; i++)
+            {
+                if (AxiInputArr[i].IsKey())
+                    return true;
+            }
+            return false;
+        }
+
+        public bool GetKey(ulong Key)
+        {
+            return GetKey((EnumCommand)Key);
+        }
+
+        internal EnumCommand[] GetAllCmd()
+        {
+            return DictSkey2AxiInput.Keys.ToArray();
+        }
+
+    }
+}
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/XMBMultiKeysSetting.cs.meta b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/XMBMultiKeysSetting.cs.meta
new file mode 100644
index 00000000..2333e4e7
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput.Settings/XMBMultiKeysSetting.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 90bd1ccb53a0ddd4b814030f1ae218a2
\ No newline at end of file
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput/AxiInput.Struct.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput/AxiInput.Struct.cs
index c3547656..3d874383 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput/AxiInput.Struct.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInput/AxiInput.Struct.cs
@@ -50,5 +50,6 @@ namespace Assets.Script.AppMain.AxiInput
         POTION_2,
         POTION_3,
         POTION_4,
+        HOME,
     }
 }
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Common/PC_XBOXKEY.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Common/PC_XBOXKEY.cs
index 282032e8..873ae60f 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Common/PC_XBOXKEY.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Common/PC_XBOXKEY.cs
@@ -15,5 +15,6 @@ namespace AxibugEmuOnline.Client.Common
         public static KeyCode L3 => KeyCode.Joystick1Button8;
         public static KeyCode R3 => KeyCode.Joystick1Button9;
         public static KeyCode L => KeyCode.Joystick1Button10;
+        public static KeyCode R => KeyCode.Joystick1Button11;
     }
 }
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UniInterface/UniKeyboard.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UniInterface/UniKeyboard.cs
index a2ba21de..e0140a68 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UniInterface/UniKeyboard.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UniInterface/UniKeyboard.cs
@@ -1,14 +1,13 @@
+using Assets.Script.AppMain.AxiInput.Settings;
 using AxibugEmuOnline.Client;
 using AxibugEmuOnline.Client.ClientCore;
 using AxibugEmuOnline.Client.Event;
-using AxibugEmuOnline.Client.Manager;
 using AxiReplay;
 using MAME.Core;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using UnityEngine;
-using static AxibugEmuOnline.Client.Manager.MAMEKSingleKeysSeting;
 
 public class UniKeyboard : MonoBehaviour, IKeyboard
 {
@@ -335,19 +334,19 @@ public class MameSingleConoller : IController
             return 0;
         CurrLocalSingleAllInput = 0;
 
-        MAMEKSingleKeysSeting keys = App.input.mame.controllers[ControllerIndex];
-        if (keys.GetKey(MAMEKSingleKey.INSERT_COIN)) CurrLocalSingleAllInput |= (ulong)tg_INSERT_COIN;
-        if (keys.GetKey(MAMEKSingleKey.GAMESTART)) CurrLocalSingleAllInput |= (ulong)tg_GAMESTART;
-        if (keys.GetKey(MAMEKSingleKey.UP)) CurrLocalSingleAllInput |= (ulong)tg_UP;
-        if (keys.GetKey(MAMEKSingleKey.DOWN)) CurrLocalSingleAllInput |= (ulong)tg_DOWN;
-        if (keys.GetKey(MAMEKSingleKey.LEFT)) CurrLocalSingleAllInput |= (ulong)tg_LEFT;
-        if (keys.GetKey(MAMEKSingleKey.RIGHT)) CurrLocalSingleAllInput |= (ulong)tg_RIGHT;
-        if (keys.GetKey(MAMEKSingleKey.BTN_A)) CurrLocalSingleAllInput |= (ulong)tg_BTN_A;
-        if (keys.GetKey(MAMEKSingleKey.BTN_B)) CurrLocalSingleAllInput |= (ulong)tg_BTN_B;
-        if (keys.GetKey(MAMEKSingleKey.BTN_C)) CurrLocalSingleAllInput |= (ulong)tg_BTN_C;
-        if (keys.GetKey(MAMEKSingleKey.BTN_D)) CurrLocalSingleAllInput |= (ulong)tg_BTN_D;
-        if (keys.GetKey(MAMEKSingleKey.BTN_E)) CurrLocalSingleAllInput |= (ulong)tg_BTN_E;
-        if (keys.GetKey(MAMEKSingleKey.BTN_F)) CurrLocalSingleAllInput |= (ulong)tg_BTN_F;
+        var keys = App.input.mame.controllers[ControllerIndex];
+        if (keys.GetKey(UMAMEKSingleKey.INSERT_COIN)) CurrLocalSingleAllInput |= (ulong)tg_INSERT_COIN;
+        if (keys.GetKey(UMAMEKSingleKey.GAMESTART)) CurrLocalSingleAllInput |= (ulong)tg_GAMESTART;
+        if (keys.GetKey(UMAMEKSingleKey.UP)) CurrLocalSingleAllInput |= (ulong)tg_UP;
+        if (keys.GetKey(UMAMEKSingleKey.DOWN)) CurrLocalSingleAllInput |= (ulong)tg_DOWN;
+        if (keys.GetKey(UMAMEKSingleKey.LEFT)) CurrLocalSingleAllInput |= (ulong)tg_LEFT;
+        if (keys.GetKey(UMAMEKSingleKey.RIGHT)) CurrLocalSingleAllInput |= (ulong)tg_RIGHT;
+        if (keys.GetKey(UMAMEKSingleKey.BTN_A)) CurrLocalSingleAllInput |= (ulong)tg_BTN_A;
+        if (keys.GetKey(UMAMEKSingleKey.BTN_B)) CurrLocalSingleAllInput |= (ulong)tg_BTN_B;
+        if (keys.GetKey(UMAMEKSingleKey.BTN_C)) CurrLocalSingleAllInput |= (ulong)tg_BTN_C;
+        if (keys.GetKey(UMAMEKSingleKey.BTN_D)) CurrLocalSingleAllInput |= (ulong)tg_BTN_D;
+        if (keys.GetKey(UMAMEKSingleKey.BTN_E)) CurrLocalSingleAllInput |= (ulong)tg_BTN_E;
+        if (keys.GetKey(UMAMEKSingleKey.BTN_F)) CurrLocalSingleAllInput |= (ulong)tg_BTN_F;
 
         //if (Input.GetKey(INSERT_COIN)) CurrLocalSingleAllInput |= (ulong)tg_INSERT_COIN;
         //if (Input.GetKey(GAMESTART)) CurrLocalSingleAllInput |= (ulong)tg_GAMESTART;
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/IkeyMapperChanger/CommandChanger.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/IkeyMapperChanger/CommandChanger.cs
index 34bdc92d..1b183452 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/IkeyMapperChanger/CommandChanger.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/IkeyMapperChanger/CommandChanger.cs
@@ -1,8 +1,13 @@
-namespace AxibugEmuOnline.Client
+using AxibugEmuOnline.Client.Manager;
+using System.Collections.Generic;
+
+namespace AxibugEmuOnline.Client
 {
     public abstract class CommandChanger : IKeyMapperChanger
     {
         public string Name => GetType().Name;
-        public abstract object GetConfig();
+        public abstract EnumCommand[] GetConfig();
+
+        public abstract SingleKeysSetting GetKeySetting();
     }
 }
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/IkeyMapperChanger/GamingChanger.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/IkeyMapperChanger/GamingChanger.cs
index 86396de7..6bde9c9e 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/IkeyMapperChanger/GamingChanger.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/IkeyMapperChanger/GamingChanger.cs
@@ -1,26 +1,35 @@
-using System.Collections.Generic;
-using UnityEngine;
+using AxibugEmuOnline.Client.ClientCore;
+using AxibugEmuOnline.Client.Manager;
 
 namespace AxibugEmuOnline.Client
 {
     public class GamingChanger : CommandChanger
     {
-
-        Dictionary<KeyCode, EnumCommand> m_uiKeyMapper = new Dictionary<KeyCode, EnumCommand>();
-        public GamingChanger()
+        public override EnumCommand[] GetConfig()
         {
-            m_uiKeyMapper[KeyCode.Escape] = EnumCommand.OptionMenu;
-
-            if (Application.platform == RuntimePlatform.PSP2)
-            {
-                m_uiKeyMapper[Common.PSVitaKey.L] = EnumCommand.OptionMenu;
-                m_uiKeyMapper[Common.PSVitaKey.R] = EnumCommand.OptionMenu;
-            }
-
-            //PC XBOX
-            m_uiKeyMapper[Common.PC_XBOXKEY.Y] = EnumCommand.OptionMenu;
+            return App.input.gaming.controllers[0].GetAllCmd();
         }
 
-        public override object GetConfig() => m_uiKeyMapper;
+        public override SingleKeysSetting GetKeySetting()
+        {
+            return App.input.gaming.controllers[0];
+        }
+
+        //Dictionary<KeyCode, EnumCommand> m_uiKeyMapper = new Dictionary<KeyCode, EnumCommand>();
+        //public GamingChanger()
+        //{
+        //    m_uiKeyMapper[KeyCode.Escape] = EnumCommand.OptionMenu;
+
+        //    if (Application.platform == RuntimePlatform.PSP2)
+        //    {
+        //        m_uiKeyMapper[Common.PSVitaKey.L] = EnumCommand.OptionMenu;
+        //        m_uiKeyMapper[Common.PSVitaKey.R] = EnumCommand.OptionMenu;
+        //    }
+
+        //    //PC XBOX
+        //    m_uiKeyMapper[Common.PC_XBOXKEY.Y] = EnumCommand.OptionMenu;
+        //}
+
+        //public override object GetConfig() => m_uiKeyMapper;
     }
 }
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/IkeyMapperChanger/NormalChanger.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/IkeyMapperChanger/NormalChanger.cs
index c4d310c2..b2a61332 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/IkeyMapperChanger/NormalChanger.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/IkeyMapperChanger/NormalChanger.cs
@@ -1,54 +1,64 @@
-using System.Collections.Generic;
-using UnityEngine;
+using AxibugEmuOnline.Client.ClientCore;
+using AxibugEmuOnline.Client.Manager;
 
 namespace AxibugEmuOnline.Client
 {
 
     public class NormalChanger : CommandChanger
     {
-        Dictionary<KeyCode, EnumCommand> m_uiKeyMapper = new Dictionary<KeyCode, EnumCommand>();
-        public NormalChanger()
+        public override EnumCommand[] GetConfig()
         {
-            m_uiKeyMapper[KeyCode.A] = EnumCommand.SelectItemLeft;
-            m_uiKeyMapper[KeyCode.D] = EnumCommand.SelectItemRight;
-            m_uiKeyMapper[KeyCode.W] = EnumCommand.SelectItemUp;
-            m_uiKeyMapper[KeyCode.S] = EnumCommand.SelectItemDown;
-            m_uiKeyMapper[KeyCode.K] = EnumCommand.Enter;
-            m_uiKeyMapper[KeyCode.L] = EnumCommand.Back;
-            m_uiKeyMapper[KeyCode.I] = EnumCommand.OptionMenu;
-
-            m_uiKeyMapper[KeyCode.LeftArrow] = EnumCommand.SelectItemLeft;
-            m_uiKeyMapper[KeyCode.RightArrow] = EnumCommand.SelectItemRight;
-            m_uiKeyMapper[KeyCode.UpArrow] = EnumCommand.SelectItemUp;
-            m_uiKeyMapper[KeyCode.DownArrow] = EnumCommand.SelectItemDown;
-            m_uiKeyMapper[KeyCode.Return] = EnumCommand.Enter;
-            m_uiKeyMapper[KeyCode.Escape] = EnumCommand.Back;
-            m_uiKeyMapper[KeyCode.RightShift] = EnumCommand.OptionMenu;
-            m_uiKeyMapper[KeyCode.LeftShift] = EnumCommand.OptionMenu;
-
-            if (Application.platform == RuntimePlatform.PSP2)
-            {
-                m_uiKeyMapper[Common.PSVitaKey.Left] = EnumCommand.SelectItemLeft;
-                m_uiKeyMapper[Common.PSVitaKey.Right] = EnumCommand.SelectItemRight;
-                m_uiKeyMapper[Common.PSVitaKey.Up] = EnumCommand.SelectItemUp;
-                m_uiKeyMapper[Common.PSVitaKey.Down] = EnumCommand.SelectItemDown;
-                m_uiKeyMapper[Common.PSVitaKey.Circle] = EnumCommand.Enter;
-                m_uiKeyMapper[Common.PSVitaKey.Cross] = EnumCommand.Back;
-                m_uiKeyMapper[Common.PSVitaKey.Triangle] = EnumCommand.OptionMenu;
-            }
-
-            //PC XBOX
-
-            //m_uiKeyMapper[Common.PC_XBOXKEY.Left] = EnumCommand.SelectItemLeft;
-            //m_uiKeyMapper[Common.PSVitaKey.Right] = EnumCommand.SelectItemRight;
-            //m_uiKeyMapper[Common.PSVitaKey.Up] = EnumCommand.SelectItemUp;
-            //m_uiKeyMapper[Common.PSVitaKey.Down] = EnumCommand.SelectItemDown;
-            m_uiKeyMapper[Common.PC_XBOXKEY.MenuBtn] = EnumCommand.Enter;
-            m_uiKeyMapper[Common.PC_XBOXKEY.ViewBtn] = EnumCommand.Back;
-            m_uiKeyMapper[Common.PC_XBOXKEY.Y] = EnumCommand.OptionMenu;
+            return App.input.xmb.controllers[0].GetAllCmd();
         }
 
-        public override object GetConfig() => m_uiKeyMapper;
+        public override SingleKeysSetting GetKeySetting()
+        {
+            return App.input.xmb.controllers[0];
+        }
+
+        //Dictionary<KeyCode, EnumCommand> m_uiKeyMapper = new Dictionary<KeyCode, EnumCommand>();
+        //public NormalChanger()
+        //{
+        //    m_uiKeyMapper[KeyCode.A] = EnumCommand.SelectItemLeft;
+        //    m_uiKeyMapper[KeyCode.D] = EnumCommand.SelectItemRight;
+        //    m_uiKeyMapper[KeyCode.W] = EnumCommand.SelectItemUp;
+        //    m_uiKeyMapper[KeyCode.S] = EnumCommand.SelectItemDown;
+        //    m_uiKeyMapper[KeyCode.K] = EnumCommand.Enter;
+        //    m_uiKeyMapper[KeyCode.L] = EnumCommand.Back;
+        //    m_uiKeyMapper[KeyCode.I] = EnumCommand.OptionMenu;
+
+        //    m_uiKeyMapper[KeyCode.LeftArrow] = EnumCommand.SelectItemLeft;
+        //    m_uiKeyMapper[KeyCode.RightArrow] = EnumCommand.SelectItemRight;
+        //    m_uiKeyMapper[KeyCode.UpArrow] = EnumCommand.SelectItemUp;
+        //    m_uiKeyMapper[KeyCode.DownArrow] = EnumCommand.SelectItemDown;
+        //    m_uiKeyMapper[KeyCode.Return] = EnumCommand.Enter;
+        //    m_uiKeyMapper[KeyCode.Escape] = EnumCommand.Back;
+        //    m_uiKeyMapper[KeyCode.RightShift] = EnumCommand.OptionMenu;
+        //    m_uiKeyMapper[KeyCode.LeftShift] = EnumCommand.OptionMenu;
+
+        //    if (Application.platform == RuntimePlatform.PSP2)
+        //    {
+        //        m_uiKeyMapper[Common.PSVitaKey.Left] = EnumCommand.SelectItemLeft;
+        //        m_uiKeyMapper[Common.PSVitaKey.Right] = EnumCommand.SelectItemRight;
+        //        m_uiKeyMapper[Common.PSVitaKey.Up] = EnumCommand.SelectItemUp;
+        //        m_uiKeyMapper[Common.PSVitaKey.Down] = EnumCommand.SelectItemDown;
+        //        m_uiKeyMapper[Common.PSVitaKey.Circle] = EnumCommand.Enter;
+        //        m_uiKeyMapper[Common.PSVitaKey.Cross] = EnumCommand.Back;
+        //        m_uiKeyMapper[Common.PSVitaKey.Triangle] = EnumCommand.OptionMenu;
+        //    }
+
+        //    //PC XBOX
+
+        //    //m_uiKeyMapper[Common.PC_XBOXKEY.Left] = EnumCommand.SelectItemLeft;
+        //    //m_uiKeyMapper[Common.PSVitaKey.Right] = EnumCommand.SelectItemRight;
+        //    //m_uiKeyMapper[Common.PSVitaKey.Up] = EnumCommand.SelectItemUp;
+        //    //m_uiKeyMapper[Common.PSVitaKey.Down] = EnumCommand.SelectItemDown;
+        //    m_uiKeyMapper[Common.PC_XBOXKEY.MenuBtn] = EnumCommand.Enter;
+        //    m_uiKeyMapper[Common.PC_XBOXKEY.ViewBtn] = EnumCommand.Back;
+        //    m_uiKeyMapper[Common.PC_XBOXKEY.Y] = EnumCommand.OptionMenu;
+        //}
+
+        //public override object GetConfig() => m_uiKeyMapper;
     }
 
 }
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppInput.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppInput.cs
index 72f08ae7..8e72ef4b 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppInput.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppInput.cs
@@ -1,22 +1,26 @@
 using Assets.Script.AppMain.AxiInput;
-using AxibugEmuOnline.Client.Common;
-using System.Collections.Generic;
-using UnityEngine;
-using static AxibugEmuOnline.Client.Manager.MAMEKSingleKeysSeting;
+using Assets.Script.AppMain.AxiInput.Settings;
+using UnityEngine.UIElements.Experimental;
 
 namespace AxibugEmuOnline.Client.Manager
 {
     public class AppInput
     {
-        public MAMEKMultiKeysSetting mame;
+        public XMBMultiKeysSetting xmb;
+        public GamingMultiKeysSetting gaming;
+        public UMAMEMultiKeysSetting mame;
         public AppInput()
         {
-            mame = new MAMEKMultiKeysSetting();
+            xmb = new XMBMultiKeysSetting();
+            gaming = new GamingMultiKeysSetting();
+            mame = new UMAMEMultiKeysSetting();
             LoadDefaultSetting();
         }
 
         public void LoadDefaultSetting()
         {
+            xmb.LoadDefaultSetting();
+            gaming.LoadDefaultSetting();
             mame.LoadDefaultSetting();
         }
     }
@@ -32,180 +36,9 @@ namespace AxibugEmuOnline.Client.Manager
     {
         void ClearAll();
         void SetKey(ulong Key, AxiInput input);
+        bool GetKey(ulong Key);
         void ColletAllKey();
         bool HadAnyKeyDown();
     }
 
-    public class MAMEKMultiKeysSetting : MultiKeysSetting
-    {
-        public MAMEKSingleKeysSeting[] controllers;
-
-        public MAMEKMultiKeysSetting()
-        {
-            controllers = new MAMEKSingleKeysSeting[4];
-            for (int i = 0; i < controllers.Length; i++)
-                controllers[i] = new MAMEKSingleKeysSeting();
-        }
-
-        public bool HadAnyKeyDown(int index)
-        {
-            if (index >= controllers.Length)
-                return false;
-            return controllers[index].HadAnyKeyDown();
-        }
-        public void ClearAll()
-        {
-            controllers[0].ClearAll();
-            controllers[1].ClearAll();
-            controllers[2].ClearAll();
-            controllers[3].ClearAll();
-        }
-
-
-        public void LoadDefaultSetting()
-        {
-            ClearAll();
-#if UNITY_PSP2 && !UNITY_EDITOR
-            //PSV 摇杆
-            controllers[0].SetKey((ulong)MAMEKSingleKey.GAMESTART, AxiInputEx.ByKeyCode(PSVitaKey.Start));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.INSERT_COIN, AxiInputEx.ByKeyCode(PSVitaKey.Select));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.UP, AxiInputEx.ByKeyCode(PSVitaKey.Up));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.DOWN, AxiInputEx.ByKeyCode(PSVitaKey.Down));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.LEFT, AxiInputEx.ByKeyCode(PSVitaKey.Left));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.RIGHT, AxiInputEx.ByKeyCode(PSVitaKey.Right));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_A, AxiInputEx.ByKeyCode(PSVitaKey.Block));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_B, AxiInputEx.ByKeyCode(PSVitaKey.Cross));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_C, AxiInputEx.ByKeyCode(PSVitaKey.Circle));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_D, AxiInputEx.ByKeyCode(PSVitaKey.Triangle));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_E, AxiInputEx.ByKeyCode(PSVitaKey.L));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_F, AxiInputEx.ByKeyCode(PSVitaKey.R));
-            //PSV 摇杆
-            controllers[0].SetKey((ulong)MAMEKSingleKey.UP, AxiInputEx.ByAxis(AxiInputAxisType.UP));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.DOWN, AxiInputEx.ByAxis(AxiInputAxisType.DOWN));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.LEFT, AxiInputEx.ByAxis(AxiInputAxisType.LEFT));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.RIGHT, AxiInputEx.ByAxis(AxiInputAxisType.RIGHT));
-            controllers[0].ColletAllKey();
-            return;
-#endif
-            #region P1
-            //P1 键盘
-            controllers[0].SetKey((ulong)MAMEKSingleKey.GAMESTART, AxiInputEx.ByKeyCode(KeyCode.Alpha1));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.INSERT_COIN, AxiInputEx.ByKeyCode(KeyCode.Alpha5));
-
-            controllers[0].SetKey((ulong)MAMEKSingleKey.UP, AxiInputEx.ByKeyCode(KeyCode.W));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.DOWN, AxiInputEx.ByKeyCode(KeyCode.S));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.LEFT, AxiInputEx.ByKeyCode(KeyCode.A));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.RIGHT, AxiInputEx.ByKeyCode(KeyCode.D));
-
-
-            controllers[0].SetKey((ulong)MAMEKSingleKey.UP, AxiInputEx.ByKeyCode(KeyCode.G));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.DOWN, AxiInputEx.ByKeyCode(KeyCode.V));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.LEFT, AxiInputEx.ByKeyCode(KeyCode.C));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.RIGHT, AxiInputEx.ByKeyCode(KeyCode.B));
-
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_A, AxiInputEx.ByKeyCode(KeyCode.J));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_B, AxiInputEx.ByKeyCode(KeyCode.K));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_C, AxiInputEx.ByKeyCode(KeyCode.L));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_D, AxiInputEx.ByKeyCode(KeyCode.U));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_E, AxiInputEx.ByKeyCode(KeyCode.I));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_F, AxiInputEx.ByKeyCode(KeyCode.O));
-
-            //Axis
-            controllers[0].SetKey((ulong)MAMEKSingleKey.UP, AxiInputEx.ByAxis(AxiInputAxisType.UP));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.DOWN, AxiInputEx.ByAxis(AxiInputAxisType.DOWN));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.LEFT, AxiInputEx.ByAxis(AxiInputAxisType.LEFT));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.RIGHT, AxiInputEx.ByAxis(AxiInputAxisType.RIGHT));
-
-            //P1 UGUI
-            controllers[0].SetKey((ulong)MAMEKSingleKey.GAMESTART, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.POTION_1));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.INSERT_COIN, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.POTION_2));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.UP, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.UP));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.DOWN, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.DOWN));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.LEFT, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.LEFT));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.RIGHT, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.RIGHT));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_A, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_1));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_B, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_2));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_C, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_3));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_D, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_4));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_E, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_5));
-            controllers[0].SetKey((ulong)MAMEKSingleKey.BTN_F, AxiInputEx.ByUGUIBtn(AxiInputUGuiBtnType.BTN_6));
-
-            controllers[0].ColletAllKey();
-            #endregion
-        }
-    }
-
-    public class MAMEKSingleKeysSeting : SingleKeysSetting
-    {
-        public enum MAMEKSingleKey
-        {
-            INSERT_COIN,
-            GAMESTART,
-            UP,
-            DOWN,
-            LEFT,
-            RIGHT,
-            BTN_A,
-            BTN_B,
-            BTN_C,
-            BTN_D,
-            BTN_E,
-            BTN_F
-        }
-
-        Dictionary<MAMEKSingleKey, List<AxiInput>> DictSkey2AxiInput = new Dictionary<MAMEKSingleKey, List<AxiInput>>();
-        AxiInput[] AxiInputArr = null;
-
-        public void SetKey(ulong Key, AxiInput input)
-        {
-            List<AxiInput> list;
-            if (!DictSkey2AxiInput.TryGetValue((MAMEKSingleKey)Key, out list))
-                list = DictSkey2AxiInput[(MAMEKSingleKey)Key] = ObjectPoolAuto.AcquireList<AxiInput>();
-            list.Add(input);
-        }
-
-        public bool GetKey(MAMEKSingleKey Key)
-        {
-            List<AxiInput> list;
-            if (!DictSkey2AxiInput.TryGetValue(Key, out list))
-                return false;
-            for (int i = 0; i < list.Count; i++)
-            {
-                if (list[i].IsKey())
-                    return true;
-            }
-            return false;
-        }
-
-        public void ClearAll()
-        {
-            foreach (List<AxiInput> singlelist in DictSkey2AxiInput.Values)
-                ObjectPoolAuto.Release(singlelist);
-            DictSkey2AxiInput.Clear();
-            AxiInputArr = null;
-        }
-
-        public void ColletAllKey()
-        {
-            List<AxiInput> list = ObjectPoolAuto.AcquireList<AxiInput>();
-            foreach (List<AxiInput> singlelist in DictSkey2AxiInput.Values)
-                list.AddRange(singlelist);
-            AxiInputArr = list.ToArray();
-            ObjectPoolAuto.Release(list);
-        }
-
-        public bool HadAnyKeyDown()
-        {
-            if (AxiInputArr == null)
-                return false;
-
-            for (int i = 0; AxiInputArr.Length > 0; i++)
-            {
-                if (AxiInputArr[i].IsKey())
-                    return true;
-            }
-            return false;
-        }
-
-    }
 }
\ No newline at end of file
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/CommandListener.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/CommandListener.cs
index a04550ab..35725ae7 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/CommandListener.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/CommandListener.cs
@@ -1,27 +1,53 @@
-using System.Collections.Generic;
+using AxibugEmuOnline.Client.ClientCore;
+using AxibugEmuOnline.Client.Manager;
+using System.Collections.Generic;
 using UnityEngine;
+using static UnityEditor.Progress;
 
 namespace AxibugEmuOnline.Client
 {
     public class CommandListener : ICommandListener
     {
-        Dictionary<KeyCode, EnumCommand> m_keyMapper = new Dictionary<KeyCode, EnumCommand>();
+        //Dictionary<KeyCode, EnumCommand> m_keyMapper = new Dictionary<KeyCode, EnumCommand>();
+        SingleKeysSetting singleKeysSetting;
+        Dictionary<EnumCommand, bool> m_dictLastState = new Dictionary<EnumCommand, bool>();
+        EnumCommand[] m_checkCmds;
         List<CommandState> m_commands = new List<CommandState>();
         IEnumerable<CommandState> GetCommand()
         {
             m_commands.Clear();
-            foreach (var item in m_keyMapper)
+            //foreach (var item in m_keyMapper)
+            //{
+            //    if (Input.GetKeyDown(item.Key)) m_commands.Add(new CommandState { Cmd = item.Value, Cancel = false });
+            //    if (Input.GetKeyUp(item.Key)) m_commands.Add(new CommandState { Cmd = item.Value, Cancel = true });
+            //}
+            if (m_checkCmds != null)
             {
-                if (Input.GetKeyDown(item.Key)) m_commands.Add(new CommandState { Cmd = item.Value, Cancel = false });
-                if (Input.GetKeyUp(item.Key)) m_commands.Add(new CommandState { Cmd = item.Value, Cancel = true });
+                foreach (var cmd in m_checkCmds)
+                {
+                    bool oldstate = m_dictLastState[cmd];
+                    bool newstate = singleKeysSetting.GetKey((ulong)cmd);
+                    m_dictLastState[cmd] = newstate;
+                    if (oldstate != newstate)
+                    {
+                        m_commands.Add(new CommandState { Cmd = cmd, Cancel = !newstate });
+                    }
+                }
             }
 
             return m_commands;
         }
         public void ApplyKeyMapper(IKeyMapperChanger changer)
         {
-            var cfg = (Dictionary<KeyCode, EnumCommand>)changer.GetConfig();
-            m_keyMapper = cfg;
+            //var cfg = (Dictionary<KeyCode, EnumCommand>)changer.GetConfig();
+            singleKeysSetting = changer.GetKeySetting();
+            m_dictLastState.Clear();
+            EnumCommand[] arr = changer.GetConfig();
+            for (int i = 0; i < arr.Length; i++)
+            {
+                m_dictLastState[arr[i]] = false;
+            }
+            m_checkCmds = arr;
         }
 
         public void Update(IEnumerable<CommandExecuter> executers)
@@ -30,6 +56,7 @@ namespace AxibugEmuOnline.Client
             {
                 foreach (var executer in executers)
                 {
+                    App.log.Debug($"{cmd.Cmd}|{cmd.Cancel}");
                     executer.ExecuteCommand(cmd.Cmd, cmd.Cancel);
                 }
             }
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/ICommandListener.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/ICommandListener.cs
index 9d0e9bef..118d987b 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/ICommandListener.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/ICommandListener.cs
@@ -1,11 +1,13 @@
-using System.Collections.Generic;
+using AxibugEmuOnline.Client.Manager;
+using System.Collections.Generic;
 
 namespace AxibugEmuOnline.Client
 {
     public interface IKeyMapperChanger
     {
         string Name { get; }
-        object GetConfig();
+        EnumCommand[] GetConfig();
+        SingleKeysSetting GetKeySetting();
     }
     public interface ICommandListener
     {