diff --git a/Ryujinx.Tests.Unicorn/Native/Arm32Register.cs b/Ryujinx.Tests.Unicorn/Native/Arm32Register.cs
deleted file mode 100644
index 419f8e4d9a..0000000000
--- a/Ryujinx.Tests.Unicorn/Native/Arm32Register.cs
+++ /dev/null
@@ -1,135 +0,0 @@
-namespace Ryujinx.Tests.Unicorn.Native
-{
-    public enum Arm32Register
-    {
-        INVALID = 0,
-
-        APSR,
-        APSR_NZCV,
-        CPSR,
-        FPEXC,
-        FPINST,
-        FPSCR,
-        FPSCR_NZCV,
-        FPSID,
-        ITSTATE,
-        LR,
-        PC,
-        SP,
-        SPSR,
-        D0,
-        D1,
-        D2,
-        D3,
-        D4,
-        D5,
-        D6,
-        D7,
-        D8,
-        D9,
-        D10,
-        D11,
-        D12,
-        D13,
-        D14,
-        D15,
-        D16,
-        D17,
-        D18,
-        D19,
-        D20,
-        D21,
-        D22,
-        D23,
-        D24,
-        D25,
-        D26,
-        D27,
-        D28,
-        D29,
-        D30,
-        D31,
-        FPINST2,
-        MVFR0,
-        MVFR1,
-        MVFR2,
-        Q0,
-        Q1,
-        Q2,
-        Q3,
-        Q4,
-        Q5,
-        Q6,
-        Q7,
-        Q8,
-        Q9,
-        Q10,
-        Q11,
-        Q12,
-        Q13,
-        Q14,
-        Q15,
-        R0,
-        R1,
-        R2,
-        R3,
-        R4,
-        R5,
-        R6,
-        R7,
-        R8,
-        R9,
-        R10,
-        R11,
-        R12,
-        S0,
-        S1,
-        S2,
-        S3,
-        S4,
-        S5,
-        S6,
-        S7,
-        S8,
-        S9,
-        S10,
-        S11,
-        S12,
-        S13,
-        S14,
-        S15,
-        S16,
-        S17,
-        S18,
-        S19,
-        S20,
-        S21,
-        S22,
-        S23,
-        S24,
-        S25,
-        S26,
-        S27,
-        S28,
-        S29,
-        S30,
-        S31,
-        C1_C0_2,
-        C13_C0_2,
-        C13_C0_3,
-        IPSR,
-        MSP,
-        PSP,
-        CONTROL,
-        ENDING,
-
-        // Alias registers.
-        R13 = SP,
-        R14 = LR,
-        R15 = PC,
-        SB = R9,
-        SL = R10,
-        FP = R11,
-        IP = R12,
-    }
-}
diff --git a/Ryujinx.Tests.Unicorn/Native/ArmRegister.cs b/Ryujinx.Tests.Unicorn/Native/ArmRegister.cs
deleted file mode 100644
index af331bd1cf..0000000000
--- a/Ryujinx.Tests.Unicorn/Native/ArmRegister.cs
+++ /dev/null
@@ -1,295 +0,0 @@
-// ReSharper disable InconsistentNaming
-namespace Ryujinx.Tests.Unicorn.Native
-{
-    public enum ArmRegister
-    {
-        INVALID = 0,
-
-        X29,
-        X30,
-        NZCV,
-        SP,
-        WSP,
-        WZR,
-        XZR,
-        B0,
-        B1,
-        B2,
-        B3,
-        B4,
-        B5,
-        B6,
-        B7,
-        B8,
-        B9,
-        B10,
-        B11,
-        B12,
-        B13,
-        B14,
-        B15,
-        B16,
-        B17,
-        B18,
-        B19,
-        B20,
-        B21,
-        B22,
-        B23,
-        B24,
-        B25,
-        B26,
-        B27,
-        B28,
-        B29,
-        B30,
-        B31,
-        D0,
-        D1,
-        D2,
-        D3,
-        D4,
-        D5,
-        D6,
-        D7,
-        D8,
-        D9,
-        D10,
-        D11,
-        D12,
-        D13,
-        D14,
-        D15,
-        D16,
-        D17,
-        D18,
-        D19,
-        D20,
-        D21,
-        D22,
-        D23,
-        D24,
-        D25,
-        D26,
-        D27,
-        D28,
-        D29,
-        D30,
-        D31,
-        H0,
-        H1,
-        H2,
-        H3,
-        H4,
-        H5,
-        H6,
-        H7,
-        H8,
-        H9,
-        H10,
-        H11,
-        H12,
-        H13,
-        H14,
-        H15,
-        H16,
-        H17,
-        H18,
-        H19,
-        H20,
-        H21,
-        H22,
-        H23,
-        H24,
-        H25,
-        H26,
-        H27,
-        H28,
-        H29,
-        H30,
-        H31,
-        Q0,
-        Q1,
-        Q2,
-        Q3,
-        Q4,
-        Q5,
-        Q6,
-        Q7,
-        Q8,
-        Q9,
-        Q10,
-        Q11,
-        Q12,
-        Q13,
-        Q14,
-        Q15,
-        Q16,
-        Q17,
-        Q18,
-        Q19,
-        Q20,
-        Q21,
-        Q22,
-        Q23,
-        Q24,
-        Q25,
-        Q26,
-        Q27,
-        Q28,
-        Q29,
-        Q30,
-        Q31,
-        S0,
-        S1,
-        S2,
-        S3,
-        S4,
-        S5,
-        S6,
-        S7,
-        S8,
-        S9,
-        S10,
-        S11,
-        S12,
-        S13,
-        S14,
-        S15,
-        S16,
-        S17,
-        S18,
-        S19,
-        S20,
-        S21,
-        S22,
-        S23,
-        S24,
-        S25,
-        S26,
-        S27,
-        S28,
-        S29,
-        S30,
-        S31,
-        W0,
-        W1,
-        W2,
-        W3,
-        W4,
-        W5,
-        W6,
-        W7,
-        W8,
-        W9,
-        W10,
-        W11,
-        W12,
-        W13,
-        W14,
-        W15,
-        W16,
-        W17,
-        W18,
-        W19,
-        W20,
-        W21,
-        W22,
-        W23,
-        W24,
-        W25,
-        W26,
-        W27,
-        W28,
-        W29,
-        W30,
-        X0,
-        X1,
-        X2,
-        X3,
-        X4,
-        X5,
-        X6,
-        X7,
-        X8,
-        X9,
-        X10,
-        X11,
-        X12,
-        X13,
-        X14,
-        X15,
-        X16,
-        X17,
-        X18,
-        X19,
-        X20,
-        X21,
-        X22,
-        X23,
-        X24,
-        X25,
-        X26,
-        X27,
-        X28,
-
-        V0,
-        V1,
-        V2,
-        V3,
-        V4,
-        V5,
-        V6,
-        V7,
-        V8,
-        V9,
-        V10,
-        V11,
-        V12,
-        V13,
-        V14,
-        V15,
-        V16,
-        V17,
-        V18,
-        V19,
-        V20,
-        V21,
-        V22,
-        V23,
-        V24,
-        V25,
-        V26,
-        V27,
-        V28,
-        V29,
-        V30,
-        V31,
-
-        // > pseudo registers
-        PC,            // program counter register
-
-        CPACR_EL1,
-        ESR,
-
-        // > thread registers
-        TPIDR_EL0,
-        TPIDRRO_EL0,
-        TPIDR_EL1,
-
-        PSTATE,        // PSTATE pseudoregister
-
-        // > floating point control and status registers
-        FPCR,
-        FPSR,
-
-        ENDING,        // <-- mark the end of the list of registers
-
-        // > alias registers
-
-        IP0 =   X16,
-        IP1 =   X17,
-        FP =    X29,
-        LR =    X30,
-    }
-}
diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Arch.cs b/Ryujinx.Tests.Unicorn/Native/Const/Arch.cs
new file mode 100644
index 0000000000..f614d091b7
--- /dev/null
+++ b/Ryujinx.Tests.Unicorn/Native/Const/Arch.cs
@@ -0,0 +1,20 @@
+// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
+
+// ReSharper disable InconsistentNaming
+namespace Ryujinx.Tests.Unicorn.Native.Const
+{
+    public enum Arch
+    {
+        ARM = 1,
+        ARM64 = 2,
+        MIPS = 3,
+        X86 = 4,
+        PPC = 5,
+        SPARC = 6,
+        M68K = 7,
+        RISCV = 8,
+        S390X = 9,
+        TRICORE = 10,
+        MAX = 11,
+    }
+}
diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Arm.cs b/Ryujinx.Tests.Unicorn/Native/Const/Arm.cs
new file mode 100644
index 0000000000..4b7b3d6f31
--- /dev/null
+++ b/Ryujinx.Tests.Unicorn/Native/Const/Arm.cs
@@ -0,0 +1,200 @@
+// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
+
+// ReSharper disable InconsistentNaming
+namespace Ryujinx.Tests.Unicorn.Native.Const
+{
+    public enum Arm
+    {
+
+        // ARM CPU
+
+        CPU_ARM_926 = 0,
+        CPU_ARM_946 = 1,
+        CPU_ARM_1026 = 2,
+        CPU_ARM_1136_R2 = 3,
+        CPU_ARM_1136 = 4,
+        CPU_ARM_1176 = 5,
+        CPU_ARM_11MPCORE = 6,
+        CPU_ARM_CORTEX_M0 = 7,
+        CPU_ARM_CORTEX_M3 = 8,
+        CPU_ARM_CORTEX_M4 = 9,
+        CPU_ARM_CORTEX_M7 = 10,
+        CPU_ARM_CORTEX_M33 = 11,
+        CPU_ARM_CORTEX_R5 = 12,
+        CPU_ARM_CORTEX_R5F = 13,
+        CPU_ARM_CORTEX_A7 = 14,
+        CPU_ARM_CORTEX_A8 = 15,
+        CPU_ARM_CORTEX_A9 = 16,
+        CPU_ARM_CORTEX_A15 = 17,
+        CPU_ARM_TI925T = 18,
+        CPU_ARM_SA1100 = 19,
+        CPU_ARM_SA1110 = 20,
+        CPU_ARM_PXA250 = 21,
+        CPU_ARM_PXA255 = 22,
+        CPU_ARM_PXA260 = 23,
+        CPU_ARM_PXA261 = 24,
+        CPU_ARM_PXA262 = 25,
+        CPU_ARM_PXA270 = 26,
+        CPU_ARM_PXA270A0 = 27,
+        CPU_ARM_PXA270A1 = 28,
+        CPU_ARM_PXA270B0 = 29,
+        CPU_ARM_PXA270B1 = 30,
+        CPU_ARM_PXA270C0 = 31,
+        CPU_ARM_PXA270C5 = 32,
+        CPU_ARM_MAX = 33,
+        CPU_ARM_ENDING = 34,
+
+        // ARM registers
+
+        REG_INVALID = 0,
+        REG_APSR = 1,
+        REG_APSR_NZCV = 2,
+        REG_CPSR = 3,
+        REG_FPEXC = 4,
+        REG_FPINST = 5,
+        REG_FPSCR = 6,
+        REG_FPSCR_NZCV = 7,
+        REG_FPSID = 8,
+        REG_ITSTATE = 9,
+        REG_LR = 10,
+        REG_PC = 11,
+        REG_SP = 12,
+        REG_SPSR = 13,
+        REG_D0 = 14,
+        REG_D1 = 15,
+        REG_D2 = 16,
+        REG_D3 = 17,
+        REG_D4 = 18,
+        REG_D5 = 19,
+        REG_D6 = 20,
+        REG_D7 = 21,
+        REG_D8 = 22,
+        REG_D9 = 23,
+        REG_D10 = 24,
+        REG_D11 = 25,
+        REG_D12 = 26,
+        REG_D13 = 27,
+        REG_D14 = 28,
+        REG_D15 = 29,
+        REG_D16 = 30,
+        REG_D17 = 31,
+        REG_D18 = 32,
+        REG_D19 = 33,
+        REG_D20 = 34,
+        REG_D21 = 35,
+        REG_D22 = 36,
+        REG_D23 = 37,
+        REG_D24 = 38,
+        REG_D25 = 39,
+        REG_D26 = 40,
+        REG_D27 = 41,
+        REG_D28 = 42,
+        REG_D29 = 43,
+        REG_D30 = 44,
+        REG_D31 = 45,
+        REG_FPINST2 = 46,
+        REG_MVFR0 = 47,
+        REG_MVFR1 = 48,
+        REG_MVFR2 = 49,
+        REG_Q0 = 50,
+        REG_Q1 = 51,
+        REG_Q2 = 52,
+        REG_Q3 = 53,
+        REG_Q4 = 54,
+        REG_Q5 = 55,
+        REG_Q6 = 56,
+        REG_Q7 = 57,
+        REG_Q8 = 58,
+        REG_Q9 = 59,
+        REG_Q10 = 60,
+        REG_Q11 = 61,
+        REG_Q12 = 62,
+        REG_Q13 = 63,
+        REG_Q14 = 64,
+        REG_Q15 = 65,
+        REG_R0 = 66,
+        REG_R1 = 67,
+        REG_R2 = 68,
+        REG_R3 = 69,
+        REG_R4 = 70,
+        REG_R5 = 71,
+        REG_R6 = 72,
+        REG_R7 = 73,
+        REG_R8 = 74,
+        REG_R9 = 75,
+        REG_R10 = 76,
+        REG_R11 = 77,
+        REG_R12 = 78,
+        REG_S0 = 79,
+        REG_S1 = 80,
+        REG_S2 = 81,
+        REG_S3 = 82,
+        REG_S4 = 83,
+        REG_S5 = 84,
+        REG_S6 = 85,
+        REG_S7 = 86,
+        REG_S8 = 87,
+        REG_S9 = 88,
+        REG_S10 = 89,
+        REG_S11 = 90,
+        REG_S12 = 91,
+        REG_S13 = 92,
+        REG_S14 = 93,
+        REG_S15 = 94,
+        REG_S16 = 95,
+        REG_S17 = 96,
+        REG_S18 = 97,
+        REG_S19 = 98,
+        REG_S20 = 99,
+        REG_S21 = 100,
+        REG_S22 = 101,
+        REG_S23 = 102,
+        REG_S24 = 103,
+        REG_S25 = 104,
+        REG_S26 = 105,
+        REG_S27 = 106,
+        REG_S28 = 107,
+        REG_S29 = 108,
+        REG_S30 = 109,
+        REG_S31 = 110,
+        REG_C1_C0_2 = 111,
+        REG_C13_C0_2 = 112,
+        REG_C13_C0_3 = 113,
+        REG_IPSR = 114,
+        REG_MSP = 115,
+        REG_PSP = 116,
+        REG_CONTROL = 117,
+        REG_IAPSR = 118,
+        REG_EAPSR = 119,
+        REG_XPSR = 120,
+        REG_EPSR = 121,
+        REG_IEPSR = 122,
+        REG_PRIMASK = 123,
+        REG_BASEPRI = 124,
+        REG_BASEPRI_MAX = 125,
+        REG_FAULTMASK = 126,
+        REG_APSR_NZCVQ = 127,
+        REG_APSR_G = 128,
+        REG_APSR_NZCVQG = 129,
+        REG_IAPSR_NZCVQ = 130,
+        REG_IAPSR_G = 131,
+        REG_IAPSR_NZCVQG = 132,
+        REG_EAPSR_NZCVQ = 133,
+        REG_EAPSR_G = 134,
+        REG_EAPSR_NZCVQG = 135,
+        REG_XPSR_NZCVQ = 136,
+        REG_XPSR_G = 137,
+        REG_XPSR_NZCVQG = 138,
+        REG_CP_REG = 139,
+        REG_ENDING = 140,
+
+        // alias registers
+        REG_R13 = 12,
+        REG_R14 = 10,
+        REG_R15 = 11,
+        REG_SB = 75,
+        REG_SL = 76,
+        REG_FP = 77,
+        REG_IP = 78,
+    }
+}
diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Arm64.cs b/Ryujinx.Tests.Unicorn/Native/Const/Arm64.cs
new file mode 100644
index 0000000000..11344557b7
--- /dev/null
+++ b/Ryujinx.Tests.Unicorn/Native/Const/Arm64.cs
@@ -0,0 +1,341 @@
+// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
+
+// ReSharper disable InconsistentNaming
+namespace Ryujinx.Tests.Unicorn.Native.Const
+{
+    public enum Arm64
+    {
+
+        // ARM64 CPU
+
+        CPU_ARM64_A57 = 0,
+        CPU_ARM64_A53 = 1,
+        CPU_ARM64_A72 = 2,
+        CPU_ARM64_MAX = 3,
+        CPU_ARM64_ENDING = 4,
+
+        // ARM64 registers
+
+        REG_INVALID = 0,
+        REG_X29 = 1,
+        REG_X30 = 2,
+        REG_NZCV = 3,
+        REG_SP = 4,
+        REG_WSP = 5,
+        REG_WZR = 6,
+        REG_XZR = 7,
+        REG_B0 = 8,
+        REG_B1 = 9,
+        REG_B2 = 10,
+        REG_B3 = 11,
+        REG_B4 = 12,
+        REG_B5 = 13,
+        REG_B6 = 14,
+        REG_B7 = 15,
+        REG_B8 = 16,
+        REG_B9 = 17,
+        REG_B10 = 18,
+        REG_B11 = 19,
+        REG_B12 = 20,
+        REG_B13 = 21,
+        REG_B14 = 22,
+        REG_B15 = 23,
+        REG_B16 = 24,
+        REG_B17 = 25,
+        REG_B18 = 26,
+        REG_B19 = 27,
+        REG_B20 = 28,
+        REG_B21 = 29,
+        REG_B22 = 30,
+        REG_B23 = 31,
+        REG_B24 = 32,
+        REG_B25 = 33,
+        REG_B26 = 34,
+        REG_B27 = 35,
+        REG_B28 = 36,
+        REG_B29 = 37,
+        REG_B30 = 38,
+        REG_B31 = 39,
+        REG_D0 = 40,
+        REG_D1 = 41,
+        REG_D2 = 42,
+        REG_D3 = 43,
+        REG_D4 = 44,
+        REG_D5 = 45,
+        REG_D6 = 46,
+        REG_D7 = 47,
+        REG_D8 = 48,
+        REG_D9 = 49,
+        REG_D10 = 50,
+        REG_D11 = 51,
+        REG_D12 = 52,
+        REG_D13 = 53,
+        REG_D14 = 54,
+        REG_D15 = 55,
+        REG_D16 = 56,
+        REG_D17 = 57,
+        REG_D18 = 58,
+        REG_D19 = 59,
+        REG_D20 = 60,
+        REG_D21 = 61,
+        REG_D22 = 62,
+        REG_D23 = 63,
+        REG_D24 = 64,
+        REG_D25 = 65,
+        REG_D26 = 66,
+        REG_D27 = 67,
+        REG_D28 = 68,
+        REG_D29 = 69,
+        REG_D30 = 70,
+        REG_D31 = 71,
+        REG_H0 = 72,
+        REG_H1 = 73,
+        REG_H2 = 74,
+        REG_H3 = 75,
+        REG_H4 = 76,
+        REG_H5 = 77,
+        REG_H6 = 78,
+        REG_H7 = 79,
+        REG_H8 = 80,
+        REG_H9 = 81,
+        REG_H10 = 82,
+        REG_H11 = 83,
+        REG_H12 = 84,
+        REG_H13 = 85,
+        REG_H14 = 86,
+        REG_H15 = 87,
+        REG_H16 = 88,
+        REG_H17 = 89,
+        REG_H18 = 90,
+        REG_H19 = 91,
+        REG_H20 = 92,
+        REG_H21 = 93,
+        REG_H22 = 94,
+        REG_H23 = 95,
+        REG_H24 = 96,
+        REG_H25 = 97,
+        REG_H26 = 98,
+        REG_H27 = 99,
+        REG_H28 = 100,
+        REG_H29 = 101,
+        REG_H30 = 102,
+        REG_H31 = 103,
+        REG_Q0 = 104,
+        REG_Q1 = 105,
+        REG_Q2 = 106,
+        REG_Q3 = 107,
+        REG_Q4 = 108,
+        REG_Q5 = 109,
+        REG_Q6 = 110,
+        REG_Q7 = 111,
+        REG_Q8 = 112,
+        REG_Q9 = 113,
+        REG_Q10 = 114,
+        REG_Q11 = 115,
+        REG_Q12 = 116,
+        REG_Q13 = 117,
+        REG_Q14 = 118,
+        REG_Q15 = 119,
+        REG_Q16 = 120,
+        REG_Q17 = 121,
+        REG_Q18 = 122,
+        REG_Q19 = 123,
+        REG_Q20 = 124,
+        REG_Q21 = 125,
+        REG_Q22 = 126,
+        REG_Q23 = 127,
+        REG_Q24 = 128,
+        REG_Q25 = 129,
+        REG_Q26 = 130,
+        REG_Q27 = 131,
+        REG_Q28 = 132,
+        REG_Q29 = 133,
+        REG_Q30 = 134,
+        REG_Q31 = 135,
+        REG_S0 = 136,
+        REG_S1 = 137,
+        REG_S2 = 138,
+        REG_S3 = 139,
+        REG_S4 = 140,
+        REG_S5 = 141,
+        REG_S6 = 142,
+        REG_S7 = 143,
+        REG_S8 = 144,
+        REG_S9 = 145,
+        REG_S10 = 146,
+        REG_S11 = 147,
+        REG_S12 = 148,
+        REG_S13 = 149,
+        REG_S14 = 150,
+        REG_S15 = 151,
+        REG_S16 = 152,
+        REG_S17 = 153,
+        REG_S18 = 154,
+        REG_S19 = 155,
+        REG_S20 = 156,
+        REG_S21 = 157,
+        REG_S22 = 158,
+        REG_S23 = 159,
+        REG_S24 = 160,
+        REG_S25 = 161,
+        REG_S26 = 162,
+        REG_S27 = 163,
+        REG_S28 = 164,
+        REG_S29 = 165,
+        REG_S30 = 166,
+        REG_S31 = 167,
+        REG_W0 = 168,
+        REG_W1 = 169,
+        REG_W2 = 170,
+        REG_W3 = 171,
+        REG_W4 = 172,
+        REG_W5 = 173,
+        REG_W6 = 174,
+        REG_W7 = 175,
+        REG_W8 = 176,
+        REG_W9 = 177,
+        REG_W10 = 178,
+        REG_W11 = 179,
+        REG_W12 = 180,
+        REG_W13 = 181,
+        REG_W14 = 182,
+        REG_W15 = 183,
+        REG_W16 = 184,
+        REG_W17 = 185,
+        REG_W18 = 186,
+        REG_W19 = 187,
+        REG_W20 = 188,
+        REG_W21 = 189,
+        REG_W22 = 190,
+        REG_W23 = 191,
+        REG_W24 = 192,
+        REG_W25 = 193,
+        REG_W26 = 194,
+        REG_W27 = 195,
+        REG_W28 = 196,
+        REG_W29 = 197,
+        REG_W30 = 198,
+        REG_X0 = 199,
+        REG_X1 = 200,
+        REG_X2 = 201,
+        REG_X3 = 202,
+        REG_X4 = 203,
+        REG_X5 = 204,
+        REG_X6 = 205,
+        REG_X7 = 206,
+        REG_X8 = 207,
+        REG_X9 = 208,
+        REG_X10 = 209,
+        REG_X11 = 210,
+        REG_X12 = 211,
+        REG_X13 = 212,
+        REG_X14 = 213,
+        REG_X15 = 214,
+        REG_X16 = 215,
+        REG_X17 = 216,
+        REG_X18 = 217,
+        REG_X19 = 218,
+        REG_X20 = 219,
+        REG_X21 = 220,
+        REG_X22 = 221,
+        REG_X23 = 222,
+        REG_X24 = 223,
+        REG_X25 = 224,
+        REG_X26 = 225,
+        REG_X27 = 226,
+        REG_X28 = 227,
+        REG_V0 = 228,
+        REG_V1 = 229,
+        REG_V2 = 230,
+        REG_V3 = 231,
+        REG_V4 = 232,
+        REG_V5 = 233,
+        REG_V6 = 234,
+        REG_V7 = 235,
+        REG_V8 = 236,
+        REG_V9 = 237,
+        REG_V10 = 238,
+        REG_V11 = 239,
+        REG_V12 = 240,
+        REG_V13 = 241,
+        REG_V14 = 242,
+        REG_V15 = 243,
+        REG_V16 = 244,
+        REG_V17 = 245,
+        REG_V18 = 246,
+        REG_V19 = 247,
+        REG_V20 = 248,
+        REG_V21 = 249,
+        REG_V22 = 250,
+        REG_V23 = 251,
+        REG_V24 = 252,
+        REG_V25 = 253,
+        REG_V26 = 254,
+        REG_V27 = 255,
+        REG_V28 = 256,
+        REG_V29 = 257,
+        REG_V30 = 258,
+        REG_V31 = 259,
+
+        // pseudo registers
+        REG_PC = 260,
+        REG_CPACR_EL1 = 261,
+
+        // thread registers, depreciated, use UC_ARM64_REG_CP_REG instead
+        REG_TPIDR_EL0 = 262,
+        REG_TPIDRRO_EL0 = 263,
+        REG_TPIDR_EL1 = 264,
+        REG_PSTATE = 265,
+
+        // exception link registers, depreciated, use UC_ARM64_REG_CP_REG instead
+        REG_ELR_EL0 = 266,
+        REG_ELR_EL1 = 267,
+        REG_ELR_EL2 = 268,
+        REG_ELR_EL3 = 269,
+
+        // stack pointers registers, depreciated, use UC_ARM64_REG_CP_REG instead
+        REG_SP_EL0 = 270,
+        REG_SP_EL1 = 271,
+        REG_SP_EL2 = 272,
+        REG_SP_EL3 = 273,
+
+        // other CP15 registers, depreciated, use UC_ARM64_REG_CP_REG instead
+        REG_TTBR0_EL1 = 274,
+        REG_TTBR1_EL1 = 275,
+        REG_ESR_EL0 = 276,
+        REG_ESR_EL1 = 277,
+        REG_ESR_EL2 = 278,
+        REG_ESR_EL3 = 279,
+        REG_FAR_EL0 = 280,
+        REG_FAR_EL1 = 281,
+        REG_FAR_EL2 = 282,
+        REG_FAR_EL3 = 283,
+        REG_PAR_EL1 = 284,
+        REG_MAIR_EL1 = 285,
+        REG_VBAR_EL0 = 286,
+        REG_VBAR_EL1 = 287,
+        REG_VBAR_EL2 = 288,
+        REG_VBAR_EL3 = 289,
+        REG_CP_REG = 290,
+
+        // floating point control and status registers
+        REG_FPCR = 291,
+        REG_FPSR = 292,
+        REG_ENDING = 293,
+
+        // alias registers
+        REG_IP0 = 215,
+        REG_IP1 = 216,
+        REG_FP = 1,
+        REG_LR = 2,
+
+        // ARM64 instructions
+
+        INS_INVALID = 0,
+        INS_MRS = 1,
+        INS_MSR = 2,
+        INS_SYS = 3,
+        INS_SYSL = 4,
+        INS_ENDING = 5,
+    }
+}
diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Common.cs b/Ryujinx.Tests.Unicorn/Native/Const/Common.cs
new file mode 100644
index 0000000000..e4b59a489d
--- /dev/null
+++ b/Ryujinx.Tests.Unicorn/Native/Const/Common.cs
@@ -0,0 +1,44 @@
+// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
+
+// ReSharper disable InconsistentNaming
+namespace Ryujinx.Tests.Unicorn.Native.Const
+{
+    public enum Common
+    {
+        API_MAJOR = 2,
+
+        API_MINOR = 0,
+
+        API_PATCH = 0,
+        API_EXTRA = 255,
+        VERSION_MAJOR = 2,
+
+        VERSION_MINOR = 0,
+
+        VERSION_PATCH = 0,
+        VERSION_EXTRA = 255,
+        SECOND_SCALE = 1000000,
+        MILISECOND_SCALE = 1000,
+        QUERY_MODE = 1,
+        QUERY_PAGE_SIZE = 2,
+        QUERY_ARCH = 3,
+        QUERY_TIMEOUT = 4,
+
+        CTL_IO_NONE = 0,
+        CTL_IO_WRITE = 1,
+        CTL_IO_READ = 2,
+        CTL_IO_READ_WRITE = 3,
+
+        CTL_UC_MODE = 0,
+        CTL_UC_PAGE_SIZE = 1,
+        CTL_UC_ARCH = 2,
+        CTL_UC_TIMEOUT = 3,
+        CTL_UC_USE_EXITS = 4,
+        CTL_UC_EXITS_CNT = 5,
+        CTL_UC_EXITS = 6,
+        CTL_CPU_MODEL = 7,
+        CTL_TB_REQUEST_CACHE = 8,
+        CTL_TB_REMOVE_CACHE = 9,
+        CTL_TB_FLUSH = 10,
+    }
+}
diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Error.cs b/Ryujinx.Tests.Unicorn/Native/Const/Error.cs
new file mode 100644
index 0000000000..9cedb0fccc
--- /dev/null
+++ b/Ryujinx.Tests.Unicorn/Native/Const/Error.cs
@@ -0,0 +1,31 @@
+// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
+
+// ReSharper disable InconsistentNaming
+namespace Ryujinx.Tests.Unicorn.Native.Const
+{
+    public enum Error
+    {
+        OK = 0,
+        NOMEM = 1,
+        ARCH = 2,
+        HANDLE = 3,
+        MODE = 4,
+        VERSION = 5,
+        READ_UNMAPPED = 6,
+        WRITE_UNMAPPED = 7,
+        FETCH_UNMAPPED = 8,
+        HOOK = 9,
+        INSN_INVALID = 10,
+        MAP = 11,
+        WRITE_PROT = 12,
+        READ_PROT = 13,
+        FETCH_PROT = 14,
+        ARG = 15,
+        READ_UNALIGNED = 16,
+        WRITE_UNALIGNED = 17,
+        FETCH_UNALIGNED = 18,
+        HOOK_EXIST = 19,
+        RESOURCE = 20,
+        EXCEPTION = 21,
+    }
+}
diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Hook.cs b/Ryujinx.Tests.Unicorn/Native/Const/Hook.cs
new file mode 100644
index 0000000000..a6b9dca6ed
--- /dev/null
+++ b/Ryujinx.Tests.Unicorn/Native/Const/Hook.cs
@@ -0,0 +1,33 @@
+// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
+
+// ReSharper disable InconsistentNaming
+namespace Ryujinx.Tests.Unicorn.Native.Const
+{
+    public enum Hook
+    {
+        INTR = 1,
+        INSN = 2,
+        CODE = 4,
+        BLOCK = 8,
+        MEM_READ_UNMAPPED = 16,
+        MEM_WRITE_UNMAPPED = 32,
+        MEM_FETCH_UNMAPPED = 64,
+        MEM_READ_PROT = 128,
+        MEM_WRITE_PROT = 256,
+        MEM_FETCH_PROT = 512,
+        MEM_READ = 1024,
+        MEM_WRITE = 2048,
+        MEM_FETCH = 4096,
+        MEM_READ_AFTER = 8192,
+        INSN_INVALID = 16384,
+        EDGE_GENERATED = 32768,
+        TCG_OPCODE = 65536,
+        MEM_UNMAPPED = 112,
+        MEM_PROT = 896,
+        MEM_READ_INVALID = 144,
+        MEM_WRITE_INVALID = 288,
+        MEM_FETCH_INVALID = 576,
+        MEM_INVALID = 1008,
+        MEM_VALID = 7168,
+    }
+}
diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Memory.cs b/Ryujinx.Tests.Unicorn/Native/Const/Memory.cs
new file mode 100644
index 0000000000..a7d60e6115
--- /dev/null
+++ b/Ryujinx.Tests.Unicorn/Native/Const/Memory.cs
@@ -0,0 +1,19 @@
+// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
+
+// ReSharper disable InconsistentNaming
+namespace Ryujinx.Tests.Unicorn.Native.Const
+{
+    public enum Memory
+    {
+        READ = 16,
+        WRITE = 17,
+        FETCH = 18,
+        READ_UNMAPPED = 19,
+        WRITE_UNMAPPED = 20,
+        FETCH_UNMAPPED = 21,
+        WRITE_PROT = 22,
+        READ_PROT = 23,
+        FETCH_PROT = 24,
+        READ_AFTER = 25,
+    }
+}
diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Mode.cs b/Ryujinx.Tests.Unicorn/Native/Const/Mode.cs
new file mode 100644
index 0000000000..804d01a97b
--- /dev/null
+++ b/Ryujinx.Tests.Unicorn/Native/Const/Mode.cs
@@ -0,0 +1,35 @@
+// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
+
+// ReSharper disable InconsistentNaming
+namespace Ryujinx.Tests.Unicorn.Native.Const
+{
+    public enum Mode
+    {
+        LITTLE_ENDIAN = 0,
+        BIG_ENDIAN = 1073741824,
+        ARM = 0,
+        THUMB = 16,
+        MCLASS = 32,
+        V8 = 64,
+        ARMBE8 = 1024,
+        ARM926 = 128,
+        ARM946 = 256,
+        ARM1176 = 512,
+        MICRO = 16,
+        MIPS3 = 32,
+        MIPS32R6 = 64,
+        MIPS32 = 4,
+        MIPS64 = 8,
+        MODE_16 = 2,
+        MODE_32 = 4,
+        MODE_64 = 8,
+        PPC32 = 4,
+        PPC64 = 8,
+        QPX = 16,
+        SPARC32 = 4,
+        SPARC64 = 8,
+        V9 = 16,
+        RISCV32 = 4,
+        RISCV64 = 8,
+    }
+}
diff --git a/Ryujinx.Tests.Unicorn/Native/Const/Permission.cs b/Ryujinx.Tests.Unicorn/Native/Const/Permission.cs
new file mode 100644
index 0000000000..19ddc4f270
--- /dev/null
+++ b/Ryujinx.Tests.Unicorn/Native/Const/Permission.cs
@@ -0,0 +1,14 @@
+// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
+
+// ReSharper disable InconsistentNaming
+namespace Ryujinx.Tests.Unicorn.Native.Const
+{
+    public enum Permission
+    {
+        NONE = 0,
+        READ = 1,
+        WRITE = 2,
+        EXEC = 4,
+        ALL = 7,
+    }
+}
diff --git a/Ryujinx.Tests.Unicorn/Native/Const/TCG.cs b/Ryujinx.Tests.Unicorn/Native/Const/TCG.cs
new file mode 100644
index 0000000000..f38785db70
--- /dev/null
+++ b/Ryujinx.Tests.Unicorn/Native/Const/TCG.cs
@@ -0,0 +1,12 @@
+// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
+
+// ReSharper disable InconsistentNaming
+namespace Ryujinx.Tests.Unicorn.Native.Const
+{
+    public enum TCG
+    {
+        OP_SUB = 0,
+        OP_FLAG_CMP = 1,
+        OP_FLAG_DIRECT = 2,
+    }
+}
diff --git a/Ryujinx.Tests.Unicorn/Native/Interface.cs b/Ryujinx.Tests.Unicorn/Native/Interface.cs
index 59b1da0792..0ecda22eaa 100644
--- a/Ryujinx.Tests.Unicorn/Native/Interface.cs
+++ b/Ryujinx.Tests.Unicorn/Native/Interface.cs
@@ -1,13 +1,43 @@
+using Ryujinx.Tests.Unicorn.Native.Const;
 using System;
