diff --git a/DDrawCompat/Common/Disasm.cpp b/DDrawCompat/Common/Disasm.cpp new file mode 100644 index 0000000..832e915 --- /dev/null +++ b/DDrawCompat/Common/Disasm.cpp @@ -0,0 +1,656 @@ +#include + +namespace +{ + enum OpcodeFlags + { + OF_NONE = 0, + OF_PREFIX = 1 << 0, + OF_PREFIX_OS = 1 << 1, + OF_PREFIX_AS = 1 << 2, + OF_ESCAPE = 1 << 3, + OF_MODRM = 1 << 4, + OF_AS = 1 << 5, + OF_IB = 1 << 6, + OF_IW = 1 << 7, + OF_IW_ID = 1 << 8, + OF_ICOND = 1 << 9, + OF_CB = 1 << 10, + OF_CW_CD = 1 << 11, + OF_CD_CP = 1 << 12, + OF_INVALID = 1 << 13 + }; + + const unsigned g_opcodeFlags[256] = { + OF_MODRM, // 00 /r + OF_MODRM, // 01 /r + OF_MODRM, // 02 /r + OF_MODRM, // 03 /r + OF_IB, // 04 ib + OF_IW_ID, // 05 iw/id + OF_NONE, // 06 + OF_NONE, // 07 + OF_MODRM, // 08 /r + OF_MODRM, // 09 /r + OF_MODRM, // 0A /r + OF_MODRM, // 0B /r + OF_IB, // 0C ib + OF_IW_ID, // 0D iw/id + OF_NONE, // 0E + OF_ESCAPE, // 0F + OF_MODRM, // 10 /r + OF_MODRM, // 11 /r + OF_MODRM, // 12 /r + OF_MODRM, // 13 /r + OF_IB, // 14 ib + OF_IW_ID, // 15 iw/id + OF_NONE, // 16 + OF_NONE, // 17 + OF_MODRM, // 18 /r + OF_MODRM, // 19 /r + OF_MODRM, // 1A /r + OF_MODRM, // 1B /r + OF_IB, // 1C ib + OF_IW_ID, // 1D iw/id + OF_NONE, // 1E + OF_NONE, // 1F + OF_MODRM, // 20 /r + OF_MODRM, // 21 /r + OF_MODRM, // 22 /r + OF_MODRM, // 23 /r + OF_IB, // 24 ib + OF_IW_ID, // 25 iw/id + OF_PREFIX, // 26 + OF_NONE, // 27 + OF_MODRM, // 28 /r + OF_MODRM, // 29 /r + OF_MODRM, // 2A /r + OF_MODRM, // 2B /r + OF_IB, // 2C ib + OF_IW_ID, // 2D iw/id + OF_PREFIX, // 2E + OF_NONE, // 2F + OF_MODRM, // 30 /r + OF_MODRM, // 31 /r + OF_MODRM, // 32 /r + OF_MODRM, // 33 /r + OF_IB, // 34 ib + OF_IW_ID, // 35 iw/id + OF_PREFIX, // 36 + OF_NONE, // 37 + OF_MODRM, // 38 /r + OF_MODRM, // 39 /r + OF_MODRM, // 3A /r + OF_MODRM, // 3B /r + OF_IB, // 3C ib + OF_IW_ID, // 3D iw/id + OF_PREFIX, // 3E + OF_NONE, // 3F + OF_NONE, // 40 (40+rw/rd) + OF_NONE, // 41 (40+rw/rd) + OF_NONE, // 42 (40+rw/rd) + OF_NONE, // 43 (40+rw/rd) + OF_NONE, // 44 (40+rw/rd) + OF_NONE, // 45 (40+rw/rd) + OF_NONE, // 46 (40+rw/rd) + OF_NONE, // 47 (40+rw/rd) + OF_NONE, // 48 (48+rw/rd) + OF_NONE, // 49 (48+rw/rd) + OF_NONE, // 4A (48+rw/rd) + OF_NONE, // 4B (48+rw/rd) + OF_NONE, // 4C (48+rw/rd) + OF_NONE, // 4D (48+rw/rd) + OF_NONE, // 4E (48+rw/rd) + OF_NONE, // 4F (48+rw/rd) + OF_NONE, // 50 (50+rw/rd) + OF_NONE, // 51 (50+rw/rd) + OF_NONE, // 52 (50+rw/rd) + OF_NONE, // 53 (50+rw/rd) + OF_NONE, // 54 (50+rw/rd) + OF_NONE, // 55 (50+rw/rd) + OF_NONE, // 56 (50+rw/rd) + OF_NONE, // 57 (50+rw/rd) + OF_NONE, // 58 (58+rw/rd) + OF_NONE, // 59 (58+rw/rd) + OF_NONE, // 5A (58+rw/rd) + OF_NONE, // 5B (58+rw/rd) + OF_NONE, // 5C (58+rw/rd) + OF_NONE, // 5D (58+rw/rd) + OF_NONE, // 5E (58+rw/rd) + OF_NONE, // 5F (58+rw/rd) + OF_NONE, // 60 + OF_NONE, // 61 + OF_MODRM, // 62 /r + OF_MODRM, // 63 /r + OF_PREFIX, // 64 + OF_PREFIX, // 65 + OF_PREFIX | OF_PREFIX_OS, // 66 + OF_PREFIX | OF_PREFIX_AS, // 67 + OF_IW_ID, // 68 iw/id + OF_MODRM | OF_IW_ID, // 69 /r iw/id + OF_IB, // 6A ib + OF_MODRM | OF_IB, // 6B /r ib + OF_NONE, // 6C + OF_NONE, // 6D + OF_NONE, // 6E + OF_NONE, // 6F + OF_CB, // 70 cb + OF_CB, // 71 cb + OF_CB, // 72 cb + OF_CB, // 73 cb + OF_CB, // 74 cb + OF_CB, // 75 cb + OF_CB, // 76 cb + OF_CB, // 77 cb + OF_CB, // 78 cb + OF_CB, // 79 cb + OF_CB, // 7A cb + OF_CB, // 7B cb + OF_CB, // 7C cb + OF_CB, // 7D cb + OF_CB, // 7E cb + OF_CB, // 7F cb + OF_MODRM | OF_IB, // 80 /r ib + OF_MODRM | OF_IW_ID, // 81 /r iw/id + OF_MODRM | OF_IB, // 82 /r ib + OF_MODRM | OF_IB, // 83 /r ib + OF_MODRM, // 84 /r + OF_MODRM, // 85 /r + OF_MODRM, // 86 /r + OF_MODRM, // 87 /r + OF_MODRM, // 88 /r + OF_MODRM, // 89 /r + OF_MODRM, // 8A /r + OF_MODRM, // 8B /r + OF_MODRM, // 8C /r + OF_MODRM, // 8D /r + OF_MODRM, // 8E /r + OF_MODRM, // 8F /r + OF_NONE, // 90 + OF_NONE, // 91 (90+rw/rd) + OF_NONE, // 92 (90+rw/rd) + OF_NONE, // 93 (90+rw/rd) + OF_NONE, // 94 (90+rw/rd) + OF_NONE, // 95 (90+rw/rd) + OF_NONE, // 96 (90+rw/rd) + OF_NONE, // 97 (90+rw/rd) + OF_NONE, // 98 + OF_NONE, // 99 + OF_CD_CP, // 9A cd/cp + OF_NONE, // 9B + OF_NONE, // 9C + OF_NONE, // 9D + OF_NONE, // 9E + OF_NONE, // 9F + OF_IW_ID | OF_AS, // A0 iw/id (AS) + OF_IW_ID | OF_AS, // A1 iw/id (AS) + OF_IW_ID | OF_AS, // A2 iw/id (AS) + OF_IW_ID | OF_AS, // A3 iw/id (AS) + OF_NONE, // A4 + OF_NONE, // A5 + OF_NONE, // A6 + OF_NONE, // A7 + OF_IB, // A8 ib + OF_IW_ID, // A9 iw/id + OF_NONE, // AA + OF_NONE, // AB + OF_NONE, // AC + OF_NONE, // AD + OF_NONE, // AE + OF_NONE, // AF + OF_IB, // B0 (B0+rb) ib + OF_IB, // B1 (B0+rb) ib + OF_IB, // B2 (B0+rb) ib + OF_IB, // B3 (B0+rb) ib + OF_IB, // B4 (B0+rb) ib + OF_IB, // B5 (B0+rb) ib + OF_IB, // B6 (B0+rb) ib + OF_IB, // B7 (B0+rb) ib + OF_IW_ID, // B8 (B8+rw/rd) iw/id + OF_IW_ID, // B9 (B8+rw/rd) iw/id + OF_IW_ID, // BA (B8+rw/rd) iw/id + OF_IW_ID, // BB (B8+rw/rd) iw/id + OF_IW_ID, // BC (B8+rw/rd) iw/id + OF_IW_ID, // BD (B8+rw/rd) iw/id + OF_IW_ID, // BE (B8+rw/rd) iw/id + OF_IW_ID, // BF (B8+rw/rd) iw/id + OF_MODRM | OF_IB, // C0 /r ib + OF_MODRM | OF_IB, // C1 /r ib + OF_IW, // C2 iw + OF_NONE, // C3 + OF_MODRM, // C4 /r + OF_MODRM, // C5 /r + OF_MODRM | OF_IB, // C6 /r ib + OF_MODRM | OF_IW_ID, // C7 /r iw/id + OF_IW | OF_IB, // C8 iw ib + OF_NONE, // C9 + OF_IW, // CA iw + OF_NONE, // CB + OF_NONE, // CC + OF_IB, // CD ib + OF_NONE, // CE + OF_NONE, // CF + OF_MODRM, // D0 /r + OF_MODRM, // D1 /r + OF_MODRM, // D2 /r + OF_MODRM, // D3 /r + OF_IB, // D4 ib + OF_IB, // D5 ib + OF_INVALID, // D6 ? + OF_NONE, // D7 + OF_MODRM, // D8 /r + OF_MODRM, // D9 /r + OF_MODRM, // DA /r + OF_MODRM, // DB /r + OF_MODRM, // DC /r + OF_MODRM, // DD /r + OF_MODRM, // DE /r + OF_MODRM, // DF /r + OF_CB, // E0 cb + OF_CB, // E1 cb + OF_CB, // E2 cb + OF_CB, // E3 cb + OF_IB, // E4 ib + OF_IB, // E5 ib + OF_IB, // E6 ib + OF_IB, // E7 ib + OF_CW_CD, // E8 cw/cd + OF_CW_CD, // E9 cw/cd + OF_CD_CP, // EA cd/cp + OF_CB, // EB cb + OF_NONE, // EC + OF_NONE, // ED + OF_NONE, // EE + OF_NONE, // EF + OF_PREFIX, // F0 + OF_NONE, // F1 + OF_PREFIX, // F2 + OF_PREFIX, // F3 + OF_NONE, // F4 + OF_NONE, // F5 + OF_MODRM | OF_IB | OF_ICOND, // F6 /r (ib) + OF_MODRM | OF_IW_ID | OF_ICOND, // F7 /r (iw/id) + OF_NONE, // F8 + OF_NONE, // F9 + OF_NONE, // FA + OF_NONE, // FB + OF_NONE, // FC + OF_NONE, // FD + OF_MODRM, // FE /r + OF_MODRM, // FF /r + }; + + const unsigned g_opcodeFlags0F[256] = { + OF_MODRM, // 0F 00 /r + OF_MODRM, // 0F 01 /r + OF_MODRM, // 0F 02 /r + OF_MODRM, // 0F 03 /r + OF_INVALID, // 0F 04 ? + OF_NONE, // 0F 05 + OF_NONE, // 0F 06 + OF_NONE, // 0F 07 + OF_NONE, // 0F 08 + OF_NONE, // 0F 09 + OF_INVALID, // 0F 0A ? + OF_NONE, // 0F 0B + OF_INVALID, // 0F 0C ? + OF_MODRM, // 0F 0D /r + OF_INVALID, // 0F 0E ? + OF_INVALID, // 0F 0F ? + OF_MODRM, // 0F 10 /r + OF_MODRM, // 0F 11 /r + OF_MODRM, // 0F 12 /r + OF_MODRM, // 0F 13 /r + OF_MODRM, // 0F 14 /r + OF_MODRM, // 0F 15 /r + OF_MODRM, // 0F 16 /r + OF_MODRM, // 0F 17 /r + OF_MODRM, // 0F 18 /r + OF_INVALID, // 0F 19 ? + OF_MODRM, // 0F 1A /r + OF_MODRM, // 0F 1B /r + OF_MODRM, // 0F 1C /r + OF_INVALID, // 0F 1D ? + OF_MODRM, // 0F 1E /r + OF_MODRM, // 0F 1F /r + OF_MODRM, // 0F 20 /r + OF_MODRM, // 0F 21 /r + OF_MODRM, // 0F 22 /r + OF_MODRM, // 0F 23 /r + OF_INVALID, // 0F 24 ? + OF_INVALID, // 0F 25 ? + OF_INVALID, // 0F 26 ? + OF_INVALID, // 0F 27 ? + OF_MODRM, // 0F 28 /r + OF_MODRM, // 0F 29 /r + OF_MODRM, // 0F 2A /r + OF_MODRM, // 0F 2B /r + OF_MODRM, // 0F 2C /r + OF_MODRM, // 0F 2D /r + OF_MODRM, // 0F 2E /r + OF_MODRM, // 0F 2F /r + OF_NONE, // 0F 30 + OF_NONE, // 0F 31 + OF_NONE, // 0F 32 + OF_NONE, // 0F 33 + OF_NONE, // 0F 34 + OF_NONE, // 0F 35 + OF_INVALID, // 0F 36 ? + OF_NONE, // 0F 37 + OF_ESCAPE | OF_MODRM, // 0F 38 xx /r + OF_INVALID, // 0F 39 ? + OF_ESCAPE | OF_MODRM | OF_IB, // 0F 3A xx /r ib + OF_INVALID, // 0F 3B ? + OF_INVALID, // 0F 3C ? + OF_INVALID, // 0F 3D ? + OF_INVALID, // 0F 3E ? + OF_INVALID, // 0F 3F ? + OF_MODRM, // 0F 40 /r + OF_MODRM, // 0F 41 /r + OF_MODRM, // 0F 42 /r + OF_MODRM, // 0F 43 /r + OF_MODRM, // 0F 44 /r + OF_MODRM, // 0F 45 /r + OF_MODRM, // 0F 46 /r + OF_MODRM, // 0F 47 /r + OF_MODRM, // 0F 48 /r + OF_MODRM, // 0F 49 /r + OF_MODRM, // 0F 4A /r + OF_MODRM, // 0F 4B /r + OF_MODRM, // 0F 4C /r + OF_MODRM, // 0F 4D /r + OF_MODRM, // 0F 4E /r + OF_MODRM, // 0F 4F /r + OF_MODRM, // 0F 50 /r + OF_MODRM, // 0F 51 /r + OF_MODRM, // 0F 52 /r + OF_MODRM, // 0F 53 /r + OF_MODRM, // 0F 54 /r + OF_MODRM, // 0F 55 /r + OF_MODRM, // 0F 56 /r + OF_MODRM, // 0F 57 /r + OF_MODRM, // 0F 58 /r + OF_MODRM, // 0F 59 /r + OF_MODRM, // 0F 5A /r + OF_MODRM, // 0F 5B /r + OF_MODRM, // 0F 5C /r + OF_MODRM, // 0F 5D /r + OF_MODRM, // 0F 5E /r + OF_MODRM, // 0F 5F /r + OF_MODRM, // 0F 60 /r + OF_MODRM, // 0F 61 /r + OF_MODRM, // 0F 62 /r + OF_MODRM, // 0F 63 /r + OF_MODRM, // 0F 64 /r + OF_MODRM, // 0F 65 /r + OF_MODRM, // 0F 66 /r + OF_MODRM, // 0F 67 /r + OF_MODRM, // 0F 68 /r + OF_MODRM, // 0F 69 /r + OF_MODRM, // 0F 6A /r + OF_MODRM, // 0F 6B /r + OF_MODRM, // 0F 6C /r + OF_MODRM, // 0F 6D /r + OF_MODRM, // 0F 6E /r + OF_MODRM, // 0F 6F /r + OF_MODRM | OF_IB, // 0F 70 /r ib + OF_MODRM | OF_IB, // 0F 71 /r ib + OF_MODRM | OF_IB, // 0F 72 /r ib + OF_MODRM | OF_IB, // 0F 73 /r ib + OF_MODRM, // 0F 74 /r + OF_MODRM, // 0F 75 /r + OF_MODRM, // 0F 76 /r + OF_NONE, // 0F 77 + OF_INVALID, // 0F 78 ? + OF_INVALID, // 0F 79 ? + OF_INVALID, // 0F 7A ? + OF_INVALID, // 0F 7B ? + OF_MODRM, // 0F 7C /r + OF_MODRM, // 0F 7D /r + OF_MODRM, // 0F 7E /r + OF_MODRM, // 0F 7F /r + OF_CW_CD, // 0F 80 cw/cd + OF_CW_CD, // 0F 81 cw/cd + OF_CW_CD, // 0F 82 cw/cd + OF_CW_CD, // 0F 83 cw/cd + OF_CW_CD, // 0F 84 cw/cd + OF_CW_CD, // 0F 85 cw/cd + OF_CW_CD, // 0F 86 cw/cd + OF_CW_CD, // 0F 87 cw/cd + OF_CW_CD, // 0F 88 cw/cd + OF_CW_CD, // 0F 89 cw/cd + OF_CW_CD, // 0F 8A cw/cd + OF_CW_CD, // 0F 8B cw/cd + OF_CW_CD, // 0F 8C cw/cd + OF_CW_CD, // 0F 8D cw/cd + OF_CW_CD, // 0F 8E cw/cd + OF_CW_CD, // 0F 8F cw/cd + OF_MODRM, // 0F 90 /r + OF_MODRM, // 0F 91 /r + OF_MODRM, // 0F 92 /r + OF_MODRM, // 0F 93 /r + OF_MODRM, // 0F 94 /r + OF_MODRM, // 0F 95 /r + OF_MODRM, // 0F 96 /r + OF_MODRM, // 0F 97 /r + OF_MODRM, // 0F 98 /r + OF_MODRM, // 0F 99 /r + OF_MODRM, // 0F 9A /r + OF_MODRM, // 0F 9B /r + OF_MODRM, // 0F 9C /r + OF_MODRM, // 0F 9D /r + OF_MODRM, // 0F 9E /r + OF_MODRM, // 0F 9F /r + OF_NONE, // 0F A0 + OF_NONE, // 0F A1 + OF_NONE, // 0F A2 + OF_MODRM, // 0F A3 /r + OF_MODRM | OF_IB, // 0F A4 /r ib + OF_MODRM, // 0F A5 /r + OF_INVALID, // 0F A6 ? + OF_INVALID, // 0F A7 ? + OF_NONE, // 0F A8 + OF_NONE, // 0F A9 + OF_NONE, // 0F AA + OF_MODRM, // 0F AB /r + OF_MODRM | OF_IB, // 0F AC /r ib + OF_MODRM, // 0F AD /r + OF_MODRM, // 0F AE /r + OF_MODRM, // 0F AF /r + OF_MODRM, // 0F B0 /r + OF_MODRM, // 0F B1 /r + OF_MODRM, // 0F B2 /r + OF_MODRM, // 0F B3 /r + OF_MODRM, // 0F B4 /r + OF_MODRM, // 0F B5 /r + OF_MODRM, // 0F B6 /r + OF_MODRM, // 0F B7 /r + OF_MODRM, // 0F B8 /r + OF_MODRM, // 0F B9 /r + OF_MODRM | OF_IB, // 0F BA /r ib + OF_MODRM, // 0F BB /r + OF_MODRM, // 0F BC /r + OF_MODRM, // 0F BD /r + OF_MODRM, // 0F BE /r + OF_MODRM, // 0F BF /r + OF_MODRM, // 0F C0 /r + OF_MODRM, // 0F C1 /r + OF_MODRM | OF_IB, // 0F C2 /r ib + OF_MODRM, // 0F C3 /r + OF_MODRM | OF_IB, // 0F C4 /r ib + OF_MODRM | OF_IB, // 0F C5 /r ib + OF_MODRM | OF_IB, // 0F C6 /r ib + OF_MODRM, // 0F C7 /r + OF_NONE, // 0F C8 (C8+rd) + OF_NONE, // 0F C9 (C8+rd) + OF_NONE, // 0F CA (C8+rd) + OF_NONE, // 0F C8 (C8+rd) + OF_NONE, // 0F CC (C8+rd) + OF_NONE, // 0F CD (C8+rd) + OF_NONE, // 0F CE (C8+rd) + OF_NONE, // 0F CF (C8+rd) + OF_MODRM, // 0F D0 /r + OF_MODRM, // 0F D1 /r + OF_MODRM, // 0F D2 /r + OF_MODRM, // 0F D3 /r + OF_MODRM, // 0F D4 /r + OF_MODRM, // 0F D5 /r + OF_MODRM, // 0F D6 /r + OF_MODRM, // 0F D7 /r + OF_MODRM, // 0F D8 /r + OF_MODRM, // 0F D9 /r + OF_MODRM, // 0F DA /r + OF_MODRM, // 0F DB /r + OF_MODRM, // 0F DC /r + OF_MODRM, // 0F DD /r + OF_MODRM, // 0F DE /r + OF_MODRM, // 0F DF /r + OF_MODRM, // 0F E0 /r + OF_MODRM, // 0F E1 /r + OF_MODRM, // 0F E2 /r + OF_MODRM, // 0F E3 /r + OF_MODRM, // 0F E4 /r + OF_MODRM, // 0F E5 /r + OF_MODRM, // 0F E6 /r + OF_MODRM, // 0F E7 /r + OF_MODRM, // 0F E8 /r + OF_MODRM, // 0F E9 /r + OF_MODRM, // 0F EA /r + OF_MODRM, // 0F EB /r + OF_MODRM, // 0F EC /r + OF_MODRM, // 0F ED /r + OF_MODRM, // 0F EE /r + OF_MODRM, // 0F EF /r + OF_MODRM, // 0F F0 /r + OF_MODRM, // 0F F1 /r + OF_MODRM, // 0F F2 /r + OF_MODRM, // 0F F3 /r + OF_MODRM, // 0F F4 /r + OF_MODRM, // 0F F5 /r + OF_MODRM, // 0F F6 /r + OF_MODRM, // 0F F7 /r + OF_MODRM, // 0F F8 /r + OF_MODRM, // 0F F9 /r + OF_MODRM, // 0F FA /r + OF_MODRM, // 0F FB /r + OF_MODRM, // 0F FC /r + OF_MODRM, // 0F FD /r + OF_MODRM, // 0F FE /r + OF_MODRM // 0F FF /r + }; +} + +namespace Compat +{ + unsigned getInstructionLength(const void* instruction) + { + auto instr = static_cast(instruction); + unsigned prefixFlags = 0; + unsigned opcodeFlags = g_opcodeFlags[instr[0]]; + unsigned length = 1; + + while (opcodeFlags & OF_PREFIX) + { + prefixFlags |= opcodeFlags & (OF_PREFIX_AS | OF_PREFIX_OS); + opcodeFlags = g_opcodeFlags[instr[length]]; + ++length; + } + + if (opcodeFlags & OF_ESCAPE) + { + opcodeFlags = g_opcodeFlags0F[instr[length]]; + ++length; + if (opcodeFlags & OF_ESCAPE) + { + ++length; + } + } + + if (0 == opcodeFlags) + { + return length; + } + + if (opcodeFlags & OF_INVALID) + { + return 0; + } + + if (opcodeFlags & OF_MODRM) + { + const unsigned char modrm = instr[length]; + ++length; + + if ((opcodeFlags & OF_ICOND) && 0 != ((modrm >> 3) & 7)) + { + opcodeFlags &= ~(OF_IB | OF_IW_ID); + } + + const unsigned char mod = modrm >> 6; + const unsigned char rm = modrm & 7; + if (1 == mod) + { + ++length; // disp8 + } + else if (2 == mod) + { + length += (prefixFlags & OF_PREFIX_AS) ? 2 : 4; // disp16/32 + } + else if (0 == mod) + { + if (prefixFlags & OF_PREFIX_AS) + { + if (6 == rm) + { + length += 2; // disp16 + } + } + else if (4 == rm && 5 == (instr[length] & 7) || + 5 == rm) + { + length += 4; // disp32 + } + } + + if (4 == rm && 3 != mod && !(prefixFlags & OF_PREFIX_AS)) + { + ++length; // SIB + } + } + + if (opcodeFlags & OF_IB) + { + ++length; // ib + } + if (opcodeFlags & OF_IW) + { + length += 2; // iw + } + if (opcodeFlags & OF_IW_ID) + { + if (opcodeFlags & OF_AS) + { + length += (prefixFlags & OF_PREFIX_AS) ? 2 : 4; // iw/id + } + else + { + length += (prefixFlags & OF_PREFIX_OS) ? 2 : 4; // iw/id + } + } + + if (opcodeFlags & OF_CB) + { + ++length; // cb + } + else if (opcodeFlags & OF_CW_CD) + { + length += (prefixFlags & OF_PREFIX_OS) ? 2 : 4; // cw/cd + } + else if (opcodeFlags & OF_CD_CP) + { + length += (prefixFlags & OF_PREFIX_OS) ? 4 : 6; // cd/cp + } + + return length; + } +} diff --git a/DDrawCompat/Common/Disasm.h b/DDrawCompat/Common/Disasm.h new file mode 100644 index 0000000..d48fcdd --- /dev/null +++ b/DDrawCompat/Common/Disasm.h @@ -0,0 +1,6 @@ +#pragma once + +namespace Compat +{ + unsigned getInstructionLength(const void* instruction); +} diff --git a/DDrawCompat/Common/Hook.cpp b/DDrawCompat/Common/Hook.cpp index 2c3492a..8d9cb34 100644 --- a/DDrawCompat/Common/Hook.cpp +++ b/DDrawCompat/Common/Hook.cpp @@ -5,9 +5,8 @@ #include #include -#include -#include +#include #include #include #include @@ -15,35 +14,7 @@ namespace { - IDebugClient4* g_debugClient = nullptr; - IDebugControl* g_debugControl = nullptr; - IDebugSymbols* g_debugSymbols = nullptr; - IDebugDataSpaces4* g_debugDataSpaces = nullptr; - ULONG64 g_debugBase = 0; - bool g_isDbgEngInitialized = false; - - LONG WINAPI dbgEngWinVerifyTrust(HWND hwnd, GUID* pgActionID, LPVOID pWVTData); PIMAGE_NT_HEADERS getImageNtHeaders(HMODULE module); - bool initDbgEng(); - - FARPROC WINAPI dbgEngGetProcAddress(HMODULE hModule, LPCSTR lpProcName) - { - LOG_FUNC("dbgEngGetProcAddress", hModule, lpProcName); - if (0 == strcmp(lpProcName, "WinVerifyTrust")) - { - return LOG_RESULT(reinterpret_cast(&dbgEngWinVerifyTrust)); - } - return LOG_RESULT(GetProcAddress(hModule, lpProcName)); - } - - LONG WINAPI dbgEngWinVerifyTrust( - [[maybe_unused]] HWND hwnd, - [[maybe_unused]] GUID* pgActionID, - [[maybe_unused]] LPVOID pWVTData) - { - LOG_FUNC("dbgEngWinVerifyTrust", hwnd, pgActionID, pWVTData); - return LOG_RESULT(0); - } FARPROC* findProcAddressInIat(HMODULE module, const char* procName) { @@ -159,11 +130,6 @@ namespace return; } - if (!initDbgEng()) - { - return; - } - const DWORD trampolineSize = 32; BYTE* trampoline = static_cast( VirtualAlloc(nullptr, trampolineSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)); @@ -171,7 +137,7 @@ namespace BYTE* dst = trampoline; while (src - targetFunc < 5) { - unsigned instructionSize = Compat::getInstructionSize(src); + unsigned instructionSize = Compat::getInstructionLength(src); if (0 == instructionSize) { return; @@ -208,114 +174,10 @@ namespace GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN, reinterpret_cast(targetFunc), &module); } - - bool initDbgEng() - { - if (g_isDbgEngInitialized) - { - return 0 != g_debugBase; - } - g_isDbgEngInitialized = true; - - if (!GetModuleHandle("dbghelp.dll")) - { - LoadLibraryW((Compat::getSystemPath() / "dbghelp.dll").c_str()); - } - - auto dbgEng = LoadLibraryW((Compat::getSystemPath() / "dbgeng.dll").c_str()); - if (!dbgEng) - { - LOG_INFO << "ERROR: DbgEng: failed to load library"; - return false; - } - - Compat::hookIatFunction(dbgEng, "GetProcAddress", dbgEngGetProcAddress); - - auto debugCreate = reinterpret_cast(Compat::getProcAddress(dbgEng, "DebugCreate")); - if (!debugCreate) - { - LOG_INFO << "ERROR: DbgEng: DebugCreate not found"; - return false; - } - - HRESULT result = S_OK; - if (FAILED(result = debugCreate(IID_IDebugClient4, reinterpret_cast(&g_debugClient))) || - FAILED(result = g_debugClient->QueryInterface(IID_IDebugControl, reinterpret_cast(&g_debugControl))) || - FAILED(result = g_debugClient->QueryInterface(IID_IDebugSymbols, reinterpret_cast(&g_debugSymbols))) || - FAILED(result = g_debugClient->QueryInterface(IID_IDebugDataSpaces4, reinterpret_cast(&g_debugDataSpaces)))) - { - LOG_INFO << "ERROR: DbgEng: object creation failed: " << Compat::hex(result); - return false; - } - - result = g_debugClient->OpenDumpFileWide(Compat::getModulePath(Dll::g_currentModule).c_str(), 0); - if (FAILED(result)) - { - LOG_INFO << "ERROR: DbgEng: OpenDumpFile failed: " << Compat::hex(result); - return false; - } - - g_debugControl->SetEngineOptions(DEBUG_ENGOPT_DISABLE_MODULE_SYMBOL_LOAD); - result = g_debugControl->WaitForEvent(0, INFINITE); - if (FAILED(result)) - { - LOG_INFO << "ERROR: DbgEng: WaitForEvent failed: " << Compat::hex(result); - return false; - } - - DEBUG_MODULE_PARAMETERS dmp = {}; - result = g_debugSymbols->GetModuleParameters(1, 0, 0, &dmp); - if (FAILED(result)) - { - LOG_INFO << "ERROR: DbgEng: GetModuleParameters failed: " << Compat::hex(result); - return false; - } - - ULONG size = 0; - result = g_debugDataSpaces->GetValidRegionVirtual(dmp.Base, dmp.Size, &g_debugBase, &size); - if (FAILED(result) || 0 == g_debugBase) - { - LOG_INFO << "ERROR: DbgEng: GetValidRegionVirtual failed: " << Compat::hex(result); - return false; - } - - return true; - } } namespace Compat { - void closeDbgEng() - { - if (g_debugClient) - { - g_debugClient->EndSession(DEBUG_END_PASSIVE); - } - if (g_debugDataSpaces) - { - g_debugDataSpaces->Release(); - g_debugDataSpaces = nullptr; - } - if (g_debugSymbols) - { - g_debugSymbols->Release(); - g_debugSymbols = nullptr; - } - if (g_debugControl) - { - g_debugControl->Release(); - g_debugControl = nullptr; - } - if (g_debugClient) - { - g_debugClient->Release(); - g_debugClient = nullptr; - } - - g_debugBase = 0; - g_isDbgEngInitialized = false; - } - std::string funcPtrToStr(const void* funcPtr) { std::ostringstream oss; @@ -332,28 +194,6 @@ namespace Compat return oss.str(); } - unsigned getInstructionSize(void* instruction) - { - const unsigned MAX_INSTRUCTION_SIZE = 15; - HRESULT result = g_debugDataSpaces->WriteVirtual(g_debugBase, instruction, MAX_INSTRUCTION_SIZE, nullptr); - if (FAILED(result)) - { - LOG_ONCE("ERROR: DbgEng: WriteVirtual failed: " << Compat::hex(result)); - return 0; - } - - ULONG64 endOffset = 0; - result = g_debugControl->Disassemble(g_debugBase, 0, nullptr, 0, nullptr, &endOffset); - if (FAILED(result)) - { - LOG_ONCE("ERROR: DbgEng: Disassemble failed: " << Compat::hex(result) << " " - << Compat::hexDump(instruction, MAX_INSTRUCTION_SIZE)); - return 0; - } - - return static_cast(endOffset - g_debugBase); - } - DWORD getModuleFileOffset(const void* address) { LOG_FUNC("getModuleFileOffset", address); diff --git a/DDrawCompat/Common/Hook.h b/DDrawCompat/Common/Hook.h index 897afd3..7a1630f 100644 --- a/DDrawCompat/Common/Hook.h +++ b/DDrawCompat/Common/Hook.h @@ -13,9 +13,7 @@ namespace Compat { - void closeDbgEng(); std::string funcPtrToStr(const void* funcPtr); - unsigned getInstructionSize(void* instruction); DWORD getModuleFileOffset(const void* address); HMODULE getModuleHandleFromAddress(const void* address); diff --git a/DDrawCompat/DDraw/DirectDraw.cpp b/DDrawCompat/DDraw/DirectDraw.cpp index 9dfbf03..a04ff04 100644 --- a/DDrawCompat/DDraw/DirectDraw.cpp +++ b/DDrawCompat/DDraw/DirectDraw.cpp @@ -331,7 +331,6 @@ namespace DDraw g_origDDrawWindowProc = ddrawWndProc; Compat::hookFunction(reinterpret_cast(g_origDDrawWindowProc), ddrawWindowProc, "ddrawWindowProc"); - Compat::closeDbgEng(); } void onCreate(GUID* guid, CompatRef dd) diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index b7f45e1..fba9ed0 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -140,6 +140,7 @@ + @@ -338,6 +339,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 2343e09..8f50274 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -714,6 +714,9 @@ Header Files\Config\Settings + + Header Files\Common + @@ -1118,6 +1121,9 @@ Source Files\Config\Settings + + Source Files\Common + diff --git a/DDrawCompat/Dll/DllMain.cpp b/DDrawCompat/Dll/DllMain.cpp index 254a782..2057d98 100644 --- a/DDrawCompat/Dll/DllMain.cpp +++ b/DDrawCompat/Dll/DllMain.cpp @@ -140,7 +140,6 @@ namespace Direct3d::installHooks(dd, dd7); LOG_INFO << "Installing GDI hooks"; Gdi::installHooks(); - Compat::closeDbgEng(); LOG_INFO << "Finished installing hooks"; } @@ -203,7 +202,7 @@ namespace << Compat::hex(ExceptionInfo->ExceptionRecord->ExceptionCode); const auto writeDump = reinterpret_cast( - GetProcAddress(GetModuleHandle("dbghelp"), "MiniDumpWriteDump")); + GetProcAddress(LoadLibraryA("dbghelp"), "MiniDumpWriteDump")); if (writeDump) { @@ -348,7 +347,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) Win32::Thread::installHooks(); Win32::Version::installHooks(); Win32::Winmm::installHooks(); - Compat::closeDbgEng(); CALL_ORIG_FUNC(timeBeginPeriod)(1); Win32::DpiAwareness::init(); diff --git a/DDrawCompat/Overlay/Steam.cpp b/DDrawCompat/Overlay/Steam.cpp index d3c2c9e..8eada36 100644 --- a/DDrawCompat/Overlay/Steam.cpp +++ b/DDrawCompat/Overlay/Steam.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -157,7 +158,7 @@ namespace unsigned totalInstructionSize = 0; while (totalInstructionSize < 5) { - unsigned instructionSize = Compat::getInstructionSize(instructions + totalInstructionSize); + unsigned instructionSize = Compat::getInstructionLength(instructions + totalInstructionSize); if (0 == instructionSize) { return LOG_RESULT(nullptr);