diff --git a/DDrawCompat/v0.3.1/Common/Disasm.cpp b/DDrawCompat/v0.3.1/Common/Disasm.cpp new file mode 100644 index 00000000..a977427b --- /dev/null +++ b/DDrawCompat/v0.3.1/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 Compat32 +{ + 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/v0.3.1/Common/Disasm.h b/DDrawCompat/v0.3.1/Common/Disasm.h new file mode 100644 index 00000000..354e7f9c --- /dev/null +++ b/DDrawCompat/v0.3.1/Common/Disasm.h @@ -0,0 +1,6 @@ +#pragma once + +namespace Compat32 +{ + unsigned getInstructionLength(const void* instruction); +} diff --git a/DDrawCompat/v0.3.1/Common/Hook.cpp b/DDrawCompat/v0.3.1/Common/Hook.cpp index 0ccdb9d0..39141a92 100644 --- a/DDrawCompat/v0.3.1/Common/Hook.cpp +++ b/DDrawCompat/v0.3.1/Common/Hook.cpp @@ -1,5 +1,3 @@ -#define WIN32_LEAN_AND_MEAN - #undef CINTERFACE #include @@ -7,10 +5,8 @@ #include #include -#include -#include -#include +#include #include #include #include @@ -18,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) { @@ -73,12 +41,13 @@ namespace auto origThunk = reinterpret_cast(moduleBase + desc->OriginalFirstThunk); while (0 != thunk->u1.AddressOfData && 0 != origThunk->u1.AddressOfData) { - auto origImport = reinterpret_cast( - moduleBase + origThunk->u1.AddressOfData); - - if (0 == strcmp(origImport->Name, procName)) + if (!(origThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)) { - return reinterpret_cast(&thunk->u1.Function); + auto origImport = reinterpret_cast(moduleBase + origThunk->u1.AddressOfData); + if (0 == strcmp(origImport->Name, procName)) + { + return reinterpret_cast(&thunk->u1.Function); + } } ++thunk; @@ -107,34 +76,11 @@ namespace return ntHeaders; } - 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: " << Compat32::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: " << Compat32::hex(result) << " " - << Compat32::hexDump(instruction, MAX_INSTRUCTION_SIZE)); - return 0; - } - - return static_cast(endOffset - g_debugBase); - } - void hookFunction(void*& origFuncPtr, void* newFuncPtr, const char* funcName) { - BYTE* targetFunc = reinterpret_cast(origFuncPtr); + BYTE* targetFunc = static_cast(origFuncPtr); std::ostringstream oss; -#ifdef DEBUGLOGS oss << Compat32::funcPtrToStr(targetFunc) << ' '; char origFuncPtrStr[20] = {}; @@ -145,8 +91,6 @@ namespace } auto prevTargetFunc = targetFunc; -#endif - while (true) { unsigned instructionSize = 0; @@ -163,21 +107,21 @@ namespace else if (0xFF == targetFunc[0] && 0x25 == targetFunc[1]) { instructionSize = 6; - auto candidateTargetFunc = **reinterpret_cast(targetFunc + 2); - if (Compat32::getModuleHandleFromAddress(candidateTargetFunc) == Compat32::getModuleHandleFromAddress(targetFunc)) + targetFunc = **reinterpret_cast(targetFunc + 2); + if (Compat32::getModuleHandleFromAddress(targetFunc) == Compat32::getModuleHandleFromAddress(prevTargetFunc)) { + targetFunc = prevTargetFunc; break; } - targetFunc = candidateTargetFunc; } else { break; } -#ifdef DEBUGLOGS - oss << Compat32::hexDump(prevTargetFunc, instructionSize) << " -> " << Compat32::funcPtrToStr(targetFunc) << ' '; + + Compat32::LogDebug() << Compat32::hexDump(prevTargetFunc, instructionSize) << " -> " + << Compat32::funcPtrToStr(targetFunc) << ' '; prevTargetFunc = targetFunc; -#endif } if (Compat32::getModuleHandleFromAddress(targetFunc) == Dll::g_currentModule) @@ -186,203 +130,55 @@ namespace return; } - if (!initDbgEng()) - { - return; - } - - unsigned totalInstructionSize = 0; - while (totalInstructionSize < 5) + const DWORD trampolineSize = 32; + BYTE* trampoline = static_cast( + VirtualAlloc(nullptr, trampolineSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)); + BYTE* src = targetFunc; + BYTE* dst = trampoline; + while (src - targetFunc < 5) { - unsigned instructionSize = getInstructionSize(targetFunc + totalInstructionSize); + unsigned instructionSize = Compat32::getInstructionLength(src); if (0 == instructionSize) { return; } - totalInstructionSize += instructionSize; + + memcpy(dst, src, instructionSize); + if (0xE8 == *src && 5 == instructionSize) + { + *reinterpret_cast(dst + 1) += src - dst; + } + + src += instructionSize; + dst += instructionSize; } LOG_DEBUG << "Hooking function: " << funcName - << " (" << oss.str() << Compat32::hexDump(targetFunc, totalInstructionSize) << ')'; + << " (" << oss.str() << Compat32::hexDump(targetFunc, src - targetFunc) << ')'; - BYTE* trampoline = static_cast( - VirtualAlloc(nullptr, totalInstructionSize + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)); - memcpy(trampoline, targetFunc, totalInstructionSize); - trampoline[totalInstructionSize] = 0xE9; - reinterpret_cast(trampoline[totalInstructionSize + 1]) = targetFunc - (trampoline + 5); + *dst = 0xE9; + *reinterpret_cast(dst + 1) = src - (dst + 5); DWORD oldProtect = 0; - VirtualProtect(trampoline, totalInstructionSize + 5, PAGE_EXECUTE_READ, &oldProtect); + VirtualProtect(trampoline, trampolineSize, PAGE_EXECUTE_READ, &oldProtect); - VirtualProtect(targetFunc, totalInstructionSize, PAGE_EXECUTE_READWRITE, &oldProtect); + VirtualProtect(targetFunc, src - targetFunc, PAGE_EXECUTE_READWRITE, &oldProtect); targetFunc[0] = 0xE9; - reinterpret_cast(targetFunc[1]) = static_cast(newFuncPtr) - (targetFunc + 5); - memset(targetFunc + 5, 0xCC, totalInstructionSize - 5); - VirtualProtect(targetFunc, totalInstructionSize, PAGE_EXECUTE_READ, &oldProtect); + *reinterpret_cast(targetFunc + 1) = static_cast(newFuncPtr) - (targetFunc + 5); + memset(targetFunc + 5, 0xCC, src - targetFunc - 5); + VirtualProtect(targetFunc, src - targetFunc, PAGE_EXECUTE_READ, &oldProtect); - FlushInstructionCache(GetCurrentProcess(), nullptr, 0); + origFuncPtr = trampoline; + CALL_ORIG_FUNC(FlushInstructionCache)(GetCurrentProcess(), nullptr, 0); HMODULE module = nullptr; GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN, reinterpret_cast(targetFunc), &module); - - origFuncPtr = trampoline; - } - - bool initDbgEng() - { - if (g_isDbgEngInitialized) - { - return 0 != g_debugBase; - } - g_isDbgEngInitialized = true; - - //********** Begin Edit ************* - typedef HRESULT(STDAPICALLTYPE* PFN_DebugCreate)(_In_ REFIID InterfaceId, _Out_ PVOID* Interface); - static PFN_DebugCreate pDebugCreate = nullptr; - static bool RunOnce = true; - if (RunOnce) - { - RunOnce = false; - - char path[MAX_PATH]; - HMODULE help_dll = nullptr; - HMODULE eng_dll = nullptr; - - // Check if modules are loaded - GetModuleHandleExA(0, "dbghelp.dll", &help_dll); - GetModuleHandleExA(0, "dbgeng.dll", &eng_dll); - bool LoadFromSystem32 = (!help_dll && !eng_dll); - if (help_dll) - { - Compat32::Log() << "Warning: DbgHelp: is already loaded!"; - } - if (eng_dll) - { - Compat32::Log() << "Warning: DbgEng: is already loaded!"; - } - - if (LoadFromSystem32) - { - // Get System32 path - char syspath[MAX_PATH]; - GetSystemDirectory(syspath, MAX_PATH); - - // Load dbghelp.dll from System32 - strcpy_s(path, MAX_PATH, syspath); - PathAppend(path, "dbghelp.dll"); - help_dll = LoadLibrary(path); - - // Try loading dbgeng.dll from System32 - strcpy_s(path, MAX_PATH, syspath); - PathAppend(path, "dbgeng.dll"); - eng_dll = LoadLibrary(path); - } - - // Try loading dbgeng.dll from local path - if (!eng_dll || !GetProcAddress(eng_dll, "DebugCreate")) - { - eng_dll = LoadLibrary("dbgeng.dll"); - } - - // Hook function and get process address - if (eng_dll && GetProcAddress(eng_dll, "DebugCreate")) - { - if (DDrawCompat::IsEnabled()) - { - Compat32::hookIatFunction(eng_dll, "GetProcAddress", dbgEngGetProcAddress); - } - - pDebugCreate = (PFN_DebugCreate)GetProcAddress(eng_dll, "DebugCreate"); - - GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)pDebugCreate, &eng_dll); - } - } - if (!pDebugCreate) - { - Compat32::Log() << "ERROR: DbgEng: failed to get proc address!"; - return false; - } - //********** End Edit *************** - - HRESULT result = S_OK; - if (FAILED(result = pDebugCreate(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)))) - { - Compat32::Log() << "ERROR: DbgEng: object creation failed: " << Compat32::hex(result); - return false; - } - - result = g_debugClient->OpenDumpFileWide(Compat32::getModulePath(Dll::g_currentModule).c_str(), 0); - if (FAILED(result)) - { - Compat32::Log() << "ERROR: DbgEng: OpenDumpFile failed: " << Compat32::hex(result); - return false; - } - - g_debugControl->SetEngineOptions(DEBUG_ENGOPT_DISABLE_MODULE_SYMBOL_LOAD); - result = g_debugControl->WaitForEvent(0, INFINITE); - if (FAILED(result)) - { - Compat32::Log() << "ERROR: DbgEng: WaitForEvent failed: " << Compat32::hex(result); - return false; - } - - DEBUG_MODULE_PARAMETERS dmp = {}; - result = g_debugSymbols->GetModuleParameters(1, 0, 0, &dmp); - if (FAILED(result)) - { - Compat32::Log() << "ERROR: DbgEng: GetModuleParameters failed: " << Compat32::hex(result); - return false; - } - - ULONG size = 0; - result = g_debugDataSpaces->GetValidRegionVirtual(dmp.Base, dmp.Size, &g_debugBase, &size); - if (FAILED(result) || 0 == g_debugBase) - { - Compat32::Log() << "ERROR: DbgEng: GetValidRegionVirtual failed: " << Compat32::hex(result); - return false; - } - - return true; } } namespace Compat32 { - 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(void* funcPtr) + std::string funcPtrToStr(const void* funcPtr) { std::ostringstream oss; HMODULE module = Compat32::getModuleHandleFromAddress(funcPtr); @@ -398,11 +194,41 @@ namespace Compat32 return oss.str(); } - HMODULE getModuleHandleFromAddress(void* address) + DWORD getModuleFileOffset(const void* address) + { + LOG_FUNC("getModuleFileOffset", address); + HMODULE mod = getModuleHandleFromAddress(address); + if (!mod) + { + return LOG_RESULT(0); + } + + PIMAGE_NT_HEADERS ntHeaders = getImageNtHeaders(mod); + if (!ntHeaders) + { + return LOG_RESULT(0); + } + + DWORD offset = static_cast(address) - reinterpret_cast(mod); + auto sectionHeader = reinterpret_cast( + &ntHeaders->OptionalHeader.DataDirectory[ntHeaders->OptionalHeader.NumberOfRvaAndSizes]); + for (unsigned i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i) + { + if (offset >= sectionHeader->VirtualAddress && + offset < sectionHeader->VirtualAddress + sectionHeader->SizeOfRawData) + { + return LOG_RESULT(sectionHeader->PointerToRawData + offset - sectionHeader->VirtualAddress); + } + sectionHeader++; + } + return LOG_RESULT(0); + } + + HMODULE getModuleHandleFromAddress(const void* address) { HMODULE module = nullptr; GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - static_cast(address), &module); + static_cast(address), &module); return module; } diff --git a/DDrawCompat/v0.3.1/Common/Hook.h b/DDrawCompat/v0.3.1/Common/Hook.h index 0f5724e0..a91a717d 100644 --- a/DDrawCompat/v0.3.1/Common/Hook.h +++ b/DDrawCompat/v0.3.1/Common/Hook.h @@ -13,13 +13,16 @@ namespace Compat32 { - void closeDbgEng(); - std::string funcPtrToStr(void* funcPtr); - HMODULE getModuleHandleFromAddress(void* address); + std::string funcPtrToStr(const void* funcPtr); + DWORD getModuleFileOffset(const void* address); + HMODULE getModuleHandleFromAddress(const void* address); template decltype(origFunc) g_origFuncPtr = origFunc; + template + std::string g_origFuncName; + FARPROC getProcAddress(HMODULE module, const char* procName); void hookFunction(void*& origFuncPtr, void* newFuncPtr, const char* funcName); void hookFunction(HMODULE module, const char* funcName, void*& origFuncPtr, void* newFuncPtr); @@ -29,6 +32,7 @@ namespace Compat32 template void hookFunction(const char* moduleName, const char* funcName, decltype(origFunc) newFuncPtr) { + g_origFuncName = funcName; hookFunction(moduleName, funcName, reinterpret_cast(g_origFuncPtr), newFuncPtr); } diff --git a/DDrawCompat/v0.3.1/Dll/DllMain.cpp b/DDrawCompat/v0.3.1/Dll/DllMain.cpp index 3cc74a29..d3197027 100644 --- a/DDrawCompat/v0.3.1/Dll/DllMain.cpp +++ b/DDrawCompat/v0.3.1/Dll/DllMain.cpp @@ -119,7 +119,7 @@ namespace Compat32 } //********** End Edit *************** - Compat32::closeDbgEng(); + //Compat32::closeDbgEng(); Gdi::PresentationWindow::startThread(); Compat32::Log() << "Finished installing hooks"; isAlreadyInstalled = true; @@ -226,7 +226,7 @@ namespace Compat32 Compat32::Log() << "Installing GDI hooks"; Gdi::installHooks(); } - Compat32::closeDbgEng(); + //Compat32::closeDbgEng(); } } //********** End Edit *************** @@ -316,7 +316,7 @@ namespace Compat32 Win32::MemoryManagement::installHooks(); Win32::MsgHooks::installHooks(); Time::init(); - Compat32::closeDbgEng(); + //Compat32::closeDbgEng(); } //********** Begin Edit ************* diff --git a/DDrawCompat/v0.3.1/Gdi/PresentationWindow.cpp b/DDrawCompat/v0.3.1/Gdi/PresentationWindow.cpp index 0f75d420..2c79c29b 100644 --- a/DDrawCompat/v0.3.1/Gdi/PresentationWindow.cpp +++ b/DDrawCompat/v0.3.1/Gdi/PresentationWindow.cpp @@ -132,7 +132,7 @@ namespace EnumWindows(initTopLevelWindow, 0); } - Compat32::closeDbgEng(); + //Compat32::closeDbgEng(); MSG msg = {}; while (GetMessage(&msg, nullptr, 0, 0)) diff --git a/Dllmain/BuildNo.rc b/Dllmain/BuildNo.rc index 84109a79..34fec2c3 100644 --- a/Dllmain/BuildNo.rc +++ b/Dllmain/BuildNo.rc @@ -1 +1 @@ -#define BUILD_NUMBER 7149 +#define BUILD_NUMBER 7150 diff --git a/dxwrapper.vcxproj b/dxwrapper.vcxproj index e4a15b7f..dd3b04b7 100644 --- a/dxwrapper.vcxproj +++ b/dxwrapper.vcxproj @@ -391,6 +391,9 @@ copy /Y "$(ProjectDir)Settings\Settings.ini" "$(TargetDir)Build\dxwrapper.ini" & true + + true + true @@ -942,6 +945,9 @@ copy /Y "$(ProjectDir)Settings\Settings.ini" "$(TargetDir)Build\dxwrapper.ini" & true + + true + true diff --git a/dxwrapper.vcxproj.filters b/dxwrapper.vcxproj.filters index da3975f6..585ae330 100644 --- a/dxwrapper.vcxproj.filters +++ b/dxwrapper.vcxproj.filters @@ -883,6 +883,9 @@ d3d9 + + DDrawCompat\v0.3.1 + @@ -1865,6 +1868,9 @@ ddraw\Shaders + + DDrawCompat\v0.3.1 +