+using System.IO;
+using System.Reflection;
 using System.Runtime.InteropServices;
 
 namespace Ryujinx.Tests.Unicorn.Native
 {
-    public class Interface
+    public static class Interface
     {
-        public static void Checked(UnicornError error)
+        public static bool IsUnicornAvailable { get; private set; } = true;
+
+        private static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
         {
-            if (error != UnicornError.UC_ERR_OK)
+            if (libraryName == "unicorn")
+            {
+                string loadPath = $"{Path.GetDirectoryName(assembly.Location)}/";
+                loadPath += OperatingSystem.IsWindows() ? $"{libraryName}.dll" : $"lib{libraryName}.so";
+
+                if (!NativeLibrary.TryLoad(loadPath, out IntPtr libraryPtr))
+                {
+                    IsUnicornAvailable = false;
+                    Console.Error.WriteLine($"ERROR: Could not find unicorn at: {loadPath}");
+                }
+
+                return libraryPtr;
+            }
+
+            // Otherwise, fallback to default import resolver.
+            return IntPtr.Zero;
+        }
+
+        static Interface()
+        {
+            NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), ImportResolver);
+        }
+
+        public static void Checked(Error error)
+        {
+            if (error != Error.OK)
             {
                 throw new UnicornException(error);
             }
@@ -31,39 +61,39 @@ namespace Ryujinx.Tests.Unicorn.Native
         public static extern uint uc_version(out uint major, out uint minor);
 
         [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)]
