commit de493310e7da1a7bc0570b520c8e0cf85cb8c6ee Author: quaK <38787176+Joelrau@users.noreply.github.com> Date: Thu May 19 19:11:05 2022 +0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5a07442d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vs +.vscode +build/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..fc70e9f2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,33 @@ +[submodule "deps/GSL"] + path = deps/GSL + url = https://github.com/Microsoft/GSL.git +[submodule "deps/asmjit"] + path = deps/asmjit + url = https://github.com/asmjit/asmjit +[submodule "deps/udis86"] + path = deps/udis86 + url = https://github.com/vmt/udis86.git +[submodule "deps/minhook"] + path = deps/minhook + url = https://github.com/TsudaKageyu/minhook.git +[submodule "deps/libtommath"] + path = deps/libtommath + url = https://github.com/libtom/libtommath.git + branch = develop +[submodule "deps/libtomcrypt"] + path = deps/libtomcrypt + url = https://github.com/libtom/libtomcrypt.git + branch = develop +[submodule "deps/zlib"] + path = deps/zlib + url = https://github.com/madler/zlib.git + branch = develop +[submodule "deps/stb"] + path = deps/stb + url = https://github.com/nothings/stb.git +[submodule "deps/zstd"] + path = deps/zstd + url = https://github.com/facebook/zstd.git +[submodule "deps/rapidjson"] + path = deps/rapidjson + url = https://github.com/Tencent/rapidjson.git diff --git a/deps/GSL b/deps/GSL new file mode 160000 index 00000000..da01eb28 --- /dev/null +++ b/deps/GSL @@ -0,0 +1 @@ +Subproject commit da01eb28dbb75bed11a51acff0f80ecedd622573 diff --git a/deps/asmjit b/deps/asmjit new file mode 160000 index 00000000..a4cb51b5 --- /dev/null +++ b/deps/asmjit @@ -0,0 +1 @@ +Subproject commit a4cb51b532af0f8137c4182914244c3b05d7745f diff --git a/deps/extra/udis86/libudis86/itab.c b/deps/extra/udis86/libudis86/itab.c new file mode 100644 index 00000000..953f3e52 --- /dev/null +++ b/deps/extra/udis86/libudis86/itab.c @@ -0,0 +1,5946 @@ +/* itab.c -- generated by udis86:scripts/ud_itab.py, do no edit */ +#include "decode.h" + +#define GROUP(n) (0x8000 | (n)) +#define INVALID 0 + + +const uint16_t ud_itab__0[] = { + /* 0 */ 15, 16, 17, 18, + /* 4 */ 19, 20, GROUP(1), GROUP(2), + /* 8 */ 964, 965, 966, 967, + /* c */ 968, 969, GROUP(3), GROUP(4), + /* 10 */ 5, 6, 7, 8, + /* 14 */ 9, 10, GROUP(284), GROUP(285), + /* 18 */ 1336, 1337, 1338, 1339, + /* 1c */ 1340, 1341, GROUP(286), GROUP(287), + /* 20 */ 49, 50, 51, 52, + /* 24 */ 53, 54, INVALID, GROUP(288), + /* 28 */ 1407, 1408, 1409, 1410, + /* 2c */ 1411, 1412, INVALID, GROUP(289), + /* 30 */ 1487, 1488, 1489, 1490, + /* 34 */ 1491, 1492, INVALID, GROUP(290), + /* 38 */ 100, 101, 102, 103, + /* 3c */ 104, 105, INVALID, GROUP(291), + /* 40 */ 699, 700, 701, 702, + /* 44 */ 703, 704, 705, 706, + /* 48 */ 175, 176, 177, 178, + /* 4c */ 179, 180, 181, 182, + /* 50 */ 1246, 1247, 1248, 1249, + /* 54 */ 1250, 1251, 1252, 1253, + /* 58 */ 1101, 1102, 1103, 1104, + /* 5c */ 1105, 1106, 1107, 1108, + /* 60 */ GROUP(292), GROUP(295), GROUP(298), GROUP(299), + /* 64 */ INVALID, INVALID, INVALID, INVALID, + /* 68 */ 1254, 697, 1256, 698, + /* 6c */ 709, GROUP(300), 982, GROUP(301), + /* 70 */ 726, 728, 730, 732, + /* 74 */ 734, 736, 738, 740, + /* 78 */ 742, 744, 746, 748, + /* 7c */ 750, 752, 754, 756, + /* 80 */ GROUP(302), GROUP(303), GROUP(304), GROUP(313), + /* 84 */ 1433, 1434, 1475, 1476, + /* 88 */ 828, 829, 830, 831, + /* 8c */ 832, 770, 833, GROUP(314), + /* 90 */ 1477, 1478, 1479, 1480, + /* 94 */ 1481, 1482, 1483, 1484, + /* 98 */ GROUP(315), GROUP(316), GROUP(317), 1470, + /* 9c */ GROUP(318), GROUP(322), 1310, 766, + /* a0 */ 834, 835, 836, 837, + /* a4 */ 922, GROUP(326), 114, GROUP(327), + /* a8 */ 1435, 1436, 1402, GROUP(328), + /* ac */ 790, GROUP(329), 1346, GROUP(330), + /* b0 */ 838, 839, 840, 841, + /* b4 */ 842, 843, 844, 845, + /* b8 */ 846, 847, 848, 849, + /* bc */ 850, 851, 852, 853, + /* c0 */ GROUP(331), GROUP(332), 1301, 1302, + /* c4 */ GROUP(333), GROUP(403), GROUP(405), GROUP(406), + /* c8 */ 200, 776, 1303, 1304, + /* cc */ 713, 714, GROUP(407), GROUP(408), + /* d0 */ GROUP(409), GROUP(410), GROUP(411), GROUP(412), + /* d4 */ GROUP(413), GROUP(414), GROUP(415), 1486, + /* d8 */ GROUP(416), GROUP(419), GROUP(422), GROUP(425), + /* dc */ GROUP(428), GROUP(431), GROUP(434), GROUP(437), + /* e0 */ 794, 795, 796, GROUP(440), + /* e4 */ 690, 691, 978, 979, + /* e8 */ 72, 763, GROUP(441), 765, + /* ec */ 692, 693, 980, 981, + /* f0 */ 789, 712, 1299, 1300, + /* f4 */ 687, 83, GROUP(442), GROUP(443), + /* f8 */ 77, 1395, 81, 1398, + /* fc */ 78, 1396, GROUP(444), GROUP(445), +}; + +static const uint16_t ud_itab__1[] = { + /* 0 */ 1240, INVALID, +}; + +static const uint16_t ud_itab__2[] = { + /* 0 */ 1096, INVALID, +}; + +static const uint16_t ud_itab__3[] = { + /* 0 */ 1241, INVALID, +}; + +static const uint16_t ud_itab__4[] = { + /* 0 */ GROUP(5), GROUP(6), 767, 797, + /* 4 */ INVALID, 1426, 82, 1431, + /* 8 */ 716, 1471, INVALID, 1444, + /* c */ INVALID, GROUP(27), 430, GROUP(28), + /* 10 */ GROUP(29), GROUP(30), GROUP(31), GROUP(34), + /* 14 */ GROUP(35), GROUP(36), GROUP(37), GROUP(40), + /* 18 */ GROUP(41), 955, 956, 957, + /* 1c */ 958, 959, 960, 961, + /* 20 */ 854, 855, 856, 857, + /* 24 */ INVALID, INVALID, INVALID, INVALID, + /* 28 */ GROUP(42), GROUP(43), GROUP(44), GROUP(45), + /* 2c */ GROUP(46), GROUP(47), GROUP(48), GROUP(49), + /* 30 */ 1472, 1297, 1295, 1296, + /* 34 */ GROUP(50), GROUP(52), INVALID, 1514, + /* 38 */ GROUP(54), INVALID, GROUP(116), INVALID, + /* 3c */ INVALID, INVALID, INVALID, INVALID, + /* 40 */ 84, 85, 86, 87, + /* 44 */ 88, 89, 90, 91, + /* 48 */ 92, 93, 94, 95, + /* 4c */ 96, 97, 98, 99, + /* 50 */ GROUP(143), GROUP(144), GROUP(145), GROUP(146), + /* 54 */ GROUP(147), GROUP(148), GROUP(149), GROUP(150), + /* 58 */ GROUP(151), GROUP(152), GROUP(153), GROUP(154), + /* 5c */ GROUP(155), GROUP(156), GROUP(157), GROUP(158), + /* 60 */ GROUP(159), GROUP(160), GROUP(161), GROUP(162), + /* 64 */ GROUP(163), GROUP(164), GROUP(165), GROUP(166), + /* 68 */ GROUP(167), GROUP(168), GROUP(169), GROUP(170), + /* 6c */ GROUP(171), GROUP(172), GROUP(173), GROUP(176), + /* 70 */ GROUP(177), GROUP(178), GROUP(182), GROUP(186), + /* 74 */ GROUP(191), GROUP(192), GROUP(193), 199, + /* 78 */ GROUP(194), GROUP(195), INVALID, INVALID, + /* 7c */ GROUP(196), GROUP(197), GROUP(198), GROUP(201), + /* 80 */ 727, 729, 731, 733, + /* 84 */ 735, 737, 739, 741, + /* 88 */ 743, 745, 747, 749, + /* 8c */ 751, 753, 755, 757, + /* 90 */ 1350, 1351, 1352, 1353, + /* 94 */ 1354, 1355, 1356, 1357, + /* 98 */ 1358, 1359, 1360, 1361, + /* 9c */ 1362, 1363, 1364, 1365, + /* a0 */ 1245, 1100, 131, 1670, + /* a4 */ 1375, 1376, GROUP(202), GROUP(207), + /* a8 */ 1244, 1099, 1305, 1675, + /* ac */ 1377, 1378, GROUP(215), 694, + /* b0 */ 122, 123, 775, 1673, + /* b4 */ 772, 773, 940, 941, + /* b8 */ GROUP(221), INVALID, GROUP(222), 1671, + /* bc */ 1659, 1660, 930, 931, + /* c0 */ 1473, 1474, GROUP(223), 904, + /* c4 */ GROUP(224), GROUP(225), GROUP(226), GROUP(227), + /* c8 */ 1661, 1662, 1663, 1664, + /* cc */ 1665, 1666, 1667, 1668, + /* d0 */ GROUP(236), GROUP(237), GROUP(238), GROUP(239), + /* d4 */ GROUP(240), GROUP(241), GROUP(242), GROUP(243), + /* d8 */ GROUP(244), GROUP(245), GROUP(246), GROUP(247), + /* dc */ GROUP(248), GROUP(249), GROUP(250), GROUP(251), + /* e0 */ GROUP(252), GROUP(253), GROUP(254), GROUP(255), + /* e4 */ GROUP(256), GROUP(257), GROUP(258), GROUP(259), + /* e8 */ GROUP(260), GROUP(261), GROUP(262), GROUP(263), + /* ec */ GROUP(264), GROUP(265), GROUP(266), GROUP(267), + /* f0 */ GROUP(268), GROUP(269), GROUP(270), GROUP(271), + /* f4 */ GROUP(272), GROUP(273), GROUP(274), GROUP(275), + /* f8 */ GROUP(277), GROUP(278), GROUP(279), GROUP(280), + /* fc */ GROUP(281), GROUP(282), GROUP(283), INVALID, +}; + +static const uint16_t ud_itab__5[] = { + /* 0 */ 1384, 1406, 786, 798, + /* 4 */ 1453, 1454, INVALID, INVALID, +}; + +static const uint16_t ud_itab__6[] = { + /* 0 */ GROUP(7), GROUP(8), +}; + +static const uint16_t ud_itab__7[] = { + /* 0 */ 1374, 1383, 785, 774, + /* 4 */ 1385, INVALID, 787, 719, +}; + +static const uint16_t ud_itab__8[] = { + /* 0 */ GROUP(9), GROUP(14), GROUP(15), GROUP(16), + /* 4 */ 1386, INVALID, 788, GROUP(25), +}; + +static const uint16_t ud_itab__9[] = { + /* 0 */ INVALID, GROUP(10), GROUP(11), GROUP(12), + /* 4 */ GROUP(13), INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__10[] = { + /* 0 */ INVALID, 1455, INVALID, +}; + +static const uint16_t ud_itab__11[] = { + /* 0 */ INVALID, 1461, INVALID, +}; + +static const uint16_t ud_itab__12[] = { + /* 0 */ INVALID, 1462, INVALID, +}; + +static const uint16_t ud_itab__13[] = { + /* 0 */ INVALID, 1463, INVALID, +}; + +static const uint16_t ud_itab__14[] = { + /* 0 */ 824, 952, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__15[] = { + /* 0 */ 1485, 1508, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__16[] = { + /* 0 */ GROUP(17), GROUP(18), GROUP(19), GROUP(20), + /* 4 */ GROUP(21), GROUP(22), GROUP(23), GROUP(24), +}; + +static const uint16_t ud_itab__17[] = { + /* 0 */ 1466, INVALID, INVALID, +}; + +static const uint16_t ud_itab__18[] = { + /* 0 */ 1467, INVALID, INVALID, +}; + +static const uint16_t ud_itab__19[] = { + /* 0 */ 1468, INVALID, INVALID, +}; + +static const uint16_t ud_itab__20[] = { + /* 0 */ 1469, INVALID, INVALID, +}; + +static const uint16_t ud_itab__21[] = { + /* 0 */ 1397, INVALID, INVALID, +}; + +static const uint16_t ud_itab__22[] = { + /* 0 */ 80, INVALID, INVALID, +}; + +static const uint16_t ud_itab__23[] = { + /* 0 */ 1399, INVALID, INVALID, +}; + +static const uint16_t ud_itab__24[] = { + /* 0 */ 720, INVALID, INVALID, +}; + +static const uint16_t ud_itab__25[] = { + /* 0 */ 1425, GROUP(26), INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__26[] = { + /* 0 */ 1298, INVALID, INVALID, +}; + +static const uint16_t ud_itab__27[] = { + /* 0 */ 1119, 1120, 1121, 1122, + /* 4 */ 1123, 1124, 1125, 1126, +}; + +static const uint16_t ud_itab__28[] = { + /* 0 */ INVALID, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, + /* 8 */ INVALID, INVALID, INVALID, INVALID, + /* c */ 1216, 1217, INVALID, INVALID, + /* 10 */ INVALID, INVALID, INVALID, INVALID, + /* 14 */ INVALID, INVALID, INVALID, INVALID, + /* 18 */ INVALID, INVALID, INVALID, INVALID, + /* 1c */ 1218, 1219, INVALID, INVALID, + /* 20 */ INVALID, INVALID, INVALID, INVALID, + /* 24 */ INVALID, INVALID, INVALID, INVALID, + /* 28 */ INVALID, INVALID, INVALID, INVALID, + /* 2c */ INVALID, INVALID, INVALID, INVALID, + /* 30 */ INVALID, INVALID, INVALID, INVALID, + /* 34 */ INVALID, INVALID, INVALID, INVALID, + /* 38 */ INVALID, INVALID, INVALID, INVALID, + /* 3c */ INVALID, INVALID, INVALID, INVALID, + /* 40 */ INVALID, INVALID, INVALID, INVALID, + /* 44 */ INVALID, INVALID, INVALID, INVALID, + /* 48 */ INVALID, INVALID, INVALID, INVALID, + /* 4c */ INVALID, INVALID, INVALID, INVALID, + /* 50 */ INVALID, INVALID, INVALID, INVALID, + /* 54 */ INVALID, INVALID, INVALID, INVALID, + /* 58 */ INVALID, INVALID, INVALID, INVALID, + /* 5c */ INVALID, INVALID, INVALID, INVALID, + /* 60 */ INVALID, INVALID, INVALID, INVALID, + /* 64 */ INVALID, INVALID, INVALID, INVALID, + /* 68 */ INVALID, INVALID, INVALID, INVALID, + /* 6c */ INVALID, INVALID, INVALID, INVALID, + /* 70 */ INVALID, INVALID, INVALID, INVALID, + /* 74 */ INVALID, INVALID, INVALID, INVALID, + /* 78 */ INVALID, INVALID, INVALID, INVALID, + /* 7c */ INVALID, INVALID, INVALID, INVALID, + /* 80 */ INVALID, INVALID, INVALID, INVALID, + /* 84 */ INVALID, INVALID, INVALID, INVALID, + /* 88 */ INVALID, INVALID, 1220, INVALID, + /* 8c */ INVALID, INVALID, 1221, INVALID, + /* 90 */ 1222, INVALID, INVALID, INVALID, + /* 94 */ 1223, INVALID, 1224, 1225, + /* 98 */ INVALID, INVALID, 1226, INVALID, + /* 9c */ INVALID, INVALID, 1227, INVALID, + /* a0 */ 1228, INVALID, INVALID, INVALID, + /* a4 */ 1229, INVALID, 1230, 1231, + /* a8 */ INVALID, INVALID, 1232, INVALID, + /* ac */ INVALID, INVALID, 1233, INVALID, + /* b0 */ 1234, INVALID, INVALID, INVALID, + /* b4 */ 1235, INVALID, 1236, 1237, + /* b8 */ INVALID, INVALID, INVALID, 1238, + /* bc */ INVALID, INVALID, INVALID, 1239, + /* c0 */ INVALID, INVALID, INVALID, INVALID, + /* c4 */ INVALID, INVALID, INVALID, INVALID, + /* c8 */ INVALID, INVALID, INVALID, INVALID, + /* cc */ INVALID, INVALID, INVALID, INVALID, + /* d0 */ INVALID, INVALID, INVALID, INVALID, + /* d4 */ INVALID, INVALID, INVALID, INVALID, + /* d8 */ INVALID, INVALID, INVALID, INVALID, + /* dc */ INVALID, INVALID, INVALID, INVALID, + /* e0 */ INVALID, INVALID, INVALID, INVALID, + /* e4 */ INVALID, INVALID, INVALID, INVALID, + /* e8 */ INVALID, INVALID, INVALID, INVALID, + /* ec */ INVALID, INVALID, INVALID, INVALID, + /* f0 */ INVALID, INVALID, INVALID, INVALID, + /* f4 */ INVALID, INVALID, INVALID, INVALID, + /* f8 */ INVALID, INVALID, INVALID, INVALID, + /* fc */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__29[] = { + /* 0 */ 936, 925, 928, 932, +}; + +static const uint16_t ud_itab__30[] = { + /* 0 */ 938, 926, 929, 934, +}; + +static const uint16_t ud_itab__31[] = { + /* 0 */ GROUP(32), GROUP(33), +}; + +static const uint16_t ud_itab__32[] = { + /* 0 */ 892, 1563, 1571, 888, +}; + +static const uint16_t ud_itab__33[] = { + /* 0 */ 896, 1561, 1569, INVALID, +}; + +static const uint16_t ud_itab__34[] = { + /* 0 */ 894, INVALID, INVALID, 890, +}; + +static const uint16_t ud_itab__35[] = { + /* 0 */ 1449, INVALID, INVALID, 1451, +}; + +static const uint16_t ud_itab__36[] = { + /* 0 */ 1447, INVALID, INVALID, 1445, +}; + +static const uint16_t ud_itab__37[] = { + /* 0 */ GROUP(38), GROUP(39), +}; + +static const uint16_t ud_itab__38[] = { + /* 0 */ 882, INVALID, 1567, 878, +}; + +static const uint16_t ud_itab__39[] = { + /* 0 */ 886, INVALID, 1565, INVALID, +}; + +static const uint16_t ud_itab__40[] = { + /* 0 */ 884, INVALID, INVALID, 880, +}; + +static const uint16_t ud_itab__41[] = { + /* 0 */ 1127, 1128, 1129, 1130, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__42[] = { + /* 0 */ 862, INVALID, INVALID, 858, +}; + +static const uint16_t ud_itab__43[] = { + /* 0 */ 864, INVALID, INVALID, 860, +}; + +static const uint16_t ud_itab__44[] = { + /* 0 */ 141, 152, 154, 142, +}; + +static const uint16_t ud_itab__45[] = { + /* 0 */ 907, INVALID, INVALID, 905, +}; + +static const uint16_t ud_itab__46[] = { + /* 0 */ 165, 166, 168, 162, +}; + +static const uint16_t ud_itab__47[] = { + /* 0 */ 147, 148, 158, 138, +}; + +static const uint16_t ud_itab__48[] = { + /* 0 */ 1442, INVALID, INVALID, 1440, +}; + +static const uint16_t ud_itab__49[] = { + /* 0 */ 129, INVALID, INVALID, 127, +}; + +static const uint16_t ud_itab__50[] = { + /* 0 */ 1427, GROUP(51), +}; + +static const uint16_t ud_itab__51[] = { + /* 0 */ INVALID, 1428, INVALID, +}; + +static const uint16_t ud_itab__52[] = { + /* 0 */ 1429, GROUP(53), +}; + +static const uint16_t ud_itab__53[] = { + /* 0 */ INVALID, 1430, INVALID, +}; + +static const uint16_t ud_itab__54[] = { + /* 0 */ GROUP(67), GROUP(68), GROUP(63), GROUP(64), + /* 4 */ GROUP(65), GROUP(66), GROUP(86), GROUP(90), + /* 8 */ GROUP(69), GROUP(70), GROUP(71), GROUP(72), + /* c */ INVALID, INVALID, INVALID, INVALID, + /* 10 */ GROUP(73), INVALID, INVALID, INVALID, + /* 14 */ GROUP(75), GROUP(76), INVALID, GROUP(77), + /* 18 */ INVALID, INVALID, INVALID, INVALID, + /* 1c */ GROUP(78), GROUP(79), GROUP(80), INVALID, + /* 20 */ GROUP(81), GROUP(82), GROUP(83), GROUP(84), + /* 24 */ GROUP(85), GROUP(108), INVALID, INVALID, + /* 28 */ GROUP(87), GROUP(88), GROUP(89), GROUP(74), + /* 2c */ INVALID, INVALID, INVALID, INVALID, + /* 30 */ GROUP(91), GROUP(92), GROUP(93), GROUP(94), + /* 34 */ GROUP(95), GROUP(96), INVALID, GROUP(97), + /* 38 */ GROUP(98), GROUP(99), GROUP(100), GROUP(101), + /* 3c */ GROUP(102), GROUP(103), GROUP(104), GROUP(105), + /* 40 */ GROUP(106), GROUP(107), INVALID, INVALID, + /* 44 */ INVALID, INVALID, INVALID, INVALID, + /* 48 */ INVALID, INVALID, INVALID, INVALID, + /* 4c */ INVALID, INVALID, INVALID, INVALID, + /* 50 */ INVALID, INVALID, INVALID, INVALID, + /* 54 */ INVALID, INVALID, INVALID, INVALID, + /* 58 */ INVALID, INVALID, INVALID, INVALID, + /* 5c */ INVALID, INVALID, INVALID, INVALID, + /* 60 */ INVALID, INVALID, INVALID, INVALID, + /* 64 */ INVALID, INVALID, INVALID, INVALID, + /* 68 */ INVALID, INVALID, INVALID, INVALID, + /* 6c */ INVALID, INVALID, INVALID, INVALID, + /* 70 */ INVALID, INVALID, INVALID, INVALID, + /* 74 */ INVALID, INVALID, INVALID, INVALID, + /* 78 */ INVALID, INVALID, INVALID, INVALID, + /* 7c */ INVALID, INVALID, INVALID, INVALID, + /* 80 */ GROUP(55), GROUP(59), INVALID, INVALID, + /* 84 */ INVALID, INVALID, INVALID, INVALID, + /* 88 */ INVALID, INVALID, INVALID, INVALID, + /* 8c */ INVALID, INVALID, INVALID, INVALID, + /* 90 */ INVALID, INVALID, INVALID, INVALID, + /* 94 */ INVALID, INVALID, INVALID, INVALID, + /* 98 */ INVALID, INVALID, INVALID, INVALID, + /* 9c */ INVALID, INVALID, INVALID, INVALID, + /* a0 */ INVALID, INVALID, INVALID, INVALID, + /* a4 */ INVALID, INVALID, INVALID, INVALID, + /* a8 */ INVALID, INVALID, INVALID, INVALID, + /* ac */ INVALID, INVALID, INVALID, INVALID, + /* b0 */ INVALID, INVALID, INVALID, INVALID, + /* b4 */ INVALID, INVALID, INVALID, INVALID, + /* b8 */ INVALID, INVALID, INVALID, INVALID, + /* bc */ INVALID, INVALID, INVALID, INVALID, + /* c0 */ INVALID, INVALID, INVALID, INVALID, + /* c4 */ INVALID, INVALID, INVALID, INVALID, + /* c8 */ INVALID, INVALID, INVALID, INVALID, + /* cc */ INVALID, INVALID, INVALID, INVALID, + /* d0 */ INVALID, INVALID, INVALID, INVALID, + /* d4 */ INVALID, INVALID, INVALID, INVALID, + /* d8 */ INVALID, INVALID, INVALID, GROUP(109), + /* dc */ GROUP(110), GROUP(111), GROUP(112), GROUP(113), + /* e0 */ INVALID, INVALID, INVALID, INVALID, + /* e4 */ INVALID, INVALID, INVALID, INVALID, + /* e8 */ INVALID, INVALID, INVALID, INVALID, + /* ec */ INVALID, INVALID, INVALID, INVALID, + /* f0 */ GROUP(114), GROUP(115), INVALID, INVALID, + /* f4 */ INVALID, INVALID, INVALID, INVALID, + /* f8 */ INVALID, INVALID, INVALID, INVALID, + /* fc */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__55[] = { + /* 0 */ INVALID, INVALID, INVALID, GROUP(56), +}; + +static const uint16_t ud_itab__56[] = { + /* 0 */ GROUP(57), GROUP(58), +}; + +static const uint16_t ud_itab__57[] = { + /* 0 */ INVALID, 717, INVALID, +}; + +static const uint16_t ud_itab__58[] = { + /* 0 */ INVALID, 718, INVALID, +}; + +static const uint16_t ud_itab__59[] = { + /* 0 */ INVALID, INVALID, INVALID, GROUP(60), +}; + +static const uint16_t ud_itab__60[] = { + /* 0 */ GROUP(61), GROUP(62), +}; + +static const uint16_t ud_itab__61[] = { + /* 0 */ INVALID, 721, INVALID, +}; + +static const uint16_t ud_itab__62[] = { + /* 0 */ INVALID, 722, INVALID, +}; + +static const uint16_t ud_itab__63[] = { + /* 0 */ 1588, INVALID, INVALID, 1589, +}; + +static const uint16_t ud_itab__64[] = { + /* 0 */ 1591, INVALID, INVALID, 1592, +}; + +static const uint16_t ud_itab__65[] = { + /* 0 */ 1594, INVALID, INVALID, 1595, +}; + +static const uint16_t ud_itab__66[] = { + /* 0 */ 1597, INVALID, INVALID, 1598, +}; + +static const uint16_t ud_itab__67[] = { + /* 0 */ 1582, INVALID, INVALID, 1583, +}; + +static const uint16_t ud_itab__68[] = { + /* 0 */ 1585, INVALID, INVALID, 1586, +}; + +static const uint16_t ud_itab__69[] = { + /* 0 */ 1606, INVALID, INVALID, 1607, +}; + +static const uint16_t ud_itab__70[] = { + /* 0 */ 1612, INVALID, INVALID, 1613, +}; + +static const uint16_t ud_itab__71[] = { + /* 0 */ 1609, INVALID, INVALID, 1610, +}; + +static const uint16_t ud_itab__72[] = { + /* 0 */ 1615, INVALID, INVALID, 1616, +}; + +static const uint16_t ud_itab__73[] = { + /* 0 */ INVALID, INVALID, INVALID, 1621, +}; + +static const uint16_t ud_itab__74[] = { + /* 0 */ INVALID, INVALID, INVALID, 1683, +}; + +static const uint16_t ud_itab__75[] = { + /* 0 */ INVALID, INVALID, INVALID, 1657, +}; + +static const uint16_t ud_itab__76[] = { + /* 0 */ INVALID, INVALID, INVALID, 1656, +}; + +static const uint16_t ud_itab__77[] = { + /* 0 */ INVALID, INVALID, INVALID, 1711, +}; + +static const uint16_t ud_itab__78[] = { + /* 0 */ 1573, INVALID, INVALID, 1574, +}; + +static const uint16_t ud_itab__79[] = { + /* 0 */ 1576, INVALID, INVALID, 1577, +}; + +static const uint16_t ud_itab__80[] = { + /* 0 */ 1579, INVALID, INVALID, 1580, +}; + +static const uint16_t ud_itab__81[] = { + /* 0 */ INVALID, INVALID, INVALID, 1685, +}; + +static const uint16_t ud_itab__82[] = { + /* 0 */ INVALID, INVALID, INVALID, 1687, +}; + +static const uint16_t ud_itab__83[] = { + /* 0 */ INVALID, INVALID, INVALID, 1689, +}; + +static const uint16_t ud_itab__84[] = { + /* 0 */ INVALID, INVALID, INVALID, 1691, +}; + +static const uint16_t ud_itab__85[] = { + /* 0 */ INVALID, INVALID, INVALID, 1693, +}; + +static const uint16_t ud_itab__86[] = { + /* 0 */ 1600, INVALID, INVALID, 1601, +}; + +static const uint16_t ud_itab__87[] = { + /* 0 */ INVALID, INVALID, INVALID, 1622, +}; + +static const uint16_t ud_itab__88[] = { + /* 0 */ INVALID, INVALID, INVALID, 1708, +}; + +static const uint16_t ud_itab__89[] = { + /* 0 */ INVALID, INVALID, INVALID, 1681, +}; + +static const uint16_t ud_itab__90[] = { + /* 0 */ 1603, INVALID, INVALID, 1604, +}; + +static const uint16_t ud_itab__91[] = { + /* 0 */ INVALID, INVALID, INVALID, 1696, +}; + +static const uint16_t ud_itab__92[] = { + /* 0 */ INVALID, INVALID, INVALID, 1698, +}; + +static const uint16_t ud_itab__93[] = { + /* 0 */ INVALID, INVALID, INVALID, 1700, +}; + +static const uint16_t ud_itab__94[] = { + /* 0 */ INVALID, INVALID, INVALID, 1702, +}; + +static const uint16_t ud_itab__95[] = { + /* 0 */ INVALID, INVALID, INVALID, 1704, +}; + +static const uint16_t ud_itab__96[] = { + /* 0 */ INVALID, INVALID, INVALID, 1706, +}; + +static const uint16_t ud_itab__97[] = { + /* 0 */ INVALID, INVALID, INVALID, 1717, +}; + +static const uint16_t ud_itab__98[] = { + /* 0 */ INVALID, INVALID, INVALID, 1624, +}; + +static const uint16_t ud_itab__99[] = { + /* 0 */ INVALID, INVALID, INVALID, 1626, +}; + +static const uint16_t ud_itab__100[] = { + /* 0 */ INVALID, INVALID, INVALID, 1628, +}; + +static const uint16_t ud_itab__101[] = { + /* 0 */ INVALID, INVALID, INVALID, 1630, +}; + +static const uint16_t ud_itab__102[] = { + /* 0 */ INVALID, INVALID, INVALID, 1632, +}; + +static const uint16_t ud_itab__103[] = { + /* 0 */ INVALID, INVALID, INVALID, 1634, +}; + +static const uint16_t ud_itab__104[] = { + /* 0 */ INVALID, INVALID, INVALID, 1638, +}; + +static const uint16_t ud_itab__105[] = { + /* 0 */ INVALID, INVALID, INVALID, 1636, +}; + +static const uint16_t ud_itab__106[] = { + /* 0 */ INVALID, INVALID, INVALID, 1640, +}; + +static const uint16_t ud_itab__107[] = { + /* 0 */ INVALID, INVALID, INVALID, 1642, +}; + +static const uint16_t ud_itab__108[] = { + /* 0 */ INVALID, INVALID, INVALID, 1695, +}; + +static const uint16_t ud_itab__109[] = { + /* 0 */ INVALID, INVALID, INVALID, 45, +}; + +static const uint16_t ud_itab__110[] = { + /* 0 */ INVALID, INVALID, INVALID, 41, +}; + +static const uint16_t ud_itab__111[] = { + /* 0 */ INVALID, INVALID, INVALID, 43, +}; + +static const uint16_t ud_itab__112[] = { + /* 0 */ INVALID, INVALID, INVALID, 37, +}; + +static const uint16_t ud_itab__113[] = { + /* 0 */ INVALID, INVALID, INVALID, 39, +}; + +static const uint16_t ud_itab__114[] = { + /* 0 */ 1723, 1725, INVALID, INVALID, +}; + +static const uint16_t ud_itab__115[] = { + /* 0 */ 1724, 1726, INVALID, INVALID, +}; + +static const uint16_t ud_itab__116[] = { + /* 0 */ INVALID, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, + /* 8 */ GROUP(117), GROUP(118), GROUP(119), GROUP(120), + /* c */ GROUP(121), GROUP(122), GROUP(123), GROUP(124), + /* 10 */ INVALID, INVALID, INVALID, INVALID, + /* 14 */ GROUP(125), GROUP(126), GROUP(127), GROUP(129), + /* 18 */ INVALID, INVALID, INVALID, INVALID, + /* 1c */ INVALID, INVALID, INVALID, INVALID, + /* 20 */ GROUP(130), GROUP(131), GROUP(132), INVALID, + /* 24 */ INVALID, INVALID, INVALID, INVALID, + /* 28 */ INVALID, INVALID, INVALID, INVALID, + /* 2c */ INVALID, INVALID, INVALID, INVALID, + /* 30 */ INVALID, INVALID, INVALID, INVALID, + /* 34 */ INVALID, INVALID, INVALID, INVALID, + /* 38 */ INVALID, INVALID, INVALID, INVALID, + /* 3c */ INVALID, INVALID, INVALID, INVALID, + /* 40 */ GROUP(134), GROUP(135), GROUP(136), INVALID, + /* 44 */ GROUP(137), INVALID, INVALID, INVALID, + /* 48 */ INVALID, INVALID, INVALID, INVALID, + /* 4c */ INVALID, INVALID, INVALID, INVALID, + /* 50 */ INVALID, INVALID, INVALID, INVALID, + /* 54 */ INVALID, INVALID, INVALID, INVALID, + /* 58 */ INVALID, INVALID, INVALID, INVALID, + /* 5c */ INVALID, INVALID, INVALID, INVALID, + /* 60 */ GROUP(139), GROUP(140), GROUP(141), GROUP(142), + /* 64 */ INVALID, INVALID, INVALID, INVALID, + /* 68 */ INVALID, INVALID, INVALID, INVALID, + /* 6c */ INVALID, INVALID, INVALID, INVALID, + /* 70 */ INVALID, INVALID, INVALID, INVALID, + /* 74 */ INVALID, INVALID, INVALID, INVALID, + /* 78 */ INVALID, INVALID, INVALID, INVALID, + /* 7c */ INVALID, INVALID, INVALID, INVALID, + /* 80 */ INVALID, INVALID, INVALID, INVALID, + /* 84 */ INVALID, INVALID, INVALID, INVALID, + /* 88 */ INVALID, INVALID, INVALID, INVALID, + /* 8c */ INVALID, INVALID, INVALID, INVALID, + /* 90 */ INVALID, INVALID, INVALID, INVALID, + /* 94 */ INVALID, INVALID, INVALID, INVALID, + /* 98 */ INVALID, INVALID, INVALID, INVALID, + /* 9c */ INVALID, INVALID, INVALID, INVALID, + /* a0 */ INVALID, INVALID, INVALID, INVALID, + /* a4 */ INVALID, INVALID, INVALID, INVALID, + /* a8 */ INVALID, INVALID, INVALID, INVALID, + /* ac */ INVALID, INVALID, INVALID, INVALID, + /* b0 */ INVALID, INVALID, INVALID, INVALID, + /* b4 */ INVALID, INVALID, INVALID, INVALID, + /* b8 */ INVALID, INVALID, INVALID, INVALID, + /* bc */ INVALID, INVALID, INVALID, INVALID, + /* c0 */ INVALID, INVALID, INVALID, INVALID, + /* c4 */ INVALID, INVALID, INVALID, INVALID, + /* c8 */ INVALID, INVALID, INVALID, INVALID, + /* cc */ INVALID, INVALID, INVALID, INVALID, + /* d0 */ INVALID, INVALID, INVALID, INVALID, + /* d4 */ INVALID, INVALID, INVALID, INVALID, + /* d8 */ INVALID, INVALID, INVALID, INVALID, + /* dc */ INVALID, INVALID, INVALID, GROUP(138), + /* e0 */ INVALID, INVALID, INVALID, INVALID, + /* e4 */ INVALID, INVALID, INVALID, INVALID, + /* e8 */ INVALID, INVALID, INVALID, INVALID, + /* ec */ INVALID, INVALID, INVALID, INVALID, + /* f0 */ INVALID, INVALID, INVALID, INVALID, + /* f4 */ INVALID, INVALID, INVALID, INVALID, + /* f8 */ INVALID, INVALID, INVALID, INVALID, + /* fc */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__117[] = { + /* 0 */ INVALID, INVALID, INVALID, 1644, +}; + +static const uint16_t ud_itab__118[] = { + /* 0 */ INVALID, INVALID, INVALID, 1646, +}; + +static const uint16_t ud_itab__119[] = { + /* 0 */ INVALID, INVALID, INVALID, 1648, +}; + +static const uint16_t ud_itab__120[] = { + /* 0 */ INVALID, INVALID, INVALID, 1650, +}; + +static const uint16_t ud_itab__121[] = { + /* 0 */ INVALID, INVALID, INVALID, 1654, +}; + +static const uint16_t ud_itab__122[] = { + /* 0 */ INVALID, INVALID, INVALID, 1652, +}; + +static const uint16_t ud_itab__123[] = { + /* 0 */ INVALID, INVALID, INVALID, 1677, +}; + +static const uint16_t ud_itab__124[] = { + /* 0 */ 1618, INVALID, INVALID, 1619, +}; + +static const uint16_t ud_itab__125[] = { + /* 0 */ INVALID, INVALID, INVALID, 1045, +}; + +static const uint16_t ud_itab__126[] = { + /* 0 */ INVALID, INVALID, INVALID, 1056, +}; + +static const uint16_t ud_itab__127[] = { + /* 0 */ INVALID, INVALID, INVALID, GROUP(128), +}; + +static const uint16_t ud_itab__128[] = { + /* 0 */ 1047, 1049, 1051, +}; + +static const uint16_t ud_itab__129[] = { + /* 0 */ INVALID, INVALID, INVALID, 201, +}; + +static const uint16_t ud_itab__130[] = { + /* 0 */ INVALID, INVALID, INVALID, 1058, +}; + +static const uint16_t ud_itab__131[] = { + /* 0 */ INVALID, INVALID, INVALID, 1557, +}; + +static const uint16_t ud_itab__132[] = { + /* 0 */ INVALID, INVALID, INVALID, GROUP(133), +}; + +static const uint16_t ud_itab__133[] = { + /* 0 */ 1062, 1063, 1064, +}; + +static const uint16_t ud_itab__134[] = { + /* 0 */ INVALID, INVALID, INVALID, 197, +}; + +static const uint16_t ud_itab__135[] = { + /* 0 */ INVALID, INVALID, INVALID, 195, +}; + +static const uint16_t ud_itab__136[] = { + /* 0 */ INVALID, INVALID, INVALID, 1679, +}; + +static const uint16_t ud_itab__137[] = { + /* 0 */ INVALID, INVALID, INVALID, 1512, +}; + +static const uint16_t ud_itab__138[] = { + /* 0 */ INVALID, INVALID, INVALID, 47, +}; + +static const uint16_t ud_itab__139[] = { + /* 0 */ INVALID, INVALID, INVALID, 1715, +}; + +static const uint16_t ud_itab__140[] = { + /* 0 */ INVALID, INVALID, INVALID, 1713, +}; + +static const uint16_t ud_itab__141[] = { + /* 0 */ INVALID, INVALID, INVALID, 1721, +}; + +static const uint16_t ud_itab__142[] = { + /* 0 */ INVALID, INVALID, INVALID, 1719, +}; + +static const uint16_t ud_itab__143[] = { + /* 0 */ 900, INVALID, INVALID, 898, +}; + +static const uint16_t ud_itab__144[] = { + /* 0 */ 1387, 1391, 1393, 1389, +}; + +static const uint16_t ud_itab__145[] = { + /* 0 */ 1306, INVALID, 1308, INVALID, +}; + +static const uint16_t ud_itab__146[] = { + /* 0 */ 1291, INVALID, 1293, INVALID, +}; + +static const uint16_t ud_itab__147[] = { + /* 0 */ 61, INVALID, INVALID, 59, +}; + +static const uint16_t ud_itab__148[] = { + /* 0 */ 65, INVALID, INVALID, 63, +}; + +static const uint16_t ud_itab__149[] = { + /* 0 */ 976, INVALID, INVALID, 974, +}; + +static const uint16_t ud_itab__150[] = { + /* 0 */ 1499, INVALID, INVALID, 1497, +}; + +static const uint16_t ud_itab__151[] = { + /* 0 */ 27, 29, 31, 25, +}; + +static const uint16_t ud_itab__152[] = { + /* 0 */ 946, 948, 950, 944, +}; + +static const uint16_t ud_itab__153[] = { + /* 0 */ 145, 150, 156, 139, +}; + +static const uint16_t ud_itab__154[] = { + /* 0 */ 134, INVALID, 163, 143, +}; + +static const uint16_t ud_itab__155[] = { + /* 0 */ 1419, 1421, 1423, 1417, +}; + +static const uint16_t ud_itab__156[] = { + /* 0 */ 818, 820, 822, 816, +}; + +static const uint16_t ud_itab__157[] = { + /* 0 */ 189, 191, 193, 187, +}; + +static const uint16_t ud_itab__158[] = { + /* 0 */ 802, 804, 806, 800, +}; + +static const uint16_t ud_itab__159[] = { + /* 0 */ 1209, INVALID, INVALID, 1207, +}; + +static const uint16_t ud_itab__160[] = { + /* 0 */ 1212, INVALID, INVALID, 1210, +}; + +static const uint16_t ud_itab__161[] = { + /* 0 */ 1215, INVALID, INVALID, 1213, +}; + +static const uint16_t ud_itab__162[] = { + /* 0 */ 987, INVALID, INVALID, 985, +}; + +static const uint16_t ud_itab__163[] = { + /* 0 */ 1038, INVALID, INVALID, 1036, +}; + +static const uint16_t ud_itab__164[] = { + /* 0 */ 1041, INVALID, INVALID, 1039, +}; + +static const uint16_t ud_itab__165[] = { + /* 0 */ 1044, INVALID, INVALID, 1042, +}; + +static const uint16_t ud_itab__166[] = { + /* 0 */ 993, INVALID, INVALID, 991, +}; + +static const uint16_t ud_itab__167[] = { + /* 0 */ 1200, INVALID, INVALID, 1198, +}; + +static const uint16_t ud_itab__168[] = { + /* 0 */ 1203, INVALID, INVALID, 1201, +}; + +static const uint16_t ud_itab__169[] = { + /* 0 */ 1206, INVALID, INVALID, 1204, +}; + +static const uint16_t ud_itab__170[] = { + /* 0 */ 990, INVALID, INVALID, 988, +}; + +static const uint16_t ud_itab__171[] = { + /* 0 */ INVALID, INVALID, INVALID, 1547, +}; + +static const uint16_t ud_itab__172[] = { + /* 0 */ INVALID, INVALID, INVALID, 1545, +}; + +static const uint16_t ud_itab__173[] = { + /* 0 */ GROUP(174), INVALID, INVALID, GROUP(175), +}; + +static const uint16_t ud_itab__174[] = { + /* 0 */ 866, 867, 910, +}; + +static const uint16_t ud_itab__175[] = { + /* 0 */ 868, 870, 911, +}; + +static const uint16_t ud_itab__176[] = { + /* 0 */ 920, INVALID, 1522, 1517, +}; + +static const uint16_t ud_itab__177[] = { + /* 0 */ 1134, 1537, 1535, 1539, +}; + +static const uint16_t ud_itab__178[] = { + /* 0 */ INVALID, INVALID, GROUP(179), INVALID, + /* 4 */ GROUP(180), INVALID, GROUP(181), INVALID, +}; + +static const uint16_t ud_itab__179[] = { + /* 0 */ 1159, INVALID, INVALID, 1163, +}; + +static const uint16_t ud_itab__180[] = { + /* 0 */ 1152, INVALID, INVALID, 1150, +}; + +static const uint16_t ud_itab__181[] = { + /* 0 */ 1138, INVALID, INVALID, 1137, +}; + +static const uint16_t ud_itab__182[] = { + /* 0 */ INVALID, INVALID, GROUP(183), INVALID, + /* 4 */ GROUP(184), INVALID, GROUP(185), INVALID, +}; + +static const uint16_t ud_itab__183[] = { + /* 0 */ 1165, INVALID, INVALID, 1169, +}; + +static const uint16_t ud_itab__184[] = { + /* 0 */ 1153, INVALID, INVALID, 1157, +}; + +static const uint16_t ud_itab__185[] = { + /* 0 */ 1142, INVALID, INVALID, 1141, +}; + +static const uint16_t ud_itab__186[] = { + /* 0 */ INVALID, INVALID, GROUP(187), GROUP(188), + /* 4 */ INVALID, INVALID, GROUP(189), GROUP(190), +}; + +static const uint16_t ud_itab__187[] = { + /* 0 */ 1171, INVALID, INVALID, 1175, +}; + +static const uint16_t ud_itab__188[] = { + /* 0 */ INVALID, INVALID, INVALID, 1543, +}; + +static const uint16_t ud_itab__189[] = { + /* 0 */ 1146, INVALID, INVALID, 1145, +}; + +static const uint16_t ud_itab__190[] = { + /* 0 */ INVALID, INVALID, INVALID, 1541, +}; + +static const uint16_t ud_itab__191[] = { + /* 0 */ 1027, INVALID, INVALID, 1028, +}; + +static const uint16_t ud_itab__192[] = { + /* 0 */ 1030, INVALID, INVALID, 1031, +}; + +static const uint16_t ud_itab__193[] = { + /* 0 */ 1033, INVALID, INVALID, 1034, +}; + +static const uint16_t ud_itab__194[] = { + /* 0 */ INVALID, 1464, INVALID, +}; + +static const uint16_t ud_itab__195[] = { + /* 0 */ INVALID, 1465, INVALID, +}; + +static const uint16_t ud_itab__196[] = { + /* 0 */ INVALID, 1551, INVALID, 1549, +}; + +static const uint16_t ud_itab__197[] = { + /* 0 */ INVALID, 1555, INVALID, 1553, +}; + +static const uint16_t ud_itab__198[] = { + /* 0 */ GROUP(199), INVALID, 916, GROUP(200), +}; + +static const uint16_t ud_itab__199[] = { + /* 0 */ 872, 873, 913, +}; + +static const uint16_t ud_itab__200[] = { + /* 0 */ 874, 876, 914, +}; + +static const uint16_t ud_itab__201[] = { + /* 0 */ 921, INVALID, 1524, 1515, +}; + +static const uint16_t ud_itab__202[] = { + /* 0 */ INVALID, GROUP(203), +}; + +static const uint16_t ud_itab__203[] = { + /* 0 */ GROUP(204), GROUP(205), GROUP(206), INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__204[] = { + /* 0 */ 825, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__205[] = { + /* 0 */ 1509, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__206[] = { + /* 0 */ 1510, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__207[] = { + /* 0 */ INVALID, GROUP(208), +}; + +static const uint16_t ud_itab__208[] = { + /* 0 */ GROUP(209), GROUP(210), GROUP(211), GROUP(212), + /* 4 */ GROUP(213), GROUP(214), INVALID, INVALID, +}; + +static const uint16_t ud_itab__209[] = { + /* 0 */ 1511, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__210[] = { + /* 0 */ 1501, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__211[] = { + /* 0 */ 1502, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__212[] = { + /* 0 */ 1503, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__213[] = { + /* 0 */ 1504, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__214[] = { + /* 0 */ 1505, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__215[] = { + /* 0 */ GROUP(216), GROUP(217), +}; + +static const uint16_t ud_itab__216[] = { + /* 0 */ 683, 682, 768, 1400, + /* 4 */ 1507, 1506, INVALID, 79, +}; + +static const uint16_t ud_itab__217[] = { + /* 0 */ INVALID, INVALID, INVALID, INVALID, + /* 4 */ INVALID, GROUP(218), GROUP(219), GROUP(220), +}; + +static const uint16_t ud_itab__218[] = { + /* 0 */ 777, 778, 779, 780, + /* 4 */ 781, 782, 783, 784, +}; + +static const uint16_t ud_itab__219[] = { + /* 0 */ 808, 809, 810, 811, + /* 4 */ 812, 813, 814, 815, +}; + +static const uint16_t ud_itab__220[] = { + /* 0 */ 1366, 1367, 1368, 1369, + /* 4 */ 1370, 1371, 1372, 1373, +}; + +static const uint16_t ud_itab__221[] = { + /* 0 */ INVALID, INVALID, 1710, INVALID, +}; + +static const uint16_t ud_itab__222[] = { + /* 0 */ INVALID, INVALID, INVALID, INVALID, + /* 4 */ 1669, 1676, 1674, 1672, +}; + +static const uint16_t ud_itab__223[] = { + /* 0 */ 112, 117, 120, 110, +}; + +static const uint16_t ud_itab__224[] = { + /* 0 */ 1059, INVALID, INVALID, 1060, +}; + +static const uint16_t ud_itab__225[] = { + /* 0 */ 1055, INVALID, INVALID, 1053, +}; + +static const uint16_t ud_itab__226[] = { + /* 0 */ 1381, INVALID, INVALID, 1379, +}; + +static const uint16_t ud_itab__227[] = { + /* 0 */ GROUP(228), GROUP(235), +}; + +static const uint16_t ud_itab__228[] = { + /* 0 */ INVALID, GROUP(229), INVALID, INVALID, + /* 4 */ INVALID, INVALID, GROUP(230), GROUP(234), +}; + +static const uint16_t ud_itab__229[] = { + /* 0 */ 124, 125, 126, +}; + +static const uint16_t ud_itab__230[] = { + /* 0 */ GROUP(231), INVALID, GROUP(232), GROUP(233), +}; + +static const uint16_t ud_itab__231[] = { + /* 0 */ INVALID, 1459, INVALID, +}; + +static const uint16_t ud_itab__232[] = { + /* 0 */ INVALID, 1458, INVALID, +}; + +static const uint16_t ud_itab__233[] = { + /* 0 */ INVALID, 1457, INVALID, +}; + +static const uint16_t ud_itab__234[] = { + /* 0 */ INVALID, 1460, INVALID, +}; + +static const uint16_t ud_itab__235[] = { + /* 0 */ INVALID, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, 1456, INVALID, +}; + +static const uint16_t ud_itab__236[] = { + /* 0 */ INVALID, 35, INVALID, 33, +}; + +static const uint16_t ud_itab__237[] = { + /* 0 */ 1160, INVALID, INVALID, 1161, +}; + +static const uint16_t ud_itab__238[] = { + /* 0 */ 1166, INVALID, INVALID, 1167, +}; + +static const uint16_t ud_itab__239[] = { + /* 0 */ 1172, INVALID, INVALID, 1173, +}; + +static const uint16_t ud_itab__240[] = { + /* 0 */ 1527, INVALID, INVALID, 1528, +}; + +static const uint16_t ud_itab__241[] = { + /* 0 */ 1093, INVALID, INVALID, 1094, +}; + +static const uint16_t ud_itab__242[] = { + /* 0 */ INVALID, 1521, 1526, 918, +}; + +static const uint16_t ud_itab__243[] = { + /* 0 */ 1086, INVALID, INVALID, 1084, +}; + +static const uint16_t ud_itab__244[] = { + /* 0 */ 1192, INVALID, INVALID, 1193, +}; + +static const uint16_t ud_itab__245[] = { + /* 0 */ 1195, INVALID, INVALID, 1196, +}; + +static const uint16_t ud_itab__246[] = { + /* 0 */ 1083, INVALID, INVALID, 1081, +}; + +static const uint16_t ud_itab__247[] = { + /* 0 */ 1017, INVALID, INVALID, 1015, +}; + +static const uint16_t ud_itab__248[] = { + /* 0 */ 1009, INVALID, INVALID, 1010, +}; + +static const uint16_t ud_itab__249[] = { + /* 0 */ 1012, INVALID, INVALID, 1013, +}; + +static const uint16_t ud_itab__250[] = { + /* 0 */ 1075, INVALID, INVALID, 1076, +}; + +static const uint16_t ud_itab__251[] = { + /* 0 */ 1020, INVALID, INVALID, 1018, +}; + +static const uint16_t ud_itab__252[] = { + /* 0 */ 1023, INVALID, INVALID, 1021, +}; + +static const uint16_t ud_itab__253[] = { + /* 0 */ 1147, INVALID, INVALID, 1148, +}; + +static const uint16_t ud_itab__254[] = { + /* 0 */ 1156, INVALID, INVALID, 1154, +}; + +static const uint16_t ud_itab__255[] = { + /* 0 */ 1026, INVALID, INVALID, 1024, +}; + +static const uint16_t ud_itab__256[] = { + /* 0 */ 1087, INVALID, INVALID, 1088, +}; + +static const uint16_t ud_itab__257[] = { + /* 0 */ 1092, INVALID, INVALID, 1090, +}; + +static const uint16_t ud_itab__258[] = { + /* 0 */ INVALID, 136, 132, 160, +}; + +static const uint16_t ud_itab__259[] = { + /* 0 */ 909, INVALID, INVALID, 902, +}; + +static const uint16_t ud_itab__260[] = { + /* 0 */ 1186, INVALID, INVALID, 1187, +}; + +static const uint16_t ud_itab__261[] = { + /* 0 */ 1189, INVALID, INVALID, 1190, +}; + +static const uint16_t ud_itab__262[] = { + /* 0 */ 1080, INVALID, INVALID, 1078, +}; + +static const uint16_t ud_itab__263[] = { + /* 0 */ 1118, INVALID, INVALID, 1116, +}; + +static const uint16_t ud_itab__264[] = { + /* 0 */ 1003, INVALID, INVALID, 1004, +}; + +static const uint16_t ud_itab__265[] = { + /* 0 */ 1006, INVALID, INVALID, 1007, +}; + +static const uint16_t ud_itab__266[] = { + /* 0 */ 1074, INVALID, INVALID, 1072, +}; + +static const uint16_t ud_itab__267[] = { + /* 0 */ 1266, INVALID, INVALID, 1264, +}; + +static const uint16_t ud_itab__268[] = { + /* 0 */ INVALID, 1559, INVALID, INVALID, +}; + +static const uint16_t ud_itab__269[] = { + /* 0 */ 1136, INVALID, INVALID, 1135, +}; + +static const uint16_t ud_itab__270[] = { + /* 0 */ 1140, INVALID, INVALID, 1139, +}; + +static const uint16_t ud_itab__271[] = { + /* 0 */ 1144, INVALID, INVALID, 1143, +}; + +static const uint16_t ud_itab__272[] = { + /* 0 */ 1533, INVALID, INVALID, 1534, +}; + +static const uint16_t ud_itab__273[] = { + /* 0 */ 1069, INVALID, INVALID, 1070, +}; + +static const uint16_t ud_itab__274[] = { + /* 0 */ 1133, INVALID, INVALID, 1131, +}; + +static const uint16_t ud_itab__275[] = { + /* 0 */ INVALID, GROUP(276), +}; + +static const uint16_t ud_itab__276[] = { + /* 0 */ 799, INVALID, INVALID, 1519, +}; + +static const uint16_t ud_itab__277[] = { + /* 0 */ 1179, INVALID, INVALID, 1177, +}; + +static const uint16_t ud_itab__278[] = { + /* 0 */ 1182, INVALID, INVALID, 1180, +}; + +static const uint16_t ud_itab__279[] = { + /* 0 */ 1183, INVALID, INVALID, 1184, +}; + +static const uint16_t ud_itab__280[] = { + /* 0 */ 1532, INVALID, INVALID, 1530, +}; + +static const uint16_t ud_itab__281[] = { + /* 0 */ 996, INVALID, INVALID, 994, +}; + +static const uint16_t ud_itab__282[] = { + /* 0 */ 997, INVALID, INVALID, 998, +}; + +static const uint16_t ud_itab__283[] = { + /* 0 */ 1000, INVALID, INVALID, 1001, +}; + +static const uint16_t ud_itab__284[] = { + /* 0 */ 1242, INVALID, +}; + +static const uint16_t ud_itab__285[] = { + /* 0 */ 1097, INVALID, +}; + +static const uint16_t ud_itab__286[] = { + /* 0 */ 1243, INVALID, +}; + +static const uint16_t ud_itab__287[] = { + /* 0 */ 1098, INVALID, +}; + +static const uint16_t ud_itab__288[] = { + /* 0 */ 173, INVALID, +}; + +static const uint16_t ud_itab__289[] = { + /* 0 */ 174, INVALID, +}; + +static const uint16_t ud_itab__290[] = { + /* 0 */ 1, INVALID, +}; + +static const uint16_t ud_itab__291[] = { + /* 0 */ 4, INVALID, +}; + +static const uint16_t ud_itab__292[] = { + /* 0 */ GROUP(293), GROUP(294), INVALID, +}; + +static const uint16_t ud_itab__293[] = { + /* 0 */ 1257, INVALID, +}; + +static const uint16_t ud_itab__294[] = { + /* 0 */ 1258, INVALID, +}; + +static const uint16_t ud_itab__295[] = { + /* 0 */ GROUP(296), GROUP(297), INVALID, +}; + +static const uint16_t ud_itab__296[] = { + /* 0 */ 1110, INVALID, +}; + +static const uint16_t ud_itab__297[] = { + /* 0 */ 1111, INVALID, +}; + +static const uint16_t ud_itab__298[] = { + /* 0 */ 1658, INVALID, +}; + +static const uint16_t ud_itab__299[] = { + /* 0 */ 67, 68, +}; + +static const uint16_t ud_itab__300[] = { + /* 0 */ 710, 711, INVALID, +}; + +static const uint16_t ud_itab__301[] = { + /* 0 */ 983, 984, INVALID, +}; + +static const uint16_t ud_itab__302[] = { + /* 0 */ 21, 970, 11, 1342, + /* 4 */ 55, 1413, 1493, 106, +}; + +static const uint16_t ud_itab__303[] = { + /* 0 */ 23, 971, 13, 1343, + /* 4 */ 57, 1414, 1494, 108, +}; + +static const uint16_t ud_itab__304[] = { + /* 0 */ GROUP(305), GROUP(306), GROUP(307), GROUP(308), + /* 4 */ GROUP(309), GROUP(310), GROUP(311), GROUP(312), +}; + +static const uint16_t ud_itab__305[] = { + /* 0 */ 22, INVALID, +}; + +static const uint16_t ud_itab__306[] = { + /* 0 */ 972, INVALID, +}; + +static const uint16_t ud_itab__307[] = { + /* 0 */ 12, INVALID, +}; + +static const uint16_t ud_itab__308[] = { + /* 0 */ 1344, INVALID, +}; + +static const uint16_t ud_itab__309[] = { + /* 0 */ 56, INVALID, +}; + +static const uint16_t ud_itab__310[] = { + /* 0 */ 1415, INVALID, +}; + +static const uint16_t ud_itab__311[] = { + /* 0 */ 1495, INVALID, +}; + +static const uint16_t ud_itab__312[] = { + /* 0 */ 107, INVALID, +}; + +static const uint16_t ud_itab__313[] = { + /* 0 */ 24, 973, 14, 1345, + /* 4 */ 58, 1416, 1496, 109, +}; + +static const uint16_t ud_itab__314[] = { + /* 0 */ 1109, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__315[] = { + /* 0 */ 74, 75, 76, +}; + +static const uint16_t ud_itab__316[] = { + /* 0 */ 170, 171, 172, +}; + +static const uint16_t ud_itab__317[] = { + /* 0 */ 73, INVALID, +}; + +static const uint16_t ud_itab__318[] = { + /* 0 */ GROUP(319), GROUP(320), GROUP(321), +}; + +static const uint16_t ud_itab__319[] = { + /* 0 */ 1259, 1260, +}; + +static const uint16_t ud_itab__320[] = { + /* 0 */ 1261, 1262, +}; + +static const uint16_t ud_itab__321[] = { + /* 0 */ INVALID, 1263, +}; + +static const uint16_t ud_itab__322[] = { + /* 0 */ GROUP(323), GROUP(324), GROUP(325), +}; + +static const uint16_t ud_itab__323[] = { + /* 0 */ 1112, INVALID, +}; + +static const uint16_t ud_itab__324[] = { + /* 0 */ 1113, 1114, +}; + +static const uint16_t ud_itab__325[] = { + /* 0 */ INVALID, 1115, +}; + +static const uint16_t ud_itab__326[] = { + /* 0 */ 923, 924, 927, +}; + +static const uint16_t ud_itab__327[] = { + /* 0 */ 115, 116, 119, +}; + +static const uint16_t ud_itab__328[] = { + /* 0 */ 1403, 1404, 1405, +}; + +static const uint16_t ud_itab__329[] = { + /* 0 */ 791, 792, 793, +}; + +static const uint16_t ud_itab__330[] = { + /* 0 */ 1347, 1348, 1349, +}; + +static const uint16_t ud_itab__331[] = { + /* 0 */ 1279, 1286, 1267, 1275, + /* 4 */ 1327, 1334, 1318, 1313, +}; + +static const uint16_t ud_itab__332[] = { + /* 0 */ 1284, 1287, 1268, 1274, + /* 4 */ 1323, 1330, 1319, 1315, +}; + +static const uint16_t ud_itab__333[] = { + /* 0 */ GROUP(334), GROUP(335), INVALID, INVALID, + /* 4 */ INVALID, GROUP(341), GROUP(357), GROUP(369), + /* 8 */ INVALID, GROUP(394), INVALID, INVALID, + /* c */ INVALID, GROUP(399), INVALID, INVALID, +}; + +static const uint16_t ud_itab__334[] = { + /* 0 */ 771, INVALID, +}; + +static const uint16_t ud_itab__335[] = { + /* 0 */ INVALID, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, + /* 8 */ INVALID, INVALID, INVALID, INVALID, + /* c */ INVALID, INVALID, INVALID, INVALID, + /* 10 */ 937, 939, GROUP(336), 895, + /* 14 */ 1450, 1448, GROUP(337), 885, + /* 18 */ INVALID, INVALID, INVALID, INVALID, + /* 1c */ INVALID, INVALID, INVALID, INVALID, + /* 20 */ INVALID, INVALID, INVALID, INVALID, + /* 24 */ INVALID, INVALID, INVALID, INVALID, + /* 28 */ 863, 865, INVALID, 908, + /* 2c */ INVALID, INVALID, 1443, 130, + /* 30 */ INVALID, INVALID, INVALID, INVALID, + /* 34 */ INVALID, INVALID, INVALID, INVALID, + /* 38 */ INVALID, INVALID, INVALID, INVALID, + /* 3c */ INVALID, INVALID, INVALID, INVALID, + /* 40 */ INVALID, INVALID, INVALID, INVALID, + /* 44 */ INVALID, INVALID, INVALID, INVALID, + /* 48 */ INVALID, INVALID, INVALID, INVALID, + /* 4c */ INVALID, INVALID, INVALID, INVALID, + /* 50 */ 901, 1388, 1307, 1292, + /* 54 */ 62, 66, 977, 1500, + /* 58 */ 28, 947, 146, 135, + /* 5c */ 1420, 819, 190, 803, + /* 60 */ INVALID, INVALID, INVALID, INVALID, + /* 64 */ INVALID, INVALID, INVALID, INVALID, + /* 68 */ INVALID, INVALID, INVALID, INVALID, + /* 6c */ INVALID, INVALID, INVALID, INVALID, + /* 70 */ INVALID, INVALID, INVALID, INVALID, + /* 74 */ INVALID, INVALID, INVALID, GROUP(340), + /* 78 */ INVALID, INVALID, INVALID, INVALID, + /* 7c */ INVALID, INVALID, INVALID, INVALID, + /* 80 */ INVALID, INVALID, INVALID, INVALID, + /* 84 */ INVALID, INVALID, INVALID, INVALID, + /* 88 */ INVALID, INVALID, INVALID, INVALID, + /* 8c */ INVALID, INVALID, INVALID, INVALID, + /* 90 */ INVALID, INVALID, INVALID, INVALID, + /* 94 */ INVALID, INVALID, INVALID, INVALID, + /* 98 */ INVALID, INVALID, INVALID, INVALID, + /* 9c */ INVALID, INVALID, INVALID, INVALID, + /* a0 */ INVALID, INVALID, INVALID, INVALID, + /* a4 */ INVALID, INVALID, INVALID, INVALID, + /* a8 */ INVALID, INVALID, INVALID, INVALID, + /* ac */ INVALID, INVALID, GROUP(338), INVALID, + /* b0 */ INVALID, INVALID, INVALID, INVALID, + /* b4 */ INVALID, INVALID, INVALID, INVALID, + /* b8 */ INVALID, INVALID, INVALID, INVALID, + /* bc */ INVALID, INVALID, INVALID, INVALID, + /* c0 */ INVALID, INVALID, 113, INVALID, + /* c4 */ INVALID, INVALID, 1382, INVALID, + /* c8 */ INVALID, INVALID, INVALID, INVALID, + /* cc */ INVALID, INVALID, INVALID, INVALID, + /* d0 */ INVALID, INVALID, INVALID, INVALID, + /* d4 */ INVALID, INVALID, INVALID, INVALID, + /* d8 */ INVALID, INVALID, INVALID, INVALID, + /* dc */ INVALID, INVALID, INVALID, INVALID, + /* e0 */ INVALID, INVALID, INVALID, INVALID, + /* e4 */ INVALID, INVALID, INVALID, INVALID, + /* e8 */ INVALID, INVALID, INVALID, INVALID, + /* ec */ INVALID, INVALID, INVALID, INVALID, + /* f0 */ INVALID, INVALID, INVALID, INVALID, + /* f4 */ INVALID, INVALID, INVALID, INVALID, + /* f8 */ INVALID, INVALID, INVALID, INVALID, + /* fc */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__336[] = { + /* 0 */ 893, 897, +}; + +static const uint16_t ud_itab__337[] = { + /* 0 */ 883, 887, +}; + +static const uint16_t ud_itab__338[] = { + /* 0 */ GROUP(339), INVALID, +}; + +static const uint16_t ud_itab__339[] = { + /* 0 */ INVALID, INVALID, INVALID, 1401, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__340[] = { + /* 0 */ 1742, 1743, +}; + +static const uint16_t ud_itab__341[] = { + /* 0 */ INVALID, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, + /* 8 */ INVALID, INVALID, INVALID, INVALID, + /* c */ INVALID, INVALID, INVALID, INVALID, + /* 10 */ 933, 935, GROUP(342), 891, + /* 14 */ 1452, 1446, GROUP(343), 881, + /* 18 */ INVALID, INVALID, INVALID, INVALID, + /* 1c */ INVALID, INVALID, INVALID, INVALID, + /* 20 */ INVALID, INVALID, INVALID, INVALID, + /* 24 */ INVALID, INVALID, INVALID, INVALID, + /* 28 */ 859, 861, INVALID, 906, + /* 2c */ INVALID, INVALID, 1441, 128, + /* 30 */ INVALID, INVALID, INVALID, INVALID, + /* 34 */ INVALID, INVALID, INVALID, INVALID, + /* 38 */ INVALID, INVALID, INVALID, INVALID, + /* 3c */ INVALID, INVALID, INVALID, INVALID, + /* 40 */ INVALID, INVALID, INVALID, INVALID, + /* 44 */ INVALID, INVALID, INVALID, INVALID, + /* 48 */ INVALID, INVALID, INVALID, INVALID, + /* 4c */ INVALID, INVALID, INVALID, INVALID, + /* 50 */ 899, 1390, INVALID, INVALID, + /* 54 */ 60, 64, 975, 1498, + /* 58 */ 26, 945, 140, 144, + /* 5c */ 1418, 817, 188, 801, + /* 60 */ 1208, 1211, 1214, 986, + /* 64 */ 1037, 1040, 1043, 992, + /* 68 */ 1199, 1202, 1205, 989, + /* 6c */ 1548, 1546, GROUP(344), 1518, + /* 70 */ 1540, GROUP(345), GROUP(347), GROUP(349), + /* 74 */ 1029, 1032, 1035, INVALID, + /* 78 */ INVALID, INVALID, INVALID, INVALID, + /* 7c */ 1550, 1554, GROUP(351), 1516, + /* 80 */ INVALID, INVALID, INVALID, INVALID, + /* 84 */ INVALID, INVALID, INVALID, INVALID, + /* 88 */ INVALID, INVALID, INVALID, INVALID, + /* 8c */ INVALID, INVALID, INVALID, INVALID, + /* 90 */ INVALID, INVALID, INVALID, INVALID, + /* 94 */ INVALID, INVALID, INVALID, INVALID, + /* 98 */ INVALID, INVALID, INVALID, INVALID, + /* 9c */ INVALID, INVALID, INVALID, INVALID, + /* a0 */ INVALID, INVALID, INVALID, INVALID, + /* a4 */ INVALID, INVALID, INVALID, INVALID, + /* a8 */ INVALID, INVALID, INVALID, INVALID, + /* ac */ INVALID, INVALID, INVALID, INVALID, + /* b0 */ INVALID, INVALID, INVALID, INVALID, + /* b4 */ INVALID, INVALID, INVALID, INVALID, + /* b8 */ INVALID, INVALID, INVALID, INVALID, + /* bc */ INVALID, INVALID, INVALID, INVALID, + /* c0 */ INVALID, INVALID, 111, INVALID, + /* c4 */ 1061, 1054, 1380, INVALID, + /* c8 */ INVALID, INVALID, INVALID, INVALID, + /* cc */ INVALID, INVALID, INVALID, INVALID, + /* d0 */ 34, 1162, 1168, 1174, + /* d4 */ 1529, 1095, 919, GROUP(352), + /* d8 */ 1194, 1197, 1082, 1016, + /* dc */ 1011, 1014, 1077, 1019, + /* e0 */ 1022, 1149, 1155, 1025, + /* e4 */ 1089, 1091, 161, 903, + /* e8 */ 1188, 1191, 1079, 1117, + /* ec */ 1005, 1008, 1073, 1265, + /* f0 */ INVALID, GROUP(353), GROUP(354), GROUP(355), + /* f4 */ INVALID, 1071, 1132, GROUP(356), + /* f8 */ 1178, 1181, 1185, 1531, + /* fc */ 995, 999, 1002, INVALID, +}; + +static const uint16_t ud_itab__342[] = { + /* 0 */ 889, INVALID, +}; + +static const uint16_t ud_itab__343[] = { + /* 0 */ 879, INVALID, +}; + +static const uint16_t ud_itab__344[] = { + /* 0 */ 869, 871, 912, +}; + +static const uint16_t ud_itab__345[] = { + /* 0 */ INVALID, INVALID, 1164, INVALID, + /* 4 */ 1151, INVALID, GROUP(346), INVALID, +}; + +static const uint16_t ud_itab__346[] = { + /* 0 */ 1756, INVALID, +}; + +static const uint16_t ud_itab__347[] = { + /* 0 */ INVALID, INVALID, 1170, INVALID, + /* 4 */ 1158, INVALID, GROUP(348), INVALID, +}; + +static const uint16_t ud_itab__348[] = { + /* 0 */ 1758, INVALID, +}; + +static const uint16_t ud_itab__349[] = { + /* 0 */ INVALID, INVALID, 1176, 1544, + /* 4 */ INVALID, INVALID, GROUP(350), 1542, +}; + +static const uint16_t ud_itab__350[] = { + /* 0 */ 1760, INVALID, +}; + +static const uint16_t ud_itab__351[] = { + /* 0 */ 875, 877, 915, +}; + +static const uint16_t ud_itab__352[] = { + /* 0 */ 1085, INVALID, +}; + +static const uint16_t ud_itab__353[] = { + /* 0 */ 1755, INVALID, +}; + +static const uint16_t ud_itab__354[] = { + /* 0 */ 1757, INVALID, +}; + +static const uint16_t ud_itab__355[] = { + /* 0 */ 1759, INVALID, +}; + +static const uint16_t ud_itab__356[] = { + /* 0 */ INVALID, 1520, +}; + +static const uint16_t ud_itab__357[] = { + /* 0 */ 1584, 1587, 1590, 1593, + /* 4 */ 1596, 1599, 1602, 1605, + /* 8 */ 1608, 1614, 1611, 1617, + /* c */ GROUP(358), GROUP(359), GROUP(360), GROUP(361), + /* 10 */ INVALID, INVALID, INVALID, INVALID, + /* 14 */ INVALID, INVALID, INVALID, 1712, + /* 18 */ GROUP(362), GROUP(363), INVALID, INVALID, + /* 1c */ 1575, 1578, 1581, INVALID, + /* 20 */ 1686, 1688, 1690, 1692, + /* 24 */ 1694, INVALID, INVALID, INVALID, + /* 28 */ 1623, 1709, 1682, 1684, + /* 2c */ GROUP(365), GROUP(366), GROUP(367), GROUP(368), + /* 30 */ 1697, 1699, 1701, 1703, + /* 34 */ 1705, 1707, INVALID, 1718, + /* 38 */ 1625, 1627, 1629, 1631, + /* 3c */ 1633, 1635, 1639, 1637, + /* 40 */ 1641, 1643, INVALID, INVALID, + /* 44 */ INVALID, INVALID, INVALID, INVALID, + /* 48 */ INVALID, INVALID, INVALID, INVALID, + /* 4c */ INVALID, INVALID, INVALID, INVALID, + /* 50 */ INVALID, INVALID, INVALID, INVALID, + /* 54 */ INVALID, INVALID, INVALID, INVALID, + /* 58 */ INVALID, INVALID, INVALID, INVALID, + /* 5c */ INVALID, INVALID, INVALID, INVALID, + /* 60 */ INVALID, INVALID, INVALID, INVALID, + /* 64 */ INVALID, INVALID, INVALID, INVALID, + /* 68 */ INVALID, INVALID, INVALID, INVALID, + /* 6c */ INVALID, INVALID, INVALID, INVALID, + /* 70 */ INVALID, INVALID, INVALID, INVALID, + /* 74 */ INVALID, INVALID, INVALID, INVALID, + /* 78 */ INVALID, INVALID, INVALID, INVALID, + /* 7c */ INVALID, INVALID, INVALID, INVALID, + /* 80 */ INVALID, INVALID, INVALID, INVALID, + /* 84 */ INVALID, INVALID, INVALID, INVALID, + /* 88 */ INVALID, INVALID, INVALID, INVALID, + /* 8c */ INVALID, INVALID, INVALID, INVALID, + /* 90 */ INVALID, INVALID, INVALID, INVALID, + /* 94 */ INVALID, INVALID, INVALID, INVALID, + /* 98 */ INVALID, INVALID, INVALID, INVALID, + /* 9c */ INVALID, INVALID, INVALID, INVALID, + /* a0 */ INVALID, INVALID, INVALID, INVALID, + /* a4 */ INVALID, INVALID, INVALID, INVALID, + /* a8 */ INVALID, INVALID, INVALID, INVALID, + /* ac */ INVALID, INVALID, INVALID, INVALID, + /* b0 */ INVALID, INVALID, INVALID, INVALID, + /* b4 */ INVALID, INVALID, INVALID, INVALID, + /* b8 */ INVALID, INVALID, INVALID, INVALID, + /* bc */ INVALID, INVALID, INVALID, INVALID, + /* c0 */ INVALID, INVALID, INVALID, INVALID, + /* c4 */ INVALID, INVALID, INVALID, INVALID, + /* c8 */ INVALID, INVALID, INVALID, INVALID, + /* cc */ INVALID, INVALID, INVALID, INVALID, + /* d0 */ INVALID, INVALID, INVALID, INVALID, + /* d4 */ INVALID, INVALID, INVALID, INVALID, + /* d8 */ INVALID, INVALID, INVALID, 46, + /* dc */ 42, 44, 38, 40, + /* e0 */ INVALID, INVALID, INVALID, INVALID, + /* e4 */ INVALID, INVALID, INVALID, INVALID, + /* e8 */ INVALID, INVALID, INVALID, INVALID, + /* ec */ INVALID, INVALID, INVALID, INVALID, + /* f0 */ INVALID, INVALID, INVALID, INVALID, + /* f4 */ INVALID, INVALID, INVALID, INVALID, + /* f8 */ INVALID, INVALID, INVALID, INVALID, + /* fc */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__358[] = { + /* 0 */ 1737, INVALID, +}; + +static const uint16_t ud_itab__359[] = { + /* 0 */ 1735, INVALID, +}; + +static const uint16_t ud_itab__360[] = { + /* 0 */ 1740, INVALID, +}; + +static const uint16_t ud_itab__361[] = { + /* 0 */ 1741, INVALID, +}; + +static const uint16_t ud_itab__362[] = { + /* 0 */ 1727, INVALID, +}; + +static const uint16_t ud_itab__363[] = { + /* 0 */ GROUP(364), INVALID, +}; + +static const uint16_t ud_itab__364[] = { + /* 0 */ INVALID, 1728, +}; + +static const uint16_t ud_itab__365[] = { + /* 0 */ 1731, INVALID, +}; + +static const uint16_t ud_itab__366[] = { + /* 0 */ 1733, INVALID, +}; + +static const uint16_t ud_itab__367[] = { + /* 0 */ 1732, INVALID, +}; + +static const uint16_t ud_itab__368[] = { + /* 0 */ 1734, INVALID, +}; + +static const uint16_t ud_itab__369[] = { + /* 0 */ INVALID, INVALID, INVALID, INVALID, + /* 4 */ GROUP(370), GROUP(371), GROUP(372), INVALID, + /* 8 */ 1645, 1647, 1649, 1651, + /* c */ 1655, 1653, 1678, 1620, + /* 10 */ INVALID, INVALID, INVALID, INVALID, + /* 14 */ GROUP(374), 1057, GROUP(375), 202, + /* 18 */ GROUP(379), GROUP(381), INVALID, INVALID, + /* 1c */ INVALID, INVALID, INVALID, INVALID, + /* 20 */ GROUP(383), 1558, GROUP(385), INVALID, + /* 24 */ INVALID, INVALID, INVALID, INVALID, + /* 28 */ INVALID, INVALID, INVALID, INVALID, + /* 2c */ INVALID, INVALID, INVALID, INVALID, + /* 30 */ INVALID, INVALID, INVALID, INVALID, + /* 34 */ INVALID, INVALID, INVALID, INVALID, + /* 38 */ INVALID, INVALID, INVALID, INVALID, + /* 3c */ INVALID, INVALID, INVALID, INVALID, + /* 40 */ 198, 196, 1680, INVALID, + /* 44 */ 1513, INVALID, INVALID, INVALID, + /* 48 */ INVALID, INVALID, GROUP(391), GROUP(392), + /* 4c */ GROUP(393), INVALID, INVALID, INVALID, + /* 50 */ INVALID, INVALID, INVALID, INVALID, + /* 54 */ INVALID, INVALID, INVALID, INVALID, + /* 58 */ INVALID, INVALID, INVALID, INVALID, + /* 5c */ INVALID, INVALID, INVALID, INVALID, + /* 60 */ 1716, 1714, 1722, 1720, + /* 64 */ INVALID, INVALID, INVALID, INVALID, + /* 68 */ INVALID, INVALID, INVALID, INVALID, + /* 6c */ INVALID, INVALID, INVALID, INVALID, + /* 70 */ INVALID, INVALID, INVALID, INVALID, + /* 74 */ INVALID, INVALID, INVALID, INVALID, + /* 78 */ INVALID, INVALID, INVALID, INVALID, + /* 7c */ INVALID, INVALID, INVALID, INVALID, + /* 80 */ INVALID, INVALID, INVALID, INVALID, + /* 84 */ INVALID, INVALID, INVALID, INVALID, + /* 88 */ INVALID, INVALID, INVALID, INVALID, + /* 8c */ INVALID, INVALID, INVALID, INVALID, + /* 90 */ INVALID, INVALID, INVALID, INVALID, + /* 94 */ INVALID, INVALID, INVALID, INVALID, + /* 98 */ INVALID, INVALID, INVALID, INVALID, + /* 9c */ INVALID, INVALID, INVALID, INVALID, + /* a0 */ INVALID, INVALID, INVALID, INVALID, + /* a4 */ INVALID, INVALID, INVALID, INVALID, + /* a8 */ INVALID, INVALID, INVALID, INVALID, + /* ac */ INVALID, INVALID, INVALID, INVALID, + /* b0 */ INVALID, INVALID, INVALID, INVALID, + /* b4 */ INVALID, INVALID, INVALID, INVALID, + /* b8 */ INVALID, INVALID, INVALID, INVALID, + /* bc */ INVALID, INVALID, INVALID, INVALID, + /* c0 */ INVALID, INVALID, INVALID, INVALID, + /* c4 */ INVALID, INVALID, INVALID, INVALID, + /* c8 */ INVALID, INVALID, INVALID, INVALID, + /* cc */ INVALID, INVALID, INVALID, INVALID, + /* d0 */ INVALID, INVALID, INVALID, INVALID, + /* d4 */ INVALID, INVALID, INVALID, INVALID, + /* d8 */ INVALID, INVALID, INVALID, INVALID, + /* dc */ INVALID, INVALID, INVALID, 48, + /* e0 */ INVALID, INVALID, INVALID, INVALID, + /* e4 */ INVALID, INVALID, INVALID, INVALID, + /* e8 */ INVALID, INVALID, INVALID, INVALID, + /* ec */ INVALID, INVALID, INVALID, INVALID, + /* f0 */ INVALID, INVALID, INVALID, INVALID, + /* f4 */ INVALID, INVALID, INVALID, INVALID, + /* f8 */ INVALID, INVALID, INVALID, INVALID, + /* fc */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__370[] = { + /* 0 */ 1738, INVALID, +}; + +static const uint16_t ud_itab__371[] = { + /* 0 */ 1736, INVALID, +}; + +static const uint16_t ud_itab__372[] = { + /* 0 */ GROUP(373), INVALID, +}; + +static const uint16_t ud_itab__373[] = { + /* 0 */ INVALID, 1739, +}; + +static const uint16_t ud_itab__374[] = { + /* 0 */ 1046, INVALID, +}; + +static const uint16_t ud_itab__375[] = { + /* 0 */ GROUP(376), GROUP(377), GROUP(378), +}; + +static const uint16_t ud_itab__376[] = { + /* 0 */ 1048, INVALID, +}; + +static const uint16_t ud_itab__377[] = { + /* 0 */ 1050, INVALID, +}; + +static const uint16_t ud_itab__378[] = { + /* 0 */ INVALID, 1052, +}; + +static const uint16_t ud_itab__379[] = { + /* 0 */ GROUP(380), INVALID, +}; + +static const uint16_t ud_itab__380[] = { + /* 0 */ INVALID, 1730, +}; + +static const uint16_t ud_itab__381[] = { + /* 0 */ GROUP(382), INVALID, +}; + +static const uint16_t ud_itab__382[] = { + /* 0 */ INVALID, 1729, +}; + +static const uint16_t ud_itab__383[] = { + /* 0 */ GROUP(384), INVALID, +}; + +static const uint16_t ud_itab__384[] = { + /* 0 */ 1065, INVALID, +}; + +static const uint16_t ud_itab__385[] = { + /* 0 */ GROUP(386), GROUP(388), +}; + +static const uint16_t ud_itab__386[] = { + /* 0 */ GROUP(387), INVALID, +}; + +static const uint16_t ud_itab__387[] = { + /* 0 */ 1066, INVALID, +}; + +static const uint16_t ud_itab__388[] = { + /* 0 */ GROUP(389), GROUP(390), +}; + +static const uint16_t ud_itab__389[] = { + /* 0 */ 1067, INVALID, +}; + +static const uint16_t ud_itab__390[] = { + /* 0 */ 1068, INVALID, +}; + +static const uint16_t ud_itab__391[] = { + /* 0 */ 1745, INVALID, +}; + +static const uint16_t ud_itab__392[] = { + /* 0 */ 1744, INVALID, +}; + +static const uint16_t ud_itab__393[] = { + /* 0 */ 1754, INVALID, +}; + +static const uint16_t ud_itab__394[] = { + /* 0 */ INVALID, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, + /* 8 */ INVALID, INVALID, INVALID, INVALID, + /* c */ INVALID, INVALID, INVALID, INVALID, + /* 10 */ GROUP(395), GROUP(396), GROUP(397), INVALID, + /* 14 */ INVALID, INVALID, GROUP(398), INVALID, + /* 18 */ INVALID, INVALID, INVALID, INVALID, + /* 1c */ INVALID, INVALID, INVALID, INVALID, + /* 20 */ INVALID, INVALID, INVALID, INVALID, + /* 24 */ INVALID, INVALID, INVALID, INVALID, + /* 28 */ INVALID, INVALID, 155, INVALID, + /* 2c */ 169, 159, INVALID, INVALID, + /* 30 */ INVALID, INVALID, INVALID, INVALID, + /* 34 */ INVALID, INVALID, INVALID, INVALID, + /* 38 */ INVALID, INVALID, INVALID, INVALID, + /* 3c */ INVALID, INVALID, INVALID, INVALID, + /* 40 */ INVALID, INVALID, INVALID, INVALID, + /* 44 */ INVALID, INVALID, INVALID, INVALID, + /* 48 */ INVALID, INVALID, INVALID, INVALID, + /* 4c */ INVALID, INVALID, INVALID, INVALID, + /* 50 */ INVALID, 1394, 1309, 1294, + /* 54 */ INVALID, INVALID, INVALID, INVALID, + /* 58 */ 32, 951, 157, 164, + /* 5c */ 1424, 823, 194, 807, + /* 60 */ INVALID, INVALID, INVALID, INVALID, + /* 64 */ INVALID, INVALID, INVALID, INVALID, + /* 68 */ INVALID, INVALID, INVALID, INVALID, + /* 6c */ INVALID, INVALID, INVALID, 1523, + /* 70 */ 1536, INVALID, INVALID, INVALID, + /* 74 */ INVALID, INVALID, INVALID, INVALID, + /* 78 */ INVALID, INVALID, INVALID, INVALID, + /* 7c */ INVALID, INVALID, 917, 1525, + /* 80 */ INVALID, INVALID, INVALID, INVALID, + /* 84 */ INVALID, INVALID, INVALID, INVALID, + /* 88 */ INVALID, INVALID, INVALID, INVALID, + /* 8c */ INVALID, INVALID, INVALID, INVALID, + /* 90 */ INVALID, INVALID, INVALID, INVALID, + /* 94 */ INVALID, INVALID, INVALID, INVALID, + /* 98 */ INVALID, INVALID, INVALID, INVALID, + /* 9c */ INVALID, INVALID, INVALID, INVALID, + /* a0 */ INVALID, INVALID, INVALID, INVALID, + /* a4 */ INVALID, INVALID, INVALID, INVALID, + /* a8 */ INVALID, INVALID, INVALID, INVALID, + /* ac */ INVALID, INVALID, INVALID, INVALID, + /* b0 */ INVALID, INVALID, INVALID, INVALID, + /* b4 */ INVALID, INVALID, INVALID, INVALID, + /* b8 */ INVALID, INVALID, INVALID, INVALID, + /* bc */ INVALID, INVALID, INVALID, INVALID, + /* c0 */ INVALID, INVALID, 121, INVALID, + /* c4 */ INVALID, INVALID, INVALID, INVALID, + /* c8 */ INVALID, INVALID, INVALID, INVALID, + /* cc */ INVALID, INVALID, INVALID, INVALID, + /* d0 */ INVALID, INVALID, INVALID, INVALID, + /* d4 */ INVALID, INVALID, INVALID, INVALID, + /* d8 */ INVALID, INVALID, INVALID, INVALID, + /* dc */ INVALID, INVALID, INVALID, INVALID, + /* e0 */ INVALID, INVALID, INVALID, INVALID, + /* e4 */ INVALID, INVALID, 133, INVALID, + /* e8 */ INVALID, INVALID, INVALID, INVALID, + /* ec */ INVALID, INVALID, INVALID, INVALID, + /* f0 */ INVALID, INVALID, INVALID, INVALID, + /* f4 */ INVALID, INVALID, INVALID, INVALID, + /* f8 */ INVALID, INVALID, INVALID, INVALID, + /* fc */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__395[] = { + /* 0 */ 1751, 1750, +}; + +static const uint16_t ud_itab__396[] = { + /* 0 */ 1753, 1752, +}; + +static const uint16_t ud_itab__397[] = { + /* 0 */ 1572, 1570, +}; + +static const uint16_t ud_itab__398[] = { + /* 0 */ 1568, 1566, +}; + +static const uint16_t ud_itab__399[] = { + /* 0 */ INVALID, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, + /* 8 */ INVALID, INVALID, INVALID, INVALID, + /* c */ INVALID, INVALID, INVALID, INVALID, + /* 10 */ GROUP(402), GROUP(400), GROUP(401), INVALID, + /* 14 */ INVALID, INVALID, INVALID, INVALID, + /* 18 */ INVALID, INVALID, INVALID, INVALID, + /* 1c */ INVALID, INVALID, INVALID, INVALID, + /* 20 */ INVALID, INVALID, INVALID, INVALID, + /* 24 */ INVALID, INVALID, INVALID, INVALID, + /* 28 */ INVALID, INVALID, 153, INVALID, + /* 2c */ 167, 149, INVALID, INVALID, + /* 30 */ INVALID, INVALID, INVALID, INVALID, + /* 34 */ INVALID, INVALID, INVALID, INVALID, + /* 38 */ INVALID, INVALID, INVALID, INVALID, + /* 3c */ INVALID, INVALID, INVALID, INVALID, + /* 40 */ INVALID, INVALID, INVALID, INVALID, + /* 44 */ INVALID, INVALID, INVALID, INVALID, + /* 48 */ INVALID, INVALID, INVALID, INVALID, + /* 4c */ INVALID, INVALID, INVALID, INVALID, + /* 50 */ INVALID, 1392, INVALID, INVALID, + /* 54 */ INVALID, INVALID, INVALID, INVALID, + /* 58 */ 30, 949, 151, INVALID, + /* 5c */ 1422, 821, 192, 805, + /* 60 */ INVALID, INVALID, INVALID, INVALID, + /* 64 */ INVALID, INVALID, INVALID, INVALID, + /* 68 */ INVALID, INVALID, INVALID, INVALID, + /* 6c */ INVALID, INVALID, INVALID, INVALID, + /* 70 */ 1538, INVALID, INVALID, INVALID, + /* 74 */ INVALID, INVALID, INVALID, INVALID, + /* 78 */ INVALID, INVALID, INVALID, INVALID, + /* 7c */ 1552, 1556, INVALID, INVALID, + /* 80 */ INVALID, INVALID, INVALID, INVALID, + /* 84 */ INVALID, INVALID, INVALID, INVALID, + /* 88 */ INVALID, INVALID, INVALID, INVALID, + /* 8c */ INVALID, INVALID, INVALID, INVALID, + /* 90 */ INVALID, INVALID, INVALID, INVALID, + /* 94 */ INVALID, INVALID, INVALID, INVALID, + /* 98 */ INVALID, INVALID, INVALID, INVALID, + /* 9c */ INVALID, INVALID, INVALID, INVALID, + /* a0 */ INVALID, INVALID, INVALID, INVALID, + /* a4 */ INVALID, INVALID, INVALID, INVALID, + /* a8 */ INVALID, INVALID, INVALID, INVALID, + /* ac */ INVALID, INVALID, INVALID, INVALID, + /* b0 */ INVALID, INVALID, INVALID, INVALID, + /* b4 */ INVALID, INVALID, INVALID, INVALID, + /* b8 */ INVALID, INVALID, INVALID, INVALID, + /* bc */ INVALID, INVALID, INVALID, INVALID, + /* c0 */ INVALID, INVALID, 118, INVALID, + /* c4 */ INVALID, INVALID, INVALID, INVALID, + /* c8 */ INVALID, INVALID, INVALID, INVALID, + /* cc */ INVALID, INVALID, INVALID, INVALID, + /* d0 */ 36, INVALID, INVALID, INVALID, + /* d4 */ INVALID, INVALID, INVALID, INVALID, + /* d8 */ INVALID, INVALID, INVALID, INVALID, + /* dc */ INVALID, INVALID, INVALID, INVALID, + /* e0 */ INVALID, INVALID, INVALID, INVALID, + /* e4 */ INVALID, INVALID, 137, INVALID, + /* e8 */ INVALID, INVALID, INVALID, INVALID, + /* ec */ INVALID, INVALID, INVALID, INVALID, + /* f0 */ 1560, INVALID, INVALID, INVALID, + /* f4 */ INVALID, INVALID, INVALID, INVALID, + /* f8 */ INVALID, INVALID, INVALID, INVALID, + /* fc */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__400[] = { + /* 0 */ 1749, 1748, +}; + +static const uint16_t ud_itab__401[] = { + /* 0 */ 1564, 1562, +}; + +static const uint16_t ud_itab__402[] = { + /* 0 */ 1747, 1746, +}; + +static const uint16_t ud_itab__403[] = { + /* 0 */ GROUP(404), GROUP(335), INVALID, INVALID, + /* 4 */ INVALID, GROUP(341), GROUP(357), GROUP(369), + /* 8 */ INVALID, GROUP(394), INVALID, INVALID, + /* c */ INVALID, GROUP(399), INVALID, INVALID, +}; + +static const uint16_t ud_itab__404[] = { + /* 0 */ 769, INVALID, +}; + +static const uint16_t ud_itab__405[] = { + /* 0 */ 826, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__406[] = { + /* 0 */ 827, INVALID, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__407[] = { + /* 0 */ 715, INVALID, +}; + +static const uint16_t ud_itab__408[] = { + /* 0 */ 723, 724, 725, +}; + +static const uint16_t ud_itab__409[] = { + /* 0 */ 1280, 1285, 1269, 1273, + /* 4 */ 1326, 1333, 1320, 1314, +}; + +static const uint16_t ud_itab__410[] = { + /* 0 */ 1281, 1288, 1272, 1276, + /* 4 */ 1325, 1332, 1329, 1312, +}; + +static const uint16_t ud_itab__411[] = { + /* 0 */ 1282, 1289, 1270, 1277, + /* 4 */ 1324, 1331, 1321, 1316, +}; + +static const uint16_t ud_itab__412[] = { + /* 0 */ 1283, 1290, 1271, 1278, + /* 4 */ 1328, 1335, 1322, 1317, +}; + +static const uint16_t ud_itab__413[] = { + /* 0 */ 3, INVALID, +}; + +static const uint16_t ud_itab__414[] = { + /* 0 */ 2, INVALID, +}; + +static const uint16_t ud_itab__415[] = { + /* 0 */ 1311, INVALID, +}; + +static const uint16_t ud_itab__416[] = { + /* 0 */ GROUP(417), GROUP(418), +}; + +static const uint16_t ud_itab__417[] = { + /* 0 */ 206, 503, 307, 357, + /* 4 */ 587, 630, 387, 413, +}; + +static const uint16_t ud_itab__418[] = { + /* 0 */ 215, 216, 217, 218, + /* 4 */ 219, 220, 221, 222, + /* 8 */ 504, 505, 506, 507, + /* c */ 508, 509, 510, 511, + /* 10 */ 309, 310, 311, 312, + /* 14 */ 313, 314, 315, 316, + /* 18 */ 359, 360, 361, 362, + /* 1c */ 363, 364, 365, 366, + /* 20 */ 589, 590, 591, 592, + /* 24 */ 593, 594, 595, 596, + /* 28 */ 614, 615, 616, 617, + /* 2c */ 618, 619, 620, 621, + /* 30 */ 388, 389, 390, 391, + /* 34 */ 392, 393, 394, 395, + /* 38 */ 414, 415, 416, 417, + /* 3c */ 418, 419, 420, 421, +}; + +static const uint16_t ud_itab__419[] = { + /* 0 */ GROUP(420), GROUP(421), +}; + +static const uint16_t ud_itab__420[] = { + /* 0 */ 476, INVALID, 573, 540, + /* 4 */ 493, 492, 584, 583, +}; + +static const uint16_t ud_itab__421[] = { + /* 0 */ 477, 478, 479, 480, + /* 4 */ 481, 482, 483, 484, + /* 8 */ 658, 659, 660, 661, + /* c */ 662, 663, 664, 665, + /* 10 */ 522, INVALID, INVALID, INVALID, + /* 14 */ INVALID, INVALID, INVALID, INVALID, + /* 18 */ 549, 550, 551, 552, + /* 1c */ 553, 554, 555, 556, + /* 20 */ 233, 204, INVALID, INVALID, + /* 24 */ 639, 657, INVALID, INVALID, + /* 28 */ 485, 486, 487, 488, + /* 2c */ 489, 490, 491, INVALID, + /* 30 */ 203, 685, 529, 526, + /* 34 */ 684, 528, 377, 454, + /* 38 */ 527, 686, 537, 536, + /* 3c */ 530, 534, 535, 376, +}; + +static const uint16_t ud_itab__422[] = { + /* 0 */ GROUP(423), GROUP(424), +}; + +static const uint16_t ud_itab__423[] = { + /* 0 */ 456, 520, 448, 450, + /* 4 */ 462, 464, 460, 458, +}; + +static const uint16_t ud_itab__424[] = { + /* 0 */ 235, 236, 237, 238, + /* 4 */ 239, 240, 241, 242, + /* 8 */ 243, 244, 245, 246, + /* c */ 247, 248, 249, 250, + /* 10 */ 251, 252, 253, 254, + /* 14 */ 255, 256, 257, 258, + /* 18 */ 259, 260, 261, 262, + /* 1c */ 263, 264, 265, 266, + /* 20 */ INVALID, INVALID, INVALID, INVALID, + /* 24 */ INVALID, INVALID, INVALID, INVALID, + /* 28 */ INVALID, 656, INVALID, INVALID, + /* 2c */ INVALID, INVALID, INVALID, INVALID, + /* 30 */ INVALID, INVALID, INVALID, INVALID, + /* 34 */ INVALID, INVALID, INVALID, INVALID, + /* 38 */ INVALID, INVALID, INVALID, INVALID, + /* 3c */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__425[] = { + /* 0 */ GROUP(426), GROUP(427), +}; + +static const uint16_t ud_itab__426[] = { + /* 0 */ 453, 471, 467, 470, + /* 4 */ INVALID, 474, INVALID, 538, +}; + +static const uint16_t ud_itab__427[] = { + /* 0 */ 267, 268, 269, 270, + /* 4 */ 271, 272, 273, 274, + /* 8 */ 275, 276, 277, 278, + /* c */ 279, 280, 281, 282, + /* 10 */ 283, 284, 285, 286, + /* 14 */ 287, 288, 289, 290, + /* 18 */ 291, 292, 293, 294, + /* 1c */ 295, 296, 297, 298, + /* 20 */ 524, 523, 234, 455, + /* 24 */ 525, 532, INVALID, INVALID, + /* 28 */ 299, 300, 301, 302, + /* 2c */ 303, 304, 305, 306, + /* 30 */ 333, 334, 335, 336, + /* 34 */ 337, 338, 339, 340, + /* 38 */ INVALID, INVALID, INVALID, INVALID, + /* 3c */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__428[] = { + /* 0 */ GROUP(429), GROUP(430), +}; + +static const uint16_t ud_itab__429[] = { + /* 0 */ 205, 494, 308, 358, + /* 4 */ 588, 613, 378, 404, +}; + +static const uint16_t ud_itab__430[] = { + /* 0 */ 207, 208, 209, 210, + /* 4 */ 211, 212, 213, 214, + /* 8 */ 495, 496, 497, 498, + /* c */ 499, 500, 501, 502, + /* 10 */ 317, 318, 319, 320, + /* 14 */ 321, 322, 323, 324, + /* 18 */ 325, 326, 327, 328, + /* 1c */ 329, 330, 331, 332, + /* 20 */ 622, 623, 624, 625, + /* 24 */ 626, 627, 628, 629, + /* 28 */ 597, 598, 599, 600, + /* 2c */ 601, 602, 603, 604, + /* 30 */ 405, 406, 407, 408, + /* 34 */ 409, 410, 411, 412, + /* 38 */ 379, 380, 381, 382, + /* 3c */ 383, 384, 385, 386, +}; + +static const uint16_t ud_itab__431[] = { + /* 0 */ GROUP(432), GROUP(433), +}; + +static const uint16_t ud_itab__432[] = { + /* 0 */ 475, 472, 574, 539, + /* 4 */ 531, INVALID, 533, 585, +}; + +static const uint16_t ud_itab__433[] = { + /* 0 */ 431, 432, 433, 434, + /* 4 */ 435, 436, 437, 438, + /* 8 */ 666, 667, 668, 669, + /* c */ 670, 671, 672, 673, + /* 10 */ 575, 576, 577, 578, + /* 14 */ 579, 580, 581, 582, + /* 18 */ 541, 542, 543, 544, + /* 1c */ 545, 546, 547, 548, + /* 20 */ 640, 641, 642, 643, + /* 24 */ 644, 645, 646, 647, + /* 28 */ 648, 649, 650, 651, + /* 2c */ 652, 653, 654, 655, + /* 30 */ INVALID, INVALID, INVALID, INVALID, + /* 34 */ INVALID, INVALID, INVALID, INVALID, + /* 38 */ INVALID, INVALID, INVALID, INVALID, + /* 3c */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__434[] = { + /* 0 */ GROUP(435), GROUP(436), +}; + +static const uint16_t ud_itab__435[] = { + /* 0 */ 457, 521, 447, 449, + /* 4 */ 463, 465, 461, 459, +}; + +static const uint16_t ud_itab__436[] = { + /* 0 */ 223, 224, 225, 226, + /* 4 */ 227, 228, 229, 230, + /* 8 */ 512, 513, 514, 515, + /* c */ 516, 517, 518, 519, + /* 10 */ 367, 368, 369, 370, + /* 14 */ 371, 372, 373, 374, + /* 18 */ INVALID, 375, INVALID, INVALID, + /* 1c */ INVALID, INVALID, INVALID, INVALID, + /* 20 */ 631, 632, 633, 634, + /* 24 */ 635, 636, 637, 638, + /* 28 */ 605, 606, 607, 608, + /* 2c */ 609, 610, 611, 612, + /* 30 */ 422, 423, 424, 425, + /* 34 */ 426, 427, 428, 429, + /* 38 */ 396, 397, 398, 399, + /* 3c */ 400, 401, 402, 403, +}; + +static const uint16_t ud_itab__437[] = { + /* 0 */ GROUP(438), GROUP(439), +}; + +static const uint16_t ud_itab__438[] = { + /* 0 */ 451, 473, 466, 468, + /* 4 */ 231, 452, 232, 469, +}; + +static const uint16_t ud_itab__439[] = { + /* 0 */ 439, 440, 441, 442, + /* 4 */ 443, 444, 445, 446, + /* 8 */ 674, 675, 676, 677, + /* c */ 678, 679, 680, 681, + /* 10 */ 557, 558, 559, 560, + /* 14 */ 561, 562, 563, 564, + /* 18 */ 565, 566, 567, 568, + /* 1c */ 569, 570, 571, 572, + /* 20 */ 586, INVALID, INVALID, INVALID, + /* 24 */ INVALID, INVALID, INVALID, INVALID, + /* 28 */ 341, 342, 343, 344, + /* 2c */ 345, 346, 347, 348, + /* 30 */ 349, 350, 351, 352, + /* 34 */ 353, 354, 355, 356, + /* 38 */ INVALID, INVALID, INVALID, INVALID, + /* 3c */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__440[] = { + /* 0 */ 758, 759, 760, +}; + +static const uint16_t ud_itab__441[] = { + /* 0 */ 764, INVALID, +}; + +static const uint16_t ud_itab__442[] = { + /* 0 */ 1432, 1437, 962, 953, + /* 4 */ 942, 695, 186, 689, +}; + +static const uint16_t ud_itab__443[] = { + /* 0 */ 1438, 1439, 963, 954, + /* 4 */ 943, 696, 185, 688, +}; + +static const uint16_t ud_itab__444[] = { + /* 0 */ 708, 183, INVALID, INVALID, + /* 4 */ INVALID, INVALID, INVALID, INVALID, +}; + +static const uint16_t ud_itab__445[] = { + /* 0 */ 707, 184, GROUP(446), 71, + /* 4 */ 761, 762, 1255, INVALID, +}; + +static const uint16_t ud_itab__446[] = { + /* 0 */ 69, 70, +}; + + +struct ud_lookup_table_list_entry ud_lookup_table_list[] = { + /* 000 */ { ud_itab__0, UD_TAB__OPC_TABLE, "opctbl" }, + /* 001 */ { ud_itab__1, UD_TAB__OPC_MODE, "/m" }, + /* 002 */ { ud_itab__2, UD_TAB__OPC_MODE, "/m" }, + /* 003 */ { ud_itab__3, UD_TAB__OPC_MODE, "/m" }, + /* 004 */ { ud_itab__4, UD_TAB__OPC_TABLE, "opctbl" }, + /* 005 */ { ud_itab__5, UD_TAB__OPC_REG, "/reg" }, + /* 006 */ { ud_itab__6, UD_TAB__OPC_MOD, "/mod" }, + /* 007 */ { ud_itab__7, UD_TAB__OPC_REG, "/reg" }, + /* 008 */ { ud_itab__8, UD_TAB__OPC_REG, "/reg" }, + /* 009 */ { ud_itab__9, UD_TAB__OPC_RM, "/rm" }, + /* 010 */ { ud_itab__10, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 011 */ { ud_itab__11, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 012 */ { ud_itab__12, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 013 */ { ud_itab__13, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 014 */ { ud_itab__14, UD_TAB__OPC_RM, "/rm" }, + /* 015 */ { ud_itab__15, UD_TAB__OPC_RM, "/rm" }, + /* 016 */ { ud_itab__16, UD_TAB__OPC_RM, "/rm" }, + /* 017 */ { ud_itab__17, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 018 */ { ud_itab__18, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 019 */ { ud_itab__19, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 020 */ { ud_itab__20, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 021 */ { ud_itab__21, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 022 */ { ud_itab__22, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 023 */ { ud_itab__23, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 024 */ { ud_itab__24, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 025 */ { ud_itab__25, UD_TAB__OPC_RM, "/rm" }, + /* 026 */ { ud_itab__26, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 027 */ { ud_itab__27, UD_TAB__OPC_REG, "/reg" }, + /* 028 */ { ud_itab__28, UD_TAB__OPC_3DNOW, "/3dnow" }, + /* 029 */ { ud_itab__29, UD_TAB__OPC_SSE, "/sse" }, + /* 030 */ { ud_itab__30, UD_TAB__OPC_SSE, "/sse" }, + /* 031 */ { ud_itab__31, UD_TAB__OPC_MOD, "/mod" }, + /* 032 */ { ud_itab__32, UD_TAB__OPC_SSE, "/sse" }, + /* 033 */ { ud_itab__33, UD_TAB__OPC_SSE, "/sse" }, + /* 034 */ { ud_itab__34, UD_TAB__OPC_SSE, "/sse" }, + /* 035 */ { ud_itab__35, UD_TAB__OPC_SSE, "/sse" }, + /* 036 */ { ud_itab__36, UD_TAB__OPC_SSE, "/sse" }, + /* 037 */ { ud_itab__37, UD_TAB__OPC_MOD, "/mod" }, + /* 038 */ { ud_itab__38, UD_TAB__OPC_SSE, "/sse" }, + /* 039 */ { ud_itab__39, UD_TAB__OPC_SSE, "/sse" }, + /* 040 */ { ud_itab__40, UD_TAB__OPC_SSE, "/sse" }, + /* 041 */ { ud_itab__41, UD_TAB__OPC_REG, "/reg" }, + /* 042 */ { ud_itab__42, UD_TAB__OPC_SSE, "/sse" }, + /* 043 */ { ud_itab__43, UD_TAB__OPC_SSE, "/sse" }, + /* 044 */ { ud_itab__44, UD_TAB__OPC_SSE, "/sse" }, + /* 045 */ { ud_itab__45, UD_TAB__OPC_SSE, "/sse" }, + /* 046 */ { ud_itab__46, UD_TAB__OPC_SSE, "/sse" }, + /* 047 */ { ud_itab__47, UD_TAB__OPC_SSE, "/sse" }, + /* 048 */ { ud_itab__48, UD_TAB__OPC_SSE, "/sse" }, + /* 049 */ { ud_itab__49, UD_TAB__OPC_SSE, "/sse" }, + /* 050 */ { ud_itab__50, UD_TAB__OPC_MODE, "/m" }, + /* 051 */ { ud_itab__51, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 052 */ { ud_itab__52, UD_TAB__OPC_MODE, "/m" }, + /* 053 */ { ud_itab__53, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 054 */ { ud_itab__54, UD_TAB__OPC_TABLE, "opctbl" }, + /* 055 */ { ud_itab__55, UD_TAB__OPC_SSE, "/sse" }, + /* 056 */ { ud_itab__56, UD_TAB__OPC_MODE, "/m" }, + /* 057 */ { ud_itab__57, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 058 */ { ud_itab__58, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 059 */ { ud_itab__59, UD_TAB__OPC_SSE, "/sse" }, + /* 060 */ { ud_itab__60, UD_TAB__OPC_MODE, "/m" }, + /* 061 */ { ud_itab__61, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 062 */ { ud_itab__62, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 063 */ { ud_itab__63, UD_TAB__OPC_SSE, "/sse" }, + /* 064 */ { ud_itab__64, UD_TAB__OPC_SSE, "/sse" }, + /* 065 */ { ud_itab__65, UD_TAB__OPC_SSE, "/sse" }, + /* 066 */ { ud_itab__66, UD_TAB__OPC_SSE, "/sse" }, + /* 067 */ { ud_itab__67, UD_TAB__OPC_SSE, "/sse" }, + /* 068 */ { ud_itab__68, UD_TAB__OPC_SSE, "/sse" }, + /* 069 */ { ud_itab__69, UD_TAB__OPC_SSE, "/sse" }, + /* 070 */ { ud_itab__70, UD_TAB__OPC_SSE, "/sse" }, + /* 071 */ { ud_itab__71, UD_TAB__OPC_SSE, "/sse" }, + /* 072 */ { ud_itab__72, UD_TAB__OPC_SSE, "/sse" }, + /* 073 */ { ud_itab__73, UD_TAB__OPC_SSE, "/sse" }, + /* 074 */ { ud_itab__74, UD_TAB__OPC_SSE, "/sse" }, + /* 075 */ { ud_itab__75, UD_TAB__OPC_SSE, "/sse" }, + /* 076 */ { ud_itab__76, UD_TAB__OPC_SSE, "/sse" }, + /* 077 */ { ud_itab__77, UD_TAB__OPC_SSE, "/sse" }, + /* 078 */ { ud_itab__78, UD_TAB__OPC_SSE, "/sse" }, + /* 079 */ { ud_itab__79, UD_TAB__OPC_SSE, "/sse" }, + /* 080 */ { ud_itab__80, UD_TAB__OPC_SSE, "/sse" }, + /* 081 */ { ud_itab__81, UD_TAB__OPC_SSE, "/sse" }, + /* 082 */ { ud_itab__82, UD_TAB__OPC_SSE, "/sse" }, + /* 083 */ { ud_itab__83, UD_TAB__OPC_SSE, "/sse" }, + /* 084 */ { ud_itab__84, UD_TAB__OPC_SSE, "/sse" }, + /* 085 */ { ud_itab__85, UD_TAB__OPC_SSE, "/sse" }, + /* 086 */ { ud_itab__86, UD_TAB__OPC_SSE, "/sse" }, + /* 087 */ { ud_itab__87, UD_TAB__OPC_SSE, "/sse" }, + /* 088 */ { ud_itab__88, UD_TAB__OPC_SSE, "/sse" }, + /* 089 */ { ud_itab__89, UD_TAB__OPC_SSE, "/sse" }, + /* 090 */ { ud_itab__90, UD_TAB__OPC_SSE, "/sse" }, + /* 091 */ { ud_itab__91, UD_TAB__OPC_SSE, "/sse" }, + /* 092 */ { ud_itab__92, UD_TAB__OPC_SSE, "/sse" }, + /* 093 */ { ud_itab__93, UD_TAB__OPC_SSE, "/sse" }, + /* 094 */ { ud_itab__94, UD_TAB__OPC_SSE, "/sse" }, + /* 095 */ { ud_itab__95, UD_TAB__OPC_SSE, "/sse" }, + /* 096 */ { ud_itab__96, UD_TAB__OPC_SSE, "/sse" }, + /* 097 */ { ud_itab__97, UD_TAB__OPC_SSE, "/sse" }, + /* 098 */ { ud_itab__98, UD_TAB__OPC_SSE, "/sse" }, + /* 099 */ { ud_itab__99, UD_TAB__OPC_SSE, "/sse" }, + /* 100 */ { ud_itab__100, UD_TAB__OPC_SSE, "/sse" }, + /* 101 */ { ud_itab__101, UD_TAB__OPC_SSE, "/sse" }, + /* 102 */ { ud_itab__102, UD_TAB__OPC_SSE, "/sse" }, + /* 103 */ { ud_itab__103, UD_TAB__OPC_SSE, "/sse" }, + /* 104 */ { ud_itab__104, UD_TAB__OPC_SSE, "/sse" }, + /* 105 */ { ud_itab__105, UD_TAB__OPC_SSE, "/sse" }, + /* 106 */ { ud_itab__106, UD_TAB__OPC_SSE, "/sse" }, + /* 107 */ { ud_itab__107, UD_TAB__OPC_SSE, "/sse" }, + /* 108 */ { ud_itab__108, UD_TAB__OPC_SSE, "/sse" }, + /* 109 */ { ud_itab__109, UD_TAB__OPC_SSE, "/sse" }, + /* 110 */ { ud_itab__110, UD_TAB__OPC_SSE, "/sse" }, + /* 111 */ { ud_itab__111, UD_TAB__OPC_SSE, "/sse" }, + /* 112 */ { ud_itab__112, UD_TAB__OPC_SSE, "/sse" }, + /* 113 */ { ud_itab__113, UD_TAB__OPC_SSE, "/sse" }, + /* 114 */ { ud_itab__114, UD_TAB__OPC_SSE, "/sse" }, + /* 115 */ { ud_itab__115, UD_TAB__OPC_SSE, "/sse" }, + /* 116 */ { ud_itab__116, UD_TAB__OPC_TABLE, "opctbl" }, + /* 117 */ { ud_itab__117, UD_TAB__OPC_SSE, "/sse" }, + /* 118 */ { ud_itab__118, UD_TAB__OPC_SSE, "/sse" }, + /* 119 */ { ud_itab__119, UD_TAB__OPC_SSE, "/sse" }, + /* 120 */ { ud_itab__120, UD_TAB__OPC_SSE, "/sse" }, + /* 121 */ { ud_itab__121, UD_TAB__OPC_SSE, "/sse" }, + /* 122 */ { ud_itab__122, UD_TAB__OPC_SSE, "/sse" }, + /* 123 */ { ud_itab__123, UD_TAB__OPC_SSE, "/sse" }, + /* 124 */ { ud_itab__124, UD_TAB__OPC_SSE, "/sse" }, + /* 125 */ { ud_itab__125, UD_TAB__OPC_SSE, "/sse" }, + /* 126 */ { ud_itab__126, UD_TAB__OPC_SSE, "/sse" }, + /* 127 */ { ud_itab__127, UD_TAB__OPC_SSE, "/sse" }, + /* 128 */ { ud_itab__128, UD_TAB__OPC_OSIZE, "/o" }, + /* 129 */ { ud_itab__129, UD_TAB__OPC_SSE, "/sse" }, + /* 130 */ { ud_itab__130, UD_TAB__OPC_SSE, "/sse" }, + /* 131 */ { ud_itab__131, UD_TAB__OPC_SSE, "/sse" }, + /* 132 */ { ud_itab__132, UD_TAB__OPC_SSE, "/sse" }, + /* 133 */ { ud_itab__133, UD_TAB__OPC_OSIZE, "/o" }, + /* 134 */ { ud_itab__134, UD_TAB__OPC_SSE, "/sse" }, + /* 135 */ { ud_itab__135, UD_TAB__OPC_SSE, "/sse" }, + /* 136 */ { ud_itab__136, UD_TAB__OPC_SSE, "/sse" }, + /* 137 */ { ud_itab__137, UD_TAB__OPC_SSE, "/sse" }, + /* 138 */ { ud_itab__138, UD_TAB__OPC_SSE, "/sse" }, + /* 139 */ { ud_itab__139, UD_TAB__OPC_SSE, "/sse" }, + /* 140 */ { ud_itab__140, UD_TAB__OPC_SSE, "/sse" }, + /* 141 */ { ud_itab__141, UD_TAB__OPC_SSE, "/sse" }, + /* 142 */ { ud_itab__142, UD_TAB__OPC_SSE, "/sse" }, + /* 143 */ { ud_itab__143, UD_TAB__OPC_SSE, "/sse" }, + /* 144 */ { ud_itab__144, UD_TAB__OPC_SSE, "/sse" }, + /* 145 */ { ud_itab__145, UD_TAB__OPC_SSE, "/sse" }, + /* 146 */ { ud_itab__146, UD_TAB__OPC_SSE, "/sse" }, + /* 147 */ { ud_itab__147, UD_TAB__OPC_SSE, "/sse" }, + /* 148 */ { ud_itab__148, UD_TAB__OPC_SSE, "/sse" }, + /* 149 */ { ud_itab__149, UD_TAB__OPC_SSE, "/sse" }, + /* 150 */ { ud_itab__150, UD_TAB__OPC_SSE, "/sse" }, + /* 151 */ { ud_itab__151, UD_TAB__OPC_SSE, "/sse" }, + /* 152 */ { ud_itab__152, UD_TAB__OPC_SSE, "/sse" }, + /* 153 */ { ud_itab__153, UD_TAB__OPC_SSE, "/sse" }, + /* 154 */ { ud_itab__154, UD_TAB__OPC_SSE, "/sse" }, + /* 155 */ { ud_itab__155, UD_TAB__OPC_SSE, "/sse" }, + /* 156 */ { ud_itab__156, UD_TAB__OPC_SSE, "/sse" }, + /* 157 */ { ud_itab__157, UD_TAB__OPC_SSE, "/sse" }, + /* 158 */ { ud_itab__158, UD_TAB__OPC_SSE, "/sse" }, + /* 159 */ { ud_itab__159, UD_TAB__OPC_SSE, "/sse" }, + /* 160 */ { ud_itab__160, UD_TAB__OPC_SSE, "/sse" }, + /* 161 */ { ud_itab__161, UD_TAB__OPC_SSE, "/sse" }, + /* 162 */ { ud_itab__162, UD_TAB__OPC_SSE, "/sse" }, + /* 163 */ { ud_itab__163, UD_TAB__OPC_SSE, "/sse" }, + /* 164 */ { ud_itab__164, UD_TAB__OPC_SSE, "/sse" }, + /* 165 */ { ud_itab__165, UD_TAB__OPC_SSE, "/sse" }, + /* 166 */ { ud_itab__166, UD_TAB__OPC_SSE, "/sse" }, + /* 167 */ { ud_itab__167, UD_TAB__OPC_SSE, "/sse" }, + /* 168 */ { ud_itab__168, UD_TAB__OPC_SSE, "/sse" }, + /* 169 */ { ud_itab__169, UD_TAB__OPC_SSE, "/sse" }, + /* 170 */ { ud_itab__170, UD_TAB__OPC_SSE, "/sse" }, + /* 171 */ { ud_itab__171, UD_TAB__OPC_SSE, "/sse" }, + /* 172 */ { ud_itab__172, UD_TAB__OPC_SSE, "/sse" }, + /* 173 */ { ud_itab__173, UD_TAB__OPC_SSE, "/sse" }, + /* 174 */ { ud_itab__174, UD_TAB__OPC_OSIZE, "/o" }, + /* 175 */ { ud_itab__175, UD_TAB__OPC_OSIZE, "/o" }, + /* 176 */ { ud_itab__176, UD_TAB__OPC_SSE, "/sse" }, + /* 177 */ { ud_itab__177, UD_TAB__OPC_SSE, "/sse" }, + /* 178 */ { ud_itab__178, UD_TAB__OPC_REG, "/reg" }, + /* 179 */ { ud_itab__179, UD_TAB__OPC_SSE, "/sse" }, + /* 180 */ { ud_itab__180, UD_TAB__OPC_SSE, "/sse" }, + /* 181 */ { ud_itab__181, UD_TAB__OPC_SSE, "/sse" }, + /* 182 */ { ud_itab__182, UD_TAB__OPC_REG, "/reg" }, + /* 183 */ { ud_itab__183, UD_TAB__OPC_SSE, "/sse" }, + /* 184 */ { ud_itab__184, UD_TAB__OPC_SSE, "/sse" }, + /* 185 */ { ud_itab__185, UD_TAB__OPC_SSE, "/sse" }, + /* 186 */ { ud_itab__186, UD_TAB__OPC_REG, "/reg" }, + /* 187 */ { ud_itab__187, UD_TAB__OPC_SSE, "/sse" }, + /* 188 */ { ud_itab__188, UD_TAB__OPC_SSE, "/sse" }, + /* 189 */ { ud_itab__189, UD_TAB__OPC_SSE, "/sse" }, + /* 190 */ { ud_itab__190, UD_TAB__OPC_SSE, "/sse" }, + /* 191 */ { ud_itab__191, UD_TAB__OPC_SSE, "/sse" }, + /* 192 */ { ud_itab__192, UD_TAB__OPC_SSE, "/sse" }, + /* 193 */ { ud_itab__193, UD_TAB__OPC_SSE, "/sse" }, + /* 194 */ { ud_itab__194, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 195 */ { ud_itab__195, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 196 */ { ud_itab__196, UD_TAB__OPC_SSE, "/sse" }, + /* 197 */ { ud_itab__197, UD_TAB__OPC_SSE, "/sse" }, + /* 198 */ { ud_itab__198, UD_TAB__OPC_SSE, "/sse" }, + /* 199 */ { ud_itab__199, UD_TAB__OPC_OSIZE, "/o" }, + /* 200 */ { ud_itab__200, UD_TAB__OPC_OSIZE, "/o" }, + /* 201 */ { ud_itab__201, UD_TAB__OPC_SSE, "/sse" }, + /* 202 */ { ud_itab__202, UD_TAB__OPC_MOD, "/mod" }, + /* 203 */ { ud_itab__203, UD_TAB__OPC_REG, "/reg" }, + /* 204 */ { ud_itab__204, UD_TAB__OPC_RM, "/rm" }, + /* 205 */ { ud_itab__205, UD_TAB__OPC_RM, "/rm" }, + /* 206 */ { ud_itab__206, UD_TAB__OPC_RM, "/rm" }, + /* 207 */ { ud_itab__207, UD_TAB__OPC_MOD, "/mod" }, + /* 208 */ { ud_itab__208, UD_TAB__OPC_REG, "/reg" }, + /* 209 */ { ud_itab__209, UD_TAB__OPC_RM, "/rm" }, + /* 210 */ { ud_itab__210, UD_TAB__OPC_RM, "/rm" }, + /* 211 */ { ud_itab__211, UD_TAB__OPC_RM, "/rm" }, + /* 212 */ { ud_itab__212, UD_TAB__OPC_RM, "/rm" }, + /* 213 */ { ud_itab__213, UD_TAB__OPC_RM, "/rm" }, + /* 214 */ { ud_itab__214, UD_TAB__OPC_RM, "/rm" }, + /* 215 */ { ud_itab__215, UD_TAB__OPC_MOD, "/mod" }, + /* 216 */ { ud_itab__216, UD_TAB__OPC_REG, "/reg" }, + /* 217 */ { ud_itab__217, UD_TAB__OPC_REG, "/reg" }, + /* 218 */ { ud_itab__218, UD_TAB__OPC_RM, "/rm" }, + /* 219 */ { ud_itab__219, UD_TAB__OPC_RM, "/rm" }, + /* 220 */ { ud_itab__220, UD_TAB__OPC_RM, "/rm" }, + /* 221 */ { ud_itab__221, UD_TAB__OPC_SSE, "/sse" }, + /* 222 */ { ud_itab__222, UD_TAB__OPC_REG, "/reg" }, + /* 223 */ { ud_itab__223, UD_TAB__OPC_SSE, "/sse" }, + /* 224 */ { ud_itab__224, UD_TAB__OPC_SSE, "/sse" }, + /* 225 */ { ud_itab__225, UD_TAB__OPC_SSE, "/sse" }, + /* 226 */ { ud_itab__226, UD_TAB__OPC_SSE, "/sse" }, + /* 227 */ { ud_itab__227, UD_TAB__OPC_MOD, "/mod" }, + /* 228 */ { ud_itab__228, UD_TAB__OPC_REG, "/reg" }, + /* 229 */ { ud_itab__229, UD_TAB__OPC_OSIZE, "/o" }, + /* 230 */ { ud_itab__230, UD_TAB__OPC_SSE, "/sse" }, + /* 231 */ { ud_itab__231, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 232 */ { ud_itab__232, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 233 */ { ud_itab__233, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 234 */ { ud_itab__234, UD_TAB__OPC_VENDOR, "/vendor" }, + /* 235 */ { ud_itab__235, UD_TAB__OPC_REG, "/reg" }, + /* 236 */ { ud_itab__236, UD_TAB__OPC_SSE, "/sse" }, + /* 237 */ { ud_itab__237, UD_TAB__OPC_SSE, "/sse" }, + /* 238 */ { ud_itab__238, UD_TAB__OPC_SSE, "/sse" }, + /* 239 */ { ud_itab__239, UD_TAB__OPC_SSE, "/sse" }, + /* 240 */ { ud_itab__240, UD_TAB__OPC_SSE, "/sse" }, + /* 241 */ { ud_itab__241, UD_TAB__OPC_SSE, "/sse" }, + /* 242 */ { ud_itab__242, UD_TAB__OPC_SSE, "/sse" }, + /* 243 */ { ud_itab__243, UD_TAB__OPC_SSE, "/sse" }, + /* 244 */ { ud_itab__244, UD_TAB__OPC_SSE, "/sse" }, + /* 245 */ { ud_itab__245, UD_TAB__OPC_SSE, "/sse" }, + /* 246 */ { ud_itab__246, UD_TAB__OPC_SSE, "/sse" }, + /* 247 */ { ud_itab__247, UD_TAB__OPC_SSE, "/sse" }, + /* 248 */ { ud_itab__248, UD_TAB__OPC_SSE, "/sse" }, + /* 249 */ { ud_itab__249, UD_TAB__OPC_SSE, "/sse" }, + /* 250 */ { ud_itab__250, UD_TAB__OPC_SSE, "/sse" }, + /* 251 */ { ud_itab__251, UD_TAB__OPC_SSE, "/sse" }, + /* 252 */ { ud_itab__252, UD_TAB__OPC_SSE, "/sse" }, + /* 253 */ { ud_itab__253, UD_TAB__OPC_SSE, "/sse" }, + /* 254 */ { ud_itab__254, UD_TAB__OPC_SSE, "/sse" }, + /* 255 */ { ud_itab__255, UD_TAB__OPC_SSE, "/sse" }, + /* 256 */ { ud_itab__256, UD_TAB__OPC_SSE, "/sse" }, + /* 257 */ { ud_itab__257, UD_TAB__OPC_SSE, "/sse" }, + /* 258 */ { ud_itab__258, UD_TAB__OPC_SSE, "/sse" }, + /* 259 */ { ud_itab__259, UD_TAB__OPC_SSE, "/sse" }, + /* 260 */ { ud_itab__260, UD_TAB__OPC_SSE, "/sse" }, + /* 261 */ { ud_itab__261, UD_TAB__OPC_SSE, "/sse" }, + /* 262 */ { ud_itab__262, UD_TAB__OPC_SSE, "/sse" }, + /* 263 */ { ud_itab__263, UD_TAB__OPC_SSE, "/sse" }, + /* 264 */ { ud_itab__264, UD_TAB__OPC_SSE, "/sse" }, + /* 265 */ { ud_itab__265, UD_TAB__OPC_SSE, "/sse" }, + /* 266 */ { ud_itab__266, UD_TAB__OPC_SSE, "/sse" }, + /* 267 */ { ud_itab__267, UD_TAB__OPC_SSE, "/sse" }, + /* 268 */ { ud_itab__268, UD_TAB__OPC_SSE, "/sse" }, + /* 269 */ { ud_itab__269, UD_TAB__OPC_SSE, "/sse" }, + /* 270 */ { ud_itab__270, UD_TAB__OPC_SSE, "/sse" }, + /* 271 */ { ud_itab__271, UD_TAB__OPC_SSE, "/sse" }, + /* 272 */ { ud_itab__272, UD_TAB__OPC_SSE, "/sse" }, + /* 273 */ { ud_itab__273, UD_TAB__OPC_SSE, "/sse" }, + /* 274 */ { ud_itab__274, UD_TAB__OPC_SSE, "/sse" }, + /* 275 */ { ud_itab__275, UD_TAB__OPC_MOD, "/mod" }, + /* 276 */ { ud_itab__276, UD_TAB__OPC_SSE, "/sse" }, + /* 277 */ { ud_itab__277, UD_TAB__OPC_SSE, "/sse" }, + /* 278 */ { ud_itab__278, UD_TAB__OPC_SSE, "/sse" }, + /* 279 */ { ud_itab__279, UD_TAB__OPC_SSE, "/sse" }, + /* 280 */ { ud_itab__280, UD_TAB__OPC_SSE, "/sse" }, + /* 281 */ { ud_itab__281, UD_TAB__OPC_SSE, "/sse" }, + /* 282 */ { ud_itab__282, UD_TAB__OPC_SSE, "/sse" }, + /* 283 */ { ud_itab__283, UD_TAB__OPC_SSE, "/sse" }, + /* 284 */ { ud_itab__284, UD_TAB__OPC_MODE, "/m" }, + /* 285 */ { ud_itab__285, UD_TAB__OPC_MODE, "/m" }, + /* 286 */ { ud_itab__286, UD_TAB__OPC_MODE, "/m" }, + /* 287 */ { ud_itab__287, UD_TAB__OPC_MODE, "/m" }, + /* 288 */ { ud_itab__288, UD_TAB__OPC_MODE, "/m" }, + /* 289 */ { ud_itab__289, UD_TAB__OPC_MODE, "/m" }, + /* 290 */ { ud_itab__290, UD_TAB__OPC_MODE, "/m" }, + /* 291 */ { ud_itab__291, UD_TAB__OPC_MODE, "/m" }, + /* 292 */ { ud_itab__292, UD_TAB__OPC_OSIZE, "/o" }, + /* 293 */ { ud_itab__293, UD_TAB__OPC_MODE, "/m" }, + /* 294 */ { ud_itab__294, UD_TAB__OPC_MODE, "/m" }, + /* 295 */ { ud_itab__295, UD_TAB__OPC_OSIZE, "/o" }, + /* 296 */ { ud_itab__296, UD_TAB__OPC_MODE, "/m" }, + /* 297 */ { ud_itab__297, UD_TAB__OPC_MODE, "/m" }, + /* 298 */ { ud_itab__298, UD_TAB__OPC_MODE, "/m" }, + /* 299 */ { ud_itab__299, UD_TAB__OPC_MODE, "/m" }, + /* 300 */ { ud_itab__300, UD_TAB__OPC_OSIZE, "/o" }, + /* 301 */ { ud_itab__301, UD_TAB__OPC_OSIZE, "/o" }, + /* 302 */ { ud_itab__302, UD_TAB__OPC_REG, "/reg" }, + /* 303 */ { ud_itab__303, UD_TAB__OPC_REG, "/reg" }, + /* 304 */ { ud_itab__304, UD_TAB__OPC_REG, "/reg" }, + /* 305 */ { ud_itab__305, UD_TAB__OPC_MODE, "/m" }, + /* 306 */ { ud_itab__306, UD_TAB__OPC_MODE, "/m" }, + /* 307 */ { ud_itab__307, UD_TAB__OPC_MODE, "/m" }, + /* 308 */ { ud_itab__308, UD_TAB__OPC_MODE, "/m" }, + /* 309 */ { ud_itab__309, UD_TAB__OPC_MODE, "/m" }, + /* 310 */ { ud_itab__310, UD_TAB__OPC_MODE, "/m" }, + /* 311 */ { ud_itab__311, UD_TAB__OPC_MODE, "/m" }, + /* 312 */ { ud_itab__312, UD_TAB__OPC_MODE, "/m" }, + /* 313 */ { ud_itab__313, UD_TAB__OPC_REG, "/reg" }, + /* 314 */ { ud_itab__314, UD_TAB__OPC_REG, "/reg" }, + /* 315 */ { ud_itab__315, UD_TAB__OPC_OSIZE, "/o" }, + /* 316 */ { ud_itab__316, UD_TAB__OPC_OSIZE, "/o" }, + /* 317 */ { ud_itab__317, UD_TAB__OPC_MODE, "/m" }, + /* 318 */ { ud_itab__318, UD_TAB__OPC_OSIZE, "/o" }, + /* 319 */ { ud_itab__319, UD_TAB__OPC_MODE, "/m" }, + /* 320 */ { ud_itab__320, UD_TAB__OPC_MODE, "/m" }, + /* 321 */ { ud_itab__321, UD_TAB__OPC_MODE, "/m" }, + /* 322 */ { ud_itab__322, UD_TAB__OPC_OSIZE, "/o" }, + /* 323 */ { ud_itab__323, UD_TAB__OPC_MODE, "/m" }, + /* 324 */ { ud_itab__324, UD_TAB__OPC_MODE, "/m" }, + /* 325 */ { ud_itab__325, UD_TAB__OPC_MODE, "/m" }, + /* 326 */ { ud_itab__326, UD_TAB__OPC_OSIZE, "/o" }, + /* 327 */ { ud_itab__327, UD_TAB__OPC_OSIZE, "/o" }, + /* 328 */ { ud_itab__328, UD_TAB__OPC_OSIZE, "/o" }, + /* 329 */ { ud_itab__329, UD_TAB__OPC_OSIZE, "/o" }, + /* 330 */ { ud_itab__330, UD_TAB__OPC_OSIZE, "/o" }, + /* 331 */ { ud_itab__331, UD_TAB__OPC_REG, "/reg" }, + /* 332 */ { ud_itab__332, UD_TAB__OPC_REG, "/reg" }, + /* 333 */ { ud_itab__333, UD_TAB__OPC_VEX, "/vex" }, + /* 334 */ { ud_itab__334, UD_TAB__OPC_MODE, "/m" }, + /* 335 */ { ud_itab__335, UD_TAB__OPC_TABLE, "opctbl" }, + /* 336 */ { ud_itab__336, UD_TAB__OPC_MOD, "/mod" }, + /* 337 */ { ud_itab__337, UD_TAB__OPC_MOD, "/mod" }, + /* 338 */ { ud_itab__338, UD_TAB__OPC_MOD, "/mod" }, + /* 339 */ { ud_itab__339, UD_TAB__OPC_REG, "/reg" }, + /* 340 */ { ud_itab__340, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 341 */ { ud_itab__341, UD_TAB__OPC_TABLE, "opctbl" }, + /* 342 */ { ud_itab__342, UD_TAB__OPC_MOD, "/mod" }, + /* 343 */ { ud_itab__343, UD_TAB__OPC_MOD, "/mod" }, + /* 344 */ { ud_itab__344, UD_TAB__OPC_OSIZE, "/o" }, + /* 345 */ { ud_itab__345, UD_TAB__OPC_REG, "/reg" }, + /* 346 */ { ud_itab__346, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 347 */ { ud_itab__347, UD_TAB__OPC_REG, "/reg" }, + /* 348 */ { ud_itab__348, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 349 */ { ud_itab__349, UD_TAB__OPC_REG, "/reg" }, + /* 350 */ { ud_itab__350, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 351 */ { ud_itab__351, UD_TAB__OPC_OSIZE, "/o" }, + /* 352 */ { ud_itab__352, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 353 */ { ud_itab__353, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 354 */ { ud_itab__354, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 355 */ { ud_itab__355, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 356 */ { ud_itab__356, UD_TAB__OPC_MOD, "/mod" }, + /* 357 */ { ud_itab__357, UD_TAB__OPC_TABLE, "opctbl" }, + /* 358 */ { ud_itab__358, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 359 */ { ud_itab__359, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 360 */ { ud_itab__360, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 361 */ { ud_itab__361, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 362 */ { ud_itab__362, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 363 */ { ud_itab__363, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 364 */ { ud_itab__364, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 365 */ { ud_itab__365, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 366 */ { ud_itab__366, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 367 */ { ud_itab__367, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 368 */ { ud_itab__368, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 369 */ { ud_itab__369, UD_TAB__OPC_TABLE, "opctbl" }, + /* 370 */ { ud_itab__370, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 371 */ { ud_itab__371, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 372 */ { ud_itab__372, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 373 */ { ud_itab__373, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 374 */ { ud_itab__374, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 375 */ { ud_itab__375, UD_TAB__OPC_OSIZE, "/o" }, + /* 376 */ { ud_itab__376, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 377 */ { ud_itab__377, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 378 */ { ud_itab__378, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 379 */ { ud_itab__379, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 380 */ { ud_itab__380, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 381 */ { ud_itab__381, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 382 */ { ud_itab__382, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 383 */ { ud_itab__383, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 384 */ { ud_itab__384, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 385 */ { ud_itab__385, UD_TAB__OPC_MODE, "/m" }, + /* 386 */ { ud_itab__386, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 387 */ { ud_itab__387, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 388 */ { ud_itab__388, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 389 */ { ud_itab__389, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 390 */ { ud_itab__390, UD_TAB__OPC_VEX_L, "/vexl" }, + /* 391 */ { ud_itab__391, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 392 */ { ud_itab__392, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 393 */ { ud_itab__393, UD_TAB__OPC_VEX_W, "/vexw" }, + /* 394 */ { ud_itab__394, UD_TAB__OPC_TABLE, "opctbl" }, + /* 395 */ { ud_itab__395, UD_TAB__OPC_MOD, "/mod" }, + /* 396 */ { ud_itab__396, UD_TAB__OPC_MOD, "/mod" }, + /* 397 */ { ud_itab__397, UD_TAB__OPC_MOD, "/mod" }, + /* 398 */ { ud_itab__398, UD_TAB__OPC_MOD, "/mod" }, + /* 399 */ { ud_itab__399, UD_TAB__OPC_TABLE, "opctbl" }, + /* 400 */ { ud_itab__400, UD_TAB__OPC_MOD, "/mod" }, + /* 401 */ { ud_itab__401, UD_TAB__OPC_MOD, "/mod" }, + /* 402 */ { ud_itab__402, UD_TAB__OPC_MOD, "/mod" }, + /* 403 */ { ud_itab__403, UD_TAB__OPC_VEX, "/vex" }, + /* 404 */ { ud_itab__404, UD_TAB__OPC_MODE, "/m" }, + /* 405 */ { ud_itab__405, UD_TAB__OPC_REG, "/reg" }, + /* 406 */ { ud_itab__406, UD_TAB__OPC_REG, "/reg" }, + /* 407 */ { ud_itab__407, UD_TAB__OPC_MODE, "/m" }, + /* 408 */ { ud_itab__408, UD_TAB__OPC_OSIZE, "/o" }, + /* 409 */ { ud_itab__409, UD_TAB__OPC_REG, "/reg" }, + /* 410 */ { ud_itab__410, UD_TAB__OPC_REG, "/reg" }, + /* 411 */ { ud_itab__411, UD_TAB__OPC_REG, "/reg" }, + /* 412 */ { ud_itab__412, UD_TAB__OPC_REG, "/reg" }, + /* 413 */ { ud_itab__413, UD_TAB__OPC_MODE, "/m" }, + /* 414 */ { ud_itab__414, UD_TAB__OPC_MODE, "/m" }, + /* 415 */ { ud_itab__415, UD_TAB__OPC_MODE, "/m" }, + /* 416 */ { ud_itab__416, UD_TAB__OPC_MOD, "/mod" }, + /* 417 */ { ud_itab__417, UD_TAB__OPC_REG, "/reg" }, + /* 418 */ { ud_itab__418, UD_TAB__OPC_X87, "/x87" }, + /* 419 */ { ud_itab__419, UD_TAB__OPC_MOD, "/mod" }, + /* 420 */ { ud_itab__420, UD_TAB__OPC_REG, "/reg" }, + /* 421 */ { ud_itab__421, UD_TAB__OPC_X87, "/x87" }, + /* 422 */ { ud_itab__422, UD_TAB__OPC_MOD, "/mod" }, + /* 423 */ { ud_itab__423, UD_TAB__OPC_REG, "/reg" }, + /* 424 */ { ud_itab__424, UD_TAB__OPC_X87, "/x87" }, + /* 425 */ { ud_itab__425, UD_TAB__OPC_MOD, "/mod" }, + /* 426 */ { ud_itab__426, UD_TAB__OPC_REG, "/reg" }, + /* 427 */ { ud_itab__427, UD_TAB__OPC_X87, "/x87" }, + /* 428 */ { ud_itab__428, UD_TAB__OPC_MOD, "/mod" }, + /* 429 */ { ud_itab__429, UD_TAB__OPC_REG, "/reg" }, + /* 430 */ { ud_itab__430, UD_TAB__OPC_X87, "/x87" }, + /* 431 */ { ud_itab__431, UD_TAB__OPC_MOD, "/mod" }, + /* 432 */ { ud_itab__432, UD_TAB__OPC_REG, "/reg" }, + /* 433 */ { ud_itab__433, UD_TAB__OPC_X87, "/x87" }, + /* 434 */ { ud_itab__434, UD_TAB__OPC_MOD, "/mod" }, + /* 435 */ { ud_itab__435, UD_TAB__OPC_REG, "/reg" }, + /* 436 */ { ud_itab__436, UD_TAB__OPC_X87, "/x87" }, + /* 437 */ { ud_itab__437, UD_TAB__OPC_MOD, "/mod" }, + /* 438 */ { ud_itab__438, UD_TAB__OPC_REG, "/reg" }, + /* 439 */ { ud_itab__439, UD_TAB__OPC_X87, "/x87" }, + /* 440 */ { ud_itab__440, UD_TAB__OPC_ASIZE, "/a" }, + /* 441 */ { ud_itab__441, UD_TAB__OPC_MODE, "/m" }, + /* 442 */ { ud_itab__442, UD_TAB__OPC_REG, "/reg" }, + /* 443 */ { ud_itab__443, UD_TAB__OPC_REG, "/reg" }, + /* 444 */ { ud_itab__444, UD_TAB__OPC_REG, "/reg" }, + /* 445 */ { ud_itab__445, UD_TAB__OPC_REG, "/reg" }, + /* 446 */ { ud_itab__446, UD_TAB__OPC_MODE, "/m" }, +}; + +/* itab entry operand definitions (for readability) */ +#define O_AL { OP_AL, SZ_B } +#define O_AX { OP_AX, SZ_W } +#define O_Av { OP_A, SZ_V } +#define O_C { OP_C, SZ_NA } +#define O_CL { OP_CL, SZ_B } +#define O_CS { OP_CS, SZ_NA } +#define O_CX { OP_CX, SZ_W } +#define O_D { OP_D, SZ_NA } +#define O_DL { OP_DL, SZ_B } +#define O_DS { OP_DS, SZ_NA } +#define O_DX { OP_DX, SZ_W } +#define O_E { OP_E, SZ_NA } +#define O_ES { OP_ES, SZ_NA } +#define O_Eb { OP_E, SZ_B } +#define O_Ed { OP_E, SZ_D } +#define O_Eq { OP_E, SZ_Q } +#define O_Ev { OP_E, SZ_V } +#define O_Ew { OP_E, SZ_W } +#define O_Ey { OP_E, SZ_Y } +#define O_Ez { OP_E, SZ_Z } +#define O_FS { OP_FS, SZ_NA } +#define O_Fv { OP_F, SZ_V } +#define O_G { OP_G, SZ_NA } +#define O_GS { OP_GS, SZ_NA } +#define O_Gb { OP_G, SZ_B } +#define O_Gd { OP_G, SZ_D } +#define O_Gq { OP_G, SZ_Q } +#define O_Gv { OP_G, SZ_V } +#define O_Gw { OP_G, SZ_W } +#define O_Gy { OP_G, SZ_Y } +#define O_Gz { OP_G, SZ_Z } +#define O_H { OP_H, SZ_X } +#define O_Hqq { OP_H, SZ_QQ } +#define O_Hx { OP_H, SZ_X } +#define O_I1 { OP_I1, SZ_NA } +#define O_I3 { OP_I3, SZ_NA } +#define O_Ib { OP_I, SZ_B } +#define O_Iv { OP_I, SZ_V } +#define O_Iw { OP_I, SZ_W } +#define O_Iz { OP_I, SZ_Z } +#define O_Jb { OP_J, SZ_B } +#define O_Jv { OP_J, SZ_V } +#define O_Jz { OP_J, SZ_Z } +#define O_L { OP_L, SZ_O } +#define O_Lx { OP_L, SZ_X } +#define O_M { OP_M, SZ_NA } +#define O_Mb { OP_M, SZ_B } +#define O_MbRd { OP_MR, SZ_BD } +#define O_MbRv { OP_MR, SZ_BV } +#define O_Md { OP_M, SZ_D } +#define O_MdRy { OP_MR, SZ_DY } +#define O_MdU { OP_MU, SZ_DO } +#define O_Mdq { OP_M, SZ_DQ } +#define O_Mo { OP_M, SZ_O } +#define O_Mq { OP_M, SZ_Q } +#define O_MqU { OP_MU, SZ_QO } +#define O_Ms { OP_M, SZ_W } +#define O_Mt { OP_M, SZ_T } +#define O_Mv { OP_M, SZ_V } +#define O_Mw { OP_M, SZ_W } +#define O_MwRd { OP_MR, SZ_WD } +#define O_MwRv { OP_MR, SZ_WV } +#define O_MwRy { OP_MR, SZ_WY } +#define O_MwU { OP_MU, SZ_WO } +#define O_N { OP_N, SZ_Q } +#define O_NONE { OP_NONE, SZ_NA } +#define O_Ob { OP_O, SZ_B } +#define O_Ov { OP_O, SZ_V } +#define O_Ow { OP_O, SZ_W } +#define O_P { OP_P, SZ_Q } +#define O_Q { OP_Q, SZ_Q } +#define O_R { OP_R, SZ_RDQ } +#define O_R0b { OP_R0, SZ_B } +#define O_R0v { OP_R0, SZ_V } +#define O_R0w { OP_R0, SZ_W } +#define O_R0y { OP_R0, SZ_Y } +#define O_R0z { OP_R0, SZ_Z } +#define O_R1b { OP_R1, SZ_B } +#define O_R1v { OP_R1, SZ_V } +#define O_R1w { OP_R1, SZ_W } +#define O_R1y { OP_R1, SZ_Y } +#define O_R1z { OP_R1, SZ_Z } +#define O_R2b { OP_R2, SZ_B } +#define O_R2v { OP_R2, SZ_V } +#define O_R2w { OP_R2, SZ_W } +#define O_R2y { OP_R2, SZ_Y } +#define O_R2z { OP_R2, SZ_Z } +#define O_R3b { OP_R3, SZ_B } +#define O_R3v { OP_R3, SZ_V } +#define O_R3w { OP_R3, SZ_W } +#define O_R3y { OP_R3, SZ_Y } +#define O_R3z { OP_R3, SZ_Z } +#define O_R4b { OP_R4, SZ_B } +#define O_R4v { OP_R4, SZ_V } +#define O_R4w { OP_R4, SZ_W } +#define O_R4y { OP_R4, SZ_Y } +#define O_R4z { OP_R4, SZ_Z } +#define O_R5b { OP_R5, SZ_B } +#define O_R5v { OP_R5, SZ_V } +#define O_R5w { OP_R5, SZ_W } +#define O_R5y { OP_R5, SZ_Y } +#define O_R5z { OP_R5, SZ_Z } +#define O_R6b { OP_R6, SZ_B } +#define O_R6v { OP_R6, SZ_V } +#define O_R6w { OP_R6, SZ_W } +#define O_R6y { OP_R6, SZ_Y } +#define O_R6z { OP_R6, SZ_Z } +#define O_R7b { OP_R7, SZ_B } +#define O_R7v { OP_R7, SZ_V } +#define O_R7w { OP_R7, SZ_W } +#define O_R7y { OP_R7, SZ_Y } +#define O_R7z { OP_R7, SZ_Z } +#define O_S { OP_S, SZ_W } +#define O_SS { OP_SS, SZ_NA } +#define O_ST0 { OP_ST0, SZ_NA } +#define O_ST1 { OP_ST1, SZ_NA } +#define O_ST2 { OP_ST2, SZ_NA } +#define O_ST3 { OP_ST3, SZ_NA } +#define O_ST4 { OP_ST4, SZ_NA } +#define O_ST5 { OP_ST5, SZ_NA } +#define O_ST6 { OP_ST6, SZ_NA } +#define O_ST7 { OP_ST7, SZ_NA } +#define O_U { OP_U, SZ_O } +#define O_Ux { OP_U, SZ_X } +#define O_V { OP_V, SZ_DQ } +#define O_Vdq { OP_V, SZ_DQ } +#define O_Vqq { OP_V, SZ_QQ } +#define O_Vsd { OP_V, SZ_Q } +#define O_Vx { OP_V, SZ_X } +#define O_W { OP_W, SZ_DQ } +#define O_Wdq { OP_W, SZ_DQ } +#define O_Wqq { OP_W, SZ_QQ } +#define O_Wsd { OP_W, SZ_Q } +#define O_Wx { OP_W, SZ_X } +#define O_eAX { OP_eAX, SZ_Z } +#define O_eCX { OP_eCX, SZ_Z } +#define O_eDX { OP_eDX, SZ_Z } +#define O_rAX { OP_rAX, SZ_V } +#define O_rCX { OP_rCX, SZ_V } +#define O_rDX { OP_rDX, SZ_V } +#define O_sIb { OP_sI, SZ_B } +#define O_sIv { OP_sI, SZ_V } +#define O_sIz { OP_sI, SZ_Z } + +struct ud_itab_entry ud_itab[] = { + /* 0000 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0001 */ { UD_Iaaa, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0002 */ { UD_Iaad, O_Ib, O_NONE, O_NONE, O_NONE, P_none }, + /* 0003 */ { UD_Iaam, O_Ib, O_NONE, O_NONE, O_NONE, P_none }, + /* 0004 */ { UD_Iaas, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0005 */ { UD_Iadc, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0006 */ { UD_Iadc, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0007 */ { UD_Iadc, O_Gb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0008 */ { UD_Iadc, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0009 */ { UD_Iadc, O_AL, O_Ib, O_NONE, O_NONE, P_none }, + /* 0010 */ { UD_Iadc, O_rAX, O_sIz, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0011 */ { UD_Iadc, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0012 */ { UD_Iadc, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 0013 */ { UD_Iadc, O_Ev, O_sIz, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0014 */ { UD_Iadc, O_Ev, O_sIb, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0015 */ { UD_Iadd, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0016 */ { UD_Iadd, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0017 */ { UD_Iadd, O_Gb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0018 */ { UD_Iadd, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0019 */ { UD_Iadd, O_AL, O_Ib, O_NONE, O_NONE, P_none }, + /* 0020 */ { UD_Iadd, O_rAX, O_sIz, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0021 */ { UD_Iadd, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0022 */ { UD_Iadd, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 0023 */ { UD_Iadd, O_Ev, O_sIz, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0024 */ { UD_Iadd, O_Ev, O_sIb, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0025 */ { UD_Iaddpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0026 */ { UD_Ivaddpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0027 */ { UD_Iaddps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0028 */ { UD_Ivaddps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0029 */ { UD_Iaddsd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0030 */ { UD_Ivaddsd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0031 */ { UD_Iaddss, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0032 */ { UD_Ivaddss, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0033 */ { UD_Iaddsubpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0034 */ { UD_Ivaddsubpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0035 */ { UD_Iaddsubps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0036 */ { UD_Ivaddsubps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0037 */ { UD_Iaesdec, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0038 */ { UD_Ivaesdec, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0039 */ { UD_Iaesdeclast, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0040 */ { UD_Ivaesdeclast, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0041 */ { UD_Iaesenc, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0042 */ { UD_Ivaesenc, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0043 */ { UD_Iaesenclast, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0044 */ { UD_Ivaesenclast, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0045 */ { UD_Iaesimc, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0046 */ { UD_Ivaesimc, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0047 */ { UD_Iaeskeygenassist, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0048 */ { UD_Ivaeskeygenassist, O_Vx, O_Wx, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0049 */ { UD_Iand, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0050 */ { UD_Iand, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0051 */ { UD_Iand, O_Gb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0052 */ { UD_Iand, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0053 */ { UD_Iand, O_AL, O_Ib, O_NONE, O_NONE, P_none }, + /* 0054 */ { UD_Iand, O_rAX, O_sIz, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0055 */ { UD_Iand, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0056 */ { UD_Iand, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 0057 */ { UD_Iand, O_Ev, O_sIz, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0058 */ { UD_Iand, O_Ev, O_sIb, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0059 */ { UD_Iandpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0060 */ { UD_Ivandpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0061 */ { UD_Iandps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0062 */ { UD_Ivandps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0063 */ { UD_Iandnpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0064 */ { UD_Ivandnpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0065 */ { UD_Iandnps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0066 */ { UD_Ivandnps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0067 */ { UD_Iarpl, O_Ew, O_Gw, O_NONE, O_NONE, P_aso }, + /* 0068 */ { UD_Imovsxd, O_Gq, O_Ed, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexx|P_rexr|P_rexb }, + /* 0069 */ { UD_Icall, O_Ev, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0070 */ { UD_Icall, O_Eq, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 0071 */ { UD_Icall, O_Fv, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0072 */ { UD_Icall, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0073 */ { UD_Icall, O_Av, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0074 */ { UD_Icbw, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0075 */ { UD_Icwde, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0076 */ { UD_Icdqe, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0077 */ { UD_Iclc, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0078 */ { UD_Icld, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0079 */ { UD_Iclflush, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0080 */ { UD_Iclgi, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0081 */ { UD_Icli, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0082 */ { UD_Iclts, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0083 */ { UD_Icmc, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0084 */ { UD_Icmovo, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0085 */ { UD_Icmovno, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0086 */ { UD_Icmovb, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0087 */ { UD_Icmovae, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0088 */ { UD_Icmovz, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0089 */ { UD_Icmovnz, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0090 */ { UD_Icmovbe, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0091 */ { UD_Icmova, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0092 */ { UD_Icmovs, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0093 */ { UD_Icmovns, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0094 */ { UD_Icmovp, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0095 */ { UD_Icmovnp, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0096 */ { UD_Icmovl, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0097 */ { UD_Icmovge, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0098 */ { UD_Icmovle, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0099 */ { UD_Icmovg, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0100 */ { UD_Icmp, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0101 */ { UD_Icmp, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0102 */ { UD_Icmp, O_Gb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0103 */ { UD_Icmp, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0104 */ { UD_Icmp, O_AL, O_Ib, O_NONE, O_NONE, P_none }, + /* 0105 */ { UD_Icmp, O_rAX, O_sIz, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0106 */ { UD_Icmp, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0107 */ { UD_Icmp, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 0108 */ { UD_Icmp, O_Ev, O_sIz, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0109 */ { UD_Icmp, O_Ev, O_sIb, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0110 */ { UD_Icmppd, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0111 */ { UD_Ivcmppd, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0112 */ { UD_Icmpps, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0113 */ { UD_Ivcmpps, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0114 */ { UD_Icmpsb, O_NONE, O_NONE, O_NONE, O_NONE, P_strz|P_seg }, + /* 0115 */ { UD_Icmpsw, O_NONE, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw|P_seg }, + /* 0116 */ { UD_Icmpsd, O_NONE, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw|P_seg }, + /* 0117 */ { UD_Icmpsd, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0118 */ { UD_Ivcmpsd, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0119 */ { UD_Icmpsq, O_NONE, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw|P_seg }, + /* 0120 */ { UD_Icmpss, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0121 */ { UD_Ivcmpss, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0122 */ { UD_Icmpxchg, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0123 */ { UD_Icmpxchg, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0124 */ { UD_Icmpxchg8b, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0125 */ { UD_Icmpxchg8b, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0126 */ { UD_Icmpxchg16b, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0127 */ { UD_Icomisd, O_Vsd, O_Wsd, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0128 */ { UD_Ivcomisd, O_Vsd, O_Wsd, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0129 */ { UD_Icomiss, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0130 */ { UD_Ivcomiss, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0131 */ { UD_Icpuid, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0132 */ { UD_Icvtdq2pd, O_V, O_Wdq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0133 */ { UD_Ivcvtdq2pd, O_Vx, O_Wdq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0134 */ { UD_Icvtdq2ps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0135 */ { UD_Ivcvtdq2ps, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0136 */ { UD_Icvtpd2dq, O_Vdq, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0137 */ { UD_Ivcvtpd2dq, O_Vdq, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0138 */ { UD_Icvtpd2pi, O_P, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0139 */ { UD_Icvtpd2ps, O_Vdq, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0140 */ { UD_Ivcvtpd2ps, O_Vdq, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0141 */ { UD_Icvtpi2ps, O_V, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0142 */ { UD_Icvtpi2pd, O_V, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0143 */ { UD_Icvtps2dq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0144 */ { UD_Ivcvtps2dq, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0145 */ { UD_Icvtps2pd, O_V, O_Wdq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0146 */ { UD_Ivcvtps2pd, O_Vx, O_Wdq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0147 */ { UD_Icvtps2pi, O_P, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0148 */ { UD_Icvtsd2si, O_Gy, O_MqU, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0149 */ { UD_Ivcvtsd2si, O_Gy, O_MqU, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0150 */ { UD_Icvtsd2ss, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0151 */ { UD_Ivcvtsd2ss, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0152 */ { UD_Icvtsi2sd, O_V, O_Ey, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0153 */ { UD_Ivcvtsi2sd, O_Vx, O_Hx, O_Ey, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0154 */ { UD_Icvtsi2ss, O_V, O_Ey, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0155 */ { UD_Ivcvtsi2ss, O_Vx, O_Hx, O_Ey, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0156 */ { UD_Icvtss2sd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0157 */ { UD_Ivcvtss2sd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0158 */ { UD_Icvtss2si, O_Gy, O_MdU, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0159 */ { UD_Ivcvtss2si, O_Gy, O_MdU, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0160 */ { UD_Icvttpd2dq, O_Vdq, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0161 */ { UD_Ivcvttpd2dq, O_Vdq, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0162 */ { UD_Icvttpd2pi, O_P, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0163 */ { UD_Icvttps2dq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0164 */ { UD_Ivcvttps2dq, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0165 */ { UD_Icvttps2pi, O_P, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0166 */ { UD_Icvttsd2si, O_Gy, O_MqU, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0167 */ { UD_Ivcvttsd2si, O_Gy, O_MqU, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0168 */ { UD_Icvttss2si, O_Gy, O_MdU, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0169 */ { UD_Ivcvttss2si, O_Gy, O_MdU, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0170 */ { UD_Icwd, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0171 */ { UD_Icdq, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0172 */ { UD_Icqo, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0173 */ { UD_Idaa, O_NONE, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 0174 */ { UD_Idas, O_NONE, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 0175 */ { UD_Idec, O_R0z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0176 */ { UD_Idec, O_R1z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0177 */ { UD_Idec, O_R2z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0178 */ { UD_Idec, O_R3z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0179 */ { UD_Idec, O_R4z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0180 */ { UD_Idec, O_R5z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0181 */ { UD_Idec, O_R6z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0182 */ { UD_Idec, O_R7z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0183 */ { UD_Idec, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0184 */ { UD_Idec, O_Ev, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0185 */ { UD_Idiv, O_Ev, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0186 */ { UD_Idiv, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0187 */ { UD_Idivpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0188 */ { UD_Ivdivpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0189 */ { UD_Idivps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0190 */ { UD_Ivdivps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0191 */ { UD_Idivsd, O_V, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0192 */ { UD_Ivdivsd, O_Vx, O_Hx, O_MqU, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0193 */ { UD_Idivss, O_V, O_MdU, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0194 */ { UD_Ivdivss, O_Vx, O_Hx, O_MdU, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0195 */ { UD_Idppd, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0196 */ { UD_Ivdppd, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0197 */ { UD_Idpps, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0198 */ { UD_Ivdpps, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0199 */ { UD_Iemms, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0200 */ { UD_Ienter, O_Iw, O_Ib, O_NONE, O_NONE, P_def64 }, + /* 0201 */ { UD_Iextractps, O_MdRy, O_V, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0202 */ { UD_Ivextractps, O_MdRy, O_Vx, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0203 */ { UD_If2xm1, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0204 */ { UD_Ifabs, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0205 */ { UD_Ifadd, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0206 */ { UD_Ifadd, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0207 */ { UD_Ifadd, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0208 */ { UD_Ifadd, O_ST1, O_ST0, O_NONE, O_NONE, P_none }, + /* 0209 */ { UD_Ifadd, O_ST2, O_ST0, O_NONE, O_NONE, P_none }, + /* 0210 */ { UD_Ifadd, O_ST3, O_ST0, O_NONE, O_NONE, P_none }, + /* 0211 */ { UD_Ifadd, O_ST4, O_ST0, O_NONE, O_NONE, P_none }, + /* 0212 */ { UD_Ifadd, O_ST5, O_ST0, O_NONE, O_NONE, P_none }, + /* 0213 */ { UD_Ifadd, O_ST6, O_ST0, O_NONE, O_NONE, P_none }, + /* 0214 */ { UD_Ifadd, O_ST7, O_ST0, O_NONE, O_NONE, P_none }, + /* 0215 */ { UD_Ifadd, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0216 */ { UD_Ifadd, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0217 */ { UD_Ifadd, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0218 */ { UD_Ifadd, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0219 */ { UD_Ifadd, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0220 */ { UD_Ifadd, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0221 */ { UD_Ifadd, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0222 */ { UD_Ifadd, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0223 */ { UD_Ifaddp, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0224 */ { UD_Ifaddp, O_ST1, O_ST0, O_NONE, O_NONE, P_none }, + /* 0225 */ { UD_Ifaddp, O_ST2, O_ST0, O_NONE, O_NONE, P_none }, + /* 0226 */ { UD_Ifaddp, O_ST3, O_ST0, O_NONE, O_NONE, P_none }, + /* 0227 */ { UD_Ifaddp, O_ST4, O_ST0, O_NONE, O_NONE, P_none }, + /* 0228 */ { UD_Ifaddp, O_ST5, O_ST0, O_NONE, O_NONE, P_none }, + /* 0229 */ { UD_Ifaddp, O_ST6, O_ST0, O_NONE, O_NONE, P_none }, + /* 0230 */ { UD_Ifaddp, O_ST7, O_ST0, O_NONE, O_NONE, P_none }, + /* 0231 */ { UD_Ifbld, O_Mt, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0232 */ { UD_Ifbstp, O_Mt, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0233 */ { UD_Ifchs, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0234 */ { UD_Ifclex, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0235 */ { UD_Ifcmovb, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0236 */ { UD_Ifcmovb, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0237 */ { UD_Ifcmovb, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0238 */ { UD_Ifcmovb, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0239 */ { UD_Ifcmovb, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0240 */ { UD_Ifcmovb, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0241 */ { UD_Ifcmovb, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0242 */ { UD_Ifcmovb, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0243 */ { UD_Ifcmove, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0244 */ { UD_Ifcmove, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0245 */ { UD_Ifcmove, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0246 */ { UD_Ifcmove, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0247 */ { UD_Ifcmove, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0248 */ { UD_Ifcmove, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0249 */ { UD_Ifcmove, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0250 */ { UD_Ifcmove, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0251 */ { UD_Ifcmovbe, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0252 */ { UD_Ifcmovbe, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0253 */ { UD_Ifcmovbe, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0254 */ { UD_Ifcmovbe, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0255 */ { UD_Ifcmovbe, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0256 */ { UD_Ifcmovbe, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0257 */ { UD_Ifcmovbe, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0258 */ { UD_Ifcmovbe, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0259 */ { UD_Ifcmovu, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0260 */ { UD_Ifcmovu, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0261 */ { UD_Ifcmovu, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0262 */ { UD_Ifcmovu, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0263 */ { UD_Ifcmovu, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0264 */ { UD_Ifcmovu, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0265 */ { UD_Ifcmovu, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0266 */ { UD_Ifcmovu, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0267 */ { UD_Ifcmovnb, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0268 */ { UD_Ifcmovnb, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0269 */ { UD_Ifcmovnb, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0270 */ { UD_Ifcmovnb, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0271 */ { UD_Ifcmovnb, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0272 */ { UD_Ifcmovnb, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0273 */ { UD_Ifcmovnb, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0274 */ { UD_Ifcmovnb, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0275 */ { UD_Ifcmovne, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0276 */ { UD_Ifcmovne, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0277 */ { UD_Ifcmovne, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0278 */ { UD_Ifcmovne, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0279 */ { UD_Ifcmovne, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0280 */ { UD_Ifcmovne, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0281 */ { UD_Ifcmovne, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0282 */ { UD_Ifcmovne, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0283 */ { UD_Ifcmovnbe, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0284 */ { UD_Ifcmovnbe, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0285 */ { UD_Ifcmovnbe, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0286 */ { UD_Ifcmovnbe, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0287 */ { UD_Ifcmovnbe, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0288 */ { UD_Ifcmovnbe, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0289 */ { UD_Ifcmovnbe, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0290 */ { UD_Ifcmovnbe, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0291 */ { UD_Ifcmovnu, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0292 */ { UD_Ifcmovnu, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0293 */ { UD_Ifcmovnu, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0294 */ { UD_Ifcmovnu, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0295 */ { UD_Ifcmovnu, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0296 */ { UD_Ifcmovnu, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0297 */ { UD_Ifcmovnu, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0298 */ { UD_Ifcmovnu, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0299 */ { UD_Ifucomi, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0300 */ { UD_Ifucomi, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0301 */ { UD_Ifucomi, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0302 */ { UD_Ifucomi, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0303 */ { UD_Ifucomi, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0304 */ { UD_Ifucomi, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0305 */ { UD_Ifucomi, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0306 */ { UD_Ifucomi, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0307 */ { UD_Ifcom, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0308 */ { UD_Ifcom, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0309 */ { UD_Ifcom, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0310 */ { UD_Ifcom, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0311 */ { UD_Ifcom, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0312 */ { UD_Ifcom, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0313 */ { UD_Ifcom, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0314 */ { UD_Ifcom, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0315 */ { UD_Ifcom, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0316 */ { UD_Ifcom, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0317 */ { UD_Ifcom2, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0318 */ { UD_Ifcom2, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0319 */ { UD_Ifcom2, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0320 */ { UD_Ifcom2, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0321 */ { UD_Ifcom2, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0322 */ { UD_Ifcom2, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0323 */ { UD_Ifcom2, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0324 */ { UD_Ifcom2, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0325 */ { UD_Ifcomp3, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0326 */ { UD_Ifcomp3, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0327 */ { UD_Ifcomp3, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0328 */ { UD_Ifcomp3, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0329 */ { UD_Ifcomp3, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0330 */ { UD_Ifcomp3, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0331 */ { UD_Ifcomp3, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0332 */ { UD_Ifcomp3, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0333 */ { UD_Ifcomi, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0334 */ { UD_Ifcomi, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0335 */ { UD_Ifcomi, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0336 */ { UD_Ifcomi, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0337 */ { UD_Ifcomi, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0338 */ { UD_Ifcomi, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0339 */ { UD_Ifcomi, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0340 */ { UD_Ifcomi, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0341 */ { UD_Ifucomip, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0342 */ { UD_Ifucomip, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0343 */ { UD_Ifucomip, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0344 */ { UD_Ifucomip, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0345 */ { UD_Ifucomip, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0346 */ { UD_Ifucomip, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0347 */ { UD_Ifucomip, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0348 */ { UD_Ifucomip, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0349 */ { UD_Ifcomip, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0350 */ { UD_Ifcomip, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0351 */ { UD_Ifcomip, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0352 */ { UD_Ifcomip, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0353 */ { UD_Ifcomip, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0354 */ { UD_Ifcomip, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0355 */ { UD_Ifcomip, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0356 */ { UD_Ifcomip, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0357 */ { UD_Ifcomp, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0358 */ { UD_Ifcomp, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0359 */ { UD_Ifcomp, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0360 */ { UD_Ifcomp, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0361 */ { UD_Ifcomp, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0362 */ { UD_Ifcomp, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0363 */ { UD_Ifcomp, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0364 */ { UD_Ifcomp, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0365 */ { UD_Ifcomp, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0366 */ { UD_Ifcomp, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0367 */ { UD_Ifcomp5, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0368 */ { UD_Ifcomp5, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0369 */ { UD_Ifcomp5, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0370 */ { UD_Ifcomp5, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0371 */ { UD_Ifcomp5, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0372 */ { UD_Ifcomp5, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0373 */ { UD_Ifcomp5, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0374 */ { UD_Ifcomp5, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0375 */ { UD_Ifcompp, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0376 */ { UD_Ifcos, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0377 */ { UD_Ifdecstp, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0378 */ { UD_Ifdiv, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0379 */ { UD_Ifdiv, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0380 */ { UD_Ifdiv, O_ST1, O_ST0, O_NONE, O_NONE, P_none }, + /* 0381 */ { UD_Ifdiv, O_ST2, O_ST0, O_NONE, O_NONE, P_none }, + /* 0382 */ { UD_Ifdiv, O_ST3, O_ST0, O_NONE, O_NONE, P_none }, + /* 0383 */ { UD_Ifdiv, O_ST4, O_ST0, O_NONE, O_NONE, P_none }, + /* 0384 */ { UD_Ifdiv, O_ST5, O_ST0, O_NONE, O_NONE, P_none }, + /* 0385 */ { UD_Ifdiv, O_ST6, O_ST0, O_NONE, O_NONE, P_none }, + /* 0386 */ { UD_Ifdiv, O_ST7, O_ST0, O_NONE, O_NONE, P_none }, + /* 0387 */ { UD_Ifdiv, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0388 */ { UD_Ifdiv, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0389 */ { UD_Ifdiv, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0390 */ { UD_Ifdiv, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0391 */ { UD_Ifdiv, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0392 */ { UD_Ifdiv, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0393 */ { UD_Ifdiv, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0394 */ { UD_Ifdiv, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0395 */ { UD_Ifdiv, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0396 */ { UD_Ifdivp, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0397 */ { UD_Ifdivp, O_ST1, O_ST0, O_NONE, O_NONE, P_none }, + /* 0398 */ { UD_Ifdivp, O_ST2, O_ST0, O_NONE, O_NONE, P_none }, + /* 0399 */ { UD_Ifdivp, O_ST3, O_ST0, O_NONE, O_NONE, P_none }, + /* 0400 */ { UD_Ifdivp, O_ST4, O_ST0, O_NONE, O_NONE, P_none }, + /* 0401 */ { UD_Ifdivp, O_ST5, O_ST0, O_NONE, O_NONE, P_none }, + /* 0402 */ { UD_Ifdivp, O_ST6, O_ST0, O_NONE, O_NONE, P_none }, + /* 0403 */ { UD_Ifdivp, O_ST7, O_ST0, O_NONE, O_NONE, P_none }, + /* 0404 */ { UD_Ifdivr, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0405 */ { UD_Ifdivr, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0406 */ { UD_Ifdivr, O_ST1, O_ST0, O_NONE, O_NONE, P_none }, + /* 0407 */ { UD_Ifdivr, O_ST2, O_ST0, O_NONE, O_NONE, P_none }, + /* 0408 */ { UD_Ifdivr, O_ST3, O_ST0, O_NONE, O_NONE, P_none }, + /* 0409 */ { UD_Ifdivr, O_ST4, O_ST0, O_NONE, O_NONE, P_none }, + /* 0410 */ { UD_Ifdivr, O_ST5, O_ST0, O_NONE, O_NONE, P_none }, + /* 0411 */ { UD_Ifdivr, O_ST6, O_ST0, O_NONE, O_NONE, P_none }, + /* 0412 */ { UD_Ifdivr, O_ST7, O_ST0, O_NONE, O_NONE, P_none }, + /* 0413 */ { UD_Ifdivr, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0414 */ { UD_Ifdivr, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0415 */ { UD_Ifdivr, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0416 */ { UD_Ifdivr, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0417 */ { UD_Ifdivr, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0418 */ { UD_Ifdivr, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0419 */ { UD_Ifdivr, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0420 */ { UD_Ifdivr, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0421 */ { UD_Ifdivr, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0422 */ { UD_Ifdivrp, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0423 */ { UD_Ifdivrp, O_ST1, O_ST0, O_NONE, O_NONE, P_none }, + /* 0424 */ { UD_Ifdivrp, O_ST2, O_ST0, O_NONE, O_NONE, P_none }, + /* 0425 */ { UD_Ifdivrp, O_ST3, O_ST0, O_NONE, O_NONE, P_none }, + /* 0426 */ { UD_Ifdivrp, O_ST4, O_ST0, O_NONE, O_NONE, P_none }, + /* 0427 */ { UD_Ifdivrp, O_ST5, O_ST0, O_NONE, O_NONE, P_none }, + /* 0428 */ { UD_Ifdivrp, O_ST6, O_ST0, O_NONE, O_NONE, P_none }, + /* 0429 */ { UD_Ifdivrp, O_ST7, O_ST0, O_NONE, O_NONE, P_none }, + /* 0430 */ { UD_Ifemms, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0431 */ { UD_Iffree, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0432 */ { UD_Iffree, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0433 */ { UD_Iffree, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0434 */ { UD_Iffree, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0435 */ { UD_Iffree, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0436 */ { UD_Iffree, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0437 */ { UD_Iffree, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0438 */ { UD_Iffree, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0439 */ { UD_Iffreep, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0440 */ { UD_Iffreep, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0441 */ { UD_Iffreep, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0442 */ { UD_Iffreep, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0443 */ { UD_Iffreep, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0444 */ { UD_Iffreep, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0445 */ { UD_Iffreep, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0446 */ { UD_Iffreep, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0447 */ { UD_Ificom, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0448 */ { UD_Ificom, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0449 */ { UD_Ificomp, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0450 */ { UD_Ificomp, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0451 */ { UD_Ifild, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0452 */ { UD_Ifild, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0453 */ { UD_Ifild, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0454 */ { UD_Ifincstp, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0455 */ { UD_Ifninit, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0456 */ { UD_Ifiadd, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0457 */ { UD_Ifiadd, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0458 */ { UD_Ifidivr, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0459 */ { UD_Ifidivr, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0460 */ { UD_Ifidiv, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0461 */ { UD_Ifidiv, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0462 */ { UD_Ifisub, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0463 */ { UD_Ifisub, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0464 */ { UD_Ifisubr, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0465 */ { UD_Ifisubr, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0466 */ { UD_Ifist, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0467 */ { UD_Ifist, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0468 */ { UD_Ifistp, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0469 */ { UD_Ifistp, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0470 */ { UD_Ifistp, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0471 */ { UD_Ifisttp, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0472 */ { UD_Ifisttp, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0473 */ { UD_Ifisttp, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0474 */ { UD_Ifld, O_Mt, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0475 */ { UD_Ifld, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0476 */ { UD_Ifld, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0477 */ { UD_Ifld, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0478 */ { UD_Ifld, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0479 */ { UD_Ifld, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0480 */ { UD_Ifld, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0481 */ { UD_Ifld, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0482 */ { UD_Ifld, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0483 */ { UD_Ifld, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0484 */ { UD_Ifld, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0485 */ { UD_Ifld1, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0486 */ { UD_Ifldl2t, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0487 */ { UD_Ifldl2e, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0488 */ { UD_Ifldpi, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0489 */ { UD_Ifldlg2, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0490 */ { UD_Ifldln2, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0491 */ { UD_Ifldz, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0492 */ { UD_Ifldcw, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0493 */ { UD_Ifldenv, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0494 */ { UD_Ifmul, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0495 */ { UD_Ifmul, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0496 */ { UD_Ifmul, O_ST1, O_ST0, O_NONE, O_NONE, P_none }, + /* 0497 */ { UD_Ifmul, O_ST2, O_ST0, O_NONE, O_NONE, P_none }, + /* 0498 */ { UD_Ifmul, O_ST3, O_ST0, O_NONE, O_NONE, P_none }, + /* 0499 */ { UD_Ifmul, O_ST4, O_ST0, O_NONE, O_NONE, P_none }, + /* 0500 */ { UD_Ifmul, O_ST5, O_ST0, O_NONE, O_NONE, P_none }, + /* 0501 */ { UD_Ifmul, O_ST6, O_ST0, O_NONE, O_NONE, P_none }, + /* 0502 */ { UD_Ifmul, O_ST7, O_ST0, O_NONE, O_NONE, P_none }, + /* 0503 */ { UD_Ifmul, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0504 */ { UD_Ifmul, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0505 */ { UD_Ifmul, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0506 */ { UD_Ifmul, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0507 */ { UD_Ifmul, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0508 */ { UD_Ifmul, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0509 */ { UD_Ifmul, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0510 */ { UD_Ifmul, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0511 */ { UD_Ifmul, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0512 */ { UD_Ifmulp, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0513 */ { UD_Ifmulp, O_ST1, O_ST0, O_NONE, O_NONE, P_none }, + /* 0514 */ { UD_Ifmulp, O_ST2, O_ST0, O_NONE, O_NONE, P_none }, + /* 0515 */ { UD_Ifmulp, O_ST3, O_ST0, O_NONE, O_NONE, P_none }, + /* 0516 */ { UD_Ifmulp, O_ST4, O_ST0, O_NONE, O_NONE, P_none }, + /* 0517 */ { UD_Ifmulp, O_ST5, O_ST0, O_NONE, O_NONE, P_none }, + /* 0518 */ { UD_Ifmulp, O_ST6, O_ST0, O_NONE, O_NONE, P_none }, + /* 0519 */ { UD_Ifmulp, O_ST7, O_ST0, O_NONE, O_NONE, P_none }, + /* 0520 */ { UD_Ifimul, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0521 */ { UD_Ifimul, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0522 */ { UD_Ifnop, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0523 */ { UD_Ifndisi, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0524 */ { UD_Ifneni, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0525 */ { UD_Ifnsetpm, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0526 */ { UD_Ifpatan, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0527 */ { UD_Ifprem, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0528 */ { UD_Ifprem1, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0529 */ { UD_Ifptan, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0530 */ { UD_Ifrndint, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0531 */ { UD_Ifrstor, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0532 */ { UD_Ifrstpm, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0533 */ { UD_Ifnsave, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0534 */ { UD_Ifscale, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0535 */ { UD_Ifsin, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0536 */ { UD_Ifsincos, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0537 */ { UD_Ifsqrt, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0538 */ { UD_Ifstp, O_Mt, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0539 */ { UD_Ifstp, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0540 */ { UD_Ifstp, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0541 */ { UD_Ifstp, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0542 */ { UD_Ifstp, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0543 */ { UD_Ifstp, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0544 */ { UD_Ifstp, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0545 */ { UD_Ifstp, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0546 */ { UD_Ifstp, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0547 */ { UD_Ifstp, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0548 */ { UD_Ifstp, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0549 */ { UD_Ifstp1, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0550 */ { UD_Ifstp1, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0551 */ { UD_Ifstp1, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0552 */ { UD_Ifstp1, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0553 */ { UD_Ifstp1, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0554 */ { UD_Ifstp1, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0555 */ { UD_Ifstp1, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0556 */ { UD_Ifstp1, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0557 */ { UD_Ifstp8, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0558 */ { UD_Ifstp8, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0559 */ { UD_Ifstp8, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0560 */ { UD_Ifstp8, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0561 */ { UD_Ifstp8, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0562 */ { UD_Ifstp8, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0563 */ { UD_Ifstp8, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0564 */ { UD_Ifstp8, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0565 */ { UD_Ifstp9, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0566 */ { UD_Ifstp9, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0567 */ { UD_Ifstp9, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0568 */ { UD_Ifstp9, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0569 */ { UD_Ifstp9, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0570 */ { UD_Ifstp9, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0571 */ { UD_Ifstp9, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0572 */ { UD_Ifstp9, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0573 */ { UD_Ifst, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0574 */ { UD_Ifst, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0575 */ { UD_Ifst, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0576 */ { UD_Ifst, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0577 */ { UD_Ifst, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0578 */ { UD_Ifst, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0579 */ { UD_Ifst, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0580 */ { UD_Ifst, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0581 */ { UD_Ifst, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0582 */ { UD_Ifst, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0583 */ { UD_Ifnstcw, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0584 */ { UD_Ifnstenv, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0585 */ { UD_Ifnstsw, O_Mw, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0586 */ { UD_Ifnstsw, O_AX, O_NONE, O_NONE, O_NONE, P_none }, + /* 0587 */ { UD_Ifsub, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0588 */ { UD_Ifsub, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0589 */ { UD_Ifsub, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0590 */ { UD_Ifsub, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0591 */ { UD_Ifsub, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0592 */ { UD_Ifsub, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0593 */ { UD_Ifsub, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0594 */ { UD_Ifsub, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0595 */ { UD_Ifsub, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0596 */ { UD_Ifsub, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0597 */ { UD_Ifsub, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0598 */ { UD_Ifsub, O_ST1, O_ST0, O_NONE, O_NONE, P_none }, + /* 0599 */ { UD_Ifsub, O_ST2, O_ST0, O_NONE, O_NONE, P_none }, + /* 0600 */ { UD_Ifsub, O_ST3, O_ST0, O_NONE, O_NONE, P_none }, + /* 0601 */ { UD_Ifsub, O_ST4, O_ST0, O_NONE, O_NONE, P_none }, + /* 0602 */ { UD_Ifsub, O_ST5, O_ST0, O_NONE, O_NONE, P_none }, + /* 0603 */ { UD_Ifsub, O_ST6, O_ST0, O_NONE, O_NONE, P_none }, + /* 0604 */ { UD_Ifsub, O_ST7, O_ST0, O_NONE, O_NONE, P_none }, + /* 0605 */ { UD_Ifsubp, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0606 */ { UD_Ifsubp, O_ST1, O_ST0, O_NONE, O_NONE, P_none }, + /* 0607 */ { UD_Ifsubp, O_ST2, O_ST0, O_NONE, O_NONE, P_none }, + /* 0608 */ { UD_Ifsubp, O_ST3, O_ST0, O_NONE, O_NONE, P_none }, + /* 0609 */ { UD_Ifsubp, O_ST4, O_ST0, O_NONE, O_NONE, P_none }, + /* 0610 */ { UD_Ifsubp, O_ST5, O_ST0, O_NONE, O_NONE, P_none }, + /* 0611 */ { UD_Ifsubp, O_ST6, O_ST0, O_NONE, O_NONE, P_none }, + /* 0612 */ { UD_Ifsubp, O_ST7, O_ST0, O_NONE, O_NONE, P_none }, + /* 0613 */ { UD_Ifsubr, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0614 */ { UD_Ifsubr, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0615 */ { UD_Ifsubr, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0616 */ { UD_Ifsubr, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0617 */ { UD_Ifsubr, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0618 */ { UD_Ifsubr, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0619 */ { UD_Ifsubr, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0620 */ { UD_Ifsubr, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0621 */ { UD_Ifsubr, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0622 */ { UD_Ifsubr, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0623 */ { UD_Ifsubr, O_ST1, O_ST0, O_NONE, O_NONE, P_none }, + /* 0624 */ { UD_Ifsubr, O_ST2, O_ST0, O_NONE, O_NONE, P_none }, + /* 0625 */ { UD_Ifsubr, O_ST3, O_ST0, O_NONE, O_NONE, P_none }, + /* 0626 */ { UD_Ifsubr, O_ST4, O_ST0, O_NONE, O_NONE, P_none }, + /* 0627 */ { UD_Ifsubr, O_ST5, O_ST0, O_NONE, O_NONE, P_none }, + /* 0628 */ { UD_Ifsubr, O_ST6, O_ST0, O_NONE, O_NONE, P_none }, + /* 0629 */ { UD_Ifsubr, O_ST7, O_ST0, O_NONE, O_NONE, P_none }, + /* 0630 */ { UD_Ifsubr, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0631 */ { UD_Ifsubrp, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0632 */ { UD_Ifsubrp, O_ST1, O_ST0, O_NONE, O_NONE, P_none }, + /* 0633 */ { UD_Ifsubrp, O_ST2, O_ST0, O_NONE, O_NONE, P_none }, + /* 0634 */ { UD_Ifsubrp, O_ST3, O_ST0, O_NONE, O_NONE, P_none }, + /* 0635 */ { UD_Ifsubrp, O_ST4, O_ST0, O_NONE, O_NONE, P_none }, + /* 0636 */ { UD_Ifsubrp, O_ST5, O_ST0, O_NONE, O_NONE, P_none }, + /* 0637 */ { UD_Ifsubrp, O_ST6, O_ST0, O_NONE, O_NONE, P_none }, + /* 0638 */ { UD_Ifsubrp, O_ST7, O_ST0, O_NONE, O_NONE, P_none }, + /* 0639 */ { UD_Iftst, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0640 */ { UD_Ifucom, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0641 */ { UD_Ifucom, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0642 */ { UD_Ifucom, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0643 */ { UD_Ifucom, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0644 */ { UD_Ifucom, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0645 */ { UD_Ifucom, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0646 */ { UD_Ifucom, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0647 */ { UD_Ifucom, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0648 */ { UD_Ifucomp, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0649 */ { UD_Ifucomp, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0650 */ { UD_Ifucomp, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0651 */ { UD_Ifucomp, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0652 */ { UD_Ifucomp, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0653 */ { UD_Ifucomp, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0654 */ { UD_Ifucomp, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0655 */ { UD_Ifucomp, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0656 */ { UD_Ifucompp, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0657 */ { UD_Ifxam, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0658 */ { UD_Ifxch, O_ST0, O_ST0, O_NONE, O_NONE, P_none }, + /* 0659 */ { UD_Ifxch, O_ST0, O_ST1, O_NONE, O_NONE, P_none }, + /* 0660 */ { UD_Ifxch, O_ST0, O_ST2, O_NONE, O_NONE, P_none }, + /* 0661 */ { UD_Ifxch, O_ST0, O_ST3, O_NONE, O_NONE, P_none }, + /* 0662 */ { UD_Ifxch, O_ST0, O_ST4, O_NONE, O_NONE, P_none }, + /* 0663 */ { UD_Ifxch, O_ST0, O_ST5, O_NONE, O_NONE, P_none }, + /* 0664 */ { UD_Ifxch, O_ST0, O_ST6, O_NONE, O_NONE, P_none }, + /* 0665 */ { UD_Ifxch, O_ST0, O_ST7, O_NONE, O_NONE, P_none }, + /* 0666 */ { UD_Ifxch4, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0667 */ { UD_Ifxch4, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0668 */ { UD_Ifxch4, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0669 */ { UD_Ifxch4, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0670 */ { UD_Ifxch4, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0671 */ { UD_Ifxch4, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0672 */ { UD_Ifxch4, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0673 */ { UD_Ifxch4, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0674 */ { UD_Ifxch7, O_ST0, O_NONE, O_NONE, O_NONE, P_none }, + /* 0675 */ { UD_Ifxch7, O_ST1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0676 */ { UD_Ifxch7, O_ST2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0677 */ { UD_Ifxch7, O_ST3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0678 */ { UD_Ifxch7, O_ST4, O_NONE, O_NONE, O_NONE, P_none }, + /* 0679 */ { UD_Ifxch7, O_ST5, O_NONE, O_NONE, O_NONE, P_none }, + /* 0680 */ { UD_Ifxch7, O_ST6, O_NONE, O_NONE, O_NONE, P_none }, + /* 0681 */ { UD_Ifxch7, O_ST7, O_NONE, O_NONE, O_NONE, P_none }, + /* 0682 */ { UD_Ifxrstor, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0683 */ { UD_Ifxsave, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0684 */ { UD_Ifxtract, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0685 */ { UD_Ifyl2x, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0686 */ { UD_Ifyl2xp1, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0687 */ { UD_Ihlt, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0688 */ { UD_Iidiv, O_Ev, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0689 */ { UD_Iidiv, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0690 */ { UD_Iin, O_AL, O_Ib, O_NONE, O_NONE, P_none }, + /* 0691 */ { UD_Iin, O_eAX, O_Ib, O_NONE, O_NONE, P_oso }, + /* 0692 */ { UD_Iin, O_AL, O_DX, O_NONE, O_NONE, P_none }, + /* 0693 */ { UD_Iin, O_eAX, O_DX, O_NONE, O_NONE, P_oso }, + /* 0694 */ { UD_Iimul, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0695 */ { UD_Iimul, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0696 */ { UD_Iimul, O_Ev, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0697 */ { UD_Iimul, O_Gv, O_Ev, O_Iz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0698 */ { UD_Iimul, O_Gv, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0699 */ { UD_Iinc, O_R0z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0700 */ { UD_Iinc, O_R1z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0701 */ { UD_Iinc, O_R2z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0702 */ { UD_Iinc, O_R3z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0703 */ { UD_Iinc, O_R4z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0704 */ { UD_Iinc, O_R5z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0705 */ { UD_Iinc, O_R6z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0706 */ { UD_Iinc, O_R7z, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0707 */ { UD_Iinc, O_Ev, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0708 */ { UD_Iinc, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0709 */ { UD_Iinsb, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg }, + /* 0710 */ { UD_Iinsw, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_oso|P_seg }, + /* 0711 */ { UD_Iinsd, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_oso|P_seg }, + /* 0712 */ { UD_Iint1, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0713 */ { UD_Iint3, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0714 */ { UD_Iint, O_Ib, O_NONE, O_NONE, O_NONE, P_none }, + /* 0715 */ { UD_Iinto, O_NONE, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 0716 */ { UD_Iinvd, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0717 */ { UD_Iinvept, O_Gd, O_Mo, O_NONE, O_NONE, P_none }, + /* 0718 */ { UD_Iinvept, O_Gq, O_Mo, O_NONE, O_NONE, P_none }, + /* 0719 */ { UD_Iinvlpg, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0720 */ { UD_Iinvlpga, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0721 */ { UD_Iinvvpid, O_Gd, O_Mo, O_NONE, O_NONE, P_none }, + /* 0722 */ { UD_Iinvvpid, O_Gq, O_Mo, O_NONE, O_NONE, P_none }, + /* 0723 */ { UD_Iiretw, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0724 */ { UD_Iiretd, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0725 */ { UD_Iiretq, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0726 */ { UD_Ijo, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0727 */ { UD_Ijo, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0728 */ { UD_Ijno, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0729 */ { UD_Ijno, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0730 */ { UD_Ijb, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0731 */ { UD_Ijb, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0732 */ { UD_Ijae, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0733 */ { UD_Ijae, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0734 */ { UD_Ijz, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0735 */ { UD_Ijz, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0736 */ { UD_Ijnz, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0737 */ { UD_Ijnz, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0738 */ { UD_Ijbe, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0739 */ { UD_Ijbe, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0740 */ { UD_Ija, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0741 */ { UD_Ija, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0742 */ { UD_Ijs, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0743 */ { UD_Ijs, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0744 */ { UD_Ijns, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0745 */ { UD_Ijns, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0746 */ { UD_Ijp, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0747 */ { UD_Ijp, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0748 */ { UD_Ijnp, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0749 */ { UD_Ijnp, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0750 */ { UD_Ijl, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0751 */ { UD_Ijl, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0752 */ { UD_Ijge, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0753 */ { UD_Ijge, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0754 */ { UD_Ijle, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0755 */ { UD_Ijle, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0756 */ { UD_Ijg, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0757 */ { UD_Ijg, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0758 */ { UD_Ijcxz, O_Jb, O_NONE, O_NONE, O_NONE, P_aso }, + /* 0759 */ { UD_Ijecxz, O_Jb, O_NONE, O_NONE, O_NONE, P_aso }, + /* 0760 */ { UD_Ijrcxz, O_Jb, O_NONE, O_NONE, O_NONE, P_aso }, + /* 0761 */ { UD_Ijmp, O_Ev, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 0762 */ { UD_Ijmp, O_Fv, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0763 */ { UD_Ijmp, O_Jz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0764 */ { UD_Ijmp, O_Av, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0765 */ { UD_Ijmp, O_Jb, O_NONE, O_NONE, O_NONE, P_def64 }, + /* 0766 */ { UD_Ilahf, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0767 */ { UD_Ilar, O_Gv, O_Ew, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0768 */ { UD_Ildmxcsr, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0769 */ { UD_Ilds, O_Gv, O_M, O_NONE, O_NONE, P_aso|P_oso }, + /* 0770 */ { UD_Ilea, O_Gv, O_M, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0771 */ { UD_Iles, O_Gv, O_M, O_NONE, O_NONE, P_aso|P_oso }, + /* 0772 */ { UD_Ilfs, O_Gz, O_M, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0773 */ { UD_Ilgs, O_Gz, O_M, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0774 */ { UD_Ilidt, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0775 */ { UD_Ilss, O_Gv, O_M, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0776 */ { UD_Ileave, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0777 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0778 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0779 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0780 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0781 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0782 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0783 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0784 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0785 */ { UD_Ilgdt, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0786 */ { UD_Illdt, O_Ew, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0787 */ { UD_Ilmsw, O_Ew, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0788 */ { UD_Ilmsw, O_Ew, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0789 */ { UD_Ilock, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0790 */ { UD_Ilodsb, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg }, + /* 0791 */ { UD_Ilodsw, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0792 */ { UD_Ilodsd, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0793 */ { UD_Ilodsq, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0794 */ { UD_Iloopne, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0795 */ { UD_Iloope, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0796 */ { UD_Iloop, O_Jb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0797 */ { UD_Ilsl, O_Gv, O_Ew, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0798 */ { UD_Iltr, O_Ew, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0799 */ { UD_Imaskmovq, O_P, O_N, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0800 */ { UD_Imaxpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0801 */ { UD_Ivmaxpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0802 */ { UD_Imaxps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0803 */ { UD_Ivmaxps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0804 */ { UD_Imaxsd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0805 */ { UD_Ivmaxsd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0806 */ { UD_Imaxss, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0807 */ { UD_Ivmaxss, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0808 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0809 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0810 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0811 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0812 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0813 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0814 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0815 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0816 */ { UD_Iminpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0817 */ { UD_Ivminpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0818 */ { UD_Iminps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0819 */ { UD_Ivminps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0820 */ { UD_Iminsd, O_V, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0821 */ { UD_Ivminsd, O_Vx, O_Hx, O_MqU, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0822 */ { UD_Iminss, O_V, O_MdU, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0823 */ { UD_Ivminss, O_Vx, O_Hx, O_MdU, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0824 */ { UD_Imonitor, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0825 */ { UD_Imontmul, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0826 */ { UD_Imov, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0827 */ { UD_Imov, O_Ev, O_sIz, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0828 */ { UD_Imov, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0829 */ { UD_Imov, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0830 */ { UD_Imov, O_Gb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0831 */ { UD_Imov, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0832 */ { UD_Imov, O_MwRv, O_S, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0833 */ { UD_Imov, O_S, O_MwRv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0834 */ { UD_Imov, O_AL, O_Ob, O_NONE, O_NONE, P_none }, + /* 0835 */ { UD_Imov, O_rAX, O_Ov, O_NONE, O_NONE, P_aso|P_oso|P_rexw }, + /* 0836 */ { UD_Imov, O_Ob, O_AL, O_NONE, O_NONE, P_none }, + /* 0837 */ { UD_Imov, O_Ov, O_rAX, O_NONE, O_NONE, P_aso|P_oso|P_rexw }, + /* 0838 */ { UD_Imov, O_R0b, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 0839 */ { UD_Imov, O_R1b, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 0840 */ { UD_Imov, O_R2b, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 0841 */ { UD_Imov, O_R3b, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 0842 */ { UD_Imov, O_R4b, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 0843 */ { UD_Imov, O_R5b, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 0844 */ { UD_Imov, O_R6b, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 0845 */ { UD_Imov, O_R7b, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 0846 */ { UD_Imov, O_R0v, O_Iv, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0847 */ { UD_Imov, O_R1v, O_Iv, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0848 */ { UD_Imov, O_R2v, O_Iv, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0849 */ { UD_Imov, O_R3v, O_Iv, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0850 */ { UD_Imov, O_R4v, O_Iv, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0851 */ { UD_Imov, O_R5v, O_Iv, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0852 */ { UD_Imov, O_R6v, O_Iv, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0853 */ { UD_Imov, O_R7v, O_Iv, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0854 */ { UD_Imov, O_R, O_C, O_NONE, O_NONE, P_rexr|P_rexw|P_rexb }, + /* 0855 */ { UD_Imov, O_R, O_D, O_NONE, O_NONE, P_rexr|P_rexw|P_rexb }, + /* 0856 */ { UD_Imov, O_C, O_R, O_NONE, O_NONE, P_rexr|P_rexw|P_rexb }, + /* 0857 */ { UD_Imov, O_D, O_R, O_NONE, O_NONE, P_rexr|P_rexw|P_rexb }, + /* 0858 */ { UD_Imovapd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0859 */ { UD_Ivmovapd, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0860 */ { UD_Imovapd, O_W, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0861 */ { UD_Ivmovapd, O_Wx, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0862 */ { UD_Imovaps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0863 */ { UD_Ivmovaps, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0864 */ { UD_Imovaps, O_W, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0865 */ { UD_Ivmovaps, O_Wx, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0866 */ { UD_Imovd, O_P, O_Ey, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0867 */ { UD_Imovd, O_P, O_Ey, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0868 */ { UD_Imovd, O_V, O_Ey, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0869 */ { UD_Ivmovd, O_Vx, O_Ey, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0870 */ { UD_Imovd, O_V, O_Ey, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0871 */ { UD_Ivmovd, O_Vx, O_Ey, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0872 */ { UD_Imovd, O_Ey, O_P, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0873 */ { UD_Imovd, O_Ey, O_P, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0874 */ { UD_Imovd, O_Ey, O_V, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0875 */ { UD_Ivmovd, O_Ey, O_Vx, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0876 */ { UD_Imovd, O_Ey, O_V, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0877 */ { UD_Ivmovd, O_Ey, O_Vx, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0878 */ { UD_Imovhpd, O_V, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0879 */ { UD_Ivmovhpd, O_Vx, O_Hx, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0880 */ { UD_Imovhpd, O_M, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0881 */ { UD_Ivmovhpd, O_M, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0882 */ { UD_Imovhps, O_V, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0883 */ { UD_Ivmovhps, O_Vx, O_Hx, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0884 */ { UD_Imovhps, O_M, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0885 */ { UD_Ivmovhps, O_M, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0886 */ { UD_Imovlhps, O_V, O_U, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0887 */ { UD_Ivmovlhps, O_Vx, O_Hx, O_Ux, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0888 */ { UD_Imovlpd, O_V, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0889 */ { UD_Ivmovlpd, O_Vx, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0890 */ { UD_Imovlpd, O_M, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0891 */ { UD_Ivmovlpd, O_M, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0892 */ { UD_Imovlps, O_V, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0893 */ { UD_Ivmovlps, O_Vx, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0894 */ { UD_Imovlps, O_M, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0895 */ { UD_Ivmovlps, O_M, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0896 */ { UD_Imovhlps, O_V, O_U, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0897 */ { UD_Ivmovhlps, O_Vx, O_Ux, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0898 */ { UD_Imovmskpd, O_Gd, O_U, O_NONE, O_NONE, P_oso|P_rexr|P_rexb }, + /* 0899 */ { UD_Ivmovmskpd, O_Gd, O_Ux, O_NONE, O_NONE, P_oso|P_rexr|P_rexb|P_vexl }, + /* 0900 */ { UD_Imovmskps, O_Gd, O_U, O_NONE, O_NONE, P_oso|P_rexr|P_rexb }, + /* 0901 */ { UD_Ivmovmskps, O_Gd, O_Ux, O_NONE, O_NONE, P_oso|P_rexr|P_rexb }, + /* 0902 */ { UD_Imovntdq, O_M, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0903 */ { UD_Ivmovntdq, O_M, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0904 */ { UD_Imovnti, O_M, O_Gy, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0905 */ { UD_Imovntpd, O_M, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0906 */ { UD_Ivmovntpd, O_M, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0907 */ { UD_Imovntps, O_M, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0908 */ { UD_Ivmovntps, O_M, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0909 */ { UD_Imovntq, O_M, O_P, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0910 */ { UD_Imovq, O_P, O_Eq, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0911 */ { UD_Imovq, O_V, O_Eq, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0912 */ { UD_Ivmovq, O_Vx, O_Eq, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0913 */ { UD_Imovq, O_Eq, O_P, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0914 */ { UD_Imovq, O_Eq, O_V, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0915 */ { UD_Ivmovq, O_Eq, O_Vx, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0916 */ { UD_Imovq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0917 */ { UD_Ivmovq, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0918 */ { UD_Imovq, O_W, O_V, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0919 */ { UD_Ivmovq, O_Wx, O_Vx, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0920 */ { UD_Imovq, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0921 */ { UD_Imovq, O_Q, O_P, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0922 */ { UD_Imovsb, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg }, + /* 0923 */ { UD_Imovsw, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0924 */ { UD_Imovsd, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0925 */ { UD_Imovsd, O_V, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0926 */ { UD_Imovsd, O_W, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0927 */ { UD_Imovsq, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0928 */ { UD_Imovss, O_V, O_MdU, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0929 */ { UD_Imovss, O_W, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0930 */ { UD_Imovsx, O_Gv, O_Eb, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0931 */ { UD_Imovsx, O_Gy, O_Ew, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0932 */ { UD_Imovupd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0933 */ { UD_Ivmovupd, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0934 */ { UD_Imovupd, O_W, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0935 */ { UD_Ivmovupd, O_Wx, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0936 */ { UD_Imovups, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0937 */ { UD_Ivmovups, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0938 */ { UD_Imovups, O_W, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0939 */ { UD_Ivmovups, O_Wx, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0940 */ { UD_Imovzx, O_Gv, O_Eb, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0941 */ { UD_Imovzx, O_Gy, O_Ew, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0942 */ { UD_Imul, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0943 */ { UD_Imul, O_Ev, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0944 */ { UD_Imulpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0945 */ { UD_Ivmulpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0946 */ { UD_Imulps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0947 */ { UD_Ivmulps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0948 */ { UD_Imulsd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0949 */ { UD_Ivmulsd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0950 */ { UD_Imulss, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0951 */ { UD_Ivmulss, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0952 */ { UD_Imwait, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 0953 */ { UD_Ineg, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0954 */ { UD_Ineg, O_Ev, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0955 */ { UD_Inop, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0956 */ { UD_Inop, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0957 */ { UD_Inop, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0958 */ { UD_Inop, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0959 */ { UD_Inop, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0960 */ { UD_Inop, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0961 */ { UD_Inop, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0962 */ { UD_Inot, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0963 */ { UD_Inot, O_Ev, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0964 */ { UD_Ior, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0965 */ { UD_Ior, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0966 */ { UD_Ior, O_Gb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0967 */ { UD_Ior, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0968 */ { UD_Ior, O_AL, O_Ib, O_NONE, O_NONE, P_none }, + /* 0969 */ { UD_Ior, O_rAX, O_sIz, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0970 */ { UD_Ior, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0971 */ { UD_Ior, O_Ev, O_sIz, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0972 */ { UD_Ior, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0973 */ { UD_Ior, O_Ev, O_sIb, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0974 */ { UD_Iorpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0975 */ { UD_Ivorpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0976 */ { UD_Iorps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0977 */ { UD_Ivorps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0978 */ { UD_Iout, O_Ib, O_AL, O_NONE, O_NONE, P_none }, + /* 0979 */ { UD_Iout, O_Ib, O_eAX, O_NONE, O_NONE, P_oso }, + /* 0980 */ { UD_Iout, O_DX, O_AL, O_NONE, O_NONE, P_none }, + /* 0981 */ { UD_Iout, O_DX, O_eAX, O_NONE, O_NONE, P_oso }, + /* 0982 */ { UD_Ioutsb, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg }, + /* 0983 */ { UD_Ioutsw, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_oso|P_seg }, + /* 0984 */ { UD_Ioutsd, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_oso|P_seg }, + /* 0985 */ { UD_Ipacksswb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0986 */ { UD_Ivpacksswb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0987 */ { UD_Ipacksswb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0988 */ { UD_Ipackssdw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0989 */ { UD_Ivpackssdw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0990 */ { UD_Ipackssdw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0991 */ { UD_Ipackuswb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0992 */ { UD_Ivpackuswb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0993 */ { UD_Ipackuswb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0994 */ { UD_Ipaddb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0995 */ { UD_Ivpaddb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 0996 */ { UD_Ipaddb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0997 */ { UD_Ipaddw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0998 */ { UD_Ipaddw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0999 */ { UD_Ivpaddw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1000 */ { UD_Ipaddd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1001 */ { UD_Ipaddd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1002 */ { UD_Ivpaddd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1003 */ { UD_Ipaddsb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1004 */ { UD_Ipaddsb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1005 */ { UD_Ivpaddsb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1006 */ { UD_Ipaddsw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1007 */ { UD_Ipaddsw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1008 */ { UD_Ivpaddsw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1009 */ { UD_Ipaddusb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1010 */ { UD_Ipaddusb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1011 */ { UD_Ivpaddusb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1012 */ { UD_Ipaddusw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1013 */ { UD_Ipaddusw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1014 */ { UD_Ivpaddusw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1015 */ { UD_Ipand, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1016 */ { UD_Ivpand, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1017 */ { UD_Ipand, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1018 */ { UD_Ipandn, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1019 */ { UD_Ivpandn, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1020 */ { UD_Ipandn, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1021 */ { UD_Ipavgb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1022 */ { UD_Ivpavgb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1023 */ { UD_Ipavgb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1024 */ { UD_Ipavgw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1025 */ { UD_Ivpavgw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1026 */ { UD_Ipavgw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1027 */ { UD_Ipcmpeqb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1028 */ { UD_Ipcmpeqb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1029 */ { UD_Ivpcmpeqb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1030 */ { UD_Ipcmpeqw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1031 */ { UD_Ipcmpeqw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1032 */ { UD_Ivpcmpeqw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1033 */ { UD_Ipcmpeqd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1034 */ { UD_Ipcmpeqd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1035 */ { UD_Ivpcmpeqd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1036 */ { UD_Ipcmpgtb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1037 */ { UD_Ivpcmpgtb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1038 */ { UD_Ipcmpgtb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1039 */ { UD_Ipcmpgtw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1040 */ { UD_Ivpcmpgtw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1041 */ { UD_Ipcmpgtw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1042 */ { UD_Ipcmpgtd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1043 */ { UD_Ivpcmpgtd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1044 */ { UD_Ipcmpgtd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1045 */ { UD_Ipextrb, O_MbRv, O_V, O_Ib, O_NONE, P_aso|P_rexx|P_rexr|P_rexb|P_def64 }, + /* 1046 */ { UD_Ivpextrb, O_MbRv, O_Vx, O_Ib, O_NONE, P_aso|P_rexx|P_rexr|P_rexb|P_def64 }, + /* 1047 */ { UD_Ipextrd, O_Ed, O_V, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexw|P_rexb }, + /* 1048 */ { UD_Ivpextrd, O_Ed, O_Vx, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexw|P_rexb }, + /* 1049 */ { UD_Ipextrd, O_Ed, O_V, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexw|P_rexb }, + /* 1050 */ { UD_Ivpextrd, O_Ed, O_Vx, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexw|P_rexb }, + /* 1051 */ { UD_Ipextrq, O_Eq, O_V, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexb|P_def64 }, + /* 1052 */ { UD_Ivpextrq, O_Eq, O_Vx, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexb|P_def64 }, + /* 1053 */ { UD_Ipextrw, O_Gd, O_U, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexb }, + /* 1054 */ { UD_Ivpextrw, O_Gd, O_Ux, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexb }, + /* 1055 */ { UD_Ipextrw, O_Gd, O_N, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1056 */ { UD_Ipextrw, O_MwRd, O_V, O_Ib, O_NONE, P_aso|P_rexw|P_rexx|P_rexr|P_rexb }, + /* 1057 */ { UD_Ivpextrw, O_MwRd, O_Vx, O_Ib, O_NONE, P_aso|P_rexw|P_rexx|P_rexr|P_rexb }, + /* 1058 */ { UD_Ipinsrb, O_V, O_MbRd, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1059 */ { UD_Ipinsrw, O_P, O_MwRy, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 1060 */ { UD_Ipinsrw, O_V, O_MwRy, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 1061 */ { UD_Ivpinsrw, O_Vx, O_MwRy, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 1062 */ { UD_Ipinsrd, O_V, O_Ed, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1063 */ { UD_Ipinsrd, O_V, O_Ed, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1064 */ { UD_Ipinsrq, O_V, O_Eq, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1065 */ { UD_Ivpinsrb, O_V, O_H, O_MbRd, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1066 */ { UD_Ivpinsrd, O_V, O_H, O_Ed, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1067 */ { UD_Ivpinsrd, O_V, O_H, O_Ed, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1068 */ { UD_Ivpinsrq, O_V, O_H, O_Eq, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1069 */ { UD_Ipmaddwd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1070 */ { UD_Ipmaddwd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1071 */ { UD_Ivpmaddwd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1072 */ { UD_Ipmaxsw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1073 */ { UD_Ivpmaxsw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1074 */ { UD_Ipmaxsw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1075 */ { UD_Ipmaxub, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1076 */ { UD_Ipmaxub, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1077 */ { UD_Ivpmaxub, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1078 */ { UD_Ipminsw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1079 */ { UD_Ivpminsw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1080 */ { UD_Ipminsw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1081 */ { UD_Ipminub, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1082 */ { UD_Ivpminub, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1083 */ { UD_Ipminub, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1084 */ { UD_Ipmovmskb, O_Gd, O_U, O_NONE, O_NONE, P_oso|P_rexr|P_rexw|P_rexb }, + /* 1085 */ { UD_Ivpmovmskb, O_Gd, O_Ux, O_NONE, O_NONE, P_oso|P_rexr|P_rexw|P_rexb }, + /* 1086 */ { UD_Ipmovmskb, O_Gd, O_N, O_NONE, O_NONE, P_oso|P_rexr|P_rexw|P_rexb }, + /* 1087 */ { UD_Ipmulhuw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1088 */ { UD_Ipmulhuw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1089 */ { UD_Ivpmulhuw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1090 */ { UD_Ipmulhw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1091 */ { UD_Ivpmulhw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1092 */ { UD_Ipmulhw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1093 */ { UD_Ipmullw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1094 */ { UD_Ipmullw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1095 */ { UD_Ivpmullw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1096 */ { UD_Ipop, O_ES, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 1097 */ { UD_Ipop, O_SS, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 1098 */ { UD_Ipop, O_DS, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 1099 */ { UD_Ipop, O_GS, O_NONE, O_NONE, O_NONE, P_none }, + /* 1100 */ { UD_Ipop, O_FS, O_NONE, O_NONE, O_NONE, P_none }, + /* 1101 */ { UD_Ipop, O_R0v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1102 */ { UD_Ipop, O_R1v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1103 */ { UD_Ipop, O_R2v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1104 */ { UD_Ipop, O_R3v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1105 */ { UD_Ipop, O_R4v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1106 */ { UD_Ipop, O_R5v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1107 */ { UD_Ipop, O_R6v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1108 */ { UD_Ipop, O_R7v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1109 */ { UD_Ipop, O_Ev, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 1110 */ { UD_Ipopa, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_inv64 }, + /* 1111 */ { UD_Ipopad, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_inv64 }, + /* 1112 */ { UD_Ipopfw, O_NONE, O_NONE, O_NONE, O_NONE, P_oso }, + /* 1113 */ { UD_Ipopfd, O_NONE, O_NONE, O_NONE, O_NONE, P_oso }, + /* 1114 */ { UD_Ipopfq, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 1115 */ { UD_Ipopfq, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 1116 */ { UD_Ipor, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1117 */ { UD_Ivpor, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1118 */ { UD_Ipor, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1119 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1120 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1121 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1122 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1123 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1124 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1125 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1126 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1127 */ { UD_Iprefetchnta, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1128 */ { UD_Iprefetcht0, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1129 */ { UD_Iprefetcht1, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1130 */ { UD_Iprefetcht2, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1131 */ { UD_Ipsadbw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1132 */ { UD_Ivpsadbw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1133 */ { UD_Ipsadbw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1134 */ { UD_Ipshufw, O_P, O_Q, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1135 */ { UD_Ipsllw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1136 */ { UD_Ipsllw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1137 */ { UD_Ipsllw, O_U, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 1138 */ { UD_Ipsllw, O_N, O_Ib, O_NONE, O_NONE, P_none }, + /* 1139 */ { UD_Ipslld, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1140 */ { UD_Ipslld, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1141 */ { UD_Ipslld, O_U, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 1142 */ { UD_Ipslld, O_N, O_Ib, O_NONE, O_NONE, P_none }, + /* 1143 */ { UD_Ipsllq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1144 */ { UD_Ipsllq, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1145 */ { UD_Ipsllq, O_U, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 1146 */ { UD_Ipsllq, O_N, O_Ib, O_NONE, O_NONE, P_none }, + /* 1147 */ { UD_Ipsraw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1148 */ { UD_Ipsraw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1149 */ { UD_Ivpsraw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1150 */ { UD_Ipsraw, O_U, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 1151 */ { UD_Ivpsraw, O_Hx, O_Ux, O_Ib, O_NONE, P_rexb }, + /* 1152 */ { UD_Ipsraw, O_N, O_Ib, O_NONE, O_NONE, P_none }, + /* 1153 */ { UD_Ipsrad, O_N, O_Ib, O_NONE, O_NONE, P_none }, + /* 1154 */ { UD_Ipsrad, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1155 */ { UD_Ivpsrad, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1156 */ { UD_Ipsrad, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1157 */ { UD_Ipsrad, O_U, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 1158 */ { UD_Ivpsrad, O_Hx, O_Ux, O_Ib, O_NONE, P_rexb }, + /* 1159 */ { UD_Ipsrlw, O_N, O_Ib, O_NONE, O_NONE, P_none }, + /* 1160 */ { UD_Ipsrlw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1161 */ { UD_Ipsrlw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1162 */ { UD_Ivpsrlw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1163 */ { UD_Ipsrlw, O_U, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 1164 */ { UD_Ivpsrlw, O_Hx, O_Ux, O_Ib, O_NONE, P_rexb }, + /* 1165 */ { UD_Ipsrld, O_N, O_Ib, O_NONE, O_NONE, P_none }, + /* 1166 */ { UD_Ipsrld, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1167 */ { UD_Ipsrld, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1168 */ { UD_Ivpsrld, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1169 */ { UD_Ipsrld, O_U, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 1170 */ { UD_Ivpsrld, O_Hx, O_Ux, O_Ib, O_NONE, P_rexb }, + /* 1171 */ { UD_Ipsrlq, O_N, O_Ib, O_NONE, O_NONE, P_none }, + /* 1172 */ { UD_Ipsrlq, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1173 */ { UD_Ipsrlq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1174 */ { UD_Ivpsrlq, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1175 */ { UD_Ipsrlq, O_U, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 1176 */ { UD_Ivpsrlq, O_Hx, O_Ux, O_Ib, O_NONE, P_rexb }, + /* 1177 */ { UD_Ipsubb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1178 */ { UD_Ivpsubb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1179 */ { UD_Ipsubb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1180 */ { UD_Ipsubw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1181 */ { UD_Ivpsubw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1182 */ { UD_Ipsubw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1183 */ { UD_Ipsubd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1184 */ { UD_Ipsubd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1185 */ { UD_Ivpsubd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1186 */ { UD_Ipsubsb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1187 */ { UD_Ipsubsb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1188 */ { UD_Ivpsubsb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1189 */ { UD_Ipsubsw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1190 */ { UD_Ipsubsw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1191 */ { UD_Ivpsubsw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1192 */ { UD_Ipsubusb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1193 */ { UD_Ipsubusb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1194 */ { UD_Ivpsubusb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1195 */ { UD_Ipsubusw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1196 */ { UD_Ipsubusw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1197 */ { UD_Ivpsubusw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1198 */ { UD_Ipunpckhbw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1199 */ { UD_Ivpunpckhbw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1200 */ { UD_Ipunpckhbw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1201 */ { UD_Ipunpckhwd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1202 */ { UD_Ivpunpckhwd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1203 */ { UD_Ipunpckhwd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1204 */ { UD_Ipunpckhdq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1205 */ { UD_Ivpunpckhdq, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1206 */ { UD_Ipunpckhdq, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1207 */ { UD_Ipunpcklbw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1208 */ { UD_Ivpunpcklbw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1209 */ { UD_Ipunpcklbw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1210 */ { UD_Ipunpcklwd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1211 */ { UD_Ivpunpcklwd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1212 */ { UD_Ipunpcklwd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1213 */ { UD_Ipunpckldq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1214 */ { UD_Ivpunpckldq, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1215 */ { UD_Ipunpckldq, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1216 */ { UD_Ipi2fw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1217 */ { UD_Ipi2fd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1218 */ { UD_Ipf2iw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1219 */ { UD_Ipf2id, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1220 */ { UD_Ipfnacc, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1221 */ { UD_Ipfpnacc, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1222 */ { UD_Ipfcmpge, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1223 */ { UD_Ipfmin, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1224 */ { UD_Ipfrcp, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1225 */ { UD_Ipfrsqrt, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1226 */ { UD_Ipfsub, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1227 */ { UD_Ipfadd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1228 */ { UD_Ipfcmpgt, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1229 */ { UD_Ipfmax, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1230 */ { UD_Ipfrcpit1, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1231 */ { UD_Ipfrsqit1, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1232 */ { UD_Ipfsubr, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1233 */ { UD_Ipfacc, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1234 */ { UD_Ipfcmpeq, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1235 */ { UD_Ipfmul, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1236 */ { UD_Ipfrcpit2, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1237 */ { UD_Ipmulhrw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1238 */ { UD_Ipswapd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1239 */ { UD_Ipavgusb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1240 */ { UD_Ipush, O_ES, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 1241 */ { UD_Ipush, O_CS, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 1242 */ { UD_Ipush, O_SS, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 1243 */ { UD_Ipush, O_DS, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 1244 */ { UD_Ipush, O_GS, O_NONE, O_NONE, O_NONE, P_none }, + /* 1245 */ { UD_Ipush, O_FS, O_NONE, O_NONE, O_NONE, P_none }, + /* 1246 */ { UD_Ipush, O_R0v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1247 */ { UD_Ipush, O_R1v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1248 */ { UD_Ipush, O_R2v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1249 */ { UD_Ipush, O_R3v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1250 */ { UD_Ipush, O_R4v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1251 */ { UD_Ipush, O_R5v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1252 */ { UD_Ipush, O_R6v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1253 */ { UD_Ipush, O_R7v, O_NONE, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 1254 */ { UD_Ipush, O_sIz, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 1255 */ { UD_Ipush, O_Ev, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 1256 */ { UD_Ipush, O_sIb, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 1257 */ { UD_Ipusha, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_inv64 }, + /* 1258 */ { UD_Ipushad, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_inv64 }, + /* 1259 */ { UD_Ipushfw, O_NONE, O_NONE, O_NONE, O_NONE, P_oso }, + /* 1260 */ { UD_Ipushfw, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_def64 }, + /* 1261 */ { UD_Ipushfd, O_NONE, O_NONE, O_NONE, O_NONE, P_oso }, + /* 1262 */ { UD_Ipushfq, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_def64 }, + /* 1263 */ { UD_Ipushfq, O_NONE, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_def64 }, + /* 1264 */ { UD_Ipxor, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1265 */ { UD_Ivpxor, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1266 */ { UD_Ipxor, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1267 */ { UD_Ircl, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1268 */ { UD_Ircl, O_Ev, O_Ib, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1269 */ { UD_Ircl, O_Eb, O_I1, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1270 */ { UD_Ircl, O_Eb, O_CL, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1271 */ { UD_Ircl, O_Ev, O_CL, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1272 */ { UD_Ircl, O_Ev, O_I1, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1273 */ { UD_Ircr, O_Eb, O_I1, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1274 */ { UD_Ircr, O_Ev, O_Ib, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1275 */ { UD_Ircr, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1276 */ { UD_Ircr, O_Ev, O_I1, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1277 */ { UD_Ircr, O_Eb, O_CL, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1278 */ { UD_Ircr, O_Ev, O_CL, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1279 */ { UD_Irol, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1280 */ { UD_Irol, O_Eb, O_I1, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1281 */ { UD_Irol, O_Ev, O_I1, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1282 */ { UD_Irol, O_Eb, O_CL, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1283 */ { UD_Irol, O_Ev, O_CL, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1284 */ { UD_Irol, O_Ev, O_Ib, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1285 */ { UD_Iror, O_Eb, O_I1, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1286 */ { UD_Iror, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1287 */ { UD_Iror, O_Ev, O_Ib, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1288 */ { UD_Iror, O_Ev, O_I1, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1289 */ { UD_Iror, O_Eb, O_CL, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1290 */ { UD_Iror, O_Ev, O_CL, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1291 */ { UD_Ircpps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1292 */ { UD_Ivrcpps, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1293 */ { UD_Ircpss, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1294 */ { UD_Ivrcpss, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1295 */ { UD_Irdmsr, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1296 */ { UD_Irdpmc, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1297 */ { UD_Irdtsc, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1298 */ { UD_Irdtscp, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1299 */ { UD_Irepne, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1300 */ { UD_Irep, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1301 */ { UD_Iret, O_Iw, O_NONE, O_NONE, O_NONE, P_none }, + /* 1302 */ { UD_Iret, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1303 */ { UD_Iretf, O_Iw, O_NONE, O_NONE, O_NONE, P_none }, + /* 1304 */ { UD_Iretf, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1305 */ { UD_Irsm, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1306 */ { UD_Irsqrtps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1307 */ { UD_Ivrsqrtps, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1308 */ { UD_Irsqrtss, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1309 */ { UD_Ivrsqrtss, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1310 */ { UD_Isahf, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1311 */ { UD_Isalc, O_NONE, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 1312 */ { UD_Isar, O_Ev, O_I1, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1313 */ { UD_Isar, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1314 */ { UD_Isar, O_Eb, O_I1, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1315 */ { UD_Isar, O_Ev, O_Ib, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1316 */ { UD_Isar, O_Eb, O_CL, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1317 */ { UD_Isar, O_Ev, O_CL, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1318 */ { UD_Ishl, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1319 */ { UD_Ishl, O_Ev, O_Ib, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1320 */ { UD_Ishl, O_Eb, O_I1, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1321 */ { UD_Ishl, O_Eb, O_CL, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1322 */ { UD_Ishl, O_Ev, O_CL, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1323 */ { UD_Ishl, O_Ev, O_Ib, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1324 */ { UD_Ishl, O_Eb, O_CL, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1325 */ { UD_Ishl, O_Ev, O_I1, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1326 */ { UD_Ishl, O_Eb, O_I1, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1327 */ { UD_Ishl, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1328 */ { UD_Ishl, O_Ev, O_CL, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1329 */ { UD_Ishl, O_Ev, O_I1, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1330 */ { UD_Ishr, O_Ev, O_Ib, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1331 */ { UD_Ishr, O_Eb, O_CL, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1332 */ { UD_Ishr, O_Ev, O_I1, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1333 */ { UD_Ishr, O_Eb, O_I1, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1334 */ { UD_Ishr, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1335 */ { UD_Ishr, O_Ev, O_CL, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1336 */ { UD_Isbb, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1337 */ { UD_Isbb, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1338 */ { UD_Isbb, O_Gb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1339 */ { UD_Isbb, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1340 */ { UD_Isbb, O_AL, O_Ib, O_NONE, O_NONE, P_none }, + /* 1341 */ { UD_Isbb, O_rAX, O_sIz, O_NONE, O_NONE, P_oso|P_rexw }, + /* 1342 */ { UD_Isbb, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1343 */ { UD_Isbb, O_Ev, O_sIz, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1344 */ { UD_Isbb, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 1345 */ { UD_Isbb, O_Ev, O_sIb, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1346 */ { UD_Iscasb, O_NONE, O_NONE, O_NONE, O_NONE, P_strz }, + /* 1347 */ { UD_Iscasw, O_NONE, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw }, + /* 1348 */ { UD_Iscasd, O_NONE, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw }, + /* 1349 */ { UD_Iscasq, O_NONE, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw }, + /* 1350 */ { UD_Iseto, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1351 */ { UD_Isetno, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1352 */ { UD_Isetb, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1353 */ { UD_Isetae, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1354 */ { UD_Isetz, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1355 */ { UD_Isetnz, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1356 */ { UD_Isetbe, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1357 */ { UD_Iseta, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1358 */ { UD_Isets, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1359 */ { UD_Isetns, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1360 */ { UD_Isetp, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1361 */ { UD_Isetnp, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1362 */ { UD_Isetl, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1363 */ { UD_Isetge, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1364 */ { UD_Isetle, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1365 */ { UD_Isetg, O_Eb, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1366 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1367 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1368 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1369 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1370 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1371 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1372 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1373 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1374 */ { UD_Isgdt, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1375 */ { UD_Ishld, O_Ev, O_Gv, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1376 */ { UD_Ishld, O_Ev, O_Gv, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1377 */ { UD_Ishrd, O_Ev, O_Gv, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1378 */ { UD_Ishrd, O_Ev, O_Gv, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1379 */ { UD_Ishufpd, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1380 */ { UD_Ivshufpd, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1381 */ { UD_Ishufps, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1382 */ { UD_Ivshufps, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1383 */ { UD_Isidt, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1384 */ { UD_Isldt, O_MwRv, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1385 */ { UD_Ismsw, O_MwRv, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1386 */ { UD_Ismsw, O_MwRv, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1387 */ { UD_Isqrtps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1388 */ { UD_Ivsqrtps, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1389 */ { UD_Isqrtpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1390 */ { UD_Ivsqrtpd, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1391 */ { UD_Isqrtsd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1392 */ { UD_Ivsqrtsd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1393 */ { UD_Isqrtss, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1394 */ { UD_Ivsqrtss, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1395 */ { UD_Istc, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1396 */ { UD_Istd, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1397 */ { UD_Istgi, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1398 */ { UD_Isti, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1399 */ { UD_Iskinit, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1400 */ { UD_Istmxcsr, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1401 */ { UD_Ivstmxcsr, O_Md, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1402 */ { UD_Istosb, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg }, + /* 1403 */ { UD_Istosw, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 1404 */ { UD_Istosd, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 1405 */ { UD_Istosq, O_NONE, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 1406 */ { UD_Istr, O_MwRv, O_NONE, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1407 */ { UD_Isub, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1408 */ { UD_Isub, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1409 */ { UD_Isub, O_Gb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1410 */ { UD_Isub, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1411 */ { UD_Isub, O_AL, O_Ib, O_NONE, O_NONE, P_none }, + /* 1412 */ { UD_Isub, O_rAX, O_sIz, O_NONE, O_NONE, P_oso|P_rexw }, + /* 1413 */ { UD_Isub, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1414 */ { UD_Isub, O_Ev, O_sIz, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1415 */ { UD_Isub, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 1416 */ { UD_Isub, O_Ev, O_sIb, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1417 */ { UD_Isubpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1418 */ { UD_Ivsubpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1419 */ { UD_Isubps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1420 */ { UD_Ivsubps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1421 */ { UD_Isubsd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1422 */ { UD_Ivsubsd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1423 */ { UD_Isubss, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1424 */ { UD_Ivsubss, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1425 */ { UD_Iswapgs, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1426 */ { UD_Isyscall, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1427 */ { UD_Isysenter, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1428 */ { UD_Isysenter, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1429 */ { UD_Isysexit, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1430 */ { UD_Isysexit, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1431 */ { UD_Isysret, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1432 */ { UD_Itest, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1433 */ { UD_Itest, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1434 */ { UD_Itest, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1435 */ { UD_Itest, O_AL, O_Ib, O_NONE, O_NONE, P_none }, + /* 1436 */ { UD_Itest, O_rAX, O_sIz, O_NONE, O_NONE, P_oso|P_rexw }, + /* 1437 */ { UD_Itest, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1438 */ { UD_Itest, O_Ev, O_sIz, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1439 */ { UD_Itest, O_Ev, O_Iz, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1440 */ { UD_Iucomisd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1441 */ { UD_Ivucomisd, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1442 */ { UD_Iucomiss, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1443 */ { UD_Ivucomiss, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1444 */ { UD_Iud2, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1445 */ { UD_Iunpckhpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1446 */ { UD_Ivunpckhpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1447 */ { UD_Iunpckhps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1448 */ { UD_Ivunpckhps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1449 */ { UD_Iunpcklps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1450 */ { UD_Ivunpcklps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1451 */ { UD_Iunpcklpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1452 */ { UD_Ivunpcklpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1453 */ { UD_Iverr, O_Ew, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1454 */ { UD_Iverw, O_Ew, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1455 */ { UD_Ivmcall, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1456 */ { UD_Irdrand, O_R, O_NONE, O_NONE, O_NONE, P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1457 */ { UD_Ivmclear, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1458 */ { UD_Ivmxon, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1459 */ { UD_Ivmptrld, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1460 */ { UD_Ivmptrst, O_Mq, O_NONE, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1461 */ { UD_Ivmlaunch, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1462 */ { UD_Ivmresume, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1463 */ { UD_Ivmxoff, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1464 */ { UD_Ivmread, O_Ey, O_Gy, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 1465 */ { UD_Ivmwrite, O_Gy, O_Ey, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 1466 */ { UD_Ivmrun, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1467 */ { UD_Ivmmcall, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1468 */ { UD_Ivmload, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1469 */ { UD_Ivmsave, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1470 */ { UD_Iwait, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1471 */ { UD_Iwbinvd, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1472 */ { UD_Iwrmsr, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1473 */ { UD_Ixadd, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, + /* 1474 */ { UD_Ixadd, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1475 */ { UD_Ixchg, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1476 */ { UD_Ixchg, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1477 */ { UD_Ixchg, O_R0v, O_rAX, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1478 */ { UD_Ixchg, O_R1v, O_rAX, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1479 */ { UD_Ixchg, O_R2v, O_rAX, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1480 */ { UD_Ixchg, O_R3v, O_rAX, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1481 */ { UD_Ixchg, O_R4v, O_rAX, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1482 */ { UD_Ixchg, O_R5v, O_rAX, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1483 */ { UD_Ixchg, O_R6v, O_rAX, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1484 */ { UD_Ixchg, O_R7v, O_rAX, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1485 */ { UD_Ixgetbv, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1486 */ { UD_Ixlatb, O_NONE, O_NONE, O_NONE, O_NONE, P_rexw|P_seg }, + /* 1487 */ { UD_Ixor, O_Eb, O_Gb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1488 */ { UD_Ixor, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1489 */ { UD_Ixor, O_Gb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1490 */ { UD_Ixor, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1491 */ { UD_Ixor, O_AL, O_Ib, O_NONE, O_NONE, P_none }, + /* 1492 */ { UD_Ixor, O_rAX, O_sIz, O_NONE, O_NONE, P_oso|P_rexw }, + /* 1493 */ { UD_Ixor, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1494 */ { UD_Ixor, O_Ev, O_sIz, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1495 */ { UD_Ixor, O_Eb, O_Ib, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 1496 */ { UD_Ixor, O_Ev, O_sIb, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1497 */ { UD_Ixorpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1498 */ { UD_Ivxorpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1499 */ { UD_Ixorps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1500 */ { UD_Ivxorps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1501 */ { UD_Ixcryptecb, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1502 */ { UD_Ixcryptcbc, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1503 */ { UD_Ixcryptctr, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1504 */ { UD_Ixcryptcfb, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1505 */ { UD_Ixcryptofb, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1506 */ { UD_Ixrstor, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1507 */ { UD_Ixsave, O_M, O_NONE, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1508 */ { UD_Ixsetbv, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1509 */ { UD_Ixsha1, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1510 */ { UD_Ixsha256, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1511 */ { UD_Ixstore, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1512 */ { UD_Ipclmulqdq, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1513 */ { UD_Ivpclmulqdq, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1514 */ { UD_Igetsec, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1515 */ { UD_Imovdqa, O_W, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1516 */ { UD_Ivmovdqa, O_Wx, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1517 */ { UD_Imovdqa, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1518 */ { UD_Ivmovdqa, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1519 */ { UD_Imaskmovdqu, O_V, O_U, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1520 */ { UD_Ivmaskmovdqu, O_Vx, O_Ux, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1521 */ { UD_Imovdq2q, O_P, O_U, O_NONE, O_NONE, P_aso|P_rexb }, + /* 1522 */ { UD_Imovdqu, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1523 */ { UD_Ivmovdqu, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1524 */ { UD_Imovdqu, O_W, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1525 */ { UD_Ivmovdqu, O_Wx, O_Vx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1526 */ { UD_Imovq2dq, O_V, O_N, O_NONE, O_NONE, P_aso|P_rexr }, + /* 1527 */ { UD_Ipaddq, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1528 */ { UD_Ipaddq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1529 */ { UD_Ivpaddq, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1530 */ { UD_Ipsubq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1531 */ { UD_Ivpsubq, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1532 */ { UD_Ipsubq, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1533 */ { UD_Ipmuludq, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1534 */ { UD_Ipmuludq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1535 */ { UD_Ipshufhw, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1536 */ { UD_Ivpshufhw, O_Vx, O_Wx, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1537 */ { UD_Ipshuflw, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1538 */ { UD_Ivpshuflw, O_Vx, O_Wx, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1539 */ { UD_Ipshufd, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1540 */ { UD_Ivpshufd, O_Vx, O_Wx, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1541 */ { UD_Ipslldq, O_U, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 1542 */ { UD_Ivpslldq, O_Hx, O_Ux, O_Ib, O_NONE, P_rexb }, + /* 1543 */ { UD_Ipsrldq, O_U, O_Ib, O_NONE, O_NONE, P_rexb }, + /* 1544 */ { UD_Ivpsrldq, O_Hx, O_Ux, O_Ib, O_NONE, P_rexb }, + /* 1545 */ { UD_Ipunpckhqdq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1546 */ { UD_Ivpunpckhqdq, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1547 */ { UD_Ipunpcklqdq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1548 */ { UD_Ivpunpcklqdq, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1549 */ { UD_Ihaddpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1550 */ { UD_Ivhaddpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1551 */ { UD_Ihaddps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1552 */ { UD_Ivhaddps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1553 */ { UD_Ihsubpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1554 */ { UD_Ivhsubpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1555 */ { UD_Ihsubps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1556 */ { UD_Ivhsubps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1557 */ { UD_Iinsertps, O_V, O_Md, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1558 */ { UD_Ivinsertps, O_Vx, O_Hx, O_Md, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1559 */ { UD_Ilddqu, O_V, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1560 */ { UD_Ivlddqu, O_Vx, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1561 */ { UD_Imovddup, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1562 */ { UD_Ivmovddup, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1563 */ { UD_Imovddup, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1564 */ { UD_Ivmovddup, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1565 */ { UD_Imovshdup, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1566 */ { UD_Ivmovshdup, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1567 */ { UD_Imovshdup, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1568 */ { UD_Ivmovshdup, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1569 */ { UD_Imovsldup, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1570 */ { UD_Ivmovsldup, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1571 */ { UD_Imovsldup, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1572 */ { UD_Ivmovsldup, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1573 */ { UD_Ipabsb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1574 */ { UD_Ipabsb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1575 */ { UD_Ivpabsb, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1576 */ { UD_Ipabsw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1577 */ { UD_Ipabsw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1578 */ { UD_Ivpabsw, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1579 */ { UD_Ipabsd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1580 */ { UD_Ipabsd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1581 */ { UD_Ivpabsd, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1582 */ { UD_Ipshufb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1583 */ { UD_Ipshufb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1584 */ { UD_Ivpshufb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1585 */ { UD_Iphaddw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1586 */ { UD_Iphaddw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1587 */ { UD_Ivphaddw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1588 */ { UD_Iphaddd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1589 */ { UD_Iphaddd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1590 */ { UD_Ivphaddd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1591 */ { UD_Iphaddsw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1592 */ { UD_Iphaddsw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1593 */ { UD_Ivphaddsw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1594 */ { UD_Ipmaddubsw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1595 */ { UD_Ipmaddubsw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1596 */ { UD_Ivpmaddubsw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1597 */ { UD_Iphsubw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1598 */ { UD_Iphsubw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1599 */ { UD_Ivphsubw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1600 */ { UD_Iphsubd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1601 */ { UD_Iphsubd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1602 */ { UD_Ivphsubd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1603 */ { UD_Iphsubsw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1604 */ { UD_Iphsubsw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1605 */ { UD_Ivphsubsw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1606 */ { UD_Ipsignb, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1607 */ { UD_Ipsignb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1608 */ { UD_Ivpsignb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1609 */ { UD_Ipsignd, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1610 */ { UD_Ipsignd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1611 */ { UD_Ivpsignd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1612 */ { UD_Ipsignw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1613 */ { UD_Ipsignw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1614 */ { UD_Ivpsignw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1615 */ { UD_Ipmulhrsw, O_P, O_Q, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1616 */ { UD_Ipmulhrsw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1617 */ { UD_Ivpmulhrsw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1618 */ { UD_Ipalignr, O_P, O_Q, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1619 */ { UD_Ipalignr, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1620 */ { UD_Ivpalignr, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1621 */ { UD_Ipblendvb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1622 */ { UD_Ipmuldq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1623 */ { UD_Ivpmuldq, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1624 */ { UD_Ipminsb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1625 */ { UD_Ivpminsb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1626 */ { UD_Ipminsd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1627 */ { UD_Ivpminsd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1628 */ { UD_Ipminuw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1629 */ { UD_Ivpminuw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1630 */ { UD_Ipminud, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1631 */ { UD_Ivpminud, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1632 */ { UD_Ipmaxsb, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1633 */ { UD_Ivpmaxsb, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1634 */ { UD_Ipmaxsd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1635 */ { UD_Ivpmaxsd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1636 */ { UD_Ipmaxud, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1637 */ { UD_Ivpmaxud, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1638 */ { UD_Ipmaxuw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1639 */ { UD_Ivpmaxuw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1640 */ { UD_Ipmulld, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1641 */ { UD_Ivpmulld, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1642 */ { UD_Iphminposuw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1643 */ { UD_Ivphminposuw, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1644 */ { UD_Iroundps, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1645 */ { UD_Ivroundps, O_Vx, O_Wx, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1646 */ { UD_Iroundpd, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1647 */ { UD_Ivroundpd, O_Vx, O_Wx, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1648 */ { UD_Iroundss, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1649 */ { UD_Ivroundss, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1650 */ { UD_Iroundsd, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1651 */ { UD_Ivroundsd, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1652 */ { UD_Iblendpd, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1653 */ { UD_Ivblendpd, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1654 */ { UD_Iblendps, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1655 */ { UD_Ivblendps, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1656 */ { UD_Iblendvpd, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1657 */ { UD_Iblendvps, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1658 */ { UD_Ibound, O_Gv, O_M, O_NONE, O_NONE, P_aso|P_oso }, + /* 1659 */ { UD_Ibsf, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1660 */ { UD_Ibsr, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1661 */ { UD_Ibswap, O_R0y, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1662 */ { UD_Ibswap, O_R1y, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1663 */ { UD_Ibswap, O_R2y, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1664 */ { UD_Ibswap, O_R3y, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1665 */ { UD_Ibswap, O_R4y, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1666 */ { UD_Ibswap, O_R5y, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1667 */ { UD_Ibswap, O_R6y, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1668 */ { UD_Ibswap, O_R7y, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 1669 */ { UD_Ibt, O_Ev, O_Ib, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1670 */ { UD_Ibt, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1671 */ { UD_Ibtc, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1672 */ { UD_Ibtc, O_Ev, O_Ib, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1673 */ { UD_Ibtr, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1674 */ { UD_Ibtr, O_Ev, O_Ib, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1675 */ { UD_Ibts, O_Ev, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1676 */ { UD_Ibts, O_Ev, O_Ib, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1677 */ { UD_Ipblendw, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1678 */ { UD_Ivpblendw, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1679 */ { UD_Impsadbw, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1680 */ { UD_Ivmpsadbw, O_Vx, O_Hx, O_Wx, O_Ib, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1681 */ { UD_Imovntdqa, O_V, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1682 */ { UD_Ivmovntdqa, O_Vx, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb|P_vexl }, + /* 1683 */ { UD_Ipackusdw, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1684 */ { UD_Ivpackusdw, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb|P_vexl }, + /* 1685 */ { UD_Ipmovsxbw, O_V, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1686 */ { UD_Ivpmovsxbw, O_Vx, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1687 */ { UD_Ipmovsxbd, O_V, O_MdU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1688 */ { UD_Ivpmovsxbd, O_Vx, O_MdU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1689 */ { UD_Ipmovsxbq, O_V, O_MwU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1690 */ { UD_Ivpmovsxbq, O_Vx, O_MwU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1691 */ { UD_Ipmovsxwd, O_V, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1692 */ { UD_Ivpmovsxwd, O_Vx, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1693 */ { UD_Ipmovsxwq, O_V, O_MdU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1694 */ { UD_Ivpmovsxwq, O_Vx, O_MdU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1695 */ { UD_Ipmovsxdq, O_V, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1696 */ { UD_Ipmovzxbw, O_V, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1697 */ { UD_Ivpmovzxbw, O_Vx, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1698 */ { UD_Ipmovzxbd, O_V, O_MdU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1699 */ { UD_Ivpmovzxbd, O_Vx, O_MdU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1700 */ { UD_Ipmovzxbq, O_V, O_MwU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1701 */ { UD_Ivpmovzxbq, O_Vx, O_MwU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1702 */ { UD_Ipmovzxwd, O_V, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1703 */ { UD_Ivpmovzxwd, O_Vx, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1704 */ { UD_Ipmovzxwq, O_V, O_MdU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1705 */ { UD_Ivpmovzxwq, O_Vx, O_MdU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1706 */ { UD_Ipmovzxdq, O_V, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1707 */ { UD_Ivpmovzxdq, O_Vx, O_MqU, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1708 */ { UD_Ipcmpeqq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1709 */ { UD_Ivpcmpeqq, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1710 */ { UD_Ipopcnt, O_Gv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1711 */ { UD_Iptest, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1712 */ { UD_Ivptest, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb|P_vexl }, + /* 1713 */ { UD_Ipcmpestri, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1714 */ { UD_Ivpcmpestri, O_Vx, O_Wx, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1715 */ { UD_Ipcmpestrm, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1716 */ { UD_Ivpcmpestrm, O_Vx, O_Wx, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1717 */ { UD_Ipcmpgtq, O_V, O_W, O_NONE, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1718 */ { UD_Ivpcmpgtq, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1719 */ { UD_Ipcmpistri, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1720 */ { UD_Ivpcmpistri, O_Vx, O_Wx, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1721 */ { UD_Ipcmpistrm, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1722 */ { UD_Ivpcmpistrm, O_Vx, O_Wx, O_Ib, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1723 */ { UD_Imovbe, O_Gv, O_Mv, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1724 */ { UD_Imovbe, O_Mv, O_Gv, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1725 */ { UD_Icrc32, O_Gy, O_Eb, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1726 */ { UD_Icrc32, O_Gy, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 1727 */ { UD_Ivbroadcastss, O_V, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1728 */ { UD_Ivbroadcastsd, O_Vqq, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1729 */ { UD_Ivextractf128, O_Wdq, O_Vqq, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1730 */ { UD_Ivinsertf128, O_Vqq, O_Hqq, O_Wdq, O_Ib, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1731 */ { UD_Ivmaskmovps, O_V, O_H, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1732 */ { UD_Ivmaskmovps, O_M, O_H, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1733 */ { UD_Ivmaskmovpd, O_V, O_H, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1734 */ { UD_Ivmaskmovpd, O_M, O_H, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1735 */ { UD_Ivpermilpd, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1736 */ { UD_Ivpermilpd, O_V, O_W, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1737 */ { UD_Ivpermilps, O_Vx, O_Hx, O_Wx, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1738 */ { UD_Ivpermilps, O_Vx, O_Wx, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1739 */ { UD_Ivperm2f128, O_Vqq, O_Hqq, O_Wqq, O_Ib, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1740 */ { UD_Ivtestps, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1741 */ { UD_Ivtestpd, O_Vx, O_Wx, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1742 */ { UD_Ivzeroupper, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1743 */ { UD_Ivzeroall, O_NONE, O_NONE, O_NONE, O_NONE, P_none }, + /* 1744 */ { UD_Ivblendvpd, O_Vx, O_Hx, O_Wx, O_Lx, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1745 */ { UD_Ivblendvps, O_Vx, O_Hx, O_Wx, O_Lx, P_aso|P_rexr|P_rexx|P_rexb|P_vexl }, + /* 1746 */ { UD_Ivmovsd, O_V, O_H, O_U, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1747 */ { UD_Ivmovsd, O_V, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1748 */ { UD_Ivmovsd, O_U, O_H, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1749 */ { UD_Ivmovsd, O_Mq, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1750 */ { UD_Ivmovss, O_V, O_H, O_U, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1751 */ { UD_Ivmovss, O_V, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1752 */ { UD_Ivmovss, O_U, O_H, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1753 */ { UD_Ivmovss, O_Md, O_V, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1754 */ { UD_Ivpblendvb, O_V, O_H, O_W, O_L, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1755 */ { UD_Ivpsllw, O_V, O_H, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1756 */ { UD_Ivpsllw, O_H, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1757 */ { UD_Ivpslld, O_V, O_H, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1758 */ { UD_Ivpslld, O_H, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1759 */ { UD_Ivpsllq, O_V, O_H, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1760 */ { UD_Ivpsllq, O_H, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, +}; + + +const char* ud_mnemonics_str[] = { + "aaa", + "aad", + "aam", + "aas", + "adc", + "add", + "addpd", + "addps", + "addsd", + "addss", + "addsubpd", + "addsubps", + "aesdec", + "aesdeclast", + "aesenc", + "aesenclast", + "aesimc", + "aeskeygenassist", + "and", + "andnpd", + "andnps", + "andpd", + "andps", + "arpl", + "blendpd", + "blendps", + "blendvpd", + "blendvps", + "bound", + "bsf", + "bsr", + "bswap", + "bt", + "btc", + "btr", + "bts", + "call", + "cbw", + "cdq", + "cdqe", + "clc", + "cld", + "clflush", + "clgi", + "cli", + "clts", + "cmc", + "cmova", + "cmovae", + "cmovb", + "cmovbe", + "cmovg", + "cmovge", + "cmovl", + "cmovle", + "cmovno", + "cmovnp", + "cmovns", + "cmovnz", + "cmovo", + "cmovp", + "cmovs", + "cmovz", + "cmp", + "cmppd", + "cmpps", + "cmpsb", + "cmpsd", + "cmpsq", + "cmpss", + "cmpsw", + "cmpxchg", + "cmpxchg16b", + "cmpxchg8b", + "comisd", + "comiss", + "cpuid", + "cqo", + "crc32", + "cvtdq2pd", + "cvtdq2ps", + "cvtpd2dq", + "cvtpd2pi", + "cvtpd2ps", + "cvtpi2pd", + "cvtpi2ps", + "cvtps2dq", + "cvtps2pd", + "cvtps2pi", + "cvtsd2si", + "cvtsd2ss", + "cvtsi2sd", + "cvtsi2ss", + "cvtss2sd", + "cvtss2si", + "cvttpd2dq", + "cvttpd2pi", + "cvttps2dq", + "cvttps2pi", + "cvttsd2si", + "cvttss2si", + "cwd", + "cwde", + "daa", + "das", + "dec", + "div", + "divpd", + "divps", + "divsd", + "divss", + "dppd", + "dpps", + "emms", + "enter", + "extractps", + "f2xm1", + "fabs", + "fadd", + "faddp", + "fbld", + "fbstp", + "fchs", + "fclex", + "fcmovb", + "fcmovbe", + "fcmove", + "fcmovnb", + "fcmovnbe", + "fcmovne", + "fcmovnu", + "fcmovu", + "fcom", + "fcom2", + "fcomi", + "fcomip", + "fcomp", + "fcomp3", + "fcomp5", + "fcompp", + "fcos", + "fdecstp", + "fdiv", + "fdivp", + "fdivr", + "fdivrp", + "femms", + "ffree", + "ffreep", + "fiadd", + "ficom", + "ficomp", + "fidiv", + "fidivr", + "fild", + "fimul", + "fincstp", + "fist", + "fistp", + "fisttp", + "fisub", + "fisubr", + "fld", + "fld1", + "fldcw", + "fldenv", + "fldl2e", + "fldl2t", + "fldlg2", + "fldln2", + "fldpi", + "fldz", + "fmul", + "fmulp", + "fndisi", + "fneni", + "fninit", + "fnop", + "fnsave", + "fnsetpm", + "fnstcw", + "fnstenv", + "fnstsw", + "fpatan", + "fprem", + "fprem1", + "fptan", + "frndint", + "frstor", + "frstpm", + "fscale", + "fsin", + "fsincos", + "fsqrt", + "fst", + "fstp", + "fstp1", + "fstp8", + "fstp9", + "fsub", + "fsubp", + "fsubr", + "fsubrp", + "ftst", + "fucom", + "fucomi", + "fucomip", + "fucomp", + "fucompp", + "fxam", + "fxch", + "fxch4", + "fxch7", + "fxrstor", + "fxsave", + "fxtract", + "fyl2x", + "fyl2xp1", + "getsec", + "haddpd", + "haddps", + "hlt", + "hsubpd", + "hsubps", + "idiv", + "imul", + "in", + "inc", + "insb", + "insd", + "insertps", + "insw", + "int", + "int1", + "int3", + "into", + "invd", + "invept", + "invlpg", + "invlpga", + "invvpid", + "iretd", + "iretq", + "iretw", + "ja", + "jae", + "jb", + "jbe", + "jcxz", + "jecxz", + "jg", + "jge", + "jl", + "jle", + "jmp", + "jno", + "jnp", + "jns", + "jnz", + "jo", + "jp", + "jrcxz", + "js", + "jz", + "lahf", + "lar", + "lddqu", + "ldmxcsr", + "lds", + "lea", + "leave", + "les", + "lfence", + "lfs", + "lgdt", + "lgs", + "lidt", + "lldt", + "lmsw", + "lock", + "lodsb", + "lodsd", + "lodsq", + "lodsw", + "loop", + "loope", + "loopne", + "lsl", + "lss", + "ltr", + "maskmovdqu", + "maskmovq", + "maxpd", + "maxps", + "maxsd", + "maxss", + "mfence", + "minpd", + "minps", + "minsd", + "minss", + "monitor", + "montmul", + "mov", + "movapd", + "movaps", + "movbe", + "movd", + "movddup", + "movdq2q", + "movdqa", + "movdqu", + "movhlps", + "movhpd", + "movhps", + "movlhps", + "movlpd", + "movlps", + "movmskpd", + "movmskps", + "movntdq", + "movntdqa", + "movnti", + "movntpd", + "movntps", + "movntq", + "movq", + "movq2dq", + "movsb", + "movsd", + "movshdup", + "movsldup", + "movsq", + "movss", + "movsw", + "movsx", + "movsxd", + "movupd", + "movups", + "movzx", + "mpsadbw", + "mul", + "mulpd", + "mulps", + "mulsd", + "mulss", + "mwait", + "neg", + "nop", + "not", + "or", + "orpd", + "orps", + "out", + "outsb", + "outsd", + "outsw", + "pabsb", + "pabsd", + "pabsw", + "packssdw", + "packsswb", + "packusdw", + "packuswb", + "paddb", + "paddd", + "paddq", + "paddsb", + "paddsw", + "paddusb", + "paddusw", + "paddw", + "palignr", + "pand", + "pandn", + "pavgb", + "pavgusb", + "pavgw", + "pblendvb", + "pblendw", + "pclmulqdq", + "pcmpeqb", + "pcmpeqd", + "pcmpeqq", + "pcmpeqw", + "pcmpestri", + "pcmpestrm", + "pcmpgtb", + "pcmpgtd", + "pcmpgtq", + "pcmpgtw", + "pcmpistri", + "pcmpistrm", + "pextrb", + "pextrd", + "pextrq", + "pextrw", + "pf2id", + "pf2iw", + "pfacc", + "pfadd", + "pfcmpeq", + "pfcmpge", + "pfcmpgt", + "pfmax", + "pfmin", + "pfmul", + "pfnacc", + "pfpnacc", + "pfrcp", + "pfrcpit1", + "pfrcpit2", + "pfrsqit1", + "pfrsqrt", + "pfsub", + "pfsubr", + "phaddd", + "phaddsw", + "phaddw", + "phminposuw", + "phsubd", + "phsubsw", + "phsubw", + "pi2fd", + "pi2fw", + "pinsrb", + "pinsrd", + "pinsrq", + "pinsrw", + "pmaddubsw", + "pmaddwd", + "pmaxsb", + "pmaxsd", + "pmaxsw", + "pmaxub", + "pmaxud", + "pmaxuw", + "pminsb", + "pminsd", + "pminsw", + "pminub", + "pminud", + "pminuw", + "pmovmskb", + "pmovsxbd", + "pmovsxbq", + "pmovsxbw", + "pmovsxdq", + "pmovsxwd", + "pmovsxwq", + "pmovzxbd", + "pmovzxbq", + "pmovzxbw", + "pmovzxdq", + "pmovzxwd", + "pmovzxwq", + "pmuldq", + "pmulhrsw", + "pmulhrw", + "pmulhuw", + "pmulhw", + "pmulld", + "pmullw", + "pmuludq", + "pop", + "popa", + "popad", + "popcnt", + "popfd", + "popfq", + "popfw", + "por", + "prefetch", + "prefetchnta", + "prefetcht0", + "prefetcht1", + "prefetcht2", + "psadbw", + "pshufb", + "pshufd", + "pshufhw", + "pshuflw", + "pshufw", + "psignb", + "psignd", + "psignw", + "pslld", + "pslldq", + "psllq", + "psllw", + "psrad", + "psraw", + "psrld", + "psrldq", + "psrlq", + "psrlw", + "psubb", + "psubd", + "psubq", + "psubsb", + "psubsw", + "psubusb", + "psubusw", + "psubw", + "pswapd", + "ptest", + "punpckhbw", + "punpckhdq", + "punpckhqdq", + "punpckhwd", + "punpcklbw", + "punpckldq", + "punpcklqdq", + "punpcklwd", + "push", + "pusha", + "pushad", + "pushfd", + "pushfq", + "pushfw", + "pxor", + "rcl", + "rcpps", + "rcpss", + "rcr", + "rdmsr", + "rdpmc", + "rdrand", + "rdtsc", + "rdtscp", + "rep", + "repne", + "ret", + "retf", + "rol", + "ror", + "roundpd", + "roundps", + "roundsd", + "roundss", + "rsm", + "rsqrtps", + "rsqrtss", + "sahf", + "salc", + "sar", + "sbb", + "scasb", + "scasd", + "scasq", + "scasw", + "seta", + "setae", + "setb", + "setbe", + "setg", + "setge", + "setl", + "setle", + "setno", + "setnp", + "setns", + "setnz", + "seto", + "setp", + "sets", + "setz", + "sfence", + "sgdt", + "shl", + "shld", + "shr", + "shrd", + "shufpd", + "shufps", + "sidt", + "skinit", + "sldt", + "smsw", + "sqrtpd", + "sqrtps", + "sqrtsd", + "sqrtss", + "stc", + "std", + "stgi", + "sti", + "stmxcsr", + "stosb", + "stosd", + "stosq", + "stosw", + "str", + "sub", + "subpd", + "subps", + "subsd", + "subss", + "swapgs", + "syscall", + "sysenter", + "sysexit", + "sysret", + "test", + "ucomisd", + "ucomiss", + "ud2", + "unpckhpd", + "unpckhps", + "unpcklpd", + "unpcklps", + "vaddpd", + "vaddps", + "vaddsd", + "vaddss", + "vaddsubpd", + "vaddsubps", + "vaesdec", + "vaesdeclast", + "vaesenc", + "vaesenclast", + "vaesimc", + "vaeskeygenassist", + "vandnpd", + "vandnps", + "vandpd", + "vandps", + "vblendpd", + "vblendps", + "vblendvpd", + "vblendvps", + "vbroadcastsd", + "vbroadcastss", + "vcmppd", + "vcmpps", + "vcmpsd", + "vcmpss", + "vcomisd", + "vcomiss", + "vcvtdq2pd", + "vcvtdq2ps", + "vcvtpd2dq", + "vcvtpd2ps", + "vcvtps2dq", + "vcvtps2pd", + "vcvtsd2si", + "vcvtsd2ss", + "vcvtsi2sd", + "vcvtsi2ss", + "vcvtss2sd", + "vcvtss2si", + "vcvttpd2dq", + "vcvttps2dq", + "vcvttsd2si", + "vcvttss2si", + "vdivpd", + "vdivps", + "vdivsd", + "vdivss", + "vdppd", + "vdpps", + "verr", + "verw", + "vextractf128", + "vextractps", + "vhaddpd", + "vhaddps", + "vhsubpd", + "vhsubps", + "vinsertf128", + "vinsertps", + "vlddqu", + "vmaskmovdqu", + "vmaskmovpd", + "vmaskmovps", + "vmaxpd", + "vmaxps", + "vmaxsd", + "vmaxss", + "vmcall", + "vmclear", + "vminpd", + "vminps", + "vminsd", + "vminss", + "vmlaunch", + "vmload", + "vmmcall", + "vmovapd", + "vmovaps", + "vmovd", + "vmovddup", + "vmovdqa", + "vmovdqu", + "vmovhlps", + "vmovhpd", + "vmovhps", + "vmovlhps", + "vmovlpd", + "vmovlps", + "vmovmskpd", + "vmovmskps", + "vmovntdq", + "vmovntdqa", + "vmovntpd", + "vmovntps", + "vmovq", + "vmovsd", + "vmovshdup", + "vmovsldup", + "vmovss", + "vmovupd", + "vmovups", + "vmpsadbw", + "vmptrld", + "vmptrst", + "vmread", + "vmresume", + "vmrun", + "vmsave", + "vmulpd", + "vmulps", + "vmulsd", + "vmulss", + "vmwrite", + "vmxoff", + "vmxon", + "vorpd", + "vorps", + "vpabsb", + "vpabsd", + "vpabsw", + "vpackssdw", + "vpacksswb", + "vpackusdw", + "vpackuswb", + "vpaddb", + "vpaddd", + "vpaddq", + "vpaddsb", + "vpaddsw", + "vpaddusb", + "vpaddusw", + "vpaddw", + "vpalignr", + "vpand", + "vpandn", + "vpavgb", + "vpavgw", + "vpblendvb", + "vpblendw", + "vpclmulqdq", + "vpcmpeqb", + "vpcmpeqd", + "vpcmpeqq", + "vpcmpeqw", + "vpcmpestri", + "vpcmpestrm", + "vpcmpgtb", + "vpcmpgtd", + "vpcmpgtq", + "vpcmpgtw", + "vpcmpistri", + "vpcmpistrm", + "vperm2f128", + "vpermilpd", + "vpermilps", + "vpextrb", + "vpextrd", + "vpextrq", + "vpextrw", + "vphaddd", + "vphaddsw", + "vphaddw", + "vphminposuw", + "vphsubd", + "vphsubsw", + "vphsubw", + "vpinsrb", + "vpinsrd", + "vpinsrq", + "vpinsrw", + "vpmaddubsw", + "vpmaddwd", + "vpmaxsb", + "vpmaxsd", + "vpmaxsw", + "vpmaxub", + "vpmaxud", + "vpmaxuw", + "vpminsb", + "vpminsd", + "vpminsw", + "vpminub", + "vpminud", + "vpminuw", + "vpmovmskb", + "vpmovsxbd", + "vpmovsxbq", + "vpmovsxbw", + "vpmovsxwd", + "vpmovsxwq", + "vpmovzxbd", + "vpmovzxbq", + "vpmovzxbw", + "vpmovzxdq", + "vpmovzxwd", + "vpmovzxwq", + "vpmuldq", + "vpmulhrsw", + "vpmulhuw", + "vpmulhw", + "vpmulld", + "vpmullw", + "vpor", + "vpsadbw", + "vpshufb", + "vpshufd", + "vpshufhw", + "vpshuflw", + "vpsignb", + "vpsignd", + "vpsignw", + "vpslld", + "vpslldq", + "vpsllq", + "vpsllw", + "vpsrad", + "vpsraw", + "vpsrld", + "vpsrldq", + "vpsrlq", + "vpsrlw", + "vpsubb", + "vpsubd", + "vpsubq", + "vpsubsb", + "vpsubsw", + "vpsubusb", + "vpsubusw", + "vpsubw", + "vptest", + "vpunpckhbw", + "vpunpckhdq", + "vpunpckhqdq", + "vpunpckhwd", + "vpunpcklbw", + "vpunpckldq", + "vpunpcklqdq", + "vpunpcklwd", + "vpxor", + "vrcpps", + "vrcpss", + "vroundpd", + "vroundps", + "vroundsd", + "vroundss", + "vrsqrtps", + "vrsqrtss", + "vshufpd", + "vshufps", + "vsqrtpd", + "vsqrtps", + "vsqrtsd", + "vsqrtss", + "vstmxcsr", + "vsubpd", + "vsubps", + "vsubsd", + "vsubss", + "vtestpd", + "vtestps", + "vucomisd", + "vucomiss", + "vunpckhpd", + "vunpckhps", + "vunpcklpd", + "vunpcklps", + "vxorpd", + "vxorps", + "vzeroall", + "vzeroupper", + "wait", + "wbinvd", + "wrmsr", + "xadd", + "xchg", + "xcryptcbc", + "xcryptcfb", + "xcryptctr", + "xcryptecb", + "xcryptofb", + "xgetbv", + "xlatb", + "xor", + "xorpd", + "xorps", + "xrstor", + "xsave", + "xsetbv", + "xsha1", + "xsha256", + "xstore", + "invalid", + "3dnow", + "none", + "db", + "pause" +}; diff --git a/deps/extra/udis86/libudis86/itab.h b/deps/extra/udis86/libudis86/itab.h new file mode 100644 index 00000000..3d54c435 --- /dev/null +++ b/deps/extra/udis86/libudis86/itab.h @@ -0,0 +1,939 @@ +#ifndef UD_ITAB_H +#define UD_ITAB_H + +/* itab.h -- generated by udis86:scripts/ud_itab.py, do no edit */ + +/* ud_table_type -- lookup table types (see decode.c) */ +enum ud_table_type { + UD_TAB__OPC_VEX, + UD_TAB__OPC_TABLE, + UD_TAB__OPC_X87, + UD_TAB__OPC_MOD, + UD_TAB__OPC_RM, + UD_TAB__OPC_OSIZE, + UD_TAB__OPC_MODE, + UD_TAB__OPC_VEX_L, + UD_TAB__OPC_3DNOW, + UD_TAB__OPC_REG, + UD_TAB__OPC_ASIZE, + UD_TAB__OPC_VEX_W, + UD_TAB__OPC_SSE, + UD_TAB__OPC_VENDOR +}; + +/* ud_mnemonic -- mnemonic constants */ +enum ud_mnemonic_code { + UD_Iaaa, + UD_Iaad, + UD_Iaam, + UD_Iaas, + UD_Iadc, + UD_Iadd, + UD_Iaddpd, + UD_Iaddps, + UD_Iaddsd, + UD_Iaddss, + UD_Iaddsubpd, + UD_Iaddsubps, + UD_Iaesdec, + UD_Iaesdeclast, + UD_Iaesenc, + UD_Iaesenclast, + UD_Iaesimc, + UD_Iaeskeygenassist, + UD_Iand, + UD_Iandnpd, + UD_Iandnps, + UD_Iandpd, + UD_Iandps, + UD_Iarpl, + UD_Iblendpd, + UD_Iblendps, + UD_Iblendvpd, + UD_Iblendvps, + UD_Ibound, + UD_Ibsf, + UD_Ibsr, + UD_Ibswap, + UD_Ibt, + UD_Ibtc, + UD_Ibtr, + UD_Ibts, + UD_Icall, + UD_Icbw, + UD_Icdq, + UD_Icdqe, + UD_Iclc, + UD_Icld, + UD_Iclflush, + UD_Iclgi, + UD_Icli, + UD_Iclts, + UD_Icmc, + UD_Icmova, + UD_Icmovae, + UD_Icmovb, + UD_Icmovbe, + UD_Icmovg, + UD_Icmovge, + UD_Icmovl, + UD_Icmovle, + UD_Icmovno, + UD_Icmovnp, + UD_Icmovns, + UD_Icmovnz, + UD_Icmovo, + UD_Icmovp, + UD_Icmovs, + UD_Icmovz, + UD_Icmp, + UD_Icmppd, + UD_Icmpps, + UD_Icmpsb, + UD_Icmpsd, + UD_Icmpsq, + UD_Icmpss, + UD_Icmpsw, + UD_Icmpxchg, + UD_Icmpxchg16b, + UD_Icmpxchg8b, + UD_Icomisd, + UD_Icomiss, + UD_Icpuid, + UD_Icqo, + UD_Icrc32, + UD_Icvtdq2pd, + UD_Icvtdq2ps, + UD_Icvtpd2dq, + UD_Icvtpd2pi, + UD_Icvtpd2ps, + UD_Icvtpi2pd, + UD_Icvtpi2ps, + UD_Icvtps2dq, + UD_Icvtps2pd, + UD_Icvtps2pi, + UD_Icvtsd2si, + UD_Icvtsd2ss, + UD_Icvtsi2sd, + UD_Icvtsi2ss, + UD_Icvtss2sd, + UD_Icvtss2si, + UD_Icvttpd2dq, + UD_Icvttpd2pi, + UD_Icvttps2dq, + UD_Icvttps2pi, + UD_Icvttsd2si, + UD_Icvttss2si, + UD_Icwd, + UD_Icwde, + UD_Idaa, + UD_Idas, + UD_Idec, + UD_Idiv, + UD_Idivpd, + UD_Idivps, + UD_Idivsd, + UD_Idivss, + UD_Idppd, + UD_Idpps, + UD_Iemms, + UD_Ienter, + UD_Iextractps, + UD_If2xm1, + UD_Ifabs, + UD_Ifadd, + UD_Ifaddp, + UD_Ifbld, + UD_Ifbstp, + UD_Ifchs, + UD_Ifclex, + UD_Ifcmovb, + UD_Ifcmovbe, + UD_Ifcmove, + UD_Ifcmovnb, + UD_Ifcmovnbe, + UD_Ifcmovne, + UD_Ifcmovnu, + UD_Ifcmovu, + UD_Ifcom, + UD_Ifcom2, + UD_Ifcomi, + UD_Ifcomip, + UD_Ifcomp, + UD_Ifcomp3, + UD_Ifcomp5, + UD_Ifcompp, + UD_Ifcos, + UD_Ifdecstp, + UD_Ifdiv, + UD_Ifdivp, + UD_Ifdivr, + UD_Ifdivrp, + UD_Ifemms, + UD_Iffree, + UD_Iffreep, + UD_Ifiadd, + UD_Ificom, + UD_Ificomp, + UD_Ifidiv, + UD_Ifidivr, + UD_Ifild, + UD_Ifimul, + UD_Ifincstp, + UD_Ifist, + UD_Ifistp, + UD_Ifisttp, + UD_Ifisub, + UD_Ifisubr, + UD_Ifld, + UD_Ifld1, + UD_Ifldcw, + UD_Ifldenv, + UD_Ifldl2e, + UD_Ifldl2t, + UD_Ifldlg2, + UD_Ifldln2, + UD_Ifldpi, + UD_Ifldz, + UD_Ifmul, + UD_Ifmulp, + UD_Ifndisi, + UD_Ifneni, + UD_Ifninit, + UD_Ifnop, + UD_Ifnsave, + UD_Ifnsetpm, + UD_Ifnstcw, + UD_Ifnstenv, + UD_Ifnstsw, + UD_Ifpatan, + UD_Ifprem, + UD_Ifprem1, + UD_Ifptan, + UD_Ifrndint, + UD_Ifrstor, + UD_Ifrstpm, + UD_Ifscale, + UD_Ifsin, + UD_Ifsincos, + UD_Ifsqrt, + UD_Ifst, + UD_Ifstp, + UD_Ifstp1, + UD_Ifstp8, + UD_Ifstp9, + UD_Ifsub, + UD_Ifsubp, + UD_Ifsubr, + UD_Ifsubrp, + UD_Iftst, + UD_Ifucom, + UD_Ifucomi, + UD_Ifucomip, + UD_Ifucomp, + UD_Ifucompp, + UD_Ifxam, + UD_Ifxch, + UD_Ifxch4, + UD_Ifxch7, + UD_Ifxrstor, + UD_Ifxsave, + UD_Ifxtract, + UD_Ifyl2x, + UD_Ifyl2xp1, + UD_Igetsec, + UD_Ihaddpd, + UD_Ihaddps, + UD_Ihlt, + UD_Ihsubpd, + UD_Ihsubps, + UD_Iidiv, + UD_Iimul, + UD_Iin, + UD_Iinc, + UD_Iinsb, + UD_Iinsd, + UD_Iinsertps, + UD_Iinsw, + UD_Iint, + UD_Iint1, + UD_Iint3, + UD_Iinto, + UD_Iinvd, + UD_Iinvept, + UD_Iinvlpg, + UD_Iinvlpga, + UD_Iinvvpid, + UD_Iiretd, + UD_Iiretq, + UD_Iiretw, + UD_Ija, + UD_Ijae, + UD_Ijb, + UD_Ijbe, + UD_Ijcxz, + UD_Ijecxz, + UD_Ijg, + UD_Ijge, + UD_Ijl, + UD_Ijle, + UD_Ijmp, + UD_Ijno, + UD_Ijnp, + UD_Ijns, + UD_Ijnz, + UD_Ijo, + UD_Ijp, + UD_Ijrcxz, + UD_Ijs, + UD_Ijz, + UD_Ilahf, + UD_Ilar, + UD_Ilddqu, + UD_Ildmxcsr, + UD_Ilds, + UD_Ilea, + UD_Ileave, + UD_Iles, + UD_Ilfence, + UD_Ilfs, + UD_Ilgdt, + UD_Ilgs, + UD_Ilidt, + UD_Illdt, + UD_Ilmsw, + UD_Ilock, + UD_Ilodsb, + UD_Ilodsd, + UD_Ilodsq, + UD_Ilodsw, + UD_Iloop, + UD_Iloope, + UD_Iloopne, + UD_Ilsl, + UD_Ilss, + UD_Iltr, + UD_Imaskmovdqu, + UD_Imaskmovq, + UD_Imaxpd, + UD_Imaxps, + UD_Imaxsd, + UD_Imaxss, + UD_Imfence, + UD_Iminpd, + UD_Iminps, + UD_Iminsd, + UD_Iminss, + UD_Imonitor, + UD_Imontmul, + UD_Imov, + UD_Imovapd, + UD_Imovaps, + UD_Imovbe, + UD_Imovd, + UD_Imovddup, + UD_Imovdq2q, + UD_Imovdqa, + UD_Imovdqu, + UD_Imovhlps, + UD_Imovhpd, + UD_Imovhps, + UD_Imovlhps, + UD_Imovlpd, + UD_Imovlps, + UD_Imovmskpd, + UD_Imovmskps, + UD_Imovntdq, + UD_Imovntdqa, + UD_Imovnti, + UD_Imovntpd, + UD_Imovntps, + UD_Imovntq, + UD_Imovq, + UD_Imovq2dq, + UD_Imovsb, + UD_Imovsd, + UD_Imovshdup, + UD_Imovsldup, + UD_Imovsq, + UD_Imovss, + UD_Imovsw, + UD_Imovsx, + UD_Imovsxd, + UD_Imovupd, + UD_Imovups, + UD_Imovzx, + UD_Impsadbw, + UD_Imul, + UD_Imulpd, + UD_Imulps, + UD_Imulsd, + UD_Imulss, + UD_Imwait, + UD_Ineg, + UD_Inop, + UD_Inot, + UD_Ior, + UD_Iorpd, + UD_Iorps, + UD_Iout, + UD_Ioutsb, + UD_Ioutsd, + UD_Ioutsw, + UD_Ipabsb, + UD_Ipabsd, + UD_Ipabsw, + UD_Ipackssdw, + UD_Ipacksswb, + UD_Ipackusdw, + UD_Ipackuswb, + UD_Ipaddb, + UD_Ipaddd, + UD_Ipaddq, + UD_Ipaddsb, + UD_Ipaddsw, + UD_Ipaddusb, + UD_Ipaddusw, + UD_Ipaddw, + UD_Ipalignr, + UD_Ipand, + UD_Ipandn, + UD_Ipavgb, + UD_Ipavgusb, + UD_Ipavgw, + UD_Ipblendvb, + UD_Ipblendw, + UD_Ipclmulqdq, + UD_Ipcmpeqb, + UD_Ipcmpeqd, + UD_Ipcmpeqq, + UD_Ipcmpeqw, + UD_Ipcmpestri, + UD_Ipcmpestrm, + UD_Ipcmpgtb, + UD_Ipcmpgtd, + UD_Ipcmpgtq, + UD_Ipcmpgtw, + UD_Ipcmpistri, + UD_Ipcmpistrm, + UD_Ipextrb, + UD_Ipextrd, + UD_Ipextrq, + UD_Ipextrw, + UD_Ipf2id, + UD_Ipf2iw, + UD_Ipfacc, + UD_Ipfadd, + UD_Ipfcmpeq, + UD_Ipfcmpge, + UD_Ipfcmpgt, + UD_Ipfmax, + UD_Ipfmin, + UD_Ipfmul, + UD_Ipfnacc, + UD_Ipfpnacc, + UD_Ipfrcp, + UD_Ipfrcpit1, + UD_Ipfrcpit2, + UD_Ipfrsqit1, + UD_Ipfrsqrt, + UD_Ipfsub, + UD_Ipfsubr, + UD_Iphaddd, + UD_Iphaddsw, + UD_Iphaddw, + UD_Iphminposuw, + UD_Iphsubd, + UD_Iphsubsw, + UD_Iphsubw, + UD_Ipi2fd, + UD_Ipi2fw, + UD_Ipinsrb, + UD_Ipinsrd, + UD_Ipinsrq, + UD_Ipinsrw, + UD_Ipmaddubsw, + UD_Ipmaddwd, + UD_Ipmaxsb, + UD_Ipmaxsd, + UD_Ipmaxsw, + UD_Ipmaxub, + UD_Ipmaxud, + UD_Ipmaxuw, + UD_Ipminsb, + UD_Ipminsd, + UD_Ipminsw, + UD_Ipminub, + UD_Ipminud, + UD_Ipminuw, + UD_Ipmovmskb, + UD_Ipmovsxbd, + UD_Ipmovsxbq, + UD_Ipmovsxbw, + UD_Ipmovsxdq, + UD_Ipmovsxwd, + UD_Ipmovsxwq, + UD_Ipmovzxbd, + UD_Ipmovzxbq, + UD_Ipmovzxbw, + UD_Ipmovzxdq, + UD_Ipmovzxwd, + UD_Ipmovzxwq, + UD_Ipmuldq, + UD_Ipmulhrsw, + UD_Ipmulhrw, + UD_Ipmulhuw, + UD_Ipmulhw, + UD_Ipmulld, + UD_Ipmullw, + UD_Ipmuludq, + UD_Ipop, + UD_Ipopa, + UD_Ipopad, + UD_Ipopcnt, + UD_Ipopfd, + UD_Ipopfq, + UD_Ipopfw, + UD_Ipor, + UD_Iprefetch, + UD_Iprefetchnta, + UD_Iprefetcht0, + UD_Iprefetcht1, + UD_Iprefetcht2, + UD_Ipsadbw, + UD_Ipshufb, + UD_Ipshufd, + UD_Ipshufhw, + UD_Ipshuflw, + UD_Ipshufw, + UD_Ipsignb, + UD_Ipsignd, + UD_Ipsignw, + UD_Ipslld, + UD_Ipslldq, + UD_Ipsllq, + UD_Ipsllw, + UD_Ipsrad, + UD_Ipsraw, + UD_Ipsrld, + UD_Ipsrldq, + UD_Ipsrlq, + UD_Ipsrlw, + UD_Ipsubb, + UD_Ipsubd, + UD_Ipsubq, + UD_Ipsubsb, + UD_Ipsubsw, + UD_Ipsubusb, + UD_Ipsubusw, + UD_Ipsubw, + UD_Ipswapd, + UD_Iptest, + UD_Ipunpckhbw, + UD_Ipunpckhdq, + UD_Ipunpckhqdq, + UD_Ipunpckhwd, + UD_Ipunpcklbw, + UD_Ipunpckldq, + UD_Ipunpcklqdq, + UD_Ipunpcklwd, + UD_Ipush, + UD_Ipusha, + UD_Ipushad, + UD_Ipushfd, + UD_Ipushfq, + UD_Ipushfw, + UD_Ipxor, + UD_Ircl, + UD_Ircpps, + UD_Ircpss, + UD_Ircr, + UD_Irdmsr, + UD_Irdpmc, + UD_Irdrand, + UD_Irdtsc, + UD_Irdtscp, + UD_Irep, + UD_Irepne, + UD_Iret, + UD_Iretf, + UD_Irol, + UD_Iror, + UD_Iroundpd, + UD_Iroundps, + UD_Iroundsd, + UD_Iroundss, + UD_Irsm, + UD_Irsqrtps, + UD_Irsqrtss, + UD_Isahf, + UD_Isalc, + UD_Isar, + UD_Isbb, + UD_Iscasb, + UD_Iscasd, + UD_Iscasq, + UD_Iscasw, + UD_Iseta, + UD_Isetae, + UD_Isetb, + UD_Isetbe, + UD_Isetg, + UD_Isetge, + UD_Isetl, + UD_Isetle, + UD_Isetno, + UD_Isetnp, + UD_Isetns, + UD_Isetnz, + UD_Iseto, + UD_Isetp, + UD_Isets, + UD_Isetz, + UD_Isfence, + UD_Isgdt, + UD_Ishl, + UD_Ishld, + UD_Ishr, + UD_Ishrd, + UD_Ishufpd, + UD_Ishufps, + UD_Isidt, + UD_Iskinit, + UD_Isldt, + UD_Ismsw, + UD_Isqrtpd, + UD_Isqrtps, + UD_Isqrtsd, + UD_Isqrtss, + UD_Istc, + UD_Istd, + UD_Istgi, + UD_Isti, + UD_Istmxcsr, + UD_Istosb, + UD_Istosd, + UD_Istosq, + UD_Istosw, + UD_Istr, + UD_Isub, + UD_Isubpd, + UD_Isubps, + UD_Isubsd, + UD_Isubss, + UD_Iswapgs, + UD_Isyscall, + UD_Isysenter, + UD_Isysexit, + UD_Isysret, + UD_Itest, + UD_Iucomisd, + UD_Iucomiss, + UD_Iud2, + UD_Iunpckhpd, + UD_Iunpckhps, + UD_Iunpcklpd, + UD_Iunpcklps, + UD_Ivaddpd, + UD_Ivaddps, + UD_Ivaddsd, + UD_Ivaddss, + UD_Ivaddsubpd, + UD_Ivaddsubps, + UD_Ivaesdec, + UD_Ivaesdeclast, + UD_Ivaesenc, + UD_Ivaesenclast, + UD_Ivaesimc, + UD_Ivaeskeygenassist, + UD_Ivandnpd, + UD_Ivandnps, + UD_Ivandpd, + UD_Ivandps, + UD_Ivblendpd, + UD_Ivblendps, + UD_Ivblendvpd, + UD_Ivblendvps, + UD_Ivbroadcastsd, + UD_Ivbroadcastss, + UD_Ivcmppd, + UD_Ivcmpps, + UD_Ivcmpsd, + UD_Ivcmpss, + UD_Ivcomisd, + UD_Ivcomiss, + UD_Ivcvtdq2pd, + UD_Ivcvtdq2ps, + UD_Ivcvtpd2dq, + UD_Ivcvtpd2ps, + UD_Ivcvtps2dq, + UD_Ivcvtps2pd, + UD_Ivcvtsd2si, + UD_Ivcvtsd2ss, + UD_Ivcvtsi2sd, + UD_Ivcvtsi2ss, + UD_Ivcvtss2sd, + UD_Ivcvtss2si, + UD_Ivcvttpd2dq, + UD_Ivcvttps2dq, + UD_Ivcvttsd2si, + UD_Ivcvttss2si, + UD_Ivdivpd, + UD_Ivdivps, + UD_Ivdivsd, + UD_Ivdivss, + UD_Ivdppd, + UD_Ivdpps, + UD_Iverr, + UD_Iverw, + UD_Ivextractf128, + UD_Ivextractps, + UD_Ivhaddpd, + UD_Ivhaddps, + UD_Ivhsubpd, + UD_Ivhsubps, + UD_Ivinsertf128, + UD_Ivinsertps, + UD_Ivlddqu, + UD_Ivmaskmovdqu, + UD_Ivmaskmovpd, + UD_Ivmaskmovps, + UD_Ivmaxpd, + UD_Ivmaxps, + UD_Ivmaxsd, + UD_Ivmaxss, + UD_Ivmcall, + UD_Ivmclear, + UD_Ivminpd, + UD_Ivminps, + UD_Ivminsd, + UD_Ivminss, + UD_Ivmlaunch, + UD_Ivmload, + UD_Ivmmcall, + UD_Ivmovapd, + UD_Ivmovaps, + UD_Ivmovd, + UD_Ivmovddup, + UD_Ivmovdqa, + UD_Ivmovdqu, + UD_Ivmovhlps, + UD_Ivmovhpd, + UD_Ivmovhps, + UD_Ivmovlhps, + UD_Ivmovlpd, + UD_Ivmovlps, + UD_Ivmovmskpd, + UD_Ivmovmskps, + UD_Ivmovntdq, + UD_Ivmovntdqa, + UD_Ivmovntpd, + UD_Ivmovntps, + UD_Ivmovq, + UD_Ivmovsd, + UD_Ivmovshdup, + UD_Ivmovsldup, + UD_Ivmovss, + UD_Ivmovupd, + UD_Ivmovups, + UD_Ivmpsadbw, + UD_Ivmptrld, + UD_Ivmptrst, + UD_Ivmread, + UD_Ivmresume, + UD_Ivmrun, + UD_Ivmsave, + UD_Ivmulpd, + UD_Ivmulps, + UD_Ivmulsd, + UD_Ivmulss, + UD_Ivmwrite, + UD_Ivmxoff, + UD_Ivmxon, + UD_Ivorpd, + UD_Ivorps, + UD_Ivpabsb, + UD_Ivpabsd, + UD_Ivpabsw, + UD_Ivpackssdw, + UD_Ivpacksswb, + UD_Ivpackusdw, + UD_Ivpackuswb, + UD_Ivpaddb, + UD_Ivpaddd, + UD_Ivpaddq, + UD_Ivpaddsb, + UD_Ivpaddsw, + UD_Ivpaddusb, + UD_Ivpaddusw, + UD_Ivpaddw, + UD_Ivpalignr, + UD_Ivpand, + UD_Ivpandn, + UD_Ivpavgb, + UD_Ivpavgw, + UD_Ivpblendvb, + UD_Ivpblendw, + UD_Ivpclmulqdq, + UD_Ivpcmpeqb, + UD_Ivpcmpeqd, + UD_Ivpcmpeqq, + UD_Ivpcmpeqw, + UD_Ivpcmpestri, + UD_Ivpcmpestrm, + UD_Ivpcmpgtb, + UD_Ivpcmpgtd, + UD_Ivpcmpgtq, + UD_Ivpcmpgtw, + UD_Ivpcmpistri, + UD_Ivpcmpistrm, + UD_Ivperm2f128, + UD_Ivpermilpd, + UD_Ivpermilps, + UD_Ivpextrb, + UD_Ivpextrd, + UD_Ivpextrq, + UD_Ivpextrw, + UD_Ivphaddd, + UD_Ivphaddsw, + UD_Ivphaddw, + UD_Ivphminposuw, + UD_Ivphsubd, + UD_Ivphsubsw, + UD_Ivphsubw, + UD_Ivpinsrb, + UD_Ivpinsrd, + UD_Ivpinsrq, + UD_Ivpinsrw, + UD_Ivpmaddubsw, + UD_Ivpmaddwd, + UD_Ivpmaxsb, + UD_Ivpmaxsd, + UD_Ivpmaxsw, + UD_Ivpmaxub, + UD_Ivpmaxud, + UD_Ivpmaxuw, + UD_Ivpminsb, + UD_Ivpminsd, + UD_Ivpminsw, + UD_Ivpminub, + UD_Ivpminud, + UD_Ivpminuw, + UD_Ivpmovmskb, + UD_Ivpmovsxbd, + UD_Ivpmovsxbq, + UD_Ivpmovsxbw, + UD_Ivpmovsxwd, + UD_Ivpmovsxwq, + UD_Ivpmovzxbd, + UD_Ivpmovzxbq, + UD_Ivpmovzxbw, + UD_Ivpmovzxdq, + UD_Ivpmovzxwd, + UD_Ivpmovzxwq, + UD_Ivpmuldq, + UD_Ivpmulhrsw, + UD_Ivpmulhuw, + UD_Ivpmulhw, + UD_Ivpmulld, + UD_Ivpmullw, + UD_Ivpor, + UD_Ivpsadbw, + UD_Ivpshufb, + UD_Ivpshufd, + UD_Ivpshufhw, + UD_Ivpshuflw, + UD_Ivpsignb, + UD_Ivpsignd, + UD_Ivpsignw, + UD_Ivpslld, + UD_Ivpslldq, + UD_Ivpsllq, + UD_Ivpsllw, + UD_Ivpsrad, + UD_Ivpsraw, + UD_Ivpsrld, + UD_Ivpsrldq, + UD_Ivpsrlq, + UD_Ivpsrlw, + UD_Ivpsubb, + UD_Ivpsubd, + UD_Ivpsubq, + UD_Ivpsubsb, + UD_Ivpsubsw, + UD_Ivpsubusb, + UD_Ivpsubusw, + UD_Ivpsubw, + UD_Ivptest, + UD_Ivpunpckhbw, + UD_Ivpunpckhdq, + UD_Ivpunpckhqdq, + UD_Ivpunpckhwd, + UD_Ivpunpcklbw, + UD_Ivpunpckldq, + UD_Ivpunpcklqdq, + UD_Ivpunpcklwd, + UD_Ivpxor, + UD_Ivrcpps, + UD_Ivrcpss, + UD_Ivroundpd, + UD_Ivroundps, + UD_Ivroundsd, + UD_Ivroundss, + UD_Ivrsqrtps, + UD_Ivrsqrtss, + UD_Ivshufpd, + UD_Ivshufps, + UD_Ivsqrtpd, + UD_Ivsqrtps, + UD_Ivsqrtsd, + UD_Ivsqrtss, + UD_Ivstmxcsr, + UD_Ivsubpd, + UD_Ivsubps, + UD_Ivsubsd, + UD_Ivsubss, + UD_Ivtestpd, + UD_Ivtestps, + UD_Ivucomisd, + UD_Ivucomiss, + UD_Ivunpckhpd, + UD_Ivunpckhps, + UD_Ivunpcklpd, + UD_Ivunpcklps, + UD_Ivxorpd, + UD_Ivxorps, + UD_Ivzeroall, + UD_Ivzeroupper, + UD_Iwait, + UD_Iwbinvd, + UD_Iwrmsr, + UD_Ixadd, + UD_Ixchg, + UD_Ixcryptcbc, + UD_Ixcryptcfb, + UD_Ixcryptctr, + UD_Ixcryptecb, + UD_Ixcryptofb, + UD_Ixgetbv, + UD_Ixlatb, + UD_Ixor, + UD_Ixorpd, + UD_Ixorps, + UD_Ixrstor, + UD_Ixsave, + UD_Ixsetbv, + UD_Ixsha1, + UD_Ixsha256, + UD_Ixstore, + UD_Iinvalid, + UD_I3dnow, + UD_Inone, + UD_Idb, + UD_Ipause, + UD_MAX_MNEMONIC_CODE +}; + +extern const char * ud_mnemonics_str[]; + +#endif /* UD_ITAB_H */ diff --git a/deps/libtomcrypt b/deps/libtomcrypt new file mode 160000 index 00000000..06a81aeb --- /dev/null +++ b/deps/libtomcrypt @@ -0,0 +1 @@ +Subproject commit 06a81aeb227424182125363f7554fad5146d6d2a diff --git a/deps/libtommath b/deps/libtommath new file mode 160000 index 00000000..4b473685 --- /dev/null +++ b/deps/libtommath @@ -0,0 +1 @@ +Subproject commit 4b47368501321c795d5b54d87a5bab35a21a7940 diff --git a/deps/minhook b/deps/minhook new file mode 160000 index 00000000..4a455528 --- /dev/null +++ b/deps/minhook @@ -0,0 +1 @@ +Subproject commit 4a455528f61b5a375b1f9d44e7d296d47f18bb18 diff --git a/deps/premake/asmjit.lua b/deps/premake/asmjit.lua new file mode 100644 index 00000000..ee932594 --- /dev/null +++ b/deps/premake/asmjit.lua @@ -0,0 +1,34 @@ +asmjit = { + source = path.join(dependencies.basePath, "asmjit"), +} + +function asmjit.import() + links { "asmjit" } + asmjit.includes() +end + +function asmjit.includes() + includedirs { + path.join(asmjit.source, "src") + } + + defines { + "ASMJIT_STATIC" + } +end + +function asmjit.project() + project "asmjit" + language "C++" + + asmjit.includes() + + files { + path.join(asmjit.source, "src/**.cpp"), + } + + warnings "Off" + kind "StaticLib" +end + +table.insert(dependencies, asmjit) diff --git a/deps/premake/gsl.lua b/deps/premake/gsl.lua new file mode 100644 index 00000000..7a2daf64 --- /dev/null +++ b/deps/premake/gsl.lua @@ -0,0 +1,19 @@ +gsl = { + source = path.join(dependencies.basePath, "GSL"), +} + +function gsl.import() + gsl.includes() +end + +function gsl.includes() + includedirs { + path.join(gsl.source, "include") + } +end + +function gsl.project() + +end + +table.insert(dependencies, gsl) diff --git a/deps/premake/libtomcrypt.lua b/deps/premake/libtomcrypt.lua new file mode 100644 index 00000000..6c6f28d1 --- /dev/null +++ b/deps/premake/libtomcrypt.lua @@ -0,0 +1,61 @@ +libtomcrypt = { + source = path.join(dependencies.basePath, "libtomcrypt"), +} + +function libtomcrypt.import() + links { + "libtomcrypt" + } + + libtomcrypt.includes() +end + +function libtomcrypt.includes() + includedirs { + path.join(libtomcrypt.source, "src/headers") + } + + defines { + "LTC_NO_FAST", + "LTC_NO_PROTOTYPES", + "LTC_NO_RSA_BLINDING", + } +end + +function libtomcrypt.project() + project "libtomcrypt" + language "C" + + libtomcrypt.includes() + libtommath.import() + + files { + path.join(libtomcrypt.source, "src/**.c"), + } + + removefiles { + path.join(libtomcrypt.source, "src/**/*tab.c"), + path.join(libtomcrypt.source, "src/encauth/ocb3/**.c"), + } + + defines { + "_CRT_SECURE_NO_WARNINGS", + "LTC_SOURCE", + "_LIB", + "USE_LTM" + } + + removedefines { + "_DLL", + "_USRDLL" + } + + linkoptions { + "-IGNORE:4221" + } + + warnings "Off" + kind "StaticLib" +end + +table.insert(dependencies, libtomcrypt) diff --git a/deps/premake/libtommath.lua b/deps/premake/libtommath.lua new file mode 100644 index 00000000..ab4cdde3 --- /dev/null +++ b/deps/premake/libtommath.lua @@ -0,0 +1,52 @@ +libtommath = { + source = path.join(dependencies.basePath, "libtommath"), +} + +function libtommath.import() + links { + "libtommath" + } + + libtommath.includes() +end + +function libtommath.includes() + includedirs { + libtommath.source + } + + defines { + "LTM_DESC", + "__STDC_IEC_559__", + "MP_NO_DEV_URANDOM", + } +end + +function libtommath.project() + project "libtommath" + language "C" + + libtommath.includes() + + files { + path.join(libtommath.source, "*.c"), + } + + defines { + "_LIB" + } + + removedefines { + "_DLL", + "_USRDLL" + } + + linkoptions { + "-IGNORE:4221" + } + + warnings "Off" + kind "StaticLib" +end + +table.insert(dependencies, libtommath) diff --git a/deps/premake/minhook.lua b/deps/premake/minhook.lua new file mode 100644 index 00000000..396d4d38 --- /dev/null +++ b/deps/premake/minhook.lua @@ -0,0 +1,31 @@ +minhook = { + source = path.join(dependencies.basePath, "minhook"), +} + +function minhook.import() + links { "minhook" } + minhook.includes() +end + +function minhook.includes() + includedirs { + path.join(minhook.source, "include") + } +end + +function minhook.project() + project "minhook" + language "C" + + minhook.includes() + + files { + path.join(minhook.source, "src/**.h"), + path.join(minhook.source, "src/**.c"), + } + + warnings "Off" + kind "StaticLib" +end + +table.insert(dependencies, minhook) diff --git a/deps/premake/minizip.lua b/deps/premake/minizip.lua new file mode 100644 index 00000000..4a5754bc --- /dev/null +++ b/deps/premake/minizip.lua @@ -0,0 +1,43 @@ +minizip = { + source = path.join(dependencies.basePath, "zlib/contrib/minizip"), +} + +function minizip.import() + links { "minizip" } + zlib.import() + minizip.includes() +end + +function minizip.includes() + includedirs { + minizip.source + } + + zlib.includes() +end + +function minizip.project() + project "minizip" + language "C" + + minizip.includes() + + files { + path.join(minizip.source, "*.h"), + path.join(minizip.source, "*.c"), + } + + removefiles { + path.join(minizip.source, "miniunz.c"), + path.join(minizip.source, "minizip.c"), + } + + defines { + "_CRT_SECURE_NO_DEPRECATE", + } + + warnings "Off" + kind "StaticLib" +end + +table.insert(dependencies, minizip) diff --git a/deps/premake/rapidjson.lua b/deps/premake/rapidjson.lua new file mode 100644 index 00000000..d1085120 --- /dev/null +++ b/deps/premake/rapidjson.lua @@ -0,0 +1,19 @@ +rapidjson = { + source = path.join(dependencies.basePath, "rapidjson"), +} + +function rapidjson.import() + rapidjson.includes() +end + +function rapidjson.includes() + includedirs { + path.join(rapidjson.source, "include"), + } +end + +function rapidjson.project() + +end + +table.insert(dependencies, rapidjson) diff --git a/deps/premake/stb.lua b/deps/premake/stb.lua new file mode 100644 index 00000000..6f20a983 --- /dev/null +++ b/deps/premake/stb.lua @@ -0,0 +1,19 @@ +stb = { + source = path.join(dependencies.basePath, "stb"), +} + +function stb.import() + stb.includes() +end + +function stb.includes() + includedirs { + stb.source + } +end + +function stb.project() + +end + +table.insert(dependencies, stb) diff --git a/deps/premake/udis86.lua b/deps/premake/udis86.lua new file mode 100644 index 00000000..896ec8b7 --- /dev/null +++ b/deps/premake/udis86.lua @@ -0,0 +1,37 @@ +udis86 = { + source = path.join(dependencies.basePath, "udis86"), +} + +function udis86.import() + links { + "udis86" + } + + udis86.includes() +end + +function udis86.includes() + includedirs { + udis86.source, + path.join(udis86.source, "libudis86"), + path.join(dependencies.basePath, "extra/udis86"), + path.join(dependencies.basePath, "extra/udis86/libudis86"), + } +end + +function udis86.project() + project "udis86" + language "C" + + udis86.includes() + + files { + path.join(udis86.source, "libudis86/*.c"), + path.join(dependencies.basePath, "extra/udis86/libudis86/*.c"), + } + + warnings "Off" + kind "StaticLib" +end + +table.insert(dependencies, udis86) diff --git a/deps/premake/zlib.lua b/deps/premake/zlib.lua new file mode 100644 index 00000000..566a707b --- /dev/null +++ b/deps/premake/zlib.lua @@ -0,0 +1,39 @@ +zlib = { + source = path.join(dependencies.basePath, "zlib"), +} + +function zlib.import() + links { "zlib" } + zlib.includes() +end + +function zlib.includes() + includedirs { + zlib.source + } + + defines { + "ZLIB_CONST", + } +end + +function zlib.project() + project "zlib" + language "C" + + zlib.includes() + + files { + path.join(zlib.source, "*.h"), + path.join(zlib.source, "*.c"), + } + + defines { + "_CRT_SECURE_NO_DEPRECATE", + } + + warnings "Off" + kind "StaticLib" +end + +table.insert(dependencies, zlib) diff --git a/deps/rapidjson b/deps/rapidjson new file mode 160000 index 00000000..2b2c8045 --- /dev/null +++ b/deps/rapidjson @@ -0,0 +1 @@ +Subproject commit 2b2c80450031028439ba2a17a09ef5aa10f2159b diff --git a/deps/stb b/deps/stb new file mode 160000 index 00000000..af1a5bc3 --- /dev/null +++ b/deps/stb @@ -0,0 +1 @@ +Subproject commit af1a5bc352164740c1cc1354942b1c6b72eacb8a diff --git a/deps/udis86 b/deps/udis86 new file mode 160000 index 00000000..56ff6c87 --- /dev/null +++ b/deps/udis86 @@ -0,0 +1 @@ +Subproject commit 56ff6c87c11de0ffa725b14339004820556e343d diff --git a/deps/zlib b/deps/zlib new file mode 160000 index 00000000..ec3df002 --- /dev/null +++ b/deps/zlib @@ -0,0 +1 @@ +Subproject commit ec3df00224d4b396e2ac6586ab5d25f673caa4c2 diff --git a/deps/zstd b/deps/zstd new file mode 160000 index 00000000..f349d187 --- /dev/null +++ b/deps/zstd @@ -0,0 +1 @@ +Subproject commit f349d18776001f39791323e59ef2395983c1cd2e diff --git a/generate.bat b/generate.bat new file mode 100644 index 00000000..06c74119 --- /dev/null +++ b/generate.bat @@ -0,0 +1,3 @@ +@echo off +git submodule update --init --recursive +tools\premake5 %* vs2022 \ No newline at end of file diff --git a/premake5.lua b/premake5.lua new file mode 100644 index 00000000..b3a3bfcc --- /dev/null +++ b/premake5.lua @@ -0,0 +1,369 @@ +gitVersioningCommand = "git describe --tags --dirty --always" +gitCurrentBranchCommand = "git symbolic-ref -q --short HEAD" + +-- Quote the given string input as a C string +function cstrquote(value) + if value == nil then + return "\"\"" + end + result = value:gsub("\\", "\\\\") + result = result:gsub("\"", "\\\"") + result = result:gsub("\n", "\\n") + result = result:gsub("\t", "\\t") + result = result:gsub("\r", "\\r") + result = result:gsub("\a", "\\a") + result = result:gsub("\b", "\\b") + result = "\"" .. result .. "\"" + return result +end + +-- Converts tags in "vX.X.X" format and given revision number Y to an array of numbers {X,X,X,Y}. +-- In the case where the format does not work fall back to padding with zeroes and just ending with the revision number. +-- partscount can be either 3 or 4. +function vertonumarr(value, vernumber, partscount) + vernum = {} + for num in string.gmatch(value or "", "%d+") do + if #vernum < 3 then + table.insert(vernum, tonumber(num)) + end + end + while #vernum < 3 do + table.insert(vernum, 0) + end + if #vernum < partscount then + table.insert(vernum, tonumber(vernumber)) + end + return vernum +end + +dependencies = { + basePath = "./deps" +} + +function dependencies.load() + dir = path.join(dependencies.basePath, "premake/*.lua") + deps = os.matchfiles(dir) + + for i, dep in pairs(deps) do + dep = dep:gsub(".lua", "") + require(dep) + end +end + +function dependencies.imports() + for i, proj in pairs(dependencies) do + if type(i) == 'number' then + proj.import() + end + end +end + +function dependencies.projects() + for i, proj in pairs(dependencies) do + if type(i) == 'number' then + proj.project() + end + end +end + +newoption { + trigger = "copy-to", + description = "Optional, copy the EXE to a custom folder after build, define the path here if wanted.", + value = "PATH" +} + +newoption { + trigger = "dev-build", + description = "Enable development builds of the client." +} + +newoption { + trigger = "inject-host-as-lib", + description = "Decide whether to load the game as lib or to inject it" +} + +newaction { + trigger = "version", + description = "Returns the version string for the current commit of the source code.", + onWorkspace = function(wks) + -- get current version via git + local proc = assert(io.popen(gitVersioningCommand, "r")) + local gitDescribeOutput = assert(proc:read('*a')):gsub("%s+", "") + proc:close() + local version = gitDescribeOutput + + proc = assert(io.popen(gitCurrentBranchCommand, "r")) + local gitCurrentBranchOutput = assert(proc:read('*a')):gsub("%s+", "") + local gitCurrentBranchSuccess = proc:close() + if gitCurrentBranchSuccess then + -- We got a branch name, check if it is a feature branch + if gitCurrentBranchOutput ~= "develop" and gitCurrentBranchOutput ~= "master" then + version = version .. "-" .. gitCurrentBranchOutput + end + end + + print(version) + os.exit(0) + end +} + +newaction { + trigger = "generate-buildinfo", + description = "Sets up build information file like version.h.", + onWorkspace = function(wks) + -- get old version number from version.hpp if any + local oldVersion = "(none)" + local oldVersionHeader = io.open(wks.location .. "/src/version.h", "r") + if oldVersionHeader ~= nil then + local oldVersionHeaderContent = assert(oldVersionHeader:read('*l')) + while oldVersionHeaderContent do + m = string.match(oldVersionHeaderContent, "#define GIT_DESCRIBE (.+)%s*$") + if m ~= nil then + oldVersion = m + end + + oldVersionHeaderContent = oldVersionHeader:read('*l') + end + end + + -- get current version via git + local proc = assert(io.popen(gitVersioningCommand, "r")) + local gitDescribeOutput = assert(proc:read('*a')):gsub("%s+", "") + proc:close() + + -- generate version.hpp with a revision number if not equal + gitDescribeOutputQuoted = cstrquote(gitDescribeOutput) + if oldVersion ~= gitDescribeOutputQuoted then + -- get current git hash and write to version.txt (used by the preliminary updater) + -- TODO - remove once proper updater and release versioning exists + local proc = assert(io.popen("git rev-parse HEAD", "r")) + local gitCommitHash = assert(proc:read('*a')):gsub("%s+", "") + proc:close() + + -- get whether this is a clean revision (no uncommitted changes) + proc = assert(io.popen("git status --porcelain", "r")) + local revDirty = (assert(proc:read('*a')) ~= "") + if revDirty then revDirty = 1 else revDirty = 0 end + proc:close() + + -- get current tag name + proc = assert(io.popen("git describe --tags --abbrev=0")) + local tagName = proc:read('*l') + + -- get current branch name + proc = assert(io.popen("git branch --show-current")) + local branchName = proc:read('*l') + + -- branch for ci + if branchName == nil or branchName == '' then + proc = assert(io.popen("git show -s --pretty=%d HEAD")) + local branchInfo = proc:read('*l') + m = string.match(branchInfo, ".+,.+, ([^)]+)") + if m ~= nil then + branchName = m + end + end + + if branchName == nil then + branchName = "develop" + end + + print("Detected branch: " .. branchName) + + -- get revision number via git + local proc = assert(io.popen("git rev-list --count HEAD", "r")) + local revNumber = assert(proc:read('*a')):gsub("%s+", "") + + print ("Update " .. oldVersion .. " -> " .. gitDescribeOutputQuoted) + + -- write to version.txt for preliminary updater + -- NOTE - remove this once we have a proper updater and proper release versioning + local versionFile = assert(io.open(wks.location .. "/version.txt", "w")) + versionFile:write(gitCommitHash) + versionFile:close() + + -- write version header + local versionHeader = assert(io.open(wks.location .. "/src/version.h", "w")) + versionHeader:write("/*\n") + versionHeader:write(" * Automatically generated by premake5.\n") + versionHeader:write(" * Do not touch!\n") + versionHeader:write(" */\n") + versionHeader:write("\n") + versionHeader:write("#define GIT_DESCRIBE " .. gitDescribeOutputQuoted .. "\n") + versionHeader:write("#define GIT_DIRTY " .. revDirty .. "\n") + versionHeader:write("#define GIT_HASH " .. cstrquote(gitCommitHash) .. "\n") + versionHeader:write("#define GIT_TAG " .. cstrquote(tagName) .. "\n") + versionHeader:write("#define GIT_BRANCH " .. cstrquote(branchName) .. "\n") + versionHeader:write("\n") + versionHeader:write("// Version transformed for RC files\n") + versionHeader:write("#define VERSION_PRODUCT_RC " .. table.concat(vertonumarr(tagName, revNumber, 3), ",") .. "\n") + versionHeader:write("#define VERSION_PRODUCT " .. cstrquote(table.concat(vertonumarr(tagName, revNumber, 3), ".")) .. "\n") + versionHeader:write("#define VERSION_FILE_RC " .. table.concat(vertonumarr(tagName, revNumber, 4), ",") .. "\n") + versionHeader:write("#define VERSION_FILE " .. cstrquote(table.concat(vertonumarr(tagName, revNumber, 4), ".")) .. "\n") + versionHeader:write("\n") + versionHeader:write("// Alias definitions\n") + versionHeader:write("#define VERSION GIT_DESCRIBE\n") + versionHeader:write("#define SHORTVERSION VERSION_PRODUCT\n") + versionHeader:close() + local versionHeader = assert(io.open(wks.location .. "/src/version.hpp", "w")) + versionHeader:write("/*\n") + versionHeader:write(" * Automatically generated by premake5.\n") + versionHeader:write(" * Do not touch!\n") + versionHeader:write(" *\n") + versionHeader:write(" * This file exists for reasons of complying with our coding standards.\n") + versionHeader:write(" *\n") + versionHeader:write(" * The Resource Compiler will ignore any content from C++ header files if they're not from STDInclude.hpp.\n") + versionHeader:write(" * That's the reason why we now place all version info in version.h instead.\n") + versionHeader:write(" */\n") + versionHeader:write("\n") + versionHeader:write("#include \".\\version.h\"\n") + versionHeader:close() + end + end +} + +dependencies.load() + +workspace "iw7-mod" +startproject "client" +location "./build" +objdir "%{wks.location}/obj" +targetdir "%{wks.location}/bin/%{cfg.platform}/%{cfg.buildcfg}" + +configurations {"Debug", "Release"} + +language "C++" +cppdialect "C++20" + +architecture "x86_64" +platforms "x64" + +systemversion "latest" +symbols "On" +staticruntime "On" +editandcontinue "Off" +warnings "Extra" +characterset "ASCII" + +if _OPTIONS["dev-build"] then + defines {"DEV_BUILD"} +end + +if os.getenv("CI") then + defines {"CI"} +end + +flags {"NoIncrementalLink", "NoMinimalRebuild", "MultiProcessorCompile", "No64BitChecks"} + +filter "platforms:x64" + defines {"_WINDOWS", "WIN32"} +filter {} + +filter "configurations:Release" + optimize "Size" + buildoptions {"/GL"} + linkoptions { "/IGNORE:4702", "/LTCG" } + defines {"NDEBUG"} + flags {"FatalCompileWarnings"} +filter {} + +filter "configurations:Debug" + optimize "Debug" + buildoptions {"/bigobj"} + defines {"DEBUG", "_DEBUG"} +filter {} + +project "common" +kind "StaticLib" +language "C++" + +files {"./src/common/**.hpp", "./src/common/**.cpp"} + +includedirs {"./src/common", "%{prj.location}/src"} + +resincludedirs {"$(ProjectDir)src"} + +dependencies.imports() + +project "runner" +kind "WindowedApp" +language "C++" + +files {"./src/runner/**.rc", "./src/runner/**.hpp", "./src/runner/**.cpp", "./src/runner/resources/**.*"} + +includedirs {"./src/runner", "./src/common", "%{prj.location}/src"} + +resincludedirs {"$(ProjectDir)src"} + +links {"common"} + +dependencies.imports() + +project "client" +kind "ConsoleApp" +language "C++" + +targetname "iw7-mod" + +pchheader "std_include.hpp" +pchsource "src/client/std_include.cpp" + +if _OPTIONS["no-inject-host-as-lib"] then + linkoptions {"/IGNORE:4254", "/DYNAMICBASE:NO", "/SAFESEH:NO", "/LARGEADDRESSAWARE", "/LAST:.main", "/PDBCompress"} +else + defines {"INJECT_HOST_AS_LIB"} + linkoptions {"/IGNORE:4254", "/SAFESEH:NO", "/LARGEADDRESSAWARE", "/PDBCompress"} +end + +files {"./src/client/**.rc", "./src/client/**.hpp", "./src/client/**.cpp", "./src/client/resources/**.*"} + +includedirs {"./src/client", "./src/common", "%{prj.location}/src"} + +resincludedirs {"$(ProjectDir)src"} + +dependson {"tlsdll", "runner"} + +links {"common"} + +prebuildcommands {"pushd %{_MAIN_SCRIPT_DIR}", "tools\\premake5 generate-buildinfo", "popd"} + +if _OPTIONS["copy-to"] then + postbuildcommands {"copy /y \"$(TargetPath)\" \"" .. _OPTIONS["copy-to"] .. "\""} +end + +if _OPTIONS["debug-dir"] then + debugdir ( _OPTIONS["debug-dir"] ) +end + +dependencies.imports() + +project "tlsdll" +kind "SharedLib" +language "C++" + +files {"./src/tlsdll/**.rc", "./src/tlsdll/**.hpp", "./src/tlsdll/**.cpp", "./src/tlsdll/resources/**.*"} + +includedirs {"./src/tlsdll", "%{prj.location}/src"} + +links {"common"} + +resincludedirs {"$(ProjectDir)src"} + +project "runner" +kind "WindowedApp" +language "C++" + +files {"./src/runner/**.rc", "./src/runner/**.hpp", "./src/runner/**.cpp", "./src/runner/resources/**.*"} + +includedirs {"./src/runner", "./src/common", "%{prj.location}/src"} + +links {"common"} + +resincludedirs {"$(ProjectDir)src"} + +links {"common"} + +dependencies.imports() + +group "Dependencies" +dependencies.projects() \ No newline at end of file diff --git a/src/client/component/arxan.cpp b/src/client/component/arxan.cpp new file mode 100644 index 00000000..d5200cc3 --- /dev/null +++ b/src/client/component/arxan.cpp @@ -0,0 +1,169 @@ +#include +#include "loader/component_loader.hpp" +//#include "scheduler.hpp" +#include "game/game.hpp" + +#include + +namespace arxan +{ + namespace + { + utils::hook::detour nt_close_hook; + utils::hook::detour nt_query_information_process_hook; + + NTSTATUS WINAPI nt_query_information_process_stub(const HANDLE handle, const PROCESSINFOCLASS info_class, + const PVOID info, + const ULONG info_length, const PULONG ret_length) + { + auto* orig = static_cast(nt_query_information_process_hook. + get_original()); + const auto status = orig(handle, info_class, info, info_length, ret_length); + + if (NT_SUCCESS(status)) + { + if (info_class == ProcessBasicInformation) + { + static DWORD explorer_pid = 0; + if (!explorer_pid) + { + auto* const shell_window = GetShellWindow(); + GetWindowThreadProcessId(shell_window, &explorer_pid); + } + + static_cast(info)->Reserved3 = PVOID(DWORD64(explorer_pid)); + } + else if (info_class == 30) // ProcessDebugObjectHandle + { + *static_cast(info) = nullptr; + + return 0xC0000353; + } + else if (info_class == 7) // ProcessDebugPort + { + *static_cast(info) = nullptr; + } + else if (info_class == 31) + { + *static_cast(info) = 1; + } + + //https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess + } + + return status; + } + + NTSTATUS NTAPI nt_close_stub(const HANDLE handle) + { + char info[16]; + if (NtQueryObject(handle, OBJECT_INFORMATION_CLASS(4), &info, 2, nullptr) >= 0 && size_t(handle) != 0x12345) + { + auto* orig = static_cast(nt_close_hook.get_original()); + return orig(handle); + } + + return STATUS_INVALID_HANDLE; + } + + LONG WINAPI exception_filter(const LPEXCEPTION_POINTERS info) + { + if (info->ExceptionRecord->ExceptionCode == STATUS_INVALID_HANDLE) + { + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; + } + + void hide_being_debugged() + { + auto* const peb = PPEB(__readgsqword(0x60)); + peb->BeingDebugged = false; + *reinterpret_cast(LPSTR(peb) + 0xBC) &= ~0x70; + } + + void remove_hardware_breakpoints() + { + CONTEXT context; + ZeroMemory(&context, sizeof(context)); + context.ContextFlags = CONTEXT_DEBUG_REGISTERS; + + auto* const thread = GetCurrentThread(); + GetThreadContext(thread, &context); + + context.Dr0 = 0; + context.Dr1 = 0; + context.Dr2 = 0; + context.Dr3 = 0; + context.Dr6 = 0; + context.Dr7 = 0; + + SetThreadContext(thread, &context); + } + + BOOL WINAPI set_thread_context_stub(const HANDLE thread, CONTEXT* context) + { + return SetThreadContext(thread, context); + } + + utils::hook::detour doexit_hook; + void doexit_stub() + { + MessageBoxA(0, "doexit", "", 0); + return doexit_hook.invoke(); + } + + utils::hook::detour integrity_check1_hook; + __int64 integrity_check1_stub_hook(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5) + { + __int64 result; + doexit_hook.disable(); + integrity_check1_hook.disable(); + + printf("[ arxan ]: integrity check 1 bypassing...\n"); + result = integrity_check1_hook.invoke<__int64>(a1, a2, a3, a4, a5); + printf("[ arxan ]: integrity check 1 passed!\n"); + + doexit_hook.enable(); + integrity_check1_hook.enable(); + return result; + } + } + + class component final : public component_interface + { + public: + void* load_import(const std::string& library, const std::string& function) override + { + if (function == "SetThreadContext") + { + //return set_thread_context_stub; + } + + return nullptr; + } + + void post_load() override + { + hide_being_debugged(); + //scheduler::loop(hide_being_debugged, scheduler::pipeline::async); + + const utils::nt::library ntdll("ntdll.dll"); + nt_close_hook.create(ntdll.get_proc("NtClose"), nt_close_stub); + nt_query_information_process_hook.create(ntdll.get_proc("NtQueryInformationProcess"), + nt_query_information_process_stub); + // https://www.geoffchappell.com/studies/windows/win32/ntdll/api/index.htm + AddVectoredExceptionHandler(1, exception_filter); + } + + void post_unpack() override + { + doexit_hook.create(0x12D7348_b, doexit_stub); + + integrity_check1_hook.create(0xC6D8B0_b, integrity_check1_stub_hook); // SV_SpawnServer + } + }; +} + +REGISTER_COMPONENT(arxan::component) \ No newline at end of file diff --git a/src/client/component/auth.cpp b/src/client/component/auth.cpp new file mode 100644 index 00000000..00563b09 --- /dev/null +++ b/src/client/component/auth.cpp @@ -0,0 +1,106 @@ +#include +#include "loader/component_loader.hpp" + +#include "auth.hpp" +//#include "command.hpp" +//#include "network.hpp" + +#include +#include +#include +#include +#include + +#include "game/game.hpp" +#include "steam/steam.hpp" + +namespace auth +{ + namespace + { + std::string get_hdd_serial() + { + DWORD serial{}; + if (!GetVolumeInformationA("C:\\", nullptr, 0, &serial, nullptr, nullptr, nullptr, 0)) + { + return {}; + } + + return utils::string::va("%08X", serial); + } + + std::string get_hw_profile_guid() + { + HW_PROFILE_INFO info; + if (!GetCurrentHwProfileA(&info)) + { + return {}; + } + + return std::string{info.szHwProfileGuid, sizeof(info.szHwProfileGuid)}; + } + + std::string get_protected_data() + { + std::string input = "X-Labs-H1Mod-Auth"; + + DATA_BLOB data_in{}, data_out{}; + data_in.pbData = reinterpret_cast(input.data()); + data_in.cbData = static_cast(input.size()); + if (CryptProtectData(&data_in, nullptr, nullptr, nullptr, nullptr, CRYPTPROTECT_LOCAL_MACHINE, &data_out) != TRUE) + { + return {}; + } + + const auto size = std::min(data_out.cbData, 52ul); + std::string result{reinterpret_cast(data_out.pbData), size}; + LocalFree(data_out.pbData); + + return result; + } + + std::string get_key_entropy() + { + std::string entropy{}; + entropy.append(utils::smbios::get_uuid()); + entropy.append(get_hw_profile_guid()); + entropy.append(get_protected_data()); + entropy.append(get_hdd_serial()); + + if (entropy.empty()) + { + entropy.resize(32); + utils::cryptography::random::get_data(entropy.data(), entropy.size()); + } + + return entropy; + } + + utils::cryptography::ecc::key& get_key() + { + static auto key = utils::cryptography::ecc::generate_key(512, get_key_entropy()); + return key; + } + } + + uint64_t get_guid() + { + if (game::environment::is_dedi()) + { + return 0x110000100000000 | (::utils::cryptography::random::get_integer() & ~0x80000000); + } + + return get_key().get_hash(); + } + + class component final : public component_interface + { + public: + void post_unpack() override + { + + } + }; +} + +REGISTER_COMPONENT(auth::component) diff --git a/src/client/component/auth.hpp b/src/client/component/auth.hpp new file mode 100644 index 00000000..2a6b92f2 --- /dev/null +++ b/src/client/component/auth.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace auth +{ + uint64_t get_guid(); +} \ No newline at end of file diff --git a/src/client/component/console.cpp b/src/client/component/console.cpp new file mode 100644 index 00000000..d46bc2bc --- /dev/null +++ b/src/client/component/console.cpp @@ -0,0 +1,89 @@ +#include +#include "console.hpp" +#include "loader/component_loader.hpp" + +#include "game/game.hpp" +//#include "command.hpp" + +namespace game_console +{ + void print(int type, const std::string& data); +} + +namespace console +{ + namespace + { + static bool ingame = false; + static bool exit = false; + + DWORD WINAPI console(LPVOID) + { + ShowWindow(GetConsoleWindow(), SW_SHOW); + SetConsoleTitle("IW7-Mod"); + + std::string cmd; + exit = false; + + while (!exit) + { + std::getline(std::cin, cmd); + if (ingame) + { + game::Cbuf_AddText(0, cmd.data()); + } + } + + return 0; + } + } + + std::string format(va_list* ap, const char* message) + { + static thread_local char buffer[0x1000]; + + const auto count = _vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer), message, *ap); + + if (count < 0) return {}; + return { buffer, static_cast(count) }; + } + + void dispatch_message(const int type, const std::string& message) + { + printf("%s\n", message.data()); + + //game_console::print(type, message); + } + + void print(const int type, const char* fmt, ...) + { + va_list ap; + va_start(ap, fmt); + const auto result = format(&ap, fmt); + va_end(ap); + + dispatch_message(type, result); + } + + class component final : public component_interface + { + public: + void post_start() override + { + CreateThread(0, 0, console, 0, 0, 0); + } + + void post_unpack() override + { + ingame = true; + } + + void pre_destroy() override + { + ingame = false; + exit = true; + } + }; +} + +REGISTER_COMPONENT(console::component) diff --git a/src/client/component/console.hpp b/src/client/component/console.hpp new file mode 100644 index 00000000..4101a3a6 --- /dev/null +++ b/src/client/component/console.hpp @@ -0,0 +1,44 @@ +#pragma once + +namespace console +{ + HWND get_window(); + void set_title(std::string title); + void set_size(int width, int height); + + enum console_type + { + con_type_error = 1, + con_type_debug = 2, + con_type_warning = 3, + con_type_info = 7 + }; + + void print(int type, const char* fmt, ...); + + template + void error(const char* fmt, Args&&... args) + { + print(con_type_error, fmt, std::forward(args)...); + } + + template + void debug(const char* fmt, Args&&... args) + { +#ifdef DEBUG + print(con_type_debug, fmt, std::forward(args)...); +#endif + } + + template + void warn(const char* fmt, Args&&... args) + { + print(con_type_warning, fmt, std::forward(args)...); + } + + template + void info(const char* fmt, Args&&... args) + { + print(con_type_info, fmt, std::forward(args)...); + } +} \ No newline at end of file diff --git a/src/client/component/demonware.cpp b/src/client/component/demonware.cpp new file mode 100644 index 00000000..40e21fc3 --- /dev/null +++ b/src/client/component/demonware.cpp @@ -0,0 +1,666 @@ +#include +#include "loader/component_loader.hpp" + +#include +#include + +#include "game/game.hpp" +#include +#include "game/demonware/servers/lobby_server.hpp" +#include "game/demonware/servers/auth3_server.hpp" +#include "game/demonware/servers/stun_server.hpp" +#include "game/demonware/servers/umbrella_server.hpp" +#include "game/demonware/server_registry.hpp" + +#include "console.hpp" + +#define TCP_BLOCKING true +#define UDP_BLOCKING false + +namespace demonware +{ + namespace + { + volatile bool exit_server; + std::thread server_thread; + utils::concurrency::container> blocking_sockets; + utils::concurrency::container> socket_map; + server_registry tcp_servers; + server_registry udp_servers; + + tcp_server* find_server(const SOCKET socket) + { + return socket_map.access([&](const std::unordered_map& map) -> tcp_server* + { + const auto entry = map.find(socket); + if (entry == map.end()) + { + return nullptr; + } + + return entry->second; + }); + } + + bool socket_link(const SOCKET socket, const uint32_t address) + { + auto* server = tcp_servers.find(address); + if (!server) + { + return false; + } + + socket_map.access([&](std::unordered_map& map) + { + map[socket] = server; + }); + + return true; + } + + void socket_unlink(const SOCKET socket) + { + socket_map.access([&](std::unordered_map& map) + { + const auto entry = map.find(socket); + if (entry != map.end()) + { + map.erase(entry); + } + }); + } + + bool is_socket_blocking(const SOCKET socket, const bool def) + { + return blocking_sockets.access([&](std::unordered_map& map) + { + const auto entry = map.find(socket); + if (entry == map.end()) + { + return def; + } + + return entry->second; + }); + } + + void remove_blocking_socket(const SOCKET socket) + { + blocking_sockets.access([&](std::unordered_map& map) + { + const auto entry = map.find(socket); + if (entry != map.end()) + { + map.erase(entry); + } + }); + } + + void add_blocking_socket(const SOCKET socket, const bool block) + { + blocking_sockets.access([&](std::unordered_map& map) + { + map[socket] = block; + }); + } + + void server_main() + { + exit_server = false; + + while (!exit_server) + { + tcp_servers.frame(); + udp_servers.frame(); + std::this_thread::sleep_for(50ms); + } + } + + namespace io + { + int getaddrinfo_stub(const char* name, const char* service, + const addrinfo* hints, addrinfo** res) + { +#ifdef DEBUG + printf("[ network ]: [getaddrinfo]: \"%s\" \"%s\"\n", name, service); +#endif + + base_server* server = tcp_servers.find(name); + if (!server) + { + server = udp_servers.find(name); + } + + if (!server) + { + return getaddrinfo(name, service, hints, res); + } + + const auto address = utils::memory::get_allocator()->allocate(); + const auto ai = utils::memory::get_allocator()->allocate(); + + auto in_addr = reinterpret_cast(address); + in_addr->sin_addr.s_addr = server->get_address(); + in_addr->sin_family = AF_INET; + + ai->ai_family = AF_INET; + ai->ai_socktype = SOCK_STREAM; + ai->ai_addr = address; + ai->ai_addrlen = sizeof(sockaddr); + ai->ai_next = nullptr; + ai->ai_flags = 0; + ai->ai_protocol = 0; + ai->ai_canonname = const_cast(name); + + *res = ai; + + return 0; + } + + void freeaddrinfo_stub(addrinfo* ai) + { + if (!utils::memory::get_allocator()->find(ai)) + { + return freeaddrinfo(ai); + } + + utils::memory::get_allocator()->free(ai->ai_addr); + utils::memory::get_allocator()->free(ai); + } + + int getpeername_stub(const SOCKET s, sockaddr* addr, socklen_t* addrlen) + { + auto* server = find_server(s); + + printf("getpeername\n"); + + if (server) + { + auto in_addr = reinterpret_cast(addr); + in_addr->sin_addr.s_addr = server->get_address(); + in_addr->sin_family = AF_INET; + *addrlen = sizeof(sockaddr); + + return 0; + } + + return getpeername(s, addr, addrlen); + } + + int getsockname_stub(const SOCKET s, sockaddr* addr, socklen_t* addrlen) + { + auto* server = find_server(s); + + if (server) + { + auto in_addr = reinterpret_cast(addr); + in_addr->sin_addr.s_addr = server->get_address(); + in_addr->sin_family = AF_INET; + *addrlen = sizeof(sockaddr); + + return 0; + } + + return getsockname(s, addr, addrlen); + } + + hostent* gethostbyname_stub(const char* name) + { +#ifdef DEBUG + printf("[ network ]: [gethostbyname]: \"%s\"\n", name); +#endif + + base_server* server = tcp_servers.find(name); + if (!server) + { + server = udp_servers.find(name); + } + + if (!server) + { +#pragma warning(push) +#pragma warning(disable: 4996) + return gethostbyname(name); +#pragma warning(pop) + } + + static thread_local in_addr address{}; + address.s_addr = server->get_address(); + + static thread_local in_addr* addr_list[2]{}; + addr_list[0] = &address; + addr_list[1] = nullptr; + + static thread_local hostent host{}; + host.h_name = const_cast(name); + host.h_aliases = nullptr; + host.h_addrtype = AF_INET; + host.h_length = sizeof(in_addr); + host.h_addr_list = reinterpret_cast(addr_list); + + return &host; + } + + int connect_stub(const SOCKET s, const struct sockaddr* addr, const int len) + { + if (len == sizeof(sockaddr_in)) + { + const auto* in_addr = reinterpret_cast(addr); + if (socket_link(s, in_addr->sin_addr.s_addr)) return 0; + } + + return connect(s, addr, len); + } + + int closesocket_stub(const SOCKET s) + { + remove_blocking_socket(s); + socket_unlink(s); + + return closesocket(s); + } + + int send_stub(const SOCKET s, const char* buf, const int len, const int flags) + { + auto* server = find_server(s); + + printf("send: %s\n", buf); + + if (server) + { + server->handle_input(buf, len); + return len; + } + + return send(s, buf, len, flags); + } + + int recv_stub(const SOCKET s, char* buf, const int len, const int flags) + { + auto* server = find_server(s); + + printf("recv: %s\n", buf); + + if (server) + { + if (server->pending_data()) + { + return static_cast(server->handle_output(buf, len)); + } + else + { + WSASetLastError(WSAEWOULDBLOCK); + return -1; + } + } + + return recv(s, buf, len, flags); + } + + int sendto_stub(const SOCKET s, const char* buf, const int len, const int flags, const sockaddr* to, + const int tolen) + { + const auto* in_addr = reinterpret_cast(to); + auto* server = udp_servers.find(in_addr->sin_addr.s_addr); + + printf("sendto: %s\n", buf); + + if (server) + { + server->handle_input(buf, len, { s, to, tolen }); + return len; + } + + return sendto(s, buf, len, flags, to, tolen); + } + + int recvfrom_stub(const SOCKET s, char* buf, const int len, const int flags, struct sockaddr* from, + int* fromlen) + { + //printf("recvfrom: %s\n", buf); + + // Not supported yet + if (is_socket_blocking(s, UDP_BLOCKING)) + { + return recvfrom(s, buf, len, flags, from, fromlen); + } + + size_t result = 0; + udp_servers.for_each([&](udp_server& server) + { + if (server.pending_data(s)) + { + result = server.handle_output( + s, buf, static_cast(len), from, fromlen); + } + }); + + if (result) + { + return static_cast(result); + } + + return recvfrom(s, buf, len, flags, from, fromlen); + } + + int select_stub(const int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, + struct timeval* timeout) + { + if (exit_server) + { + return select(nfds, readfds, writefds, exceptfds, timeout); + } + + auto result = 0; + std::vector read_sockets; + std::vector write_sockets; + + socket_map.access([&](std::unordered_map& sockets) + { + for (auto& s : sockets) + { + if (readfds) + { + if (FD_ISSET(s.first, readfds)) + { + if (s.second->pending_data()) + { + read_sockets.push_back(s.first); + FD_CLR(s.first, readfds); + } + } + } + + if (writefds) + { + if (FD_ISSET(s.first, writefds)) + { + write_sockets.push_back(s.first); + FD_CLR(s.first, writefds); + } + } + + if (exceptfds) + { + if (FD_ISSET(s.first, exceptfds)) + { + FD_CLR(s.first, exceptfds); + } + } + } + }); + + if ((!readfds || readfds->fd_count == 0) && (!writefds || writefds->fd_count == 0)) + { + timeout->tv_sec = 0; + timeout->tv_usec = 0; + } + + result = select(nfds, readfds, writefds, exceptfds, timeout); + if (result < 0) result = 0; + + for (const auto& socket : read_sockets) + { + if (readfds) + { + FD_SET(socket, readfds); + result++; + } + } + + for (const auto& socket : write_sockets) + { + if (writefds) + { + FD_SET(socket, writefds); + result++; + } + } + + return result; + } + + int ioctlsocket_stub(const SOCKET s, const long cmd, u_long* argp) + { + if (static_cast(cmd) == (FIONBIO)) + { + add_blocking_socket(s, *argp == 0); + } + + return ioctlsocket(s, cmd, argp); + } + + BOOL internet_get_connected_state_stub(LPDWORD, DWORD) + { + // Allow offline play + return TRUE; + } + } + + void bd_logger_stub(int type, const char* const /*channelName*/, const char* /*fileLoc*/, const char* const /*file*/, + const char* const function, const unsigned int /*line*/, const char* const msg, ...) + { + //static auto* enabled = + // game::Dvar_RegisterBool("bd_logger", false, game::DVAR_FLAG_SAVED, "Log bd info to the console."); + //if (!enabled->current.enabled) + //{ + // return; + //} + + char buffer[2048]; + + va_list ap; + va_start(ap, msg); + + vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap); + console::print(type, "%s: %s", function, buffer); + + va_end(ap); + } + +/*#ifdef DEBUG + void a(unsigned int n) + { + printf("bdAuth: Auth task failed with HTTP code [%u]\n", n); + } + + void b(unsigned int n) + { + printf("bdAuth: Decoded client ticket of unexpected size [%u]\n", n); + } + + void c(unsigned int n) + { + printf("bdAuth: Decoded server ticket of unexpected size [%u]\n", n); + } + + void d() + { + printf("bdAuth: Auth ticket magic number mismatch\n"); + } + + void e() + { + printf("bdAuth: Cross Authentication completed\n"); + } + + void f() + { + printf("bdAuth: Auth task reply contains invalid data / format\n"); + } + + void g(unsigned int n) + { + printf("bdAuth: Auth task returned with error code [%u]\n", n); + } + + void h(unsigned int n) + { + printf("bdAuth: Invalid or No Task ID [%u] in Auth reply\n", n); + } + + void i() + { + printf("bdAuth: Received reply from DemonWare Auth server\n"); + } + + void l() + { + printf("bdAuth: Unknown error\n"); + } +#endif*/ + + utils::hook::detour handle_auth_reply_hook; + bool handle_auth_reply_stub(void* a1, void* a2, void* a3) + { + // Skip bdAuth::validateResponseSignature + //utils::hook::set(0x7D4AB0_b, 0xC301B0); + // Skip bdAuth::processPlatformData + //utils::hook::set(0x7D55C0_b, 0xC301B0); + + //return handle_auth_reply_hook.invoke(a1, a2, a3); + } + + void request_start_match_stub() + { + //const auto* args = "StartServer"; + //utils::hook::invoke(0x1E35B0_b, 0, &args); + } + } + + class component final : public component_interface + { + public: + component() + { + udp_servers.create("genesis.stun.us.demonware.net"); + udp_servers.create("genesis.stun.eu.demonware.net"); + udp_servers.create("genesis.stun.jp.demonware.net"); + udp_servers.create("genesis.stun.au.demonware.net"); + + udp_servers.create("stun.us.demonware.net"); + udp_servers.create("stun.eu.demonware.net"); + udp_servers.create("stun.jp.demonware.net"); + udp_servers.create("stun.au.demonware.net"); + + tcp_servers.create("iw-pc-steam-auth3.prod.demonware.net"); + tcp_servers.create("iw-pc-steam-lobby.prod.demonware.net"); + //tcp_servers.create("iw-pc-steam-qbl.prod.demonware.net"); + tcp_servers.create("prod.umbrella.demonware.net"); + } + + void post_load() override + { + server_thread = utils::thread::create_named_thread("Demonware", server_main); + } + + void* load_import(const std::string& library, const std::string& function) override + { + if (library == "WS2_32.dll") + { + if (function == "#3") return io::closesocket_stub; + if (function == "#4") return io::connect_stub; + if (function == "#5") return io::getpeername_stub; + if (function == "#6") return io::getsockname_stub; + if (function == "#10") return io::ioctlsocket_stub; + if (function == "#16") return io::recv_stub; + if (function == "#17") return io::recvfrom_stub; + if (function == "#18") return io::select_stub; + if (function == "#19") return io::send_stub; + if (function == "#20") return io::sendto_stub; + if (function == "#52") return io::gethostbyname_stub; + if (function == "getaddrinfo") return io::getaddrinfo_stub; + if (function == "freeaddrinfo") return io::freeaddrinfo_stub; + } + + if (function == "InternetGetConnectedState") + { + return io::internet_get_connected_state_stub; + } + + return nullptr; + } + + void post_unpack() override + { + /*utils::hook::jump(0x1285040_b, bd_logger_stub, true); + + utils::hook::set(0xB5BB96F_b, 0x0); // CURLOPT_SSL_VERIFYPEER + utils::hook::set(0xB7C6CB1_b, 0xAF); // CURLOPT_SSL_VERIFYHOST + utils::hook::set(0x15E4650_b, 0x0); // HTTPS -> HTTP + + // umbrella dev + const char* umbrella_dev = "http://dev.umbrella.demonware.net"; + std::memset(reinterpret_cast(0x15E8010_b), 0, strlen(umbrella_dev) + 1); + std::memcpy(reinterpret_cast(0x15E8010_b), + umbrella_dev, strlen(umbrella_dev)); + + // umbrella cert + const char* umbrella_cert = "http://cert.umbrella.demonware.net"; + std::memset(reinterpret_cast(0x15E8038_b), 0, strlen(umbrella_cert) + 1); + std::memcpy(reinterpret_cast(0x15E8038_b), + umbrella_cert, strlen(umbrella_cert)); + + // umbrella prod + const char* umbrella_prod = "http://prod.umbrella.demonware.net"; + std::memset(reinterpret_cast(0x15E8060_b), 0, strlen(umbrella_prod) + 1); + std::memcpy(reinterpret_cast(0x15E8060_b), + umbrella_prod, strlen(umbrella_prod)); + + // uno dev + const char* uno_dev = "http://dev.uno.demonware.net/v1.0"; + std::memset(reinterpret_cast(0x15E8418_b), 0, strlen(uno_dev) + 1); + std::memcpy(reinterpret_cast(0x15E8418_b), + uno_dev, strlen(uno_dev)); + + // uno cert + const char* uno_cert = "http://cert.uno.demonware.net/v1.0"; + std::memset(reinterpret_cast(0x15E8440_b), 0, strlen(uno_cert) + 1); + std::memcpy(reinterpret_cast(0x15E8440_b), + uno_cert, strlen(uno_cert)); + + // uno prod + const char* uno = "http://prod.uno.demonware.net/v1.0"; + std::memset(reinterpret_cast(0x15E8468_b), 0, strlen(uno) + 1); + std::memcpy(reinterpret_cast(0x15E8468_b), + uno, strlen(uno)); + + // auth + const char* auth = "http://%s:%d/auth/"; + std::memset(reinterpret_cast(0x15E3600_b), 0, strlen(auth) + 1); + std::memcpy(reinterpret_cast(0x15E3600_b), auth, strlen(auth));*/ + + // utils::hook::set(0x19F8C0_b, 0xC3); // SV_SendMatchData, not sure + //utils::hook::nop(0x19BB67_b, 5); // LiveStorage_SendMatchDataComplete + //utils::hook::set(0x1A3340_b, 0xC3); // Live_CheckForFullDisconnect + + // Remove some while loop that freezes the rendering for a few secs while connecting + //utils::hook::nop(0x625555_b, 5); + + //handle_auth_reply_hook.create(0x7AC600_b, handle_auth_reply_stub); + + // Skip update check in Live_SyncOnlineDataFlags + //utils::hook::set(0x47A6D0_b, 0xC301B0); + // Remove update failed popup + //utils::hook::set(0x47B2B0_b, 0xC301B0); + + // xpartygo -> just start the match + //utils::hook::jump(0x355B80_b, request_start_match_stub, true); + + //utils::hook::set(0x396AD0_b, 0xC301B0); // DB_IsZoneLoaded("ffotd") + //utils::hook::set(0x4DD600_b, 0xC300B0); // dont use ffotd + //utils::hook::set(0x4DD5B0_b, 0xC300B0); // dont dl ffotd + } + + void pre_destroy() override + { + exit_server = true; + if (server_thread.joinable()) + { + server_thread.join(); + } + } + }; +} + +REGISTER_COMPONENT(demonware::component) diff --git a/src/client/component/demonware.hpp b/src/client/component/demonware.hpp new file mode 100644 index 00000000..d26d1ccd --- /dev/null +++ b/src/client/component/demonware.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace demonware +{ + +} \ No newline at end of file diff --git a/src/client/component/game_module.cpp b/src/client/component/game_module.cpp new file mode 100644 index 00000000..0ec79d45 --- /dev/null +++ b/src/client/component/game_module.cpp @@ -0,0 +1,123 @@ +#include +#include "loader/component_loader.hpp" +#include "game_module.hpp" + +#include +#include + +namespace game_module +{ + namespace + { + utils::hook::detour handle_a_hook; + utils::hook::detour handle_w_hook; + utils::hook::detour handle_ex_a_hook; + utils::hook::detour handle_ex_w_hook; + utils::hook::detour file_name_a_hook; + utils::hook::detour file_name_w_hook; + + HMODULE __stdcall get_module_handle_a(const LPCSTR module_name) + { + if (!module_name) + { + return get_game_module(); + } + + return handle_a_hook.invoke(module_name); + } + + HMODULE __stdcall get_module_handle_w(const LPWSTR module_name) + { + if (!module_name) + { + return get_game_module(); + } + + return handle_w_hook.invoke(module_name); + } + + BOOL __stdcall get_module_handle_ex_a(const DWORD flags, const LPCSTR module_name, HMODULE* hmodule) + { + if (!module_name) + { + *hmodule = get_game_module(); + return TRUE; + } + + return handle_ex_a_hook.invoke(flags, module_name, hmodule); + } + + BOOL __stdcall get_module_handle_ex_w(const DWORD flags, const LPCWSTR module_name, HMODULE* hmodule) + { + if (!module_name) + { + *hmodule = get_game_module(); + return TRUE; + } + + return handle_ex_w_hook.invoke(flags, module_name, hmodule); + } + + DWORD __stdcall get_module_file_name_a(HMODULE hmodule, const LPSTR filename, const DWORD size) + { + if (!hmodule) + { + hmodule = get_game_module(); + } + + return file_name_a_hook.invoke(hmodule, filename, size); + } + + DWORD __stdcall get_module_file_name_w(HMODULE hmodule, const LPWSTR filename, const DWORD size) + { + if (!hmodule) + { + hmodule = get_game_module(); + } + + return file_name_w_hook.invoke(hmodule, filename, size); + } + + void hook_module_resolving() + { + handle_a_hook.create(&GetModuleHandleA, &get_module_handle_a); + handle_w_hook.create(&GetModuleHandleW, &get_module_handle_w); + handle_ex_w_hook.create(&GetModuleHandleExA, &get_module_handle_ex_a); + handle_ex_w_hook.create(&GetModuleHandleExW, &get_module_handle_ex_w); + file_name_a_hook.create(&GetModuleFileNameA, &get_module_file_name_a); + file_name_w_hook.create(&GetModuleFileNameW, &get_module_file_name_w); + } + } + + utils::nt::library get_game_module() + { + static utils::nt::library game{HMODULE(game::base_address)}; + return game; + } + + utils::nt::library get_host_module() + { + static utils::nt::library host{}; + return host; + } + + class component final : public component_interface + { + public: + void post_start() override + { + get_host_module(); + } + + void post_load() override + { +#ifdef INJECT_HOST_AS_LIB + hook_module_resolving(); +#else + assert(get_host_module() == get_game_module()); +#endif + } + }; +} + +REGISTER_COMPONENT(game_module::component) diff --git a/src/client/component/game_module.hpp b/src/client/component/game_module.hpp new file mode 100644 index 00000000..e2ca5f56 --- /dev/null +++ b/src/client/component/game_module.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace game_module +{ + utils::nt::library get_game_module(); + utils::nt::library get_host_module(); +} \ No newline at end of file diff --git a/src/client/component/resources.cpp b/src/client/component/resources.cpp new file mode 100644 index 00000000..2a95b18a --- /dev/null +++ b/src/client/component/resources.cpp @@ -0,0 +1,70 @@ +#include +#include "loader/component_loader.hpp" +#include + +namespace resources +{ + namespace + { + HICON icon; + HANDLE splash, logo; + + HANDLE WINAPI load_image_a(const HINSTANCE handle, LPCSTR name, const UINT type, const int c_x, const int c_y, + const UINT load) + { + const utils::nt::library self; + if (!IS_INTRESOURCE(name) && name == "logo.bmp"s) return logo; + if (self.get_handle() == handle && name == LPCSTR(0x64)) return splash; + + return LoadImageA(handle, name, type, c_x, c_y, load); + } + + HICON WINAPI load_icon_a(const HINSTANCE handle, const LPCSTR name) + { + const utils::nt::library self; + if (self.get_handle() == handle && name == LPCSTR(2)) return icon; + + return LoadIconA(handle, name); + } + } + + class component final : public component_interface + { + public: + ~component() override + { + if (icon) DestroyIcon(icon); + if (logo) DeleteObject(logo); + if (splash) DeleteObject(splash); + } + + void post_start() override + { + const utils::nt::library self; + + icon = LoadIconA(self.get_handle(), MAKEINTRESOURCEA(ID_ICON)); + logo = LoadImageA(self.get_handle(), MAKEINTRESOURCEA(IMAGE_LOGO), 0, 0, 0, LR_COPYFROMRESOURCE); + splash = LoadImageA(self.get_handle(), MAKEINTRESOURCEA(IMAGE_SPLASH), 0, 0, 0, LR_COPYFROMRESOURCE); + } + + void* load_import(const std::string& library, const std::string& function) override + { + if (library == "USER32.dll") + { + if (function == "LoadIconA") + { + return load_icon_a; + } + + if (function == "LoadImageA") + { + return load_image_a; + } + } + + return nullptr; + } + }; +} + +REGISTER_COMPONENT(resources::component) diff --git a/src/client/game/demonware/bit_buffer.cpp b/src/client/game/demonware/bit_buffer.cpp new file mode 100644 index 00000000..2b65be2d --- /dev/null +++ b/src/client/game/demonware/bit_buffer.cpp @@ -0,0 +1,182 @@ +#include +#include "bit_buffer.hpp" + +namespace demonware +{ + bool bit_buffer::read_bytes(const unsigned int bytes, unsigned char* output) + { + return this->read(bytes * 8, output); + } + + bool bit_buffer::read_bool(bool* output) + { + if (!this->read_data_type(1)) + { + return false; + } + + return this->read(1, output); + } + + bool bit_buffer::read_uint32(unsigned int* output) + { + if (!this->read_data_type(8)) + { + return false; + } + + return this->read(32, output); + } + + bool bit_buffer::read_data_type(const char expected) + { + char data_type = 0; + + if (!this->use_data_types_) return true; + if (this->read(5, &data_type)) + { + return (data_type == expected); + } + + return false; + } + + bool bit_buffer::write_bytes(const unsigned int bytes, const char* data) + { + return this->write_bytes(bytes, reinterpret_cast(data)); + } + + bool bit_buffer::write_bytes(const unsigned int bytes, const unsigned char* data) + { + return this->write(bytes * 8, data); + } + + bool bit_buffer::write_bool(bool data) + { + if (this->write_data_type(1)) + { + return this->write(1, &data); + } + + return false; + } + + bool bit_buffer::write_int32(int data) + { + if (this->write_data_type(7)) + { + return this->write(32, &data); + } + + return false; + } + + bool bit_buffer::write_uint32(unsigned int data) + { + if (this->write_data_type(8)) + { + return this->write(32, &data); + } + + return false; + } + + bool bit_buffer::write_data_type(char data) + { + if (!this->use_data_types_) + { + return true; + } + + return this->write(5, &data); + } + + bool bit_buffer::read(unsigned int bits, void* output) + { + if (bits == 0) return false; + if ((this->current_bit_ + bits) > (this->buffer_.size() * 8)) return false; + + int cur_byte = this->current_bit_ >> 3; + auto cur_out = 0; + + const char* bytes = this->buffer_.data(); + const auto output_bytes = static_cast(output); + + while (bits > 0) + { + const int min_bit = (bits < 8) ? bits : 8; + const auto this_byte = bytes[cur_byte++] & 0xFF; + const int remain = this->current_bit_ & 7; + + if ((min_bit + remain) <= 8) + { + output_bytes[cur_out] = BYTE((0xFF >> (8 - min_bit)) & (this_byte >> remain)); + } + else + { + output_bytes[cur_out] = BYTE( + (0xFF >> (8 - min_bit)) & (bytes[cur_byte] << (8 - remain)) | (this_byte >> remain)); + } + + cur_out++; + this->current_bit_ += min_bit; + bits -= min_bit; + } + + return true; + } + + bool bit_buffer::write(const unsigned int bits, const void* data) + { + if (bits == 0) return false; + this->buffer_.resize(this->buffer_.size() + (bits >> 3) + 1); + + int bit = bits; + const auto bytes = const_cast(this->buffer_.data()); + const auto* input_bytes = static_cast(data); + + while (bit > 0) + { + const int bit_pos = this->current_bit_ & 7; + auto rem_bit = 8 - bit_pos; + const auto this_write = (bit < rem_bit) ? bit : rem_bit; + + const BYTE mask = ((0xFF >> rem_bit) | (0xFF << (bit_pos + this_write))); + const int byte_pos = this->current_bit_ >> 3; + + const BYTE temp_byte = (mask & bytes[byte_pos]); + const BYTE this_bit = ((bits - bit) & 7); + const auto this_byte = (bits - bit) >> 3; + + auto this_data = input_bytes[this_byte]; + + const auto next_byte = (((bits - 1) >> 3) > this_byte) ? input_bytes[this_byte + 1] : 0; + + this_data = BYTE((next_byte << (8 - this_bit)) | (this_data >> this_bit)); + + const BYTE out_byte = (~mask & (this_data << bit_pos) | temp_byte); + bytes[byte_pos] = out_byte; + + this->current_bit_ += this_write; + bit -= this_write; + } + + return true; + } + + void bit_buffer::set_use_data_types(const bool use_data_types) + { + this->use_data_types_ = use_data_types; + } + + unsigned int bit_buffer::size() const + { + return this->current_bit_ / 8 + (this->current_bit_ % 8 ? 1 : 0); + } + + std::string& bit_buffer::get_buffer() + { + this->buffer_.resize(this->size()); + return this->buffer_; + } +} diff --git a/src/client/game/demonware/bit_buffer.hpp b/src/client/game/demonware/bit_buffer.hpp new file mode 100644 index 00000000..f2fd5c09 --- /dev/null +++ b/src/client/game/demonware/bit_buffer.hpp @@ -0,0 +1,40 @@ +#pragma once + +namespace demonware +{ + class bit_buffer final + { + public: + bit_buffer() = default; + + explicit bit_buffer(std::string buffer) : buffer_(std::move(buffer)) + { + } + + bool read_bytes(unsigned int bytes, unsigned char* output); + bool read_bool(bool* output); + bool read_uint32(unsigned int* output); + bool read_data_type(char expected); + + bool write_bytes(unsigned int bytes, const char* data); + bool write_bytes(unsigned int bytes, const unsigned char* data); + bool write_bool(bool data); + bool write_int32(int data); + bool write_uint32(unsigned int data); + bool write_data_type(char data); + + bool read(unsigned int bits, void* output); + bool write(unsigned int bits, const void* data); + + void set_use_data_types(bool use_data_types); + + unsigned int size() const; + + std::string& get_buffer(); + + private: + std::string buffer_{}; + unsigned int current_bit_ = 0; + bool use_data_types_ = true; + }; +} diff --git a/src/client/game/demonware/byte_buffer.cpp b/src/client/game/demonware/byte_buffer.cpp new file mode 100644 index 00000000..25673496 --- /dev/null +++ b/src/client/game/demonware/byte_buffer.cpp @@ -0,0 +1,308 @@ +#include +#include "byte_buffer.hpp" + +namespace demonware +{ + bool byte_buffer::read_byte(unsigned char* output) + { + if (!this->read_data_type(3)) return false; + return this->read(1, output); + } + + bool byte_buffer::read_bool(bool* output) + { + if (!this->read_data_type(1)) return false; + return this->read(1, output); + } + + bool byte_buffer::read_int16(short* output) + { + if (!this->read_data_type(5)) return false; + return this->read(2, output); + } + + bool byte_buffer::read_uint16(unsigned short* output) + { + if (!this->read_data_type(6)) return false; + return this->read(2, output); + } + + bool byte_buffer::read_int32(int* output) + { + if (!this->read_data_type(7)) return false; + return this->read(4, output); + } + + bool byte_buffer::read_uint32(unsigned int* output) + { + if (!this->read_data_type(8)) return false; + return this->read(4, output); + } + + bool byte_buffer::read_int64(__int64* output) + { + if (!this->read_data_type(9)) return false; + return this->read(8, output); + } + + bool byte_buffer::read_uint64(unsigned __int64* output) + { + if (!this->read_data_type(10)) return false; + return this->read(8, output); + } + + bool byte_buffer::read_float(float* output) + { + if (!this->read_data_type(13)) return false; + return this->read(4, output); + } + + bool byte_buffer::read_string(std::string* output) + { + char* out_data; + if (this->read_string(&out_data)) + { + output->clear(); + output->append(out_data); + return true; + } + + return false; + } + + bool byte_buffer::read_string(char** output) + { + if (!this->read_data_type(16)) return false; + + *output = const_cast(this->buffer_.data()) + this->current_byte_; + this->current_byte_ += strlen(*output) + 1; + + return true; + } + + bool byte_buffer::read_string(char* output, const int length) + { + if (!this->read_data_type(16)) return false; + + strcpy_s(output, length, const_cast(this->buffer_.data()) + this->current_byte_); + this->current_byte_ += strlen(output) + 1; + + return true; + } + + bool byte_buffer::read_blob(std::string* output) + { + char* out_data; + int length; + if (this->read_blob(&out_data, &length)) + { + output->clear(); + output->append(out_data, length); + return true; + } + + return false; + } + + bool byte_buffer::read_blob(char** output, int* length) + { + if (!this->read_data_type(0x13)) + { + return false; + } + + unsigned int size; + this->read_uint32(&size); + + *output = const_cast(this->buffer_.data()) + this->current_byte_; + *length = static_cast(size); + + this->current_byte_ += size; + + return true; + } + + bool byte_buffer::read_data_type(const char expected) + { + if (!this->use_data_types_) return true; + + char type; + this->read(1, &type); + return type == expected; + } + + bool byte_buffer::read_array_header(const unsigned char expected, unsigned int* element_count, + unsigned int* element_size) + { + if (element_count) *element_count = 0; + if (element_size) *element_size = 0; + + if (!this->read_data_type(expected + 100)) return false; + + uint32_t array_size, el_count; + if (!this->read_uint32(&array_size)) return false; + + this->set_use_data_types(false); + this->read_uint32(&el_count); + this->set_use_data_types(true); + + if (element_count) *element_count = el_count; + if (element_size) *element_size = array_size / el_count; + + return true; + } + + bool byte_buffer::write_byte(char data) + { + this->write_data_type(3); + return this->write(1, &data); + } + + bool byte_buffer::write_bool(bool data) + { + this->write_data_type(1); + return this->write(1, &data); + } + + bool byte_buffer::write_int16(short data) + { + this->write_data_type(5); + return this->write(2, &data); + } + + bool byte_buffer::write_uint16(unsigned short data) + { + this->write_data_type(6); + return this->write(2, &data); + } + + bool byte_buffer::write_int32(int data) + { + this->write_data_type(7); + return this->write(4, &data); + } + + bool byte_buffer::write_uint32(unsigned int data) + { + this->write_data_type(8); + return this->write(4, &data); + } + + bool byte_buffer::write_int64(__int64 data) + { + this->write_data_type(9); + return this->write(8, &data); + } + + bool byte_buffer::write_uint64(unsigned __int64 data) + { + this->write_data_type(10); + return this->write(8, &data); + } + + bool byte_buffer::write_data_type(char data) + { + if (!this->use_data_types_) return true; + return this->write(1, &data); + } + + bool byte_buffer::write_float(float data) + { + this->write_data_type(13); + return this->write(4, &data); + } + + bool byte_buffer::write_string(const std::string& data) + { + return this->write_string(data.data()); + } + + bool byte_buffer::write_string(const char* data) + { + this->write_data_type(16); + return this->write(static_cast(strlen(data)) + 1, data); + } + + bool byte_buffer::write_blob(const std::string& data) + { + return this->write_blob(data.data(), INT(data.size())); + } + + bool byte_buffer::write_blob(const char* data, const int length) + { + this->write_data_type(0x13); + this->write_uint32(length); + + return this->write(length, data); + } + + bool byte_buffer::write_array_header(const unsigned char type, const unsigned int element_count, + const unsigned int element_size) + { + const auto using_types = this->is_using_data_types(); + this->set_use_data_types(false); + + auto result = this->write_byte(type + 100); + + this->set_use_data_types(true); + result &= this->write_uint32(element_count * element_size); + this->set_use_data_types(false); + + result &= this->write_uint32(element_count); + + this->set_use_data_types(using_types); + return result; + } + + bool byte_buffer::read(const int bytes, void* output) + { + if (bytes + this->current_byte_ > this->buffer_.size()) return false; + + std::memmove(output, this->buffer_.data() + this->current_byte_, bytes); + this->current_byte_ += bytes; + + return true; + } + + bool byte_buffer::write(const int bytes, const void* data) + { + this->buffer_.append(static_cast(data), bytes); + this->current_byte_ += bytes; + return true; + } + + bool byte_buffer::write(const std::string& data) + { + return this->write(static_cast(data.size()), data.data()); + } + + void byte_buffer::set_use_data_types(const bool use_data_types) + { + this->use_data_types_ = use_data_types; + } + + size_t byte_buffer::size() const + { + return this->buffer_.size(); + } + + bool byte_buffer::is_using_data_types() const + { + return use_data_types_; + } + + std::string& byte_buffer::get_buffer() + { + return this->buffer_; + } + + std::string byte_buffer::get_remaining() + { + return std::string(this->buffer_.begin() + this->current_byte_, this->buffer_.end()); + } + + bool byte_buffer::has_more_data() const + { + return this->buffer_.size() > this->current_byte_; + } +} diff --git a/src/client/game/demonware/byte_buffer.hpp b/src/client/game/demonware/byte_buffer.hpp new file mode 100644 index 00000000..43e462aa --- /dev/null +++ b/src/client/game/demonware/byte_buffer.hpp @@ -0,0 +1,69 @@ +#pragma once + +namespace demonware +{ + class byte_buffer final + { + public: + byte_buffer() = default; + + explicit byte_buffer(std::string buffer) : buffer_(std::move(buffer)) + { + } + + bool read_byte(unsigned char* output); + bool read_bool(bool* output); + bool read_int16(short* output); + bool read_uint16(unsigned short* output); + bool read_int32(int* output); + bool read_uint32(unsigned int* output); + bool read_int64(__int64* output); + bool read_uint64(unsigned __int64* output); + bool read_float(float* output); + bool read_string(char** output); + bool read_string(char* output, int length); + bool read_string(std::string* output); + bool read_blob(char** output, int* length); + bool read_blob(std::string* output); + bool read_data_type(char expected); + + bool read_array_header(unsigned char expected, unsigned int* element_count, + unsigned int* element_size = nullptr); + + bool write_byte(char data); + bool write_bool(bool data); + bool write_int16(short data); + bool write_uint16(unsigned short data); + bool write_int32(int data); + bool write_uint32(unsigned int data); + bool write_int64(__int64 data); + bool write_uint64(unsigned __int64 data); + bool write_data_type(char data); + bool write_float(float data); + bool write_string(const char* data); + bool write_string(const std::string& data); + bool write_blob(const char* data, int length); + bool write_blob(const std::string& data); + + bool write_array_header(unsigned char type, unsigned int element_count, unsigned int element_size); + + bool read(int bytes, void* output); + bool write(int bytes, const void* data); + bool write(const std::string& data); + + void set_use_data_types(bool use_data_types); + size_t size() const; + + bool is_using_data_types() const; + + std::string& get_buffer(); + std::string get_remaining(); + + bool has_more_data() const; + + private: + std::string buffer_; + size_t current_byte_ = 0; + bool use_data_types_ = true; + }; +} diff --git a/src/client/game/demonware/data_types.hpp b/src/client/game/demonware/data_types.hpp new file mode 100644 index 00000000..579e2248 --- /dev/null +++ b/src/client/game/demonware/data_types.hpp @@ -0,0 +1,210 @@ +#pragma once + +#include "byte_buffer.hpp" + +namespace demonware +{ + class bdTaskResult + { + public: + virtual ~bdTaskResult() = default; + + virtual void serialize(byte_buffer*) + { + } + + virtual void deserialize(byte_buffer*) + { + } + }; + + class bdFileData final : public bdTaskResult + { + public: + std::string file_data; + + explicit bdFileData(std::string buffer) : file_data(std::move(buffer)) + { + } + + void serialize(byte_buffer* buffer) override + { + buffer->write_blob(this->file_data); + } + + void deserialize(byte_buffer* buffer) override + { + buffer->read_blob(&this->file_data); + } + }; + + class bdFileInfo final : public bdTaskResult + { + public: + uint64_t file_id; + uint32_t create_time; + uint32_t modified_time; + bool priv; + uint64_t owner_id; + std::string filename; + uint32_t file_size; + + void serialize(byte_buffer* buffer) override + { + buffer->write_uint32(this->file_size); + buffer->write_uint64(this->file_id); + buffer->write_uint32(this->create_time); + buffer->write_uint32(this->modified_time); + buffer->write_bool(this->priv); + buffer->write_uint64(this->owner_id); + buffer->write_string(this->filename); + } + + void deserialize(byte_buffer* buffer) override + { + buffer->read_uint32(&this->file_size); + buffer->read_uint64(&this->file_id); + buffer->read_uint32(&this->create_time); + buffer->read_uint32(&this->modified_time); + buffer->read_bool(&this->priv); + buffer->read_uint64(&this->owner_id); + buffer->read_string(&this->filename); + } + }; + + class bdTimeStamp final : public bdTaskResult + { + public: + uint32_t unix_time; + + void serialize(byte_buffer* buffer) override + { + buffer->write_uint32(this->unix_time); + } + + void deserialize(byte_buffer* buffer) override + { + buffer->read_uint32(&this->unix_time); + } + }; + + class bdDMLInfo : public bdTaskResult + { + public: + std::string country_code; // Char [3] + std::string country; // Char [65] + std::string region; // Char [65] + std::string city; // Char [129] + float latitude; + float longitude; + + void serialize(byte_buffer* buffer) override + { + buffer->write_string(this->country_code); + buffer->write_string(this->country); + buffer->write_string(this->region); + buffer->write_string(this->city); + buffer->write_float(this->latitude); + buffer->write_float(this->longitude); + } + + void deserialize(byte_buffer* buffer) override + { + buffer->read_string(&this->country_code); + buffer->read_string(&this->country); + buffer->read_string(&this->region); + buffer->read_string(&this->city); + buffer->read_float(&this->latitude); + buffer->read_float(&this->longitude); + } + }; + + class bdDMLRawData final : public bdDMLInfo + { + public: + uint32_t asn; // Autonomous System Number. + std::string timezone; + + void serialize(byte_buffer* buffer) override + { + bdDMLInfo::serialize(buffer); + + buffer->write_uint32(this->asn); + buffer->write_string(this->timezone); + } + + void deserialize(byte_buffer* buffer) override + { + bdDMLInfo::deserialize(buffer); + + buffer->read_uint32(&this->asn); + buffer->read_string(&this->timezone); + } + }; + + // made up name + class bdFile final : public bdTaskResult + { + public: + uint64_t owner_id; + std::string platform; + std::string filename; + uint32_t unk; + std::string data; + + void serialize(byte_buffer* buffer) override + { + buffer->write_uint64(this->owner_id); + buffer->write_string(this->platform); + buffer->write_string(this->filename); + buffer->write_uint32(this->unk); + buffer->write_blob(this->data); + } + + void deserialize(byte_buffer* buffer) override + { + buffer->read_uint64(&this->owner_id); + buffer->read_string(&this->platform); + buffer->read_string(&this->filename); + buffer->read_uint32(&this->unk); + buffer->read_blob(&this->data); + } + }; + + class bdFile2 final : public bdTaskResult + { + public: + uint32_t unk1; + uint32_t unk2; + uint32_t unk3; + bool priv; + uint64_t owner_id; + std::string platform; + std::string filename; + std::string data; + + void serialize(byte_buffer* buffer) override + { + buffer->write_uint32(this->unk1); + buffer->write_uint32(this->unk2); + buffer->write_uint32(this->unk3); + buffer->write_bool(this->priv); + buffer->write_uint64(this->owner_id); + buffer->write_string(this->platform); + buffer->write_string(this->filename); + buffer->write_blob(this->data); + } + + void deserialize(byte_buffer* buffer) override + { + buffer->read_uint32(&this->unk1); + buffer->read_uint32(&this->unk2); + buffer->read_uint32(&this->unk3); + buffer->read_bool(&this->priv); + buffer->read_uint64(&this->owner_id); + buffer->read_string(&this->platform); + buffer->read_string(&this->filename); + buffer->read_blob(&this->data); + } + }; +} diff --git a/src/client/game/demonware/keys.cpp b/src/client/game/demonware/keys.cpp new file mode 100644 index 00000000..b5ad226a --- /dev/null +++ b/src/client/game/demonware/keys.cpp @@ -0,0 +1,130 @@ +#include +#include "keys.hpp" + +#include +#include + +namespace demonware +{ + struct data_t + { + char m_session_key[24]; + char m_response[8]; + char m_hmac_key[20]; + char m_enc_key[16]; + char m_dec_key[16]; + } data{}; + + std::string packet_buffer; + + void calculate_hmacs_s1(const char* data_, const unsigned int data_size, const char* key, + const unsigned int key_size, + char* dst, const unsigned int dst_size) + { + char buffer[64]; + unsigned int pos = 0; + unsigned int out_offset = 0; + char count = 1; + std::string result; + + // buffer add key + std::memcpy(&buffer[pos], key, key_size); + pos += key_size; + + // buffer add count + buffer[pos] = count; + pos++; + + // calculate hmac + result = utils::cryptography::hmac_sha1::compute(std::string(buffer, pos), std::string(data_, data_size)); + + // save output + std::memcpy(dst, result.data(), std::min(20u, (dst_size - out_offset))); + out_offset = 20; + + // second loop + while (true) + { + // if we filled the output buffer, exit + if (out_offset >= dst_size) + break; + + // buffer add last result + pos = 0; + std::memcpy(&buffer[pos], result.data(), 20); + pos += 20; + + // buffer add key + std::memcpy(&buffer[pos], key, key_size); + pos += key_size; + + // buffer add count + count++; + buffer[pos] = count; + pos++; + + // calculate hmac + result = utils::cryptography::hmac_sha1::compute(std::string(buffer, pos), std::string(data_, data_size)); + + // save output + std::memcpy(dst + out_offset, result.data(), std::min(20u, (dst_size - out_offset))); + out_offset += 20; + } + } + + void derive_keys_s1() + { + const auto out_1 = utils::cryptography::sha1::compute(packet_buffer); // out_1 size 20 + + auto data_3 = utils::cryptography::hmac_sha1::compute(data.m_session_key, out_1); + + char out_2[16]; + calculate_hmacs_s1(data_3.data(), 20, "CLIENTCHAL", 10, out_2, 16); + + char out_3[72]; + calculate_hmacs_s1(data_3.data(), 20, "BDDATA", 6, out_3, 72); + + std::memcpy(data.m_response, &out_2[8], 8); + std::memcpy(data.m_hmac_key, &out_3[20], 20); + std::memcpy(data.m_dec_key, &out_3[40], 16); + std::memcpy(data.m_enc_key, &out_3[56], 16); + +#ifdef DEBUG + printf("[DW] Response id: %s\n", utils::string::dump_hex(std::string(&out_2[8], 8)).data()); + printf("[DW] Hash verify: %s\n", utils::string::dump_hex(std::string(&out_3[20], 20)).data()); + printf("[DW] AES dec key: %s\n", utils::string::dump_hex(std::string(&out_3[40], 16)).data()); + printf("[DW] AES enc key: %s\n", utils::string::dump_hex(std::string(&out_3[56], 16)).data()); + printf("[DW] Bravo 6, going dark.\n"); +#endif + } + + void queue_packet_to_hash(const std::string& packet) + { + packet_buffer.append(packet); + } + + void set_session_key(const std::string& key) + { + std::memcpy(data.m_session_key, key.data(), 24); + } + + std::string get_decrypt_key() + { + return std::string(data.m_dec_key, 16); + } + + std::string get_encrypt_key() + { + return std::string(data.m_enc_key, 16); + } + + std::string get_hmac_key() + { + return std::string(data.m_hmac_key, 20); + } + + std::string get_response_id() + { + return std::string(data.m_response, 8); + } +} diff --git a/src/client/game/demonware/keys.hpp b/src/client/game/demonware/keys.hpp new file mode 100644 index 00000000..e2d29c69 --- /dev/null +++ b/src/client/game/demonware/keys.hpp @@ -0,0 +1,12 @@ +#pragma once + +namespace demonware +{ + void derive_keys_s1(); + void queue_packet_to_hash(const std::string& packet); + void set_session_key(const std::string& key); + std::string get_decrypt_key(); + std::string get_encrypt_key(); + std::string get_hmac_key(); + std::string get_response_id(); +} diff --git a/src/client/game/demonware/reply.cpp b/src/client/game/demonware/reply.cpp new file mode 100644 index 00000000..09c5cc74 --- /dev/null +++ b/src/client/game/demonware/reply.cpp @@ -0,0 +1,87 @@ +#include +#include "keys.hpp" +#include "reply.hpp" +#include "servers/service_server.hpp" + +#include + +namespace demonware +{ + std::string unencrypted_reply::data() + { + byte_buffer result; + result.set_use_data_types(false); + + result.write_int32(static_cast(this->buffer_.size()) + 2); + result.write_bool(false); + result.write_byte(this->type()); + result.write(this->buffer_); + + return result.get_buffer(); + } + + std::string encrypted_reply::data() + { + byte_buffer result; + result.set_use_data_types(false); + + byte_buffer enc_buffer; + enc_buffer.set_use_data_types(false); + + enc_buffer.write_uint32(static_cast(this->buffer_.size())); // service data size CHECKTHIS!! + enc_buffer.write_byte(this->type()); // TASK_REPLY type + enc_buffer.write(this->buffer_); // service data + + auto aligned_data = enc_buffer.get_buffer(); + auto size = aligned_data.size(); + size = ~15 & (size + 15); // 16 byte align + aligned_data.resize(size); + + // seed + std::string seed("\x5E\xED\x5E\xED\x5E\xED\x5E\xED\x5E\xED\x5E\xED\x5E\xED\x5E\xED", 16); + + // encrypt + const auto enc_data = utils::cryptography::aes::encrypt(aligned_data, seed, demonware::get_encrypt_key()); + + // header : encrypted service data : hash + static auto msg_count = 0; + msg_count++; + + byte_buffer response; + response.set_use_data_types(false); + + response.write_int32(30 + static_cast(enc_data.size())); + response.write_byte(static_cast(0xAB)); + response.write_byte(static_cast(0x85)); + response.write_int32(msg_count); + response.write(16, seed.data()); + response.write(enc_data); + + // hash entire packet and append end + auto hash_data = utils::cryptography::hmac_sha1::compute(response.get_buffer(), demonware::get_hmac_key()); + hash_data.resize(8); + response.write(8, hash_data.data()); + + return response.get_buffer(); + } + + void remote_reply::send(bit_buffer* buffer, const bool encrypted) + { + std::unique_ptr reply; + + if (encrypted) reply = std::make_unique(this->type_, buffer); + else reply = std::make_unique(this->type_, buffer); + + this->server_->send_reply(reply.get()); + } + + void remote_reply::send(byte_buffer* buffer, const bool encrypted) + { + std::unique_ptr reply; + + if (encrypted) reply = std::make_unique(this->type_, buffer); + else reply = std::make_unique(this->type_, buffer); + + this->server_->send_reply(reply.get()); + } +} diff --git a/src/client/game/demonware/reply.hpp b/src/client/game/demonware/reply.hpp new file mode 100644 index 00000000..b7724dfd --- /dev/null +++ b/src/client/game/demonware/reply.hpp @@ -0,0 +1,164 @@ +#pragma once + +#include "bit_buffer.hpp" +#include "byte_buffer.hpp" +#include "data_types.hpp" + +namespace demonware +{ + class reply + { + public: + reply() = default; + + reply(reply&&) = delete; + reply(const reply&) = delete; + reply& operator=(reply&&) = delete; + reply& operator=(const reply&) = delete; + + virtual ~reply() = default; + virtual std::string data() = 0; + }; + + class raw_reply : public reply + { + protected: + std::string buffer_; + + public: + raw_reply() = default; + + explicit raw_reply(std::string data) : buffer_(std::move(data)) + { + } + + std::string data() override + { + return this->buffer_; + } + }; + + class typed_reply : public raw_reply + { + public: + typed_reply(const uint8_t _type) : type_(_type) + { + } + + protected: + uint8_t type() const { return this->type_; } + + private: + uint8_t type_; + }; + + class encrypted_reply final : public typed_reply + { + public: + encrypted_reply(const uint8_t type, bit_buffer* bbuffer) : typed_reply(type) + { + this->buffer_.append(bbuffer->get_buffer()); + } + + encrypted_reply(const uint8_t type, byte_buffer* bbuffer) : typed_reply(type) + { + this->buffer_.append(bbuffer->get_buffer()); + } + + std::string data() override; + }; + + class unencrypted_reply final : public typed_reply + { + public: + unencrypted_reply(const uint8_t _type, bit_buffer* bbuffer) : typed_reply(_type) + { + this->buffer_.append(bbuffer->get_buffer()); + } + + unencrypted_reply(const uint8_t _type, byte_buffer* bbuffer) : typed_reply(_type) + { + this->buffer_.append(bbuffer->get_buffer()); + } + + std::string data() override; + }; + + class service_server; + + class remote_reply final + { + public: + remote_reply(service_server* server, uint8_t _type) : type_(_type), server_(server) + { + } + + void send(bit_buffer* buffer, bool encrypted); + void send(byte_buffer* buffer, bool encrypted); + + uint8_t type() const { return this->type_; } + + private: + uint8_t type_; + service_server* server_; + }; + + class service_reply final + { + public: + service_reply(service_server* _server, const uint8_t _type, const uint32_t _error) + : type_(_type), error_(_error), reply_(_server, 1) + { + } + + uint64_t send() + { + static uint64_t id = 0x0000000000000000; + const auto transaction_id = ++id; + + byte_buffer buffer; + buffer.write_uint64(transaction_id); + buffer.write_uint32(this->error_); + buffer.write_byte(this->type_); + + if (!this->error_) + { + buffer.write_uint32(uint32_t(this->objects_.size())); + if (!this->objects_.empty()) + { + buffer.write_uint32(uint32_t(this->objects_.size())); + + for (auto& object : this->objects_) + { + object->serialize(&buffer); + } + + this->objects_.clear(); + } + } + else + { + buffer.write_uint64(transaction_id); + } + + this->reply_.send(&buffer, true); + return transaction_id; + } + + void add(const std::shared_ptr& object) + { + this->objects_.push_back(object); + } + + void add(bdTaskResult* object) + { + this->add(std::shared_ptr(object)); + } + + private: + uint8_t type_; + uint32_t error_; + remote_reply reply_; + std::vector> objects_; + }; +} diff --git a/src/client/game/demonware/server_registry.hpp b/src/client/game/demonware/server_registry.hpp new file mode 100644 index 00000000..725e24c6 --- /dev/null +++ b/src/client/game/demonware/server_registry.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include "servers/base_server.hpp" +#include + +namespace demonware +{ + template + class server_registry + { + static_assert(std::is_base_of::value, "Invalid server registry type"); + + public: + template + void create(Args&&... args) + { + static_assert(std::is_base_of::value, "Invalid server type"); + + auto server = std::make_unique(std::forward(args)...); + const auto address = server->get_address(); + servers_[address] = std::move(server); + } + + void for_each(const std::function& callback) const + { + for (auto& server : servers_) + { + callback(*server.second); + } + } + + T* find(const std::string& name) + { + const auto address = utils::cryptography::jenkins_one_at_a_time::compute(name); + return find(address); + } + + T* find(const uint32_t address) + { + const auto it = servers_.find(address); + if (it == servers_.end()) + { + return nullptr; + } + + return it->second.get(); + } + + void frame() + { + for (auto& server : servers_) + { + server.second->frame(); + } + } + + private: + std::unordered_map> servers_; + }; +} diff --git a/src/client/game/demonware/servers/auth3_server.cpp b/src/client/game/demonware/servers/auth3_server.cpp new file mode 100644 index 00000000..9ea470fa --- /dev/null +++ b/src/client/game/demonware/servers/auth3_server.cpp @@ -0,0 +1,168 @@ +#include + +#include "auth3_server.hpp" +#include "../keys.hpp" + +#include +#include + +namespace demonware +{ + namespace + { +#pragma pack(push, 1) + struct auth_ticket + { + unsigned int m_magicNumber; + char m_type; + unsigned int m_titleID; + unsigned int m_timeIssued; + unsigned int m_timeExpires; + unsigned __int64 m_licenseID; + unsigned __int64 m_userID; + char m_username[64]; + char m_sessionKey[24]; + char m_usingHashMagicNumber[3]; + char m_hash[4]; + }; +#pragma pack(pop) + } + + void auth3_server::send_reply(reply* data) + { + if (!data) return; + this->send(data->data()); + } + + void auth3_server::handle(const std::string& packet) + { + if (packet.starts_with("POST /auth/")) + { +#ifdef DEBUG + printf("[DW]: [auth]: user requested authentication.\n"); +#endif + return; + } + + unsigned int title_id = 0; + unsigned int iv_seed = 0; + std::string identity{}; + std::string token{}; + + rapidjson::Document j; + j.Parse(packet.data(), packet.size()); + + if (j.HasMember("title_id") && j["title_id"].IsString()) + { + title_id = std::stoul(j["title_id"].GetString()); + } + + if (j.HasMember("iv_seed") && j["iv_seed"].IsString()) + { + iv_seed = std::stoul(j["iv_seed"].GetString()); + } + + if (j.HasMember("identity") && j["identity"].IsString()) + { + identity = j["identity"].GetString(); + } + + if (j.HasMember("extra_data") && j["extra_data"].IsString()) + { + rapidjson::Document extra_data; + auto& ed = j["extra_data"]; + extra_data.Parse(ed.GetString(), ed.GetStringLength()); + + if (extra_data.HasMember("token") && extra_data["token"].IsString()) + { + auto& token_field = extra_data["token"]; + std::string token_b64(token_field.GetString(), token_field.GetStringLength()); + token = utils::cryptography::base64::decode(token_b64); + } + } + +#ifdef DEBUG + printf("[DW]: [auth]: authenticating user %s\n", token.data() + 64); +#endif + + std::string auth_key(reinterpret_cast(token.data() + 32), 24); + std::string session_key( + "\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37", 24); + + // client_ticket + auth_ticket ticket{}; + std::memset(&ticket, 0x0, sizeof ticket); + ticket.m_magicNumber = 0x0EFBDADDE; + ticket.m_type = 0; + ticket.m_titleID = title_id; + ticket.m_timeIssued = static_cast(time(nullptr)); + ticket.m_timeExpires = ticket.m_timeIssued + 30000; + ticket.m_licenseID = 0; + ticket.m_userID = reinterpret_cast(token.data() + 56); + strncpy_s(ticket.m_username, sizeof(ticket.m_username), reinterpret_cast(token.data() + 64), 64); + std::memcpy(ticket.m_sessionKey, session_key.data(), 24); + + const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast(&iv_seed), 4)); + const auto ticket_enc = utils::cryptography::des3::encrypt( + std::string(reinterpret_cast(&ticket), sizeof(ticket)), iv, auth_key); + const auto ticket_b64 = utils::cryptography::base64::encode( + reinterpret_cast(ticket_enc.data()), 128); + + // server_ticket + uint8_t auth_data[128]; + std::memset(&auth_data, 0, sizeof auth_data); + std::memcpy(auth_data, session_key.data(), 24); + const auto auth_data_b64 = utils::cryptography::base64::encode(auth_data, 128); + + demonware::set_session_key(session_key); + + // header time + char date[64]; + const auto now = time(nullptr); + tm gmtm{}; + gmtime_s(&gmtm, &now); + strftime(date, 64, "%a, %d %b %G %T", &gmtm); + + // json content + rapidjson::Document doc; + doc.SetObject(); + + doc.AddMember("auth_task", "29", doc.GetAllocator()); + doc.AddMember("code", "700", doc.GetAllocator()); + + auto seed = std::to_string(iv_seed); + doc.AddMember("iv_seed", rapidjson::StringRef(seed.data(), seed.size()), doc.GetAllocator()); + doc.AddMember("client_ticket", rapidjson::StringRef(ticket_b64.data(), ticket_b64.size()), doc.GetAllocator()); + doc.AddMember("server_ticket", rapidjson::StringRef(auth_data_b64.data(), auth_data_b64.size()), + doc.GetAllocator()); + doc.AddMember("client_id", "", doc.GetAllocator()); + doc.AddMember("account_type", "steam", doc.GetAllocator()); + doc.AddMember("crossplay_enabled", false, doc.GetAllocator()); + doc.AddMember("loginqueue_eanbled", false, doc.GetAllocator()); + + rapidjson::Value value{}; + doc.AddMember("lsg_endpoint", value, doc.GetAllocator()); + + rapidjson::StringBuffer buffer{}; + rapidjson::Writer> + writer(buffer); + doc.Accept(writer); + + // http stuff + std::string result; + result.append("HTTP/1.1 200 OK\r\n"); + result.append("Server: TornadoServer/4.5.3\r\n"); + result.append("Content-Type: application/json\r\n"); + result.append(utils::string::va("Date: %s GMT\r\n", date)); + result.append(utils::string::va("Content-Length: %d\r\n\r\n", buffer.GetLength())); + result.append(buffer.GetString(), buffer.GetLength()); + + raw_reply reply(result); + + this->send_reply(&reply); + +#ifdef DEBUG + printf("[DW]: [auth]: user successfully authenticated.\n"); +#endif + } +} diff --git a/src/client/game/demonware/servers/auth3_server.hpp b/src/client/game/demonware/servers/auth3_server.hpp new file mode 100644 index 00000000..e58e73e7 --- /dev/null +++ b/src/client/game/demonware/servers/auth3_server.hpp @@ -0,0 +1,16 @@ +#pragma once +#include "tcp_server.hpp" +#include "../reply.hpp" + +namespace demonware +{ + class auth3_server : public tcp_server + { + public: + using tcp_server::tcp_server; + + private: + void send_reply(reply* data); + void handle(const std::string& packet) override; + }; +} diff --git a/src/client/game/demonware/servers/base_server.cpp b/src/client/game/demonware/servers/base_server.cpp new file mode 100644 index 00000000..727a36a6 --- /dev/null +++ b/src/client/game/demonware/servers/base_server.cpp @@ -0,0 +1,22 @@ +#include +#include "base_server.hpp" + +#include + +namespace demonware +{ + base_server::base_server(std::string name): name_(std::move(name)) + { + this->address_ = utils::cryptography::jenkins_one_at_a_time::compute(this->name_); + } + + const std::string& base_server::get_name() const + { + return this->name_; + } + + uint32_t base_server::get_address() const + { + return this->address_; + } +} diff --git a/src/client/game/demonware/servers/base_server.hpp b/src/client/game/demonware/servers/base_server.hpp new file mode 100644 index 00000000..1c3e5aa0 --- /dev/null +++ b/src/client/game/demonware/servers/base_server.hpp @@ -0,0 +1,30 @@ +#pragma once + +namespace demonware +{ + class base_server + { + public: + using stream_queue = std::queue; + using data_queue = std::queue; + + base_server(std::string name); + + base_server(base_server&&) = delete; + base_server(const base_server&) = delete; + base_server& operator=(base_server&&) = delete; + base_server& operator=(const base_server&) = delete; + + virtual ~base_server() = default; + + const std::string& get_name() const; + + uint32_t get_address() const; + + virtual void frame() = 0; + + private: + std::string name_; + std::uint32_t address_ = 0; + }; +} diff --git a/src/client/game/demonware/servers/lobby_server.cpp b/src/client/game/demonware/servers/lobby_server.cpp new file mode 100644 index 00000000..04b52aaa --- /dev/null +++ b/src/client/game/demonware/servers/lobby_server.cpp @@ -0,0 +1,178 @@ +#include +#include "lobby_server.hpp" + +#include "../services.hpp" +#include "../keys.hpp" + +#include + +namespace demonware +{ + lobby_server::lobby_server(std::string name) : tcp_server(std::move(name)) + { + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + this->register_service(); + }; + + void lobby_server::send_reply(reply* data) + { + if (!data) return; + this->send(data->data()); + } + + void lobby_server::handle(const std::string& packet) + { + byte_buffer buffer(packet); + buffer.set_use_data_types(false); + + try + { + while (buffer.has_more_data()) + { + int size; + buffer.read_int32(&size); + + if (size <= 0) + { + const std::string zero("\x00\x00\x00\x00", 4); + raw_reply reply(zero); + this->send_reply(&reply); + return; + } + else if (size == 0xC8) + { +#ifdef DEBUG + printf("[DW]: [lobby]: received client_header_ack.\n"); +#endif + + int c8; + buffer.read_int32(&c8); + std::string packet_1 = buffer.get_remaining(); + demonware::queue_packet_to_hash(packet_1); + + const std::string packet_2( + "\x16\x00\x00\x00\xab\x81\xd2\x00\x00\x00\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37", + 26); + demonware::queue_packet_to_hash(packet_2); + + raw_reply reply(packet_2); + this->send_reply(&reply); +#ifdef DEBUG + printf("[DW]: [lobby]: sending server_header_ack.\n"); +#endif + return; + } + + if (buffer.size() < size_t(size)) return; + + uint8_t check_ab; + buffer.read_byte(&check_ab); + if (check_ab == 0xAB) + { + uint8_t type; + buffer.read_byte(&type); + + if (type == 0x82) + { +#ifdef DEBUG + printf("[DW]: [lobby]: received client_auth.\n"); +#endif + std::string packet_3(packet.data(), packet.size() - 8); // this 8 are client hash check? + + demonware::queue_packet_to_hash(packet_3); + demonware::derive_keys_s1(); + + char buff[14] = "\x0A\x00\x00\x00\xAB\x83"; + std::memcpy(&buff[6], demonware::get_response_id().data(), 8); + std::string response(buff, 14); + + raw_reply reply(response); + this->send_reply(&reply); + +#ifdef DEBUG + printf("[DW]: [lobby]: sending server_auth_done.\n"); +#endif + return; + } + else if (type == 0x85) + { + uint32_t msg_count; + buffer.read_uint32(&msg_count); + + char seed[16]; + buffer.read(16, &seed); + + std::string enc = buffer.get_remaining(); + + char hash[8]; + std::memcpy(hash, &(enc.data()[enc.size() - 8]), 8); + + std::string dec = utils::cryptography::aes::decrypt( + std::string(enc.data(), enc.size() - 8), std::string(seed, 16), + demonware::get_decrypt_key()); + + byte_buffer serv(dec); + serv.set_use_data_types(false); + + uint32_t serv_size; + serv.read_uint32(&serv_size); + + uint8_t magic; // 0x86 + serv.read_byte(&magic); + + uint8_t service_id; + serv.read_byte(&service_id); + + this->call_service(service_id, serv.get_remaining()); + + return; + } + } + + printf("[DW]: [lobby]: ERROR! received unk message.\n"); + return; + } + } + catch (...) + { + } + } + + void lobby_server::call_service(const uint8_t id, const std::string& data) + { + const auto& it = this->services_.find(id); + + if (it != this->services_.end()) + { + it->second->exec_task(this, data); + } + else + { + printf("[DW]: [lobby]: missing service '%s'\n", utils::string::va("%d", id)); + + // return no error + byte_buffer buffer(data); + uint8_t task_id; + buffer.read_byte(&task_id); + + this->create_reply(task_id)->send(); + } + } +} diff --git a/src/client/game/demonware/servers/lobby_server.hpp b/src/client/game/demonware/servers/lobby_server.hpp new file mode 100644 index 00000000..8f1bda94 --- /dev/null +++ b/src/client/game/demonware/servers/lobby_server.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "tcp_server.hpp" +#include "service_server.hpp" +#include "../service.hpp" + +namespace demonware +{ + class lobby_server : public tcp_server, service_server + { + public: + lobby_server(std::string name); + + template + void register_service() + { + static_assert(std::is_base_of::value, "service must inherit from service"); + + auto service = std::make_unique(); + const uint8_t id = service->id(); + + this->services_[id] = std::move(service); + } + + void send_reply(reply* data) override; + + private: + std::unordered_map> services_; + + void handle(const std::string& packet) override; + void call_service(uint8_t id, const std::string& data); + }; +} diff --git a/src/client/game/demonware/servers/service_server.hpp b/src/client/game/demonware/servers/service_server.hpp new file mode 100644 index 00000000..dcf40fe7 --- /dev/null +++ b/src/client/game/demonware/servers/service_server.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "../reply.hpp" + +namespace demonware +{ + class service_server + { + public: + virtual ~service_server() = default; + + virtual std::shared_ptr create_message(uint8_t type) + { + auto reply = std::make_shared(this, type); + return reply; + } + + + virtual std::shared_ptr create_reply(uint8_t type, uint32_t error = 0) + { + auto reply = std::make_shared(this, type, error); + return reply; + } + + virtual void send_reply(reply* data) = 0; + }; +} diff --git a/src/client/game/demonware/servers/stun_server.cpp b/src/client/game/demonware/servers/stun_server.cpp new file mode 100644 index 00000000..0814d5ff --- /dev/null +++ b/src/client/game/demonware/servers/stun_server.cpp @@ -0,0 +1,62 @@ +#include +#include "stun_server.hpp" + +#include "../byte_buffer.hpp" + +namespace demonware +{ + void stun_server::handle(const endpoint_data& endpoint, const std::string& packet) + { + uint8_t type, version, padding; + + byte_buffer buffer(packet); + buffer.set_use_data_types(false); + buffer.read_byte(&type); + buffer.read_byte(&version); + buffer.read_byte(&padding); + + switch (type) + { + case 30: + this->ip_discovery(endpoint); + break; + case 20: + this->nat_discovery(endpoint); + break; + default: + break; + } + } + + void stun_server::ip_discovery(const endpoint_data& endpoint) + { + const uint32_t ip = 0x0100007f; + + byte_buffer buffer; + buffer.set_use_data_types(false); + buffer.write_byte(31); // type + buffer.write_byte(2); // version + buffer.write_byte(0); // version + buffer.write_uint32(ip); // external ip + buffer.write_uint16(3074); // port + + this->send(endpoint, buffer.get_buffer()); + } + + void stun_server::nat_discovery(const endpoint_data& endpoint) + { + const uint32_t ip = 0x0100007f; + + byte_buffer buffer; + buffer.set_use_data_types(false); + buffer.write_byte(21); // type + buffer.write_byte(2); // version + buffer.write_byte(0); // version + buffer.write_uint32(ip); // external ip + buffer.write_uint16(3074); // port + buffer.write_uint32(this->get_address()); // server ip + buffer.write_uint16(3074); // server port + + this->send(endpoint, buffer.get_buffer()); + } +} diff --git a/src/client/game/demonware/servers/stun_server.hpp b/src/client/game/demonware/servers/stun_server.hpp new file mode 100644 index 00000000..cb4192e1 --- /dev/null +++ b/src/client/game/demonware/servers/stun_server.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "udp_server.hpp" + +namespace demonware +{ + class stun_server : public udp_server + { + public: + using udp_server::udp_server; + + private: + void handle(const endpoint_data& endpoint, const std::string& packet) override; + + void ip_discovery(const endpoint_data& endpoint); + void nat_discovery(const endpoint_data& endpoint); + }; +} diff --git a/src/client/game/demonware/servers/tcp_server.cpp b/src/client/game/demonware/servers/tcp_server.cpp new file mode 100644 index 00000000..8e60d20a --- /dev/null +++ b/src/client/game/demonware/servers/tcp_server.cpp @@ -0,0 +1,84 @@ +#include +#include "tcp_server.hpp" + +namespace demonware +{ + void tcp_server::handle_input(const char* buf, size_t size) + { + in_queue_.access([&](data_queue& queue) + { + queue.emplace(buf, size); + }); + } + + size_t tcp_server::handle_output(char* buf, size_t size) + { + if (out_queue_.get_raw().empty()) + { + return 0; + } + + return out_queue_.access([&](stream_queue& queue) + { + for (size_t i = 0; i < size; ++i) + { + if (queue.empty()) + { + return i; + } + + buf[i] = queue.front(); + queue.pop(); + } + + return size; + }); + } + + bool tcp_server::pending_data() + { + return !this->out_queue_.get_raw().empty(); + } + + void tcp_server::frame() + { + if (this->in_queue_.get_raw().empty()) + { + return; + } + + while (true) + { + std::string packet{}; + const auto result = this->in_queue_.access([&](data_queue& queue) + { + if (queue.empty()) + { + return false; + } + + packet = std::move(queue.front()); + queue.pop(); + return true; + }); + + if (!result) + { + break; + } + + this->handle(packet); + } + } + + void tcp_server::send(const std::string& data) + { + out_queue_.access([&](stream_queue& queue) + { + for (const auto& val : data) + { + queue.push(val); + } + }); + } +} diff --git a/src/client/game/demonware/servers/tcp_server.hpp b/src/client/game/demonware/servers/tcp_server.hpp new file mode 100644 index 00000000..3f6967ee --- /dev/null +++ b/src/client/game/demonware/servers/tcp_server.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "base_server.hpp" +#include + +namespace demonware +{ + class tcp_server : public base_server + { + public: + using base_server::base_server; + + void handle_input(const char* buf, size_t size); + size_t handle_output(char* buf, size_t size); + bool pending_data(); + void frame() override; + + protected: + virtual void handle(const std::string& data) = 0; + + void send(const std::string& data); + + private: + utils::concurrency::container in_queue_; + utils::concurrency::container out_queue_; + }; +} diff --git a/src/client/game/demonware/servers/udp_server.cpp b/src/client/game/demonware/servers/udp_server.cpp new file mode 100644 index 00000000..019c3f84 --- /dev/null +++ b/src/client/game/demonware/servers/udp_server.cpp @@ -0,0 +1,103 @@ +#include +#include "udp_server.hpp" + +namespace demonware +{ + void udp_server::handle_input(const char* buf, size_t size, endpoint_data endpoint) + { + in_queue_.access([&](in_queue& queue) + { + in_packet p; + p.data = std::string{buf, size}; + p.endpoint = std::move(endpoint); + + queue.emplace(std::move(p)); + }); + } + + size_t udp_server::handle_output(SOCKET socket, char* buf, size_t size, sockaddr* address, int* addrlen) + { + return out_queue_.access([&](socket_queue_map& map) -> size_t + { + const auto entry = map.find(socket); + if (entry == map.end()) + { + return 0; + } + + auto& queue = entry->second; + + if (queue.empty()) + { + return 0; + } + + auto data = std::move(queue.front()); + queue.pop(); + + const auto copy_size = std::min(size, data.data.size()); + std::memcpy(buf, data.data.data(), copy_size); + std::memcpy(address, &data.address, sizeof(data.address)); + *addrlen = sizeof(data.address); + + return copy_size; + }); + } + + bool udp_server::pending_data(SOCKET socket) + { + return this->out_queue_.access([&](const socket_queue_map& map) + { + const auto entry = map.find(socket); + if (entry == map.end()) + { + return false; + } + + return !entry->second.empty(); + }); + } + + void udp_server::send(const endpoint_data& endpoint, std::string data) + { + out_queue_.access([&](socket_queue_map& map) + { + out_packet p; + p.data = std::move(data); + p.address = endpoint.address; + + map[endpoint.socket].emplace(std::move(p)); + }); + } + + void udp_server::frame() + { + if (this->in_queue_.get_raw().empty()) + { + return; + } + + while (true) + { + in_packet packet{}; + const auto result = this->in_queue_.access([&](in_queue& queue) + { + if (queue.empty()) + { + return false; + } + + packet = std::move(queue.front()); + queue.pop(); + return true; + }); + + if (!result) + { + break; + } + + this->handle(packet.endpoint, std::move(packet.data)); + } + } +} diff --git a/src/client/game/demonware/servers/udp_server.hpp b/src/client/game/demonware/servers/udp_server.hpp new file mode 100644 index 00000000..340c5980 --- /dev/null +++ b/src/client/game/demonware/servers/udp_server.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include "base_server.hpp" +#include + +namespace demonware +{ + class udp_server : public base_server + { + public: + struct endpoint_data + { + SOCKET socket{}; + sockaddr_in address{}; + + endpoint_data() = default; + + endpoint_data(const SOCKET sock, const sockaddr* addr, const int size) + { + if (size != sizeof(this->address)) + { + throw std::runtime_error("Invalid size"); + } + + this->socket = sock; + std::memcpy(&this->address, addr, sizeof(this->address)); + } + }; + + using base_server::base_server; + + void handle_input(const char* buf, size_t size, endpoint_data endpoint); + size_t handle_output(SOCKET socket, char* buf, size_t size, sockaddr* address, int* addrlen); + bool pending_data(SOCKET socket); + + void frame() override; + + protected: + virtual void handle(const endpoint_data& endpoint, const std::string& data) = 0; + void send(const endpoint_data& endpoint, std::string data); + + private: + struct in_packet + { + std::string data; + endpoint_data endpoint; + }; + + struct out_packet + { + std::string data; + sockaddr_in address; + }; + + using in_queue = std::queue; + using out_queue = std::queue; + using socket_queue_map = std::unordered_map; + + utils::concurrency::container in_queue_; + utils::concurrency::container out_queue_; + }; +} diff --git a/src/client/game/demonware/servers/umbrella_server.cpp b/src/client/game/demonware/servers/umbrella_server.cpp new file mode 100644 index 00000000..cadce9dd --- /dev/null +++ b/src/client/game/demonware/servers/umbrella_server.cpp @@ -0,0 +1,11 @@ +#include + +#include "umbrella_server.hpp" + +namespace demonware +{ + void umbrella_server::handle(const std::string& packet) + { + // TODO: + } +} diff --git a/src/client/game/demonware/servers/umbrella_server.hpp b/src/client/game/demonware/servers/umbrella_server.hpp new file mode 100644 index 00000000..6507270c --- /dev/null +++ b/src/client/game/demonware/servers/umbrella_server.hpp @@ -0,0 +1,14 @@ +#pragma once +#include "tcp_server.hpp" + +namespace demonware +{ + class umbrella_server : public tcp_server + { + public: + using tcp_server::tcp_server; + + private: + void handle(const std::string& packet) override; + }; +} diff --git a/src/client/game/demonware/service.hpp b/src/client/game/demonware/service.hpp new file mode 100644 index 00000000..ada7e845 --- /dev/null +++ b/src/client/game/demonware/service.hpp @@ -0,0 +1,89 @@ +#pragma once +#include +#include "servers/service_server.hpp" + +namespace demonware +{ + class service + { + using callback_t = std::function; + + uint8_t id_; + std::string name_; + std::mutex mutex_; + uint8_t task_id_; + std::map tasks_; + + public: + virtual ~service() = default; + service(service&&) = delete; + service(const service&) = delete; + service& operator=(const service&) = delete; + + service(const uint8_t id, std::string name) : id_(id), name_(std::move(name)), task_id_(0) + { + } + + uint8_t id() const + { + return this->id_; + } + + const std::string& name() const + { + return this->name_; + } + + uint8_t task_id() const + { + return this->task_id_; + } + + virtual void exec_task(service_server* server, const std::string& data) + { + std::lock_guard _(this->mutex_); + + byte_buffer buffer(data); + + buffer.read_byte(&this->task_id_); + + const auto& it = this->tasks_.find(this->task_id_); + + if (it != this->tasks_.end()) + { +#ifdef DEBUG + printf("[DW] %s: executing task '%d'\n", name_.data(), this->task_id_); +#endif + + it->second(server, &buffer); + } + else + { + printf("[DW] %s: missing task '%d'\n", name_.data(), this->task_id_); + + // return no error + server->create_reply(this->task_id_)->send(); + } + } + + protected: + + template + void register_task(const uint8_t id, T (Class::* callback)(Args ...) const) + { + this->tasks_[id] = [this, callback](Args ... args) -> T + { + return (reinterpret_cast(this)->*callback)(args...); + }; + } + + template + void register_task(const uint8_t id, T (Class::* callback)(Args ...)) + { + this->tasks_[id] = [this, callback](Args ... args) -> T + { + return (reinterpret_cast(this)->*callback)(args...); + }; + } + }; +} diff --git a/src/client/game/demonware/services.hpp b/src/client/game/demonware/services.hpp new file mode 100644 index 00000000..86326c7e --- /dev/null +++ b/src/client/game/demonware/services.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include "bit_buffer.hpp" +#include "byte_buffer.hpp" +#include "data_types.hpp" +#include "reply.hpp" +#include "service.hpp" +#include "servers/service_server.hpp" + +//#include "services/bdTeams.hpp" // 3 +#include "services/bdStats.hpp" // 4 +//#include "services/bdMessaging.hpp" // 6 +#include "services/bdProfiles.hpp" // 8 +#include "services/bdStorage.hpp" // 10 +#include "services/bdTitleUtilities.hpp" // 12 +#include "services/bdBandwidthTest.hpp" // 18 +//#include "services/bdMatchMaking.hpp" // 21 +#include "services/bdCounters.hpp" // 23 +#include "services/bdDML.hpp" // 27 +#include "services/bdGroups.hpp" // 28 +//#include "services/bdCMail.hpp" // 29 +#include "services/bdFacebook.hpp" // 36 +#include "services/bdAnticheat.hpp" // 38 +#include "services/bdContentStreaming.hpp" // 50 +//#include "services/bdTags.hpp" // 52 +#include "services/bdUNK63.hpp" // 63 +#include "services/bdEventLog.hpp" // 67 +#include "services/bdRichPresence.hpp" // 68 +//#include "services/bdTitleUtilities2.hpp" // 72 +#include "services/bdUNK80.hpp" +#include "services/bdUNK95.hpp" +// AccountLinking // 86 +#include "services/bdPresence.hpp" //103 +#include "services/bdMarketingComms.hpp" //104 +#include "services/bdMatchMaking2.hpp" //138 +#include "services/bdMarketing.hpp" //139 diff --git a/src/client/game/demonware/services/bdAnticheat.cpp b/src/client/game/demonware/services/bdAnticheat.cpp new file mode 100644 index 00000000..9d69e186 --- /dev/null +++ b/src/client/game/demonware/services/bdAnticheat.cpp @@ -0,0 +1,25 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdAnticheat::bdAnticheat() : service(38, "bdAnticheat") + { + this->register_task(2, &bdAnticheat::unk2); + this->register_task(4, &bdAnticheat::report_console_details); + } + + void bdAnticheat::unk2(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: Read data as soon as needed + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdAnticheat::report_console_details(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: Read data as soon as needed + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdAnticheat.hpp b/src/client/game/demonware/services/bdAnticheat.hpp new file mode 100644 index 00000000..0e65bc2d --- /dev/null +++ b/src/client/game/demonware/services/bdAnticheat.hpp @@ -0,0 +1,14 @@ +#pragma once + +namespace demonware +{ + class bdAnticheat final : public service + { + public: + bdAnticheat(); + + private: + void unk2(service_server* server, byte_buffer* buffer) const; + void report_console_details(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdBandwidthTest.cpp b/src/client/game/demonware/services/bdBandwidthTest.cpp new file mode 100644 index 00000000..2c41e4d2 --- /dev/null +++ b/src/client/game/demonware/services/bdBandwidthTest.cpp @@ -0,0 +1,27 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + static uint8_t bandwidth_iw6[51] = + { + 0x0F, 0xC1, 0x1C, 0x37, 0xB8, 0xEF, 0x7C, 0xD6, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xF4, 0x01, 0x00, 0x00, 0xD0, 0x07, + 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x88, 0x13, 0x00, 0x00, 0xF4, 0x01, + 0x00, 0x00, 0x02, 0x0C, 0x88, 0xB3, 0x04, 0x65, 0x89, 0xBF, 0xC3, 0x6A, + 0x27, 0x94, 0xD4, 0x8F + }; + + bdBandwidthTest::bdBandwidthTest() : service(18, "bdBandwidthTest") + { + } + + void bdBandwidthTest::exec_task(service_server* server, const std::string& data) + { + byte_buffer buffer; + buffer.write(sizeof bandwidth_iw6, bandwidth_iw6); + + auto reply = server->create_message(5); + reply->send(&buffer, true); + } +} diff --git a/src/client/game/demonware/services/bdBandwidthTest.hpp b/src/client/game/demonware/services/bdBandwidthTest.hpp new file mode 100644 index 00000000..c4feb8e9 --- /dev/null +++ b/src/client/game/demonware/services/bdBandwidthTest.hpp @@ -0,0 +1,13 @@ +#pragma once + +namespace demonware +{ + class bdBandwidthTest final : public service + { + public: + bdBandwidthTest(); + + private: + void exec_task(service_server* server, const std::string& data) override; + }; +} diff --git a/src/client/game/demonware/services/bdContentStreaming.cpp b/src/client/game/demonware/services/bdContentStreaming.cpp new file mode 100644 index 00000000..efd4db18 --- /dev/null +++ b/src/client/game/demonware/services/bdContentStreaming.cpp @@ -0,0 +1,25 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdContentStreaming::bdContentStreaming() : service(50, "bdContentStreaming") + { + this->register_task(2, &bdContentStreaming::unk2); + this->register_task(3, &bdContentStreaming::unk3); + } + + void bdContentStreaming::unk2(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdContentStreaming::unk3(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdContentStreaming.hpp b/src/client/game/demonware/services/bdContentStreaming.hpp new file mode 100644 index 00000000..68319662 --- /dev/null +++ b/src/client/game/demonware/services/bdContentStreaming.hpp @@ -0,0 +1,14 @@ +#pragma once + +namespace demonware +{ + class bdContentStreaming final : public service + { + public: + bdContentStreaming(); + + private: + void unk2(service_server* server, byte_buffer* buffer) const; + void unk3(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdCounters.cpp b/src/client/game/demonware/services/bdCounters.cpp new file mode 100644 index 00000000..70aa8736 --- /dev/null +++ b/src/client/game/demonware/services/bdCounters.cpp @@ -0,0 +1,25 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdCounters::bdCounters() : service(23, "bdCounters") + { + this->register_task(1, &bdCounters::unk1); + this->register_task(2, &bdCounters::unk2); + } + + void bdCounters::unk1(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdCounters::unk2(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdCounters.hpp b/src/client/game/demonware/services/bdCounters.hpp new file mode 100644 index 00000000..cc6a6932 --- /dev/null +++ b/src/client/game/demonware/services/bdCounters.hpp @@ -0,0 +1,14 @@ +#pragma once + +namespace demonware +{ + class bdCounters final : public service + { + public: + bdCounters(); + + private: + void unk1(service_server* server, byte_buffer* buffer) const; + void unk2(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdDML.cpp b/src/client/game/demonware/services/bdDML.cpp new file mode 100644 index 00000000..75e18ca4 --- /dev/null +++ b/src/client/game/demonware/services/bdDML.cpp @@ -0,0 +1,28 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdDML::bdDML() : service(27, "bdDML") + { + this->register_task(2, &bdDML::get_user_raw_data); + } + + void bdDML::get_user_raw_data(service_server* server, byte_buffer* /*buffer*/) const + { + auto result = new bdDMLRawData; + result->country_code = "US"; + result->country_code = "'Murica"; + result->region = "New York"; + result->city = "New York"; + result->latitude = 0; + result->longitude = 0; + + result->asn = 0x2119; + result->timezone = "+01:00"; + + auto reply = server->create_reply(this->task_id()); + reply->add(result); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdDML.hpp b/src/client/game/demonware/services/bdDML.hpp new file mode 100644 index 00000000..08faa594 --- /dev/null +++ b/src/client/game/demonware/services/bdDML.hpp @@ -0,0 +1,13 @@ +#pragma once + +namespace demonware +{ + class bdDML final : public service + { + public: + bdDML(); + + private: + void get_user_raw_data(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdEventLog.cpp b/src/client/game/demonware/services/bdEventLog.cpp new file mode 100644 index 00000000..c6eaa2b7 --- /dev/null +++ b/src/client/game/demonware/services/bdEventLog.cpp @@ -0,0 +1,17 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdEventLog::bdEventLog() : service(67, "bdEventLog") + { + this->register_task(6, &bdEventLog::unk6); + } + + void bdEventLog::unk6(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdEventLog.hpp b/src/client/game/demonware/services/bdEventLog.hpp new file mode 100644 index 00000000..ade4912d --- /dev/null +++ b/src/client/game/demonware/services/bdEventLog.hpp @@ -0,0 +1,13 @@ +#pragma once + +namespace demonware +{ + class bdEventLog final : public service + { + public: + bdEventLog(); + + private: + void unk6(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdFacebook.cpp b/src/client/game/demonware/services/bdFacebook.cpp new file mode 100644 index 00000000..ffa1c5b9 --- /dev/null +++ b/src/client/game/demonware/services/bdFacebook.cpp @@ -0,0 +1,41 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdFacebook::bdFacebook() : service(36, "bdFacebook") + { + this->register_task(1, &bdFacebook::unk1); + this->register_task(3, &bdFacebook::unk3); + this->register_task(7, &bdFacebook::unk7); + this->register_task(8, &bdFacebook::unk8); + } + + void bdFacebook::unk1(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdFacebook::unk3(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdFacebook::unk7(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdFacebook::unk8(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdFacebook.hpp b/src/client/game/demonware/services/bdFacebook.hpp new file mode 100644 index 00000000..dc12339a --- /dev/null +++ b/src/client/game/demonware/services/bdFacebook.hpp @@ -0,0 +1,16 @@ +#pragma once + +namespace demonware +{ + class bdFacebook final : public service + { + public: + bdFacebook(); + + private: + void unk1(service_server* server, byte_buffer* buffer) const; + void unk3(service_server* server, byte_buffer* buffer) const; + void unk7(service_server* server, byte_buffer* buffer) const; + void unk8(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdGroups.cpp b/src/client/game/demonware/services/bdGroups.cpp new file mode 100644 index 00000000..116d5e7e --- /dev/null +++ b/src/client/game/demonware/services/bdGroups.cpp @@ -0,0 +1,25 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdGroups::bdGroups() : service(28, "bdGroup") + { + this->register_task(1, &bdGroups::set_groups); + this->register_task(4, &bdGroups::unk4); + } + + void bdGroups::set_groups(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdGroups::unk4(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdGroups.hpp b/src/client/game/demonware/services/bdGroups.hpp new file mode 100644 index 00000000..ff42f1cf --- /dev/null +++ b/src/client/game/demonware/services/bdGroups.hpp @@ -0,0 +1,14 @@ +#pragma once + +namespace demonware +{ + class bdGroups final : public service + { + public: + bdGroups(); + + private: + void set_groups(service_server* server, byte_buffer* buffer) const; + void unk4(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdMarketing.cpp b/src/client/game/demonware/services/bdMarketing.cpp new file mode 100644 index 00000000..1009cc30 --- /dev/null +++ b/src/client/game/demonware/services/bdMarketing.cpp @@ -0,0 +1,25 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdMarketing::bdMarketing() : service(139, "bdMarketing") + { + this->register_task(2, &bdMarketing::unk2); + this->register_task(3, &bdMarketing::unk3); + } + + void bdMarketing::unk2(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdMarketing::unk3(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdMarketing.hpp b/src/client/game/demonware/services/bdMarketing.hpp new file mode 100644 index 00000000..455e1523 --- /dev/null +++ b/src/client/game/demonware/services/bdMarketing.hpp @@ -0,0 +1,14 @@ +#pragma once + +namespace demonware +{ + class bdMarketing final : public service + { + public: + bdMarketing(); + + private: + void unk2(service_server* server, byte_buffer* buffer) const; + void unk3(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdMarketingComms.cpp b/src/client/game/demonware/services/bdMarketingComms.cpp new file mode 100644 index 00000000..5cbbe7bb --- /dev/null +++ b/src/client/game/demonware/services/bdMarketingComms.cpp @@ -0,0 +1,17 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdMarketingComms::bdMarketingComms() : service(104, "bdMarketingComms") + { + this->register_task(1, &bdMarketingComms::get_messages); + } + + void bdMarketingComms::get_messages(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdMarketingComms.hpp b/src/client/game/demonware/services/bdMarketingComms.hpp new file mode 100644 index 00000000..76179493 --- /dev/null +++ b/src/client/game/demonware/services/bdMarketingComms.hpp @@ -0,0 +1,13 @@ +#pragma once + +namespace demonware +{ + class bdMarketingComms final : public service + { + public: + bdMarketingComms(); + + private: + void get_messages(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdMatchMaking2.cpp b/src/client/game/demonware/services/bdMatchMaking2.cpp new file mode 100644 index 00000000..4e9a9ea8 --- /dev/null +++ b/src/client/game/demonware/services/bdMatchMaking2.cpp @@ -0,0 +1,57 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdMatchMaking2::bdMatchMaking2() : service(138, "bdMatchMaking2") + { + this->register_task(1, &bdMatchMaking2::unk1); + this->register_task(2, &bdMatchMaking2::unk2); + this->register_task(3, &bdMatchMaking2::unk3); + this->register_task(5, &bdMatchMaking2::unk5); + this->register_task(10, &bdMatchMaking2::unk10); + this->register_task(16, &bdMatchMaking2::unk16); + } + + void bdMatchMaking2::unk1(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdMatchMaking2::unk2(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdMatchMaking2::unk3(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdMatchMaking2::unk5(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdMatchMaking2::unk10(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdMatchMaking2::unk16(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdMatchMaking2.hpp b/src/client/game/demonware/services/bdMatchMaking2.hpp new file mode 100644 index 00000000..30fa4ee8 --- /dev/null +++ b/src/client/game/demonware/services/bdMatchMaking2.hpp @@ -0,0 +1,18 @@ +#pragma once + +namespace demonware +{ + class bdMatchMaking2 final : public service + { + public: + bdMatchMaking2(); + + private: + void unk1(service_server* server, byte_buffer* buffer) const; + void unk2(service_server* server, byte_buffer* buffer) const; + void unk3(service_server* server, byte_buffer* buffer) const; + void unk5(service_server* server, byte_buffer* buffer) const; + void unk10(service_server* server, byte_buffer* buffer) const; + void unk16(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdPresence.cpp b/src/client/game/demonware/services/bdPresence.cpp new file mode 100644 index 00000000..a043a169 --- /dev/null +++ b/src/client/game/demonware/services/bdPresence.cpp @@ -0,0 +1,25 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdPresence::bdPresence() : service(103, "bdPresence") + { + this->register_task(1, &bdPresence::unk1); + this->register_task(3, &bdPresence::unk3); + } + + void bdPresence::unk1(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdPresence::unk3(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdPresence.hpp b/src/client/game/demonware/services/bdPresence.hpp new file mode 100644 index 00000000..df76cae2 --- /dev/null +++ b/src/client/game/demonware/services/bdPresence.hpp @@ -0,0 +1,14 @@ +#pragma once + +namespace demonware +{ + class bdPresence final : public service + { + public: + bdPresence(); + + private: + void unk1(service_server* server, byte_buffer* buffer) const; + void unk3(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdProfiles.cpp b/src/client/game/demonware/services/bdProfiles.cpp new file mode 100644 index 00000000..ded5fac4 --- /dev/null +++ b/src/client/game/demonware/services/bdProfiles.cpp @@ -0,0 +1,17 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdProfiles::bdProfiles() : service(8, "bdProfiles") + { + this->register_task(3, &bdProfiles::unk3); + } + + void bdProfiles::unk3(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdProfiles.hpp b/src/client/game/demonware/services/bdProfiles.hpp new file mode 100644 index 00000000..3c090e86 --- /dev/null +++ b/src/client/game/demonware/services/bdProfiles.hpp @@ -0,0 +1,13 @@ +#pragma once + +namespace demonware +{ + class bdProfiles final : public service + { + public: + bdProfiles(); + + private: + void unk3(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdRichPresence.cpp b/src/client/game/demonware/services/bdRichPresence.cpp new file mode 100644 index 00000000..917ebbad --- /dev/null +++ b/src/client/game/demonware/services/bdRichPresence.cpp @@ -0,0 +1,25 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdRichPresence::bdRichPresence() : service(68, "bdRichPresence") + { + this->register_task(1, &bdRichPresence::unk1); + this->register_task(2, &bdRichPresence::unk2); + } + + void bdRichPresence::unk1(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdRichPresence::unk2(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdRichPresence.hpp b/src/client/game/demonware/services/bdRichPresence.hpp new file mode 100644 index 00000000..c04d91a5 --- /dev/null +++ b/src/client/game/demonware/services/bdRichPresence.hpp @@ -0,0 +1,14 @@ +#pragma once + +namespace demonware +{ + class bdRichPresence final : public service + { + public: + bdRichPresence(); + + private: + void unk1(service_server* server, byte_buffer* buffer) const; + void unk2(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdStats.cpp b/src/client/game/demonware/services/bdStats.cpp new file mode 100644 index 00000000..d01b5709 --- /dev/null +++ b/src/client/game/demonware/services/bdStats.cpp @@ -0,0 +1,49 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdStats::bdStats() : service(4, "bdStats") + { + this->register_task(1, &bdStats::unk1); + this->register_task(3, &bdStats::unk3); // leaderboards + this->register_task(4, &bdStats::unk4); + this->register_task(8, &bdStats::unk8); + this->register_task(11, &bdStats::unk11); + } + + void bdStats::unk1(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdStats::unk3(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdStats::unk4(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdStats::unk8(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdStats::unk11(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdStats.hpp b/src/client/game/demonware/services/bdStats.hpp new file mode 100644 index 00000000..e84a6436 --- /dev/null +++ b/src/client/game/demonware/services/bdStats.hpp @@ -0,0 +1,17 @@ +#pragma once + +namespace demonware +{ + class bdStats final : public service + { + public: + bdStats(); + + private: + void unk1(service_server* server, byte_buffer* buffer) const; + void unk3(service_server* server, byte_buffer* buffer) const; + void unk4(service_server* server, byte_buffer* buffer) const; + void unk8(service_server* server, byte_buffer* buffer) const; + void unk11(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdStorage.cpp b/src/client/game/demonware/services/bdStorage.cpp new file mode 100644 index 00000000..1cae2206 --- /dev/null +++ b/src/client/game/demonware/services/bdStorage.cpp @@ -0,0 +1,266 @@ +#include +#include "../services.hpp" + +#include +#include +#include + +#include "game/game.hpp" + +namespace demonware +{ + bdStorage::bdStorage() : service(10, "bdStorage") + { + this->register_task(20, &bdStorage::list_publisher_files); + this->register_task(21, &bdStorage::get_publisher_file); + this->register_task(24, &bdStorage::set_user_file); + this->register_task(16, &bdStorage::get_user_file); + this->register_task(12, &bdStorage::unk12); + + this->map_publisher_resource("motd-.*\\.txt", DW_MOTD); + // this->map_publisher_resource("ffotd-.*\\.ff", DW_FASTFILE); + this->map_publisher_resource("playlists(_.+)?\\.aggr", DW_PLAYLISTS); + } + + void bdStorage::map_publisher_resource(const std::string& expression, const INT id) + { + auto data = utils::nt::load_resource(id); + this->map_publisher_resource_variant(expression, std::move(data)); + } + + void bdStorage::map_publisher_resource_variant(const std::string& expression, resource_variant resource) + { + if (resource.valueless_by_exception()) + { + throw std::runtime_error("Publisher resource variant is empty!"); + } + + this->publisher_resources_.emplace_back(std::regex{expression}, std::move(resource)); + } + + bool bdStorage::load_publisher_resource(const std::string& name, std::string& buffer) + { + for (const auto& resource : this->publisher_resources_) + { + if (std::regex_match(name, resource.first)) + { + if (std::holds_alternative(resource.second)) + { + buffer = std::get(resource.second); + } + else + { + buffer = std::get(resource.second)(); + } + + return true; + } + } + +#ifdef DEBUG + printf("[DW]: [bdStorage]: missing publisher file: %s\n", name.data()); +#endif + + return false; + } + + void bdStorage::list_publisher_files(service_server* server, byte_buffer* buffer) + { +#ifdef DEBUG + utils::io::write_file("demonware/bdStorage/list_publisher_files", buffer->get_buffer()); +#endif + + uint32_t date; + uint16_t num_results, offset; + std::string unk, filename, data; + + buffer->read_string(&unk); + buffer->read_uint32(&date); + buffer->read_uint16(&num_results); + buffer->read_uint16(&offset); + buffer->read_string(&filename); + +#ifdef DEBUG + printf("[DW]: [bdStorage]: list publisher files: %s\n", filename.data()); +#endif + + auto reply = server->create_reply(this->task_id()); + + if (this->load_publisher_resource(filename, data)) + { + auto* info = new bdFileInfo; + + info->file_id = *reinterpret_cast(utils::cryptography::sha1::compute(filename).data()); + info->filename = filename; + info->create_time = 0; + info->modified_time = info->create_time; + info->file_size = uint32_t(data.size()); + info->owner_id = 0; + info->priv = false; + + reply->add(info); + } + + reply->send(); + } + + void bdStorage::get_publisher_file(service_server* server, byte_buffer* buffer) + { +#ifdef DEBUG + utils::io::write_file("demonware/bdStorage/get_publisher_file", buffer->get_buffer()); +#endif + + std::string unk, filename; + buffer->read_string(&unk); + buffer->read_string(&filename); + +#ifdef DEBUG + printf("[DW]: [bdStorage]: loading publisher file: %s\n", filename.data()); +#endif + + std::string data; + + if (this->load_publisher_resource(filename, data)) + { +#ifdef DEBUG + printf("[DW]: [bdStorage]: sending publisher file: %s, size: %lld\n", filename.data(), data.size()); +#endif + + auto reply = server->create_reply(this->task_id()); + reply->add(new bdFileData(data)); + reply->send(); + } + else + { + server->create_reply(this->task_id(), game::BD_NO_FILE)->send(); + } + } + + std::string bdStorage::get_user_file_path(const std::string& name) + { + return "players2/user/" + name; + } + + void bdStorage::set_user_file(service_server* server, byte_buffer* buffer) const + { +#ifdef DEBUG + utils::io::write_file("demonware/bdStorage/set_user_file", buffer->get_buffer()); +#endif + + uint64_t owner; + uint32_t numfiles; + std::string game, platform; + + buffer->read_string(&game); + buffer->read_uint64(&owner); + buffer->read_string(&platform); + buffer->read_uint32(&numfiles); + + auto reply = server->create_reply(this->task_id()); + + for (uint32_t i = 0; i < numfiles; i++) + { + std::string filename, data; + uint32_t unk; + bool priv; + + buffer->read_string(&filename); + buffer->read_blob(&data); + buffer->read_uint32(&unk); + buffer->read_bool(&priv); + + const auto path = get_user_file_path(filename); + utils::io::write_file(path, data); + + auto* info = new bdFile2; + + info->unk1 = 0; + info->unk2 = 0; + info->unk3 = 0; + info->priv = false; + info->owner_id = owner; + info->platform = platform; + info->filename = filename; + info->data = data; + +#ifdef DEBUG + printf("[DW]: [bdStorage]: set user file: %s\n", filename.data()); +#endif + + reply->add(info); + } + + reply->send(); + } + + void bdStorage::get_user_file(service_server* server, byte_buffer* buffer) const + { +#ifdef DEBUG + utils::io::write_file("demonware/bdStorage/get_user_file", buffer->get_buffer()); +#endif + + uint32_t unk32_0; + uint32_t numfiles, count = 0; + uint64_t owner; + std::string game, platform; + + buffer->read_string(&game); + buffer->read_uint32(&unk32_0); + buffer->read_uint64(&owner); + buffer->read_string(&platform); + buffer->read_uint64(&owner); + buffer->read_string(&platform); + buffer->read_uint32(&numfiles); + + auto reply = server->create_reply(this->task_id()); + + for (uint32_t i = 0; i < numfiles; i++) + { + std::string filename, data; + buffer->read_string(&filename); + + const auto path = get_user_file_path(filename); + if (!utils::io::read_file(path, &data)) + { +#ifdef DEBUG + printf("[DW]: [bdStorage]: get user file: missing file: %s, %s, %s\n", game.data(), filename.data(), platform.data()); +#endif + continue; + } + + auto response = new bdFile; + response->owner_id = owner; + response->unk = 0; + response->platform = platform; + response->filename = filename; + response->data = data; + + reply->add(response); + ++count; + +#ifdef DEBUG + printf("[DW]: [bdStorage]: get user file: %s, %s, %s\n", game.data(), filename.data(), platform.data()); +#endif + } + + if (count == numfiles) + { + reply->send(); + } + else + { + server->create_reply(this->task_id(), game::BD_NO_FILE)->send(); + } + } + + void bdStorage::unk12(service_server* server, byte_buffer* buffer) const + { +#ifdef DEBUG + utils::io::write_file("demonware/bdStorage/unk12", buffer->get_buffer()); +#endif + + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdStorage.hpp b/src/client/game/demonware/services/bdStorage.hpp new file mode 100644 index 00000000..88382538 --- /dev/null +++ b/src/client/game/demonware/services/bdStorage.hpp @@ -0,0 +1,27 @@ +#pragma once + +namespace demonware +{ + class bdStorage final : public service + { + public: + bdStorage(); + + private: + using callback = std::function; + using resource_variant = std::variant; + std::vector> publisher_resources_; + + void map_publisher_resource(const std::string& expression, INT id); + void map_publisher_resource_variant(const std::string& expression, resource_variant resource); + bool load_publisher_resource(const std::string& name, std::string& buffer); + + void list_publisher_files(service_server* server, byte_buffer* buffer); + void get_publisher_file(service_server* server, byte_buffer* buffer); + void set_user_file(service_server* server, byte_buffer* buffer) const; + void get_user_file(service_server* server, byte_buffer* buffer) const; + void unk12(service_server* server, byte_buffer* buffer) const; + + static std::string get_user_file_path(const std::string& name); + }; +} diff --git a/src/client/game/demonware/services/bdTitleUtilities.cpp b/src/client/game/demonware/services/bdTitleUtilities.cpp new file mode 100644 index 00000000..8b1f90e9 --- /dev/null +++ b/src/client/game/demonware/services/bdTitleUtilities.cpp @@ -0,0 +1,20 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdTitleUtilities::bdTitleUtilities() : service(12, "bdTitleUtilities") + { + this->register_task(6, &bdTitleUtilities::get_server_time); + } + + void bdTitleUtilities::get_server_time(service_server* server, byte_buffer* /*buffer*/) const + { + auto* const time_result = new bdTimeStamp; + time_result->unix_time = uint32_t(time(nullptr)); + + auto reply = server->create_reply(this->task_id()); + reply->add(time_result); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdTitleUtilities.hpp b/src/client/game/demonware/services/bdTitleUtilities.hpp new file mode 100644 index 00000000..3f57105d --- /dev/null +++ b/src/client/game/demonware/services/bdTitleUtilities.hpp @@ -0,0 +1,13 @@ +#pragma once + +namespace demonware +{ + class bdTitleUtilities final : public service + { + public: + bdTitleUtilities(); + + private: + void get_server_time(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdUNK63.cpp b/src/client/game/demonware/services/bdUNK63.cpp new file mode 100644 index 00000000..e6f4945a --- /dev/null +++ b/src/client/game/demonware/services/bdUNK63.cpp @@ -0,0 +1,17 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdUNK63::bdUNK63() : service(63, "bdUNK63") + { + //this->register_task(6, "unk6", &bdUNK63::unk6); + } + + void bdUNK63::unk(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdUNK63.hpp b/src/client/game/demonware/services/bdUNK63.hpp new file mode 100644 index 00000000..85ed78bf --- /dev/null +++ b/src/client/game/demonware/services/bdUNK63.hpp @@ -0,0 +1,13 @@ +#pragma once + +namespace demonware +{ + class bdUNK63 final : public service + { + public: + bdUNK63(); + + private: + void unk(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdUNK80.cpp b/src/client/game/demonware/services/bdUNK80.cpp new file mode 100644 index 00000000..65c458c4 --- /dev/null +++ b/src/client/game/demonware/services/bdUNK80.cpp @@ -0,0 +1,66 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdUNK80::bdUNK80() : service(80, "bdUNK80") + { + this->register_task(42, &bdUNK80::unk42); // COD POINTS purchase ? + // this->register_task(43, &bdUNK80::unk43); COD POINTS purchase ? + this->register_task(49, &bdUNK80::unk49); + this->register_task(60, &bdUNK80::unk60); + this->register_task(130, &bdUNK80::unk130); + this->register_task(165, &bdUNK80::unk165); + this->register_task(193, &bdUNK80::unk193); + this->register_task(232, &bdUNK80::unk232); + } + + void bdUNK80::unk42(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdUNK80::unk49(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdUNK80::unk60(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdUNK80::unk130(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdUNK80::unk165(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdUNK80::unk193(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } + + void bdUNK80::unk232(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdUNK80.hpp b/src/client/game/demonware/services/bdUNK80.hpp new file mode 100644 index 00000000..2870de13 --- /dev/null +++ b/src/client/game/demonware/services/bdUNK80.hpp @@ -0,0 +1,19 @@ +#pragma once + +namespace demonware +{ + class bdUNK80 final : public service + { + public: + bdUNK80(); + + private: + void unk42(service_server* server, byte_buffer* buffer) const; + void unk49(service_server* server, byte_buffer* buffer) const; + void unk60(service_server* server, byte_buffer* buffer) const; + void unk130(service_server* server, byte_buffer* buffer) const; + void unk165(service_server* server, byte_buffer* buffer) const; + void unk193(service_server* server, byte_buffer* buffer) const; + void unk232(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/demonware/services/bdUNK95.cpp b/src/client/game/demonware/services/bdUNK95.cpp new file mode 100644 index 00000000..3cac7302 --- /dev/null +++ b/src/client/game/demonware/services/bdUNK95.cpp @@ -0,0 +1,17 @@ +#include +#include "../services.hpp" + +namespace demonware +{ + bdUNK95::bdUNK95() : service(95, "bdUNK95") + { + this->register_task(1, &bdUNK95::unk1); + } + + void bdUNK95::unk1(service_server* server, byte_buffer* /*buffer*/) const + { + // TODO: + auto reply = server->create_reply(this->task_id()); + reply->send(); + } +} diff --git a/src/client/game/demonware/services/bdUNK95.hpp b/src/client/game/demonware/services/bdUNK95.hpp new file mode 100644 index 00000000..790395d3 --- /dev/null +++ b/src/client/game/demonware/services/bdUNK95.hpp @@ -0,0 +1,13 @@ +#pragma once + +namespace demonware +{ + class bdUNK95 final : public service + { + public: + bdUNK95(); + + private: + void unk1(service_server* server, byte_buffer* buffer) const; + }; +} diff --git a/src/client/game/dvars.cpp b/src/client/game/dvars.cpp new file mode 100644 index 00000000..3bde483a --- /dev/null +++ b/src/client/game/dvars.cpp @@ -0,0 +1,121 @@ +#include +#include "loader/component_loader.hpp" + +#include + +#include "game.hpp" +#include "dvars.hpp" +#include +#include + +namespace dvars +{ + std::string dvar_get_vector_domain(const int components, const game::dvar_limits& domain) + { + if (domain.vector.min == -FLT_MAX) + { + if (domain.vector.max == FLT_MAX) + { + return utils::string::va("Domain is any %iD vector", components); + } + else + { + return utils::string::va("Domain is any %iD vector with components %g or smaller", components, + domain.vector.max); + } + } + else if (domain.vector.max == FLT_MAX) + { + return utils::string::va("Domain is any %iD vector with components %g or bigger", components, + domain.vector.min); + } + else + { + return utils::string::va("Domain is any %iD vector with components from %g to %g", components, + domain.vector.min, domain.vector.max); + } + } + + std::string dvar_get_domain(const game::dvar_type type, const game::dvar_limits& domain) + { + std::string str; + + switch (type) + { + case game::dvar_type::boolean: + return "Domain is 0 or 1"s; + + case game::dvar_type::value: + if (domain.value.min == -FLT_MAX) + { + if (domain.value.max == FLT_MAX) + { + return "Domain is any number"s; + } + else + { + return utils::string::va("Domain is any number %g or smaller", domain.value.max); + } + } + else if (domain.value.max == FLT_MAX) + { + return utils::string::va("Domain is any number %g or bigger", domain.value.min); + } + else + { + return utils::string::va("Domain is any number from %g to %g", domain.value.min, domain.value.max); + } + + case game::dvar_type::vec2: + return dvar_get_vector_domain(2, domain); + + case game::dvar_type::rgb: + case game::dvar_type::vec3: + return dvar_get_vector_domain(3, domain); + + case game::dvar_type::vec4: + return dvar_get_vector_domain(4, domain); + + case game::dvar_type::integer: + if (domain.enumeration.stringCount == INT_MIN) + { + if (domain.integer.max == INT_MAX) + { + return "Domain is any integer"s; + } + else + { + return utils::string::va("Domain is any integer %i or smaller", domain.integer.max); + } + } + else if (domain.integer.max == INT_MAX) + { + return utils::string::va("Domain is any integer %i or bigger", domain.integer.min); + } + else + { + return utils::string::va("Domain is any integer from %i to %i", domain.integer.min, domain.integer.max); + } + + case game::dvar_type::color: + return "Domain is any 4-component color, in RGBA format"s; + + case game::dvar_type::enumeration: + str = "Domain is one of the following:"s; + + for (auto string_index = 0; string_index < domain.enumeration.stringCount; ++string_index) + { + str += utils::string::va("\n %2i: %s", string_index, domain.enumeration.strings[string_index]); + } + + return str; + + case game::dvar_type::string: + return "Domain is any text"s; + + default: + return utils::string::va("unhandled dvar type '%i'", type); + } + } + +} diff --git a/src/client/game/dvars.hpp b/src/client/game/dvars.hpp new file mode 100644 index 00000000..5cc5010e --- /dev/null +++ b/src/client/game/dvars.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "game.hpp" +#include "structs.hpp" + +namespace dvars +{ + std::string dvar_get_vector_domain(const int components, const game::dvar_limits& domain); + std::string dvar_get_domain(const game::dvar_type type, const game::dvar_limits& domain); +} diff --git a/src/client/game/game.cpp b/src/client/game/game.cpp new file mode 100644 index 00000000..434b46bc --- /dev/null +++ b/src/client/game/game.cpp @@ -0,0 +1,53 @@ +#include +#include "game.hpp" + +#include + +namespace game +{ + uint64_t base_address; + + void load_base_address() + { + const auto module = GetModuleHandle(NULL); + base_address = uint64_t(module); + } + + int Cmd_Argc() + { + return 0; //return cmd_args->argc[cmd_args->nesting]; + } + + const char* Cmd_Argv(const int index) + { + return 0; //return cmd_args->argv[cmd_args->nesting][index]; + } + + int SV_Cmd_Argc() + { + return 0; //return sv_cmd_args->argc[sv_cmd_args->nesting]; + } + + const char* SV_Cmd_Argv(const int index) + { + return 0; //return sv_cmd_args->argv[sv_cmd_args->nesting][index]; + } + + bool VirtualLobby_Loaded() + { + return 0; //return *mp::virtualLobby_loaded == 1; + } + + namespace environment + { + bool is_dedi() + { + return utils::flags::has_flag("dedicated"); + } + } +} + +uintptr_t operator"" _b(const uintptr_t ptr) +{ + return game::base_address + ptr; +} \ No newline at end of file diff --git a/src/client/game/game.hpp b/src/client/game/game.hpp new file mode 100644 index 00000000..a4b33909 --- /dev/null +++ b/src/client/game/game.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "structs.hpp" + +#define SERVER_CD_KEY "IW7MOD-CD-Key" + +namespace game +{ + extern uint64_t base_address; + void load_base_address(); + + template + class symbol + { + public: + symbol(const size_t address) + : address_(reinterpret_cast(address)) + { + } + + T* get() const + { + return reinterpret_cast((uint64_t)address_ + base_address); + } + + operator T* () const + { + return this->get(); + } + + T* operator->() const + { + return this->get(); + } + + private: + T* address_; + }; + + namespace environment + { + bool is_dedi(); + } + + int Cmd_Argc(); + const char* Cmd_Argv(int index); + + int SV_Cmd_Argc(); + const char* SV_Cmd_Argv(int index); + + bool VirtualLobby_Loaded(); +} + +uintptr_t operator"" _b(const uintptr_t ptr); + +#include "symbols.hpp" diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp new file mode 100644 index 00000000..ef5f1959 --- /dev/null +++ b/src/client/game/structs.hpp @@ -0,0 +1,519 @@ +#pragma once +#include + +#define PROTOCOL 1 + +namespace game +{ + typedef float vec_t; + typedef vec_t vec2_t[2]; + typedef vec_t vec3_t[3]; + typedef vec_t vec4_t[4]; + + struct cmd_function_s + { + cmd_function_s* next; + const char* name; + void(__cdecl* function)(); + }; + + enum DvarSetSource : std::uint32_t + { + DVAR_SOURCE_INTERNAL = 0x0, + DVAR_SOURCE_EXTERNAL = 0x1, + DVAR_SOURCE_SCRIPT = 0x2, + DVAR_SOURCE_UISCRIPT = 0x3, + DVAR_SOURCE_SERVERCMD = 0x4, + DVAR_SOURCE_NUM = 0x5, + }; + + enum DvarFlags : std::uint32_t + { + DVAR_FLAG_NONE = 0, + DVAR_FLAG_SAVED = 0x1, + DVAR_FLAG_LATCHED = 0x2, + DVAR_FLAG_CHEAT = 0x4, + DVAR_FLAG_REPLICATED = 0x8, + DVAR_FLAG_WRITE = 0x800, + DVAR_FLAG_READ = 0x2000, + }; + + enum dvar_type : std::int8_t + { + boolean = 0, + value = 1, + vec2 = 2, + vec3 = 3, + vec4 = 4, + integer = 5, + enumeration = 6, + string = 7, + color = 8, + rgb = 9 // Color without alpha + }; + + union dvar_value + { + bool enabled; + int integer; + unsigned int unsignedInt; + float value; + float vector[4]; + const char* string; + char color[4]; + }; + + struct $A37BA207B3DDD6345C554D4661813EDD + { + int stringCount; + const char* const* strings; + }; + + struct $9CA192F9DB66A3CB7E01DE78A0DEA53D + { + int min; + int max; + }; + + struct $251C2428A496074035CACA7AAF3D55BD + { + float min; + float max; + }; + + union dvar_limits + { + $A37BA207B3DDD6345C554D4661813EDD enumeration; + $9CA192F9DB66A3CB7E01DE78A0DEA53D integer; + $251C2428A496074035CACA7AAF3D55BD value; + $251C2428A496074035CACA7AAF3D55BD vector; + }; + + struct dvar_t + { + int hash; // 0 + unsigned int flags; // 4 + bool unk; // 8 tls value? + dvar_type type; // 9 + bool modified; // 10 + dvar_value current; // 16 + dvar_value latched; // 32 + dvar_value reset; // 48 + dvar_limits domain; // 64 + char unk2; // 80 always 0? + void* unk3; // 88 some pointer related to hash? + }; + static_assert(sizeof(dvar_t) == 96); + + namespace assets + { + enum XAssetType : std::int32_t + { + ASSET_TYPE_PHYSPRESET = 0x0, + }; + + struct RawFile + { + const char* name; + int compressedLen; + int len; + const char* buffer; + }; + + struct ScriptFile + { + const char* name; + int compressedLen; + int len; + int bytecodeLen; + const char* buffer; + char* bytecode; + }; + + struct LuaFile + { + const char* name; + int len; + char strippingType; + const char* buffer; + }; + } + using namespace assets; + + namespace demonware + { + enum DWOnlineStatus + { + DW_LIVE_DISCONNECTED = 0x0, + DW_LIVE_UNKNOWN = 0x1, + DW_LIVE_CONNECTING = 0x2, + DW_LIVE_CONNECTED = 0x3, + }; + + enum bdLobbyErrorCode : uint32_t + { + BD_NO_ERROR = 0x0, + BD_TOO_MANY_TASKS = 0x1, + BD_NOT_CONNECTED = 0x2, + BD_SEND_FAILED = 0x3, + BD_HANDLE_TASK_FAILED = 0x4, + BD_START_TASK_FAILED = 0x5, + BD_RESULT_EXCEEDS_BUFFER_SIZE = 0x64, + BD_ACCESS_DENIED = 0x65, + BD_EXCEPTION_IN_DB = 0x66, + BD_MALFORMED_TASK_HEADER = 0x67, + BD_INVALID_ROW = 0x68, + BD_EMPTY_ARG_LIST = 0x69, + BD_PARAM_PARSE_ERROR = 0x6A, + BD_PARAM_MISMATCHED_TYPE = 0x6B, + BD_SERVICE_NOT_AVAILABLE = 0x6C, + BD_CONNECTION_RESET = 0x6D, + BD_INVALID_USER_ID = 0x6E, + BD_LOBBY_PROTOCOL_VERSION_FAILURE = 0x6F, + BD_LOBBY_INTERNAL_FAILURE = 0x70, + BD_LOBBY_PROTOCOL_ERROR = 0x71, + BD_LOBBY_FAILED_TO_DECODE_UTF8 = 0x72, + BD_LOBBY_ASCII_EXPECTED = 0x73, + BD_ASYNCHRONOUS_ERROR = 0xC8, + BD_STREAMING_COMPLETE = 0xC9, + BD_MEMBER_NO_PROPOSAL = 0x12C, + BD_TEAMNAME_ALREADY_EXISTS = 0x12D, + BD_MAX_TEAM_MEMBERSHIPS_LIMITED = 0x12E, + BD_MAX_TEAM_OWNERSHIPS_LIMITED = 0x12F, + BD_NOT_A_TEAM_MEMBER = 0x130, + BD_INVALID_TEAM_ID = 0x131, + BD_INVALID_TEAM_NAME = 0x132, + BD_NOT_A_TEAM_OWNER = 0x133, + BD_NOT_AN_ADMIN_OR_OWNER = 0x134, + BD_MEMBER_PROPOSAL_EXISTS = 0x135, + BD_MEMBER_EXISTS = 0x136, + BD_TEAM_FULL = 0x137, + BD_VULGAR_TEAM_NAME = 0x138, + BD_TEAM_USERID_BANNED = 0x139, + BD_TEAM_EMPTY = 0x13A, + BD_INVALID_TEAM_PROFILE_QUERY_ID = 0x13B, + BD_TEAMNAME_TOO_SHORT = 0x13C, + BD_UNIQUE_PROFILE_DATA_EXISTS_ALREADY = 0x13D, + BD_INVALID_LEADERBOARD_ID = 0x190, + BD_INVALID_STATS_SET = 0x191, + BD_EMPTY_STATS_SET_IGNORED = 0x193, + BD_NO_DIRECT_ACCESS_TO_ARBITRATED_LBS = 0x194, + BD_STATS_WRITE_PERMISSION_DENIED = 0x195, + BD_STATS_WRITE_TYPE_DATA_TYPE_MISMATCH = 0x196, + BD_NO_STATS_FOR_USER = 0x197, + BD_INVALID_ACCESS_TO_UNRANKED_LB = 0x198, + BD_INVALID_EXTERNAL_TITLE_ID = 0x199, + BD_DIFFERENT_LEADERBOARD_SCHEMAS = 0x19A, + BD_TOO_MANY_LEADERBOARDS_REQUESTED = 0x19B, + BD_ENTITLEMENTS_ERROR = 0x19C, + BD_ENTITLEMENTS_INVALID_TITLEID = 0x19D, + BD_ENTITLEMENTS_INVALID_LEADERBOARDID = 0x19E, + BD_ENTITLEMENTS_INVALID_GET_MODE_FOR_TITLE = 0x19F, + BD_ENTITLEMENTS_URL_CONNECTION_ERROR = 0x1A0, + BD_ENTITLEMENTS_CONFIG_ERROR = 0x1A1, + BD_ENTITLEMENTS_NAMED_PARENT_ERROR = 0x1A2, + BD_ENTITLEMENTS_NAMED_KEY_ERROR = 0x1A3, + BD_TOO_MANY_ENTITY_IDS_REQUESTED = 0x1A4, + BD_STATS_READ_FAILED = 0x1A5, + BD_INVALID_TITLE_ID = 0x1F4, + BD_MESSAGING_INVALID_MAIL_ID = 0x258, + BD_SELF_BLOCK_NOT_ALLOWED = 0x259, + BD_GLOBAL_MESSAGE_ACCESS_DENIED = 0x25A, + BD_GLOBAL_MESSAGES_USER_LIMIT_EXCEEDED = 0x25B, + BD_MESSAGING_SENDER_DOES_NOT_EXIST = 0x25C, + BD_AUTH_NO_ERROR = 0x2BC, + BD_AUTH_BAD_REQUEST = 0x2BD, + BD_AUTH_SERVER_CONFIG_ERROR = 0x2BE, + BD_AUTH_BAD_TITLE_ID = 0x2BF, + BD_AUTH_BAD_ACCOUNT = 0x2C0, + BD_AUTH_ILLEGAL_OPERATION = 0x2C1, + BD_AUTH_INCORRECT_LICENSE_CODE = 0x2C2, + BD_AUTH_CREATE_USERNAME_EXISTS = 0x2C3, + BD_AUTH_CREATE_USERNAME_ILLEGAL = 0x2C4, + BD_AUTH_CREATE_USERNAME_VULGAR = 0x2C5, + BD_AUTH_CREATE_MAX_ACC_EXCEEDED = 0x2C6, + BD_AUTH_MIGRATE_NOT_SUPPORTED = 0x2C7, + BD_AUTH_TITLE_DISABLED = 0x2C8, + BD_AUTH_ACCOUNT_EXPIRED = 0x2C9, + BD_AUTH_ACCOUNT_LOCKED = 0x2CA, + BD_AUTH_UNKNOWN_ERROR = 0x2CB, + BD_AUTH_INCORRECT_PASSWORD = 0x2CC, + BD_AUTH_IP_NOT_IN_ALLOWED_RANGE = 0x2CD, + BD_AUTH_WII_TOKEN_VERIFICATION_FAILED = 0x2CE, + BD_AUTH_WII_AUTHENTICATION_FAILED = 0x2CF, + BD_AUTH_IP_KEY_LIMIT_REACHED = 0x2D0, + BD_AUTH_INVALID_GSPID = 0x2D1, + BD_AUTH_INVALID_IP_RANGE_ID = 0x2D2, + BD_AUTH_3DS_TOKEN_VERIFICATION_FAILED = 0x2D1, + BD_AUTH_3DS_AUTHENTICATION_FAILED = 0x2D2, + BD_AUTH_STEAM_APP_ID_MISMATCH = 0x2D3, + BD_AUTH_ABACCOUNTS_APP_ID_MISMATCH = 0x2D4, + BD_AUTH_CODO_USERNAME_NOT_SET = 0x2D5, + BD_AUTH_WIIU_TOKEN_VERIFICATION_FAILED = 0x2D6, + BD_AUTH_WIIU_AUTHENTICATION_FAILED = 0x2D7, + BD_AUTH_CODO_USERNAME_NOT_BASE64 = 0x2D8, + BD_AUTH_CODO_USERNAME_NOT_UTF8 = 0x2D9, + BD_AUTH_TENCENT_TICKET_EXPIRED = 0x2DA, + BD_AUTH_PS3_SERVICE_ID_MISMATCH = 0x2DB, + BD_AUTH_CODOID_NOT_WHITELISTED = 0x2DC, + BD_AUTH_PLATFORM_TOKEN_ERROR = 0x2DD, + BD_AUTH_JSON_FORMAT_ERROR = 0x2DE, + BD_AUTH_REPLY_CONTENT_ERROR = 0x2DF, + BD_AUTH_THIRD_PARTY_TOKEN_EXPIRED = 0x2E0, + BD_AUTH_CONTINUING = 0x2E1, + BD_AUTH_PLATFORM_DEVICE_ID_ERROR = 0x2E4, + BD_NO_PROFILE_INFO_EXISTS = 0x320, + BD_FRIENDSHIP_NOT_REQUSTED = 0x384, + BD_NOT_A_FRIEND = 0x385, + BD_SELF_FRIENDSHIP_NOT_ALLOWED = 0x387, + BD_FRIENDSHIP_EXISTS = 0x388, + BD_PENDING_FRIENDSHIP_EXISTS = 0x389, + BD_USERID_BANNED = 0x38A, + BD_FRIENDS_FULL = 0x38C, + BD_FRIENDS_NO_RICH_PRESENCE = 0x38D, + BD_RICH_PRESENCE_TOO_LARGE = 0x38E, + BD_NO_FILE = 0x3E8, + BD_PERMISSION_DENIED = 0x3E9, + BD_FILESIZE_LIMIT_EXCEEDED = 0x3EA, + BD_FILENAME_MAX_LENGTH_EXCEEDED = 0x3EB, + BD_EXTERNAL_STORAGE_SERVICE_ERROR = 0x3EC, + BD_CHANNEL_DOES_NOT_EXIST = 0x44D, + BD_CHANNEL_ALREADY_SUBSCRIBED = 0x44E, + BD_CHANNEL_NOT_SUBSCRIBED = 0x44F, + BD_CHANNEL_FULL = 0x450, + BD_CHANNEL_SUBSCRIPTIONS_FULL = 0x451, + BD_CHANNEL_NO_SELF_WHISPERING = 0x452, + BD_CHANNEL_ADMIN_REQUIRED = 0x453, + BD_CHANNEL_TARGET_NOT_SUBSCRIBED = 0x454, + BD_CHANNEL_REQUIRES_PASSWORD = 0x455, + BD_CHANNEL_TARGET_IS_SELF = 0x456, + BD_CHANNEL_PUBLIC_BAN_NOT_ALLOWED = 0x457, + BD_CHANNEL_USER_BANNED = 0x458, + BD_CHANNEL_PUBLIC_PASSWORD_NOT_ALLOWED = 0x459, + BD_CHANNEL_PUBLIC_KICK_NOT_ALLOWED = 0x45A, + BD_CHANNEL_MUTED = 0x45B, + BD_EVENT_DESC_TRUNCATED = 0x4B0, + BD_CONTENT_UNLOCK_UNKNOWN_ERROR = 0x514, + BD_UNLOCK_KEY_INVALID = 0x515, + BD_UNLOCK_KEY_ALREADY_USED_UP = 0x516, + BD_SHARED_UNLOCK_LIMIT_REACHED = 0x517, + BD_DIFFERENT_HARDWARE_ID = 0x518, + BD_INVALID_CONTENT_OWNER = 0x519, + BD_CONTENT_UNLOCK_INVALID_USER = 0x51A, + BD_CONTENT_UNLOCK_INVALID_CATEGORY = 0x51B, + BD_KEY_ARCHIVE_INVALID_WRITE_TYPE = 0x5DC, + BD_KEY_ARCHIVE_EXCEEDED_MAX_IDS_PER_REQUEST = 0x5DD, + BD_BANDWIDTH_TEST_TRY_AGAIN = 0x712, + BD_BANDWIDTH_TEST_STILL_IN_PROGRESS = 0x713, + BD_BANDWIDTH_TEST_NOT_PROGRESS = 0x714, + BD_BANDWIDTH_TEST_SOCKET_ERROR = 0x715, + BD_INVALID_SESSION_NONCE = 0x76D, + BD_ARBITRATION_FAILURE = 0x76F, + BD_ARBITRATION_USER_NOT_REGISTERED = 0x771, + BD_ARBITRATION_NOT_CONFIGURED = 0x772, + BD_CONTENTSTREAMING_FILE_NOT_AVAILABLE = 0x7D0, + BD_CONTENTSTREAMING_STORAGE_SPACE_EXCEEDED = 0x7D1, + BD_CONTENTSTREAMING_NUM_FILES_EXCEEDED = 0x7D2, + BD_CONTENTSTREAMING_UPLOAD_BANDWIDTH_EXCEEDED = 0x7D3, + BD_CONTENTSTREAMING_FILENAME_MAX_LENGTH_EXCEEDED = 0x7D4, + BD_CONTENTSTREAMING_MAX_THUMB_DATA_SIZE_EXCEEDED = 0x7D5, + BD_CONTENTSTREAMING_DOWNLOAD_BANDWIDTH_EXCEEDED = 0x7D6, + BD_CONTENTSTREAMING_NOT_ENOUGH_DOWNLOAD_BUFFER_SPACE = 0x7D7, + BD_CONTENTSTREAMING_SERVER_NOT_CONFIGURED = 0x7D8, + BD_CONTENTSTREAMING_INVALID_APPLE_RECEIPT = 0x7DA, + BD_CONTENTSTREAMING_APPLE_STORE_NOT_AVAILABLE = 0x7DB, + BD_CONTENTSTREAMING_APPLE_RECEIPT_FILENAME_MISMATCH = 0x7DC, + BD_CONTENTSTREAMING_HTTP_ERROR = 0x7E4, + BD_CONTENTSTREAMING_FAILED_TO_START_HTTP = 0x7E5, + BD_CONTENTSTREAMING_LOCALE_INVALID = 0x7E6, + BD_CONTENTSTREAMING_LOCALE_MISSING = 0x7E7, + BD_VOTERANK_ERROR_EMPTY_RATING_SUBMISSION = 0x7EE, + BD_VOTERANK_ERROR_MAX_VOTES_EXCEEDED = 0x7EF, + BD_VOTERANK_ERROR_INVALID_RATING = 0x7F0, + BD_MAX_NUM_TAGS_EXCEEDED = 0x82A, + BD_TAGGED_COLLECTION_DOES_NOT_EXIST = 0x82B, + BD_EMPTY_TAG_ARRAY = 0x82C, + BD_INVALID_QUERY_ID = 0x834, + BD_NO_ENTRY_TO_UPDATE = 0x835, + BD_SESSION_INVITE_EXISTS = 0x836, + BD_INVALID_SESSION_ID = 0x837, + BD_ATTACHMENT_TOO_LARGE = 0x838, + BD_INVALID_GROUP_ID = 0xAF0, + BD_MAIL_INVALID_MAIL_ID_ERROR = 0xB55, + BD_UCD_SERVICE_ERROR = 0xC80, + BD_UCD_SERVICE_DISABLED = 0xC81, + BD_UCD_UNINTIALIZED_ERROR = 0xC82, + BD_UCD_ACCOUNT_ALREADY_REGISTERED = 0xC83, + BD_UCD_ACCOUNT_NOT_REGISTERED = 0xC84, + BD_UCD_AUTH_ATTEMPT_FAILED = 0xC85, + BD_UCD_ACCOUNT_LINKING_ERROR = 0xC86, + BD_UCD_ENCRYPTION_ERROR = 0xC87, + BD_UCD_ACCOUNT_DATA_INVALID = 0xC88, + BD_UCD_ACCOUNT_DATA_INVALID_FIRSTNAME = 0xC89, + BD_UCD_ACCOUNT_DATA_INVALID_LASTNAME = 0xC8A, + BD_UCD_ACCOUNT_DATA_INVALID_DOB = 0xC8B, + BD_UCD_ACCOUNT_DATA_INVALID_EMAIL = 0xC8C, + BD_UCD_ACCOUNT_DATA_INVALID_COUNTRY = 0xC8D, + BD_UCD_ACCOUNT_DATA_INVALID_POSTCODE = 0xC8E, + BD_UCD_ACCOUNT_DATA_INVALID_PASSWORD = 0xC8F, + BD_UCD_ACCOUNT_NAME_ALREADY_RESISTERED = 0xC94, + BD_UCD_ACCOUNT_EMAIL_ALREADY_RESISTERED = 0xC95, + BD_UCD_GUEST_ACCOUNT_AUTH_CONFLICT = 0xC96, + BD_TWITCH_SERVICE_ERROR = 0xC1D, + BD_TWITCH_ACCOUNT_ALREADY_LINKED = 0xC1E, + BD_TWITCH_NO_LINKED_ACCOUNT = 0xC1F, + BD_YOUTUBE_SERVICE_ERROR = 0xCE5, + BD_YOUTUBE_SERVICE_COMMUNICATION_ERROR = 0xCE6, + BD_YOUTUBE_USER_DENIED_AUTHORIZATION = 0xCE7, + BD_YOUTUBE_AUTH_MAX_TIME_EXCEEDED = 0xCE8, + BD_YOUTUBE_USER_UNAUTHORIZED = 0xCE9, + BD_YOUTUBE_UPLOAD_MAX_TIME_EXCEEDED = 0xCEA, + BD_YOUTUBE_DUPLICATE_UPLOAD = 0xCEB, + BD_YOUTUBE_FAILED_UPLOAD = 0xCEC, + BD_YOUTUBE_ACCOUNT_ALREADY_REGISTERED = 0xCED, + BD_YOUTUBE_ACCOUNT_NOT_REGISTERED = 0xCEE, + BD_YOUTUBE_CONTENT_SERVER_ERROR = 0xCEF, + BD_YOUTUBE_UPLOAD_DOES_NOT_EXIST = 0xCF0, + BD_YOUTUBE_NO_LINKED_ACCOUNT = 0xCF1, + BD_YOUTUBE_DEVELOPER_TAGS_INVALID = 0xCF2, + BD_TWITTER_AUTH_ATTEMPT_FAILED = 0xDAD, + BD_TWITTER_AUTH_TOKEN_INVALID = 0xDAE, + BD_TWITTER_UPDATE_LIMIT_REACHED = 0xDAF, + BD_TWITTER_UNAVAILABLE = 0xDB0, + BD_TWITTER_ERROR = 0xDB1, + BD_TWITTER_TIMED_OUT = 0xDB2, + BD_TWITTER_DISABLED_FOR_USER = 0xDB3, + BD_TWITTER_ACCOUNT_AMBIGUOUS = 0xDB4, + BD_TWITTER_MAXIMUM_ACCOUNTS_REACHED = 0xDB5, + BD_TWITTER_ACCOUNT_NOT_REGISTERED = 0xDB6, + BD_TWITTER_DUPLICATE_STATUS = 0xDB7, + BD_TWITTER_ACCOUNT_ALREADY_REGISTERED = 0xE1C, + BD_FACEBOOK_AUTH_ATTEMPT_FAILED = 0xE11, + BD_FACEBOOK_AUTH_TOKEN_INVALID = 0xE12, + BD_FACEBOOK_PHOTO_DOES_NOT_EXIST = 0xE13, + BD_FACEBOOK_PHOTO_INVALID = 0xE14, + BD_FACEBOOK_PHOTO_ALBUM_FULL = 0xE15, + BD_FACEBOOK_UNAVAILABLE = 0xE16, + BD_FACEBOOK_ERROR = 0xE17, + BD_FACEBOOK_TIMED_OUT = 0xE18, + BD_FACEBOOK_DISABLED_FOR_USER = 0xE19, + BD_FACEBOOK_ACCOUNT_AMBIGUOUS = 0xE1A, + BD_FACEBOOK_MAXIMUM_ACCOUNTS_REACHED = 0xE1B, + BD_FACEBOOK_INVALID_NUM_PICTURES_REQUESTED = 0xE1C, + BD_FACEBOOK_VIDEO_DOES_NOT_EXIST = 0xE1D, + BD_FACEBOOK_ACCOUNT_ALREADY_REGISTERED = 0xE1E, + BD_APNS_INVALID_PAYLOAD = 0xE74, + BD_APNS_INVALID_TOKEN_LENGTH_ERROR = 0xE76, + BD_MAX_CONSOLEID_LENGTH_EXCEEDED = 0xEE1, + BD_MAX_WHITELIST_LENGTH_EXCEEDED = 0xEE2, + BD_USERGROUP_NAME_ALREADY_EXISTS = 0x1770, + BD_INVALID_USERGROUP_ID = 0x1771, + BD_USER_ALREADY_IN_USERGROUP = 0x1772, + BD_USER_NOT_IN_USERGROUP = 0x1773, + BD_INVALID_USERGROUP_MEMBER_TYPE = 0x1774, + BD_TOO_MANY_MEMBERS_REQUESTED = 0x1775, + BD_USERGROUP_NAME_TOO_SHORT = 0x1776, + BD_RICH_PRESENCE_DATA_TOO_LARGE = 0x1A90, + BD_RICH_PRESENCE_TOO_MANY_USERS = 0x1A91, + BD_PRESENCE_DATA_TOO_LARGE = 0x283C, + BD_PRESENCE_TOO_MANY_USERS = 0x283D, + BD_USER_LOGGED_IN_OTHER_TITLE = 0x283E, + BD_USER_NOT_LOGGED_IN = 0x283F, + BD_SUBSCRIPTION_TOO_MANY_USERS = 0x1B58, + BD_SUBSCRIPTION_TICKET_PARSE_ERROR = 0x1B59, + BD_CODO_ID_INVALID_DATA = 0x1BBC, + BD_INVALID_MESSAGE_FORMAT = 0x1BBD, + BD_TLOG_TOO_MANY_MESSAGES = 0x1BBE, + BD_CODO_ID_NOT_IN_WHITELIST = 0x1BBF, + BD_TLOG_MESSAGE_TRANSFORMATION_ERROR = 0x1BC0, + BD_REWARDS_NOT_ENABLED = 0x1BC1, + BD_MARKETPLACE_ERROR = 0x1F40, + BD_MARKETPLACE_RESOURCE_NOT_FOUND = 0x1F41, + BD_MARKETPLACE_INVALID_CURRENCY = 0x1F42, + BD_MARKETPLACE_INVALID_PARAMETER = 0x1F43, + BD_MARKETPLACE_RESOURCE_CONFLICT = 0x1F44, + BD_MARKETPLACE_STORAGE_ERROR = 0x1F45, + BD_MARKETPLACE_INTEGRITY_ERROR = 0x1F46, + BD_MARKETPLACE_INSUFFICIENT_FUNDS_ERROR = 0x1F47, + BD_MARKETPLACE_MMP_SERVICE_ERROR = 0x1F48, + BD_MARKETPLACE_PRECONDITION_REQUIRED = 0x1F49, + BD_MARKETPLACE_ITEM_MULTIPLE_PURCHASE_ERROR = 0x1F4A, + BD_MARKETPLACE_MISSING_REQUIRED_ENTITLEMENT = 0x1F4B, + BD_MARKETPLACE_VALIDATION_ERROR = 0x1F4C, + BD_MARKETPLACE_TENCENT_PAYMENT_ERROR = 0x1F4D, + BD_MARKETPLACE_SKU_NOT_COUPON_ENABLED_ERROR = 0x1F4E, + BD_LEAGUE_INVALID_TEAM_SIZE = 0x1FA4, + BD_LEAGUE_INVALID_TEAM = 0x1FA5, + BD_LEAGUE_INVALID_SUBDIVISION = 0x1FA6, + BD_LEAGUE_INVALID_LEAGUE = 0x1FA7, + BD_LEAGUE_TOO_MANY_RESULTS_REQUESTED = 0x1FA8, + BD_LEAGUE_METADATA_TOO_LARGE = 0x1FA9, + BD_LEAGUE_TEAM_ICON_TOO_LARGE = 0x1FAA, + BD_LEAGUE_TEAM_NAME_TOO_LONG = 0x1FAB, + BD_LEAGUE_ARRAY_SIZE_MISMATCH = 0x1FAC, + BD_LEAGUE_SUBDIVISION_MISMATCH = 0x2008, + BD_LEAGUE_INVALID_WRITE_TYPE = 0x2009, + BD_LEAGUE_INVALID_STATS_DATA = 0x200A, + BD_LEAGUE_SUBDIVISION_UNRANKED = 0x200B, + BD_LEAGUE_CROSS_TEAM_STATS_WRITE_PREVENTED = 0x200C, + BD_LEAGUE_INVALID_STATS_SEASON = 0x200D, + BD_COMMERCE_ERROR = 0x206C, + BD_COMMERCE_RESOURCE_NOT_FOUND = 0x206D, + BD_COMMERCE_STORAGE_INVALID_PARAMETER = 0x206E, + BD_COMMERCE_APPLICATION_INVALID_PARAMETER = 0x206F, + BD_COMMERCE_RESOURCE_CONFLICT = 0x2070, + BD_COMMERCE_STORAGE_ERROR = 0x2071, + BD_COMMERCE_INTEGRITY_ERROR = 0x2072, + BD_COMMERCE_MMP_SERVICE_ERROR = 0x2073, + BD_COMMERCE_PERMISSION_DENIED = 0x2074, + BD_COMMERCE_INSUFFICIENT_FUNDS_ERROR = 0x2075, + BD_COMMERCE_UNKNOWN_CURRENCY = 0x2076, + BD_COMMERCE_INVALID_RECEIPT = 0x2077, + BD_COMMERCE_RECEIPT_USED = 0x2078, + BD_COMMERCE_TRANSACTION_ALREADY_APPLIED = 0x2079, + BD_COMMERCE_INVALID_CURRENCY_TYPE = 0x207A, + BD_CONNECTION_COUNTER_ERROR = 0x20D0, + BD_LINKED_ACCOUNTS_INVALID_CONTEXT = 0x2198, + BD_LINKED_ACCOUNTS_INVALID_PLATFORM = 0x2199, + BD_LINKED_ACCOUNTS_LINKED_ACCOUNTS_FETCH_ERROR = 0x219A, + BD_LINKED_ACCOUNTS_INVALID_ACCOUNT = 0x219B, + BD_GMSG_INVALID_CATEGORY_ID = 0x27D8, + BD_GMSG_CATEGORY_MEMBERSHIPS_LIMIT = 0x27D9, + BD_GMSG_NONMEMBER_POST_DISALLOWED = 0x27DA, + BD_GMSG_CATEGORY_DISALLOWS_CLIENT_TYPE = 0x27DB, + BD_GMSG_PAYLOAD_TOO_BIG = 0x27DC, + BD_GMSG_MEMBER_POST_DISALLOWED = 0x27DD, + BD_GMSG_OVERLOADED = 0x27DE, + BD_GMSG_USER_PERCATEGORY_POST_RATE_EXCEEDED = 0x27DF, + BD_GMSG_USER_GLOBAL_POST_RATE_EXCEEDED = 0x27E0, + BD_GMSG_GROUP_POST_RATE_EXCEEDED = 0x27E1, + BD_MAX_ERROR_CODE = 0x27E2, + }; + + enum bdNATType : uint8_t + { + BD_NAT_UNKNOWN = 0x0, + BD_NAT_OPEN = 0x1, + BD_NAT_MODERATE = 0x2, + BD_NAT_STRICT = 0x3, + }; + +#pragma pack(push, 1) + struct bdAuthTicket + { + unsigned int m_magicNumber; + char m_type; + unsigned int m_titleID; + unsigned int m_timeIssued; + unsigned int m_timeExpires; + unsigned long long m_licenseID; + unsigned long long m_userID; + char m_username[64]; + char m_sessionKey[24]; + char m_usingHashMagicNumber[3]; + char m_hash[4]; + }; +#pragma pack(pop) + } + using namespace demonware; +} diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp new file mode 100644 index 00000000..3cbe059a --- /dev/null +++ b/src/client/game/symbols.hpp @@ -0,0 +1,12 @@ +#pragma once + +#define WEAK __declspec(selectany) + +namespace game +{ + /*************************************************************** + * Functions + **************************************************************/ + + WEAK symbol Cbuf_AddText{ 0xB7C290 }; +} diff --git a/src/client/loader/component_interface.hpp b/src/client/loader/component_interface.hpp new file mode 100644 index 00000000..e1ee433f --- /dev/null +++ b/src/client/loader/component_interface.hpp @@ -0,0 +1,35 @@ +#pragma once + +class component_interface +{ +public: + virtual ~component_interface() + { + } + + virtual void post_start() + { + } + + virtual void post_load() + { + } + + virtual void pre_destroy() + { + } + + virtual void post_unpack() + { + } + + virtual void* load_import([[maybe_unused]] const std::string& library, [[maybe_unused]] const std::string& function) + { + return nullptr; + } + + virtual bool is_supported() + { + return true; + } +}; diff --git a/src/client/loader/component_loader.cpp b/src/client/loader/component_loader.cpp new file mode 100644 index 00000000..342a1a91 --- /dev/null +++ b/src/client/loader/component_loader.cpp @@ -0,0 +1,135 @@ +#include +#include "component_loader.hpp" + +void component_loader::register_component(std::unique_ptr&& component_) +{ + get_components().push_back(std::move(component_)); +} + +bool component_loader::post_start() +{ + static auto handled = false; + if (handled) return true; + handled = true; + + try + { + for (const auto& component_ : get_components()) + { + component_->post_start(); + } + } + catch (premature_shutdown_trigger&) + { + return false; + } + + return true; +} + +bool component_loader::post_load() +{ + static auto handled = false; + if (handled) return true; + handled = true; + + clean(); + + try + { + for (const auto& component_ : get_components()) + { + component_->post_load(); + } + } + catch (premature_shutdown_trigger&) + { + return false; + } + + return true; +} + +void component_loader::post_unpack() +{ + static auto handled = false; + if (handled) return; + handled = true; + + for (const auto& component_ : get_components()) + { + try + { + component_->post_unpack(); + } + catch (std::exception& e) + { + MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR); + quick_exit(-1); + } + } +} + +void component_loader::pre_destroy() +{ + static auto handled = false; + if (handled) return; + handled = true; + + for (const auto& component_ : get_components()) + { + component_->pre_destroy(); + } +} + +void component_loader::clean() +{ + auto& components = get_components(); + for (auto i = components.begin(); i != components.end();) + { + if (!(*i)->is_supported()) + { + (*i)->pre_destroy(); + i = components.erase(i); + } + else + { + ++i; + } + } +} + +void* component_loader::load_import(const std::string& library, const std::string& function) +{ + void* function_ptr = nullptr; + + for (const auto& component_ : get_components()) + { + auto* const component_function_ptr = component_->load_import(library, function); + if (component_function_ptr) + { + function_ptr = component_function_ptr; + } + } + + return function_ptr; +} + +void component_loader::trigger_premature_shutdown() +{ + throw premature_shutdown_trigger(); +} + +std::vector>& component_loader::get_components() +{ + using component_vector = std::vector>; + using component_vector_container = std::unique_ptr>; + + static component_vector_container components(new component_vector, [](component_vector* component_vector) + { + pre_destroy(); + delete component_vector; + }); + + return *components; +} diff --git a/src/client/loader/component_loader.hpp b/src/client/loader/component_loader.hpp new file mode 100644 index 00000000..4ff8f3c4 --- /dev/null +++ b/src/client/loader/component_loader.hpp @@ -0,0 +1,61 @@ +#pragma once +#include "component_interface.hpp" + +class component_loader final +{ +public: + class premature_shutdown_trigger final : public std::exception + { + [[nodiscard]] const char* what() const noexcept override + { + return "Premature shutdown requested"; + } + }; + + template + class installer final + { + static_assert(std::is_base_of::value, "component has invalid base class"); + + public: + installer() + { + register_component(std::make_unique()); + } + }; + + template + static T* get() + { + for (const auto& component_ : get_components()) + { + if (typeid(*component_.get()) == typeid(T)) + { + return reinterpret_cast(component_.get()); + } + } + + return nullptr; + } + + static void register_component(std::unique_ptr&& component); + + static bool post_start(); + static bool post_load(); + static void post_unpack(); + static void pre_destroy(); + static void clean(); + + static void* load_import(const std::string& library, const std::string& function); + + static void trigger_premature_shutdown(); + +private: + static std::vector>& get_components(); +}; + +#define REGISTER_COMPONENT(name) \ +namespace \ +{ \ + static component_loader::installer __component; \ +} diff --git a/src/client/loader/loader.cpp b/src/client/loader/loader.cpp new file mode 100644 index 00000000..4ec12c7c --- /dev/null +++ b/src/client/loader/loader.cpp @@ -0,0 +1,208 @@ +#include +#include "loader.hpp" +#include "seh.hpp" +#include "tls.hpp" + +#include +#include + +FARPROC loader::load(const utils::nt::library& library, const std::string& buffer) const +{ + if (buffer.empty()) return nullptr; + + const utils::nt::library source(HMODULE(buffer.data())); + if (!source) return nullptr; + + this->load_sections(library, source); + this->load_imports(library, source); + this->load_exception_table(library, source); + this->load_tls(library, source); + + DWORD old_protect; + VirtualProtect(library.get_nt_headers(), 0x1000, PAGE_EXECUTE_READWRITE, &old_protect); + + library.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] = source + .get_optional_header()->DataDirectory[ + IMAGE_DIRECTORY_ENTRY_IMPORT]; + std::memmove(library.get_nt_headers(), source.get_nt_headers(), + sizeof(IMAGE_NT_HEADERS) + source.get_nt_headers()->FileHeader.NumberOfSections * sizeof( + IMAGE_SECTION_HEADER)); + + return FARPROC(library.get_ptr() + source.get_relative_entry_point()); +} + +FARPROC loader::load_library(const std::string& filename, uint64_t* base_address) const +{ + const auto target = utils::nt::library::load(filename); + if (!target) + { + throw std::runtime_error{"Failed to map binary!"}; + } + + const auto base = size_t(target.get_ptr()); + *base_address = base; + + this->load_imports(target, target); + this->load_tls(target, target); + + return FARPROC(target.get_ptr() + target.get_relative_entry_point()); +} + +void loader::set_import_resolver(const std::function& resolver) +{ + this->import_resolver_ = resolver; +} + +void loader::load_section(const utils::nt::library& target, const utils::nt::library& source, + IMAGE_SECTION_HEADER* section) +{ + void* target_ptr = target.get_ptr() + section->VirtualAddress; + const void* source_ptr = source.get_ptr() + section->PointerToRawData; + + if (PBYTE(target_ptr) >= (target.get_ptr() + BINARY_PAYLOAD_SIZE)) + { + throw std::runtime_error("Section exceeds the binary payload size, please increase it!"); + } + + if (section->SizeOfRawData > 0) + { + std::memmove(target_ptr, source_ptr, section->SizeOfRawData); + + DWORD old_protect; + VirtualProtect(target_ptr, section->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &old_protect); + } +} + +void loader::load_sections(const utils::nt::library& target, const utils::nt::library& source) const +{ + for (auto& section : source.get_section_headers()) + { + this->load_section(target, source, section); + } +} + +void loader::load_imports(const utils::nt::library& target, const utils::nt::library& source) const +{ + auto* const import_directory = &source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; + + auto* descriptor = PIMAGE_IMPORT_DESCRIPTOR(target.get_ptr() + import_directory->VirtualAddress); + + while (descriptor->Name) + { + std::string name = LPSTR(target.get_ptr() + descriptor->Name); + + auto* name_table_entry = reinterpret_cast(target.get_ptr() + descriptor->OriginalFirstThunk); + auto* address_table_entry = reinterpret_cast(target.get_ptr() + descriptor->FirstThunk); + + if (!descriptor->OriginalFirstThunk) + { + name_table_entry = reinterpret_cast(target.get_ptr() + descriptor->FirstThunk); + } + + while (*name_table_entry) + { + FARPROC function = nullptr; + std::string function_name; + const char* function_procname; + + if (IMAGE_SNAP_BY_ORDINAL(*name_table_entry)) + { + function_name = "#" + std::to_string(IMAGE_ORDINAL(*name_table_entry)); + function_procname = MAKEINTRESOURCEA(IMAGE_ORDINAL(*name_table_entry)); + } + else + { + auto* import = PIMAGE_IMPORT_BY_NAME(target.get_ptr() + *name_table_entry); + function_name = import->Name; + function_procname = function_name.data(); + } + + if (this->import_resolver_) function = FARPROC(this->import_resolver_(name, function_name)); + if (!function) + { + auto library = utils::nt::library::load(name); + if (library) + { + function = GetProcAddress(library, function_procname); + } + } + + if (!function) + { + throw std::runtime_error(utils::string::va("Unable to load import '%s' from library '%s'", + function_name.data(), name.data())); + } + + utils::hook::set(address_table_entry, reinterpret_cast(function)); + + name_table_entry++; + address_table_entry++; + } + + descriptor++; + } +} + +void loader::load_exception_table(const utils::nt::library& target, const utils::nt::library& source) const +{ + auto* exception_directory = &source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; + + auto* function_list = PRUNTIME_FUNCTION(target.get_ptr() + exception_directory->VirtualAddress); + const auto entry_count = ULONG(exception_directory->Size / sizeof(RUNTIME_FUNCTION)); + + if (!RtlAddFunctionTable(function_list, entry_count, DWORD64(target.get_ptr()))) + { + MessageBoxA(nullptr, "Setting exception handlers failed.", "Error", MB_OK | MB_ICONERROR); + } + + { + const utils::nt::library ntdll("ntdll.dll"); + + auto* const table_list_head = ntdll.invoke_pascal("RtlGetFunctionTableListHead"); + auto* table_list_entry = table_list_head->Flink; + + while (table_list_entry != table_list_head) + { + auto* const function_table = CONTAINING_RECORD(table_list_entry, DYNAMIC_FUNCTION_TABLE, Links); + + if (function_table->BaseAddress == ULONG_PTR(target.get_handle())) + { + function_table->EntryCount = entry_count; + function_table->FunctionTable = function_list; + } + + table_list_entry = function_table->Links.Flink; + } + } + + seh::setup_handler(target.get_ptr(), target.get_ptr() + source.get_optional_header()->SizeOfImage, function_list, + entry_count); +} + +void loader::load_tls(const utils::nt::library& target, const utils::nt::library& source) const +{ + if (source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) + { + auto* target_tls = tls::allocate_tls_index(); + /* target_tls = reinterpret_cast(library.get_ptr() + library.get_optional_header() + ->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress); */ + auto* const source_tls = reinterpret_cast(target.get_ptr() + source.get_optional_header() + ->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress); + + const auto tls_size = source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData; + const auto tls_index = *reinterpret_cast(target_tls->AddressOfIndex); + utils::hook::set(source_tls->AddressOfIndex, tls_index); + + DWORD old_protect; + VirtualProtect(PVOID(target_tls->StartAddressOfRawData), + source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData, PAGE_READWRITE, + &old_protect); + + auto* const tls_base = *reinterpret_cast(__readgsqword(0x58) + 8ull * tls_index); + std::memmove(tls_base, PVOID(source_tls->StartAddressOfRawData), tls_size); + std::memmove(PVOID(target_tls->StartAddressOfRawData), PVOID(source_tls->StartAddressOfRawData), tls_size); + + VirtualProtect(target_tls, sizeof(*target_tls), PAGE_READWRITE, &old_protect); + *target_tls = *source_tls; + } +} diff --git a/src/client/loader/loader.hpp b/src/client/loader/loader.hpp new file mode 100644 index 00000000..0c0b5a12 --- /dev/null +++ b/src/client/loader/loader.hpp @@ -0,0 +1,21 @@ +#pragma once +#include + +class loader final +{ +public: + FARPROC load(const utils::nt::library& library, const std::string& buffer) const; + FARPROC load_library(const std::string& filename, uint64_t* base_address) const; + + void set_import_resolver(const std::function& resolver); + +private: + std::function import_resolver_; + + static void load_section(const utils::nt::library& target, const utils::nt::library& source, + IMAGE_SECTION_HEADER* section); + void load_sections(const utils::nt::library& target, const utils::nt::library& source) const; + void load_imports(const utils::nt::library& target, const utils::nt::library& source) const; + void load_exception_table(const utils::nt::library& target, const utils::nt::library& source) const; + void load_tls(const utils::nt::library& target, const utils::nt::library& source) const; +}; diff --git a/src/client/loader/seh.cpp b/src/client/loader/seh.cpp new file mode 100644 index 00000000..a3364a8f --- /dev/null +++ b/src/client/loader/seh.cpp @@ -0,0 +1,151 @@ +#include + +#include +#include + +#include "seh.hpp" + +namespace seh +{ + namespace + { + void*(*rtlpx_lookup_function_table)(void*, FUNCTION_TABLE_DATA*); + void*(*rtlpx_lookup_function_table_down_level)(void*, PDWORD64, PULONG); + + FUNCTION_TABLE_DATA overridden_table; + + DWORD64 override_end; + DWORD64 override_start; + + void* find_call_from_address(void* method_ptr, ud_mnemonic_code mnemonic = UD_Icall) + { + ud_t ud; + ud_init(&ud); + ud_set_mode(&ud, 64); + ud_set_pc(&ud, reinterpret_cast(method_ptr)); + ud_set_input_buffer(&ud, static_cast(method_ptr), INT32_MAX); + + void* retval = nullptr; + while (true) + { + ud_disassemble(&ud); + + if (ud_insn_mnemonic(&ud) == UD_Iint3) break; + if (ud_insn_mnemonic(&ud) == mnemonic) + { + const auto* const operand = ud_insn_opr(&ud, 0); + if (operand->type == UD_OP_JIMM) + { + if (!retval) retval = reinterpret_cast(ud_insn_len(&ud) + ud_insn_off(&ud) + operand-> + lval.sdword); + else + { + retval = nullptr; + break; + } + } + } + } + + return retval; + } + + void* rtlpx_lookup_function_table_override(void* exception_address, FUNCTION_TABLE_DATA* out_data) + { + ZeroMemory(out_data, sizeof(*out_data)); + + auto* retval = seh::rtlpx_lookup_function_table(exception_address, out_data); + + const auto address_num = DWORD64(exception_address); + if (address_num >= seh::override_start && address_num <= seh::override_end) + { + if (address_num != 0) + { + *out_data = seh::overridden_table; + retval = PVOID(seh::overridden_table.TableAddress); + } + } + + return retval; + } + + void* rtlpx_lookup_function_table_override_down_level(void* exception_address, const PDWORD64 image_base, + const PULONG length) + { + auto* retval = seh::rtlpx_lookup_function_table_down_level(exception_address, image_base, length); + + const auto address_num = DWORD64(exception_address); + if (address_num >= seh::override_start && address_num <= seh::override_end) + { + if (address_num != 0) + { + *image_base = seh::overridden_table.ImageBase; + *length = seh::overridden_table.Size; + + retval = PVOID(seh::overridden_table.TableAddress); + } + } + + return retval; + } + } + + void setup_handler(void* module_base, void* module_end, PRUNTIME_FUNCTION runtime_functions, const DWORD entryCount) + { + const utils::nt::library ntdll("ntdll.dll"); + + seh::override_start = DWORD64(module_base); + seh::override_end = DWORD64(module_end); + + seh::overridden_table.ImageBase = seh::override_start; + seh::overridden_table.TableAddress = DWORD64(runtime_functions); + seh::overridden_table.Size = entryCount * sizeof(RUNTIME_FUNCTION); + + if (IsWindows8Point1OrGreater()) + { + struct + { + DWORD64 field0; + DWORD imageSize; + DWORD fieldC; + DWORD64 field10; + } query_result = {0, 0, 0, 0}; + + ntdll.invoke_pascal("NtQueryVirtualMemory", GetCurrentProcess(), module_base, 6, &query_result, + sizeof(query_result), nullptr); + seh::overridden_table.ImageSize = query_result.imageSize; + } + + auto* base_address = ntdll.get_proc("RtlLookupFunctionTable"); + auto* internal_address = find_call_from_address(base_address); + + void* patch_function = rtlpx_lookup_function_table_override; + auto** patch_original = reinterpret_cast(&seh::rtlpx_lookup_function_table); + + if (!internal_address) + { + if (!IsWindows8Point1OrGreater()) + { + internal_address = find_call_from_address(base_address, UD_Ijmp); + patch_function = rtlpx_lookup_function_table_override_down_level; + patch_original = reinterpret_cast(&seh::rtlpx_lookup_function_table_down_level); + } + + if (!internal_address) + { + if (IsWindows8OrGreater()) + { + // TODO: Catch the error + } + + internal_address = base_address; + patch_function = rtlpx_lookup_function_table_override_down_level; + patch_original = reinterpret_cast(&seh::rtlpx_lookup_function_table_down_level); + } + } + + static utils::hook::detour hook{}; + hook = utils::hook::detour(internal_address, patch_function); + *patch_original = hook.get_original(); + } +} diff --git a/src/client/loader/seh.hpp b/src/client/loader/seh.hpp new file mode 100644 index 00000000..232dca47 --- /dev/null +++ b/src/client/loader/seh.hpp @@ -0,0 +1,38 @@ +#pragma once + +struct FUNCTION_TABLE_DATA +{ + DWORD64 TableAddress; + DWORD64 ImageBase; + DWORD ImageSize; // field +8 in ZwQueryVirtualMemory class 6 + DWORD Size; +}; + +typedef enum _FUNCTION_TABLE_TYPE +{ + RF_SORTED, + RF_UNSORTED, + RF_CALLBACK +} FUNCTION_TABLE_TYPE; + +typedef struct _DYNAMIC_FUNCTION_TABLE +{ + LIST_ENTRY Links; + PRUNTIME_FUNCTION FunctionTable; + LARGE_INTEGER TimeStamp; + + ULONG_PTR MinimumAddress; + ULONG_PTR MaximumAddress; + ULONG_PTR BaseAddress; + + PGET_RUNTIME_FUNCTION_CALLBACK Callback; + PVOID Context; + PWSTR OutOfProcessCallbackDll; + FUNCTION_TABLE_TYPE Type; + ULONG EntryCount; +} DYNAMIC_FUNCTION_TABLE, *PDYNAMIC_FUNCTION_TABLE; + +namespace seh +{ + void setup_handler(void* module_base, void* module_end, PRUNTIME_FUNCTION runtime_functions, DWORD entryCount); +} diff --git a/src/client/loader/tls.cpp b/src/client/loader/tls.cpp new file mode 100644 index 00000000..a9f3b8be --- /dev/null +++ b/src/client/loader/tls.cpp @@ -0,0 +1,34 @@ +#include +#include "tls.hpp" + +#include +#include + +namespace tls +{ + namespace + { + utils::binary_resource tls_dll_file(TLS_DLL, "h1-tlsdll.dll"); + } + + PIMAGE_TLS_DIRECTORY allocate_tls_index() + { + static auto already_allocated = false; + if (already_allocated) + { + throw std::runtime_error("Currently only a single allocation is supported!"); + } + + already_allocated = true; + + const auto dll_path = tls_dll_file.get_extracted_file(); + const auto tls_dll = utils::nt::library::load(dll_path); + if (!tls_dll) + { + throw std::runtime_error("Failed to load TLS DLL"); + } + + return reinterpret_cast(tls_dll.get_ptr() + tls_dll.get_optional_header() + ->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress); + } +} diff --git a/src/client/loader/tls.hpp b/src/client/loader/tls.hpp new file mode 100644 index 00000000..1b7c68d2 --- /dev/null +++ b/src/client/loader/tls.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace tls +{ + PIMAGE_TLS_DIRECTORY allocate_tls_index(); +} diff --git a/src/client/resource.hpp b/src/client/resource.hpp new file mode 100644 index 00000000..2bfbac57 --- /dev/null +++ b/src/client/resource.hpp @@ -0,0 +1,15 @@ +#pragma once + +#define ID_ICON 102 + +#define IMAGE_SPLASH 300 +#define IMAGE_LOGO 301 + +#define DW_MOTD 302 +#define DW_FASTFILE 303 +#define DW_PLAYLISTS 304 + +#define TLS_DLL 305 +#define RUNNER 306 + +#define ICON_IMAGE 307 diff --git a/src/client/resource.rc b/src/client/resource.rc new file mode 100644 index 00000000..0b756d23 --- /dev/null +++ b/src/client/resource.rc @@ -0,0 +1,133 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" +#include "version.h" +#include "resource.hpp" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +2 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_FILE_RC + PRODUCTVERSION VERSION_PRODUCT_RC + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else +#ifdef PRERELEASE + FILEFLAGS VS_FF_PRERELEASE +#else +#ifndef CI + FILEFLAGS VS_FF_PRIVATEBUILD +#else + FILEFLAGS 0x0L +#endif +#endif +#endif + FILEOS 0x40004L + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "XLabs" + VALUE "FileDescription", "IW7-Mod" + VALUE "FileVersion", VERSION_FILE + VALUE "InternalName", "IW7-Mod" + VALUE "LegalCopyright", "Copyright (C) 2022 X Labs Project. All rights reserved." + VALUE "Licence", "GPLv3" + VALUE "Info", "https://github.com/Joelrau/iw7-mod/" + VALUE "OriginalFilename", "iw7-mod.exe" + VALUE "ProductName", "iw7-mod" + VALUE "ProductVersion", VERSION_PRODUCT + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +///////////////////////////////////////////////////////////////////////////// +// +// Binary Data +// + +ID_ICON ICON "resources/icon.ico" + +IMAGE_SPLASH BITMAP "resources/splash.bmp" +IMAGE_LOGO BITMAP "resources/logo.bmp" + +DW_FASTFILE RCDATA "resources/dw/ffotd-1.15.1.ff" +DW_MOTD RCDATA "resources/dw/motd-english.txt" +DW_PLAYLISTS RCDATA "resources/dw/playlists_tu12.aggr" + +#ifdef _DEBUG +TLS_DLL RCDATA "../../build/bin/x64/Debug/tlsdll.dll" +#else +TLS_DLL RCDATA "../../build/bin/x64/Release/tlsdll.dll" +#endif + +#ifdef _DEBUG +RUNNER RCDATA "../../build/bin/x64/Debug/runner.exe" +#else +RUNNER RCDATA "../../build/bin/x64/Release/runner.exe" +#endif + +ICON_IMAGE RCDATA "resources/icon.png" + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/client/resources/dw/ffotd-1.15.1.ff b/src/client/resources/dw/ffotd-1.15.1.ff new file mode 100644 index 00000000..3aaf5e7f Binary files /dev/null and b/src/client/resources/dw/ffotd-1.15.1.ff differ diff --git a/src/client/resources/dw/motd-english.txt b/src/client/resources/dw/motd-english.txt new file mode 100644 index 00000000..5155298d --- /dev/null +++ b/src/client/resources/dw/motd-english.txt @@ -0,0 +1 @@ +blank \ No newline at end of file diff --git a/src/client/resources/dw/playlists_tu12.aggr b/src/client/resources/dw/playlists_tu12.aggr new file mode 100644 index 00000000..4b7240a6 Binary files /dev/null and b/src/client/resources/dw/playlists_tu12.aggr differ diff --git a/src/client/resources/icon.ico b/src/client/resources/icon.ico new file mode 100644 index 00000000..d55b4c4c Binary files /dev/null and b/src/client/resources/icon.ico differ diff --git a/src/client/resources/icon.png b/src/client/resources/icon.png new file mode 100644 index 00000000..98e2fb4c Binary files /dev/null and b/src/client/resources/icon.png differ diff --git a/src/client/resources/logo.bmp b/src/client/resources/logo.bmp new file mode 100644 index 00000000..192ab0d0 Binary files /dev/null and b/src/client/resources/logo.bmp differ diff --git a/src/client/resources/splash.bmp b/src/client/resources/splash.bmp new file mode 100644 index 00000000..165e3b7f Binary files /dev/null and b/src/client/resources/splash.bmp differ diff --git a/src/client/std_include.cpp b/src/client/std_include.cpp new file mode 100644 index 00000000..20f99122 --- /dev/null +++ b/src/client/std_include.cpp @@ -0,0 +1,49 @@ +#include + +#pragma comment(linker, "/stack:0x1000000") + +#ifdef INJECT_HOST_AS_LIB +//#pragma comment(linker, "/base:0x160000000") +#else +#pragma comment(linker, "/base:0x140000000") +#pragma comment(linker, "/merge:.data=.cld") +#pragma comment(linker, "/merge:.rdata=.clr") +#pragma comment(linker, "/merge:.cl=.main") +#pragma comment(linker, "/merge:.text=.main") +#endif + +#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language=''\"") + +#ifndef INJECT_HOST_AS_LIB +#pragma bss_seg(".payload") +char payload_data[BINARY_PAYLOAD_SIZE]; +#endif + +extern "C" +{ + __declspec(dllexport) DWORD NvOptimusEnablement = 1; + __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 1; +}; + +extern "C" +{ + int s_read_arc4random(void*, size_t) + { + return -1; + } + + int s_read_getrandom(void*, size_t) + { + return -1; + } + + int s_read_urandom(void*, size_t) + { + return -1; + } + + int s_read_ltm_rng(void*, size_t) + { + return -1; + } +} diff --git a/src/client/std_include.hpp b/src/client/std_include.hpp new file mode 100644 index 00000000..bca1b6ca --- /dev/null +++ b/src/client/std_include.hpp @@ -0,0 +1,100 @@ +#pragma once + +#define BINARY_PAYLOAD_SIZE 0x14000000 + +#pragma warning(push) +#pragma warning(disable: 4100) +#pragma warning(disable: 4127) +#pragma warning(disable: 4244) +#pragma warning(disable: 4458) +#pragma warning(disable: 4702) +#pragma warning(disable: 4996) +#pragma warning(disable: 5054) +#pragma warning(disable: 5056) +#pragma warning(disable: 6011) +#pragma warning(disable: 6297) +#pragma warning(disable: 6385) +#pragma warning(disable: 6386) +#pragma warning(disable: 6387) +#pragma warning(disable: 26110) +#pragma warning(disable: 26451) +#pragma warning(disable: 26444) +#pragma warning(disable: 26451) +#pragma warning(disable: 26489) +#pragma warning(disable: 26495) +#pragma warning(disable: 26498) +#pragma warning(disable: 26812) +#pragma warning(disable: 28020) + +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// min and max is required by gdi, therefore NOMINMAX won't work +#ifdef max +#undef max +#endif + +#ifdef min +#undef min +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#pragma warning(pop) +#pragma warning(disable: 4100) + +#pragma comment(lib, "ntdll.lib") +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "urlmon.lib" ) +#pragma comment(lib, "iphlpapi.lib") +#pragma comment(lib, "Crypt32.lib") + +#include "resource.hpp" + +using namespace std::literals; diff --git a/src/client/steam/interface.cpp b/src/client/steam/interface.cpp new file mode 100644 index 00000000..75ca922a --- /dev/null +++ b/src/client/steam/interface.cpp @@ -0,0 +1,98 @@ +#include +#include "interface.hpp" + +#include +#include + +namespace steam +{ + interface::interface() : interface(nullptr) + { + } + + interface::interface(void* interface_ptr) : interface_ptr_(static_cast(interface_ptr)) + { + } + + interface::operator bool() const + { + return this->interface_ptr_ != nullptr; + } + + void* interface::find_method(const std::string& name) + { + const auto method_entry = this->methods_.find(name); + if (method_entry != this->methods_.end()) + { + return method_entry->second; + } + + return this->search_method(name); + } + + void* interface::search_method(const std::string& name) + { + if (!utils::memory::is_bad_read_ptr(this->interface_ptr_)) + { + auto vftbl = *this->interface_ptr_; + + while (!utils::memory::is_bad_read_ptr(vftbl) && !utils::memory::is_bad_code_ptr(*vftbl)) + { + const auto ptr = *vftbl; + const auto result = this->analyze_method(ptr); + if (!result.empty()) + { + this->methods_[result] = ptr; + + if (result == name) + { + return ptr; + } + } + + ++vftbl; + } + } + + return {}; + } + + std::string interface::analyze_method(const void* method_ptr) + { + if (utils::memory::is_bad_code_ptr(method_ptr)) return {}; + + ud_t ud; + ud_init(&ud); + ud_set_mode(&ud, 64); + ud_set_pc(&ud, uint64_t(method_ptr)); + ud_set_input_buffer(&ud, static_cast(method_ptr), INT32_MAX); + + while (true) + { + ud_disassemble(&ud); + + if (ud_insn_mnemonic(&ud) == UD_Iret) + { + break; + } + + if (ud_insn_mnemonic(&ud) == UD_Ilea) + { + const auto* operand = ud_insn_opr(&ud, 1); + if (operand && operand->type == UD_OP_MEM && operand->base == UD_R_RIP) + { + auto* operand_ptr = reinterpret_cast(ud_insn_len(&ud) + ud_insn_off(&ud) + operand->lval. + sdword); + if (!utils::memory::is_bad_read_ptr(operand_ptr) && utils::memory::is_rdata_ptr(operand_ptr)) + { + return operand_ptr; + } + } + } + + if (*reinterpret_cast(ud.pc) == 0xCC) break; // int 3 + } + + return {}; + } +} diff --git a/src/client/steam/interface.hpp b/src/client/steam/interface.hpp new file mode 100644 index 00000000..c118c80e --- /dev/null +++ b/src/client/steam/interface.hpp @@ -0,0 +1,85 @@ +#pragma once + +#ifdef interface +#undef interface +#endif + +namespace steam +{ + struct raw_steam_id final + { + unsigned int account_id : 32; + unsigned int account_instance : 20; + unsigned int account_type : 4; + int universe : 8; + }; + + typedef union + { + raw_steam_id raw; + unsigned long long bits; + } steam_id; + +#pragma pack( push, 1 ) + struct raw_game_id final + { + unsigned int app_id : 24; + unsigned int type : 8; + unsigned int mod_id : 32; + }; + + typedef union + { + raw_game_id raw; + unsigned long long bits; + } game_id; +#pragma pack( pop ) + + class interface final + { + public: + + interface(); + interface(void* interface_ptr); + + operator bool() const; + + template + T invoke(const std::string& method_name, Args ... args) + { + if (!this->interface_ptr_) + { + throw std::runtime_error("Invalid interface pointer"); + } + + const auto method = this->find_method(method_name); + if (!method) + { + throw std::runtime_error("Unable to find method: " + method_name); + } + + return static_cast(method)(this->interface_ptr_, args...); + } + + template + T invoke(const size_t table_entry, Args ... args) + { + if (!this->interface_ptr_) + { + throw std::runtime_error("Invalid interface pointer"); + } + + return static_cast((*this->interface_ptr_)[table_entry])( + this->interface_ptr_, args...); + } + + private: + void*** interface_ptr_; + std::unordered_map methods_; + + void* find_method(const std::string& name); + void* search_method(const std::string& name); + + std::string analyze_method(const void* method_ptr); + }; +} diff --git a/src/client/steam/interfaces/apps.cpp b/src/client/steam/interfaces/apps.cpp new file mode 100644 index 00000000..44350e5e --- /dev/null +++ b/src/client/steam/interfaces/apps.cpp @@ -0,0 +1,104 @@ +#include +#include "../steam.hpp" + +namespace steam +{ + bool apps::BIsSubscribed() + { + return true; + } + + bool apps::BIsLowViolence() + { + return false; + } + + bool apps::BIsCybercafe() + { + return false; + } + + bool apps::BIsVACBanned() + { + return false; + } + + const char* apps::GetCurrentGameLanguage() + { + return "english"; + } + + const char* apps::GetAvailableGameLanguages() + { + return "english"; + } + + bool apps::BIsSubscribedApp(unsigned int appID) + { + return true; + } + + bool apps::BIsDlcInstalled(unsigned int appID) + { + return true; + } + + unsigned int apps::GetEarliestPurchaseUnixTime(unsigned int nAppID) + { + return 0; + } + + bool apps::BIsSubscribedFromFreeWeekend() + { + return false; + } + + int apps::GetDLCCount() + { + return 0; + } + + bool apps::BGetDLCDataByIndex(int iDLC, unsigned int* pAppID, bool* pbAvailable, char* pchName, + int cchNameBufferSize) + { + return false; + } + + void apps::InstallDLC(unsigned int nAppID) + { + } + + void apps::UninstallDLC(unsigned int nAppID) + { + } + + void apps::RequestAppProofOfPurchaseKey(unsigned int nAppID) + { + } + + bool apps::GetCurrentBetaName(char* pchName, int cchNameBufferSize) + { + strncpy_s(pchName, cchNameBufferSize, "public", cchNameBufferSize); + return true; + } + + bool apps::MarkContentCorrupt(bool bMissingFilesOnly) + { + return false; + } + + unsigned int apps::GetInstalledDepots(int* pvecDepots, unsigned int cMaxDepots) + { + return 0; + } + + unsigned int apps::GetAppInstallDir(unsigned int appID, char* pchFolder, unsigned int cchFolderBufferSize) + { + return 0; + } + + bool apps::BIsAppInstalled(unsigned int appID) + { + return false; + } +} \ No newline at end of file diff --git a/src/client/steam/interfaces/apps.hpp b/src/client/steam/interfaces/apps.hpp new file mode 100644 index 00000000..07298080 --- /dev/null +++ b/src/client/steam/interfaces/apps.hpp @@ -0,0 +1,32 @@ +#pragma once + +namespace steam +{ + class apps + { + public: + ~apps() = default; + + virtual bool BIsSubscribed(); + virtual bool BIsLowViolence(); + virtual bool BIsCybercafe(); + virtual bool BIsVACBanned(); + virtual const char* GetCurrentGameLanguage(); + virtual const char* GetAvailableGameLanguages(); + virtual bool BIsSubscribedApp(unsigned int appID); + virtual bool BIsDlcInstalled(unsigned int appID); + virtual unsigned int GetEarliestPurchaseUnixTime(unsigned int nAppID); + virtual bool BIsSubscribedFromFreeWeekend(); + virtual int GetDLCCount(); + virtual bool BGetDLCDataByIndex(int iDLC, unsigned int* pAppID, bool* pbAvailable, char* pchName, + int cchNameBufferSize); + virtual void InstallDLC(unsigned int nAppID); + virtual void UninstallDLC(unsigned int nAppID); + virtual void RequestAppProofOfPurchaseKey(unsigned int nAppID); + virtual bool GetCurrentBetaName(char* pchName, int cchNameBufferSize); + virtual bool MarkContentCorrupt(bool bMissingFilesOnly); + virtual unsigned int GetInstalledDepots(int* pvecDepots, unsigned int cMaxDepots); + virtual unsigned int GetAppInstallDir(unsigned int appID, char* pchFolder, unsigned int cchFolderBufferSize); + virtual bool BIsAppInstalled(unsigned int appID); + }; +} diff --git a/src/client/steam/interfaces/friends.cpp b/src/client/steam/interfaces/friends.cpp new file mode 100644 index 00000000..8c29dd26 --- /dev/null +++ b/src/client/steam/interfaces/friends.cpp @@ -0,0 +1,315 @@ +#include +#include "../steam.hpp" + +#include + +namespace steam +{ + const char* friends::GetPersonaName() + { + return "1337"; + } + + unsigned long long friends::SetPersonaName(const char* pchPersonaName) + { + return 0; + } + + int friends::GetPersonaState() + { + return 1; + } + + int friends::GetFriendCount(int eFriendFlags) + { + return 0; + } + + steam_id friends::GetFriendByIndex(int iFriend, int iFriendFlags) + { + return steam_id(); + } + + int friends::GetFriendRelationship(steam_id steamIDFriend) + { + return 0; + } + + int friends::GetFriendPersonaState(steam_id steamIDFriend) + { + return 0; + } + + const char* friends::GetFriendPersonaName(steam_id steamIDFriend) + { + return ""; + } + + bool friends::GetFriendGamePlayed(steam_id steamIDFriend, void* pFriendGameInfo) + { + return false; + } + + const char* friends::GetFriendPersonaNameHistory(steam_id steamIDFriend, int iPersonaName) + { + return ""; + } + + bool friends::HasFriend(steam_id steamIDFriend, int eFriendFlags) + { + return false; + } + + int friends::GetClanCount() + { + return 0; + } + + steam_id friends::GetClanByIndex(int iClan) + { + return steam_id(); + } + + const char* friends::GetClanName(steam_id steamIDClan) + { + return "3arc"; + } + + const char* friends::GetClanTag(steam_id steamIDClan) + { + return this->GetClanName(steamIDClan); + } + + bool friends::GetClanActivityCounts(steam_id steamID, int* pnOnline, int* pnInGame, int* pnChatting) + { + return false; + } + + unsigned long long friends::DownloadClanActivityCounts(steam_id groupIDs[], int nIds) + { + return 0; + } + + int friends::GetFriendCountFromSource(steam_id steamIDSource) + { + return 0; + } + + steam_id friends::GetFriendFromSourceByIndex(steam_id steamIDSource, int iFriend) + { + return steam_id(); + } + + bool friends::IsUserInSource(steam_id steamIDUser, steam_id steamIDSource) + { + return false; + } + + void friends::SetInGameVoiceSpeaking(steam_id steamIDUser, bool bSpeaking) + { + } + + void friends::ActivateGameOverlay(const char* pchDialog) + { + } + + void friends::ActivateGameOverlayToUser(const char* pchDialog, steam_id steamID) + { + } + + void friends::ActivateGameOverlayToWebPage(const char* pchURL) + { + } + + void friends::ActivateGameOverlayToStore(unsigned int nAppID, unsigned int eFlag) + { + } + + void friends::SetPlayedWith(steam_id steamIDUserPlayedWith) + { + } + + void friends::ActivateGameOverlayInviteDialog(steam_id steamIDLobby) + { + } + + int friends::GetSmallFriendAvatar(steam_id steamIDFriend) + { + return 0; + } + + int friends::GetMediumFriendAvatar(steam_id steamIDFriend) + { + return 0; + } + + int friends::GetLargeFriendAvatar(steam_id steamIDFriend) + { + return 0; + } + + bool friends::RequestUserInformation(steam_id steamIDUser, bool bRequireNameOnly) + { + return false; + } + + unsigned long long friends::RequestClanOfficerList(steam_id steamIDClan) + { + return 0; + } + + steam_id friends::GetClanOwner(steam_id steamIDClan) + { + return steam_id(); + } + + int friends::GetClanOfficerCount(steam_id steamIDClan) + { + return 0; + } + + steam_id friends::GetClanOfficerByIndex(steam_id steamIDClan, int iOfficer) + { + return steam_id(); + } + + int friends::GetUserRestrictions() + { + return 0; + } + + bool friends::SetRichPresence(const char* pchKey, const char* pchValue) + { + return true; + } + + void friends::ClearRichPresence() + { + } + + const char* friends::GetFriendRichPresence(steam_id steamIDFriend, const char* pchKey) + { + return ""; + } + + int friends::GetFriendRichPresenceKeyCount(steam_id steamIDFriend) + { + return 0; + } + + const char* friends::GetFriendRichPresenceKeyByIndex(steam_id steamIDFriend, int iKey) + { + return "a"; + } + + void friends::RequestFriendRichPresence(steam_id steamIDFriend) + { + } + + bool friends::InviteUserToGame(steam_id steamIDFriend, const char* pchConnectString) + { + return false; + } + + int friends::GetCoplayFriendCount() + { + return 0; + } + + steam_id friends::GetCoplayFriend(int iCoplayFriend) + { + return steam_id(); + } + + int friends::GetFriendCoplayTime(steam_id steamIDFriend) + { + return 0; + } + + unsigned int friends::GetFriendCoplayGame(steam_id steamIDFriend) + { + return 0; + } + + unsigned long long friends::JoinClanChatRoom(steam_id steamIDClan) + { + return 0; + } + + bool friends::LeaveClanChatRoom(steam_id steamIDClan) + { + return false; + } + + int friends::GetClanChatMemberCount(steam_id steamIDClan) + { + return 0; + } + + steam_id friends::GetChatMemberByIndex(steam_id steamIDClan, int iUser) + { + return steam_id(); + } + + bool friends::SendClanChatMessage(steam_id steamIDClanChat, const char* pchText) + { + return false; + } + + int friends::GetClanChatMessage(steam_id steamIDClanChat, int iMessage, void* prgchText, int cchTextMax, + unsigned int* peChatEntryType, steam_id* pSteamIDChatter) + { + return 0; + } + + bool friends::IsClanChatAdmin(steam_id steamIDClanChat, steam_id steamIDUser) + { + return false; + } + + bool friends::IsClanChatWindowOpenInSteam(steam_id steamIDClanChat) + { + return false; + } + + bool friends::OpenClanChatWindowInSteam(steam_id steamIDClanChat) + { + return false; + } + + bool friends::CloseClanChatWindowInSteam(steam_id steamIDClanChat) + { + return false; + } + + bool friends::SetListenForFriendsMessages(bool bInterceptEnabled) + { + return false; + } + + bool friends::ReplyToFriendMessage(steam_id steamIDFriend, const char* pchMsgToSend) + { + return false; + } + + int friends::GetFriendMessage(steam_id steamIDFriend, int iMessageID, void* pvData, int cubData, + unsigned int* peChatEntryType) + { + return 0; + } + + unsigned long long friends::GetFollowerCount(steam_id steamID) + { + return 0; + } + + unsigned long long friends::IsFollowing(steam_id steamID) + { + return 0; + } + + unsigned long long friends::EnumerateFollowingList(unsigned int unStartIndex) + { + return 0; + } +} diff --git a/src/client/steam/interfaces/friends.hpp b/src/client/steam/interfaces/friends.hpp new file mode 100644 index 00000000..f7cb2a2e --- /dev/null +++ b/src/client/steam/interfaces/friends.hpp @@ -0,0 +1,76 @@ +#pragma once + +namespace steam +{ + class friends + { + public: + ~friends() = default; + + virtual const char* GetPersonaName(); + virtual unsigned long long SetPersonaName(const char* pchPersonaName); + virtual int GetPersonaState(); + virtual int GetFriendCount(int eFriendFlags); + virtual steam_id GetFriendByIndex(int iFriend, int iFriendFlags); + virtual int GetFriendRelationship(steam_id steamIDFriend); + virtual int GetFriendPersonaState(steam_id steamIDFriend); + virtual const char* GetFriendPersonaName(steam_id steamIDFriend); + virtual bool GetFriendGamePlayed(steam_id steamIDFriend, void* pFriendGameInfo); + virtual const char* GetFriendPersonaNameHistory(steam_id steamIDFriend, int iPersonaName); + virtual bool HasFriend(steam_id steamIDFriend, int eFriendFlags); + virtual int GetClanCount(); + virtual steam_id GetClanByIndex(int iClan); + virtual const char* GetClanName(steam_id steamIDClan); + virtual const char* GetClanTag(steam_id steamIDClan); + virtual bool GetClanActivityCounts(steam_id steamID, int* pnOnline, int* pnInGame, int* pnChatting); + virtual unsigned long long DownloadClanActivityCounts(steam_id groupIDs[], int nIds); + virtual int GetFriendCountFromSource(steam_id steamIDSource); + virtual steam_id GetFriendFromSourceByIndex(steam_id steamIDSource, int iFriend); + virtual bool IsUserInSource(steam_id steamIDUser, steam_id steamIDSource); + virtual void SetInGameVoiceSpeaking(steam_id steamIDUser, bool bSpeaking); + virtual void ActivateGameOverlay(const char* pchDialog); + virtual void ActivateGameOverlayToUser(const char* pchDialog, steam_id steamID); + virtual void ActivateGameOverlayToWebPage(const char* pchURL); + virtual void ActivateGameOverlayToStore(unsigned int nAppID, unsigned int eFlag); + virtual void SetPlayedWith(steam_id steamIDUserPlayedWith); + virtual void ActivateGameOverlayInviteDialog(steam_id steamIDLobby); + virtual int GetSmallFriendAvatar(steam_id steamIDFriend); + virtual int GetMediumFriendAvatar(steam_id steamIDFriend); + virtual int GetLargeFriendAvatar(steam_id steamIDFriend); + virtual bool RequestUserInformation(steam_id steamIDUser, bool bRequireNameOnly); + virtual unsigned long long RequestClanOfficerList(steam_id steamIDClan); + virtual steam_id GetClanOwner(steam_id steamIDClan); + virtual int GetClanOfficerCount(steam_id steamIDClan); + virtual steam_id GetClanOfficerByIndex(steam_id steamIDClan, int iOfficer); + virtual int GetUserRestrictions(); + virtual bool SetRichPresence(const char* pchKey, const char* pchValue); + virtual void ClearRichPresence(); + virtual const char* GetFriendRichPresence(steam_id steamIDFriend, const char* pchKey); + virtual int GetFriendRichPresenceKeyCount(steam_id steamIDFriend); + virtual const char* GetFriendRichPresenceKeyByIndex(steam_id steamIDFriend, int iKey); + virtual void RequestFriendRichPresence(steam_id steamIDFriend); + virtual bool InviteUserToGame(steam_id steamIDFriend, const char* pchConnectString); + virtual int GetCoplayFriendCount(); + virtual steam_id GetCoplayFriend(int iCoplayFriend); + virtual int GetFriendCoplayTime(steam_id steamIDFriend); + virtual unsigned int GetFriendCoplayGame(steam_id steamIDFriend); + virtual unsigned long long JoinClanChatRoom(steam_id steamIDClan); + virtual bool LeaveClanChatRoom(steam_id steamIDClan); + virtual int GetClanChatMemberCount(steam_id steamIDClan); + virtual steam_id GetChatMemberByIndex(steam_id steamIDClan, int iUser); + virtual bool SendClanChatMessage(steam_id steamIDClanChat, const char* pchText); + virtual int GetClanChatMessage(steam_id steamIDClanChat, int iMessage, void* prgchText, int cchTextMax, + unsigned int* peChatEntryType, steam_id* pSteamIDChatter); + virtual bool IsClanChatAdmin(steam_id steamIDClanChat, steam_id steamIDUser); + virtual bool IsClanChatWindowOpenInSteam(steam_id steamIDClanChat); + virtual bool OpenClanChatWindowInSteam(steam_id steamIDClanChat); + virtual bool CloseClanChatWindowInSteam(steam_id steamIDClanChat); + virtual bool SetListenForFriendsMessages(bool bInterceptEnabled); + virtual bool ReplyToFriendMessage(steam_id steamIDFriend, const char* pchMsgToSend); + virtual int GetFriendMessage(steam_id steamIDFriend, int iMessageID, void* pvData, int cubData, + unsigned int* peChatEntryType); + virtual unsigned long long GetFollowerCount(steam_id steamID); + virtual unsigned long long IsFollowing(steam_id steamID); + virtual unsigned long long EnumerateFollowingList(unsigned int unStartIndex); + }; +} diff --git a/src/client/steam/interfaces/game_server.cpp b/src/client/steam/interfaces/game_server.cpp new file mode 100644 index 00000000..11e7a79d --- /dev/null +++ b/src/client/steam/interfaces/game_server.cpp @@ -0,0 +1,204 @@ +#include +#include "../steam.hpp" + +namespace steam +{ + bool game_server::InitGameServer(unsigned int unGameIP, unsigned short unGamePort, unsigned short usQueryPort, + unsigned int unServerFlags, unsigned int nAppID, const char* pchVersion) + { + return true; + } + + void game_server::SetProduct(const char* pchProductName) + { + } + + void game_server::SetGameDescription(const char* pchGameDescription) + { + } + + void game_server::SetModDir(const char* pchModDir) + { + } + + void game_server::SetDedicatedServer(bool bDedicatedServer) + { + } + + void game_server::LogOn(const char* pszAccountName, const char* pszPassword) + { + } + + void game_server::LogOnAnonymous() + { + auto* const retvals = calloc(1, 1); + const auto result = callbacks::register_call(); + callbacks::return_call(retvals, 0, 101, result); + } + + void game_server::LogOff() + { + } + + bool game_server::BLoggedOn() + { + return true; + } + + bool game_server::BSecure() + { + return false; + } + + steam_id game_server::GetSteamID() + { + return SteamUser()->GetSteamID(); + } + + bool game_server::WasRestartRequested() + { + return false; + } + + void game_server::SetMaxPlayerCount(int cPlayersMax) + { + } + + void game_server::SetBotPlayerCount(int cBotPlayers) + { + } + + void game_server::SetServerName(const char* pszServerName) + { + } + + void game_server::SetMapName(const char* pszMapName) + { + } + + void game_server::SetPasswordProtected(bool bPasswordProtected) + { + } + + void game_server::SetSpectatorPort(unsigned short unSpectatorPort) + { + } + + void game_server::SetSpectatorServerName(const char* pszSpectatorServerName) + { + } + + void game_server::ClearAllKeyValues() + { + } + + void game_server::SetKeyValue(const char* pKey, const char* pValue) + { + } + + void game_server::SetGameTags(const char* pchGameTags) + { + } + + void game_server::SetGameData(const char* pchGameData) + { + } + + void game_server::SetRegion(const char* pchRegionName) + { + } + + int game_server::SendUserConnectAndAuthenticate(unsigned int unIPClient, const void* pvAuthBlob, + unsigned int cubAuthBlobSize, steam_id* pSteamIDUser) + { + return 0; + } + + steam_id game_server::CreateUnauthenticatedUserConnection() + { + return SteamUser()->GetSteamID(); + } + + void game_server::SendUserDisconnect(steam_id steamIDUser) + { + } + + bool game_server::BUpdateUserData(steam_id steamIDUser, const char* pchPlayerName, unsigned int uScore) + { + return false; + } + + int game_server::GetAuthSessionTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket) + { + return 0; + } + + int game_server::BeginAuthSession(const void* pAuthTicket, int cbAuthTicket, steam_id steamID) + { + return 0; + } + + void game_server::EndAuthSession(steam_id steamID) + { + } + + void game_server::CancelAuthTicket(int hAuthTicket) + { + } + + int game_server::UserHasLicenseForApp(steam_id steamID, unsigned int appID) + { + return 0; + } + + bool game_server::RequestUserGroupStatus(steam_id steamIDUser, steam_id steamIDGroup) + { + return false; + } + + void game_server::GetGameplayStats() + { + } + + unsigned long long game_server::GetServerReputation() + { + return 0; + } + + unsigned int game_server::GetPublicIP() + { + return 0; + } + + bool game_server::HandleIncomingPacket(const void* pData, int cbData, unsigned int srcIP, unsigned short srcPort) + { + return false; + } + + int game_server::GetNextOutgoingPacket(void* pOut, int cbMaxOut, unsigned int* pNetAdr, unsigned short* pPort) + { + return 0; + } + + void game_server::EnableHeartbeats(bool bActive) + { + } + + void game_server::SetHeartbeatInterval(int iHeartbeatInterval) + { + } + + void game_server::ForceHeartbeat() + { + } + + unsigned long long game_server::AssociateWithClan(steam_id clanID) + { + return 0; + } + + unsigned long long game_server::ComputeNewPlayerCompatibility(steam_id steamID) + { + return 0; + } +} diff --git a/src/client/steam/interfaces/game_server.hpp b/src/client/steam/interfaces/game_server.hpp new file mode 100644 index 00000000..3f7f7c71 --- /dev/null +++ b/src/client/steam/interfaces/game_server.hpp @@ -0,0 +1,57 @@ +#pragma once + +namespace steam +{ + class game_server + { + public: + ~game_server() = default; + + virtual bool InitGameServer(unsigned int unGameIP, unsigned short unGamePort, unsigned short usQueryPort, + unsigned int unServerFlags, unsigned int nAppID, const char* pchVersion); + virtual void SetProduct(const char* pchProductName); + virtual void SetGameDescription(const char* pchGameDescription); + virtual void SetModDir(const char* pchModDir); + virtual void SetDedicatedServer(bool bDedicatedServer); + virtual void LogOn(const char* pszAccountName, const char* pszPassword); + virtual void LogOnAnonymous(); + virtual void LogOff(); + virtual bool BLoggedOn(); + virtual bool BSecure(); + virtual steam_id GetSteamID(); + virtual bool WasRestartRequested(); + virtual void SetMaxPlayerCount(int cPlayersMax); + virtual void SetBotPlayerCount(int cBotPlayers); + virtual void SetServerName(const char* pszServerName); + virtual void SetMapName(const char* pszMapName); + virtual void SetPasswordProtected(bool bPasswordProtected); + virtual void SetSpectatorPort(unsigned short unSpectatorPort); + virtual void SetSpectatorServerName(const char* pszSpectatorServerName); + virtual void ClearAllKeyValues(); + virtual void SetKeyValue(const char* pKey, const char* pValue); + virtual void SetGameTags(const char* pchGameTags); + virtual void SetGameData(const char* pchGameData); + virtual void SetRegion(const char* pchRegionName); + virtual int SendUserConnectAndAuthenticate(unsigned int unIPClient, const void* pvAuthBlob, + unsigned int cubAuthBlobSize, steam_id* pSteamIDUser); + virtual steam_id CreateUnauthenticatedUserConnection(); + virtual void SendUserDisconnect(steam_id steamIDUser); + virtual bool BUpdateUserData(steam_id steamIDUser, const char* pchPlayerName, unsigned int uScore); + virtual int GetAuthSessionTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket); + virtual int BeginAuthSession(const void* pAuthTicket, int cbAuthTicket, steam_id steamID); + virtual void EndAuthSession(steam_id steamID); + virtual void CancelAuthTicket(int hAuthTicket); + virtual int UserHasLicenseForApp(steam_id steamID, unsigned int appID); + virtual bool RequestUserGroupStatus(steam_id steamIDUser, steam_id steamIDGroup); + virtual void GetGameplayStats(); + virtual unsigned long long GetServerReputation(); + virtual unsigned int GetPublicIP(); + virtual bool HandleIncomingPacket(const void* pData, int cbData, unsigned int srcIP, unsigned short srcPort); + virtual int GetNextOutgoingPacket(void* pOut, int cbMaxOut, unsigned int* pNetAdr, unsigned short* pPort); + virtual void EnableHeartbeats(bool bActive); + virtual void SetHeartbeatInterval(int iHeartbeatInterval); + virtual void ForceHeartbeat(); + virtual unsigned long long AssociateWithClan(steam_id clanID); + virtual unsigned long long ComputeNewPlayerCompatibility(steam_id steamID); + }; +} diff --git a/src/client/steam/interfaces/matchmaking.cpp b/src/client/steam/interfaces/matchmaking.cpp new file mode 100644 index 00000000..8b8dec7b --- /dev/null +++ b/src/client/steam/interfaces/matchmaking.cpp @@ -0,0 +1,230 @@ +#include +#include "../steam.hpp" + +namespace steam +{ + int matchmaking::GetFavoriteGameCount() + { + return 0; + } + + bool matchmaking::GetFavoriteGame(int iGame, unsigned int* pnAppID, unsigned int* pnIP, unsigned short* pnConnPort, + unsigned short* pnQueryPort, unsigned int* punFlags, + unsigned int* pRTime32LastPlayedOnServer) + { + return false; + } + + int matchmaking::AddFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, + unsigned short nQueryPort, unsigned int unFlags, + unsigned int rTime32LastPlayedOnServer) + { + return 0; + } + + bool matchmaking::RemoveFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, + unsigned short nQueryPort, unsigned int unFlags) + { + return false; + } + + unsigned long long matchmaking::RequestLobbyList() + { + return 0; + } + + void matchmaking::AddRequestLobbyListStringFilter(const char* pchKeyToMatch, const char* pchValueToMatch, + int eComparisonType) + { + } + + void matchmaking::AddRequestLobbyListNumericalFilter(const char* pchKeyToMatch, int nValueToMatch, + int eComparisonType) + { + } + + void matchmaking::AddRequestLobbyListNearValueFilter(const char* pchKeyToMatch, int nValueToBeCloseTo) + { + } + + void matchmaking::AddRequestLobbyListFilterSlotsAvailable(int nSlotsAvailable) + { + } + + void matchmaking::AddRequestLobbyListDistanceFilter(int eLobbyDistanceFilter) + { + } + + void matchmaking::AddRequestLobbyListResultCountFilter(int cMaxResults) + { + } + + void matchmaking::AddRequestLobbyListCompatibleMembersFilter(steam_id steamID) + { + } + + steam_id matchmaking::GetLobbyByIndex(int iLobby) + { + steam_id id; + + id.raw.account_id = SteamUser()->GetSteamID().raw.account_id; + id.raw.universe = 1; + id.raw.account_type = 8; + id.raw.account_instance = 0x40000; + + return id; + } + + unsigned long long matchmaking::CreateLobby(int eLobbyType, int cMaxMembers) + { + const auto result = callbacks::register_call(); + auto retvals = static_cast(calloc(1, sizeof(lobby_created))); + //::Utils::Memory::AllocateArray(); + steam_id id; + + id.raw.account_id = SteamUser()->GetSteamID().raw.account_id; + id.raw.universe = 1; + id.raw.account_type = 8; + id.raw.account_instance = 0x40000; + + retvals->m_e_result = 1; + retvals->m_ul_steam_id_lobby = id; + + callbacks::return_call(retvals, sizeof(lobby_created), lobby_created::callback_id, result); + + matchmaking::JoinLobby(id); + + return result; + } + + unsigned long long matchmaking::JoinLobby(steam_id steamIDLobby) + { + const auto result = callbacks::register_call(); + auto* retvals = static_cast(calloc(1, sizeof(lobby_enter))); + //::Utils::Memory::AllocateArray(); + retvals->m_b_locked = false; + retvals->m_e_chat_room_enter_response = 1; + retvals->m_rgf_chat_permissions = 0xFFFFFFFF; + retvals->m_ul_steam_id_lobby = steamIDLobby; + + callbacks::return_call(retvals, sizeof(lobby_enter), lobby_enter::callback_id, result); + + return result; + } + + void matchmaking::LeaveLobby(steam_id steamIDLobby) + { + } + + bool matchmaking::InviteUserToLobby(steam_id steamIDLobby, steam_id steamIDInvitee) + { + return true; + } + + int matchmaking::GetNumLobbyMembers(steam_id steamIDLobby) + { + return 1; + } + + steam_id matchmaking::GetLobbyMemberByIndex(steam_id steamIDLobby, int iMember) + { + return SteamUser()->GetSteamID(); + } + + const char* matchmaking::GetLobbyData(steam_id steamIDLobby, const char* pchKey) + { + return ""; + } + + bool matchmaking::SetLobbyData(steam_id steamIDLobby, const char* pchKey, const char* pchValue) + { + return true; + } + + int matchmaking::GetLobbyDataCount(steam_id steamIDLobby) + { + return 0; + } + + bool matchmaking::GetLobbyDataByIndex(steam_id steamIDLobby, int iLobbyData, char* pchKey, int cchKeyBufferSize, + char* pchValue, int cchValueBufferSize) + { + return true; + } + + bool matchmaking::DeleteLobbyData(steam_id steamIDLobby, const char* pchKey) + { + return true; + } + + const char* matchmaking::GetLobbyMemberData(steam_id steamIDLobby, steam_id steamIDUser, const char* pchKey) + { + return ""; + } + + void matchmaking::SetLobbyMemberData(steam_id steamIDLobby, const char* pchKey, const char* pchValue) + { + } + + bool matchmaking::SendLobbyChatMsg(steam_id steamIDLobby, const void* pvMsgBody, int cubMsgBody) + { + return true; + } + + int matchmaking::GetLobbyChatEntry(steam_id steamIDLobby, int iChatID, steam_id* pSteamIDUser, void* pvData, + int cubData, int* peChatEntryType) + { + return 0; + } + + bool matchmaking::RequestLobbyData(steam_id steamIDLobby) + { + return true; + } + + void matchmaking::SetLobbyGameServer(steam_id steamIDLobby, unsigned int unGameServerIP, + unsigned short unGameServerPort, steam_id steamIDGameServer) + { + } + + bool matchmaking::GetLobbyGameServer(steam_id steamIDLobby, unsigned int* punGameServerIP, + unsigned short* punGameServerPort, steam_id* psteamIDGameServer) + { + return true; + } + + bool matchmaking::SetLobbyMemberLimit(steam_id steamIDLobby, int cMaxMembers) + { + return true; + } + + int matchmaking::GetLobbyMemberLimit(steam_id steamIDLobby) + { + return 0; + } + + bool matchmaking::SetLobbyType(steam_id steamIDLobby, int eLobbyType) + { + return true; + } + + bool matchmaking::SetLobbyJoinable(steam_id steamIDLobby, bool bLobbyJoinable) + { + return true; + } + + steam_id matchmaking::GetLobbyOwner(steam_id steamIDLobby) + { + return SteamUser()->GetSteamID(); + } + + bool matchmaking::SetLobbyOwner(steam_id steamIDLobby, steam_id steamIDNewOwner) + { + return true; + } + + bool matchmaking::SetLinkedLobby(steam_id steamIDLobby, steam_id steamIDLobby2) + { + return true; + } +} diff --git a/src/client/steam/interfaces/matchmaking.hpp b/src/client/steam/interfaces/matchmaking.hpp new file mode 100644 index 00000000..88923212 --- /dev/null +++ b/src/client/steam/interfaces/matchmaking.hpp @@ -0,0 +1,79 @@ +#pragma once + +namespace steam +{ + struct lobby_created final + { + enum { callback_id = 513 }; + + int m_e_result; + int m_pad; + steam_id m_ul_steam_id_lobby; + }; + + struct lobby_enter final + { + enum { callback_id = 504 }; + + steam_id m_ul_steam_id_lobby; + int m_rgf_chat_permissions; + bool m_b_locked; + int m_e_chat_room_enter_response; + }; + + class matchmaking + { + public: + ~matchmaking() = default; + + virtual int GetFavoriteGameCount(); + virtual bool GetFavoriteGame(int iGame, unsigned int* pnAppID, unsigned int* pnIP, unsigned short* pnConnPort, + unsigned short* pnQueryPort, unsigned int* punFlags, + unsigned int* pRTime32LastPlayedOnServer); + virtual int AddFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, + unsigned short nQueryPort, unsigned int unFlags, + unsigned int rTime32LastPlayedOnServer); + virtual bool RemoveFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, + unsigned short nQueryPort, unsigned int unFlags); + virtual unsigned long long RequestLobbyList(); + virtual void AddRequestLobbyListStringFilter(const char* pchKeyToMatch, const char* pchValueToMatch, + int eComparisonType); + virtual void AddRequestLobbyListNumericalFilter(const char* pchKeyToMatch, int nValueToMatch, + int eComparisonType); + virtual void AddRequestLobbyListNearValueFilter(const char* pchKeyToMatch, int nValueToBeCloseTo); + virtual void AddRequestLobbyListFilterSlotsAvailable(int nSlotsAvailable); + virtual void AddRequestLobbyListDistanceFilter(int eLobbyDistanceFilter); + virtual void AddRequestLobbyListResultCountFilter(int cMaxResults); + virtual void AddRequestLobbyListCompatibleMembersFilter(steam_id steamID); + virtual steam_id GetLobbyByIndex(int iLobby); + virtual unsigned long long CreateLobby(int eLobbyType, int cMaxMembers); + virtual unsigned long long JoinLobby(steam_id steamIDLobby); + virtual void LeaveLobby(steam_id steamIDLobby); + virtual bool InviteUserToLobby(steam_id steamIDLobby, steam_id steamIDInvitee); + virtual int GetNumLobbyMembers(steam_id steamIDLobby); + virtual steam_id GetLobbyMemberByIndex(steam_id steamIDLobby, int iMember); + virtual const char* GetLobbyData(steam_id steamIDLobby, const char* pchKey); + virtual bool SetLobbyData(steam_id steamIDLobby, const char* pchKey, const char* pchValue); + virtual int GetLobbyDataCount(steam_id steamIDLobby); + virtual bool GetLobbyDataByIndex(steam_id steamIDLobby, int iLobbyData, char* pchKey, int cchKeyBufferSize, + char* pchValue, int cchValueBufferSize); + virtual bool DeleteLobbyData(steam_id steamIDLobby, const char* pchKey); + virtual const char* GetLobbyMemberData(steam_id steamIDLobby, steam_id steamIDUser, const char* pchKey); + virtual void SetLobbyMemberData(steam_id steamIDLobby, const char* pchKey, const char* pchValue); + virtual bool SendLobbyChatMsg(steam_id steamIDLobby, const void* pvMsgBody, int cubMsgBody); + virtual int GetLobbyChatEntry(steam_id steamIDLobby, int iChatID, steam_id* pSteamIDUser, void* pvData, + int cubData, int* peChatEntryType); + virtual bool RequestLobbyData(steam_id steamIDLobby); + virtual void SetLobbyGameServer(steam_id steamIDLobby, unsigned int unGameServerIP, + unsigned short unGameServerPort, steam_id steamIDGameServer); + virtual bool GetLobbyGameServer(steam_id steamIDLobby, unsigned int* punGameServerIP, + unsigned short* punGameServerPort, steam_id* psteamIDGameServer); + virtual bool SetLobbyMemberLimit(steam_id steamIDLobby, int cMaxMembers); + virtual int GetLobbyMemberLimit(steam_id steamIDLobby); + virtual bool SetLobbyType(steam_id steamIDLobby, int eLobbyType); + virtual bool SetLobbyJoinable(steam_id steamIDLobby, bool bLobbyJoinable); + virtual steam_id GetLobbyOwner(steam_id steamIDLobby); + virtual bool SetLobbyOwner(steam_id steamIDLobby, steam_id steamIDNewOwner); + virtual bool SetLinkedLobby(steam_id steamIDLobby, steam_id steamIDLobby2); + }; +} diff --git a/src/client/steam/interfaces/networking.cpp b/src/client/steam/interfaces/networking.cpp new file mode 100644 index 00000000..d0ee6e0e --- /dev/null +++ b/src/client/steam/interfaces/networking.cpp @@ -0,0 +1,121 @@ +#include +#include "../steam.hpp" + +namespace steam +{ + bool networking::SendP2PPacket(steam_id steamIDRemote, const void* pubData, unsigned int cubData, int eP2PSendType) + { + return false; + } + + bool networking::IsP2PPacketAvailable(unsigned int* pcubMsgSize, int idk) + { + return false; + } + + bool networking::ReadP2PPacket(void* pubDest, unsigned int cubDest, unsigned int* pcubMsgSize, + steam_id* psteamIDRemote) + { + return false; + } + + bool networking::AcceptP2PSessionWithUser(steam_id steamIDRemote) + { + return false; + } + + bool networking::CloseP2PSessionWithUser(steam_id steamIDRemote) + { + return false; + } + + bool networking::CloseP2PChannelWithUser(steam_id steamIDRemote, int iVirtualPort) + { + return false; + } + + bool networking::GetP2PSessionState(steam_id steamIDRemote, void* pConnectionState) + { + return false; + } + + bool networking::AllowP2PPacketRelay(bool bAllow) + { + return false; + } + + unsigned int networking::CreateListenSocket(int nVirtualP2PPort, unsigned int nIP, unsigned short nPort, + bool bAllowUseOfPacketRelay) + { + return NULL; + } + + unsigned int networking::CreateP2PConnectionSocket(steam_id steamIDTarget, int nVirtualPort, int nTimeoutSec, + bool bAllowUseOfPacketRelay) + { + return NULL; + } + + unsigned int networking::CreateConnectionSocket(unsigned int nIP, unsigned short nPort, int nTimeoutSec) + { + return NULL; + } + + bool networking::DestroySocket(unsigned int hSocket, bool bNotifyRemoteEnd) + { + return false; + } + + bool networking::DestroyListenSocket(unsigned int hSocket, bool bNotifyRemoteEnd) + { + return false; + } + + bool networking::SendDataOnSocket(unsigned int hSocket, void* pubData, unsigned int cubData, bool bReliable) + { + return false; + } + + bool networking::IsDataAvailableOnSocket(unsigned int hSocket, unsigned int* pcubMsgSize) + { + return false; + } + + bool networking::RetrieveDataFromSocket(unsigned int hSocket, void* pubDest, unsigned int cubDest, + unsigned int* pcubMsgSize) + { + return false; + } + + bool networking::IsDataAvailable(unsigned int hListenSocket, unsigned int* pcubMsgSize, unsigned int* phSocket) + { + return false; + } + + bool networking::RetrieveData(unsigned int hListenSocket, void* pubDest, unsigned int cubDest, + unsigned int* pcubMsgSize, unsigned int* phSocket) + { + return false; + } + + bool networking::GetSocketInfo(unsigned int hSocket, steam_id* pSteamIDRemote, int* peSocketStatus, + unsigned int* punIPRemote, unsigned short* punPortRemote) + { + return false; + } + + bool networking::GetListenSocketInfo(unsigned int hListenSocket, unsigned int* pnIP, unsigned short* pnPort) + { + return false; + } + + int networking::GetSocketConnectionType(unsigned int hSocket) + { + return 0; + } + + int networking::GetMaxPacketSize(unsigned int hSocket) + { + return 0; + } +} diff --git a/src/client/steam/interfaces/networking.hpp b/src/client/steam/interfaces/networking.hpp new file mode 100644 index 00000000..bb1b29dd --- /dev/null +++ b/src/client/steam/interfaces/networking.hpp @@ -0,0 +1,39 @@ +#pragma once + +namespace steam +{ + class networking + { + public: + ~networking() = default; + + virtual bool SendP2PPacket(steam_id steamIDRemote, const void* pubData, unsigned int cubData, int eP2PSendType); + virtual bool IsP2PPacketAvailable(unsigned int* pcubMsgSize, int idk); + virtual bool ReadP2PPacket(void* pubDest, unsigned int cubDest, unsigned int* pcubMsgSize, + steam_id* psteamIDRemote); + virtual bool AcceptP2PSessionWithUser(steam_id steamIDRemote); + virtual bool CloseP2PSessionWithUser(steam_id steamIDRemote); + virtual bool CloseP2PChannelWithUser(steam_id steamIDRemote, int iVirtualPort); + virtual bool GetP2PSessionState(steam_id steamIDRemote, void* pConnectionState); + virtual bool AllowP2PPacketRelay(bool bAllow); + virtual unsigned int CreateListenSocket(int nVirtualP2PPort, unsigned int nIP, unsigned short nPort, + bool bAllowUseOfPacketRelay); + virtual unsigned int CreateP2PConnectionSocket(steam_id steamIDTarget, int nVirtualPort, int nTimeoutSec, + bool bAllowUseOfPacketRelay); + virtual unsigned int CreateConnectionSocket(unsigned int nIP, unsigned short nPort, int nTimeoutSec); + virtual bool DestroySocket(unsigned int hSocket, bool bNotifyRemoteEnd); + virtual bool DestroyListenSocket(unsigned int hSocket, bool bNotifyRemoteEnd); + virtual bool SendDataOnSocket(unsigned int hSocket, void* pubData, unsigned int cubData, bool bReliable); + virtual bool IsDataAvailableOnSocket(unsigned int hSocket, unsigned int* pcubMsgSize); + virtual bool RetrieveDataFromSocket(unsigned int hSocket, void* pubDest, unsigned int cubDest, + unsigned int* pcubMsgSize); + virtual bool IsDataAvailable(unsigned int hListenSocket, unsigned int* pcubMsgSize, unsigned int* phSocket); + virtual bool RetrieveData(unsigned int hListenSocket, void* pubDest, unsigned int cubDest, + unsigned int* pcubMsgSize, unsigned int* phSocket); + virtual bool GetSocketInfo(unsigned int hSocket, steam_id* pSteamIDRemote, int* peSocketStatus, + unsigned int* punIPRemote, unsigned short* punPortRemote); + virtual bool GetListenSocketInfo(unsigned int hListenSocket, unsigned int* pnIP, unsigned short* pnPort); + virtual int GetSocketConnectionType(unsigned int hSocket); + virtual int GetMaxPacketSize(unsigned int hSocket); + }; +} diff --git a/src/client/steam/interfaces/remote_storage.cpp b/src/client/steam/interfaces/remote_storage.cpp new file mode 100644 index 00000000..02bc968f --- /dev/null +++ b/src/client/steam/interfaces/remote_storage.cpp @@ -0,0 +1,283 @@ +#include +#include "../steam.hpp" + +namespace steam +{ + bool remote_storage::FileWrite(const char* pchFile, const void* pvData, int cubData) + { + return true; + } + + int remote_storage::FileRead(const char* pchFile, void* pvData, int cubDataToRead) + { + return 0; + } + + bool remote_storage::FileForget(const char* pchFile) + { + return true; + } + + bool remote_storage::FileDelete(const char* pchFile) + { + return true; + } + + unsigned long long remote_storage::FileShare(const char* pchFile) + { + return 0; + } + + bool remote_storage::SetSyncPlatforms(const char* pchFile, unsigned int eRemoteStoragePlatform) + { + return true; + } + + unsigned long long remote_storage::FileWriteStreamOpen(const char* pchFile) + { + return 0; + } + + int remote_storage::FileWriteStreamWriteChunk(unsigned long long hStream, const void* pvData, int cubData) + { + return 1; + } + + int remote_storage::FileWriteStreamClose(unsigned long long hStream) + { + return 1; + } + + int remote_storage::FileWriteStreamCancel(unsigned long long hStream) + { + return 1; + } + + bool remote_storage::FileExists(const char* pchFile) + { + return true; + } + + bool remote_storage::FilePersisted(const char* pchFile) + { + return true; + } + + int remote_storage::GetFileSize(const char* pchFile) + { + return 0; + } + + long long remote_storage::GetFileTimestamp(const char* pchFile) + { + return 0; + } + + unsigned remote_storage::GetSyncPlatforms(const char* pchFile) + { + return 0; + } + + int remote_storage::GetFileCount() + { + return 0; + } + + const char* remote_storage::GetFileNameAndSize(int iFile, int* pnFileSizeInBytes) + { + *pnFileSizeInBytes = 0; + return ""; + } + + bool remote_storage::GetQuota(int* pnTotalBytes, int* puAvailableBytes) + { + *pnTotalBytes = 0x10000000; + *puAvailableBytes = 0x10000000; + return false; + } + + bool remote_storage::IsCloudEnabledForAccount() + { + return false; + } + + bool remote_storage::IsCloudEnabledForApp() + { + return false; + } + + void remote_storage::SetCloudEnabledForApp(bool bEnabled) + { + } + + unsigned long long remote_storage::UGCDownload(unsigned long long hContent, unsigned int uUnk) + { + return 0; + } + + bool remote_storage::GetUGCDownloadProgress(unsigned long long hContent, unsigned int* puDownloadedBytes, + unsigned int* puTotalBytes) + { + return false; + } + + bool remote_storage::GetUGCDetails(unsigned long long hContent, unsigned int* pnAppID, char** ppchName, + int* pnFileSizeInBytes, steam_id* pSteamIDOwner) + { + return false; + } + + int remote_storage::UGCRead(unsigned long long hContent, void* pvData, int cubDataToRead, unsigned int uOffset) + { + return 0; + } + + int remote_storage::GetCachedUGCCount() + { + return 0; + } + + unsigned long long remote_storage::GetCachedUGCHandle(int iCachedContent) + { + return 0; + } + + unsigned long long remote_storage::PublishWorkshopFile(const char* pchFile, const char* pchPreviewFile, + unsigned int nConsumerAppId, const char* pchTitle, + const char* pchDescription, unsigned int eVisibility, + int* pTags, unsigned int eWorkshopFileType) + { + return 0; + } + + unsigned long long remote_storage::CreatePublishedFileUpdateRequest(unsigned long long unPublishedFileId) + { + return 0; + } + + bool remote_storage::UpdatePublishedFileFile(unsigned long long hUpdateRequest, const char* pchFile) + { + return false; + } + + bool remote_storage::UpdatePublishedFilePreviewFile(unsigned long long hUpdateRequest, const char* pchPreviewFile) + { + return false; + } + + bool remote_storage::UpdatePublishedFileTitle(unsigned long long hUpdateRequest, const char* pchTitle) + { + return false; + } + + bool remote_storage::UpdatePublishedFileDescription(unsigned long long hUpdateRequest, const char* pchDescription) + { + return false; + } + + bool remote_storage::UpdatePublishedFileVisibility(unsigned long long hUpdateRequest, unsigned int eVisibility) + { + return false; + } + + bool remote_storage::UpdatePublishedFileTags(unsigned long long hUpdateRequest, int* pTags) + { + return false; + } + + unsigned long long remote_storage::CommitPublishedFileUpdate(unsigned long long hUpdateRequest) + { + return 0; + } + + unsigned long long remote_storage::GetPublishedFileDetails(unsigned long long unPublishedFileId) + { + return 0; + } + + unsigned long long remote_storage::DeletePublishedFile(unsigned long long unPublishedFileId) + { + return 0; + } + + unsigned long long remote_storage::EnumerateUserPublishedFiles(unsigned int uStartIndex) + { + return 0; + } + + unsigned long long remote_storage::SubscribePublishedFile(unsigned long long unPublishedFileId) + { + return 0; + } + + unsigned long long remote_storage::EnumerateUserSubscribedFiles(unsigned int uStartIndex) + { + return 0; + } + + unsigned long long remote_storage::UnsubscribePublishedFile(unsigned long long unPublishedFileId) + { + return 0; + } + + bool remote_storage::UpdatePublishedFileSetChangeDescription(unsigned long long hUpdateRequest, + const char* cszDescription) + { + return false; + } + + unsigned long long remote_storage::GetPublishedItemVoteDetails(unsigned long long unPublishedFileId) + { + return 0; + } + + unsigned long long remote_storage::UpdateUserPublishedItemVote(unsigned long long unPublishedFileId, bool bVoteUp) + { + return 0; + } + + unsigned long long remote_storage::GetUserPublishedItemVoteDetails(unsigned long long unPublishedFileId) + { + return 0; + } + + unsigned long long remote_storage::EnumerateUserSharedWorkshopFiles(unsigned int nAppId, steam_id creatorSteamID, + unsigned int uStartIndex, int* pRequiredTags, + int* pExcludedTags) + { + return 0; + } + + unsigned long long remote_storage::PublishVideo(unsigned int eVideoProvider, const char* cszVideoAccountName, + const char* cszVideoIdentifier, const char* cszFileName, + unsigned int nConsumerAppId, const char* cszTitle, + const char* cszDescription, unsigned int eVisibility, int* pTags) + { + return 0; + } + + unsigned long long remote_storage::SetUserPublishedFileAction(unsigned long long unPublishedFileId, + unsigned int eAction) + { + return 0; + } + + unsigned long long remote_storage::EnumeratePublishedFilesByUserAction( + unsigned int eAction, unsigned int uStartIndex) + { + return 0; + } + + unsigned long long remote_storage::EnumeratePublishedWorkshopFiles(unsigned int eType, unsigned int uStartIndex, + unsigned int cDays, unsigned int cCount, + int* pTags, int* pUserTags) + { + return 0; + } + + unsigned long long remote_storage::UGCDownloadToLocation(unsigned long long hContent, const char* cszLocation, + unsigned int uUnk) + { + return 0; + } +} diff --git a/src/client/steam/interfaces/remote_storage.hpp b/src/client/steam/interfaces/remote_storage.hpp new file mode 100644 index 00000000..ec0d64ea --- /dev/null +++ b/src/client/steam/interfaces/remote_storage.hpp @@ -0,0 +1,78 @@ +#pragma once + +namespace steam +{ + class remote_storage + { + public: + ~remote_storage() = default; + + virtual bool FileWrite(const char* pchFile, const void* pvData, int cubData); + virtual int FileRead(const char* pchFile, void* pvData, int cubDataToRead); + virtual bool FileForget(const char* pchFile); + virtual bool FileDelete(const char* pchFile); + virtual unsigned long long FileShare(const char* pchFile); + virtual bool SetSyncPlatforms(const char* pchFile, unsigned int eRemoteStoragePlatform); + virtual unsigned long long FileWriteStreamOpen(const char* pchFile); + virtual int FileWriteStreamWriteChunk(unsigned long long hStream, const void* pvData, int cubData); + virtual int FileWriteStreamClose(unsigned long long hStream); + virtual int FileWriteStreamCancel(unsigned long long hStream); + virtual bool FileExists(const char* pchFile); + virtual bool FilePersisted(const char* pchFile); + virtual int GetFileSize(const char* pchFile); + virtual long long GetFileTimestamp(const char* pchFile); + virtual unsigned int GetSyncPlatforms(const char* pchFile); + virtual int GetFileCount(); + virtual const char* GetFileNameAndSize(int iFile, int* pnFileSizeInBytes); + virtual bool GetQuota(int* pnTotalBytes, int* puAvailableBytes); + virtual bool IsCloudEnabledForAccount(); + virtual bool IsCloudEnabledForApp(); + virtual void SetCloudEnabledForApp(bool bEnabled); + virtual unsigned long long UGCDownload(unsigned long long hContent, unsigned int uUnk); + virtual bool GetUGCDownloadProgress(unsigned long long hContent, unsigned int* puDownloadedBytes, + unsigned int* puTotalBytes); + virtual bool GetUGCDetails(unsigned long long hContent, unsigned int* pnAppID, char** ppchName, + int* pnFileSizeInBytes, steam_id* pSteamIDOwner); + virtual int UGCRead(unsigned long long hContent, void* pvData, int cubDataToRead, unsigned int uOffset); + virtual int GetCachedUGCCount(); + virtual unsigned long long GetCachedUGCHandle(int iCachedContent); + virtual unsigned long long PublishWorkshopFile(const char* pchFile, const char* pchPreviewFile, + unsigned int nConsumerAppId, const char* pchTitle, + const char* pchDescription, unsigned int eVisibility, int* pTags, + unsigned int eWorkshopFileType); + virtual unsigned long long CreatePublishedFileUpdateRequest(unsigned long long unPublishedFileId); + virtual bool UpdatePublishedFileFile(unsigned long long hUpdateRequest, const char* pchFile); + virtual bool UpdatePublishedFilePreviewFile(unsigned long long hUpdateRequest, const char* pchPreviewFile); + virtual bool UpdatePublishedFileTitle(unsigned long long hUpdateRequest, const char* pchTitle); + virtual bool UpdatePublishedFileDescription(unsigned long long hUpdateRequest, const char* pchDescription); + virtual bool UpdatePublishedFileVisibility(unsigned long long hUpdateRequest, unsigned int eVisibility); + virtual bool UpdatePublishedFileTags(unsigned long long hUpdateRequest, int* pTags); + virtual unsigned long long CommitPublishedFileUpdate(unsigned long long hUpdateRequest); + virtual unsigned long long GetPublishedFileDetails(unsigned long long unPublishedFileId); + virtual unsigned long long DeletePublishedFile(unsigned long long unPublishedFileId); + virtual unsigned long long EnumerateUserPublishedFiles(unsigned int uStartIndex); + virtual unsigned long long SubscribePublishedFile(unsigned long long unPublishedFileId); + virtual unsigned long long EnumerateUserSubscribedFiles(unsigned int uStartIndex); + virtual unsigned long long UnsubscribePublishedFile(unsigned long long unPublishedFileId); + virtual bool UpdatePublishedFileSetChangeDescription(unsigned long long hUpdateRequest, + const char* cszDescription); + virtual unsigned long long GetPublishedItemVoteDetails(unsigned long long unPublishedFileId); + virtual unsigned long long UpdateUserPublishedItemVote(unsigned long long unPublishedFileId, bool bVoteUp); + virtual unsigned long long GetUserPublishedItemVoteDetails(unsigned long long unPublishedFileId); + virtual unsigned long long EnumerateUserSharedWorkshopFiles(unsigned int nAppId, steam_id creatorSteamID, + unsigned int uStartIndex, int* pRequiredTags, + int* pExcludedTags); + virtual unsigned long long PublishVideo(unsigned int eVideoProvider, const char* cszVideoAccountName, + const char* cszVideoIdentifier, const char* cszFileName, + unsigned int nConsumerAppId, const char* cszTitle, + const char* cszDescription, unsigned int eVisibility, int* pTags); + virtual unsigned long long SetUserPublishedFileAction(unsigned long long unPublishedFileId, + unsigned int eAction); + virtual unsigned long long EnumeratePublishedFilesByUserAction(unsigned int eAction, unsigned int uStartIndex); + virtual unsigned long long EnumeratePublishedWorkshopFiles(unsigned int eType, unsigned int uStartIndex, + unsigned int cDays, unsigned int cCount, int* pTags, + int* pUserTags); + virtual unsigned long long UGCDownloadToLocation(unsigned long long hContent, const char* cszLocation, + unsigned int uUnk); + }; +} diff --git a/src/client/steam/interfaces/user.cpp b/src/client/steam/interfaces/user.cpp new file mode 100644 index 00000000..752007ba --- /dev/null +++ b/src/client/steam/interfaces/user.cpp @@ -0,0 +1,164 @@ +#include +#include "../steam.hpp" + +#include "component/auth.hpp" + +namespace steam +{ + namespace + { + std::string auth_ticket; + + steam_id generate_steam_id() + { + steam_id id{}; + id.bits = auth::get_guid(); + return id; + } + } + + int user::GetHSteamUser() + { + return NULL; + } + + bool user::LoggedOn() + { + return true; + } + + steam_id user::GetSteamID() + { + static auto id = generate_steam_id(); + return id; + } + + int user::InitiateGameConnection(void* pAuthBlob, int cbMaxAuthBlob, steam_id steamIDGameServer, + unsigned int unIPServer, unsigned short usPortServer, bool bSecure) + { + return 0; + } + + void user::TerminateGameConnection(unsigned int unIPServer, unsigned short usPortServer) + { + } + + void user::TrackAppUsageEvent(steam_id gameID, int eAppUsageEvent, const char* pchExtraInfo) + { + } + + bool user::GetUserDataFolder(char* pchBuffer, int cubBuffer) + { + return false; + } + + void user::StartVoiceRecording() + { + } + + void user::StopVoiceRecording() + { + } + + int user::GetAvailableVoice(unsigned int* pcbCompressed, unsigned int* pcbUncompressed, + unsigned int nUncompressedVoiceDesiredSampleRate) + { + return 0; + } + + int user::GetVoice(bool bWantCompressed, void* pDestBuffer, unsigned int cbDestBufferSize, + unsigned int* nBytesWritten, bool bWantUncompressed, void* pUncompressedDestBuffer, + unsigned int cbUncompressedDestBufferSize, unsigned int* nUncompressBytesWritten, + unsigned int nUncompressedVoiceDesiredSampleRate) + { + return 0; + } + + int user::DecompressVoice(void* pCompressed, unsigned int cbCompressed, void* pDestBuffer, + unsigned int cbDestBufferSize, unsigned int* nBytesWritten) + { + return 0; + } + + unsigned int user::GetVoiceOptimalSampleRate() + { + return 0; + } + + unsigned int user::GetAuthSessionTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket) + { + static uint32_t ticket = 0; + *pcbTicket = 1; + + const auto result = callbacks::register_call(); + auto* response = static_cast(calloc( + 1, sizeof(get_auth_session_ticket_response))); + response->m_h_auth_ticket = ++ticket; + response->m_e_result = 1; // k_EResultOK; + + callbacks::return_call(response, sizeof(get_auth_session_ticket_response), + get_auth_session_ticket_response::callback_id, result); + return response->m_h_auth_ticket; + } + + int user::BeginAuthSession(const void* pAuthTicket, int cbAuthTicket, steam_id steamID) + { + return 0; + } + + void user::EndAuthSession(steam_id steamID) + { + } + + void user::CancelAuthTicket(unsigned int hAuthTicket) + { + } + + unsigned int user::UserHasLicenseForApp(steam_id steamID, unsigned int appID) + { + return 0; + } + + bool user::BIsBehindNAT() + { + return false; + } + + void user::AdvertiseGame(steam_id steamIDGameServer, unsigned int unIPServer, unsigned short usPortServer) + { + } + + unsigned long long user::RequestEncryptedAppTicket(void* pUserData, int cbUserData) + { + const auto id = this->GetSteamID(); + + auth_ticket = "S1"; + auth_ticket.resize(32); + auth_ticket.append(static_cast(pUserData), 24); // key + auth_ticket.append(reinterpret_cast(&id.bits), sizeof(id.bits)); // user id + auth_ticket.append(&static_cast(pUserData)[24], 64); // user name + + // Create the call response + const auto result = callbacks::register_call(); + const auto retvals = static_cast(calloc(1, sizeof(encrypted_app_ticket_response))); + //::Utils::Memory::AllocateArray(); + retvals->m_e_result = 1; + + // Return the call response + callbacks::return_call(retvals, sizeof(encrypted_app_ticket_response), + encrypted_app_ticket_response::callback_id, result); + + return result; + } + + bool user::GetEncryptedAppTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket) + { + if (cbMaxTicket < 0 || auth_ticket.empty()) return false; + + const auto size = std::min(size_t(cbMaxTicket), auth_ticket.size()); + std::memcpy(pTicket, auth_ticket.data(), size); + *pcbTicket = static_cast(size); + + return true; + } +} diff --git a/src/client/steam/interfaces/user.hpp b/src/client/steam/interfaces/user.hpp new file mode 100644 index 00000000..07cd8018 --- /dev/null +++ b/src/client/steam/interfaces/user.hpp @@ -0,0 +1,55 @@ +#pragma once + +namespace steam +{ + struct encrypted_app_ticket_response final + { + enum { callback_id = 154 }; + + int m_e_result; + }; + + struct get_auth_session_ticket_response + { + enum { callback_id = 163 }; + + unsigned int m_h_auth_ticket; + int m_e_result; + }; + + class user + { + public: + ~user() = default; + + virtual int GetHSteamUser(); + virtual bool LoggedOn(); + virtual steam_id GetSteamID(); + + virtual int InitiateGameConnection(void* pAuthBlob, int cbMaxAuthBlob, steam_id steamIDGameServer, + unsigned int unIPServer, unsigned short usPortServer, bool bSecure); + virtual void TerminateGameConnection(unsigned int unIPServer, unsigned short usPortServer); + virtual void TrackAppUsageEvent(steam_id gameID, int eAppUsageEvent, const char* pchExtraInfo = ""); + virtual bool GetUserDataFolder(char* pchBuffer, int cubBuffer); + virtual void StartVoiceRecording(); + virtual void StopVoiceRecording(); + virtual int GetAvailableVoice(unsigned int* pcbCompressed, unsigned int* pcbUncompressed, + unsigned int nUncompressedVoiceDesiredSampleRate); + virtual int GetVoice(bool bWantCompressed, void* pDestBuffer, unsigned int cbDestBufferSize, + unsigned int* nBytesWritten, bool bWantUncompressed, void* pUncompressedDestBuffer, + unsigned int cbUncompressedDestBufferSize, unsigned int* nUncompressBytesWritten, + unsigned int nUncompressedVoiceDesiredSampleRate); + virtual int DecompressVoice(void* pCompressed, unsigned int cbCompressed, void* pDestBuffer, + unsigned int cbDestBufferSize, unsigned int* nBytesWritten); + virtual unsigned int GetVoiceOptimalSampleRate(); + virtual unsigned int GetAuthSessionTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket); + virtual int BeginAuthSession(const void* pAuthTicket, int cbAuthTicket, steam_id steamID); + virtual void EndAuthSession(steam_id steamID); + virtual void CancelAuthTicket(unsigned int hAuthTicket); + virtual unsigned int UserHasLicenseForApp(steam_id steamID, unsigned int appID); + virtual bool BIsBehindNAT(); + virtual void AdvertiseGame(steam_id steamIDGameServer, unsigned int unIPServer, unsigned short usPortServer); + virtual unsigned long long RequestEncryptedAppTicket(void* pUserData, int cbUserData); + virtual bool GetEncryptedAppTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket); + }; +} diff --git a/src/client/steam/interfaces/user_stats.cpp b/src/client/steam/interfaces/user_stats.cpp new file mode 100644 index 00000000..13d4ccc0 --- /dev/null +++ b/src/client/steam/interfaces/user_stats.cpp @@ -0,0 +1,231 @@ +#include +#include "../steam.hpp" + +namespace steam +{ + bool user_stats::RequestCurrentStats() + { + return true; + } + + bool user_stats::GetStat(const char* pchName, int* pData) + { + return false; + } + + bool user_stats::GetStat(const char* pchName, float* pData) + { + return false; + } + + bool user_stats::SetStat(const char* pchName, int nData) + { + return false; + } + + bool user_stats::SetStat(const char* pchName, float fData) + { + return false; + } + + bool user_stats::UpdateAvgRateStat(const char* pchName, float flCountThisSession, double dSessionLength) + { + return false; + } + + bool user_stats::GetAchievement(const char* pchName, bool* pbAchieved) + { + return true; + } + + bool user_stats::SetAchievement(const char* pchName) + { + return true; + } + + bool user_stats::ClearAchievement(const char* pchName) + { + return true; + } + + bool user_stats::GetAchievementAndUnlockTime(const char* pchName, bool* pbAchieved, unsigned int* punUnlockTime) + { + return true; + } + + bool user_stats::StoreStats() + { + return true; + } + + int user_stats::GetAchievementIcon(const char* pchName) + { + return 0; + } + + const char* user_stats::GetAchievementDisplayAttribute(const char* pchName, const char* pchKey) + { + return ""; + } + + bool user_stats::IndicateAchievementProgress(const char* pchName, unsigned int nCurProgress, + unsigned int nMaxProgress) + { + return true; + } + + unsigned int user_stats::GetNumAchievements() + { + return 0; + } + + const char* user_stats::GetAchievementName(unsigned int iAchievement) + { + return ""; + } + + unsigned long long user_stats::RequestUserStats(steam_id steamIDUser) + { + return 0; + } + + bool user_stats::GetUserStat(steam_id steamIDUser, const char* pchName, int* pData) + { + return false; + } + + bool user_stats::GetUserStat(steam_id steamIDUser, const char* pchName, float* pData) + { + return false; + } + + bool user_stats::GetUserAchievement(steam_id steamIDUser, const char* pchName, bool* pbAchieved) + { + return true; + } + + bool user_stats::GetUserAchievementAndUnlockTime(steam_id steamIDUser, const char* pchName, bool* pbAchieved, + unsigned int* punUnlockTime) + { + return true; + } + + bool user_stats::ResetAllStats(bool bAchievementsToo) + { + return false; + } + + unsigned long long user_stats::FindOrCreateLeaderboard(const char* pchLeaderboardName, int eLeaderboardSortMethod, + int eLeaderboardDisplayType) + { + return 0; + } + + unsigned long long user_stats::FindLeaderboard(const char* pchLeaderboardName) + { + return 0; + } + + const char* user_stats::GetLeaderboardName(unsigned long long hSteamLeaderboard) + { + return ""; + } + + int user_stats::GetLeaderboardEntryCount(unsigned long long hSteamLeaderboard) + { + return 0; + } + + int user_stats::GetLeaderboardSortMethod(unsigned long long hSteamLeaderboard) + { + return 0; + } + + int user_stats::GetLeaderboardDisplayType(unsigned long long hSteamLeaderboard) + { + return 0; + } + + unsigned long long user_stats::DownloadLeaderboardEntries(unsigned long long hSteamLeaderboard, + int eLeaderboardDataRequest, int nRangeStart, + int nRangeEnd) + { + return 0; + } + + unsigned long long user_stats::DownloadLeaderboardEntriesForUsers(unsigned long long hSteamLeaderboard, + steam_id* prgUsers, int cUsers) + { + return 0; + } + + bool user_stats::GetDownloadedLeaderboardEntry(unsigned long long hSteamLeaderboardEntries, int index, + int* pLeaderboardEntry, int* pDetails, int cDetailsMax) + { + return false; + } + + unsigned long long user_stats::UploadLeaderboardScore(unsigned long long hSteamLeaderboard, + int eLeaderboardUploadScoreMethod, int nScore, + const int* pScoreDetails, int cScoreDetailsCount) + { + return 0; + } + + unsigned long long user_stats::AttachLeaderboardUGC(unsigned long long hSteamLeaderboard, unsigned long long hUGC) + { + return 0; + } + + unsigned long long user_stats::GetNumberOfCurrentPlayers() + { + return 0; + } + + unsigned long long user_stats::RequestGlobalAchievementPercentages() + { + return 0; + } + + int user_stats::GetMostAchievedAchievementInfo(char* pchName, unsigned int unNameBufLen, float* pflPercent, + bool* pbAchieved) + { + return 0; + } + + int user_stats::GetNextMostAchievedAchievementInfo(int iIteratorPrevious, char* pchName, unsigned int unNameBufLen, + float* pflPercent, bool* pbAchieved) + { + return 0; + } + + bool user_stats::GetAchievementAchievedPercent(const char* pchName, float* pflPercent) + { + return true; + } + + unsigned long long user_stats::RequestGlobalStats(int nHistoryDays) + { + return 0; + } + + bool user_stats::GetGlobalStat(const char* pchStatName, long long* pData) + { + return false; + } + + bool user_stats::GetGlobalStat(const char* pchStatName, double* pData) + { + return false; + } + + int user_stats::GetGlobalStatHistory(const char* pchStatName, long long* pData, unsigned int cubData) + { + return 0; + } + + int user_stats::GetGlobalStatHistory(const char* pchStatName, double* pData, unsigned int cubData) + { + return 0; + } +} diff --git a/src/client/steam/interfaces/user_stats.hpp b/src/client/steam/interfaces/user_stats.hpp new file mode 100644 index 00000000..c49c79d4 --- /dev/null +++ b/src/client/steam/interfaces/user_stats.hpp @@ -0,0 +1,65 @@ +#pragma once + +namespace steam +{ + class user_stats + { + public: + ~user_stats() = default; + + virtual bool RequestCurrentStats(); + virtual bool GetStat(const char* pchName, int* pData); + virtual bool GetStat(const char* pchName, float* pData); + virtual bool SetStat(const char* pchName, int nData); + virtual bool SetStat(const char* pchName, float fData); + virtual bool UpdateAvgRateStat(const char* pchName, float flCountThisSession, double dSessionLength); + virtual bool GetAchievement(const char* pchName, bool* pbAchieved); + virtual bool SetAchievement(const char* pchName); + virtual bool ClearAchievement(const char* pchName); + virtual bool GetAchievementAndUnlockTime(const char* pchName, bool* pbAchieved, unsigned int* punUnlockTime); + virtual bool StoreStats(); + virtual int GetAchievementIcon(const char* pchName); + virtual const char* GetAchievementDisplayAttribute(const char* pchName, const char* pchKey); + virtual bool IndicateAchievementProgress(const char* pchName, unsigned int nCurProgress, + unsigned int nMaxProgress); + virtual unsigned int GetNumAchievements(); + virtual const char* GetAchievementName(unsigned int iAchievement); + virtual unsigned long long RequestUserStats(steam_id steamIDUser); + virtual bool GetUserStat(steam_id steamIDUser, const char* pchName, int* pData); + virtual bool GetUserStat(steam_id steamIDUser, const char* pchName, float* pData); + virtual bool GetUserAchievement(steam_id steamIDUser, const char* pchName, bool* pbAchieved); + virtual bool GetUserAchievementAndUnlockTime(steam_id steamIDUser, const char* pchName, bool* pbAchieved, + unsigned int* punUnlockTime); + virtual bool ResetAllStats(bool bAchievementsToo); + virtual unsigned long long FindOrCreateLeaderboard(const char* pchLeaderboardName, int eLeaderboardSortMethod, + int eLeaderboardDisplayType); + virtual unsigned long long FindLeaderboard(const char* pchLeaderboardName); + virtual const char* GetLeaderboardName(unsigned long long hSteamLeaderboard); + virtual int GetLeaderboardEntryCount(unsigned long long hSteamLeaderboard); + virtual int GetLeaderboardSortMethod(unsigned long long hSteamLeaderboard); + virtual int GetLeaderboardDisplayType(unsigned long long hSteamLeaderboard); + virtual unsigned long long DownloadLeaderboardEntries(unsigned long long hSteamLeaderboard, + int eLeaderboardDataRequest, int nRangeStart, + int nRangeEnd); + virtual unsigned long long DownloadLeaderboardEntriesForUsers(unsigned long long hSteamLeaderboard, + steam_id* prgUsers, int cUsers); + virtual bool GetDownloadedLeaderboardEntry(unsigned long long hSteamLeaderboardEntries, int index, + int* pLeaderboardEntry, int* pDetails, int cDetailsMax); + virtual unsigned long long UploadLeaderboardScore(unsigned long long hSteamLeaderboard, + int eLeaderboardUploadScoreMethod, int nScore, + const int* pScoreDetails, int cScoreDetailsCount); + virtual unsigned long long AttachLeaderboardUGC(unsigned long long hSteamLeaderboard, unsigned long long hUGC); + virtual unsigned long long GetNumberOfCurrentPlayers(); + virtual unsigned long long RequestGlobalAchievementPercentages(); + virtual int GetMostAchievedAchievementInfo(char* pchName, unsigned int unNameBufLen, float* pflPercent, + bool* pbAchieved); + virtual int GetNextMostAchievedAchievementInfo(int iIteratorPrevious, char* pchName, unsigned int unNameBufLen, + float* pflPercent, bool* pbAchieved); + virtual bool GetAchievementAchievedPercent(const char* pchName, float* pflPercent); + virtual unsigned long long RequestGlobalStats(int nHistoryDays); + virtual bool GetGlobalStat(const char* pchStatName, long long* pData); + virtual bool GetGlobalStat(const char* pchStatName, double* pData); + virtual int GetGlobalStatHistory(const char* pchStatName, long long* pData, unsigned int cubData); + virtual int GetGlobalStatHistory(const char* pchStatName, double* pData, unsigned int cubData); + }; +} diff --git a/src/client/steam/interfaces/utils.cpp b/src/client/steam/interfaces/utils.cpp new file mode 100644 index 00000000..95f923aa --- /dev/null +++ b/src/client/steam/interfaces/utils.cpp @@ -0,0 +1,123 @@ +#include +#include "../steam.hpp" + +namespace steam +{ + unsigned int utils::GetSecondsSinceAppActive() + { + return 0; + } + + unsigned int utils::GetSecondsSinceComputerActive() + { + return (uint32_t)GetTickCount64() / 1000; + } + + int utils::GetConnectedUniverse() + { + return 1; + } + + unsigned int utils::GetServerRealTime() + { + return (uint32_t)time(NULL); + } + + const char* utils::GetIPCountry() + { + return "US"; + } + + bool utils::GetImageSize(int iImage, unsigned int* pnWidth, unsigned int* pnHeight) + { + return false; + } + + bool utils::GetImageRGBA(int iImage, unsigned char* pubDest, int nDestBufferSize) + { + return false; + } + + bool utils::GetCSERIPPort(unsigned int* unIP, unsigned short* usPort) + { + return false; + } + + unsigned char utils::GetCurrentBatteryPower() + { + return 255; + } + + unsigned int utils::GetAppID() + { + return 209660; + } + + void utils::SetOverlayNotificationPosition(int eNotificationPosition) + { + //const auto& overlay = steam_proxy::get_overlay_module(); + //if (overlay) + //{ + // overlay.invoke("SetNotificationPosition", eNotificationPosition); + //} + } + + bool utils::IsAPICallCompleted(unsigned long long hSteamAPICall, bool* pbFailed) + { + return false; + } + + int utils::GetAPICallFailureReason(unsigned long long hSteamAPICall) + { + return -1; + } + + bool utils::GetAPICallResult(unsigned long long hSteamAPICall, void* pCallback, int cubCallback, + int iCallbackExpected, bool* pbFailed) + { + return false; + } + + void utils::RunFrame() + { + } + + unsigned int utils::GetIPCCallCount() + { + return 0; + } + + void utils::SetWarningMessageHook(void (*pFunction)(int hpipe, const char* message)) + { + } + + bool utils::IsOverlayEnabled() + { + return false; + } + + bool utils::BOverlayNeedsPresent() + { + return false; + } + + unsigned long long utils::CheckFileSignature(const char* szFileName) + { + return 0; + } + + bool utils::ShowGamepadTextInput(int eInputMode, int eInputLineMode, const char* szText, unsigned int uMaxLength) + { + return false; + } + + unsigned int utils::GetEnteredGamepadTextLength() + { + return 0; + } + + bool utils::GetEnteredGamepadTextInput(char* pchValue, unsigned int cchValueMax) + { + return false; + } +} diff --git a/src/client/steam/interfaces/utils.hpp b/src/client/steam/interfaces/utils.hpp new file mode 100644 index 00000000..d42a27f9 --- /dev/null +++ b/src/client/steam/interfaces/utils.hpp @@ -0,0 +1,37 @@ +#pragma once + +namespace steam +{ + class utils + { + public: + ~utils() = default; + + virtual unsigned int GetSecondsSinceAppActive(); + virtual unsigned int GetSecondsSinceComputerActive(); + virtual int GetConnectedUniverse(); + virtual unsigned int GetServerRealTime(); + virtual const char* GetIPCountry(); + virtual bool GetImageSize(int iImage, unsigned int* pnWidth, unsigned int* pnHeight); + virtual bool GetImageRGBA(int iImage, unsigned char* pubDest, int nDestBufferSize); + virtual bool GetCSERIPPort(unsigned int* unIP, unsigned short* usPort); + virtual unsigned char GetCurrentBatteryPower(); + virtual unsigned int GetAppID(); + virtual void SetOverlayNotificationPosition(int eNotificationPosition); + virtual bool IsAPICallCompleted(unsigned long long hSteamAPICall, bool* pbFailed); + virtual int GetAPICallFailureReason(unsigned long long hSteamAPICall); + virtual bool GetAPICallResult(unsigned long long hSteamAPICall, void* pCallback, int cubCallback, + int iCallbackExpected, bool* pbFailed); + virtual void RunFrame(); + virtual unsigned int GetIPCCallCount(); + virtual void SetWarningMessageHook(void (*pFunction)(int hpipe, const char* message)); + virtual bool IsOverlayEnabled(); + virtual bool BOverlayNeedsPresent(); + virtual unsigned long long CheckFileSignature(const char* szFileName); + + virtual bool ShowGamepadTextInput(int eInputMode, int eInputLineMode, const char* szText, + unsigned int uMaxLength); + virtual unsigned int GetEnteredGamepadTextLength(); + virtual bool GetEnteredGamepadTextInput(char* pchValue, unsigned int cchValueMax); + }; +} diff --git a/src/client/steam/steam.cpp b/src/client/steam/steam.cpp new file mode 100644 index 00000000..18ecd7d6 --- /dev/null +++ b/src/client/steam/steam.cpp @@ -0,0 +1,247 @@ +#include +#include "steam.hpp" + +#include + +namespace steam +{ + uint64_t callbacks::call_id_ = 0; + std::recursive_mutex callbacks::mutex_; + std::map callbacks::calls_; + std::map callbacks::result_handlers_; + std::vector callbacks::results_; + std::vector callbacks::callback_list_; + + uint64_t callbacks::register_call() + { + std::lock_guard _(mutex_); + calls_[++call_id_] = false; + return call_id_; + } + + void callbacks::register_callback(base* handler, const int callback) + { + std::lock_guard _(mutex_); + handler->set_i_callback(callback); + callback_list_.push_back(handler); + } + + void callbacks::unregister_callback(base* handler) + { + std::lock_guard _(mutex_); + for (auto i = callback_list_.begin(); i != callback_list_.end();) + { + if (*i == handler) + { + i = callback_list_.erase(i); + } + else + { + ++i; + } + } + } + + void callbacks::register_call_result(const uint64_t call, base* result) + { + std::lock_guard _(mutex_); + result_handlers_[call] = result; + } + + void callbacks::unregister_call_result(const uint64_t call, base* /*result*/) + { + std::lock_guard _(mutex_); + const auto i = result_handlers_.find(call); + if (i != result_handlers_.end()) + { + result_handlers_.erase(i); + } + } + + void callbacks::return_call(void* data, const int size, const int type, const uint64_t call) + { + std::lock_guard _(mutex_); + + result result{}; + result.call = call; + result.data = data; + result.size = size; + result.type = type; + + calls_[call] = true; + + results_.emplace_back(result); + } + + void callbacks::run_callbacks() + { + std::lock_guard _(mutex_); + + for (const auto& result : results_) + { + if (result_handlers_.find(result.call) != result_handlers_.end()) + { + result_handlers_[result.call]->run(result.data, false, result.call); + } + + for (const auto& callback : callback_list_) + { + if (callback && callback->get_i_callback() == result.type) + { + callback->run(result.data, false, 0); + } + } + + if (result.data) + { + free(result.data); + } + } + + results_.clear(); + } + + extern "C" { + + bool SteamAPI_RestartAppIfNecessary() + { + return false; + } + + bool SteamAPI_Init() + { + const std::filesystem::path steam_path = steam::SteamAPI_GetSteamInstallPath(); + if (steam_path.empty()) return true; + + ::utils::nt::library::load(steam_path / "tier0_s64.dll"); + ::utils::nt::library::load(steam_path / "vstdlib_s64.dll"); + ::utils::nt::library::load(steam_path / "gameoverlayrenderer64.dll"); + ::utils::nt::library::load(steam_path / "steamclient64.dll"); + return true; + } + + void SteamAPI_RegisterCallResult(callbacks::base* result, const uint64_t call) + { + callbacks::register_call_result(call, result); + } + + void SteamAPI_RegisterCallback(callbacks::base* handler, const int callback) + { + callbacks::register_callback(handler, callback); + } + + void SteamAPI_RunCallbacks() + { + callbacks::run_callbacks(); + } + + void SteamAPI_Shutdown() + { + } + + void SteamAPI_UnregisterCallResult(callbacks::base* result, const uint64_t call) + { + callbacks::unregister_call_result(call, result); + } + + void SteamAPI_UnregisterCallback(callbacks::base* handler) + { + callbacks::unregister_callback(handler); + } + + const char* SteamAPI_GetSteamInstallPath() + { + static std::string install_path{}; + if (!install_path.empty()) + { + return install_path.data(); + } + + HKEY reg_key; + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\WOW6432Node\\Valve\\Steam", 0, KEY_QUERY_VALUE, + ®_key) == + ERROR_SUCCESS) + { + char path[MAX_PATH] = {0}; + DWORD length = sizeof(path); + RegQueryValueExA(reg_key, "InstallPath", nullptr, nullptr, reinterpret_cast(path), + &length); + RegCloseKey(reg_key); + + install_path = path; + } + + return install_path.data(); + } + + + bool SteamGameServer_Init() + { + return true; + } + + void SteamGameServer_RunCallbacks() + { + } + + void SteamGameServer_Shutdown() + { + } + + + friends* SteamFriends() + { + static friends friends; + return &friends; + } + + matchmaking* SteamMatchmaking() + { + static matchmaking matchmaking; + return &matchmaking; + } + + game_server* SteamGameServer() + { + static game_server game_server; + return &game_server; + } + + networking* SteamNetworking() + { + static networking networking; + return &networking; + } + + remote_storage* SteamRemoteStorage() + { + static remote_storage remote_storage; + return &remote_storage; + } + + user* SteamUser() + { + static user user; + return &user; + } + + utils* SteamUtils() + { + static utils utils; + return &utils; + } + + apps* SteamApps() + { + static apps apps; + return &apps; + } + + user_stats* SteamUserStats() + { + static user_stats user_stats; + return &user_stats; + } + + } +} \ No newline at end of file diff --git a/src/client/steam/steam.hpp b/src/client/steam/steam.hpp new file mode 100644 index 00000000..3018921f --- /dev/null +++ b/src/client/steam/steam.hpp @@ -0,0 +1,121 @@ +#pragma once + +#define STEAM_EXPORT extern "C" __declspec(dllexport) + +struct raw_steam_id final +{ + unsigned int account_id : 32; + unsigned int account_instance : 20; + unsigned int account_type : 4; + int universe : 8; +}; + +typedef union +{ + raw_steam_id raw; + unsigned long long bits; +} steam_id; + +#pragma pack( push, 1 ) +struct raw_game_id final +{ + unsigned int app_id : 24; + unsigned int type : 8; + unsigned int mod_id : 32; +}; + +typedef union +{ + raw_game_id raw; + unsigned long long bits; +} game_id; +#pragma pack( pop ) + +#include "interfaces/apps.hpp" +#include "interfaces/user.hpp" +#include "interfaces/utils.hpp" +#include "interfaces/friends.hpp" +#include "interfaces/user_stats.hpp" +#include "interfaces/game_server.hpp" +#include "interfaces/networking.hpp" +#include "interfaces/matchmaking.hpp" +#include "interfaces/remote_storage.hpp" + +namespace steam +{ + class callbacks + { + public: + class base + { + public: + base() : flags_(0), callback_(0) + { + } + + virtual void run(void* pv_param) = 0; + virtual void run(void* pv_param, bool failure, uint64_t handle) = 0; + virtual int get_callback_size_bytes() = 0; + + int get_i_callback() const { return callback_; } + void set_i_callback(const int i_callback) { callback_ = i_callback; } + + protected: + ~base() = default; + + unsigned char flags_; + int callback_; + }; + + struct result final + { + void* data{}; + int size{}; + int type{}; + uint64_t call{}; + }; + + static uint64_t register_call(); + + static void register_callback(base* handler, int callback); + static void unregister_callback(base* handler); + + static void register_call_result(uint64_t call, base* result); + static void unregister_call_result(uint64_t call, base* result); + + static void return_call(void* data, int size, int type, uint64_t call); + static void run_callbacks(); + + private: + static uint64_t call_id_; + static std::recursive_mutex mutex_; + static std::map calls_; + static std::map result_handlers_; + static std::vector results_; + static std::vector callback_list_; + }; + + STEAM_EXPORT bool SteamAPI_RestartAppIfNecessary(); + STEAM_EXPORT bool SteamAPI_Init(); + STEAM_EXPORT void SteamAPI_RegisterCallResult(callbacks::base* result, uint64_t call); + STEAM_EXPORT void SteamAPI_RegisterCallback(callbacks::base* handler, int callback); + STEAM_EXPORT void SteamAPI_RunCallbacks(); + STEAM_EXPORT void SteamAPI_Shutdown(); + STEAM_EXPORT void SteamAPI_UnregisterCallResult(callbacks::base* result, const uint64_t call); + STEAM_EXPORT void SteamAPI_UnregisterCallback(callbacks::base* handler); + STEAM_EXPORT const char* SteamAPI_GetSteamInstallPath(); + + STEAM_EXPORT bool SteamGameServer_Init(); + STEAM_EXPORT void SteamGameServer_RunCallbacks(); + STEAM_EXPORT void SteamGameServer_Shutdown(); + + STEAM_EXPORT friends* SteamFriends(); + STEAM_EXPORT matchmaking* SteamMatchmaking(); + STEAM_EXPORT game_server* SteamGameServer(); + STEAM_EXPORT networking* SteamNetworking(); + STEAM_EXPORT remote_storage* SteamRemoteStorage(); + STEAM_EXPORT user* SteamUser(); + STEAM_EXPORT utils* SteamUtils(); + STEAM_EXPORT apps* SteamApps(); + STEAM_EXPORT user_stats* SteamUserStats(); +} diff --git a/src/common/exception/minidump.cpp b/src/common/exception/minidump.cpp new file mode 100644 index 00000000..9e956acc --- /dev/null +++ b/src/common/exception/minidump.cpp @@ -0,0 +1,93 @@ +#include "minidump.hpp" + +#include +#pragma comment(lib, "dbghelp.lib") + +#include + +namespace exception +{ + namespace + { + constexpr MINIDUMP_TYPE get_minidump_type() + { + const auto type = MiniDumpIgnoreInaccessibleMemory // + | MiniDumpWithHandleData // + | MiniDumpScanMemory // + | MiniDumpWithProcessThreadData // + | MiniDumpWithFullMemoryInfo // + | MiniDumpWithThreadInfo // + | MiniDumpWithUnloadedModules; + + return static_cast(type); + } + + std::string get_temp_filename() + { + char filename[MAX_PATH] = {0}; + char pathname[MAX_PATH] = {0}; + + GetTempPathA(sizeof(pathname), pathname); + GetTempFileNameA(pathname, "H1-", 0, filename); + return filename; + } + + HANDLE write_dump_to_temp_file(const LPEXCEPTION_POINTERS exceptioninfo) + { + MINIDUMP_EXCEPTION_INFORMATION minidump_exception_info = {GetCurrentThreadId(), exceptioninfo, FALSE}; + + auto* const file_handle = CreateFileA(get_temp_filename().data(), GENERIC_WRITE | GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, + FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, + nullptr); + + if (!MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), file_handle, get_minidump_type(), + &minidump_exception_info, + nullptr, + nullptr)) + { + MessageBoxA(nullptr, "There was an error creating the minidump! Hit OK to close the program.", + "Minidump Error", MB_OK | MB_ICONERROR); + TerminateProcess(GetCurrentProcess(), 123); + } + + return file_handle; + } + + std::string read_file(HANDLE file_handle) + { + FlushFileBuffers(file_handle); + SetFilePointer(file_handle, 0, nullptr, FILE_BEGIN); + + std::string buffer{}; + + DWORD bytes_read = 0; + char temp_bytes[0x2000]; + + do + { + if (!ReadFile(file_handle, temp_bytes, sizeof(temp_bytes), &bytes_read, nullptr)) + { + return {}; + } + + buffer.append(temp_bytes, bytes_read); + } + while (bytes_read == sizeof(temp_bytes)); + + return buffer; + } + } + + std::string create_minidump(const LPEXCEPTION_POINTERS exceptioninfo) + { + auto* const file_handle = write_dump_to_temp_file(exceptioninfo); + + const auto _ = gsl::finally([file_handle]() + { + CloseHandle(file_handle); + }); + + return read_file(file_handle); + } +} diff --git a/src/common/exception/minidump.hpp b/src/common/exception/minidump.hpp new file mode 100644 index 00000000..42b3a46a --- /dev/null +++ b/src/common/exception/minidump.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "../utils/nt.hpp" + +namespace exception +{ + std::string create_minidump(LPEXCEPTION_POINTERS exceptioninfo); +} diff --git a/src/common/utils/binary_resource.cpp b/src/common/utils/binary_resource.cpp new file mode 100644 index 00000000..eed83b0d --- /dev/null +++ b/src/common/utils/binary_resource.cpp @@ -0,0 +1,75 @@ +#include "binary_resource.hpp" + +#include +#include "nt.hpp" +#include "io.hpp" + +namespace utils +{ + namespace + { + std::string get_temp_folder() + { + char path[MAX_PATH] = {0}; + if (!GetTempPathA(sizeof(path), path)) + { + throw std::runtime_error("Unable to get temp path"); + } + + return path; + } + + std::string write_existing_temp_file(const std::string& file, const std::string& data, + const bool fatal_if_overwrite_fails) + { + const auto temp = get_temp_folder(); + auto file_path = temp + file; + + std::string current_data; + if (!io::read_file(file_path, ¤t_data)) + { + if (!io::write_file(file_path, data)) + { + throw std::runtime_error("Failed to write file: " + file_path); + } + + return file_path; + } + + if (current_data == data || io::write_file(file_path, data) || !fatal_if_overwrite_fails) + { + return file_path; + } + + throw std::runtime_error( + "Temporary file was already written, but differs. It can't be overwritten as it's still in use: " + + file_path); + } + } + + binary_resource::binary_resource(const int id, std::string file) + : filename_(std::move(file)) + { + this->resource_ = nt::load_resource(id); + + if (this->resource_.empty()) + { + throw std::runtime_error("Unable to load resource: " + std::to_string(id)); + } + } + + std::string binary_resource::get_extracted_file(const bool fatal_if_overwrite_fails) + { + if (this->path_.empty()) + { + this->path_ = write_existing_temp_file(this->filename_, this->resource_, fatal_if_overwrite_fails); + } + + return this->path_; + } + + const std::string& binary_resource::get_data() const + { + return this->resource_; + } +} diff --git a/src/common/utils/binary_resource.hpp b/src/common/utils/binary_resource.hpp new file mode 100644 index 00000000..da19af1a --- /dev/null +++ b/src/common/utils/binary_resource.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include + +namespace utils +{ + class binary_resource + { + public: + binary_resource(int id, std::string file); + + std::string get_extracted_file(bool fatal_if_overwrite_fails = false); + const std::string& get_data() const; + + private: + std::string resource_; + std::string filename_; + std::string path_; + }; +} diff --git a/src/common/utils/compression.cpp b/src/common/utils/compression.cpp new file mode 100644 index 00000000..1688cee5 --- /dev/null +++ b/src/common/utils/compression.cpp @@ -0,0 +1,169 @@ +#include "memory.hpp" +#include "compression.hpp" + +#include +#include + +#include + +#include "io.hpp" + +namespace utils::compression +{ + namespace zlib + { + namespace + { + class zlib_stream + { + public: + zlib_stream() + { + memset(&stream_, 0, sizeof(stream_)); + valid_ = inflateInit(&stream_) == Z_OK; + } + + zlib_stream(zlib_stream&&) = delete; + zlib_stream(const zlib_stream&) = delete; + zlib_stream& operator=(zlib_stream&&) = delete; + zlib_stream& operator=(const zlib_stream&) = delete; + + ~zlib_stream() + { + if (valid_) + { + inflateEnd(&stream_); + } + } + + z_stream& get() + { + return stream_; // + } + + bool is_valid() const + { + return valid_; + } + + private: + bool valid_{false}; + z_stream stream_{}; + }; + } + + std::string decompress(const std::string& data) + { + std::string buffer{}; + zlib_stream stream_container{}; + if (!stream_container.is_valid()) + { + return {}; + } + + int ret{}; + size_t offset = 0; + static thread_local uint8_t dest[CHUNK] = {0}; + auto& stream = stream_container.get(); + + do + { + const auto input_size = std::min(sizeof(dest), data.size() - offset); + stream.avail_in = static_cast(input_size); + stream.next_in = reinterpret_cast(data.data()) + offset; + offset += stream.avail_in; + + do + { + stream.avail_out = sizeof(dest); + stream.next_out = dest; + + ret = inflate(&stream, Z_NO_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + return {}; + } + + buffer.insert(buffer.end(), dest, dest + sizeof(dest) - stream.avail_out); + } + while (stream.avail_out == 0); + } + while (ret != Z_STREAM_END); + + return buffer; + } + + std::string compress(const std::string& data) + { + std::string result{}; + auto length = compressBound(static_cast(data.size())); + result.resize(length); + + if (compress2(reinterpret_cast(result.data()), &length, + reinterpret_cast(data.data()), static_cast(data.size()), + Z_BEST_COMPRESSION) != Z_OK) + { + return {}; + } + + result.resize(length); + return result; + } + } + + namespace zip + { + namespace + { + bool add_file(zipFile& zip_file, const std::string& filename, const std::string& data) + { + const auto zip_64 = data.size() > 0xffffffff ? 1 : 0; + if (ZIP_OK != zipOpenNewFileInZip64(zip_file, filename.data(), nullptr, nullptr, 0, nullptr, 0, nullptr, + Z_DEFLATED, Z_BEST_COMPRESSION, zip_64)) + { + return false; + } + + const auto _ = gsl::finally([&zip_file]() + { + zipCloseFileInZip(zip_file); + }); + + return ZIP_OK == zipWriteInFileInZip(zip_file, data.data(), static_cast(data.size())); + } + } + + void archive::add(std::string filename, std::string data) + { + this->files_[std::move(filename)] = std::move(data); + } + + bool archive::write(const std::string& filename, const std::string& comment) + { + // Hack to create the directory :3 + io::write_file(filename, {}); + io::remove_file(filename); + + auto* zip_file = zipOpen64(filename.data(), 0); + if (!zip_file) + { + return false; + } + + const auto _ = gsl::finally([&zip_file, &comment]() + { + zipClose(zip_file, comment.empty() ? nullptr : comment.data()); + }); + + for (const auto& file : this->files_) + { + if (!add_file(zip_file, file.first, file.second)) + { + return false; + } + } + + return true; + } + } +} diff --git a/src/common/utils/compression.hpp b/src/common/utils/compression.hpp new file mode 100644 index 00000000..dfe36ada --- /dev/null +++ b/src/common/utils/compression.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#define CHUNK 16384u + +namespace utils::compression +{ + namespace zlib + { + std::string compress(const std::string& data); + std::string decompress(const std::string& data); + } + + namespace zip + { + class archive + { + public: + void add(std::string filename, std::string data); + bool write(const std::string& filename, const std::string& comment = {}); + + private: + std::unordered_map files_; + }; + } +}; diff --git a/src/common/utils/concurrency.hpp b/src/common/utils/concurrency.hpp new file mode 100644 index 00000000..05c5d3ad --- /dev/null +++ b/src/common/utils/concurrency.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include + +namespace utils::concurrency +{ + template + class container + { + public: + template + R access(F&& accessor) const + { + std::lock_guard _{mutex_}; + return accessor(object_); + } + + template + R access(F&& accessor) + { + std::lock_guard _{mutex_}; + return accessor(object_); + } + + template + R access_with_lock(F&& accessor) const + { + std::unique_lock lock{mutex_}; + return accessor(object_, lock); + } + + template + R access_with_lock(F&& accessor) + { + std::unique_lock lock{mutex_}; + return accessor(object_, lock); + } + + T& get_raw() { return object_; } + const T& get_raw() const { return object_; } + + private: + mutable MutexType mutex_{}; + T object_{}; + }; +} diff --git a/src/common/utils/cryptography.cpp b/src/common/utils/cryptography.cpp new file mode 100644 index 00000000..2e2065a6 --- /dev/null +++ b/src/common/utils/cryptography.cpp @@ -0,0 +1,640 @@ +#include "string.hpp" +#include "cryptography.hpp" +#include "nt.hpp" +#include + +#undef max +using namespace std::string_literals; + +/// http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/Source/libtomcrypt/doc/libTomCryptDoc.pdf + +namespace utils::cryptography +{ + namespace + { + struct __ + { + __() + { + ltc_mp = ltm_desc; + + register_cipher(&aes_desc); + register_cipher(&des3_desc); + + register_prng(&sprng_desc); + register_prng(&fortuna_desc); + register_prng(&yarrow_desc); + + register_hash(&sha1_desc); + register_hash(&sha256_desc); + register_hash(&sha512_desc); + } + } ___; + + [[maybe_unused]] const char* cs(const uint8_t* data) + { + return reinterpret_cast(data); + } + + [[maybe_unused]] char* cs(uint8_t* data) + { + return reinterpret_cast(data); + } + + [[maybe_unused]] const uint8_t* cs(const char* data) + { + return reinterpret_cast(data); + } + + [[maybe_unused]] uint8_t* cs(char* data) + { + return reinterpret_cast(data); + } + + [[maybe_unused]] unsigned long ul(const size_t value) + { + return static_cast(value); + } + + class prng + { + public: + prng(const ltc_prng_descriptor& descriptor, const bool autoseed = true) + : state_(std::make_unique()) + , descriptor_(descriptor) + { + this->id_ = register_prng(&descriptor); + if (this->id_ == -1) + { + throw std::runtime_error("PRNG "s + this->descriptor_.name + " could not be registered!"); + } + + if (autoseed) + { + this->auto_seed(); + } + else + { + this->descriptor_.start(this->state_.get()); + } + } + + ~prng() + { + this->descriptor_.done(this->state_.get()); + } + + prng_state* get_state() const + { + this->descriptor_.ready(this->state_.get()); + return this->state_.get(); + } + + int get_id() const + { + return this->id_; + } + + void add_entropy(const void* data, const size_t length) const + { + this->descriptor_.add_entropy(static_cast(data), ul(length), this->state_.get()); + } + + void read(void* data, const size_t length) const + { + this->descriptor_.read(static_cast(data), ul(length), this->get_state()); + } + + private: + int id_; + std::unique_ptr state_; + const ltc_prng_descriptor& descriptor_; + + void auto_seed() const + { + rng_make_prng(128, this->id_, this->state_.get(), nullptr); + + int i[4]; // uninitialized data + auto* i_ptr = &i; + this->add_entropy(reinterpret_cast(&i), sizeof(i)); + this->add_entropy(reinterpret_cast(&i_ptr), sizeof(i_ptr)); + + auto t = time(nullptr); + this->add_entropy(reinterpret_cast(&t), sizeof(t)); + } + }; + + const prng prng_(fortuna_desc); + } + + ecc::key::key() + { + ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); + } + + ecc::key::~key() + { + this->free(); + } + + ecc::key::key(key&& obj) noexcept + : key() + { + this->operator=(std::move(obj)); + } + + ecc::key::key(const key& obj) + : key() + { + this->operator=(obj); + } + + ecc::key& ecc::key::operator=(key&& obj) noexcept + { + if (this != &obj) + { + std::memmove(&this->key_storage_, &obj.key_storage_, sizeof(this->key_storage_)); + ZeroMemory(&obj.key_storage_, sizeof(obj.key_storage_)); + } + + return *this; + } + + ecc::key& ecc::key::operator=(const key& obj) + { + if (this != &obj && obj.is_valid()) + { + this->deserialize(obj.serialize(obj.key_storage_.type)); + } + + return *this; + } + + bool ecc::key::is_valid() const + { + return (!memory::is_set(&this->key_storage_, 0, sizeof(this->key_storage_))); + } + + ecc_key& ecc::key::get() + { + return this->key_storage_; + } + + const ecc_key& ecc::key::get() const + { + return this->key_storage_; + } + + std::string ecc::key::get_public_key() const + { + uint8_t buffer[512] = {0}; + unsigned long length = sizeof(buffer); + + if (ecc_ansi_x963_export(&this->key_storage_, buffer, &length) == CRYPT_OK) + { + return std::string(cs(buffer), length); + } + + return {}; + } + + void ecc::key::set(const std::string& pub_key_buffer) + { + this->free(); + + if (ecc_ansi_x963_import(cs(pub_key_buffer.data()), + ul(pub_key_buffer.size()), + &this->key_storage_) != CRYPT_OK) + { + ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); + } + } + + void ecc::key::deserialize(const std::string& key) + { + this->free(); + + if (ecc_import(cs(key.data()), ul(key.size()), + &this->key_storage_) != CRYPT_OK + ) + { + ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); + } + } + + std::string ecc::key::serialize(const int type) const + { + uint8_t buffer[4096] = {0}; + unsigned long length = sizeof(buffer); + + if (ecc_export(buffer, &length, type, &this->key_storage_) == CRYPT_OK) + { + return std::string(cs(buffer), length); + } + + return ""; + } + + void ecc::key::free() + { + if (this->is_valid()) + { + ecc_free(&this->key_storage_); + } + + ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); + } + + bool ecc::key::operator==(key& key) const + { + return (this->is_valid() && key.is_valid() && this->serialize(PK_PUBLIC) == key.serialize(PK_PUBLIC)); + } + + uint64_t ecc::key::get_hash() const + { + const auto hash = sha1::compute(this->get_public_key()); + if (hash.size() >= 8) + { + return *reinterpret_cast(hash.data()); + } + + return 0; + } + + ecc::key ecc::generate_key(const int bits) + { + key key; + ecc_make_key(prng_.get_state(), prng_.get_id(), bits / 8, &key.get()); + + return key; + } + + ecc::key ecc::generate_key(const int bits, const std::string& entropy) + { + key key{}; + const prng yarrow(yarrow_desc, false); + yarrow.add_entropy(entropy.data(), entropy.size()); + + ecc_make_key(yarrow.get_state(), yarrow.get_id(), bits / 8, &key.get()); + + return key; + } + + std::string ecc::sign_message(const key& key, const std::string& message) + { + if (!key.is_valid()) return ""; + + uint8_t buffer[512]; + unsigned long length = sizeof(buffer); + + ecc_sign_hash(cs(message.data()), ul(message.size()), buffer, &length, prng_.get_state(), prng_.get_id(), + &key.get()); + + return std::string(cs(buffer), length); + } + + bool ecc::verify_message(const key& key, const std::string& message, const std::string& signature) + { + if (!key.is_valid()) return false; + + auto result = 0; + return (ecc_verify_hash(cs(signature.data()), + ul(signature.size()), + cs(message.data()), + ul(message.size()), &result, + &key.get()) == CRYPT_OK && result != 0); + } + + bool ecc::encrypt(const key& key, std::string& data) + { + std::string out_data{}; + out_data.resize(std::max(ul(data.size() * 3), ul(0x100))); + + auto out_len = ul(out_data.size()); + auto crypt = [&]() + { + return ecc_encrypt_key(cs(data.data()), ul(data.size()), cs(out_data.data()), &out_len, + prng_.get_state(), prng_.get_id(), find_hash("sha512"), &key.get()); + }; + + auto res = crypt(); + + if (res == CRYPT_BUFFER_OVERFLOW) + { + out_data.resize(out_len); + res = crypt(); + } + + if (res != CRYPT_OK) + { + return false; + } + + out_data.resize(out_len); + data = std::move(out_data); + return true; + } + + bool ecc::decrypt(const key& key, std::string& data) + { + std::string out_data{}; + out_data.resize(std::max(ul(data.size() * 3), ul(0x100))); + + auto out_len = ul(out_data.size()); + auto crypt = [&]() + { + return ecc_decrypt_key(cs(data.data()), ul(data.size()), cs(out_data.data()), &out_len, &key.get()); + }; + + auto res = crypt(); + + if (res == CRYPT_BUFFER_OVERFLOW) + { + out_data.resize(out_len); + res = crypt(); + } + + if (res != CRYPT_OK) + { + return false; + } + + out_data.resize(out_len); + data = std::move(out_data); + return true; + } + + std::string rsa::encrypt(const std::string& data, const std::string& hash, const std::string& key) + { + rsa_key new_key; + rsa_import(cs(key.data()), ul(key.size()), &new_key); + const auto _ = gsl::finally([&]() + { + rsa_free(&new_key); + }); + + + std::string out_data{}; + out_data.resize(std::max(ul(data.size() * 3), ul(0x100))); + + auto out_len = ul(out_data.size()); + auto crypt = [&]() + { + return rsa_encrypt_key(cs(data.data()), ul(data.size()), cs(out_data.data()), &out_len, cs(hash.data()), + ul(hash.size()), prng_.get_state(), prng_.get_id(), find_hash("sha512"), &new_key); + }; + + auto res = crypt(); + + if (res == CRYPT_BUFFER_OVERFLOW) + { + out_data.resize(out_len); + res = crypt(); + } + + if (res == CRYPT_OK) + { + out_data.resize(out_len); + return out_data; + } + + return {}; + } + + std::string des3::encrypt(const std::string& data, const std::string& iv, const std::string& key) + { + std::string enc_data; + enc_data.resize(data.size()); + + symmetric_CBC cbc; + const auto des3 = find_cipher("3des"); + + cbc_start(des3, cs(iv.data()), cs(key.data()), static_cast(key.size()), 0, &cbc); + cbc_encrypt(cs(data.data()), cs(enc_data.data()), ul(data.size()), &cbc); + cbc_done(&cbc); + + return enc_data; + } + + std::string des3::decrypt(const std::string& data, const std::string& iv, const std::string& key) + { + std::string dec_data; + dec_data.resize(data.size()); + + symmetric_CBC cbc; + const auto des3 = find_cipher("3des"); + + cbc_start(des3, cs(iv.data()), cs(key.data()), static_cast(key.size()), 0, &cbc); + cbc_decrypt(cs(data.data()), cs(dec_data.data()), ul(data.size()), &cbc); + cbc_done(&cbc); + + return dec_data; + } + + std::string tiger::compute(const std::string& data, const bool hex) + { + return compute(cs(data.data()), data.size(), hex); + } + + std::string tiger::compute(const uint8_t* data, const size_t length, const bool hex) + { + uint8_t buffer[24] = {0}; + + hash_state state; + tiger_init(&state); + tiger_process(&state, data, ul(length)); + tiger_done(&state, buffer); + + std::string hash(cs(buffer), sizeof(buffer)); + if (!hex) return hash; + + return string::dump_hex(hash, ""); + } + + std::string aes::encrypt(const std::string& data, const std::string& iv, const std::string& key) + { + std::string enc_data; + enc_data.resize(data.size()); + + symmetric_CBC cbc; + const auto aes = find_cipher("aes"); + + cbc_start(aes, cs(iv.data()), cs(key.data()), + static_cast(key.size()), 0, &cbc); + cbc_encrypt(cs(data.data()), + cs(enc_data.data()), + ul(data.size()), &cbc); + cbc_done(&cbc); + + return enc_data; + } + + std::string aes::decrypt(const std::string& data, const std::string& iv, const std::string& key) + { + std::string dec_data; + dec_data.resize(data.size()); + + symmetric_CBC cbc; + const auto aes = find_cipher("aes"); + + cbc_start(aes, cs(iv.data()), cs(key.data()), + static_cast(key.size()), 0, &cbc); + cbc_decrypt(cs(data.data()), + cs(dec_data.data()), + ul(data.size()), &cbc); + cbc_done(&cbc); + + return dec_data; + } + + std::string hmac_sha1::compute(const std::string& data, const std::string& key) + { + std::string buffer; + buffer.resize(20); + + hmac_state state; + hmac_init(&state, find_hash("sha1"), cs(key.data()), ul(key.size())); + hmac_process(&state, cs(data.data()), static_cast(data.size())); + + auto out_len = ul(buffer.size()); + hmac_done(&state, cs(buffer.data()), &out_len); + + buffer.resize(out_len); + return buffer; + } + + std::string sha1::compute(const std::string& data, const bool hex) + { + return compute(cs(data.data()), data.size(), hex); + } + + std::string sha1::compute(const uint8_t* data, const size_t length, const bool hex) + { + uint8_t buffer[20] = {0}; + + hash_state state; + sha1_init(&state); + sha1_process(&state, data, ul(length)); + sha1_done(&state, buffer); + + std::string hash(cs(buffer), sizeof(buffer)); + if (!hex) return hash; + + return string::dump_hex(hash, ""); + } + + std::string sha256::compute(const std::string& data, const bool hex) + { + return compute(cs(data.data()), data.size(), hex); + } + + std::string sha256::compute(const uint8_t* data, const size_t length, const bool hex) + { + uint8_t buffer[32] = {0}; + + hash_state state; + sha256_init(&state); + sha256_process(&state, data, ul(length)); + sha256_done(&state, buffer); + + std::string hash(cs(buffer), sizeof(buffer)); + if (!hex) return hash; + + return string::dump_hex(hash, ""); + } + + std::string sha512::compute(const std::string& data, const bool hex) + { + return compute(cs(data.data()), data.size(), hex); + } + + std::string sha512::compute(const uint8_t* data, const size_t length, const bool hex) + { + uint8_t buffer[64] = {0}; + + hash_state state; + sha512_init(&state); + sha512_process(&state, data, ul(length)); + sha512_done(&state, buffer); + + std::string hash(cs(buffer), sizeof(buffer)); + if (!hex) return hash; + + return string::dump_hex(hash, ""); + } + + std::string base64::encode(const uint8_t* data, const size_t len) + { + std::string result; + result.resize((len + 2) * 2); + + auto out_len = ul(result.size()); + if (base64_encode(data, ul(len), result.data(), &out_len) != CRYPT_OK) + { + return {}; + } + + result.resize(out_len); + return result; + } + + std::string base64::encode(const std::string& data) + { + return base64::encode(cs(data.data()), static_cast(data.size())); + } + + std::string base64::decode(const std::string& data) + { + std::string result; + result.resize((data.size() + 2) * 2); + + auto out_len = ul(result.size()); + if (base64_decode(data.data(), ul(data.size()), cs(result.data()), &out_len) != CRYPT_OK) + { + return {}; + } + + result.resize(out_len); + return result; + } + + unsigned int jenkins_one_at_a_time::compute(const std::string& data) + { + return compute(data.data(), data.size()); + } + + unsigned int jenkins_one_at_a_time::compute(const char* key, const size_t len) + { + unsigned int hash, i; + for (hash = i = 0; i < len; ++i) + { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + return hash; + } + + uint32_t random::get_integer() + { + uint32_t result; + random::get_data(&result, sizeof(result)); + return result; + } + + std::string random::get_challenge() + { + std::string result; + result.resize(sizeof(uint32_t)); + random::get_data(result.data(), result.size()); + return string::dump_hex(result, ""); + } + + void random::get_data(void* data, const size_t size) + { + prng_.read(data, size); + } +} diff --git a/src/common/utils/cryptography.hpp b/src/common/utils/cryptography.hpp new file mode 100644 index 00000000..9538c5eb --- /dev/null +++ b/src/common/utils/cryptography.hpp @@ -0,0 +1,118 @@ +#pragma once + +#include +#include + +namespace utils::cryptography +{ + namespace ecc + { + class key final + { + public: + key(); + ~key(); + + key(key&& obj) noexcept; + key(const key& obj); + key& operator=(key&& obj) noexcept; + key& operator=(const key& obj); + + bool is_valid() const; + + ecc_key& get(); + const ecc_key& get() const; + + std::string get_public_key() const; + + void set(const std::string& pub_key_buffer); + + void deserialize(const std::string& key); + + std::string serialize(int type = PK_PRIVATE) const; + + void free(); + + bool operator==(key& key) const; + + uint64_t get_hash() const; + + private: + ecc_key key_storage_{}; + }; + + key generate_key(int bits); + key generate_key(int bits, const std::string& entropy); + std::string sign_message(const key& key, const std::string& message); + bool verify_message(const key& key, const std::string& message, const std::string& signature); + + bool encrypt(const key& key, std::string& data); + bool decrypt(const key& key, std::string& data); + } + + namespace rsa + { + std::string encrypt(const std::string& data, const std::string& hash, const std::string& key); + } + + namespace des3 + { + std::string encrypt(const std::string& data, const std::string& iv, const std::string& key); + std::string decrypt(const std::string& data, const std::string& iv, const std::string& key); + } + + namespace tiger + { + std::string compute(const std::string& data, bool hex = false); + std::string compute(const uint8_t* data, size_t length, bool hex = false); + } + + namespace aes + { + std::string encrypt(const std::string& data, const std::string& iv, const std::string& key); + std::string decrypt(const std::string& data, const std::string& iv, const std::string& key); + } + + namespace hmac_sha1 + { + std::string compute(const std::string& data, const std::string& key); + } + + namespace sha1 + { + std::string compute(const std::string& data, bool hex = false); + std::string compute(const uint8_t* data, size_t length, bool hex = false); + } + + namespace sha256 + { + std::string compute(const std::string& data, bool hex = false); + std::string compute(const uint8_t* data, size_t length, bool hex = false); + } + + namespace sha512 + { + std::string compute(const std::string& data, bool hex = false); + std::string compute(const uint8_t* data, size_t length, bool hex = false); + } + + namespace base64 + { + std::string encode(const uint8_t* data, size_t len); + std::string encode(const std::string& data); + std::string decode(const std::string& data); + } + + namespace jenkins_one_at_a_time + { + unsigned int compute(const std::string& data); + unsigned int compute(const char* key, size_t len); + }; + + namespace random + { + uint32_t get_integer(); + std::string get_challenge(); + void get_data(void* data, size_t size); + } +} diff --git a/src/common/utils/flags.cpp b/src/common/utils/flags.cpp new file mode 100644 index 00000000..09f13114 --- /dev/null +++ b/src/common/utils/flags.cpp @@ -0,0 +1,53 @@ +#include "flags.hpp" +#include "string.hpp" +#include "nt.hpp" + +#include + +namespace utils::flags +{ + void parse_flags(std::vector& flags) + { + int num_args; + auto* const argv = CommandLineToArgvW(GetCommandLineW(), &num_args); + + flags.clear(); + + if (argv) + { + for (auto i = 0; i < num_args; ++i) + { + std::wstring wide_flag(argv[i]); + if (wide_flag[0] == L'-') + { + wide_flag.erase(wide_flag.begin()); + flags.emplace_back(string::convert(wide_flag)); + } + } + + LocalFree(argv); + } + } + + bool has_flag(const std::string& flag) + { + static auto parsed = false; + static std::vector enabled_flags; + + if (!parsed) + { + parse_flags(enabled_flags); + parsed = true; + } + + for (const auto& entry : enabled_flags) + { + if (string::to_lower(entry) == string::to_lower(flag)) + { + return true; + } + } + + return false; + } +} diff --git a/src/common/utils/flags.hpp b/src/common/utils/flags.hpp new file mode 100644 index 00000000..cf304b20 --- /dev/null +++ b/src/common/utils/flags.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace utils::flags +{ + bool has_flag(const std::string& flag); +} diff --git a/src/common/utils/hook.cpp b/src/common/utils/hook.cpp new file mode 100644 index 00000000..be05cb96 --- /dev/null +++ b/src/common/utils/hook.cpp @@ -0,0 +1,310 @@ +#include "hook.hpp" +#include "string.hpp" + +#include + +namespace utils::hook +{ + namespace + { + [[maybe_unused]] class _ + { + public: + _() + { + if (MH_Initialize() != MH_OK) + { + throw std::runtime_error("Failed to initialize MinHook"); + } + } + + ~_() + { + MH_Uninitialize(); + } + } __; + } + + void assembler::pushad64() + { + this->push(rax); + this->push(rcx); + this->push(rdx); + this->push(rbx); + this->push(rsp); + this->push(rbp); + this->push(rsi); + this->push(rdi); + + this->sub(rsp, 0x40); + } + + void assembler::popad64() + { + this->add(rsp, 0x40); + + this->pop(rdi); + this->pop(rsi); + this->pop(rbp); + this->pop(rsp); + this->pop(rbx); + this->pop(rdx); + this->pop(rcx); + this->pop(rax); + } + + void assembler::prepare_stack_for_call() + { + const auto reserve_callee_space = this->newLabel(); + const auto stack_unaligned = this->newLabel(); + + this->test(rsp, 0xF); + this->jnz(stack_unaligned); + + this->sub(rsp, 0x8); + this->push(rsp); + + this->push(rax); + this->mov(rax, ptr(rsp, 8, 8)); + this->add(rax, 0x8); + this->mov(ptr(rsp, 8, 8), rax); + this->pop(rax); + + this->jmp(reserve_callee_space); + + this->bind(stack_unaligned); + this->push(rsp); + + this->bind(reserve_callee_space); + this->sub(rsp, 0x40); + } + + void assembler::restore_stack_after_call() + { + this->lea(rsp, ptr(rsp, 0x40)); + this->pop(rsp); + } + + asmjit::Error assembler::call(void* target) + { + return Assembler::call(size_t(target)); + } + + asmjit::Error assembler::jmp(void* target) + { + return Assembler::jmp(size_t(target)); + } + + detour::detour(const size_t place, void* target) : detour(reinterpret_cast(place), target) + { + } + + detour::detour(void* place, void* target) + { + this->create(place, target); + } + + detour::~detour() + { + this->clear(); + } + + void detour::enable() const + { + MH_EnableHook(this->place_); + } + + void detour::disable() const + { + MH_DisableHook(this->place_); + } + + void detour::create(void* place, void* target) + { + this->clear(); + this->place_ = place; + + if (MH_CreateHook(this->place_, target, &this->original_) != MH_OK) + { + throw std::runtime_error(string::va("Unable to create hook at location: %p", this->place_)); + } + + this->enable(); + } + + void detour::create(const size_t place, void* target) + { + this->create(reinterpret_cast(place), target); + } + + void detour::clear() + { + if (this->place_) + { + MH_RemoveHook(this->place_); + } + + this->place_ = nullptr; + this->original_ = nullptr; + } + + void* detour::get_original() const + { + return this->original_; + } + + bool iat(const nt::library& library, const std::string& target_library, const std::string& process, void* stub) + { + if (!library.is_valid()) return false; + + auto* const ptr = library.get_iat_entry(target_library, process); + if (!ptr) return false; + + DWORD protect; + VirtualProtect(ptr, sizeof(*ptr), PAGE_EXECUTE_READWRITE, &protect); + + *ptr = stub; + + VirtualProtect(ptr, sizeof(*ptr), protect, &protect); + return true; + } + + void nop(void* place, const size_t length) + { + DWORD old_protect{}; + VirtualProtect(place, length, PAGE_EXECUTE_READWRITE, &old_protect); + + std::memset(place, 0x90, length); + + VirtualProtect(place, length, old_protect, &old_protect); + FlushInstructionCache(GetCurrentProcess(), place, length); + } + + void nop(const size_t place, const size_t length) + { + nop(reinterpret_cast(place), length); + } + + void copy(void* place, const void* data, const size_t length) + { + DWORD old_protect{}; + VirtualProtect(place, length, PAGE_EXECUTE_READWRITE, &old_protect); + + std::memmove(place, data, length); + + VirtualProtect(place, length, old_protect, &old_protect); + FlushInstructionCache(GetCurrentProcess(), place, length); + } + + void copy(const size_t place, const void* data, const size_t length) + { + copy(reinterpret_cast(place), data, length); + } + + bool is_relatively_far(const void* pointer, const void* data, const int offset) + { + const int64_t diff = size_t(data) - (size_t(pointer) + offset); + const auto small_diff = int32_t(diff); + return diff != int64_t(small_diff); + } + + void call(void* pointer, void* data) + { + if (is_relatively_far(pointer, data)) + { + throw std::runtime_error("Too far away to create 32bit relative branch"); + } + + auto* patch_pointer = PBYTE(pointer); + set(patch_pointer, 0xE8); + set(patch_pointer + 1, int32_t(size_t(data) - (size_t(pointer) + 5))); + } + + void call(const size_t pointer, void* data) + { + return call(reinterpret_cast(pointer), data); + } + + void call(const size_t pointer, const size_t data) + { + return call(pointer, reinterpret_cast(data)); + } + + void jump(void* pointer, void* data, const bool use_far) + { + static const unsigned char jump_data[] = { + 0x48, 0xb8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xff, 0xe0 + }; + + if (!use_far && is_relatively_far(pointer, data)) + { + throw std::runtime_error("Too far away to create 32bit relative branch"); + } + + auto* patch_pointer = PBYTE(pointer); + + if (use_far) + { + copy(patch_pointer, jump_data, sizeof(jump_data)); + copy(patch_pointer + 2, &data, sizeof(data)); + } + else + { + set(patch_pointer, 0xE9); + set(patch_pointer + 1, int32_t(size_t(data) - (size_t(pointer) + 5))); + } + } + + void jump(const size_t pointer, void* data, const bool use_far) + { + return jump(reinterpret_cast(pointer), data, use_far); + } + + void jump(const size_t pointer, const size_t data, const bool use_far) + { + return jump(pointer, reinterpret_cast(data), use_far); + } + + void* assemble(const std::function& asm_function) + { + static asmjit::JitRuntime runtime; + + asmjit::CodeHolder code; + code.init(runtime.environment()); + + assembler a(&code); + + asm_function(a); + + void* result = nullptr; + runtime.add(&result, &code); + + return result; + } + + void inject(void* pointer, const void* data) + { + if (is_relatively_far(pointer, data, 4)) + { + throw std::runtime_error("Too far away to create 32bit relative branch"); + } + + set(pointer, int32_t(size_t(data) - (size_t(pointer) + 4))); + } + + void inject(const size_t pointer, const void* data) + { + return inject(reinterpret_cast(pointer), data); + } + + void* follow_branch(void* address) + { + auto* const data = static_cast(address); + if (*data != 0xE8 && *data != 0xE9) + { + throw std::runtime_error("No branch instruction found"); + } + + return extract(data + 1); + } +} diff --git a/src/common/utils/hook.hpp b/src/common/utils/hook.hpp new file mode 100644 index 00000000..bb24f8ce --- /dev/null +++ b/src/common/utils/hook.hpp @@ -0,0 +1,205 @@ +#pragma once +#include "signature.hpp" + +#include +#include + +using namespace asmjit::x86; + +namespace utils::hook +{ + namespace detail + { + template + std::vector get_iota_functions() + { + if constexpr (entries == 0) + { + std::vector functions; + return functions; + } + else + { + auto functions = get_iota_functions(); + functions.emplace_back([]() + { + return entries - 1; + }); + return functions; + } + } + } + + // Gets the pointer to the entry in the v-table. + // It seems otherwise impossible to get this. + // This is ugly as fuck and only safely works on x64 + // Example: + // ID3D11Device* device = ... + // auto entry = get_vtable_entry(device, &ID3D11Device::CreateTexture2D); + template + void** get_vtable_entry(Class* obj, T (Class::* entry)(Args ...)) + { + union + { + decltype(entry) func; + void* pointer; + }; + + func = entry; + + auto iota_functions = detail::get_iota_functions(); + auto* object = iota_functions.data(); + + using FakeFunc = size_t(__thiscall*)(void* self); + auto index = static_cast(pointer)(&object); + + void** obj_v_table = *reinterpret_cast(obj); + return &obj_v_table[index]; + } + + class assembler : public Assembler + { + public: + using Assembler::Assembler; + using Assembler::call; + using Assembler::jmp; + + void pushad64(); + void popad64(); + + void prepare_stack_for_call(); + void restore_stack_after_call(); + + template + void call_aligned(T&& target) + { + this->prepare_stack_for_call(); + this->call(std::forward(target)); + this->restore_stack_after_call(); + } + + asmjit::Error call(void* target); + asmjit::Error jmp(void* target); + }; + + class detour + { + public: + detour() = default; + detour(void* place, void* target); + detour(size_t place, void* target); + ~detour(); + + detour(detour&& other) noexcept + { + this->operator=(std::move(other)); + } + + detour& operator=(detour&& other) noexcept + { + if (this != &other) + { + this->~detour(); + + this->place_ = other.place_; + this->original_ = other.original_; + + other.place_ = nullptr; + other.original_ = nullptr; + } + + return *this; + } + + detour(const detour&) = delete; + detour& operator=(const detour&) = delete; + + void enable() const; + void disable() const; + + void create(void* place, void* target); + void create(size_t place, void* target); + void clear(); + + template + T* get() const + { + return static_cast(this->get_original()); + } + + template + T invoke(Args ... args) + { + return static_cast(this->get_original())(args...); + } + + [[nodiscard]] void* get_original() const; + + private: + void* place_{}; + void* original_{}; + }; + + bool iat(const nt::library& library, const std::string& target_library, const std::string& process, void* stub); + + void nop(void* place, size_t length); + void nop(size_t place, size_t length); + + void copy(void* place, const void* data, size_t length); + void copy(size_t place, const void* data, size_t length); + + bool is_relatively_far(const void* pointer, const void* data, int offset = 5); + + void call(void* pointer, void* data); + void call(size_t pointer, void* data); + void call(size_t pointer, size_t data); + + void jump(void* pointer, void* data, bool use_far = false); + void jump(size_t pointer, void* data, bool use_far = false); + void jump(size_t pointer, size_t data, bool use_far = false); + + void* assemble(const std::function& asm_function); + + void inject(void* pointer, const void* data); + void inject(size_t pointer, const void* data); + + template + T extract(void* address) + { + auto* const data = static_cast(address); + const auto offset = *reinterpret_cast(data); + return reinterpret_cast(data + offset + 4); + } + + void* follow_branch(void* address); + + template + static void set(void* place, T value) + { + DWORD old_protect; + VirtualProtect(place, sizeof(T), PAGE_EXECUTE_READWRITE, &old_protect); + + *static_cast(place) = value; + + VirtualProtect(place, sizeof(T), old_protect, &old_protect); + FlushInstructionCache(GetCurrentProcess(), place, sizeof(T)); + } + + template + static void set(const size_t place, T value) + { + return set(reinterpret_cast(place), value); + } + + template + static T invoke(size_t func, Args ... args) + { + return reinterpret_cast(func)(args...); + } + + template + static T invoke(void* func, Args ... args) + { + return static_cast(func)(args...); + } +} diff --git a/src/common/utils/http.cpp b/src/common/utils/http.cpp new file mode 100644 index 00000000..3cb59991 --- /dev/null +++ b/src/common/utils/http.cpp @@ -0,0 +1,48 @@ +#include "http.hpp" +#include "nt.hpp" +#include + +namespace utils::http +{ + std::optional get_data(const std::string& url) + { + CComPtr stream; + + if (FAILED(URLOpenBlockingStreamA(nullptr, url.data(), &stream, 0, nullptr))) + { + return {}; + } + + char buffer[0x1000]; + std::string result; + + HRESULT status{}; + + do + { + DWORD bytes_read = 0; + status = stream->Read(buffer, sizeof(buffer), &bytes_read); + + if (bytes_read > 0) + { + result.append(buffer, bytes_read); + } + } + while (SUCCEEDED(status) && status != S_FALSE); + + if (FAILED(status)) + { + return {}; + } + + return {result}; + } + + std::future> get_data_async(const std::string& url) + { + return std::async(std::launch::async, [url]() + { + return get_data(url); + }); + } +} diff --git a/src/common/utils/http.hpp b/src/common/utils/http.hpp new file mode 100644 index 00000000..65628a9f --- /dev/null +++ b/src/common/utils/http.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include +#include +#include + +namespace utils::http +{ + std::optional get_data(const std::string& url); + std::future> get_data_async(const std::string& url); +} diff --git a/src/common/utils/image.cpp b/src/common/utils/image.cpp new file mode 100644 index 00000000..33f865e2 --- /dev/null +++ b/src/common/utils/image.cpp @@ -0,0 +1,53 @@ +#include "image.hpp" + +#define STB_IMAGE_IMPLEMENTATION +#include +#include + +namespace utils +{ + image::image(const std::string& image_data) + { + int channels{}; + auto* rgb_image = stbi_load_from_memory(reinterpret_cast(image_data.data()), static_cast(image_data.size()), &this->width, &this->height, &channels, 4); + if(!rgb_image) + { + throw std::runtime_error("Unable to load image"); + } + + auto _ = gsl::finally([rgb_image]() + { + stbi_image_free(rgb_image); + }); + + const auto size = this->width * this->height * 4; + this->data.resize(size); + + std::memmove(this->data.data(), rgb_image, size); + } + + int image::get_width() const + { + return this->width; + } + + int image::get_height() const + { + return this->height; + } + + const void* image::get_buffer() const + { + return this->data.data(); + } + + size_t image::get_size() const + { + return this->data.size(); + } + + const std::string& image::get_data() const + { + return this->data; + } +} diff --git a/src/common/utils/image.hpp b/src/common/utils/image.hpp new file mode 100644 index 00000000..a617df76 --- /dev/null +++ b/src/common/utils/image.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace utils +{ + class image + { + public: + image(const std::string& data); + + int get_width() const; + int get_height() const; + const void* get_buffer() const; + size_t get_size() const; + + const std::string& get_data() const; + + private: + int width{}; + int height{}; + std::string data{}; + }; +} diff --git a/src/common/utils/info_string.cpp b/src/common/utils/info_string.cpp new file mode 100644 index 00000000..3b0287e3 --- /dev/null +++ b/src/common/utils/info_string.cpp @@ -0,0 +1,65 @@ +#include "info_string.hpp" +#include "string.hpp" + +namespace utils +{ + info_string::info_string(const std::string& buffer) + { + this->parse(buffer); + } + + info_string::info_string(const std::string_view& buffer) + : info_string(std::string{buffer}) + { + } + + void info_string::set(const std::string& key, const std::string& value) + { + this->key_value_pairs_[key] = value; + } + + std::string info_string::get(const std::string& key) const + { + const auto value = this->key_value_pairs_.find(key); + if (value != this->key_value_pairs_.end()) + { + return value->second; + } + + return ""; + } + + void info_string::parse(std::string buffer) + { + if (buffer[0] == '\\') + { + buffer = buffer.substr(1); + } + + auto key_values = string::split(buffer, '\\'); + for (size_t i = 0; !key_values.empty() && i < (key_values.size() - 1); i += 2) + { + const auto& key = key_values[i]; + const auto& value = key_values[i + 1]; + this->key_value_pairs_[key] = value; + } + } + + std::string info_string::build() const + { + //auto first = true; + std::string info_string; + for (auto i = this->key_value_pairs_.begin(); i != this->key_value_pairs_.end(); ++i) + { + //if (first) first = false; + /*else*/ + info_string.append("\\"); + + info_string.append(i->first); // Key + info_string.append("\\"); + info_string.append(i->second); // Value + } + + return info_string; + } +} diff --git a/src/common/utils/info_string.hpp b/src/common/utils/info_string.hpp new file mode 100644 index 00000000..73910411 --- /dev/null +++ b/src/common/utils/info_string.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +namespace utils +{ + class info_string + { + public: + info_string() = default; + info_string(const std::string& buffer); + info_string(const std::string_view& buffer); + + void set(const std::string& key, const std::string& value); + std::string get(const std::string& key) const; + std::string build() const; + + private: + std::unordered_map key_value_pairs_{}; + + void parse(std::string buffer); + }; +} diff --git a/src/common/utils/io.cpp b/src/common/utils/io.cpp new file mode 100644 index 00000000..9b161d39 --- /dev/null +++ b/src/common/utils/io.cpp @@ -0,0 +1,130 @@ +#include "io.hpp" +#include "nt.hpp" +#include + +namespace utils::io +{ + bool remove_file(const std::string& file) + { + return DeleteFileA(file.data()) == TRUE; + } + + bool move_file(const std::string& src, const std::string& target) + { + return MoveFileA(src.data(), target.data()) == TRUE; + } + + bool file_exists(const std::string& file) + { + return std::ifstream(file).good(); + } + + bool write_file(const std::string& file, const std::string& data, const bool append) + { + const auto pos = file.find_last_of("/\\"); + if (pos != std::string::npos) + { + create_directory(file.substr(0, pos)); + } + + std::ofstream stream( + file, std::ios::binary | std::ofstream::out | (append ? std::ofstream::app : 0)); + + if (stream.is_open()) + { + stream.write(data.data(), data.size()); + stream.close(); + return true; + } + + return false; + } + + std::string read_file(const std::string& file) + { + std::string data; + read_file(file, &data); + return data; + } + + bool read_file(const std::string& file, std::string* data) + { + if (!data) return false; + data->clear(); + + if (file_exists(file)) + { + std::ifstream stream(file, std::ios::binary); + if (!stream.is_open()) return false; + + stream.seekg(0, std::ios::end); + const std::streamsize size = stream.tellg(); + stream.seekg(0, std::ios::beg); + + if (size > -1) + { + data->resize(static_cast(size)); + stream.read(const_cast(data->data()), size); + stream.close(); + return true; + } + } + + return false; + } + + size_t file_size(const std::string& file) + { + if (file_exists(file)) + { + std::ifstream stream(file, std::ios::binary); + + if (stream.good()) + { + stream.seekg(0, std::ios::end); + return static_cast(stream.tellg()); + } + } + + return 0; + } + + bool create_directory(const std::string& directory) + { + return std::filesystem::create_directories(directory); + } + + bool directory_exists(const std::string& directory) + { + return std::filesystem::is_directory(directory); + } + + bool directory_is_empty(const std::string& directory) + { + return std::filesystem::is_empty(directory); + } + + bool remove_directory(const std::string& directory) + { + return std::filesystem::remove_all(directory); + } + + std::vector list_files(const std::string& directory) + { + std::vector files; + + for (auto& file : std::filesystem::directory_iterator(directory)) + { + files.push_back(file.path().generic_string()); + } + + return files; + } + + void copy_folder(const std::filesystem::path& src, const std::filesystem::path& target) + { + std::filesystem::copy(src, target, + std::filesystem::copy_options::overwrite_existing | + std::filesystem::copy_options::recursive); + } +} diff --git a/src/common/utils/io.hpp b/src/common/utils/io.hpp new file mode 100644 index 00000000..38344987 --- /dev/null +++ b/src/common/utils/io.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include + +namespace utils::io +{ + bool remove_file(const std::string& file); + bool move_file(const std::string& src, const std::string& target); + bool file_exists(const std::string& file); + bool write_file(const std::string& file, const std::string& data, bool append = false); + bool read_file(const std::string& file, std::string* data); + std::string read_file(const std::string& file); + size_t file_size(const std::string& file); + bool create_directory(const std::string& directory); + bool directory_exists(const std::string& directory); + bool directory_is_empty(const std::string& directory); + bool remove_directory(const std::string& directory); + std::vector list_files(const std::string& directory); + void copy_folder(const std::filesystem::path& src, const std::filesystem::path& target); +} diff --git a/src/common/utils/memory.cpp b/src/common/utils/memory.cpp new file mode 100644 index 00000000..99a03916 --- /dev/null +++ b/src/common/utils/memory.cpp @@ -0,0 +1,173 @@ +#include "memory.hpp" +#include "nt.hpp" + +namespace utils +{ + memory::allocator memory::mem_allocator_; + + memory::allocator::~allocator() + { + this->clear(); + } + + void memory::allocator::clear() + { + std::lock_guard _(this->mutex_); + + for (auto& data : this->pool_) + { + memory::free(data); + } + + this->pool_.clear(); + } + + void memory::allocator::free(void* data) + { + std::lock_guard _(this->mutex_); + + const auto j = std::find(this->pool_.begin(), this->pool_.end(), data); + if (j != this->pool_.end()) + { + memory::free(data); + this->pool_.erase(j); + } + } + + void memory::allocator::free(const void* data) + { + this->free(const_cast(data)); + } + + void* memory::allocator::allocate(const size_t length) + { + std::lock_guard _(this->mutex_); + + const auto data = memory::allocate(length); + this->pool_.push_back(data); + return data; + } + + bool memory::allocator::empty() const + { + return this->pool_.empty(); + } + + char* memory::allocator::duplicate_string(const std::string& string) + { + std::lock_guard _(this->mutex_); + + const auto data = memory::duplicate_string(string); + this->pool_.push_back(data); + return data; + } + + bool memory::allocator::find(const void* data) + { + std::lock_guard _(this->mutex_); + + const auto j = std::find(this->pool_.begin(), this->pool_.end(), data); + return j != this->pool_.end(); + } + + void* memory::allocate(const size_t length) + { + return calloc(length, 1); + } + + char* memory::duplicate_string(const std::string& string) + { + const auto new_string = allocate_array(string.size() + 1); + std::memcpy(new_string, string.data(), string.size()); + return new_string; + } + + void memory::free(void* data) + { + if (data) + { + ::free(data); + } + } + + void memory::free(const void* data) + { + free(const_cast(data)); + } + + bool memory::is_set(const void* mem, const char chr, const size_t length) + { + const auto mem_arr = static_cast(mem); + + for (size_t i = 0; i < length; ++i) + { + if (mem_arr[i] != chr) + { + return false; + } + } + + return true; + } + + bool memory::is_bad_read_ptr(const void* ptr) + { + MEMORY_BASIC_INFORMATION mbi = {}; + if (VirtualQuery(ptr, &mbi, sizeof(mbi))) + { + const DWORD mask = (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | + PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); + auto b = !(mbi.Protect & mask); + // check the page is not a guard page + if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) b = true; + + return b; + } + return true; + } + + bool memory::is_bad_code_ptr(const void* ptr) + { + MEMORY_BASIC_INFORMATION mbi = {}; + if (VirtualQuery(ptr, &mbi, sizeof(mbi))) + { + const DWORD mask = (PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); + auto b = !(mbi.Protect & mask); + // check the page is not a guard page + if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) b = true; + + return b; + } + return true; + } + + bool memory::is_rdata_ptr(void* pointer) + { + const std::string rdata = ".rdata"; + const auto pointer_lib = utils::nt::library::get_by_address(pointer); + + for (const auto& section : pointer_lib.get_section_headers()) + { + const auto size = sizeof(section->Name); + char name[size + 1]; + name[size] = 0; + std::memcpy(name, section->Name, size); + + if (name == rdata) + { + const auto target = size_t(pointer); + const size_t source_start = size_t(pointer_lib.get_ptr()) + section->PointerToRawData; + const size_t source_end = source_start + section->SizeOfRawData; + + return target >= source_start && target <= source_end; + } + } + + return false; + } + + memory::allocator* memory::get_allocator() + { + return &memory::mem_allocator_; + } +} diff --git a/src/common/utils/memory.hpp b/src/common/utils/memory.hpp new file mode 100644 index 00000000..01f9554f --- /dev/null +++ b/src/common/utils/memory.hpp @@ -0,0 +1,77 @@ +#pragma once + +#include +#include + +namespace utils +{ + class memory final + { + public: + class allocator final + { + public: + ~allocator(); + + void clear(); + + void free(void* data); + + void free(const void* data); + + void* allocate(size_t length); + + template + inline T* allocate() + { + return this->allocate_array(1); + } + + template + inline T* allocate_array(const size_t count = 1) + { + return static_cast(this->allocate(count * sizeof(T))); + } + + bool empty() const; + + char* duplicate_string(const std::string& string); + + bool find(const void* data); + + private: + std::mutex mutex_; + std::vector pool_; + }; + + static void* allocate(size_t length); + + template + static inline T* allocate() + { + return allocate_array(1); + } + + template + static inline T* allocate_array(const size_t count = 1) + { + return static_cast(allocate(count * sizeof(T))); + } + + static char* duplicate_string(const std::string& string); + + static void free(void* data); + static void free(const void* data); + + static bool is_set(const void* mem, char chr, size_t length); + + static bool is_bad_read_ptr(const void* ptr); + static bool is_bad_code_ptr(const void* ptr); + static bool is_rdata_ptr(void* ptr); + + static allocator* get_allocator(); + + private: + static allocator mem_allocator_; + }; +} diff --git a/src/common/utils/nt.cpp b/src/common/utils/nt.cpp new file mode 100644 index 00000000..5fc5273c --- /dev/null +++ b/src/common/utils/nt.cpp @@ -0,0 +1,254 @@ +#include "nt.hpp" + +namespace utils::nt +{ + library library::load(const std::string& name) + { + return library(LoadLibraryA(name.data())); + } + + library library::load(const std::filesystem::path& path) + { + return library::load(path.generic_string()); + } + + library library::get_by_address(void* address) + { + HMODULE handle = nullptr; + GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, static_cast(address), &handle); + return library(handle); + } + + library::library() + { + this->module_ = GetModuleHandleA(nullptr); + } + + library::library(const std::string& name) + { + this->module_ = GetModuleHandleA(name.data()); + } + + library::library(const HMODULE handle) + { + this->module_ = handle; + } + + bool library::operator==(const library& obj) const + { + return this->module_ == obj.module_; + } + + library::operator bool() const + { + return this->is_valid(); + } + + library::operator HMODULE() const + { + return this->get_handle(); + } + + PIMAGE_NT_HEADERS library::get_nt_headers() const + { + if (!this->is_valid()) return nullptr; + return reinterpret_cast(this->get_ptr() + this->get_dos_header()->e_lfanew); + } + + PIMAGE_DOS_HEADER library::get_dos_header() const + { + return reinterpret_cast(this->get_ptr()); + } + + PIMAGE_OPTIONAL_HEADER library::get_optional_header() const + { + if (!this->is_valid()) return nullptr; + return &this->get_nt_headers()->OptionalHeader; + } + + std::vector library::get_section_headers() const + { + std::vector headers; + + auto nt_headers = this->get_nt_headers(); + auto section = IMAGE_FIRST_SECTION(nt_headers); + + for (uint16_t i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i, ++section) + { + if (section) headers.push_back(section); + else OutputDebugStringA("There was an invalid section :O"); + } + + return headers; + } + + std::uint8_t* library::get_ptr() const + { + return reinterpret_cast(this->module_); + } + + void library::unprotect() const + { + if (!this->is_valid()) return; + + DWORD protection; + VirtualProtect(this->get_ptr(), this->get_optional_header()->SizeOfImage, PAGE_EXECUTE_READWRITE, + &protection); + } + + size_t library::get_relative_entry_point() const + { + if (!this->is_valid()) return 0; + return this->get_nt_headers()->OptionalHeader.AddressOfEntryPoint; + } + + void* library::get_entry_point() const + { + if (!this->is_valid()) return nullptr; + return this->get_ptr() + this->get_relative_entry_point(); + } + + bool library::is_valid() const + { + return this->module_ != nullptr && this->get_dos_header()->e_magic == IMAGE_DOS_SIGNATURE; + } + + std::string library::get_name() const + { + if (!this->is_valid()) return ""; + + auto path = this->get_path(); + const auto pos = path.find_last_of("/\\"); + if (pos == std::string::npos) return path; + + return path.substr(pos + 1); + } + + std::string library::get_path() const + { + if (!this->is_valid()) return ""; + + char name[MAX_PATH] = {0}; + GetModuleFileNameA(this->module_, name, sizeof name); + + return name; + } + + std::string library::get_folder() const + { + if (!this->is_valid()) return ""; + + const auto path = std::filesystem::path(this->get_path()); + return path.parent_path().generic_string(); + } + + void library::free() + { + if (this->is_valid()) + { + FreeLibrary(this->module_); + this->module_ = nullptr; + } + } + + HMODULE library::get_handle() const + { + return this->module_; + } + + void** library::get_iat_entry(const std::string& module_name, const std::string& proc_name) const + { + if (!this->is_valid()) return nullptr; + + const library other_module(module_name); + if (!other_module.is_valid()) return nullptr; + + auto* const target_function = other_module.get_proc(proc_name); + if (!target_function) return nullptr; + + auto* header = this->get_optional_header(); + if (!header) return nullptr; + + auto* import_descriptor = reinterpret_cast(this->get_ptr() + header->DataDirectory + [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + + while (import_descriptor->Name) + { + if (!_stricmp(reinterpret_cast(this->get_ptr() + import_descriptor->Name), module_name.data())) + { + auto* original_thunk_data = reinterpret_cast(import_descriptor-> + OriginalFirstThunk + this->get_ptr()); + auto* thunk_data = reinterpret_cast(import_descriptor->FirstThunk + this-> + get_ptr()); + + while (original_thunk_data->u1.AddressOfData) + { + const size_t ordinal_number = original_thunk_data->u1.AddressOfData & 0xFFFFFFF; + + if (ordinal_number > 0xFFFF) continue; + + if (GetProcAddress(other_module.module_, reinterpret_cast(ordinal_number)) == + target_function) + { + return reinterpret_cast(&thunk_data->u1.Function); + } + + ++original_thunk_data; + ++thunk_data; + } + + //break; + } + + ++import_descriptor; + } + + return nullptr; + } + + void raise_hard_exception() + { + int data = false; + const library ntdll("ntdll.dll"); + ntdll.invoke_pascal("RtlAdjustPrivilege", 19, true, false, &data); + ntdll.invoke_pascal("NtRaiseHardError", 0xC000007B, 0, nullptr, nullptr, 6, &data); + } + + std::string load_resource(const int id) + { + auto* const res = FindResource(library(), MAKEINTRESOURCE(id), RT_RCDATA); + if (!res) return {}; + + auto* const handle = LoadResource(nullptr, res); + if (!handle) return {}; + + return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, res)); + } + + void relaunch_self() + { + const utils::nt::library self; + + STARTUPINFOA startup_info; + PROCESS_INFORMATION process_info; + + ZeroMemory(&startup_info, sizeof(startup_info)); + ZeroMemory(&process_info, sizeof(process_info)); + startup_info.cb = sizeof(startup_info); + + char current_dir[MAX_PATH]; + GetCurrentDirectoryA(sizeof(current_dir), current_dir); + auto* const command_line = GetCommandLineA(); + + CreateProcessA(self.get_path().data(), command_line, nullptr, nullptr, false, NULL, nullptr, current_dir, + &startup_info, &process_info); + + if (process_info.hThread && process_info.hThread != INVALID_HANDLE_VALUE) CloseHandle(process_info.hThread); + if (process_info.hProcess && process_info.hProcess != INVALID_HANDLE_VALUE) CloseHandle(process_info.hProcess); + } + + void terminate(const uint32_t code) + { + TerminateProcess(GetCurrentProcess(), code); + } +} diff --git a/src/common/utils/nt.hpp b/src/common/utils/nt.hpp new file mode 100644 index 00000000..86001bea --- /dev/null +++ b/src/common/utils/nt.hpp @@ -0,0 +1,110 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN +#include + +// min and max is required by gdi, therefore NOMINMAX won't work +#ifdef max +#undef max +#endif + +#ifdef min +#undef min +#endif + +#include +#include +#include + +namespace utils::nt +{ + class library final + { + public: + static library load(const std::string& name); + static library load(const std::filesystem::path& path); + static library get_by_address(void* address); + + library(); + explicit library(const std::string& name); + explicit library(HMODULE handle); + + library(const library& a) : module_(a.module_) + { + } + + bool operator!=(const library& obj) const { return !(*this == obj); }; + bool operator==(const library& obj) const; + + operator bool() const; + operator HMODULE() const; + + void unprotect() const; + void* get_entry_point() const; + size_t get_relative_entry_point() const; + + bool is_valid() const; + std::string get_name() const; + std::string get_path() const; + std::string get_folder() const; + std::uint8_t* get_ptr() const; + void free(); + + HMODULE get_handle() const; + + template + T get_proc(const std::string& process) const + { + if (!this->is_valid()) T{}; + return reinterpret_cast(GetProcAddress(this->module_, process.data())); + } + + template + std::function get(const std::string& process) const + { + if (!this->is_valid()) return std::function(); + return static_cast(this->get_proc(process)); + } + + template + T invoke(const std::string& process, Args ... args) const + { + auto method = this->get(process); + if (method) return method(args...); + return T(); + } + + template + T invoke_pascal(const std::string& process, Args ... args) const + { + auto method = this->get(process); + if (method) return method(args...); + return T(); + } + + template + T invoke_this(const std::string& process, void* this_ptr, Args ... args) const + { + auto method = this->get(this_ptr, process); + if (method) return method(args...); + return T(); + } + + std::vector get_section_headers() const; + + PIMAGE_NT_HEADERS get_nt_headers() const; + PIMAGE_DOS_HEADER get_dos_header() const; + PIMAGE_OPTIONAL_HEADER get_optional_header() const; + + void** get_iat_entry(const std::string& module_name, const std::string& proc_name) const; + + private: + HMODULE module_; + }; + + __declspec(noreturn) void raise_hard_exception(); + std::string load_resource(int id); + + void relaunch_self(); + __declspec(noreturn) void terminate(uint32_t code = 0); +} diff --git a/src/common/utils/signature.cpp b/src/common/utils/signature.cpp new file mode 100644 index 00000000..9bb8c621 --- /dev/null +++ b/src/common/utils/signature.cpp @@ -0,0 +1,212 @@ +#include "signature.hpp" +#include +#include + +#include + +namespace utils::hook +{ + void signature::load_pattern(const std::string& pattern) + { + this->mask_.clear(); + this->pattern_.clear(); + + uint8_t nibble = 0; + auto has_nibble = false; + + for (auto val : pattern) + { + if (val == ' ') continue; + if (val == '?') + { + this->mask_.push_back(val); + this->pattern_.push_back(0); + } + else + { + if ((val < '0' || val > '9') && (val < 'A' || val > 'F') && (val < 'a' || val > 'f')) + { + throw std::runtime_error("Invalid pattern"); + } + + char str[] = {val, 0}; + const auto current_nibble = static_cast(strtol(str, nullptr, 16)); + + if (!has_nibble) + { + has_nibble = true; + nibble = current_nibble; + } + else + { + has_nibble = false; + const uint8_t byte = current_nibble | (nibble << 4); + + this->mask_.push_back('x'); + this->pattern_.push_back(byte); + } + } + } + + while (!this->mask_.empty() && this->mask_.back() == '?') + { + this->mask_.pop_back(); + this->pattern_.pop_back(); + } + + if (this->has_sse_support()) + { + while (this->pattern_.size() < 16) + { + this->pattern_.push_back(0); + } + } + + if (has_nibble) + { + throw std::runtime_error("Invalid pattern"); + } + } + + std::vector signature::process_range(uint8_t* start, const size_t length) const + { + if (this->has_sse_support()) return this->process_range_vectorized(start, length); + return this->process_range_linear(start, length); + } + + std::vector signature::process_range_linear(uint8_t* start, const size_t length) const + { + std::vector result; + + for (size_t i = 0; i < length; ++i) + { + const auto address = start + i; + + size_t j = 0; + for (; j < this->mask_.size(); ++j) + { + if (this->mask_[j] != '?' && this->pattern_[j] != address[j]) + { + break; + } + } + + if (j == this->mask_.size()) + { + result.push_back(size_t(address)); + } + } + + return result; + } + + std::vector signature::process_range_vectorized(uint8_t* start, const size_t length) const + { + std::vector result; + __declspec(align(16)) char desired_mask[16] = {0}; + + for (size_t i = 0; i < this->mask_.size(); i++) + { + desired_mask[i / 8] |= (this->mask_[i] == '?' ? 0 : 1) << i % 8; + } + + const auto mask = _mm_load_si128(reinterpret_cast(desired_mask)); + const auto comparand = _mm_loadu_si128(reinterpret_cast(this->pattern_.data())); + + for (size_t i = 0; i < length; ++i) + { + const auto address = start + i; + const auto value = _mm_loadu_si128(reinterpret_cast(address)); + const auto comparison = _mm_cmpestrm(value, 16, comparand, static_cast(this->mask_.size()), + _SIDD_CMP_EQUAL_EACH); + + const auto matches = _mm_and_si128(mask, comparison); + const auto equivalence = _mm_xor_si128(mask, matches); + + if (_mm_test_all_zeros(equivalence, equivalence)) + { + result.push_back(size_t(address)); + } + } + + return result; + } + + signature::signature_result signature::process() const + { + const auto range = this->length_ - this->mask_.size(); + const auto cores = std::max(1u, std::thread::hardware_concurrency()); + + if (range <= cores * 10ull) return this->process_serial(); + return this->process_parallel(); + } + + signature::signature_result signature::process_serial() const + { + const auto sub = this->has_sse_support() ? 16 : this->mask_.size(); + return {this->process_range(this->start_, this->length_ - sub)}; + } + + signature::signature_result signature::process_parallel() const + { + const auto sub = this->has_sse_support() ? 16 : this->mask_.size(); + const auto range = this->length_ - sub; + const auto cores = std::max(1u, std::thread::hardware_concurrency() / 2); + // Only use half of the available cores + const auto grid = range / cores; + + std::mutex mutex; + std::vector result; + std::vector threads; + + for (auto i = 0u; i < cores; ++i) + { + const auto start = this->start_ + (grid * i); + const auto length = (i + 1 == cores) ? (this->start_ + this->length_ - sub) - start : grid; + threads.emplace_back([&, start, length]() + { + auto local_result = this->process_range(start, length); + if (local_result.empty()) return; + + std::lock_guard _(mutex); + for (const auto& address : local_result) + { + result.push_back(address); + } + }); + } + + for (auto& t : threads) + { + if (t.joinable()) + { + t.join(); + } + } + + std::sort(result.begin(), result.end()); + return {std::move(result)}; + } + + bool signature::has_sse_support() const + { + if (this->mask_.size() <= 16) + { + int cpu_id[4]; + __cpuid(cpu_id, 0); + + if (cpu_id[0] >= 1) + { + __cpuidex(cpu_id, 1, 0); + return (cpu_id[2] & (1 << 20)) != 0; + } + } + + return false; + } +} + +utils::hook::signature::signature_result operator"" _sig(const char* str, const size_t len) +{ + return utils::hook::signature(std::string(str, len)).process(); +} diff --git a/src/common/utils/signature.hpp b/src/common/utils/signature.hpp new file mode 100644 index 00000000..a3728327 --- /dev/null +++ b/src/common/utils/signature.hpp @@ -0,0 +1,73 @@ +#pragma once +#include "nt.hpp" +#include + +namespace utils::hook +{ + class signature final + { + public: + class signature_result + { + public: + signature_result(std::vector&& matches) : matches_(std::move(matches)) + { + } + + [[nodiscard]] uint8_t* get(const size_t index) const + { + if (index >= this->count()) + { + throw std::runtime_error("Invalid index"); + } + + return reinterpret_cast(this->matches_[index]); + } + + [[nodiscard]] size_t count() const + { + return this->matches_.size(); + } + + private: + std::vector matches_; + }; + + explicit signature(const std::string& pattern, const nt::library library = {}) + : signature(pattern, library.get_ptr(), library.get_optional_header()->SizeOfImage) + { + } + + signature(const std::string& pattern, void* start, void* end) + : signature(pattern, start, size_t(end) - size_t(start)) + { + } + + signature(const std::string& pattern, void* start, const size_t length) + : start_(static_cast(start)), length_(length) + { + this->load_pattern(pattern); + } + + signature_result process() const; + + private: + std::string mask_; + std::basic_string pattern_; + + uint8_t* start_; + size_t length_; + + void load_pattern(const std::string& pattern); + + signature_result process_parallel() const; + signature_result process_serial() const; + std::vector process_range(uint8_t* start, size_t length) const; + std::vector process_range_linear(uint8_t* start, size_t length) const; + std::vector process_range_vectorized(uint8_t* start, size_t length) const; + + bool has_sse_support() const; + }; +} + +utils::hook::signature::signature_result operator"" _sig(const char* str, size_t len); diff --git a/src/common/utils/smbios.cpp b/src/common/utils/smbios.cpp new file mode 100644 index 00000000..a3282c28 --- /dev/null +++ b/src/common/utils/smbios.cpp @@ -0,0 +1,94 @@ +#include "smbios.hpp" +#include "memory.hpp" + +#define WIN32_LEAN_AND_MEAN +#include +#include + +namespace utils::smbios +{ + namespace + { +#pragma warning(push) +#pragma warning(disable: 4200) + struct RawSMBIOSData + { + BYTE Used20CallingMethod; + BYTE SMBIOSMajorVersion; + BYTE SMBIOSMinorVersion; + BYTE DmiRevision; + DWORD Length; + BYTE SMBIOSTableData[]; + }; + + typedef struct + { + BYTE type; + BYTE length; + WORD handle; + } dmi_header; +#pragma warning(pop) + + std::vector get_smbios_data() + { + DWORD size = 0; + std::vector data{}; + + size = GetSystemFirmwareTable('RSMB', 0, nullptr, size); + data.resize(size); + GetSystemFirmwareTable('RSMB', 0, data.data(), size); + + return data; + } + + std::string parse_uuid(const uint8_t* data) + { + if (utils::memory::is_set(data, 0, 16) || utils::memory::is_set(data, -1, 16)) + { + return {}; + } + + char uuid[16] = {0}; + *reinterpret_cast(uuid + 0) = + _byteswap_ulong(*reinterpret_cast(data + 0)); + *reinterpret_cast(uuid + 4) = + _byteswap_ushort(*reinterpret_cast(data + 4)); + *reinterpret_cast(uuid + 6) = + _byteswap_ushort(*reinterpret_cast(data + 6)); + memcpy(uuid + 8, data + 8, 8); + + return std::string(uuid, sizeof(uuid)); + } + } + + std::string get_uuid() + { + auto smbios_data = get_smbios_data(); + auto* raw_data = reinterpret_cast(smbios_data.data()); + + auto* data = raw_data->SMBIOSTableData; + for (DWORD i = 0; i + sizeof(dmi_header) < raw_data->Length;) + { + auto* header = reinterpret_cast(data + i); + if (header->length < 4) + { + return {}; + } + + if (header->type == 0x01 && header->length >= 0x19) + { + return parse_uuid(data + i + 0x8); + } + + i += header->length; + while ((i + 1) < raw_data->Length && *reinterpret_cast(data + i) != 0) + { + ++i; + } + + i += 2; + } + + return {}; + } +} diff --git a/src/common/utils/smbios.hpp b/src/common/utils/smbios.hpp new file mode 100644 index 00000000..bbd1939d --- /dev/null +++ b/src/common/utils/smbios.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace utils::smbios +{ + std::string get_uuid(); +} diff --git a/src/common/utils/string.cpp b/src/common/utils/string.cpp new file mode 100644 index 00000000..42486cf3 --- /dev/null +++ b/src/common/utils/string.cpp @@ -0,0 +1,186 @@ +#include "string.hpp" +#include +#include +#include + +#include "nt.hpp" + +namespace utils::string +{ + const char* va(const char* fmt, ...) + { + static thread_local va_provider<8, 256> provider; + + va_list ap; + va_start(ap, fmt); + + const char* result = provider.get(fmt, ap); + + va_end(ap); + return result; + } + + std::vector split(const std::string& s, const char delim) + { + std::stringstream ss(s); + std::string item; + std::vector elems; + + while (std::getline(ss, item, delim)) + { + elems.push_back(item); // elems.push_back(std::move(item)); // if C++11 (based on comment from @mchiasson) + } + + return elems; + } + + std::string to_lower(std::string text) + { + std::transform(text.begin(), text.end(), text.begin(), [](const char input) + { + return static_cast(tolower(input)); + }); + + return text; + } + + std::string to_upper(std::string text) + { + std::transform(text.begin(), text.end(), text.begin(), [](const char input) + { + return static_cast(toupper(input)); + }); + + return text; + } + + bool starts_with(const std::string& text, const std::string& substring) + { + return text.find(substring) == 0; + } + + bool ends_with(const std::string& text, const std::string& substring) + { + if (substring.size() > text.size()) return false; + return std::equal(substring.rbegin(), substring.rend(), text.rbegin()); + } + + std::string dump_hex(const std::string& data, const std::string& separator) + { + std::string result; + + for (unsigned int i = 0; i < data.size(); ++i) + { + if (i > 0) + { + result.append(separator); + } + + result.append(va("%02X", data[i] & 0xFF)); + } + + return result; + } + + std::string get_clipboard_data() + { + if (OpenClipboard(nullptr)) + { + std::string data; + + auto* const clipboard_data = GetClipboardData(1u); + if (clipboard_data) + { + auto* const cliptext = static_cast(GlobalLock(clipboard_data)); + if (cliptext) + { + data.append(cliptext); + GlobalUnlock(clipboard_data); + } + } + CloseClipboard(); + + return data; + } + return {}; + } + + void strip(const char* in, char* out, int max) + { + if (!in || !out) return; + + max--; + auto current = 0; + while (*in != 0 && current < max) + { + const auto color_index = (*(in + 1) - 48) >= 0xC ? 7 : (*(in + 1) - 48); + + if (*in == '^' && (color_index != 7 || *(in + 1) == '7')) + { + ++in; + } + else + { + *out = *in; + ++out; + ++current; + } + + ++in; + } + *out = '\0'; + } + +#pragma warning(push) +#pragma warning(disable: 4100) + std::string convert(const std::wstring& wstr) + { + std::string result; + result.reserve(wstr.size()); + + for (const auto& chr : wstr) + { + result.push_back(static_cast(chr)); + } + + return result; + } + + std::wstring convert(const std::string& str) + { + std::wstring result; + result.reserve(str.size()); + + for (const auto& chr : str) + { + result.push_back(static_cast(chr)); + } + + return result; + } +#pragma warning(pop) + + std::string replace(std::string str, const std::string& from, const std::string& to) + { + if (from.empty()) + { + return str; + } + + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != std::string::npos) + { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); + } + + return str; + } + + bool match_compare(const std::string& input, const std::string& text, const bool exact) + { + if (exact && text == input) return true; + if (!exact && text.find(input) != std::string::npos) return true; + return false; + } +} diff --git a/src/common/utils/string.hpp b/src/common/utils/string.hpp new file mode 100644 index 00000000..322ce9ce --- /dev/null +++ b/src/common/utils/string.hpp @@ -0,0 +1,102 @@ +#pragma once +#include "memory.hpp" +#include + +#ifndef ARRAYSIZE +template +size_t ARRAYSIZE(Type (&)[n]) { return n; } +#endif + +namespace utils::string +{ + template + class va_provider final + { + public: + static_assert(Buffers != 0 && MinBufferSize != 0, "Buffers and MinBufferSize mustn't be 0"); + + va_provider() : current_buffer_(0) + { + } + + char* get(const char* format, const va_list ap) + { + ++this->current_buffer_ %= ARRAYSIZE(this->string_pool_); + auto entry = &this->string_pool_[this->current_buffer_]; + + if (!entry->size || !entry->buffer) + { + throw std::runtime_error("String pool not initialized"); + } + + while (true) + { + const int res = vsnprintf_s(entry->buffer, entry->size, _TRUNCATE, format, ap); + if (res > 0) break; // Success + if (res == 0) return nullptr; // Error + + entry->double_size(); + } + + return entry->buffer; + } + + private: + class entry final + { + public: + explicit entry(const size_t _size = MinBufferSize) : size(_size), buffer(nullptr) + { + if (this->size < MinBufferSize) this->size = MinBufferSize; + this->allocate(); + } + + ~entry() + { + if (this->buffer) memory::get_allocator()->free(this->buffer); + this->size = 0; + this->buffer = nullptr; + } + + void allocate() + { + if (this->buffer) memory::get_allocator()->free(this->buffer); + this->buffer = memory::get_allocator()->allocate_array(this->size + 1); + } + + void double_size() + { + this->size *= 2; + this->allocate(); + } + + size_t size; + char* buffer; + }; + + size_t current_buffer_; + entry string_pool_[Buffers]; + }; + + const char* va(const char* fmt, ...); + + std::vector split(const std::string& s, char delim); + + std::string to_lower(std::string text); + std::string to_upper(std::string text); + bool starts_with(const std::string& text, const std::string& substring); + bool ends_with(const std::string& text, const std::string& substring); + + std::string dump_hex(const std::string& data, const std::string& separator = " "); + + std::string get_clipboard_data(); + + void strip(const char* in, char* out, int max); + + std::string convert(const std::wstring& wstr); + std::wstring convert(const std::string& str); + + std::string replace(std::string str, const std::string& from, const std::string& to); + + bool match_compare(const std::string& input, const std::string& text, const bool exact); +} diff --git a/src/common/utils/thread.cpp b/src/common/utils/thread.cpp new file mode 100644 index 00000000..7239b536 --- /dev/null +++ b/src/common/utils/thread.cpp @@ -0,0 +1,128 @@ +#include "thread.hpp" +#include "string.hpp" + +#include + +#include + +namespace utils::thread +{ + bool set_name(const HANDLE t, const std::string& name) + { + const nt::library kernel32("kernel32.dll"); + if (!kernel32) + { + return false; + } + + const auto set_description = kernel32.get_proc("SetThreadDescription"); + if (!set_description) + { + return false; + } + + return SUCCEEDED(set_description(t, string::convert(name).data())); + } + + bool set_name(const DWORD id, const std::string& name) + { + auto* const t = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, id); + if (!t) return false; + + const auto _ = gsl::finally([t]() + { + CloseHandle(t); + }); + + return set_name(t, name); + } + + bool set_name(std::thread& t, const std::string& name) + { + return set_name(t.native_handle(), name); + } + + bool set_name(const std::string& name) + { + return set_name(GetCurrentThread(), name); + } + + std::vector get_thread_ids() + { + auto* const h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, GetCurrentProcessId()); + if (h == INVALID_HANDLE_VALUE) + { + return {}; + } + + const auto _ = gsl::finally([h]() + { + CloseHandle(h); + }); + + THREADENTRY32 entry{}; + entry.dwSize = sizeof(entry); + if (!Thread32First(h, &entry)) + { + return {}; + } + + std::vector ids{}; + + do + { + const auto check_size = entry.dwSize < FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + + sizeof(entry.th32OwnerProcessID); + entry.dwSize = sizeof(entry); + + if (check_size && entry.th32OwnerProcessID == GetCurrentProcessId()) + { + ids.emplace_back(entry.th32ThreadID); + } + } + while (Thread32Next(h, &entry)); + + return ids; + } + + void for_each_thread(const std::function& callback) + { + const auto ids = get_thread_ids(); + + for (const auto& id : ids) + { + auto* const thread = OpenThread(THREAD_ALL_ACCESS, FALSE, id); + if (thread != nullptr) + { + const auto _ = gsl::finally([thread]() + { + CloseHandle(thread); + }); + + callback(thread); + } + } + } + + void suspend_other_threads() + { + for_each_thread([](const HANDLE thread) + { + if (GetThreadId(thread) != GetCurrentThreadId()) + { + SuspendThread(thread); + } + }); + } + + void resume_other_threads() + { + for_each_thread([](const HANDLE thread) + { + if (GetThreadId(thread) != GetCurrentThreadId()) + { + ResumeThread(thread); + } + }); + } +} diff --git a/src/common/utils/thread.hpp b/src/common/utils/thread.hpp new file mode 100644 index 00000000..4ea3598c --- /dev/null +++ b/src/common/utils/thread.hpp @@ -0,0 +1,25 @@ +#pragma once +#include +#include "nt.hpp" + +namespace utils::thread +{ + bool set_name(HANDLE t, const std::string& name); + bool set_name(DWORD id, const std::string& name); + bool set_name(std::thread& t, const std::string& name); + bool set_name(const std::string& name); + + template + std::thread create_named_thread(const std::string& name, Args&&... args) + { + auto t = std::thread(std::forward(args)...); + set_name(t, name); + return t; + } + + std::vector get_thread_ids(); + void for_each_thread(const std::function& callback); + + void suspend_other_threads(); + void resume_other_threads(); +} diff --git a/src/runner/debugger.cpp b/src/runner/debugger.cpp new file mode 100644 index 00000000..d58149b7 --- /dev/null +++ b/src/runner/debugger.cpp @@ -0,0 +1,95 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include "debugger.hpp" + +namespace +{ + bool acquire_debug_privilege() + { + TOKEN_PRIVILEGES token_privileges; + ZeroMemory(&token_privileges, sizeof(token_privileges)); + token_privileges.PrivilegeCount = 1; + + HANDLE token; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)) + { + return false; + } + + if (!LookupPrivilegeValue(nullptr, SE_DEBUG_NAME, &token_privileges.Privileges[0].Luid)) + { + CloseHandle(token); + return false; + } + + token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + DWORD size; + if (!AdjustTokenPrivileges(token, FALSE, &token_privileges, 0, nullptr, &size)) + { + CloseHandle(token); + return false; + } + + return CloseHandle(token) != FALSE; + } +} + +debugger::debugger(const unsigned long process_id, const bool start) +{ + if (!start) + { + return; + } + + this->runner_ = std::thread([this, process_id]() + { + this->terminate_ = false; + this->run(process_id); + }); +} + +debugger::~debugger() +{ + this->terminate_ = true; + if (this->runner_.joinable()) + { + this->runner_.join(); + } +} + +void debugger::run(const unsigned long process_id) const +{ + acquire_debug_privilege(); + if (!DebugActiveProcess(process_id)) + { + return; + } + + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); + + DEBUG_EVENT event; + while (!this->terminate_ && WaitForDebugEvent(&event,INFINITE)) + { + if (event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) + { + ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); + continue; + } + + if (event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) + { + ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); + break; + } + +#ifdef DEV_BUILD + if (event.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) + { + OutputDebugStringA("Debugger attached!\n"); + } +#endif + + ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); + } +} diff --git a/src/runner/debugger.hpp b/src/runner/debugger.hpp new file mode 100644 index 00000000..99d1073e --- /dev/null +++ b/src/runner/debugger.hpp @@ -0,0 +1,15 @@ +#pragma once +#include + +class debugger +{ +public: + debugger(unsigned long process_id, bool start); + ~debugger(); + +private: + volatile bool terminate_ = false; + std::thread runner_; + + void run(unsigned long process_id) const; +}; diff --git a/src/runner/resource.rc b/src/runner/resource.rc new file mode 100644 index 00000000..ba86c6f4 --- /dev/null +++ b/src/runner/resource.rc @@ -0,0 +1,100 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +2 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "X Labs" + VALUE "FileDescription", "Steam mod runner" + VALUE "FileVersion", "1.0.0.0" + VALUE "InternalName", "Runner" + VALUE "LegalCopyright", "All rights reserved." + VALUE "OriginalFilename", "runner.exe" + VALUE "ProductName", "runner" + VALUE "ProductVersion", "1.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +///////////////////////////////////////////////////////////////////////////// +// +// Binary Data +// + +102 ICON "../client/resources/icon.ico" + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/runner/runner.cpp b/src/runner/runner.cpp new file mode 100644 index 00000000..01c32d2e --- /dev/null +++ b/src/runner/runner.cpp @@ -0,0 +1,26 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include "debugger.hpp" + +int __stdcall WinMain(HINSTANCE, HINSTANCE, PSTR, int) +{ + const auto* const command = "-proc "; + const char* parent_proc = strstr(GetCommandLineA(), command); + + if (parent_proc) + { + const auto pid = DWORD(atoi(parent_proc + strlen(command))); + auto* const process_handle = OpenProcess(SYNCHRONIZE, FALSE, pid); + if (process_handle) + { + //debugger _(pid, strstr(GetCommandLineA(), "-debug ") != nullptr); + WaitForSingleObject(process_handle, INFINITE); + CloseHandle(process_handle); + return 0; + } + } + + return 1; +} diff --git a/src/tlsdll/dllmain.cpp b/src/tlsdll/dllmain.cpp new file mode 100644 index 00000000..56d31a66 --- /dev/null +++ b/src/tlsdll/dllmain.cpp @@ -0,0 +1,7 @@ +#define TLS_PAYLOAD_SIZE 0x2000 +thread_local char tls_data[TLS_PAYLOAD_SIZE]; + +__declspec(dllexport) void* get_tls_data() +{ + return &tls_data[0]; +} diff --git a/src/tlsdll/resource.rc b/src/tlsdll/resource.rc new file mode 100644 index 00000000..2a778f5f --- /dev/null +++ b/src/tlsdll/resource.rc @@ -0,0 +1,100 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +2 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "X Labs" + VALUE "FileDescription", "TLS index allocation dll" + VALUE "FileVersion", "1.0.0.0" + VALUE "InternalName", "TLS DLL" + VALUE "LegalCopyright", "All rights reserved." + VALUE "OriginalFilename", "tlsdll.dll" + VALUE "ProductName", "tlsdll" + VALUE "ProductVersion", "1.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +///////////////////////////////////////////////////////////////////////////// +// +// Binary Data +// + +// Nothing here + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/tools/premake5.exe b/tools/premake5.exe new file mode 100644 index 00000000..c73da1fb Binary files /dev/null and b/tools/premake5.exe differ diff --git a/tools/protoc.exe b/tools/protoc.exe new file mode 100644 index 00000000..87bf60b6 Binary files /dev/null and b/tools/protoc.exe differ