-        public static extern UnicornError uc_open(UnicornArch arch, UnicornMode mode, out IntPtr uc);
+        public static extern Error uc_open(Arch arch, Mode mode, out IntPtr uc);
 
         [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)]
-        public static extern UnicornError uc_close(IntPtr uc);
+        public static extern Error uc_close(IntPtr uc);
 
         [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)]
-        public static extern IntPtr uc_strerror(UnicornError err);
+        public static extern IntPtr uc_strerror(Error err);
 
         [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)]
-        public static extern UnicornError uc_reg_write(IntPtr uc, int regid, byte[] value);
+        public static extern Error uc_reg_write(IntPtr uc, int regid, byte[] value);
 
         [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)]
-        public static extern UnicornError uc_reg_read(IntPtr uc, int regid, byte[] value);
+        public static extern Error uc_reg_read(IntPtr uc, int regid, byte[] value);
 
         [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)]
-        public static extern UnicornError uc_mem_write(IntPtr uc, ulong address, byte[] bytes, ulong size);
+        public static extern Error uc_mem_write(IntPtr uc, ulong address, byte[] bytes, ulong size);
 
         [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)]
-        public static extern UnicornError uc_mem_read(IntPtr uc, ulong address, byte[] bytes, ulong size);
+        public static extern Error uc_mem_read(IntPtr uc, ulong address, byte[] bytes, ulong size);
 
         [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)]
-        public static extern UnicornError uc_emu_start(IntPtr uc, ulong begin, ulong until, ulong timeout, ulong count);
+        public static extern Error uc_emu_start(IntPtr uc, ulong begin, ulong until, ulong timeout, ulong count);
 
         [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)]
-        public static extern UnicornError uc_mem_map(IntPtr uc, ulong address, ulong size, uint perms);
+        public static extern Error uc_mem_map(IntPtr uc, ulong address, ulong size, uint perms);
 
         [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)]
-        public static extern UnicornError uc_mem_unmap(IntPtr uc, ulong address, ulong size);
+        public static extern Error uc_mem_unmap(IntPtr uc, ulong address, ulong size);
 
         [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)]
-        public static extern UnicornError uc_mem_protect(IntPtr uc, ulong address, ulong size, uint perms);
+        public static extern Error uc_mem_protect(IntPtr uc, ulong address, ulong size, uint perms);
 
         [DllImport("unicorn", CallingConvention = CallingConvention.Cdecl)]
-        public static extern UnicornError uc_mem_regions(IntPtr uc, out IntPtr regions, out uint count);
+        public static extern Error uc_mem_regions(IntPtr uc, out IntPtr regions, out uint count);
     }
-}
+}
\ No newline at end of file
diff --git a/Ryujinx.Tests.Unicorn/Native/UnicornArch.cs b/Ryujinx.Tests.Unicorn/Native/UnicornArch.cs
deleted file mode 100644
index ff633293e1..0000000000
--- a/Ryujinx.Tests.Unicorn/Native/UnicornArch.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace Ryujinx.Tests.Unicorn.Native
-{
-    public enum UnicornArch : uint
-    {
-        UC_ARCH_ARM = 1,    // ARM architecture (including Thumb, Thumb-2)
-        UC_ARCH_ARM64,      // ARM-64, also called AArch64
-        UC_ARCH_MIPS,       // Mips architecture
-        UC_ARCH_X86,        // X86 architecture (including x86 & x86-64)
-        UC_ARCH_PPC,        // PowerPC architecture (currently unsupported)
-        UC_ARCH_SPARC,      // Sparc architecture
-        UC_ARCH_M68K,       // M68K architecture
-        UC_ARCH_MAX,
-    }
-}
diff --git a/Ryujinx.Tests.Unicorn/Native/UnicornMode.cs b/Ryujinx.Tests.Unicorn/Native/UnicornMode.cs
deleted file mode 100644
index 8045f2dac4..0000000000
--- a/Ryujinx.Tests.Unicorn/Native/UnicornMode.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// ReSharper disable InconsistentNaming
-namespace Ryujinx.Tests.Unicorn.Native
-{
-    public enum UnicornMode : uint
-    {
-        UC_MODE_LITTLE_ENDIAN = 0,    // little-endian mode (default mode)
-        UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode
-        // arm / arm64
-        UC_MODE_ARM = 0,              // ARM mode
-        UC_MODE_THUMB = 1 << 4,       // THUMB mode (including Thumb-2)
-        UC_MODE_MCLASS = 1 << 5,      // ARM's Cortex-M series (currently unsupported)
-        UC_MODE_V8 = 1 << 6,          // ARMv8 A32 encodings for ARM (currently unsupported)
-        // mips
-        UC_MODE_MICRO = 1 << 4,       // MicroMips mode (currently unsupported)
-        UC_MODE_MIPS3 = 1 << 5,       // Mips III ISA (currently unsupported)
-        UC_MODE_MIPS32R6 = 1 << 6,    // Mips32r6 ISA (currently unsupported)
-        UC_MODE_MIPS32 = 1 << 2,      // Mips32 ISA
-        UC_MODE_MIPS64 = 1 << 3,      // Mips64 ISA
-        // x86 / x64
-        UC_MODE_16 = 1 << 1,          // 16-bit mode
-        UC_MODE_32 = 1 << 2,          // 32-bit mode
-        UC_MODE_64 = 1 << 3,          // 64-bit mode
-        // ppc
-        UC_MODE_PPC32 = 1 << 2,       // 32-bit mode (currently unsupported)
-        UC_MODE_PPC64 = 1 << 3,       // 64-bit mode (currently unsupported)
-        UC_MODE_QPX = 1 << 4,         // Quad Processing eXtensions mode (currently unsupported)
-        // sparc
-        UC_MODE_SPARC32 = 1 << 2,     // 32-bit mode
-        UC_MODE_SPARC64 = 1 << 3,     // 64-bit mode
-        UC_MODE_V9 = 1 << 4,          // SparcV9 mode (currently unsupported)
-        // m68k
-    }
-}
diff --git a/Ryujinx.Tests.Unicorn/UnicornAArch32.cs b/Ryujinx.Tests.Unicorn/UnicornAArch32.cs
index e634e0d2aa..8b3e79b69a 100644
--- a/Ryujinx.Tests.Unicorn/UnicornAArch32.cs
+++ b/Ryujinx.Tests.Unicorn/UnicornAArch32.cs
@@ -1,4 +1,5 @@
 using Ryujinx.Tests.Unicorn.Native;
+using Ryujinx.Tests.Unicorn.Native.Const;
 using System;
 
 namespace Ryujinx.Tests.Unicorn
@@ -30,32 +31,32 @@ namespace Ryujinx.Tests.Unicorn
 
         public uint LR
         {
-            get => GetRegister(Arm32Register.LR);
-            set => SetRegister(Arm32Register.LR, value);
+            get => GetRegister(Arm.REG_LR);
+            set => SetRegister(Arm.REG_LR, value);
         }
 
         public uint SP
         {
-            get => GetRegister(Arm32Register.SP);
-            set => SetRegister(Arm32Register.SP, value);
+            get => GetRegister(Arm.REG_SP);
+            set => SetRegister(Arm.REG_SP, value);
         }
 
         public uint PC
         {
-            get => GetRegister(Arm32Register.PC) & 0xfffffffeu;
-            set => SetRegister(Arm32Register.PC, (value & 0xfffffffeu) | (ThumbFlag ? 1u : 0u));
+            get => GetRegister(Arm.REG_PC) & 0xfffffffeu;
+            set => SetRegister(Arm.REG_PC, (value & 0xfffffffeu) | (ThumbFlag ? 1u : 0u));
         }
 
         public uint CPSR
         {
-            get => (uint)GetRegister(Arm32Register.CPSR);
-            set => SetRegister(Arm32Register.CPSR, (uint)value);
+            get => GetRegister(Arm.REG_CPSR);
+            set => SetRegister(Arm.REG_CPSR, value);
         }
 
         public int Fpscr
         {
-            get => (int)GetRegister(Arm32Register.FPSCR) | ((int)GetRegister(Arm32Register.FPSCR_NZCV));
-            set => SetRegister(Arm32Register.FPSCR, (uint)value);
+            get => (int)GetRegister(Arm.REG_FPSCR) | ((int)GetRegister(Arm.REG_FPSCR_NZCV));
+            set => SetRegister(Arm.REG_FPSCR, (uint)value);
         }
 
         public bool QFlag
@@ -94,16 +95,16 @@ namespace Ryujinx.Tests.Unicorn
             set
             {
                 CPSR = (CPSR & ~0x00000020u) | (value ? 0x00000020u : 0u);
-                SetRegister(Arm32Register.PC, (GetRegister(Arm32Register.PC) & 0xfffffffeu) | (value ? 1u : 0u));
+                SetRegister(Arm.REG_PC, (GetRegister(Arm.REG_PC) & 0xfffffffeu) | (value ? 1u : 0u));
             }
         }
 
         public UnicornAArch32()
         {
-            Interface.Checked(Interface.uc_open(UnicornArch.UC_ARCH_ARM, UnicornMode.UC_MODE_LITTLE_ENDIAN, out uc));
+            Interface.Checked(Interface.uc_open(Arch.ARM, Mode.LITTLE_ENDIAN, out uc));
 
-            SetRegister(Arm32Register.C1_C0_2, GetRegister(Arm32Register.C1_C0_2) | 0xf00000);
-            SetRegister(Arm32Register.FPEXC, 0x40000000);
+            SetRegister(Arm.REG_C1_C0_2, GetRegister(Arm.REG_C1_C0_2) | 0xf00000);
+            SetRegister(Arm.REG_FPEXC, 0x40000000);
         }
 
         ~UnicornAArch32()
@@ -136,44 +137,44 @@ namespace Ryujinx.Tests.Unicorn
             RunForCount(1);
         }
 
-        private static Arm32Register[] XRegisters = new Arm32Register[16]
+        private static Arm[] XRegisters = new Arm[16]
         {
-            Arm32Register.R0,
-            Arm32Register.R1,
-            Arm32Register.R2,
-            Arm32Register.R3,
-            Arm32Register.R4,
-            Arm32Register.R5,
-            Arm32Register.R6,
-            Arm32Register.R7,
-            Arm32Register.R8,
-            Arm32Register.R9,
-            Arm32Register.R10,
-            Arm32Register.R11,
-            Arm32Register.R12,
-            Arm32Register.R13,
-            Arm32Register.R14,
-            Arm32Register.R15,
+            Arm.REG_R0,
+            Arm.REG_R1,
+            Arm.REG_R2,
+            Arm.REG_R3,
+            Arm.REG_R4,
+            Arm.REG_R5,
+            Arm.REG_R6,
+            Arm.REG_R7,
+            Arm.REG_R8,
+            Arm.REG_R9,
+            Arm.REG_R10,
+            Arm.REG_R11,
+            Arm.REG_R12,
+            Arm.REG_R13,
+            Arm.REG_R14,
+            Arm.REG_R15,
         };
 
-        private static Arm32Register[] QRegisters = new Arm32Register[16]
+        private static Arm[] QRegisters = new Arm[16]
         {
-            Arm32Register.Q0,
-            Arm32Register.Q1,
-            Arm32Register.Q2,
-            Arm32Register.Q3,
-            Arm32Register.Q4,
-            Arm32Register.Q5,
-            Arm32Register.Q6,
-            Arm32Register.Q7,
-            Arm32Register.Q8,
-            Arm32Register.Q9,
-            Arm32Register.Q10,
-            Arm32Register.Q11,
-            Arm32Register.Q12,
-            Arm32Register.Q13,
-            Arm32Register.Q14,
-            Arm32Register.Q15
+            Arm.REG_Q0,
+            Arm.REG_Q1,
+            Arm.REG_Q2,
+            Arm.REG_Q3,
+            Arm.REG_Q4,
+            Arm.REG_Q5,
+            Arm.REG_Q6,
+            Arm.REG_Q7,
+            Arm.REG_Q8,
+            Arm.REG_Q9,
+            Arm.REG_Q10,
+            Arm.REG_Q11,
+            Arm.REG_Q12,
+            Arm.REG_Q13,
+            Arm.REG_Q14,
+            Arm.REG_Q15
         };
 
         public uint GetX(int index)
@@ -204,7 +205,7 @@ namespace Ryujinx.Tests.Unicorn
             }
 
             // Getting quadword registers from Unicorn A32 seems to be broken, so we combine its 2 doubleword registers instead.
-            return GetVector((Arm32Register)((int)Arm32Register.D0 + index * 2));
+            return GetVector((Arm)((int)Arm.REG_D0 + index * 2));
         }
 
         public void SetQ(int index, SimdValue value)
@@ -214,10 +215,10 @@ namespace Ryujinx.Tests.Unicorn
                 throw new ArgumentOutOfRangeException(nameof(index));
             }
 
-            SetVector((Arm32Register)((int)Arm32Register.D0 + index * 2), value);
+            SetVector((Arm)((int)Arm.REG_D0 + index * 2), value);
         }
 
-        public uint GetRegister(Arm32Register register)
+        public uint GetRegister(Arm register)
         {
             byte[] data = new byte[4];
 
@@ -226,14 +227,14 @@ namespace Ryujinx.Tests.Unicorn
             return (uint)BitConverter.ToInt32(data, 0);
         }
 
-        public void SetRegister(Arm32Register register, uint value)
+        public void SetRegister(Arm register, uint value)
         {
             byte[] data = BitConverter.GetBytes(value);
 
             Interface.Checked(Interface.uc_reg_write(uc, (int)register, data));
         }
 
-        public SimdValue GetVector(Arm32Register register)
+        public SimdValue GetVector(Arm register)
         {
             byte[] data = new byte[8];
 
@@ -245,7 +246,7 @@ namespace Ryujinx.Tests.Unicorn
             return new SimdValue(lo, hi);
         }
 
-        private void SetVector(Arm32Register register, SimdValue value)
+        private void SetVector(Arm register, SimdValue value)
         {
             byte[] data = BitConverter.GetBytes(value.GetUInt64(0));
             Interface.Checked(Interface.uc_reg_write(uc, (int)register, data));
@@ -300,13 +301,10 @@ namespace Ryujinx.Tests.Unicorn
             try
             {
                 Interface.uc_version(out _, out _);
+            }
+            catch (DllNotFoundException) {  }
 
-                return true;
-            }
-            catch (DllNotFoundException)
-            {
-                return false;
-            }
+            return Interface.IsUnicornAvailable;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/Ryujinx.Tests.Unicorn/UnicornAArch64.cs b/Ryujinx.Tests.Unicorn/UnicornAArch64.cs
index c5d5540b1d..5cd5f88cb1 100644
--- a/Ryujinx.Tests.Unicorn/UnicornAArch64.cs
+++ b/Ryujinx.Tests.Unicorn/UnicornAArch64.cs
@@ -1,4 +1,5 @@
 using Ryujinx.Tests.Unicorn.Native;
+using Ryujinx.Tests.Unicorn.Native.Const;
 using System;
 
 namespace Ryujinx.Tests.Unicorn
@@ -30,38 +31,38 @@ namespace Ryujinx.Tests.Unicorn
 
         public ulong LR
         {
-            get => GetRegister(ArmRegister.LR);
-            set => SetRegister(ArmRegister.LR, value);
+            get => GetRegister(Arm64.REG_LR);
+            set => SetRegister(Arm64.REG_LR, value);
         }
 
         public ulong SP
         {
-            get => GetRegister(ArmRegister.SP);
-            set => SetRegister(ArmRegister.SP, value);
+            get => GetRegister(Arm64.REG_SP);
+            set => SetRegister(Arm64.REG_SP, value);
         }
 
         public ulong PC
         {
-            get => GetRegister(ArmRegister.PC);
-            set => SetRegister(ArmRegister.PC, value);
+            get => GetRegister(Arm64.REG_PC);
+            set => SetRegister(Arm64.REG_PC, value);
         }
 
         public uint Pstate
         {
-            get => (uint)GetRegister(ArmRegister.PSTATE);
-            set =>       SetRegister(ArmRegister.PSTATE, (uint)value);
+            get => (uint)GetRegister(Arm64.REG_PSTATE);
+            set =>       SetRegister(Arm64.REG_PSTATE, (uint)value);
         }
 
         public int Fpcr
         {
-            get => (int)GetRegister(ArmRegister.FPCR);
-            set =>      SetRegister(ArmRegister.FPCR, (uint)value);
+            get => (int)GetRegister(Arm64.REG_FPCR);
+            set =>      SetRegister(Arm64.REG_FPCR, (uint)value);
         }
 
         public int Fpsr
         {
-            get => (int)GetRegister(ArmRegister.FPSR);
-            set =>      SetRegister(ArmRegister.FPSR, (uint)value);
+            get => (int)GetRegister(Arm64.REG_FPSR);
+            set =>      SetRegister(Arm64.REG_FPSR, (uint)value);
         }
 
         public bool OverflowFlag
@@ -90,9 +91,9 @@ namespace Ryujinx.Tests.Unicorn
 
         public UnicornAArch64()
         {
-            Interface.Checked(Interface.uc_open(UnicornArch.UC_ARCH_ARM64, UnicornMode.UC_MODE_LITTLE_ENDIAN, out uc));
+            Interface.Checked(Interface.uc_open(Arch.ARM64, Mode.LITTLE_ENDIAN, out uc));
 
-            SetRegister(ArmRegister.CPACR_EL1, 0x00300000);
+            SetRegister(Arm64.REG_CPACR_EL1, 0x00300000);
         }
 
         ~UnicornAArch64()
@@ -125,75 +126,75 @@ namespace Ryujinx.Tests.Unicorn
             RunForCount(1);
         }
 
-        private static ArmRegister[] XRegisters = new ArmRegister[31]
+        private static Arm64[] XRegisters = new Arm64[31]
         {
-            ArmRegister.X0,
-            ArmRegister.X1,
-            ArmRegister.X2,
-            ArmRegister.X3,
-            ArmRegister.X4,
-            ArmRegister.X5,
-            ArmRegister.X6,
-            ArmRegister.X7,
-            ArmRegister.X8,
-            ArmRegister.X9,
-            ArmRegister.X10,
-            ArmRegister.X11,
-            ArmRegister.X12,
-            ArmRegister.X13,
-            ArmRegister.X14,
-            ArmRegister.X15,
-            ArmRegister.X16,
-            ArmRegister.X17,
-            ArmRegister.X18,
-            ArmRegister.X19,
-            ArmRegister.X20,
-            ArmRegister.X21,
-            ArmRegister.X22,
-            ArmRegister.X23,
-            ArmRegister.X24,
-            ArmRegister.X25,
-            ArmRegister.X26,
-            ArmRegister.X27,
-            ArmRegister.X28,
-            ArmRegister.X29,
-            ArmRegister.X30,
+            Arm64.REG_X0,
+            Arm64.REG_X1,
+            Arm64.REG_X2,
+            Arm64.REG_X3,
+            Arm64.REG_X4,
+            Arm64.REG_X5,
+            Arm64.REG_X6,
+            Arm64.REG_X7,
+            Arm64.REG_X8,
+            Arm64.REG_X9,
+            Arm64.REG_X10,
+            Arm64.REG_X11,
+            Arm64.REG_X12,
+            Arm64.REG_X13,
+            Arm64.REG_X14,
+            Arm64.REG_X15,
+            Arm64.REG_X16,
+            Arm64.REG_X17,
+            Arm64.REG_X18,
+            Arm64.REG_X19,
+            Arm64.REG_X20,
+            Arm64.REG_X21,
+            Arm64.REG_X22,
+            Arm64.REG_X23,
+            Arm64.REG_X24,
+            Arm64.REG_X25,
+            Arm64.REG_X26,
+            Arm64.REG_X27,
+            Arm64.REG_X28,
+            Arm64.REG_X29,
+            Arm64.REG_X30,
         };
 
-        private static ArmRegister[] QRegisters = new ArmRegister[32]
+        private static Arm64[] QRegisters = new Arm64[32]
         {
-            ArmRegister.Q0,
-            ArmRegister.Q1,
-            ArmRegister.Q2,
-            ArmRegister.Q3,
-            ArmRegister.Q4,
-            ArmRegister.Q5,
-            ArmRegister.Q6,
-            ArmRegister.Q7,
-            ArmRegister.Q8,
-            ArmRegister.Q9,
-            ArmRegister.Q10,
-            ArmRegister.Q11,
-            ArmRegister.Q12,
-            ArmRegister.Q13,
-            ArmRegister.Q14,
-            ArmRegister.Q15,
-            ArmRegister.Q16,
-            ArmRegister.Q17,
-            ArmRegister.Q18,
-            ArmRegister.Q19,
-            ArmRegister.Q20,
-            ArmRegister.Q21,
-            ArmRegister.Q22,
-            ArmRegister.Q23,
-            ArmRegister.Q24,
-            ArmRegister.Q25,
-            ArmRegister.Q26,
-            ArmRegister.Q27,
-            ArmRegister.Q28,
-            ArmRegister.Q29,
-            ArmRegister.Q30,
-            ArmRegister.Q31,
+            Arm64.REG_Q0,
+            Arm64.REG_Q1,
+            Arm64.REG_Q2,
+            Arm64.REG_Q3,
+            Arm64.REG_Q4,
+            Arm64.REG_Q5,
+            Arm64.REG_Q6,
+            Arm64.REG_Q7,
+            Arm64.REG_Q8,
+            Arm64.REG_Q9,
+            Arm64.REG_Q10,
+            Arm64.REG_Q11,
+            Arm64.REG_Q12,
+            Arm64.REG_Q13,
+            Arm64.REG_Q14,
+            Arm64.REG_Q15,
+            Arm64.REG_Q16,
+            Arm64.REG_Q17,
+            Arm64.REG_Q18,
+            Arm64.REG_Q19,
+            Arm64.REG_Q20,
+            Arm64.REG_Q21,
+            Arm64.REG_Q22,
+            Arm64.REG_Q23,
+            Arm64.REG_Q24,
+            Arm64.REG_Q25,
+            Arm64.REG_Q26,
+            Arm64.REG_Q27,
+            Arm64.REG_Q28,
+            Arm64.REG_Q29,
+            Arm64.REG_Q30,
+            Arm64.REG_Q31,
         };
 
         public ulong GetX(int index)
@@ -236,7 +237,7 @@ namespace Ryujinx.Tests.Unicorn
             SetVector(QRegisters[index], value);
         }
 
-        private ulong GetRegister(ArmRegister register)
+        private ulong GetRegister(Arm64 register)
         {
             byte[] data = new byte[8];
 
@@ -245,14 +246,14 @@ namespace Ryujinx.Tests.Unicorn
             return (ulong)BitConverter.ToInt64(data, 0);
         }
 
-        private void SetRegister(ArmRegister register, ulong value)
+        private void SetRegister(Arm64 register, ulong value)
         {
             byte[] data = BitConverter.GetBytes(value);
 
             Interface.Checked(Interface.uc_reg_write(uc, (int)register, data));
         }
 
-        private SimdValue GetVector(ArmRegister register)
+        private SimdValue GetVector(Arm64 register)
         {
             byte[] data = new byte[16];
 
@@ -261,7 +262,7 @@ namespace Ryujinx.Tests.Unicorn
             return new SimdValue(data);
         }
 
-        private void SetVector(ArmRegister register, SimdValue value)
+        private void SetVector(Arm64 register, SimdValue value)
         {
             byte[] data = value.ToArray();
 
@@ -315,13 +316,10 @@ namespace Ryujinx.Tests.Unicorn
             try
             {
                 Interface.uc_version(out _, out _);
+            }
+            catch (DllNotFoundException) {  }
 
-                return true;
-            }
-            catch (DllNotFoundException)
-            {
-                return false;
-            }
+            return Interface.IsUnicornAvailable;
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.Tests.Unicorn/UnicornError.cs b/Ryujinx.Tests.Unicorn/UnicornError.cs
deleted file mode 100644
index ac324089c1..0000000000
--- a/Ryujinx.Tests.Unicorn/UnicornError.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-// ReSharper disable InconsistentNaming
-namespace Ryujinx.Tests.Unicorn
-{
-    public enum UnicornError
-    {
-        UC_ERR_OK = 0,             // No error: everything was fine
-        UC_ERR_NOMEM,              // Out-Of-Memory error: uc_open(), uc_emulate()
-        UC_ERR_ARCH,               // Unsupported architecture: uc_open()
-        UC_ERR_HANDLE,             // Invalid handle
-        UC_ERR_MODE,               // Invalid/unsupported mode: uc_open()
-        UC_ERR_VERSION,            // Unsupported version (bindings)
-        UC_ERR_READ_UNMAPPED,      // Quit emulation due to READ on unmapped memory: uc_emu_start()
-        UC_ERR_WRITE_UNMAPPED,     // Quit emulation due to WRITE on unmapped memory: uc_emu_start()
-        UC_ERR_FETCH_UNMAPPED,     // Quit emulation due to FETCH on unmapped memory: uc_emu_start()
-        UC_ERR_HOOK,               // Invalid hook type: uc_hook_add()
-        UC_ERR_INSN_INVALID,       // Quit emulation due to invalid instruction: uc_emu_start()
-        UC_ERR_MAP,                // Invalid memory mapping: uc_mem_map()
-        UC_ERR_WRITE_PROT,         // Quit emulation due to UC_MEM_WRITE_PROT violation: uc_emu_start()
-        UC_ERR_READ_PROT,          // Quit emulation due to UC_MEM_READ_PROT violation: uc_emu_start()
-        UC_ERR_FETCH_PROT,         // Quit emulation due to UC_MEM_FETCH_PROT violation: uc_emu_start()
-        UC_ERR_ARG,                // Invalid argument provided to uc_xxx function (See specific function API)
-        UC_ERR_READ_UNALIGNED,     // Unaligned read
-        UC_ERR_WRITE_UNALIGNED,    // Unaligned write
-        UC_ERR_FETCH_UNALIGNED,    // Unaligned fetch
-        UC_ERR_HOOK_EXIST,         // hook for this event already existed
-        UC_ERR_RESOURCE,           // Insufficient resource: uc_emu_start()
-        UC_ERR_EXCEPTION           // Unhandled CPU exception
-    }
-}
diff --git a/Ryujinx.Tests.Unicorn/UnicornException.cs b/Ryujinx.Tests.Unicorn/UnicornException.cs
index 3cb693703c..b5c5f980eb 100644
--- a/Ryujinx.Tests.Unicorn/UnicornException.cs
+++ b/Ryujinx.Tests.Unicorn/UnicornException.cs
@@ -1,3 +1,4 @@
+using Ryujinx.Tests.Unicorn.Native.Const;
 using System;
 using System.Runtime.InteropServices;
 
@@ -5,9 +6,9 @@ namespace Ryujinx.Tests.Unicorn
 {
     public class UnicornException : Exception
     {
-        public readonly UnicornError Error;
+        public readonly Error Error;
 
-        internal UnicornException(UnicornError error)
+        internal UnicornException(Error error)
         {
             Error = error;
         }
@@ -20,4 +21,4 @@ namespace Ryujinx.Tests.Unicorn
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/Ryujinx.Tests.Unicorn/libs/README.md b/Ryujinx.Tests.Unicorn/libs/README.md
index 427044f901..d05291e5cb 100644
--- a/Ryujinx.Tests.Unicorn/libs/README.md
+++ b/Ryujinx.Tests.Unicorn/libs/README.md
@@ -9,14 +9,12 @@ CPU simulator, Armeilleure.
 
 On Windows, Unicorn is shipped as a pre-compiled dynamic library (`.dll`), licenced under the GPLv2.
 
-The source code for `windows/unicorn.dll` is available at: https://github.com/MerryMage/UnicornDotNet/tree/299451c02d9c810d2feca51f5e9cb6d8b2f38960
+The source code for `windows/unicorn.dll` is available at: https://github.com/unicorn-engine/unicorn/tree/df3aa0fccbce9e1420e82110cbae5951755a0698
 
 ## Linux
 
-On Linux, you will first need to download Unicorn from https://github.com/unicorn-engine/unicorn.
+On Windows, Unicorn is shipped as a pre-compiled shared object (`.so`), licenced under the GPLv2.
 
-Then you need to patch it to expose the FSPCR register by applying `linux/unicorn_fspcr.patch` 
-
-Then, compile Unicorn from source with its `make.sh` script.
+The source code for `linux/unicorn.so` is available at: https://github.com/unicorn-engine/unicorn/tree/df3aa0fccbce9e1420e82110cbae5951755a0698
 
 See https://github.com/Ryujinx/Ryujinx/pull/1433 for details.
diff --git a/Ryujinx.Tests.Unicorn/libs/linux/libunicorn.so b/Ryujinx.Tests.Unicorn/libs/linux/libunicorn.so
new file mode 100644
index 0000000000..8d0948af99
Binary files /dev/null and b/Ryujinx.Tests.Unicorn/libs/linux/libunicorn.so differ
diff --git a/Ryujinx.Tests.Unicorn/libs/linux/unicorn_fspcr.patch b/Ryujinx.Tests.Unicorn/libs/linux/unicorn_fspcr.patch
deleted file mode 100644
index 391c2fb62b..0000000000
--- a/Ryujinx.Tests.Unicorn/libs/linux/unicorn_fspcr.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c
-index 5ff9ebb..d4953f4 100644
---- a/qemu/target-arm/unicorn_arm.c
-+++ b/qemu/target-arm/unicorn_arm.c
-@@ -101,6 +101,9 @@ int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun
-                 case UC_ARM_REG_FPEXC:
-                     *(int32_t *)value = ARM_CPU(uc, mycpu)->env.vfp.xregs[ARM_VFP_FPEXC];
-                     break;
-+                case UC_ARM_REG_FPSCR:
-+                    *(int32_t *)value = vfp_get_fpscr(&ARM_CPU(uc, mycpu)->env);
-+                    break;
-                 case UC_ARM_REG_IPSR:
-                     *(uint32_t *)value = xpsr_read(&ARM_CPU(uc, mycpu)->env) & 0x1ff;
-                     break;
-@@ -175,6 +178,9 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, i
-                 case UC_ARM_REG_FPEXC:
-                     ARM_CPU(uc, mycpu)->env.vfp.xregs[ARM_VFP_FPEXC] = *(int32_t *)value;
-                     break;
-+                case UC_ARM_REG_FPSCR:
-+                    vfp_set_fpscr(&ARM_CPU(uc, mycpu)->env, *(uint32_t *)value);
-+                    break;
-                 case UC_ARM_REG_IPSR:
-                     xpsr_write(&ARM_CPU(uc, mycpu)->env, *(uint32_t *)value, 0x1ff);
-                     break;
diff --git a/Ryujinx.Tests.Unicorn/libs/windows/unicorn.dll b/Ryujinx.Tests.Unicorn/libs/windows/unicorn.dll
index 146628e143..1c84586e41 100644
Binary files a/Ryujinx.Tests.Unicorn/libs/windows/unicorn.dll and b/Ryujinx.Tests.Unicorn/libs/windows/unicorn.dll differ
diff --git a/Ryujinx.Tests.Unicorn/unicorn_const_generator.py b/Ryujinx.Tests.Unicorn/unicorn_const_generator.py
new file mode 100644
index 0000000000..813485fd27
--- /dev/null
+++ b/Ryujinx.Tests.Unicorn/unicorn_const_generator.py
@@ -0,0 +1,199 @@
+#!/usr/bin/env python3
+# Unicorn Engine
+# By Dang Hoang Vu, 2013
+# Modified for Ryujinx from: https://github.com/unicorn-engine/unicorn/blob/6c1cbef6ac505d355033aef1176b684d02e1eb3a/bindings/const_generator.py
+from __future__ import print_function
+import sys, re, os
+
+include = [ 'arm.h', 'arm64.h', 'unicorn.h' ]
+split_common = [ 'ARCH', 'MODE', 'ERR', 'MEM', 'TCG', 'HOOK', 'PROT' ]
+
+template = {
+    'dotnet': {
+            'header': "// Constants for Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT\n\n// ReSharper disable InconsistentNaming\nnamespace Ryujinx.Tests.Unicorn.Native.Const\n{\n    public enum %s\n    {\n",
+            'footer': "    }\n}\n",
+            'line_format': '        %s = %s,\n',
+            'out_file': os.path.join(os.path.dirname(__file__), 'Native', 'Const', '%s.cs'),
+            # prefixes for constant filenames of all archs - case sensitive
+            'arm.h': 'Arm',
+            'arm64.h': 'Arm64',
+            'unicorn.h': 'Common',
+            # prefixes for filenames of split_common values - case sensitive
+            'ARCH': 'Arch',
+            'MODE': 'Mode',
+            'ERR': 'Error',
+            'MEM': 'Memory',
+            'TCG': 'TCG',
+            'HOOK': 'Hook',
+            'PROT': 'Permission',
+            'comment_open': '        //',
+            'comment_close': '',
+        }
+}
+
+# markup for comments to be added to autogen files
+MARKUP = '//>'
+
+def gen(unicorn_repo_path):
+    global include
+    include_dir = os.path.join(unicorn_repo_path, 'include', 'unicorn')
+    templ = template["dotnet"]
+    for target in include:
+        prefix = templ[target]
+        outfile = open(templ['out_file'] %(prefix), 'wb')   # open as binary prevents windows newlines
+        outfile.write((templ['header'] % (prefix)).encode("utf-8"))
+        if target == 'unicorn.h':
+            prefix = ''
+            for cat in split_common:
+                with open(templ['out_file'] %(templ[cat]), 'wb') as file:
+                    file.write((templ['header'] %(templ[cat])).encode("utf-8"))
+        with open(os.path.join(include_dir, target)) as f:
+            lines = f.readlines()
+
+        previous = {}
+        count = 0
+        skip = 0
+        in_comment = False
+
+        for lno, line in enumerate(lines):
+            if "/*" in line:
+                in_comment = True
+            if "*/" in line:
+                in_comment = False
+            if in_comment:
+                continue
+            if skip > 0:
+                # Due to clang-format, values may come up in the next line
+                skip -= 1
+                continue
+            line = line.strip()
+
+            if line.startswith(MARKUP):  # markup for comments
+                outfile.write(("\n%s%s%s\n" %(templ['comment_open'], \
+                            line.replace(MARKUP, ''), templ['comment_close'])).encode("utf-8"))
+                continue
+
+            if line == '' or line.startswith('//'):
+                continue
+
+            tmp = line.strip().split(',')
+            if len(tmp) >= 2 and tmp[0] != "#define" and not tmp[0].startswith("UC_"):
+                continue
+            for t in tmp:
+                t = t.strip()
+                if not t or t.startswith('//'): continue
+                f = re.split('\s+', t)
+
+                # parse #define UC_TARGET (num)
+                define = False
+                if f[0] == '#define' and len(f) >= 3:
+                    define = True
+                    f.pop(0)
+                    f.insert(1, '=')
+                if f[0].startswith("UC_" + prefix.upper()) or f[0].startswith("UC_CPU"):
+                    if len(f) > 1 and f[1] not in ('//', '='):
+                        print("WARNING: Unable to convert %s" % f)
+                        print("  Line =", line)
+                        continue
+                    elif len(f) > 1 and f[1] == '=':
+                        # Like:
+                        # UC_A =
+                        #       (1 << 2)
+                        # #define UC_B \
+                        #              (UC_A | UC_C)
+                        # Let's search the next line
+                        if len(f) == 2:
+                            if lno == len(lines) - 1:
+                                print("WARNING: Unable to convert %s" % f)
+                                print("  Line =", line)
+                                continue
+                            skip += 1
+                            next_line = lines[lno + 1]
+                            next_line_tmp = next_line.strip().split(",")
+                            rhs = next_line_tmp[0]
+                        elif f[-1] == "\\":
+                            idx = 0
+                            rhs = ""
+                            while True:
+                                idx += 1
+                                if lno + idx == len(lines):
+                                    print("WARNING: Unable to convert %s" % f)
+                                    print("  Line =", line)
+                                    continue
+                                skip += 1
+                                next_line = lines[lno + idx]
+                                next_line_f = re.split('\s+', next_line.strip())
+                                if next_line_f[-1] == "\\":
+                                    rhs += "".join(next_line_f[:-1])
+                                else:
+                                    rhs += next_line.strip()
+                                    break
+                        else:
+                            rhs = ''.join(f[2:])
+                    else:
+                        rhs = str(count)
+
+
+                    lhs = f[0].strip()
+                    #print(f'lhs: {lhs} rhs: {rhs} f:{f}')
+                    # evaluate bitshifts in constants e.g. "UC_X86 = 1 << 1"
+                    match = re.match(r'(?P<rhs>\s*\d+\s*<<\s*\d+\s*)', rhs)
+                    if match:
+                        rhs = str(eval(match.group(1)))
+                    else:
+                        # evaluate references to other constants e.g. "UC_ARM_REG_X = UC_ARM_REG_SP"
+                        match = re.match(r'^([^\d]\w+)$', rhs)
+                        if match:
+                            rhs = previous[match.group(1)]
+
+                    if not rhs.isdigit():
+                        for k, v in previous.items():
+                            rhs = re.sub(r'\b%s\b' % k, v, rhs)
+                        rhs = str(eval(rhs))
+
+                    lhs_strip = re.sub(r'^UC_', '', lhs)
+                    count = int(rhs) + 1
+
+                    if target == "unicorn.h":
+                        matched_cat = False
+                        for cat in split_common:
+                            if lhs_strip.startswith(f"{cat}_"):
+                                with open(templ['out_file'] %(templ[cat]), 'ab') as cat_file:
+                                    cat_lhs_strip = lhs_strip
+                                    if not lhs_strip.lstrip(f"{cat}_").isnumeric():
+                                        cat_lhs_strip = lhs_strip.replace(f"{cat}_", "", 1)
+                                    cat_file.write(
+                                        (templ['line_format'] % (cat_lhs_strip, rhs)).encode("utf-8"))
+                                    matched_cat = True
+                                    break
+                        if matched_cat:
+                            previous[lhs] = str(rhs)
+                            continue
+
+                    if (count == 1):
+                        outfile.write(("\n").encode("utf-8"))
+
+                    if lhs_strip.startswith(f"{prefix.upper()}_") and not lhs_strip.replace(f"{prefix.upper()}_", "", 1).isnumeric():
+                        lhs_strip = lhs_strip.replace(f"{prefix.upper()}_", "", 1)
+
+                    outfile.write((templ['line_format'] % (lhs_strip, rhs)).encode("utf-8"))
+                    previous[lhs] = str(rhs)
+
+        outfile.write((templ['footer']).encode("utf-8"))
+        outfile.close()
+
+        if target == "unicorn.h":
+            for cat in split_common:
+                with open(templ['out_file'] %(templ[cat]), 'ab') as cat_file:
+                    cat_file.write(templ['footer'].encode('utf-8'))
+
+if __name__ == "__main__":
+    if len(sys.argv) < 2:
+        print("Usage:", sys.argv[0], " <path to unicorn repo>")
+        sys.exit(1)
+    unicorn_repo_path = sys.argv[1]
+    if os.path.isdir(unicorn_repo_path):
+        print("Generating constants for dotnet")
+        gen(unicorn_repo_path)
+    else:
+        print("Couldn't find unicorn repo at:", unicorn_repo_path)
diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs
index f983a03fb5..cafed37da5 100644
--- a/Ryujinx.Tests/Cpu/CpuTest.cs
+++ b/Ryujinx.Tests/Cpu/CpuTest.cs
@@ -38,14 +38,11 @@ namespace Ryujinx.Tests.Cpu
 
         private bool _usingMemory;
 
-        static CpuTest()
+        [OneTimeSetUp]
+        public void OneTimeSetup()
         {
             _unicornAvailable = UnicornAArch64.IsAvailable();
-
-            if (!_unicornAvailable)
-            {
-                Console.WriteLine("WARNING: Could not find Unicorn.");
-            }
+            Assume.That(_unicornAvailable, "Unicorn is not available");
         }
 
         [SetUp]
@@ -610,4 +607,4 @@ namespace Ryujinx.Tests.Cpu
             return rnd & 0x800FFFFFFFFFFFFFul;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/Ryujinx.Tests/Cpu/CpuTest32.cs b/Ryujinx.Tests/Cpu/CpuTest32.cs
index 2c36396f9a..53fea943d9 100644
--- a/Ryujinx.Tests/Cpu/CpuTest32.cs
+++ b/Ryujinx.Tests/Cpu/CpuTest32.cs
@@ -33,14 +33,11 @@ namespace Ryujinx.Tests.Cpu
 
         private bool _usingMemory;
 
-        static CpuTest32()
+        [OneTimeSetUp]
+        public void OneTimeSetup()
         {
             _unicornAvailable = UnicornAArch32.IsAvailable();
-
-            if (!_unicornAvailable)
-            {
-                Console.WriteLine("WARNING: Could not find Unicorn.");
-            }
+            Assume.That(_unicornAvailable, "Unicorn is not available");
         }
 
         [SetUp]
diff --git a/Ryujinx.Tests/Ryujinx.Tests.csproj b/Ryujinx.Tests/Ryujinx.Tests.csproj
index 6ab2fa6b10..b56929dc9e 100644
--- a/Ryujinx.Tests/Ryujinx.Tests.csproj
+++ b/Ryujinx.Tests/Ryujinx.Tests.csproj
@@ -34,7 +34,17 @@
   </ItemGroup>
 
   <Target Name="CopyUnicorn" AfterTargets="Build">
-    <Copy SourceFiles="..\Ryujinx.Tests.Unicorn\libs\$(TargetOS)\unicorn.dll" DestinationFolder="$(OutputPath)" ContinueOnError="true" />
+    <ItemGroup>
+      <UnicornLib Include="..\Ryujinx.Tests.Unicorn\libs\$(TargetOS)\*unicorn.*"/>
+    </ItemGroup>
+    <Copy SourceFiles="@(UnicornLib)" DestinationFolder="$(OutputPath)" ContinueOnError="true" />
+  </Target>
+
+  <Target Name="CleanUnicorn" BeforeTargets="Clean">
+    <ItemGroup>
+      <UnicornLib Include="$(OutputPath)/unicorn.*"/>
+    </ItemGroup>
+    <Delete Files="@(UnicornLib)" />
   </Target>
 
 </Project>