From 1c78e5bced2e4982ea6182acdbe36ffa7a83662a Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Tue, 2 Oct 2018 10:56:55 +0100 Subject: [PATCH] Various fixes/improvements to D3D HLE The key change is that more of the D3D state is written back to the internal Xbox D3D state, allowing GetXXX functions to return the correct values, and that GetVertexShaderDeclaration now returns the correct size to the running Xbox title. Note that this needs testing with as many titles as possible: The additional trampolines may cause regressions if they hit an unimplemented instruction in subhook (eg. I had to update Subhook to add xor, in order to be able to make this PR work at all) --- import/subhook | 2 +- src/CxbxKrnl/EmuX86.cpp | 1856 ++++++++--------- src/core/HLE/D3D8/Direct3D9/Direct3D9.cpp | 169 +- .../Direct3D9/Direct3D9.cpp.unused-patches | 426 ++-- src/core/HLE/D3D8/XbConvert.h | 2 +- src/core/HLE/D3D8/XbD3D8Types.h | 3 +- src/core/HLE/D3D8/XbVertexShader.cpp | 7 +- src/core/HLE/D3D8/XbVertexShader.h | 3 +- src/core/HLE/Patches.cpp | 8 +- 9 files changed, 1303 insertions(+), 1173 deletions(-) diff --git a/import/subhook b/import/subhook index e562d10d4..5073ab41a 160000 --- a/import/subhook +++ b/import/subhook @@ -1 +1 @@ -Subproject commit e562d10d4d88f85a8b5475139c68696dfc6bf231 +Subproject commit 5073ab41a88a07eba42877d9285601d319b14067 diff --git a/src/CxbxKrnl/EmuX86.cpp b/src/CxbxKrnl/EmuX86.cpp index c0f4390f9..213df5a36 100644 --- a/src/CxbxKrnl/EmuX86.cpp +++ b/src/CxbxKrnl/EmuX86.cpp @@ -29,7 +29,7 @@ // * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. // * // * (c) 2002-2003 Aaron Robinson -// * (c) 2016-2018 Luke Usher +// * (c) 2016-2018 Luke Usher // * (c) 2016-2018 Patrick van Logchem // * All rights reserved // * @@ -42,7 +42,7 @@ #pragma comment(lib, "distorm.lib") // Cxbx uses dynamic linking of distorm, which by default chooses for 64 bits offsets : -#define SUPPORT_64BIT_OFFSET +#define SUPPORT_64BIT_OFFSET #include "distorm.h" #include "mnemonics.h" @@ -53,12 +53,12 @@ #include "core/HLE/Intercept.hpp" // for bLLE_GPU #include -#include "devices\Xbox.h" // For g_PCIBus -#include -#include +#include "devices\Xbox.h" // For g_PCIBus +#include +#include #include "Logging.h" -extern uint32_t GetAPUTime(); +extern uint32_t GetAPUTime(); extern std::atomic_bool g_bEnableAllInterrupts; // @@ -119,8 +119,8 @@ void EmuX86_IOWrite(xbaddr addr, uint32_t value, int size) // uint32_t EmuX86_Mem_Read(xbaddr addr, int size) -{ - __try { +{ + __try { switch (size) { case sizeof(uint32_t) : @@ -133,16 +133,16 @@ uint32_t EmuX86_Mem_Read(xbaddr addr, int size) // UNREACHABLE(size); assert(false); return 0; - } + } } __except (true) { - EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "EmuX86_Mem_Read Failed (0x%08X, %d)", addr, size); + EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "EmuX86_Mem_Read Failed (0x%08X, %d)", addr, size); return 0; } } void EmuX86_Mem_Write(xbaddr addr, uint32_t value, int size) -{ +{ __try { switch (size) { case sizeof(uint32_t) : @@ -158,7 +158,7 @@ void EmuX86_Mem_Write(xbaddr addr, uint32_t value, int size) // UNREACHABLE(size); assert(false); return; - } + } } __except (true) { EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "EmuX86_Mem_Write Failed (0x%08X, 0x%08X, %d)", addr, value, size); @@ -245,7 +245,7 @@ int ContextRecordOffsetByRegisterType[/*_RegisterType*/R_DR7 + 1] = { 0 }; // supported by the XBox1's Coppermine Pentium III. // Based on https://maximumcrack.wordpress.com/2011/08/07/fpu-mmx-xmm-and-bbq/ void EmuX86_InitContextRecordOffsetByRegisterType() -{ +{ // Unsupported by XBox CPU : R_RAX, R_RCX, R_RDX, R_RBX, R_RSP, R_RBP, R_RSI, R_RDI, R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15, ContextRecordOffsetByRegisterType[R_EAX] = offsetof(CONTEXT, Eax); ContextRecordOffsetByRegisterType[R_ECX] = offsetof(CONTEXT, Ecx); @@ -342,32 +342,32 @@ void EmuX86_InitContextRecordOffsetByRegisterType() !DWORD SegSs; !BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];*/ } - -std::map g_MemoryBackedRegisters; - -void EmuX86_InitMemoryBackedRegisters() -{ - g_MemoryBackedRegisters[R_CR0] = 0; - g_MemoryBackedRegisters[R_CR2] = 0; - g_MemoryBackedRegisters[R_CR3] = 0; - g_MemoryBackedRegisters[R_CR4] = 0; -} + +std::map g_MemoryBackedRegisters; + +void EmuX86_InitMemoryBackedRegisters() +{ + g_MemoryBackedRegisters[R_CR0] = 0; + g_MemoryBackedRegisters[R_CR2] = 0; + g_MemoryBackedRegisters[R_CR3] = 0; + g_MemoryBackedRegisters[R_CR4] = 0; +} inline void * EmuX86_GetRegisterPointer(const LPEXCEPTION_POINTERS e, const uint8_t reg) -{ +{ int offset = ContextRecordOffsetByRegisterType[reg]; if (offset > 0) { - return (void*)((uintptr_t)(e->ContextRecord) + offset); - } - - // Xbox titles use some registers thatare not accessible in user mode - // They are also not available in the Context/Exception Record, so we can't map them - // Instead, we store the values in a key->value map. - auto it = g_MemoryBackedRegisters.find(reg); - if (it != g_MemoryBackedRegisters.end()) { - return &it->second; - } - + return (void*)((uintptr_t)(e->ContextRecord) + offset); + } + + // Xbox titles use some registers thatare not accessible in user mode + // They are also not available in the Context/Exception Record, so we can't map them + // Instead, we store the values in a key->value map. + auto it = g_MemoryBackedRegisters.find(reg); + if (it != g_MemoryBackedRegisters.end()) { + return &it->second; + } + assert(false); return nullptr; } @@ -375,20 +375,20 @@ inline void * EmuX86_GetRegisterPointer(const LPEXCEPTION_POINTERS e, const uint int EmuX86_DistormRegSize(const uint8_t reg) { switch (reg) { - case R_RAX: return 8; case R_RCX: return 8; case R_RDX: return 8; case R_RBX: return 8; case R_RSP: return 8; case R_RBP: return 8; case R_RSI: return 8; case R_RDI: return 8; case R_R8: return 8; case R_R9: return 8; case R_R10: return 8; case R_R11: return 8; case R_R12: return 8; case R_R13: return 8; case R_R14: return 8; case R_R15: return 8; - case R_EAX: return 4; case R_ECX: return 4; case R_EDX: return 4; case R_EBX: return 4; case R_ESP: return 4; case R_EBP: return 4; case R_ESI: return 4; case R_EDI: return 4; case R_R8D: return 4; case R_R9D: return 4; case R_R10D: return 4; case R_R11D: return 4; case R_R12D: return 4; case R_R13D: return 4; case R_R14D: return 4; case R_R15D: return 4; - case R_AX: return 2; case R_CX: return 2; case R_DX: return 2; case R_BX: return 2; case R_SP: return 2; case R_BP: return 2; case R_SI: return 2; case R_DI: return 2; case R_R8W: return 2; case R_R9W: return 2; case R_R10W: return 2; case R_R11W: return 2; case R_R12W: return 2; case R_R13W: return 2; case R_R14W: return 2; case R_R15W: return 2; - case R_AL: return 1; case R_CL: return 1; case R_DL: return 1; case R_BL: return 1; case R_AH: return 1; case R_CH: return 1; case R_DH: return 1; case R_BH: return 1; case R_R8B: return 1; case R_R9B: return 1; case R_R10B: return 1; case R_R11B: return 1; case R_R12B: return 1; case R_R13B: return 1; case R_R14B: return 1; case R_R15B: return 1; - case R_SPL: return 1; case R_BPL: return 1; case R_SIL: return 1; case R_DIL: return 1; - case R_ES: return 2; case R_CS: return 2; case R_SS: return 2; case R_DS: return 2; case R_FS: return 2; case R_GS: return 2; - case R_RIP: return 8; - case R_ST0: return 10; case R_ST1: return 10; case R_ST2: return 10; case R_ST3: return 10; case R_ST4: return 10; case R_ST5: return 10; case R_ST6: return 10; case R_ST7: return 10; - case R_MM0: return 10; case R_MM1: return 10; case R_MM2: return 10; case R_MM3: return 10; case R_MM4: return 10; case R_MM5: return 10; case R_MM6: return 10; case R_MM7: return 10; - case R_XMM0: return 16; case R_XMM1: return 16; case R_XMM2: return 16; case R_XMM3: return 16; case R_XMM4: return 16; case R_XMM5: return 16; case R_XMM6: return 16; case R_XMM7: return 16; case R_XMM8: return 16; case R_XMM9: return 16; case R_XMM10: return 16; case R_XMM11: return 16; case R_XMM12: return 16; case R_XMM13: return 16; case R_XMM14: return 16; case R_XMM15: return 16; - case R_YMM0: return 16; case R_YMM1: return 16; case R_YMM2: return 16; case R_YMM3: return 16; case R_YMM4: return 16; case R_YMM5: return 16; case R_YMM6: return 16; case R_YMM7: return 16; case R_YMM8: return 16; case R_YMM9: return 16; case R_YMM10: return 16; case R_YMM11: return 16; case R_YMM12: return 16; case R_YMM13: return 16; case R_YMM14: return 16; case R_YMM15: return 16; - case R_CR0: return 4; case R_UNUSED0: return 0; case R_CR2: return 4; case R_CR3: return 4; case R_CR4: return 4; case R_UNUSED1: return 0; case R_UNUSED2: return 0; case R_UNUSED3: return 0; case R_CR8: return 4; - case R_DR0: return 4; case R_DR1: return 4; case R_DR2: return 4; case R_DR3: return 4; case R_UNUSED4: return 0; case R_UNUSED5: return 0; case R_DR6: return 4; case R_DR7: return 4; - default: assert(false); return 0; + case R_RAX: return 8; case R_RCX: return 8; case R_RDX: return 8; case R_RBX: return 8; case R_RSP: return 8; case R_RBP: return 8; case R_RSI: return 8; case R_RDI: return 8; case R_R8: return 8; case R_R9: return 8; case R_R10: return 8; case R_R11: return 8; case R_R12: return 8; case R_R13: return 8; case R_R14: return 8; case R_R15: return 8; + case R_EAX: return 4; case R_ECX: return 4; case R_EDX: return 4; case R_EBX: return 4; case R_ESP: return 4; case R_EBP: return 4; case R_ESI: return 4; case R_EDI: return 4; case R_R8D: return 4; case R_R9D: return 4; case R_R10D: return 4; case R_R11D: return 4; case R_R12D: return 4; case R_R13D: return 4; case R_R14D: return 4; case R_R15D: return 4; + case R_AX: return 2; case R_CX: return 2; case R_DX: return 2; case R_BX: return 2; case R_SP: return 2; case R_BP: return 2; case R_SI: return 2; case R_DI: return 2; case R_R8W: return 2; case R_R9W: return 2; case R_R10W: return 2; case R_R11W: return 2; case R_R12W: return 2; case R_R13W: return 2; case R_R14W: return 2; case R_R15W: return 2; + case R_AL: return 1; case R_CL: return 1; case R_DL: return 1; case R_BL: return 1; case R_AH: return 1; case R_CH: return 1; case R_DH: return 1; case R_BH: return 1; case R_R8B: return 1; case R_R9B: return 1; case R_R10B: return 1; case R_R11B: return 1; case R_R12B: return 1; case R_R13B: return 1; case R_R14B: return 1; case R_R15B: return 1; + case R_SPL: return 1; case R_BPL: return 1; case R_SIL: return 1; case R_DIL: return 1; + case R_ES: return 2; case R_CS: return 2; case R_SS: return 2; case R_DS: return 2; case R_FS: return 2; case R_GS: return 2; + case R_RIP: return 8; + case R_ST0: return 10; case R_ST1: return 10; case R_ST2: return 10; case R_ST3: return 10; case R_ST4: return 10; case R_ST5: return 10; case R_ST6: return 10; case R_ST7: return 10; + case R_MM0: return 10; case R_MM1: return 10; case R_MM2: return 10; case R_MM3: return 10; case R_MM4: return 10; case R_MM5: return 10; case R_MM6: return 10; case R_MM7: return 10; + case R_XMM0: return 16; case R_XMM1: return 16; case R_XMM2: return 16; case R_XMM3: return 16; case R_XMM4: return 16; case R_XMM5: return 16; case R_XMM6: return 16; case R_XMM7: return 16; case R_XMM8: return 16; case R_XMM9: return 16; case R_XMM10: return 16; case R_XMM11: return 16; case R_XMM12: return 16; case R_XMM13: return 16; case R_XMM14: return 16; case R_XMM15: return 16; + case R_YMM0: return 16; case R_YMM1: return 16; case R_YMM2: return 16; case R_YMM3: return 16; case R_YMM4: return 16; case R_YMM5: return 16; case R_YMM6: return 16; case R_YMM7: return 16; case R_YMM8: return 16; case R_YMM9: return 16; case R_YMM10: return 16; case R_YMM11: return 16; case R_YMM12: return 16; case R_YMM13: return 16; case R_YMM14: return 16; case R_YMM15: return 16; + case R_CR0: return 4; case R_UNUSED0: return 0; case R_CR2: return 4; case R_CR3: return 4; case R_CR4: return 4; case R_UNUSED1: return 0; case R_UNUSED2: return 0; case R_UNUSED3: return 0; case R_CR8: return 4; + case R_DR0: return 4; case R_DR1: return 4; case R_DR2: return 4; case R_DR3: return 4; case R_UNUSED4: return 0; case R_UNUSED5: return 0; case R_DR6: return 4; case R_DR7: return 4; + default: assert(false); return 0; } } @@ -451,14 +451,14 @@ bool EmuX86_Operand_Addr_ForReadOnly(const LPEXCEPTION_POINTERS e, const _DInst& { opAddr.size = info.ops[operand].size / 8; // Convert size in bits into bytes switch (info.ops[operand].type) { - case O_NONE: // operand is to be ignored. + case O_NONE: // operand is to be ignored. { assert(opAddr.size == 0); // Ignore O_NONE operand return false; } - case O_REG: // index holds global register index. + case O_REG: // index holds global register index. { assert(opAddr.size == EmuX86_DistormRegSize(info.ops[operand].index)); @@ -466,7 +466,7 @@ bool EmuX86_Operand_Addr_ForReadOnly(const LPEXCEPTION_POINTERS e, const _DInst& opAddr.addr = (xbaddr)EmuX86_GetRegisterPointer(e, info.ops[operand].index); return true; } - case O_IMM: // instruction.imm. + case O_IMM: // instruction.imm. { assert(opAddr.size == sizeof(uint8_t) || opAddr.size == sizeof(uint16_t) || opAddr.size == sizeof(uint32_t)); @@ -474,7 +474,7 @@ bool EmuX86_Operand_Addr_ForReadOnly(const LPEXCEPTION_POINTERS e, const _DInst& opAddr.addr = (xbaddr)(&info.imm); return true; } - case O_IMM1: // instruction.imm.ex.i1. + case O_IMM1: // instruction.imm.ex.i1. { assert(opAddr.size == sizeof(uint8_t) || opAddr.size == sizeof(uint16_t) || opAddr.size == sizeof(uint32_t)); @@ -482,7 +482,7 @@ bool EmuX86_Operand_Addr_ForReadOnly(const LPEXCEPTION_POINTERS e, const _DInst& opAddr.addr = (xbaddr)(&info.imm.ex.i1); return true; } - case O_IMM2: // instruction.imm.ex.i2. + case O_IMM2: // instruction.imm.ex.i2. { assert(opAddr.size == sizeof(uint8_t) || opAddr.size == sizeof(uint16_t) || opAddr.size == sizeof(uint32_t)); @@ -490,7 +490,7 @@ bool EmuX86_Operand_Addr_ForReadOnly(const LPEXCEPTION_POINTERS e, const _DInst& opAddr.addr = (xbaddr)(&info.imm.ex.i2); return true; } - case O_DISP: // memory dereference with displacement only, instruction.disp. + case O_DISP: // memory dereference with displacement only, instruction.disp. { assert(opAddr.size == sizeof(uint32_t)); @@ -498,7 +498,7 @@ bool EmuX86_Operand_Addr_ForReadOnly(const LPEXCEPTION_POINTERS e, const _DInst& opAddr.addr = EmuX86_Distorm_read_disp(info); return true; } - case O_SMEM: // simple memory dereference with optional displacement(a single register memory dereference). + case O_SMEM: // simple memory dereference with optional displacement(a single register memory dereference). { assert(opAddr.size == 0 || opAddr.size == sizeof(uint8_t) || opAddr.size == sizeof(uint16_t) || opAddr.size == sizeof(uint32_t)); // TODO : How to handle size == 0 further on? @@ -507,7 +507,7 @@ bool EmuX86_Operand_Addr_ForReadOnly(const LPEXCEPTION_POINTERS e, const _DInst& + EmuX86_Distorm_read_disp(info); return true; } - case O_MEM: // complex memory dereference(optional fields : s / i / b / disp). + case O_MEM: // complex memory dereference(optional fields : s / i / b / disp). { assert(opAddr.size == 0 || opAddr.size == sizeof(uint8_t) || opAddr.size == sizeof(uint16_t) || opAddr.size == sizeof(uint32_t)); // TODO : How to handle size == 0 further on? assert(info.scale < 3 || info.scale == 4 || info.scale == 8); // Assume scale is either 0, 1, 2, 4 or 8 @@ -523,7 +523,7 @@ bool EmuX86_Operand_Addr_ForReadOnly(const LPEXCEPTION_POINTERS e, const _DInst& return true; } - case O_PC: // the relative address of a branch instruction(instruction.imm.addr). + case O_PC: // the relative address of a branch instruction(instruction.imm.addr). { assert(opAddr.size == sizeof(uint8_t) || opAddr.size == sizeof(uint32_t)); @@ -531,7 +531,7 @@ bool EmuX86_Operand_Addr_ForReadOnly(const LPEXCEPTION_POINTERS e, const _DInst& opAddr.addr = (xbaddr)e->ContextRecord->Eip + (xbaddr)INSTRUCTION_GET_TARGET(&info); return true; } - case O_PTR: // the absolute target address of a far branch instruction(instruction.imm.ptr.seg / off). + case O_PTR: // the absolute target address of a far branch instruction(instruction.imm.ptr.seg / off). { assert(opAddr.size == 0); @@ -672,40 +672,40 @@ inline void EmuX86_SetFlags_OSZAP ); } -inline bool EmuX86_HasFlag(LPEXCEPTION_POINTERS e, DWORD flag) -{ - return (e->ContextRecord->EFlags & flag); -} - -inline bool EmuX86_HasFlag_AF(LPEXCEPTION_POINTERS e) -{ - return EmuX86_HasFlag(e, BITMASK(EMUX86_EFLAG_AF)); -} +inline bool EmuX86_HasFlag(LPEXCEPTION_POINTERS e, DWORD flag) +{ + return (e->ContextRecord->EFlags & flag); +} -inline bool EmuX86_HasFlag_CF(LPEXCEPTION_POINTERS e) -{ - return EmuX86_HasFlag(e, BITMASK(EMUX86_EFLAG_CF)); -} +inline bool EmuX86_HasFlag_AF(LPEXCEPTION_POINTERS e) +{ + return EmuX86_HasFlag(e, BITMASK(EMUX86_EFLAG_AF)); +} -inline bool EmuX86_HasFlag_OF(LPEXCEPTION_POINTERS e) -{ - return EmuX86_HasFlag(e, BITMASK(EMUX86_EFLAG_OF)); -} +inline bool EmuX86_HasFlag_CF(LPEXCEPTION_POINTERS e) +{ + return EmuX86_HasFlag(e, BITMASK(EMUX86_EFLAG_CF)); +} -inline bool EmuX86_HasFlag_PF(LPEXCEPTION_POINTERS e) -{ - return EmuX86_HasFlag(e, BITMASK(EMUX86_EFLAG_PF)); -} +inline bool EmuX86_HasFlag_OF(LPEXCEPTION_POINTERS e) +{ + return EmuX86_HasFlag(e, BITMASK(EMUX86_EFLAG_OF)); +} -inline bool EmuX86_HasFlag_SF(LPEXCEPTION_POINTERS e) -{ - return EmuX86_HasFlag(e, BITMASK(EMUX86_EFLAG_SF)); -} +inline bool EmuX86_HasFlag_PF(LPEXCEPTION_POINTERS e) +{ + return EmuX86_HasFlag(e, BITMASK(EMUX86_EFLAG_PF)); +} -inline bool EmuX86_HasFlag_ZF(LPEXCEPTION_POINTERS e) -{ - return EmuX86_HasFlag(e, BITMASK(EMUX86_EFLAG_ZF)); -} +inline bool EmuX86_HasFlag_SF(LPEXCEPTION_POINTERS e) +{ + return EmuX86_HasFlag(e, BITMASK(EMUX86_EFLAG_SF)); +} + +inline bool EmuX86_HasFlag_ZF(LPEXCEPTION_POINTERS e) +{ + return EmuX86_HasFlag(e, BITMASK(EMUX86_EFLAG_ZF)); +} // EFLAGS Cross-Reference : http://datasheets.chipdb.org/Intel/x86/Intel%20Architecture/EFLAGS.PDF @@ -767,21 +767,21 @@ bool EmuX86_Opcode_ADD(LPEXCEPTION_POINTERS e, _DInst& info) if (info.ops[0].size > info.ops[1].size) { SignExtend32(src, info.ops[1].size); } - - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - add eax, src // perform the operation, this updates eflags for us! - mov result, eax - pushfd // push the updated host flags onto the stack + + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + add eax, src // perform the operation, this updates eflags for us! + mov result, eax + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags - e->ContextRecord->EFlags = eflags; + + // Write back the flags + e->ContextRecord->EFlags = eflags; // Write back the result EmuX86_Addr_Write(opAddr, result); @@ -807,37 +807,37 @@ bool EmuX86_Opcode_AND(LPEXCEPTION_POINTERS e, _DInst& info) SignExtend32(src, info.ops[1].size); } - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - and eax, src // perform the operation, this updates eflags for us! - mov result, eax - pushfd // push the updated host flags onto the stack + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + and eax, src // perform the operation, this updates eflags for us! + mov result, eax + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags - e->ContextRecord->EFlags = eflags; + + // Write back the flags + e->ContextRecord->EFlags = eflags; // Write back the result EmuX86_Addr_Write(opAddr, result); return true; } - -void EmuX86_Opcode_CDQ(LPEXCEPTION_POINTERS e, _DInst& info) -{ - e->ContextRecord->Edx = (e->ContextRecord->Eax & 0x80000000) ? 0xFFFFFFFF : 0; -} - -void EmuX86_Opcode_CLI() + +void EmuX86_Opcode_CDQ(LPEXCEPTION_POINTERS e, _DInst& info) +{ + e->ContextRecord->Edx = (e->ContextRecord->Eax & 0x80000000) ? 0xFFFFFFFF : 0; +} + +void EmuX86_Opcode_CLI() { g_bEnableAllInterrupts = false; -} - +} + bool EmuX86_Opcode_CMP(LPEXCEPTION_POINTERS e, _DInst& info) { // Read value from Source and Destination @@ -852,18 +852,18 @@ bool EmuX86_Opcode_CMP(LPEXCEPTION_POINTERS e, _DInst& info) if (info.ops[0].size > info.ops[1].size) { SignExtend32(src, info.ops[1].size); } - - uint32_t eflags = e->ContextRecord->EFlags; - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - cmp eax, src // perform the operation, this updates eflags for us! - pushfd // push the updated host flags onto the stack + + uint32_t eflags = e->ContextRecord->EFlags; + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + cmp eax, src // perform the operation, this updates eflags for us! + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags + + // Write back the flags e->ContextRecord->EFlags = eflags; return true; @@ -899,18 +899,18 @@ bool EmuX86_Opcode_CMPXCHG(LPEXCEPTION_POINTERS e, _DInst& info) e->ContextRecord->Eax = (e->ContextRecord->Eax & ~mask) | (dest & mask); } - // Perform arithmatic operation for flag calculation - uint32_t eflags = e->ContextRecord->EFlags; - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, eaxVal - cmp eax, dest // perform the operation, this updates eflags for us! - pushfd // push the updated host flags onto the stack + // Perform arithmatic operation for flag calculation + uint32_t eflags = e->ContextRecord->EFlags; + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, eaxVal + cmp eax, dest // perform the operation, this updates eflags for us! + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags + + // Write back the flags e->ContextRecord->EFlags = eflags; return true; @@ -971,20 +971,20 @@ bool EmuX86_Opcode_DEC(LPEXCEPTION_POINTERS e, _DInst& info) uint32_t dest = EmuX86_Addr_Read(opAddr); - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - dec eax // perform the operation, this updates eflags for us! - mov result, eax - pushfd // push the updated host flags onto the stack + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + dec eax // perform the operation, this updates eflags for us! + mov result, eax + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags - e->ContextRecord->EFlags = eflags; + + // Write back the flags + e->ContextRecord->EFlags = eflags; // Write result back EmuX86_Addr_Write(opAddr, static_cast(result)); @@ -1019,48 +1019,48 @@ bool EmuX86_Opcode_INC(LPEXCEPTION_POINTERS e, _DInst& info) uint32_t dest = EmuX86_Addr_Read(opAddr); - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - inc eax // perform the operation, this updates eflags for us! - mov result, eax - pushfd // push the updated host flags onto the stack + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + inc eax // perform the operation, this updates eflags for us! + mov result, eax + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags - e->ContextRecord->EFlags = eflags; + + // Write back the flags + e->ContextRecord->EFlags = eflags; // Write result back EmuX86_Addr_Write(opAddr, static_cast(result)); return true; -} +} bool EmuX86_Opcode_JMP(LPEXCEPTION_POINTERS e, _DInst& info) { - OperandAddress opAddr; - if (!EmuX86_Operand_Addr_ForReadOnly(e, info, 0, OUT opAddr)) - assert(false); - - e->ContextRecord->Eip = opAddr.addr; + OperandAddress opAddr; + if (!EmuX86_Operand_Addr_ForReadOnly(e, info, 0, OUT opAddr)) + assert(false); + + e->ContextRecord->Eip = opAddr.addr; return true; } - -// Jump if condition is met + +// Jump if condition is met // https://c9x.me/x86/html/file_module_x86_id_146.html // Returns true if branch was taken bool EmuX86_Opcode_Jcc(LPEXCEPTION_POINTERS e, _DInst& info, bool condition) { - if (condition) - return EmuX86_Opcode_JMP(e, info); + if (condition) + return EmuX86_Opcode_JMP(e, info); return false; } - + bool EmuX86_Opcode_LEA(LPEXCEPTION_POINTERS e, _DInst& info) { // LEA reads effective address from source operand : @@ -1142,9 +1142,9 @@ bool EmuX86_Opcode_MOVZX(LPEXCEPTION_POINTERS e, _DInst& info) return true; } - + bool EmuX86_Opcode_NEG(LPEXCEPTION_POINTERS e, _DInst& info) -{ +{ // NEG reads and writes the same operand : OperandAddress opAddr; if (!EmuX86_Operand_Addr_ForReadWrite(e, info, 0, OUT opAddr)) @@ -1169,8 +1169,8 @@ bool EmuX86_Opcode_NEG(LPEXCEPTION_POINTERS e, _DInst& info) /*EMUX86_EFLAG_CF*/(dest != 0)); return true; -} - +} + bool EmuX86_Opcode_NOT(LPEXCEPTION_POINTERS e, _DInst& info) { // NOT reads and writes the same operand : @@ -1179,19 +1179,19 @@ bool EmuX86_Opcode_NOT(LPEXCEPTION_POINTERS e, _DInst& info) return false; uint32_t dest = EmuX86_Addr_Read(opAddr); - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - not eax // perform the operation, this updates eflags for us! - mov result, eax - pushfd // push the updated host flags onto the stack + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + not eax // perform the operation, this updates eflags for us! + mov result, eax + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags + + // Write back the flags e->ContextRecord->EFlags = eflags; // Write back the result @@ -1200,7 +1200,7 @@ bool EmuX86_Opcode_NOT(LPEXCEPTION_POINTERS e, _DInst& info) // Flags are not effected return true; -} +} bool EmuX86_Opcode_OR(LPEXCEPTION_POINTERS e, _DInst& info) { @@ -1217,22 +1217,22 @@ bool EmuX86_Opcode_OR(LPEXCEPTION_POINTERS e, _DInst& info) uint32_t dest = EmuX86_Addr_Read(opAddr); if (info.ops[0].size > info.ops[1].size) { SignExtend32(src, info.ops[1].size); - } + } - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - or eax, src // perform the operation, this updates eflags for us! - mov result, eax - pushfd // push the updated host flags onto the stack + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + or eax, src // perform the operation, this updates eflags for us! + mov result, eax + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags - e->ContextRecord->EFlags = eflags; + + // Write back the flags + e->ContextRecord->EFlags = eflags; // Write back the result EmuX86_Addr_Write(opAddr, result); @@ -1258,41 +1258,41 @@ bool EmuX86_Opcode_OUT(LPEXCEPTION_POINTERS e, _DInst& info) return true; } - -// https://c9x.me/x86/html/file_module_x86_id_248.html -bool EmuX86_Opcode_POP(LPEXCEPTION_POINTERS e, _DInst& info) -{ - // Recognize POP ESP (which increments BEFORE reading from stack) : - bool bAccessesESP = (info.ops[0].type == O_REG) && (info.ops[0].index == R_ESP); - uint32_t value; - if (bAccessesESP) { - e->ContextRecord->Esp += sizeof(uint32_t); - value = EmuX86_Mem_Read(e->ContextRecord->Esp, sizeof(uint32_t)); - } - else { - value = EmuX86_Mem_Read(e->ContextRecord->Esp, sizeof(uint32_t)); - e->ContextRecord->Esp += sizeof(uint32_t); - } - +// https://c9x.me/x86/html/file_module_x86_id_248.html +bool EmuX86_Opcode_POP(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // Recognize POP ESP (which increments BEFORE reading from stack) : + bool bAccessesESP = (info.ops[0].type == O_REG) && (info.ops[0].index == R_ESP); + uint32_t value; + + if (bAccessesESP) { + e->ContextRecord->Esp += sizeof(uint32_t); + value = EmuX86_Mem_Read(e->ContextRecord->Esp, sizeof(uint32_t)); + } + else { + value = EmuX86_Mem_Read(e->ContextRecord->Esp, sizeof(uint32_t)); + e->ContextRecord->Esp += sizeof(uint32_t); + } + if (!EmuX86_Operand_Write(e, info, 0, value)) - return false; - - return true; -} + return false; -bool EmuX86_Opcode_PUSH(LPEXCEPTION_POINTERS e, _DInst& info) -{ - uint32_t value; + return true; +} + +bool EmuX86_Opcode_PUSH(LPEXCEPTION_POINTERS e, _DInst& info) +{ + uint32_t value; if (!EmuX86_Operand_Read(e, info, 0, &value)) - return false; - - e->ContextRecord->Esp -= sizeof(uint32_t); - EmuX86_Mem_Write(e->ContextRecord->Esp, value, sizeof(uint32_t)); - return true; -} + return false; -ULONGLONG CxbxRdTsc(bool xbox); // implemented in EmuKrnlKe.cpp + e->ContextRecord->Esp -= sizeof(uint32_t); + EmuX86_Mem_Write(e->ContextRecord->Esp, value, sizeof(uint32_t)); + return true; +} + +ULONGLONG CxbxRdTsc(bool xbox); // implemented in EmuKrnlKe.cpp void EmuX86_Opcode_RDTSC(LPEXCEPTION_POINTERS e) { // Avoid the overhead of xboxkrnl::KeQueryPerformanceCounter, @@ -1302,9 +1302,9 @@ void EmuX86_Opcode_RDTSC(LPEXCEPTION_POINTERS e) e->ContextRecord->Eax = PerformanceCount.LowPart; e->ContextRecord->Edx = PerformanceCount.HighPart; } - -bool EmuX86_Opcode_SAR(LPEXCEPTION_POINTERS e, _DInst& info) -{ + +bool EmuX86_Opcode_SAR(LPEXCEPTION_POINTERS e, _DInst& info) +{ // Read value from Source and Destination uint32_t src = 0; if (!EmuX86_Operand_Read(e, info, 1, &src)) @@ -1316,30 +1316,30 @@ bool EmuX86_Opcode_SAR(LPEXCEPTION_POINTERS e, _DInst& info) return false; uint32_t dest = EmuX86_Addr_Read(opAddr); - - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - uint8_t byteSrc = src; - - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - mov cl, byteSrc - sar eax, cl // perform the operation, this updates eflags for us! - mov result, eax - pushfd // push the updated host flags onto the stack + + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + uint8_t byteSrc = src; + + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + mov cl, byteSrc + sar eax, cl // perform the operation, this updates eflags for us! + mov result, eax + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags - e->ContextRecord->EFlags = eflags; - + + // Write back the flags + e->ContextRecord->EFlags = eflags; + // Write result back EmuX86_Addr_Write(opAddr, static_cast(result)); return true; -} +} bool EmuX86_Opcode_SBB(LPEXCEPTION_POINTERS e, _DInst& info) { @@ -1359,29 +1359,29 @@ bool EmuX86_Opcode_SBB(LPEXCEPTION_POINTERS e, _DInst& info) SignExtend32(src, info.ops[1].size); } - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - sbb eax, src // perform the operation, this updates eflags for us! - mov result, eax - pushfd // push the updated host flags onto the stack + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + sbb eax, src // perform the operation, this updates eflags for us! + mov result, eax + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags - e->ContextRecord->EFlags = eflags; + + // Write back the flags + e->ContextRecord->EFlags = eflags; // Write result back EmuX86_Addr_Write(opAddr, static_cast(result)); return true; } - -// Set Byte on Condition -// https://c9x.me/x86/html/file_module_x86_id_288.html + +// Set Byte on Condition +// https://c9x.me/x86/html/file_module_x86_id_288.html inline bool EmuX86_Opcode_SETcc(LPEXCEPTION_POINTERS e, _DInst& info, bool condition) { uint8_t value = (condition) ? 1 : 0; @@ -1403,25 +1403,25 @@ bool EmuX86_Opcode_SHL(LPEXCEPTION_POINTERS e, _DInst& info) uint32_t dest = EmuX86_Addr_Read(opAddr); - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - uint8_t byteSrc = src; - - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - mov cl, byteSrc - shl eax, cl // perform the operation, this updates eflags for us! - mov result, eax - pushfd // push the updated host flags onto the stack + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + uint8_t byteSrc = src; + + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + mov cl, byteSrc + shl eax, cl // perform the operation, this updates eflags for us! + mov result, eax + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags - e->ContextRecord->EFlags = eflags; - + + // Write back the flags + e->ContextRecord->EFlags = eflags; + // Write result back EmuX86_Addr_Write(opAddr, static_cast(result)); @@ -1443,32 +1443,32 @@ bool EmuX86_Opcode_SHR(LPEXCEPTION_POINTERS e, _DInst& info) uint32_t dest = EmuX86_Addr_Read(opAddr); - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - uint8_t byteSrc = src; - - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - mov cl, byteSrc - shr eax, cl // perform the operation, this updates eflags for us! - mov result, eax - pushfd // push the updated host flags onto the stack + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + uint8_t byteSrc = src; + + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + mov cl, byteSrc + shr eax, cl // perform the operation, this updates eflags for us! + mov result, eax + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags - e->ContextRecord->EFlags = eflags; - + + // Write back the flags + e->ContextRecord->EFlags = eflags; + // Write result back EmuX86_Addr_Write(opAddr, static_cast(result)); return true; } -void EmuX86_Opcode_STI() +void EmuX86_Opcode_STI() { g_bEnableAllInterrupts = true; } @@ -1490,21 +1490,21 @@ bool EmuX86_Opcode_SUB(LPEXCEPTION_POINTERS e, _DInst& info) if (info.ops[0].size > info.ops[1].size) { SignExtend32(src, info.ops[1].size); } - - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - sub eax, src // perform the operation, this updates eflags for us! - mov result, eax - pushfd // push the updated host flags onto the stack + + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + sub eax, src // perform the operation, this updates eflags for us! + mov result, eax + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags - e->ContextRecord->EFlags = eflags; + + // Write back the flags + e->ContextRecord->EFlags = eflags; // Write result back EmuX86_Addr_Write(opAddr, static_cast(result)); @@ -1524,23 +1524,23 @@ bool EmuX86_Opcode_TEST(LPEXCEPTION_POINTERS e, _DInst& info) if (!EmuX86_Operand_Read(e, info, 1, &src)) return false; - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - test eax, src // perform the operation, this updates eflags for us! - pushfd // push the updated host flags onto the stack + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + test eax, src // perform the operation, this updates eflags for us! + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags + + // Write back the flags e->ContextRecord->EFlags = eflags; return true; -} - +} + bool EmuX86_Opcode_XOR(LPEXCEPTION_POINTERS e, _DInst& info) { // Read value from Source and Destination @@ -1559,28 +1559,28 @@ bool EmuX86_Opcode_XOR(LPEXCEPTION_POINTERS e, _DInst& info) SignExtend32(src, info.ops[1].size); } - uint32_t result = 0; - uint32_t eflags = e->ContextRecord->EFlags; - __asm { - push eflags // push context eflags on the stack - popfd // pop context eflags into host eflags - mov eax, dest - xor eax, src // perform the operation, this updates eflags for us! - mov result, eax - pushfd // push the updated host flags onto the stack + uint32_t result = 0; + uint32_t eflags = e->ContextRecord->EFlags; + __asm { + push eflags // push context eflags on the stack + popfd // pop context eflags into host eflags + mov eax, dest + xor eax, src // perform the operation, this updates eflags for us! + mov result, eax + pushfd // push the updated host flags onto the stack pop eflags // pop the updated host flags back into our eflags register } - - // Write back the flags - e->ContextRecord->EFlags = eflags; + + // Write back the flags + e->ContextRecord->EFlags = eflags; // Write back the result EmuX86_Addr_Write(opAddr, result); return true; -} - +} + bool EmuX86_DecodeOpcode(const uint8_t *Eip, _DInst &info) { unsigned int decodedInstructionsCount = 0; @@ -1597,29 +1597,29 @@ bool EmuX86_DecodeOpcode(const uint8_t *Eip, _DInst &info) // halt cleanly after reaching maxInstructions 1. So instead, just call distorm : distorm_decompose(&ci, &info, /*maxInstructions=*/1, &decodedInstructionsCount); // and check if it successfully decoded one instruction : - return (decodedInstructionsCount == 1); + return (decodedInstructionsCount == 1); } - -const char *Distorm_RegStrings[/*_RegisterType*/] = { - "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", - "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D", - "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W", - "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B", - "SPL", "BPL", "SIL", "DIL", - "ES", "CS", "SS", "DS", "FS", "GS", - "RIP", - "ST0", "ST1", "ST2", "ST3", "ST4", "ST5", "ST6", "ST7", - "MM0", "MM1", "MM2", "MM3", "MM4", "MM5", "MM6", "MM7", - "XMM0", "XMM1", "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7", "XMM8", "XMM9", "XMM10", "XMM11", "XMM12", "XMM13", "XMM14", "XMM15", - "YMM0", "YMM1", "YMM2", "YMM3", "YMM4", "YMM5", "YMM6", "YMM7", "YMM8", "YMM9", "YMM10", "YMM11", "YMM12", "YMM13", "YMM14", "YMM15", - "CR0", "UNUSED0", "CR2", "CR3", "CR4", "UNUSED1", "UNUSED2", "UNUSED3", "CR8", - "DR0", "DR1", "DR2", "DR3", "UNUSED4", "UNUSED5", "DR6", "DR7", -}; - -char *Distorm_OpcodeString(const int opcode) -{ - // Note : Distorm's GET_MNEMONIC_NAME() doesn't link somehow... - switch (opcode) { + +const char *Distorm_RegStrings[/*_RegisterType*/] = { + "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", + "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D", + "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W", + "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B", + "SPL", "BPL", "SIL", "DIL", + "ES", "CS", "SS", "DS", "FS", "GS", + "RIP", + "ST0", "ST1", "ST2", "ST3", "ST4", "ST5", "ST6", "ST7", + "MM0", "MM1", "MM2", "MM3", "MM4", "MM5", "MM6", "MM7", + "XMM0", "XMM1", "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7", "XMM8", "XMM9", "XMM10", "XMM11", "XMM12", "XMM13", "XMM14", "XMM15", + "YMM0", "YMM1", "YMM2", "YMM3", "YMM4", "YMM5", "YMM6", "YMM7", "YMM8", "YMM9", "YMM10", "YMM11", "YMM12", "YMM13", "YMM14", "YMM15", + "CR0", "UNUSED0", "CR2", "CR3", "CR4", "UNUSED1", "UNUSED2", "UNUSED3", "CR8", + "DR0", "DR1", "DR2", "DR3", "UNUSED4", "UNUSED5", "DR6", "DR7", +}; + +char *Distorm_OpcodeString(const int opcode) +{ + // Note : Distorm's GET_MNEMONIC_NAME() doesn't link somehow... + switch (opcode) { case I_AAA: return "AAA"; case I_AAD: return "AAD"; case I_AAM: return "AAM"; @@ -1627,1265 +1627,1265 @@ char *Distorm_OpcodeString(const int opcode) case I_ADC: return "ADC"; case I_ADD: return "ADD"; case I_ADDPD: return "ADDPD"; - case I_ADDPS: return "ADDPS"; + case I_ADDPS: return "ADDPS"; case I_ADDSD: return "ADDSD"; case I_ADDSS: return "ADDSS"; case I_ADDSUBPD: return "ADDSUBPD"; case I_ADDSUBPS: return "ADDSUBPS"; - case I_AESDEC: return "AESDEC"; + case I_AESDEC: return "AESDEC"; case I_AESDECLAST: return "AESDECLAST"; case I_AESENC: return "AESENC"; case I_AESENCLAST: return "AESENCLAST"; - case I_AESIMC: return "AESIMC"; + case I_AESIMC: return "AESIMC"; case I_AESKEYGENASSIST: return "AESKEYGENASSIST"; case I_AND: return "AND"; case I_ANDNPD: return "ANDNPD"; case I_ANDNPS: return "ANDNPS"; - case I_ANDPD: return "ANDPD"; + case I_ANDPD: return "ANDPD"; case I_ANDPS: return "ANDPS"; case I_ARPL: return "ARPL"; case I_BLENDPD: return "BLENDPD"; case I_BLENDPS: return "BLENDPS"; - case I_BLENDVPD: return "BLENDVPD"; + case I_BLENDVPD: return "BLENDVPD"; case I_BLENDVPS: return "BLENDVPS"; case I_BOUND: return "BOUND"; case I_BSF: return "BSF"; case I_BSR: return "BSR"; - case I_BSWAP: return "BSWAP"; + case I_BSWAP: return "BSWAP"; case I_BT: return "BT"; case I_BTC: return "BTC"; case I_BTR: return "BTR"; case I_BTS: return "BTS"; case I_CALL: return "CALL"; - case I_CALL_FAR: return "CALL_FAR"; + case I_CALL_FAR: return "CALL_FAR"; case I_CBW: return "CBW"; case I_CDQ: return "CDQ"; case I_CDQE: return "CDQE"; case I_CLC: return "CLC"; case I_CLD: return "CLD"; - case I_CLFLUSH: return "CLFLUSH"; + case I_CLFLUSH: return "CLFLUSH"; case I_CLGI: return "CLGI"; case I_CLI: return "CLI"; case I_CLTS: return "CLTS"; case I_CMC: return "CMC"; case I_CMOVA: return "CMOVA"; - case I_CMOVAE: return "CMOVAE"; + case I_CMOVAE: return "CMOVAE"; case I_CMOVB: return "CMOVB"; case I_CMOVBE: return "CMOVBE"; case I_CMOVG: return "CMOVG"; case I_CMOVGE: return "CMOVGE"; - case I_CMOVL: return "CMOVL"; + case I_CMOVL: return "CMOVL"; case I_CMOVLE: return "CMOVLE"; case I_CMOVNO: return "CMOVNO"; case I_CMOVNP: return "CMOVNP"; case I_CMOVNS: return "CMOVNS"; - case I_CMOVNZ: return "CMOVNZ"; + case I_CMOVNZ: return "CMOVNZ"; case I_CMOVO: return "CMOVO"; case I_CMOVP: return "CMOVP"; case I_CMOVS: return "CMOVS"; case I_CMOVZ: return "CMOVZ"; - case I_CMP: return "CMP"; + case I_CMP: return "CMP"; case I_CMPEQPD: return "CMPEQPD"; case I_CMPEQPS: return "CMPEQPS"; case I_CMPEQSD: return "CMPEQSD"; case I_CMPEQSS: return "CMPEQSS"; - case I_CMPLEPD: return "CMPLEPD"; + case I_CMPLEPD: return "CMPLEPD"; case I_CMPLEPS: return "CMPLEPS"; case I_CMPLESD: return "CMPLESD"; case I_CMPLESS: return "CMPLESS"; case I_CMPLTPD: return "CMPLTPD"; - case I_CMPLTPS: return "CMPLTPS"; + case I_CMPLTPS: return "CMPLTPS"; case I_CMPLTSD: return "CMPLTSD"; case I_CMPLTSS: return "CMPLTSS"; case I_CMPNEQPD: return "CMPNEQPD"; case I_CMPNEQPS: return "CMPNEQPS"; - case I_CMPNEQSD: return "CMPNEQSD"; + case I_CMPNEQSD: return "CMPNEQSD"; case I_CMPNEQSS: return "CMPNEQSS"; case I_CMPNLEPD: return "CMPNLEPD"; case I_CMPNLEPS: return "CMPNLEPS"; - case I_CMPNLESD: return "CMPNLESD"; + case I_CMPNLESD: return "CMPNLESD"; case I_CMPNLESS: return "CMPNLESS"; case I_CMPNLTPD: return "CMPNLTPD"; case I_CMPNLTPS: return "CMPNLTPS"; - case I_CMPNLTSD: return "CMPNLTSD"; + case I_CMPNLTSD: return "CMPNLTSD"; case I_CMPNLTSS: return "CMPNLTSS"; case I_CMPORDPD: return "CMPORDPD"; case I_CMPORDPS: return "CMPORDPS"; - case I_CMPORDSD: return "CMPORDSD"; + case I_CMPORDSD: return "CMPORDSD"; case I_CMPORDSS: return "CMPORDSS"; case I_CMPS: return "CMPS"; case I_CMPUNORDPD: return "CMPUNORDPD"; case I_CMPUNORDPS: return "CMPUNORDPS"; - case I_CMPUNORDSD: return "CMPUNORDSD"; + case I_CMPUNORDSD: return "CMPUNORDSD"; case I_CMPUNORDSS: return "CMPUNORDSS"; case I_CMPXCHG: return "CMPXCHG"; case I_CMPXCHG16B: return "CMPXCHG16B"; - case I_CMPXCHG8B: return "CMPXCHG8B"; + case I_CMPXCHG8B: return "CMPXCHG8B"; case I_COMISD: return "COMISD"; case I_COMISS: return "COMISS"; case I_CPUID: return "CPUID"; case I_CQO: return "CQO"; - case I_CRC32: return "CRC32"; + case I_CRC32: return "CRC32"; case I_CVTDQ2PD: return "CVTDQ2PD"; case I_CVTDQ2PS: return "CVTDQ2PS"; case I_CVTPD2DQ: return "CVTPD2DQ"; case I_CVTPD2PI: return "CVTPD2PI"; - case I_CVTPD2PS: return "CVTPD2PS"; + case I_CVTPD2PS: return "CVTPD2PS"; case I_CVTPH2PS: return "CVTPH2PS"; case I_CVTPI2PD: return "CVTPI2PD"; case I_CVTPI2PS: return "CVTPI2PS"; - case I_CVTPS2DQ: return "CVTPS2DQ"; + case I_CVTPS2DQ: return "CVTPS2DQ"; case I_CVTPS2PD: return "CVTPS2PD"; case I_CVTPS2PH: return "CVTPS2PH"; case I_CVTPS2PI: return "CVTPS2PI"; - case I_CVTSD2SI: return "CVTSD2SI"; + case I_CVTSD2SI: return "CVTSD2SI"; case I_CVTSD2SS: return "CVTSD2SS"; case I_CVTSI2SD: return "CVTSI2SD"; case I_CVTSI2SS: return "CVTSI2SS"; - case I_CVTSS2SD: return "CVTSS2SD"; + case I_CVTSS2SD: return "CVTSS2SD"; case I_CVTSS2SI: return "CVTSS2SI"; case I_CVTTPD2DQ: return "CVTTPD2DQ"; case I_CVTTPD2PI: return "CVTTPD2PI"; - case I_CVTTPS2DQ: return "CVTTPS2DQ"; + case I_CVTTPS2DQ: return "CVTTPS2DQ"; case I_CVTTPS2PI: return "CVTTPS2PI"; case I_CVTTSD2SI: return "CVTTSD2SI"; case I_CVTTSS2SI: return "CVTTSS2SI"; - case I_CWD: return "CWD"; + case I_CWD: return "CWD"; case I_CWDE: return "CWDE"; case I_DAA: return "DAA"; case I_DAS: return "DAS"; case I_DEC: return "DEC"; case I_DIV: return "DIV"; - case I_DIVPD: return "DIVPD"; + case I_DIVPD: return "DIVPD"; case I_DIVPS: return "DIVPS"; case I_DIVSD: return "DIVSD"; case I_DIVSS: return "DIVSS"; case I_DPPD: return "DPPD"; - case I_DPPS: return "DPPS"; + case I_DPPS: return "DPPS"; case I_EMMS: return "EMMS"; case I_ENTER: return "ENTER"; case I_EXTRACTPS: return "EXTRACTPS"; case I_EXTRQ: return "EXTRQ"; - case I_F2XM1: return "F2XM1"; + case I_F2XM1: return "F2XM1"; case I_FABS: return "FABS"; case I_FADD: return "FADD"; case I_FADDP: return "FADDP"; case I_FBLD: return "FBLD"; - case I_FBSTP: return "FBSTP"; + case I_FBSTP: return "FBSTP"; case I_FCHS: return "FCHS"; case I_FCLEX: return "FCLEX"; case I_FCMOVB: return "FCMOVB"; case I_FCMOVBE: return "FCMOVBE"; - case I_FCMOVE: return "FCMOVE"; + case I_FCMOVE: return "FCMOVE"; case I_FCMOVNB: return "FCMOVNB"; case I_FCMOVNBE: return "FCMOVNBE"; case I_FCMOVNE: return "FCMOVNE"; case I_FCMOVNU: return "FCMOVNU"; - case I_FCMOVU: return "FCMOVU"; + case I_FCMOVU: return "FCMOVU"; case I_FCOM: return "FCOM"; case I_FCOMI: return "FCOMI"; case I_FCOMIP: return "FCOMIP"; case I_FCOMP: return "FCOMP"; - case I_FCOMPP: return "FCOMPP"; + case I_FCOMPP: return "FCOMPP"; case I_FCOS: return "FCOS"; case I_FDECSTP: return "FDECSTP"; case I_FDIV: return "FDIV"; case I_FDIVP: return "FDIVP"; - case I_FDIVR: return "FDIVR"; + case I_FDIVR: return "FDIVR"; case I_FDIVRP: return "FDIVRP"; case I_FEDISI: return "FEDISI"; case I_FEMMS: return "FEMMS"; case I_FENI: return "FENI"; - case I_FFREE: return "FFREE"; + case I_FFREE: return "FFREE"; case I_FIADD: return "FIADD"; case I_FICOM: return "FICOM"; case I_FICOMP: return "FICOMP"; case I_FIDIV: return "FIDIV"; - case I_FIDIVR: return "FIDIVR"; + case I_FIDIVR: return "FIDIVR"; case I_FILD: return "FILD"; case I_FIMUL: return "FIMUL"; case I_FINCSTP: return "FINCSTP"; case I_FINIT: return "FINIT"; - case I_FIST: return "FIST"; + case I_FIST: return "FIST"; case I_FISTP: return "FISTP"; case I_FISTTP: return "FISTTP"; case I_FISUB: return "FISUB"; case I_FISUBR: return "FISUBR"; - case I_FLD: return "FLD"; + case I_FLD: return "FLD"; case I_FLD1: return "FLD1"; case I_FLDCW: return "FLDCW"; case I_FLDENV: return "FLDENV"; case I_FLDL2E: return "FLDL2E"; - case I_FLDL2T: return "FLDL2T"; + case I_FLDL2T: return "FLDL2T"; case I_FLDLG2: return "FLDLG2"; case I_FLDLN2: return "FLDLN2"; case I_FLDPI: return "FLDPI"; case I_FLDZ: return "FLDZ"; - case I_FMUL: return "FMUL"; + case I_FMUL: return "FMUL"; case I_FMULP: return "FMULP"; case I_FNCLEX: return "FNCLEX"; case I_FNINIT: return "FNINIT"; case I_FNOP: return "FNOP"; - case I_FNSAVE: return "FNSAVE"; + case I_FNSAVE: return "FNSAVE"; case I_FNSTCW: return "FNSTCW"; case I_FNSTENV: return "FNSTENV"; case I_FNSTSW: return "FNSTSW"; case I_FPATAN: return "FPATAN"; - case I_FPREM: return "FPREM"; + case I_FPREM: return "FPREM"; case I_FPREM1: return "FPREM1"; case I_FPTAN: return "FPTAN"; case I_FRNDINT: return "FRNDINT"; case I_FRSTOR: return "FRSTOR"; - case I_FSAVE: return "FSAVE"; + case I_FSAVE: return "FSAVE"; case I_FSCALE: return "FSCALE"; case I_FSETPM: return "FSETPM"; case I_FSIN: return "FSIN"; case I_FSINCOS: return "FSINCOS"; - case I_FSQRT: return "FSQRT"; + case I_FSQRT: return "FSQRT"; case I_FST: return "FST"; case I_FSTCW: return "FSTCW"; case I_FSTENV: return "FSTENV"; case I_FSTP: return "FSTP"; - case I_FSTSW: return "FSTSW"; + case I_FSTSW: return "FSTSW"; case I_FSUB: return "FSUB"; case I_FSUBP: return "FSUBP"; case I_FSUBR: return "FSUBR"; case I_FSUBRP: return "FSUBRP"; - case I_FTST: return "FTST"; + case I_FTST: return "FTST"; case I_FUCOM: return "FUCOM"; case I_FUCOMI: return "FUCOMI"; case I_FUCOMIP: return "FUCOMIP"; case I_FUCOMP: return "FUCOMP"; - case I_FUCOMPP: return "FUCOMPP"; + case I_FUCOMPP: return "FUCOMPP"; case I_FXAM: return "FXAM"; case I_FXCH: return "FXCH"; case I_FXRSTOR: return "FXRSTOR"; case I_FXRSTOR64: return "FXRSTOR64"; - case I_FXSAVE: return "FXSAVE"; + case I_FXSAVE: return "FXSAVE"; case I_FXSAVE64: return "FXSAVE64"; case I_FXTRACT: return "FXTRACT"; case I_FYL2X: return "FYL2X"; case I_FYL2XP1: return "FYL2XP1"; - case I_GETSEC: return "GETSEC"; + case I_GETSEC: return "GETSEC"; case I_HADDPD: return "HADDPD"; case I_HADDPS: return "HADDPS"; case I_HLT: return "HLT"; case I_HSUBPD: return "HSUBPD"; - case I_HSUBPS: return "HSUBPS"; + case I_HSUBPS: return "HSUBPS"; case I_IDIV: return "IDIV"; case I_IMUL: return "IMUL"; case I_IN: return "IN"; case I_INC: return "INC"; case I_INS: return "INS"; - case I_INSERTPS: return "INSERTPS"; + case I_INSERTPS: return "INSERTPS"; case I_INSERTQ: return "INSERTQ"; case I_INT: return "INT"; case I_INT1: return "INT1"; case I_INTO: return "INTO"; - case I_INT_3: return "INT_3"; + case I_INT_3: return "INT_3"; case I_INVD: return "INVD"; case I_INVEPT: return "INVEPT"; case I_INVLPG: return "INVLPG"; case I_INVLPGA: return "INVLPGA"; - case I_INVPCID: return "INVPCID"; + case I_INVPCID: return "INVPCID"; case I_INVVPID: return "INVVPID"; case I_IRET: return "IRET"; case I_JA: return "JA"; case I_JAE: return "JAE"; - case I_JB: return "JB"; + case I_JB: return "JB"; case I_JBE: return "JBE"; case I_JCXZ: return "JCXZ"; case I_JECXZ: return "JECXZ"; case I_JG: return "JG"; case I_JGE: return "JGE"; - case I_JL: return "JL"; + case I_JL: return "JL"; case I_JLE: return "JLE"; case I_JMP: return "JMP"; case I_JMP_FAR: return "JMP_FAR"; case I_JNO: return "JNO"; case I_JNP: return "JNP"; - case I_JNS: return "JNS"; + case I_JNS: return "JNS"; case I_JNZ: return "JNZ"; case I_JO: return "JO"; case I_JP: return "JP"; case I_JRCXZ: return "JRCXZ"; case I_JS: return "JS"; - case I_JZ: return "JZ"; + case I_JZ: return "JZ"; case I_LAHF: return "LAHF"; case I_LAR: return "LAR"; case I_LDDQU: return "LDDQU"; case I_LDMXCSR: return "LDMXCSR"; case I_LDS: return "LDS"; - case I_LEA: return "LEA"; + case I_LEA: return "LEA"; case I_LEAVE: return "LEAVE"; case I_LES: return "LES"; case I_LFENCE: return "LFENCE"; case I_LFS: return "LFS"; case I_LGDT: return "LGDT"; - case I_LGS: return "LGS"; + case I_LGS: return "LGS"; case I_LIDT: return "LIDT"; case I_LLDT: return "LLDT"; case I_LMSW: return "LMSW"; case I_LODS: return "LODS"; case I_LOOP: return "LOOP"; - case I_LOOPNZ: return "LOOPNZ"; + case I_LOOPNZ: return "LOOPNZ"; case I_LOOPZ: return "LOOPZ"; case I_LSL: return "LSL"; case I_LSS: return "LSS"; case I_LTR: return "LTR"; case I_LZCNT: return "LZCNT"; - case I_MASKMOVDQU: return "MASKMOVDQU"; + case I_MASKMOVDQU: return "MASKMOVDQU"; case I_MASKMOVQ: return "MASKMOVQ"; case I_MAXPD: return "MAXPD"; case I_MAXPS: return "MAXPS"; case I_MAXSD: return "MAXSD"; - case I_MAXSS: return "MAXSS"; + case I_MAXSS: return "MAXSS"; case I_MFENCE: return "MFENCE"; case I_MINPD: return "MINPD"; case I_MINPS: return "MINPS"; case I_MINSD: return "MINSD"; - case I_MINSS: return "MINSS"; + case I_MINSS: return "MINSS"; case I_MONITOR: return "MONITOR"; case I_MOV: return "MOV"; case I_MOVAPD: return "MOVAPD"; case I_MOVAPS: return "MOVAPS"; - case I_MOVBE: return "MOVBE"; + case I_MOVBE: return "MOVBE"; case I_MOVD: return "MOVD"; case I_MOVDDUP: return "MOVDDUP"; case I_MOVDQ2Q: return "MOVDQ2Q"; case I_MOVDQA: return "MOVDQA"; - case I_MOVDQU: return "MOVDQU"; + case I_MOVDQU: return "MOVDQU"; case I_MOVHLPS: return "MOVHLPS"; case I_MOVHPD: return "MOVHPD"; case I_MOVHPS: return "MOVHPS"; case I_MOVLHPS: return "MOVLHPS"; - case I_MOVLPD: return "MOVLPD"; + case I_MOVLPD: return "MOVLPD"; case I_MOVLPS: return "MOVLPS"; case I_MOVMSKPD: return "MOVMSKPD"; case I_MOVMSKPS: return "MOVMSKPS"; case I_MOVNTDQ: return "MOVNTDQ"; - case I_MOVNTDQA: return "MOVNTDQA"; + case I_MOVNTDQA: return "MOVNTDQA"; case I_MOVNTI: return "MOVNTI"; case I_MOVNTPD: return "MOVNTPD"; case I_MOVNTPS: return "MOVNTPS"; case I_MOVNTQ: return "MOVNTQ"; - case I_MOVNTSD: return "MOVNTSD"; + case I_MOVNTSD: return "MOVNTSD"; case I_MOVNTSS: return "MOVNTSS"; case I_MOVQ: return "MOVQ"; case I_MOVQ2DQ: return "MOVQ2DQ"; case I_MOVS: return "MOVS"; - case I_MOVSD: return "MOVSD"; + case I_MOVSD: return "MOVSD"; case I_MOVSHDUP: return "MOVSHDUP"; case I_MOVSLDUP: return "MOVSLDUP"; case I_MOVSS: return "MOVSS"; case I_MOVSX: return "MOVSX"; - case I_MOVSXD: return "MOVSXD"; + case I_MOVSXD: return "MOVSXD"; case I_MOVUPD: return "MOVUPD"; case I_MOVUPS: return "MOVUPS"; case I_MOVZX: return "MOVZX"; case I_MPSADBW: return "MPSADBW"; - case I_MUL: return "MUL"; + case I_MUL: return "MUL"; case I_MULPD: return "MULPD"; case I_MULPS: return "MULPS"; case I_MULSD: return "MULSD"; case I_MULSS: return "MULSS"; - case I_MWAIT: return "MWAIT"; + case I_MWAIT: return "MWAIT"; case I_NEG: return "NEG"; case I_NOP: return "NOP"; case I_NOT: return "NOT"; case I_OR: return "OR"; case I_ORPD: return "ORPD"; - case I_ORPS: return "ORPS"; + case I_ORPS: return "ORPS"; case I_OUT: return "OUT"; case I_OUTS: return "OUTS"; case I_PABSB: return "PABSB"; case I_PABSD: return "PABSD"; case I_PABSW: return "PABSW"; - case I_PACKSSDW: return "PACKSSDW"; + case I_PACKSSDW: return "PACKSSDW"; case I_PACKSSWB: return "PACKSSWB"; case I_PACKUSDW: return "PACKUSDW"; case I_PACKUSWB: return "PACKUSWB"; - case I_PADDB: return "PADDB"; + case I_PADDB: return "PADDB"; case I_PADDD: return "PADDD"; case I_PADDQ: return "PADDQ"; case I_PADDSB: return "PADDSB"; case I_PADDSW: return "PADDSW"; - case I_PADDUSB: return "PADDUSB"; + case I_PADDUSB: return "PADDUSB"; case I_PADDUSW: return "PADDUSW"; case I_PADDW: return "PADDW"; case I_PALIGNR: return "PALIGNR"; case I_PAND: return "PAND"; - case I_PANDN: return "PANDN"; + case I_PANDN: return "PANDN"; case I_PAUSE: return "PAUSE"; case I_PAVGB: return "PAVGB"; case I_PAVGUSB: return "PAVGUSB"; case I_PAVGW: return "PAVGW"; - case I_PBLENDVB: return "PBLENDVB"; + case I_PBLENDVB: return "PBLENDVB"; case I_PBLENDW: return "PBLENDW"; case I_PCLMULQDQ: return "PCLMULQDQ"; case I_PCMPEQB: return "PCMPEQB"; - case I_PCMPEQD: return "PCMPEQD"; + case I_PCMPEQD: return "PCMPEQD"; case I_PCMPEQQ: return "PCMPEQQ"; case I_PCMPEQW: return "PCMPEQW"; case I_PCMPESTRI: return "PCMPESTRI"; - case I_PCMPESTRM: return "PCMPESTRM"; + case I_PCMPESTRM: return "PCMPESTRM"; case I_PCMPGTB: return "PCMPGTB"; case I_PCMPGTD: return "PCMPGTD"; case I_PCMPGTQ: return "PCMPGTQ"; - case I_PCMPGTW: return "PCMPGTW"; + case I_PCMPGTW: return "PCMPGTW"; case I_PCMPISTRI: return "PCMPISTRI"; case I_PCMPISTRM: return "PCMPISTRM"; case I_PEXTRB: return "PEXTRB"; - case I_PEXTRD: return "PEXTRD"; + case I_PEXTRD: return "PEXTRD"; case I_PEXTRQ: return "PEXTRQ"; case I_PEXTRW: return "PEXTRW"; case I_PF2ID: return "PF2ID"; case I_PF2IW: return "PF2IW"; - case I_PFACC: return "PFACC"; + case I_PFACC: return "PFACC"; case I_PFADD: return "PFADD"; case I_PFCMPEQ: return "PFCMPEQ"; case I_PFCMPGE: return "PFCMPGE"; case I_PFCMPGT: return "PFCMPGT"; - case I_PFMAX: return "PFMAX"; + case I_PFMAX: return "PFMAX"; case I_PFMIN: return "PFMIN"; case I_PFMUL: return "PFMUL"; case I_PFNACC: return "PFNACC"; case I_PFPNACC: return "PFPNACC"; - case I_PFRCP: return "PFRCP"; + case I_PFRCP: return "PFRCP"; case I_PFRCPIT1: return "PFRCPIT1"; case I_PFRCPIT2: return "PFRCPIT2"; case I_PFRSQIT1: return "PFRSQIT1"; case I_PFRSQRT: return "PFRSQRT"; - case I_PFSUB: return "PFSUB"; + case I_PFSUB: return "PFSUB"; case I_PFSUBR: return "PFSUBR"; case I_PHADDD: return "PHADDD"; case I_PHADDSW: return "PHADDSW"; case I_PHADDW: return "PHADDW"; - case I_PHMINPOSUW: return "PHMINPOSUW"; + case I_PHMINPOSUW: return "PHMINPOSUW"; case I_PHSUBD: return "PHSUBD"; case I_PHSUBSW: return "PHSUBSW"; case I_PHSUBW: return "PHSUBW"; case I_PI2FD: return "PI2FD"; - case I_PI2FW: return "PI2FW"; + case I_PI2FW: return "PI2FW"; case I_PINSRB: return "PINSRB"; case I_PINSRD: return "PINSRD"; case I_PINSRQ: return "PINSRQ"; case I_PINSRW: return "PINSRW"; - case I_PMADDUBSW: return "PMADDUBSW"; + case I_PMADDUBSW: return "PMADDUBSW"; case I_PMADDWD: return "PMADDWD"; case I_PMAXSB: return "PMAXSB"; case I_PMAXSD: return "PMAXSD"; case I_PMAXSW: return "PMAXSW"; - case I_PMAXUB: return "PMAXUB"; + case I_PMAXUB: return "PMAXUB"; case I_PMAXUD: return "PMAXUD"; case I_PMAXUW: return "PMAXUW"; case I_PMINSB: return "PMINSB"; case I_PMINSD: return "PMINSD"; - case I_PMINSW: return "PMINSW"; + case I_PMINSW: return "PMINSW"; case I_PMINUB: return "PMINUB"; case I_PMINUD: return "PMINUD"; case I_PMINUW: return "PMINUW"; case I_PMOVMSKB: return "PMOVMSKB"; - case I_PMOVSXBD: return "PMOVSXBD"; + case I_PMOVSXBD: return "PMOVSXBD"; case I_PMOVSXBQ: return "PMOVSXBQ"; case I_PMOVSXBW: return "PMOVSXBW"; case I_PMOVSXDQ: return "PMOVSXDQ"; - case I_PMOVSXWD: return "PMOVSXWD"; + case I_PMOVSXWD: return "PMOVSXWD"; case I_PMOVSXWQ: return "PMOVSXWQ"; case I_PMOVZXBD: return "PMOVZXBD"; case I_PMOVZXBQ: return "PMOVZXBQ"; - case I_PMOVZXBW: return "PMOVZXBW"; + case I_PMOVZXBW: return "PMOVZXBW"; case I_PMOVZXDQ: return "PMOVZXDQ"; case I_PMOVZXWD: return "PMOVZXWD"; case I_PMOVZXWQ: return "PMOVZXWQ"; - case I_PMULDQ: return "PMULDQ"; + case I_PMULDQ: return "PMULDQ"; case I_PMULHRSW: return "PMULHRSW"; case I_PMULHRW: return "PMULHRW"; case I_PMULHUW: return "PMULHUW"; case I_PMULHW: return "PMULHW"; - case I_PMULLD: return "PMULLD"; + case I_PMULLD: return "PMULLD"; case I_PMULLW: return "PMULLW"; case I_PMULUDQ: return "PMULUDQ"; case I_POP: return "POP"; case I_POPA: return "POPA"; - case I_POPCNT: return "POPCNT"; + case I_POPCNT: return "POPCNT"; case I_POPF: return "POPF"; case I_POR: return "POR"; case I_PREFETCH: return "PREFETCH"; case I_PREFETCHNTA: return "PREFETCHNTA"; - case I_PREFETCHT0: return "PREFETCHT0"; + case I_PREFETCHT0: return "PREFETCHT0"; case I_PREFETCHT1: return "PREFETCHT1"; case I_PREFETCHT2: return "PREFETCHT2"; case I_PREFETCHW: return "PREFETCHW"; - case I_PSADBW: return "PSADBW"; + case I_PSADBW: return "PSADBW"; case I_PSHUFB: return "PSHUFB"; case I_PSHUFD: return "PSHUFD"; case I_PSHUFHW: return "PSHUFHW"; case I_PSHUFLW: return "PSHUFLW"; - case I_PSHUFW: return "PSHUFW"; + case I_PSHUFW: return "PSHUFW"; case I_PSIGNB: return "PSIGNB"; case I_PSIGND: return "PSIGND"; case I_PSIGNW: return "PSIGNW"; case I_PSLLD: return "PSLLD"; - case I_PSLLDQ: return "PSLLDQ"; + case I_PSLLDQ: return "PSLLDQ"; case I_PSLLQ: return "PSLLQ"; case I_PSLLW: return "PSLLW"; case I_PSRAD: return "PSRAD"; case I_PSRAW: return "PSRAW"; - case I_PSRLD: return "PSRLD"; + case I_PSRLD: return "PSRLD"; case I_PSRLDQ: return "PSRLDQ"; case I_PSRLQ: return "PSRLQ"; case I_PSRLW: return "PSRLW"; case I_PSUBB: return "PSUBB"; - case I_PSUBD: return "PSUBD"; + case I_PSUBD: return "PSUBD"; case I_PSUBQ: return "PSUBQ"; case I_PSUBSB: return "PSUBSB"; case I_PSUBSW: return "PSUBSW"; case I_PSUBUSB: return "PSUBUSB"; - case I_PSUBUSW: return "PSUBUSW"; + case I_PSUBUSW: return "PSUBUSW"; case I_PSUBW: return "PSUBW"; case I_PSWAPD: return "PSWAPD"; case I_PTEST: return "PTEST"; case I_PUNPCKHBW: return "PUNPCKHBW"; - case I_PUNPCKHDQ: return "PUNPCKHDQ"; + case I_PUNPCKHDQ: return "PUNPCKHDQ"; case I_PUNPCKHQDQ: return "PUNPCKHQDQ"; case I_PUNPCKHWD: return "PUNPCKHWD"; case I_PUNPCKLBW: return "PUNPCKLBW"; - case I_PUNPCKLDQ: return "PUNPCKLDQ"; + case I_PUNPCKLDQ: return "PUNPCKLDQ"; case I_PUNPCKLQDQ: return "PUNPCKLQDQ"; case I_PUNPCKLWD: return "PUNPCKLWD"; case I_PUSH: return "PUSH"; - case I_PUSHA: return "PUSHA"; + case I_PUSHA: return "PUSHA"; case I_PUSHF: return "PUSHF"; case I_PXOR: return "PXOR"; case I_RCL: return "RCL"; case I_RCPPS: return "RCPPS"; case I_RCPSS: return "RCPSS"; - case I_RCR: return "RCR"; + case I_RCR: return "RCR"; case I_RDFSBASE: return "RDFSBASE"; case I_RDGSBASE: return "RDGSBASE"; case I_RDMSR: return "RDMSR"; case I_RDPMC: return "RDPMC"; - case I_RDRAND: return "RDRAND"; + case I_RDRAND: return "RDRAND"; case I_RDTSC: return "RDTSC"; case I_RDTSCP: return "RDTSCP"; case I_RET: return "RET"; case I_RETF: return "RETF"; - case I_ROL: return "ROL"; + case I_ROL: return "ROL"; case I_ROR: return "ROR"; case I_ROUNDPD: return "ROUNDPD"; case I_ROUNDPS: return "ROUNDPS"; case I_ROUNDSD: return "ROUNDSD"; - case I_ROUNDSS: return "ROUNDSS"; + case I_ROUNDSS: return "ROUNDSS"; case I_RSM: return "RSM"; case I_RSQRTPS: return "RSQRTPS"; case I_RSQRTSS: return "RSQRTSS"; case I_SAHF: return "SAHF"; - case I_SAL: return "SAL"; + case I_SAL: return "SAL"; case I_SALC: return "SALC"; case I_SAR: return "SAR"; case I_SBB: return "SBB"; case I_SCAS: return "SCAS"; case I_SETA: return "SETA"; - case I_SETAE: return "SETAE"; + case I_SETAE: return "SETAE"; case I_SETB: return "SETB"; case I_SETBE: return "SETBE"; case I_SETG: return "SETG"; case I_SETGE: return "SETGE"; case I_SETL: return "SETL"; - case I_SETLE: return "SETLE"; + case I_SETLE: return "SETLE"; case I_SETNO: return "SETNO"; case I_SETNP: return "SETNP"; case I_SETNS: return "SETNS"; case I_SETNZ: return "SETNZ"; - case I_SETO: return "SETO"; + case I_SETO: return "SETO"; case I_SETP: return "SETP"; case I_SETS: return "SETS"; case I_SETZ: return "SETZ"; case I_SFENCE: return "SFENCE"; case I_SGDT: return "SGDT"; - case I_SHL: return "SHL"; + case I_SHL: return "SHL"; case I_SHLD: return "SHLD"; case I_SHR: return "SHR"; case I_SHRD: return "SHRD"; case I_SHUFPD: return "SHUFPD"; case I_SHUFPS: return "SHUFPS"; - case I_SIDT: return "SIDT"; + case I_SIDT: return "SIDT"; case I_SKINIT: return "SKINIT"; case I_SLDT: return "SLDT"; case I_SMSW: return "SMSW"; case I_SQRTPD: return "SQRTPD"; - case I_SQRTPS: return "SQRTPS"; + case I_SQRTPS: return "SQRTPS"; case I_SQRTSD: return "SQRTSD"; case I_SQRTSS: return "SQRTSS"; case I_STC: return "STC"; case I_STD: return "STD"; - case I_STGI: return "STGI"; + case I_STGI: return "STGI"; case I_STI: return "STI"; case I_STMXCSR: return "STMXCSR"; case I_STOS: return "STOS"; case I_STR: return "STR"; case I_SUB: return "SUB"; - case I_SUBPD: return "SUBPD"; + case I_SUBPD: return "SUBPD"; case I_SUBPS: return "SUBPS"; case I_SUBSD: return "SUBSD"; case I_SUBSS: return "SUBSS"; case I_SWAPGS: return "SWAPGS"; - case I_SYSCALL: return "SYSCALL"; + case I_SYSCALL: return "SYSCALL"; case I_SYSENTER: return "SYSENTER"; case I_SYSEXIT: return "SYSEXIT"; case I_SYSRET: return "SYSRET"; case I_TEST: return "TEST"; - case I_TZCNT: return "TZCNT"; + case I_TZCNT: return "TZCNT"; case I_UCOMISD: return "UCOMISD"; case I_UCOMISS: return "UCOMISS"; case I_UD2: return "UD2"; case I_UNDEFINED: return "UNDEFINED"; - case I_UNPCKHPD: return "UNPCKHPD"; + case I_UNPCKHPD: return "UNPCKHPD"; case I_UNPCKHPS: return "UNPCKHPS"; case I_UNPCKLPD: return "UNPCKLPD"; case I_UNPCKLPS: return "UNPCKLPS"; - case I_VADDPD: return "VADDPD"; + case I_VADDPD: return "VADDPD"; case I_VADDPS: return "VADDPS"; case I_VADDSD: return "VADDSD"; case I_VADDSS: return "VADDSS"; case I_VADDSUBPD: return "VADDSUBPD"; - case I_VADDSUBPS: return "VADDSUBPS"; + case I_VADDSUBPS: return "VADDSUBPS"; case I_VAESDEC: return "VAESDEC"; case I_VAESDECLAST: return "VAESDECLAST"; case I_VAESENC: return "VAESENC"; - case I_VAESENCLAST: return "VAESENCLAST"; + case I_VAESENCLAST: return "VAESENCLAST"; case I_VAESIMC: return "VAESIMC"; case I_VAESKEYGENASSIST: return "VAESKEYGENASSIST"; case I_VANDNPD: return "VANDNPD"; - case I_VANDNPS: return "VANDNPS"; + case I_VANDNPS: return "VANDNPS"; case I_VANDPD: return "VANDPD"; case I_VANDPS: return "VANDPS"; case I_VBLENDPD: return "VBLENDPD"; case I_VBLENDPS: return "VBLENDPS"; - case I_VBLENDVPD: return "VBLENDVPD"; + case I_VBLENDVPD: return "VBLENDVPD"; case I_VBLENDVPS: return "VBLENDVPS"; case I_VBROADCASTF128: return "VBROADCASTF128"; case I_VBROADCASTSD: return "VBROADCASTSD"; - case I_VBROADCASTSS: return "VBROADCASTSS"; + case I_VBROADCASTSS: return "VBROADCASTSS"; case I_VCMPEQPD: return "VCMPEQPD"; case I_VCMPEQPS: return "VCMPEQPS"; case I_VCMPEQSD: return "VCMPEQSD"; - case I_VCMPEQSS: return "VCMPEQSS"; + case I_VCMPEQSS: return "VCMPEQSS"; case I_VCMPEQ_OSPD: return "VCMPEQ_OSPD"; case I_VCMPEQ_OSPS: return "VCMPEQ_OSPS"; case I_VCMPEQ_OSSD: return "VCMPEQ_OSSD"; - case I_VCMPEQ_OSSS: return "VCMPEQ_OSSS"; + case I_VCMPEQ_OSSS: return "VCMPEQ_OSSS"; case I_VCMPEQ_UQPD: return "VCMPEQ_UQPD"; case I_VCMPEQ_UQPS: return "VCMPEQ_UQPS"; case I_VCMPEQ_UQSD: return "VCMPEQ_UQSD"; - case I_VCMPEQ_UQSS: return "VCMPEQ_UQSS"; + case I_VCMPEQ_UQSS: return "VCMPEQ_UQSS"; case I_VCMPEQ_USPD: return "VCMPEQ_USPD"; case I_VCMPEQ_USPS: return "VCMPEQ_USPS"; case I_VCMPEQ_USSD: return "VCMPEQ_USSD"; - case I_VCMPEQ_USSS: return "VCMPEQ_USSS"; + case I_VCMPEQ_USSS: return "VCMPEQ_USSS"; case I_VCMPFALSEPD: return "VCMPFALSEPD"; case I_VCMPFALSEPS: return "VCMPFALSEPS"; case I_VCMPFALSESD: return "VCMPFALSESD"; - case I_VCMPFALSESS: return "VCMPFALSESS"; + case I_VCMPFALSESS: return "VCMPFALSESS"; case I_VCMPFALSE_OSPD: return "VCMPFALSE_OSPD"; case I_VCMPFALSE_OSPS: return "VCMPFALSE_OSPS"; - case I_VCMPFALSE_OSSD: return "VCMPFALSE_OSSD"; + case I_VCMPFALSE_OSSD: return "VCMPFALSE_OSSD"; case I_VCMPFALSE_OSSS: return "VCMPFALSE_OSSS"; case I_VCMPGEPD: return "VCMPGEPD"; case I_VCMPGEPS: return "VCMPGEPS"; - case I_VCMPGESD: return "VCMPGESD"; + case I_VCMPGESD: return "VCMPGESD"; case I_VCMPGESS: return "VCMPGESS"; case I_VCMPGE_OQPD: return "VCMPGE_OQPD"; case I_VCMPGE_OQPS: return "VCMPGE_OQPS"; - case I_VCMPGE_OQSD: return "VCMPGE_OQSD"; + case I_VCMPGE_OQSD: return "VCMPGE_OQSD"; case I_VCMPGE_OQSS: return "VCMPGE_OQSS"; case I_VCMPGTPD: return "VCMPGTPD"; case I_VCMPGTPS: return "VCMPGTPS"; - case I_VCMPGTSD: return "VCMPGTSD"; + case I_VCMPGTSD: return "VCMPGTSD"; case I_VCMPGTSS: return "VCMPGTSS"; case I_VCMPGT_OQPD: return "VCMPGT_OQPD"; case I_VCMPGT_OQPS: return "VCMPGT_OQPS"; - case I_VCMPGT_OQSD: return "VCMPGT_OQSD"; + case I_VCMPGT_OQSD: return "VCMPGT_OQSD"; case I_VCMPGT_OQSS: return "VCMPGT_OQSS"; case I_VCMPLEPD: return "VCMPLEPD"; case I_VCMPLEPS: return "VCMPLEPS"; - case I_VCMPLESD: return "VCMPLESD"; + case I_VCMPLESD: return "VCMPLESD"; case I_VCMPLESS: return "VCMPLESS"; case I_VCMPLE_OQPD: return "VCMPLE_OQPD"; case I_VCMPLE_OQPS: return "VCMPLE_OQPS"; - case I_VCMPLE_OQSD: return "VCMPLE_OQSD"; + case I_VCMPLE_OQSD: return "VCMPLE_OQSD"; case I_VCMPLE_OQSS: return "VCMPLE_OQSS"; case I_VCMPLTPD: return "VCMPLTPD"; case I_VCMPLTPS: return "VCMPLTPS"; - case I_VCMPLTSD: return "VCMPLTSD"; + case I_VCMPLTSD: return "VCMPLTSD"; case I_VCMPLTSS: return "VCMPLTSS"; case I_VCMPLT_OQPD: return "VCMPLT_OQPD"; case I_VCMPLT_OQPS: return "VCMPLT_OQPS"; - case I_VCMPLT_OQSD: return "VCMPLT_OQSD"; + case I_VCMPLT_OQSD: return "VCMPLT_OQSD"; case I_VCMPLT_OQSS: return "VCMPLT_OQSS"; case I_VCMPNEQPD: return "VCMPNEQPD"; case I_VCMPNEQPS: return "VCMPNEQPS"; - case I_VCMPNEQSD: return "VCMPNEQSD"; + case I_VCMPNEQSD: return "VCMPNEQSD"; case I_VCMPNEQSS: return "VCMPNEQSS"; case I_VCMPNEQ_OQPD: return "VCMPNEQ_OQPD"; case I_VCMPNEQ_OQPS: return "VCMPNEQ_OQPS"; - case I_VCMPNEQ_OQSD: return "VCMPNEQ_OQSD"; + case I_VCMPNEQ_OQSD: return "VCMPNEQ_OQSD"; case I_VCMPNEQ_OQSS: return "VCMPNEQ_OQSS"; case I_VCMPNEQ_OSPD: return "VCMPNEQ_OSPD"; case I_VCMPNEQ_OSPS: return "VCMPNEQ_OSPS"; - case I_VCMPNEQ_OSSD: return "VCMPNEQ_OSSD"; + case I_VCMPNEQ_OSSD: return "VCMPNEQ_OSSD"; case I_VCMPNEQ_OSSS: return "VCMPNEQ_OSSS"; case I_VCMPNEQ_USPD: return "VCMPNEQ_USPD"; case I_VCMPNEQ_USPS: return "VCMPNEQ_USPS"; - case I_VCMPNEQ_USSD: return "VCMPNEQ_USSD"; + case I_VCMPNEQ_USSD: return "VCMPNEQ_USSD"; case I_VCMPNEQ_USSS: return "VCMPNEQ_USSS"; case I_VCMPNGEPD: return "VCMPNGEPD"; case I_VCMPNGEPS: return "VCMPNGEPS"; - case I_VCMPNGESD: return "VCMPNGESD"; + case I_VCMPNGESD: return "VCMPNGESD"; case I_VCMPNGESS: return "VCMPNGESS"; case I_VCMPNGE_UQPD: return "VCMPNGE_UQPD"; case I_VCMPNGE_UQPS: return "VCMPNGE_UQPS"; - case I_VCMPNGE_UQSD: return "VCMPNGE_UQSD"; + case I_VCMPNGE_UQSD: return "VCMPNGE_UQSD"; case I_VCMPNGE_UQSS: return "VCMPNGE_UQSS"; case I_VCMPNGTPD: return "VCMPNGTPD"; case I_VCMPNGTPS: return "VCMPNGTPS"; - case I_VCMPNGTSD: return "VCMPNGTSD"; + case I_VCMPNGTSD: return "VCMPNGTSD"; case I_VCMPNGTSS: return "VCMPNGTSS"; case I_VCMPNGT_UQPD: return "VCMPNGT_UQPD"; case I_VCMPNGT_UQPS: return "VCMPNGT_UQPS"; - case I_VCMPNGT_UQSD: return "VCMPNGT_UQSD"; + case I_VCMPNGT_UQSD: return "VCMPNGT_UQSD"; case I_VCMPNGT_UQSS: return "VCMPNGT_UQSS"; case I_VCMPNLEPD: return "VCMPNLEPD"; case I_VCMPNLEPS: return "VCMPNLEPS"; - case I_VCMPNLESD: return "VCMPNLESD"; + case I_VCMPNLESD: return "VCMPNLESD"; case I_VCMPNLESS: return "VCMPNLESS"; case I_VCMPNLE_UQPD: return "VCMPNLE_UQPD"; case I_VCMPNLE_UQPS: return "VCMPNLE_UQPS"; - case I_VCMPNLE_UQSD: return "VCMPNLE_UQSD"; + case I_VCMPNLE_UQSD: return "VCMPNLE_UQSD"; case I_VCMPNLE_UQSS: return "VCMPNLE_UQSS"; case I_VCMPNLTPD: return "VCMPNLTPD"; case I_VCMPNLTPS: return "VCMPNLTPS"; - case I_VCMPNLTSD: return "VCMPNLTSD"; + case I_VCMPNLTSD: return "VCMPNLTSD"; case I_VCMPNLTSS: return "VCMPNLTSS"; case I_VCMPNLT_UQPD: return "VCMPNLT_UQPD"; case I_VCMPNLT_UQPS: return "VCMPNLT_UQPS"; - case I_VCMPNLT_UQSD: return "VCMPNLT_UQSD"; + case I_VCMPNLT_UQSD: return "VCMPNLT_UQSD"; case I_VCMPNLT_UQSS: return "VCMPNLT_UQSS"; case I_VCMPORDPD: return "VCMPORDPD"; case I_VCMPORDPS: return "VCMPORDPS"; - case I_VCMPORDSD: return "VCMPORDSD"; + case I_VCMPORDSD: return "VCMPORDSD"; case I_VCMPORDSS: return "VCMPORDSS"; case I_VCMPORD_SPD: return "VCMPORD_SPD"; case I_VCMPORD_SPS: return "VCMPORD_SPS"; - case I_VCMPORD_SSD: return "VCMPORD_SSD"; + case I_VCMPORD_SSD: return "VCMPORD_SSD"; case I_VCMPORD_SSS: return "VCMPORD_SSS"; case I_VCMPTRUEPD: return "VCMPTRUEPD"; case I_VCMPTRUEPS: return "VCMPTRUEPS"; - case I_VCMPTRUESD: return "VCMPTRUESD"; + case I_VCMPTRUESD: return "VCMPTRUESD"; case I_VCMPTRUESS: return "VCMPTRUESS"; case I_VCMPTRUE_USPD: return "VCMPTRUE_USPD"; case I_VCMPTRUE_USPS: return "VCMPTRUE_USPS"; - case I_VCMPTRUE_USSD: return "VCMPTRUE_USSD"; + case I_VCMPTRUE_USSD: return "VCMPTRUE_USSD"; case I_VCMPTRUE_USSS: return "VCMPTRUE_USSS"; case I_VCMPUNORDPD: return "VCMPUNORDPD"; case I_VCMPUNORDPS: return "VCMPUNORDPS"; - case I_VCMPUNORDSD: return "VCMPUNORDSD"; + case I_VCMPUNORDSD: return "VCMPUNORDSD"; case I_VCMPUNORDSS: return "VCMPUNORDSS"; case I_VCMPUNORD_SPD: return "VCMPUNORD_SPD"; case I_VCMPUNORD_SPS: return "VCMPUNORD_SPS"; - case I_VCMPUNORD_SSD: return "VCMPUNORD_SSD"; + case I_VCMPUNORD_SSD: return "VCMPUNORD_SSD"; case I_VCMPUNORD_SSS: return "VCMPUNORD_SSS"; case I_VCOMISD: return "VCOMISD"; case I_VCOMISS: return "VCOMISS"; - case I_VCVTDQ2PD: return "VCVTDQ2PD"; + case I_VCVTDQ2PD: return "VCVTDQ2PD"; case I_VCVTDQ2PS: return "VCVTDQ2PS"; case I_VCVTPD2DQ: return "VCVTPD2DQ"; case I_VCVTPD2PS: return "VCVTPD2PS"; - case I_VCVTPS2DQ: return "VCVTPS2DQ"; + case I_VCVTPS2DQ: return "VCVTPS2DQ"; case I_VCVTPS2PD: return "VCVTPS2PD"; case I_VCVTSD2SI: return "VCVTSD2SI"; case I_VCVTSD2SS: return "VCVTSD2SS"; - case I_VCVTSI2SD: return "VCVTSI2SD"; + case I_VCVTSI2SD: return "VCVTSI2SD"; case I_VCVTSI2SS: return "VCVTSI2SS"; case I_VCVTSS2SD: return "VCVTSS2SD"; case I_VCVTSS2SI: return "VCVTSS2SI"; - case I_VCVTTPD2DQ: return "VCVTTPD2DQ"; + case I_VCVTTPD2DQ: return "VCVTTPD2DQ"; case I_VCVTTPS2DQ: return "VCVTTPS2DQ"; case I_VCVTTSD2SI: return "VCVTTSD2SI"; case I_VCVTTSS2SI: return "VCVTTSS2SI"; - case I_VDIVPD: return "VDIVPD"; + case I_VDIVPD: return "VDIVPD"; case I_VDIVPS: return "VDIVPS"; case I_VDIVSD: return "VDIVSD"; case I_VDIVSS: return "VDIVSS"; case I_VDPPD: return "VDPPD"; - case I_VDPPS: return "VDPPS"; + case I_VDPPS: return "VDPPS"; case I_VERR: return "VERR"; case I_VERW: return "VERW"; case I_VEXTRACTF128: return "VEXTRACTF128"; - case I_VEXTRACTPS: return "VEXTRACTPS"; + case I_VEXTRACTPS: return "VEXTRACTPS"; case I_VFMADD132PD: return "VFMADD132PD"; case I_VFMADD132PS: return "VFMADD132PS"; case I_VFMADD132SD: return "VFMADD132SD"; - case I_VFMADD132SS: return "VFMADD132SS"; + case I_VFMADD132SS: return "VFMADD132SS"; case I_VFMADD213PD: return "VFMADD213PD"; case I_VFMADD213PS: return "VFMADD213PS"; case I_VFMADD213SD: return "VFMADD213SD"; - case I_VFMADD213SS: return "VFMADD213SS"; + case I_VFMADD213SS: return "VFMADD213SS"; case I_VFMADD231PD: return "VFMADD231PD"; case I_VFMADD231PS: return "VFMADD231PS"; case I_VFMADD231SD: return "VFMADD231SD"; - case I_VFMADD231SS: return "VFMADD231SS"; + case I_VFMADD231SS: return "VFMADD231SS"; case I_VFMADDSUB132PD: return "VFMADDSUB132PD"; case I_VFMADDSUB132PS: return "VFMADDSUB132PS"; - case I_VFMADDSUB213PD: return "VFMADDSUB213PD"; + case I_VFMADDSUB213PD: return "VFMADDSUB213PD"; case I_VFMADDSUB213PS: return "VFMADDSUB213PS"; case I_VFMADDSUB231PD: return "VFMADDSUB231PD"; - case I_VFMADDSUB231PS: return "VFMADDSUB231PS"; + case I_VFMADDSUB231PS: return "VFMADDSUB231PS"; case I_VFMSUB132PD: return "VFMSUB132PD"; case I_VFMSUB132PS: return "VFMSUB132PS"; case I_VFMSUB132SD: return "VFMSUB132SD"; - case I_VFMSUB132SS: return "VFMSUB132SS"; + case I_VFMSUB132SS: return "VFMSUB132SS"; case I_VFMSUB213PD: return "VFMSUB213PD"; case I_VFMSUB213PS: return "VFMSUB213PS"; case I_VFMSUB213SD: return "VFMSUB213SD"; - case I_VFMSUB213SS: return "VFMSUB213SS"; + case I_VFMSUB213SS: return "VFMSUB213SS"; case I_VFMSUB231PD: return "VFMSUB231PD"; case I_VFMSUB231PS: return "VFMSUB231PS"; case I_VFMSUB231SD: return "VFMSUB231SD"; - case I_VFMSUB231SS: return "VFMSUB231SS"; + case I_VFMSUB231SS: return "VFMSUB231SS"; case I_VFMSUBADD132PD: return "VFMSUBADD132PD"; case I_VFMSUBADD132PS: return "VFMSUBADD132PS"; - case I_VFMSUBADD213PD: return "VFMSUBADD213PD"; + case I_VFMSUBADD213PD: return "VFMSUBADD213PD"; case I_VFMSUBADD213PS: return "VFMSUBADD213PS"; case I_VFMSUBADD231PD: return "VFMSUBADD231PD"; - case I_VFMSUBADD231PS: return "VFMSUBADD231PS"; + case I_VFMSUBADD231PS: return "VFMSUBADD231PS"; case I_VFNMADD132PD: return "VFNMADD132PD"; case I_VFNMADD132PS: return "VFNMADD132PS"; case I_VFNMADD132SD: return "VFNMADD132SD"; - case I_VFNMADD132SS: return "VFNMADD132SS"; + case I_VFNMADD132SS: return "VFNMADD132SS"; case I_VFNMADD213PD: return "VFNMADD213PD"; case I_VFNMADD213PS: return "VFNMADD213PS"; case I_VFNMADD213SD: return "VFNMADD213SD"; - case I_VFNMADD213SS: return "VFNMADD213SS"; + case I_VFNMADD213SS: return "VFNMADD213SS"; case I_VFNMADD231PD: return "VFNMADD231PD"; case I_VFNMADD231PS: return "VFNMADD231PS"; case I_VFNMADD231SD: return "VFNMADD231SD"; - case I_VFNMADD231SS: return "VFNMADD231SS"; + case I_VFNMADD231SS: return "VFNMADD231SS"; case I_VFNMSUB132PD: return "VFNMSUB132PD"; case I_VFNMSUB132PS: return "VFNMSUB132PS"; case I_VFNMSUB132SD: return "VFNMSUB132SD"; - case I_VFNMSUB132SS: return "VFNMSUB132SS"; + case I_VFNMSUB132SS: return "VFNMSUB132SS"; case I_VFNMSUB213PD: return "VFNMSUB213PD"; case I_VFNMSUB213PS: return "VFNMSUB213PS"; case I_VFNMSUB213SD: return "VFNMSUB213SD"; - case I_VFNMSUB213SS: return "VFNMSUB213SS"; + case I_VFNMSUB213SS: return "VFNMSUB213SS"; case I_VFNMSUB231PD: return "VFNMSUB231PD"; case I_VFNMSUB231PS: return "VFNMSUB231PS"; case I_VFNMSUB231SD: return "VFNMSUB231SD"; - case I_VFNMSUB231SS: return "VFNMSUB231SS"; + case I_VFNMSUB231SS: return "VFNMSUB231SS"; case I_VHADDPD: return "VHADDPD"; case I_VHADDPS: return "VHADDPS"; case I_VHSUBPD: return "VHSUBPD"; case I_VHSUBPS: return "VHSUBPS"; - case I_VINSERTF128: return "VINSERTF128"; + case I_VINSERTF128: return "VINSERTF128"; case I_VINSERTPS: return "VINSERTPS"; case I_VLDDQU: return "VLDDQU"; case I_VLDMXCSR: return "VLDMXCSR"; - case I_VMASKMOVDQU: return "VMASKMOVDQU"; + case I_VMASKMOVDQU: return "VMASKMOVDQU"; case I_VMASKMOVPD: return "VMASKMOVPD"; case I_VMASKMOVPS: return "VMASKMOVPS"; case I_VMAXPD: return "VMAXPD"; - case I_VMAXPS: return "VMAXPS"; + case I_VMAXPS: return "VMAXPS"; case I_VMAXSD: return "VMAXSD"; case I_VMAXSS: return "VMAXSS"; case I_VMCALL: return "VMCALL"; case I_VMCLEAR: return "VMCLEAR"; - case I_VMFUNC: return "VMFUNC"; + case I_VMFUNC: return "VMFUNC"; case I_VMINPD: return "VMINPD"; case I_VMINPS: return "VMINPS"; case I_VMINSD: return "VMINSD"; case I_VMINSS: return "VMINSS"; - case I_VMLAUNCH: return "VMLAUNCH"; + case I_VMLAUNCH: return "VMLAUNCH"; case I_VMLOAD: return "VMLOAD"; case I_VMMCALL: return "VMMCALL"; case I_VMOVAPD: return "VMOVAPD"; case I_VMOVAPS: return "VMOVAPS"; - case I_VMOVD: return "VMOVD"; + case I_VMOVD: return "VMOVD"; case I_VMOVDDUP: return "VMOVDDUP"; case I_VMOVDQA: return "VMOVDQA"; case I_VMOVDQU: return "VMOVDQU"; - case I_VMOVHLPS: return "VMOVHLPS"; + case I_VMOVHLPS: return "VMOVHLPS"; case I_VMOVHPD: return "VMOVHPD"; case I_VMOVHPS: return "VMOVHPS"; case I_VMOVLHPS: return "VMOVLHPS"; case I_VMOVLPD: return "VMOVLPD"; - case I_VMOVLPS: return "VMOVLPS"; + case I_VMOVLPS: return "VMOVLPS"; case I_VMOVMSKPD: return "VMOVMSKPD"; case I_VMOVMSKPS: return "VMOVMSKPS"; case I_VMOVNTDQ: return "VMOVNTDQ"; - case I_VMOVNTDQA: return "VMOVNTDQA"; + case I_VMOVNTDQA: return "VMOVNTDQA"; case I_VMOVNTPD: return "VMOVNTPD"; case I_VMOVNTPS: return "VMOVNTPS"; case I_VMOVQ: return "VMOVQ"; case I_VMOVSD: return "VMOVSD"; - case I_VMOVSHDUP: return "VMOVSHDUP"; + case I_VMOVSHDUP: return "VMOVSHDUP"; case I_VMOVSLDUP: return "VMOVSLDUP"; case I_VMOVSS: return "VMOVSS"; case I_VMOVUPD: return "VMOVUPD"; case I_VMOVUPS: return "VMOVUPS"; - case I_VMPSADBW: return "VMPSADBW"; + case I_VMPSADBW: return "VMPSADBW"; case I_VMPTRLD: return "VMPTRLD"; case I_VMPTRST: return "VMPTRST"; case I_VMREAD: return "VMREAD"; case I_VMRESUME: return "VMRESUME"; - case I_VMRUN: return "VMRUN"; + case I_VMRUN: return "VMRUN"; case I_VMSAVE: return "VMSAVE"; case I_VMULPD: return "VMULPD"; case I_VMULPS: return "VMULPS"; case I_VMULSD: return "VMULSD"; - case I_VMULSS: return "VMULSS"; + case I_VMULSS: return "VMULSS"; case I_VMWRITE: return "VMWRITE"; case I_VMXOFF: return "VMXOFF"; case I_VMXON: return "VMXON"; case I_VORPD: return "VORPD"; - case I_VORPS: return "VORPS"; + case I_VORPS: return "VORPS"; case I_VPABSB: return "VPABSB"; case I_VPABSD: return "VPABSD"; case I_VPABSW: return "VPABSW"; case I_VPACKSSDW: return "VPACKSSDW"; - case I_VPACKSSWB: return "VPACKSSWB"; + case I_VPACKSSWB: return "VPACKSSWB"; case I_VPACKUSDW: return "VPACKUSDW"; case I_VPACKUSWB: return "VPACKUSWB"; case I_VPADDB: return "VPADDB"; - case I_VPADDD: return "VPADDD"; + case I_VPADDD: return "VPADDD"; case I_VPADDQ: return "VPADDQ"; case I_VPADDSB: return "VPADDSB"; case I_VPADDSW: return "VPADDSW"; case I_VPADDUSW: return "VPADDUSW"; - case I_VPADDW: return "VPADDW"; + case I_VPADDW: return "VPADDW"; case I_VPALIGNR: return "VPALIGNR"; case I_VPAND: return "VPAND"; case I_VPANDN: return "VPANDN"; case I_VPAVGB: return "VPAVGB"; - case I_VPAVGW: return "VPAVGW"; + case I_VPAVGW: return "VPAVGW"; case I_VPBLENDVB: return "VPBLENDVB"; case I_VPBLENDW: return "VPBLENDW"; case I_VPCLMULQDQ: return "VPCLMULQDQ"; - case I_VPCMPEQB: return "VPCMPEQB"; + case I_VPCMPEQB: return "VPCMPEQB"; case I_VPCMPEQD: return "VPCMPEQD"; case I_VPCMPEQQ: return "VPCMPEQQ"; case I_VPCMPEQW: return "VPCMPEQW"; - case I_VPCMPESTRI: return "VPCMPESTRI"; + case I_VPCMPESTRI: return "VPCMPESTRI"; case I_VPCMPESTRM: return "VPCMPESTRM"; case I_VPCMPGTB: return "VPCMPGTB"; case I_VPCMPGTD: return "VPCMPGTD"; - case I_VPCMPGTQ: return "VPCMPGTQ"; + case I_VPCMPGTQ: return "VPCMPGTQ"; case I_VPCMPGTW: return "VPCMPGTW"; case I_VPCMPISTRI: return "VPCMPISTRI"; case I_VPCMPISTRM: return "VPCMPISTRM"; - case I_VPERM2F128: return "VPERM2F128"; + case I_VPERM2F128: return "VPERM2F128"; case I_VPERMILPD: return "VPERMILPD"; case I_VPERMILPS: return "VPERMILPS"; case I_VPEXTRB: return "VPEXTRB"; - case I_VPEXTRD: return "VPEXTRD"; + case I_VPEXTRD: return "VPEXTRD"; case I_VPEXTRQ: return "VPEXTRQ"; case I_VPEXTRW: return "VPEXTRW"; case I_VPHADDD: return "VPHADDD"; case I_VPHADDSW: return "VPHADDSW"; - case I_VPHADDW: return "VPHADDW"; + case I_VPHADDW: return "VPHADDW"; case I_VPHMINPOSUW: return "VPHMINPOSUW"; case I_VPHSUBD: return "VPHSUBD"; case I_VPHSUBSW: return "VPHSUBSW"; - case I_VPHSUBW: return "VPHSUBW"; + case I_VPHSUBW: return "VPHSUBW"; case I_VPINSRB: return "VPINSRB"; case I_VPINSRD: return "VPINSRD"; case I_VPINSRQ: return "VPINSRQ"; case I_VPINSRW: return "VPINSRW"; - case I_VPMADDUBSW: return "VPMADDUBSW"; + case I_VPMADDUBSW: return "VPMADDUBSW"; case I_VPMADDWD: return "VPMADDWD"; case I_VPMAXSB: return "VPMAXSB"; case I_VPMAXSD: return "VPMAXSD"; case I_VPMAXSW: return "VPMAXSW"; - case I_VPMAXUB: return "VPMAXUB"; + case I_VPMAXUB: return "VPMAXUB"; case I_VPMAXUD: return "VPMAXUD"; case I_VPMAXUW: return "VPMAXUW"; case I_VPMINSB: return "VPMINSB"; case I_VPMINSD: return "VPMINSD"; - case I_VPMINSW: return "VPMINSW"; + case I_VPMINSW: return "VPMINSW"; case I_VPMINUB: return "VPMINUB"; case I_VPMINUD: return "VPMINUD"; case I_VPMINUW: return "VPMINUW"; - case I_VPMOVMSKB: return "VPMOVMSKB"; + case I_VPMOVMSKB: return "VPMOVMSKB"; case I_VPMOVSXBD: return "VPMOVSXBD"; case I_VPMOVSXBQ: return "VPMOVSXBQ"; case I_VPMOVSXBW: return "VPMOVSXBW"; - case I_VPMOVSXDQ: return "VPMOVSXDQ"; + case I_VPMOVSXDQ: return "VPMOVSXDQ"; case I_VPMOVSXWD: return "VPMOVSXWD"; case I_VPMOVSXWQ: return "VPMOVSXWQ"; case I_VPMOVZXBD: return "VPMOVZXBD"; - case I_VPMOVZXBQ: return "VPMOVZXBQ"; + case I_VPMOVZXBQ: return "VPMOVZXBQ"; case I_VPMOVZXBW: return "VPMOVZXBW"; case I_VPMOVZXDQ: return "VPMOVZXDQ"; case I_VPMOVZXWD: return "VPMOVZXWD"; - case I_VPMOVZXWQ: return "VPMOVZXWQ"; + case I_VPMOVZXWQ: return "VPMOVZXWQ"; case I_VPMULDQ: return "VPMULDQ"; case I_VPMULHRSW: return "VPMULHRSW"; case I_VPMULHUW: return "VPMULHUW"; - case I_VPMULHW: return "VPMULHW"; + case I_VPMULHW: return "VPMULHW"; case I_VPMULLD: return "VPMULLD"; case I_VPMULLW: return "VPMULLW"; case I_VPMULUDQ: return "VPMULUDQ"; case I_VPOR: return "VPOR"; - case I_VPSADBW: return "VPSADBW"; + case I_VPSADBW: return "VPSADBW"; case I_VPSHUFB: return "VPSHUFB"; case I_VPSHUFD: return "VPSHUFD"; case I_VPSHUFHW: return "VPSHUFHW"; - case I_VPSHUFLW: return "VPSHUFLW"; + case I_VPSHUFLW: return "VPSHUFLW"; case I_VPSIGNB: return "VPSIGNB"; case I_VPSIGND: return "VPSIGND"; case I_VPSIGNW: return "VPSIGNW"; case I_VPSLLD: return "VPSLLD"; - case I_VPSLLDQ: return "VPSLLDQ"; + case I_VPSLLDQ: return "VPSLLDQ"; case I_VPSLLQ: return "VPSLLQ"; case I_VPSLLW: return "VPSLLW"; case I_VPSRAD: return "VPSRAD"; case I_VPSRAW: return "VPSRAW"; - case I_VPSRLD: return "VPSRLD"; + case I_VPSRLD: return "VPSRLD"; case I_VPSRLDQ: return "VPSRLDQ"; case I_VPSRLQ: return "VPSRLQ"; case I_VPSRLW: return "VPSRLW"; case I_VPSUBB: return "VPSUBB"; - case I_VPSUBD: return "VPSUBD"; + case I_VPSUBD: return "VPSUBD"; case I_VPSUBQ: return "VPSUBQ"; case I_VPSUBSB: return "VPSUBSB"; case I_VPSUBSW: return "VPSUBSW"; case I_VPSUBUSB: return "VPSUBUSB"; - case I_VPSUBUSW: return "VPSUBUSW"; + case I_VPSUBUSW: return "VPSUBUSW"; case I_VPSUBW: return "VPSUBW"; case I_VPTEST: return "VPTEST"; case I_VPUNPCKHBW: return "VPUNPCKHBW"; - case I_VPUNPCKHDQ: return "VPUNPCKHDQ"; + case I_VPUNPCKHDQ: return "VPUNPCKHDQ"; case I_VPUNPCKHQDQ: return "VPUNPCKHQDQ"; case I_VPUNPCKHWD: return "VPUNPCKHWD"; case I_VPUNPCKLBW: return "VPUNPCKLBW"; - case I_VPUNPCKLDQ: return "VPUNPCKLDQ"; + case I_VPUNPCKLDQ: return "VPUNPCKLDQ"; case I_VPUNPCKLQDQ: return "VPUNPCKLQDQ"; case I_VPUNPCKLWD: return "VPUNPCKLWD"; case I_VPXOR: return "VPXOR"; - case I_VRCPPS: return "VRCPPS"; + case I_VRCPPS: return "VRCPPS"; case I_VRCPSS: return "VRCPSS"; case I_VROUNDPD: return "VROUNDPD"; case I_VROUNDPS: return "VROUNDPS"; - case I_VROUNDSD: return "VROUNDSD"; + case I_VROUNDSD: return "VROUNDSD"; case I_VROUNDSS: return "VROUNDSS"; case I_VRSQRTPS: return "VRSQRTPS"; case I_VRSQRTSS: return "VRSQRTSS"; - case I_VSHUFPD: return "VSHUFPD"; + case I_VSHUFPD: return "VSHUFPD"; case I_VSHUFPS: return "VSHUFPS"; case I_VSQRTPD: return "VSQRTPD"; case I_VSQRTPS: return "VSQRTPS"; case I_VSQRTSD: return "VSQRTSD"; - case I_VSQRTSS: return "VSQRTSS"; + case I_VSQRTSS: return "VSQRTSS"; case I_VSTMXCSR: return "VSTMXCSR"; case I_VSUBPD: return "VSUBPD"; case I_VSUBPS: return "VSUBPS"; case I_VSUBSD: return "VSUBSD"; - case I_VSUBSS: return "VSUBSS"; + case I_VSUBSS: return "VSUBSS"; case I_VTESTPD: return "VTESTPD"; case I_VTESTPS: return "VTESTPS"; case I_VUCOMISD: return "VUCOMISD"; - case I_VUCOMISS: return "VUCOMISS"; + case I_VUCOMISS: return "VUCOMISS"; case I_VUNPCKHPD: return "VUNPCKHPD"; case I_VUNPCKHPS: return "VUNPCKHPS"; case I_VUNPCKLPD: return "VUNPCKLPD"; - case I_VUNPCKLPS: return "VUNPCKLPS"; + case I_VUNPCKLPS: return "VUNPCKLPS"; case I_VXORPD: return "VXORPD"; case I_VXORPS: return "VXORPS"; case I_VZEROALL: return "VZEROALL"; - case I_VZEROUPPER: return "VZEROUPPER"; + case I_VZEROUPPER: return "VZEROUPPER"; case I_WAIT: return "WAIT"; case I_WBINVD: return "WBINVD"; case I_WRFSBASE: return "WRFSBASE"; case I_WRGSBASE: return "WRGSBASE"; - case I_WRMSR: return "WRMSR"; + case I_WRMSR: return "WRMSR"; case I_XABORT: return "XABORT"; case I_XADD: return "XADD"; case I_XBEGIN: return "XBEGIN"; case I_XCHG: return "XCHG"; - case I_XEND: return "XEND"; + case I_XEND: return "XEND"; case I_XGETBV: return "XGETBV"; case I_XLAT: return "XLAT"; case I_XOR: return "XOR"; case I_XORPD: return "XORPD"; - case I_XORPS: return "XORPS"; + case I_XORPS: return "XORPS"; case I_XRSTOR: return "XRSTOR"; case I_XRSTOR64: return "XRSTOR64"; case I_XSAVE: return "XSAVE"; case I_XSAVE64: return "XSAVE64"; - case I_XSAVEOPT: return "XSAVEOPT"; + case I_XSAVEOPT: return "XSAVEOPT"; case I_XSAVEOPT64: return "XSAVEOPT64"; case I_XSETBV: return "XSETBV"; - default: assert(false); return "???"; - } -} - -void output_value(std::stringstream &output, int nibbles, uint32_t value) -{ - if (value < 0xA) - // Show 0 upto 9 as 1 decimal digit - output << std::setw(1) << value; - else - output << std::setfill('0') << std::setw(nibbles) << std::right << value << 'h'; -} - -void output_value_disp(std::stringstream &output, _DInst &info) -{ - uint32_t value = EmuX86_Distorm_read_disp(info); - if (value != 0) { - int nibbles = info.dispSize / 4; - assert(nibbles == 2 || nibbles == 4 || nibbles == 8); - if ((int32_t)value < 0) { - output << '-'; - output_value(output, nibbles, -value); - } - else { - output << '+'; - output_value(output, nibbles, value); - } - } -} - -void output_segment(std::stringstream &output, _DInst &info) -{ - if (SEGMENT_GET(info.segment) != R_NONE) - output << Distorm_RegStrings[SEGMENT_GET(info.segment)] << ":"; -} - -void EmuX86_DistormLogInstruction(const uint8_t *Eip, _DInst &info) -{ - std::stringstream output; - - output << "Disassembly : " - << std::setfill('0') << std::setw(8) << std::right << std::hex << std::uppercase << (xbaddr)Eip; - for (int b = 0; b < MAX(7, info.size); b++) { - if (b < info.size) - //output << " " << std::setfill('0') << std::setw(2) << std::right << std::hex << ((uint8_t)0+Eip[b]); // add 2 hex nibbles, not chars - output << " " << std::setw(2) << ((uint8_t)0+Eip[b]); // add 2 hex nibbles, not chars - else - output << " "; - } - - output << std::setfill(' ') << std::left << std::setw(1) << " "; - if (info.flags & FLAG_LOCK) - output << "LOCK "; - - if (info.flags & FLAG_REPNZ) - output << "REPNZ "; - - if (info.flags & FLAG_REP) { - switch (info.opcode) { - case I_CMPS: - case I_SCAS: - output << "REPZ "; - break; - default: - output << "REP "; - } - } - - output << std::setw(11) << Distorm_OpcodeString(info.opcode); - for (int o = 0; o < 4 && info.ops[o].type != O_NONE; o++) { - // Convert size in bits to (hexadecimal) nibble count and a size-indicator string - int nr_nibbles; - std::string size_str; - - switch (info.ops[o].size) { - case 0: nr_nibbles = 8; size_str = ""; break; - case 8: nr_nibbles = 2; size_str = "byte ptr "; break; - case 16: nr_nibbles = 4; size_str = "word ptr "; break; - case 32: nr_nibbles = 8; size_str = "dword ptr "; break; - default: assert(false); - } - - // Output register/operand separator - output << std::setfill(' ') << std::setw(1) << std::right << ((o == 0) ? " " : ","); - // Render operand to output - switch (info.ops[o].type) { - case O_REG: - output << Distorm_RegStrings[info.ops[o].index]; - break; - case O_IMM: - output_value(output, nr_nibbles, info.imm.dword); - break; - case O_IMM1: // TODO : Needs test-case - output_value(output, nr_nibbles, info.imm.ex.i1); - break; - case O_IMM2: // TODO : Needs test-case - output_value(output, nr_nibbles, info.imm.ex.i2); - break; - case O_DISP: - output << size_str; - output_segment(output, info); // Was << "ds:", so no check on default - output << "["; - output_value(output, info.dispSize > 0 ? info.dispSize / 4 : 8, EmuX86_Distorm_read_disp(info)); - output << "]"; - break; - case O_SMEM: - output << size_str << "["; - if (!SEGMENT_IS_DEFAULT(info.segment)) - output_segment(output, info); - output << Distorm_RegStrings[info.ops[o].index]; - output_value_disp(output, info); - output << "]"; - break; - case O_MEM: - output << size_str << "["; - if (!SEGMENT_IS_DEFAULT(info.segment)) - output_segment(output, info); - if (info.base != R_NONE) - output << Distorm_RegStrings[info.base] << "+"; - output << Distorm_RegStrings[info.ops[o].index]; - if (info.scale >= 2) { - output << "*"; - output_value(output, 1/*nibble*/, info.scale); - } - output_value_disp(output, info); - output << "]"; - break; - case O_PC: - output_value(output, 8, (xbaddr)Eip + (xbaddr)INSTRUCTION_GET_TARGET(&info)); - break; - case O_PTR: // TODO : Needs test-case - output << "+" << std::setfill('0') << info.imm.ptr.seg << "/"; - output_value(output, nr_nibbles, info.imm.ptr.off); - break; - default: - assert(false); - output << "?"; - break; - } - } - - if (FLAG_GET_PRIVILEGED(info.flags)) - output << " // Privileged ring 0 instruction"; - -/* -#define FLAG_LOCK (1 << 0) // The instruction locks memory access. -#define FLAG_REPNZ (1 << 1) // The instruction is prefixed with a REPNZ. -#define FLAG_REP (1 << 2) // The instruction is prefixed with a REP, this can be a REPZ, it depends on the specific instruction. -#define FLAG_HINT_TAKEN (1 << 3) // Indicates there is a hint taken for Jcc instructions only. -#define FLAG_HINT_NOT_TAKEN (1 << 4) // Indicates there is a hint non-taken for Jcc instructions only. -#define FLAG_IMM_SIGNED (1 << 5) // The Imm value is signed extended (E.G in 64 bit decoding mode, a 32 bit imm is usually sign extended into 64 bit imm). -#define FLAG_DST_WR (1 << 6) // The destination operand is writable. -#define FLAG_GET_OPSIZE(flags) (((flags) >> 8) & 3) -#define FLAG_GET_ADDRSIZE(flags) (((flags) >> 10) & 3) -#define FLAG_GET_PREFIX(flags) ((flags) & 7) // To get the LOCK/REPNZ/REP prefixes. -*/ - - EmuLog(LOG_PREFIX, LOG_LEVEL::DEBUG, output.str().c_str()); + default: assert(false); return "???"; + } } - + +void output_value(std::stringstream &output, int nibbles, uint32_t value) +{ + if (value < 0xA) + // Show 0 upto 9 as 1 decimal digit + output << std::setw(1) << value; + else + output << std::setfill('0') << std::setw(nibbles) << std::right << value << 'h'; +} + +void output_value_disp(std::stringstream &output, _DInst &info) +{ + uint32_t value = EmuX86_Distorm_read_disp(info); + if (value != 0) { + int nibbles = info.dispSize / 4; + assert(nibbles == 2 || nibbles == 4 || nibbles == 8); + if ((int32_t)value < 0) { + output << '-'; + output_value(output, nibbles, -value); + } + else { + output << '+'; + output_value(output, nibbles, value); + } + } +} + +void output_segment(std::stringstream &output, _DInst &info) +{ + if (SEGMENT_GET(info.segment) != R_NONE) + output << Distorm_RegStrings[SEGMENT_GET(info.segment)] << ":"; +} + +void EmuX86_DistormLogInstruction(const uint8_t *Eip, _DInst &info) +{ + std::stringstream output; + + output << "Disassembly : " + << std::setfill('0') << std::setw(8) << std::right << std::hex << std::uppercase << (xbaddr)Eip; + for (int b = 0; b < MAX(7, info.size); b++) { + if (b < info.size) + //output << " " << std::setfill('0') << std::setw(2) << std::right << std::hex << ((uint8_t)0+Eip[b]); // add 2 hex nibbles, not chars + output << " " << std::setw(2) << ((uint8_t)0+Eip[b]); // add 2 hex nibbles, not chars + else + output << " "; + } + + output << std::setfill(' ') << std::left << std::setw(1) << " "; + if (info.flags & FLAG_LOCK) + output << "LOCK "; + + if (info.flags & FLAG_REPNZ) + output << "REPNZ "; + + if (info.flags & FLAG_REP) { + switch (info.opcode) { + case I_CMPS: + case I_SCAS: + output << "REPZ "; + break; + default: + output << "REP "; + } + } + + output << std::setw(11) << Distorm_OpcodeString(info.opcode); + for (int o = 0; o < 4 && info.ops[o].type != O_NONE; o++) { + // Convert size in bits to (hexadecimal) nibble count and a size-indicator string + int nr_nibbles; + std::string size_str; + + switch (info.ops[o].size) { + case 0: nr_nibbles = 8; size_str = ""; break; + case 8: nr_nibbles = 2; size_str = "byte ptr "; break; + case 16: nr_nibbles = 4; size_str = "word ptr "; break; + case 32: nr_nibbles = 8; size_str = "dword ptr "; break; + default: assert(false); + } + + // Output register/operand separator + output << std::setfill(' ') << std::setw(1) << std::right << ((o == 0) ? " " : ","); + // Render operand to output + switch (info.ops[o].type) { + case O_REG: + output << Distorm_RegStrings[info.ops[o].index]; + break; + case O_IMM: + output_value(output, nr_nibbles, info.imm.dword); + break; + case O_IMM1: // TODO : Needs test-case + output_value(output, nr_nibbles, info.imm.ex.i1); + break; + case O_IMM2: // TODO : Needs test-case + output_value(output, nr_nibbles, info.imm.ex.i2); + break; + case O_DISP: + output << size_str; + output_segment(output, info); // Was << "ds:", so no check on default + output << "["; + output_value(output, info.dispSize > 0 ? info.dispSize / 4 : 8, EmuX86_Distorm_read_disp(info)); + output << "]"; + break; + case O_SMEM: + output << size_str << "["; + if (!SEGMENT_IS_DEFAULT(info.segment)) + output_segment(output, info); + output << Distorm_RegStrings[info.ops[o].index]; + output_value_disp(output, info); + output << "]"; + break; + case O_MEM: + output << size_str << "["; + if (!SEGMENT_IS_DEFAULT(info.segment)) + output_segment(output, info); + if (info.base != R_NONE) + output << Distorm_RegStrings[info.base] << "+"; + output << Distorm_RegStrings[info.ops[o].index]; + if (info.scale >= 2) { + output << "*"; + output_value(output, 1/*nibble*/, info.scale); + } + output_value_disp(output, info); + output << "]"; + break; + case O_PC: + output_value(output, 8, (xbaddr)Eip + (xbaddr)INSTRUCTION_GET_TARGET(&info)); + break; + case O_PTR: // TODO : Needs test-case + output << "+" << std::setfill('0') << info.imm.ptr.seg << "/"; + output_value(output, nr_nibbles, info.imm.ptr.off); + break; + default: + assert(false); + output << "?"; + break; + } + } + + if (FLAG_GET_PRIVILEGED(info.flags)) + output << " // Privileged ring 0 instruction"; + +/* +#define FLAG_LOCK (1 << 0) // The instruction locks memory access. +#define FLAG_REPNZ (1 << 1) // The instruction is prefixed with a REPNZ. +#define FLAG_REP (1 << 2) // The instruction is prefixed with a REP, this can be a REPZ, it depends on the specific instruction. +#define FLAG_HINT_TAKEN (1 << 3) // Indicates there is a hint taken for Jcc instructions only. +#define FLAG_HINT_NOT_TAKEN (1 << 4) // Indicates there is a hint non-taken for Jcc instructions only. +#define FLAG_IMM_SIGNED (1 << 5) // The Imm value is signed extended (E.G in 64 bit decoding mode, a 32 bit imm is usually sign extended into 64 bit imm). +#define FLAG_DST_WR (1 << 6) // The destination operand is writable. +#define FLAG_GET_OPSIZE(flags) (((flags) >> 8) & 3) +#define FLAG_GET_ADDRSIZE(flags) (((flags) >> 10) & 3) +#define FLAG_GET_PREFIX(flags) ((flags) & 7) // To get the LOCK/REPNZ/REP prefixes. +*/ + + EmuLog(LOG_PREFIX, LOG_LEVEL::DEBUG, output.str().c_str()); +} + int EmuX86_OpcodeSize(uint8_t *Eip) { _DInst info; @@ -2903,13 +2903,13 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e) // If an opcode or one of it's operand can't be decoded, that's a clear failure. // However, if for any reason, an opcode operand cannot be read from or written to, // that case may be logged, but it shouldn't fail the opcode handler. - _DInst info; - DWORD StartingEip = e->ContextRecord->Eip; - LOG_CHECK_ENABLED(LOG_LEVEL::DEBUG) { + _DInst info; + DWORD StartingEip = e->ContextRecord->Eip; + LOG_CHECK_ENABLED(LOG_LEVEL::DEBUG) { EmuLog(LOG_PREFIX, LOG_LEVEL::DEBUG, "Starting instruction emulation from 0x%08X", e->ContextRecord->Eip); - } - - // Execute op-codes until we hit an unhandled instruction, or an error occurs + } + + // Execute op-codes until we hit an unhandled instruction, or an error occurs while (true) //for (int x=0;x<3;x++) { @@ -2917,28 +2917,28 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e) EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "Error decoding opcode at 0x%08X", e->ContextRecord->Eip); assert(false); return false; - } + } - LOG_CHECK_ENABLED(LOG_LEVEL::DEBUG) { - EmuX86_DistormLogInstruction((uint8_t*)e->ContextRecord->Eip, info); - } - - switch (info.opcode) { // Keep these cases alphabetically ordered and condensed + LOG_CHECK_ENABLED(LOG_LEVEL::DEBUG) { + EmuX86_DistormLogInstruction((uint8_t*)e->ContextRecord->Eip, info); + } + + switch (info.opcode) { // Keep these cases alphabetically ordered and condensed case I_ADD: if (EmuX86_Opcode_ADD(e, info)) break; goto opcode_error; case I_AND: if (EmuX86_Opcode_AND(e, info)) break; - goto opcode_error; - case I_CALL: - // RET and CALL always signify the end of a code block - return true; - case I_CDQ: // = 250 : Convert Doubleword to Quadword - EmuX86_Opcode_CDQ(e, info); - break; - case I_CLI: { // = 502 : Disable all interrupts - EmuX86_Opcode_CLI(); - break; + goto opcode_error; + case I_CALL: + // RET and CALL always signify the end of a code block + return true; + case I_CDQ: // = 250 : Convert Doubleword to Quadword + EmuX86_Opcode_CDQ(e, info); + break; + case I_CLI: { // = 502 : Disable all interrupts + EmuX86_Opcode_CLI(); + break; } case I_CMP: if (EmuX86_Opcode_CMP(e, info)) break; @@ -2955,7 +2955,7 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e) #if 0 // TODO : Implement EmuX86_Opcode_IMUL and enable this : case I_IMUL: { // = 117 : Signed Multiply if (EmuX86_Opcode_IMUL(e, info)) break; - goto opcode_error; + goto opcode_error; } #endif case I_IN: @@ -2965,142 +2965,142 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e) if (EmuX86_Opcode_INC(e, info)) break; goto opcode_error; case I_INVD: // = 555 : Flush internal caches; initiate flushing of external caches. - break; // Privileged Level (Ring 0) Instruction. Causes a priviledge instruction exception - We can safely ignore this + break; // Privileged Level (Ring 0) Instruction. Causes a priviledge instruction exception - We can safely ignore this case I_INVLPG: { // = 1727 - // This instruction invalidates the TLB entry specified with the source operand. Since we don't emulate - // the TLB yet, we can safely ignore this. Test case: Fable. + // This instruction invalidates the TLB entry specified with the source operand. Since we don't emulate + // the TLB yet, we can safely ignore this. Test case: Fable. break; } - case I_JA: { // = 166 : Jump if above (CF=0 and ZF=0). + case I_JA: { // = 166 : Jump if above (CF=0 and ZF=0). if (EmuX86_Opcode_Jcc(e, info, !EmuX86_HasFlag_CF(e) && !EmuX86_HasFlag_ZF(e))) { continue; - } - break; - } - case I_JAE: { // = 147 : Jump if above or equal (CF=0). + } + break; + } + case I_JAE: { // = 147 : Jump if above or equal (CF=0). if (EmuX86_Opcode_Jcc(e, info, !EmuX86_HasFlag_CF(e))) { continue; - } - break; - } - case I_JB: { // = 143 : Jump if below (CF=1). + } + break; + } + case I_JB: { // = 143 : Jump if below (CF=1). if (EmuX86_Opcode_Jcc(e, info, EmuX86_HasFlag_CF(e))) { continue; - } - break; - } - case I_JBE: { // = 161 : Jump if below or equal (CF=1 or ZF=1). + } + break; + } + case I_JBE: { // = 161 : Jump if below or equal (CF=1 or ZF=1). if (EmuX86_Opcode_Jcc(e, info, EmuX86_HasFlag_CF(e) || EmuX86_HasFlag_ZF(e))) { continue; - } - break; - } - case I_JCXZ: { // = 427 : Jump if CX register is 0. + } + break; + } + case I_JCXZ: { // = 427 : Jump if CX register is 0. if (EmuX86_Opcode_Jcc(e, info, ((e->ContextRecord->Ecx & 0xFF) == 0))) { continue; - } - break; - } - case I_JECXZ: { // = 433 : Jump if ECX register is 0. + } + break; + } + case I_JECXZ: { // = 433 : Jump if ECX register is 0. if (EmuX86_Opcode_Jcc(e, info, e->ContextRecord->Ecx == 0)) { continue; - } - break; - } - case I_JG: { // = 202 : Jump if greater (ZF=0 and SF=OF). + } + break; + } + case I_JG: { // = 202 : Jump if greater (ZF=0 and SF=OF). if (EmuX86_Opcode_Jcc(e, info, !EmuX86_HasFlag_ZF(e) && (EmuX86_HasFlag_SF(e) == EmuX86_HasFlag_OF(e)))) { continue; - } - break; - } - case I_JGE: { // = 192 : Jump if greater or equal (SF=OF). + } + break; + } + case I_JGE: { // = 192 : Jump if greater or equal (SF=OF). if (EmuX86_Opcode_Jcc(e, info, EmuX86_HasFlag_SF(e) == EmuX86_HasFlag_OF(e))) { continue; - } - break; - } - case I_JL: { // = 188 : Jump if less (SF<>OF). + } + break; + } + case I_JL: { // = 188 : Jump if less (SF<>OF). if (EmuX86_Opcode_Jcc(e, info, EmuX86_HasFlag_SF(e) != EmuX86_HasFlag_OF(e))) { continue; - } - break; - } - case I_JLE: { // = 197 : Jump if less or equal (ZF=1 or SF<>OF). + } + break; + } + case I_JLE: { // = 197 : Jump if less or equal (ZF=1 or SF<>OF). if (EmuX86_Opcode_Jcc(e, info, EmuX86_HasFlag_ZF(e) || (EmuX86_HasFlag_SF(e) != EmuX86_HasFlag_OF(e)))) { continue; - } - break; - } - case I_JMP: // = 462 : Jump - case I_JMP_FAR: { // = 467 : Jump + } + break; + } + case I_JMP: // = 462 : Jump + case I_JMP_FAR: { // = 467 : Jump if (EmuX86_Opcode_JMP(e, info)) { continue; - } - break; - } - case I_JNO: { // = 138 : Jump if not overflow (OF=0). + } + break; + } + case I_JNO: { // = 138 : Jump if not overflow (OF=0). if (EmuX86_Opcode_Jcc(e, info, !EmuX86_HasFlag_OF(e))) { continue; - } - break; - } - case I_JNP: { // = 183 : Jump if not parity (PF=0). + } + break; + } + case I_JNP: { // = 183 : Jump if not parity (PF=0). if (EmuX86_Opcode_Jcc(e, info, !EmuX86_HasFlag_PF(e))) { continue; - } - break; - } - case I_JNS: { // = 174 : Jump if not sign (SF=0). + } + break; + } + case I_JNS: { // = 174 : Jump if not sign (SF=0). if (EmuX86_Opcode_Jcc(e, info, !EmuX86_HasFlag_SF(e))) { continue; - } - break; - } - case I_JNZ: { // = 156 : Jump if not zero (ZF=0). + } + break; + } + case I_JNZ: { // = 156 : Jump if not zero (ZF=0). if (EmuX86_Opcode_Jcc(e, info, !EmuX86_HasFlag_ZF(e))) { continue; - } - break; - } - case I_JO: { // = 134 : Jump if overflow (OF=1). + } + break; + } + case I_JO: { // = 134 : Jump if overflow (OF=1). if (EmuX86_Opcode_Jcc(e, info, EmuX86_HasFlag_OF(e))) { continue; - } - break; - } - case I_JP: { // = 179 : Jump if parity (PF=1). + } + break; + } + case I_JP: { // = 179 : Jump if parity (PF=1). if (EmuX86_Opcode_Jcc(e, info, EmuX86_HasFlag_PF(e))) { continue; - } - break; - } - case I_JS: { // = 170 : Jump if sign (SF=1). + } + break; + } + case I_JS: { // = 170 : Jump if sign (SF=1). if (EmuX86_Opcode_Jcc(e, info, EmuX86_HasFlag_SF(e))) { continue; - } - break; - } - case I_JZ: { // = 152 : Jump if zero (ZF = 1). + } + break; + } + case I_JZ: { // = 152 : Jump if zero (ZF = 1). if (EmuX86_Opcode_Jcc(e, info, EmuX86_HasFlag_ZF(e))) { continue; - } - break; - } + } + break; + } case I_LEA: { // = 223 : Load Effective Address if (EmuX86_Opcode_LEA(e, info)) break; goto opcode_error; } case I_LEAVE: - // LEAVE often precedes RET - end of a code block + // LEAVE often precedes RET - end of a code block return true; - case I_LFENCE: { // = 4287 : Serializes load operations. - __asm { lfence }; // emulate as-is (doesn't cause exceptions) - break; - } - case I_MFENCE: { // = 4313 : Serializes load and store operations. - __asm { mfence }; // emulate as-is (doesn't cause exceptions) - break; - } + case I_LFENCE: { // = 4287 : Serializes load operations. + __asm { lfence }; // emulate as-is (doesn't cause exceptions) + break; + } + case I_MFENCE: { // = 4313 : Serializes load and store operations. + __asm { mfence }; // emulate as-is (doesn't cause exceptions) + break; + } case I_MOV: if (EmuX86_Opcode_MOV(e, info)) break; goto opcode_error; @@ -3109,8 +3109,8 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e) goto opcode_error; case I_MOVZX: if (EmuX86_Opcode_MOVZX(e, info)) break; - goto opcode_error; - case I_NEG: + goto opcode_error; + case I_NEG: if (EmuX86_Opcode_NEG(e, info)) break; goto opcode_error; case I_NOT: @@ -3121,85 +3121,85 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e) goto opcode_error; case I_OUT: if (EmuX86_Opcode_OUT(e, info)) break; - goto opcode_error; - case I_POP: { // = 22 : Pop a Value from the Stack + goto opcode_error; + case I_POP: { // = 22 : Pop a Value from the Stack if (EmuX86_Opcode_POP(e, info)) break; goto opcode_error; - } - case I_PUSH: { // = 16 : Push Word or Doubleword Onto the Stack + } + case I_PUSH: { // = 16 : Push Word or Doubleword Onto the Stack if (EmuX86_Opcode_PUSH(e, info)) break; goto opcode_error; } - // TODO : case I_RDPMC: // = 607 : Read Performance-Monitoring Counters; Privileged Level (Ring 0) Instruction. Causes a priviledge instruction exception - case I_RDTSC: // = 593 : Read Time-Stamp Counter - EmuX86_Opcode_RDTSC(e); - break; - case I_RET: - // RET and CALL always signify the end of a code block - return true; - case I_SAR: // = 1002 : Shift arithmetic right - EmuX86_Opcode_SAR(e, info); + // TODO : case I_RDPMC: // = 607 : Read Performance-Monitoring Counters; Privileged Level (Ring 0) Instruction. Causes a priviledge instruction exception + case I_RDTSC: // = 593 : Read Time-Stamp Counter + EmuX86_Opcode_RDTSC(e); + break; + case I_RET: + // RET and CALL always signify the end of a code block + return true; + case I_SAR: // = 1002 : Shift arithmetic right + EmuX86_Opcode_SAR(e, info); break; case I_SBB: if (EmuX86_Opcode_SBB(e, info)) break; - goto opcode_error; - case I_SETA: { // Set byte if above (CF=0 and ZF=0). + goto opcode_error; + case I_SETA: { // Set byte if above (CF=0 and ZF=0). if (EmuX86_Opcode_SETcc(e, info, !EmuX86_HasFlag_CF(e) && !EmuX86_HasFlag_ZF(e))) break; goto opcode_error; } - case I_SETAE: { // Set byte if above or equal (CF=0). + case I_SETAE: { // Set byte if above or equal (CF=0). if (EmuX86_Opcode_SETcc(e, info, !EmuX86_HasFlag_CF(e))) break; goto opcode_error; } - case I_SETB: { // Set byte if below (CF=1). + case I_SETB: { // Set byte if below (CF=1). if (EmuX86_Opcode_SETcc(e, info, EmuX86_HasFlag_CF(e))) break; goto opcode_error; } - case I_SETBE: { // Set byte if below or equal (CF=1 or ZF=1). + case I_SETBE: { // Set byte if below or equal (CF=1 or ZF=1). if (EmuX86_Opcode_SETcc(e, info, EmuX86_HasFlag_CF(e) || EmuX86_HasFlag_ZF(e))) break; goto opcode_error; } - case I_SETG: { // Set byte if greater (ZF=0 and SF=OF). + case I_SETG: { // Set byte if greater (ZF=0 and SF=OF). if (EmuX86_Opcode_SETcc(e, info, !EmuX86_HasFlag_ZF(e) && (EmuX86_HasFlag_SF(e) == EmuX86_HasFlag_OF(e)))) break; goto opcode_error; } - case I_SETGE: { // Set byte if greater or equal (SF=OF). + case I_SETGE: { // Set byte if greater or equal (SF=OF). if (EmuX86_Opcode_SETcc(e, info, EmuX86_HasFlag_SF(e) == EmuX86_HasFlag_OF(e))) break; goto opcode_error; } - case I_SETL: { // Set byte if less (SF<>OF). + case I_SETL: { // Set byte if less (SF<>OF). if (EmuX86_Opcode_SETcc(e, info, EmuX86_HasFlag_SF(e) != EmuX86_HasFlag_OF(e))) break; goto opcode_error; } - case I_SETLE: { // Set byte if less or equal (ZF=1 or SF<>OF). + case I_SETLE: { // Set byte if less or equal (ZF=1 or SF<>OF). if (EmuX86_Opcode_SETcc(e, info, EmuX86_HasFlag_ZF(e) || (EmuX86_HasFlag_SF(e) != EmuX86_HasFlag_OF(e)))) break; goto opcode_error; } - case I_SETNO: { // Set byte if not overflow (OF=0). + case I_SETNO: { // Set byte if not overflow (OF=0). if (EmuX86_Opcode_SETcc(e, info, !EmuX86_HasFlag_OF(e))) break; goto opcode_error; } - case I_SETNP: { // Set byte if not parity (PF=0). + case I_SETNP: { // Set byte if not parity (PF=0). if (EmuX86_Opcode_SETcc(e, info, !EmuX86_HasFlag_PF(e))) break; goto opcode_error; } - case I_SETNS: { // Set byte if not sign (SF=0). + case I_SETNS: { // Set byte if not sign (SF=0). if (EmuX86_Opcode_SETcc(e, info, !EmuX86_HasFlag_SF(e))) break; goto opcode_error; } - case I_SETNZ: { // Set byte if not zero (ZF=0). + case I_SETNZ: { // Set byte if not zero (ZF=0). if (EmuX86_Opcode_SETcc(e, info, !EmuX86_HasFlag_ZF(e))) break; goto opcode_error; } - case I_SETO: { // Set byte if overflow (OF=1). + case I_SETO: { // Set byte if overflow (OF=1). if (EmuX86_Opcode_SETcc(e, info, EmuX86_HasFlag_OF(e))) break; goto opcode_error; } - case I_SETP: { // Set byte if parity (PF=1). + case I_SETP: { // Set byte if parity (PF=1). if (EmuX86_Opcode_SETcc(e, info, EmuX86_HasFlag_PF(e))) break; goto opcode_error; } - case I_SETS: { // Set byte if sign (SF=1). + case I_SETS: { // Set byte if sign (SF=1). if (EmuX86_Opcode_SETcc(e, info, EmuX86_HasFlag_SF(e))) break; goto opcode_error; } @@ -3207,27 +3207,27 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e) if (EmuX86_Opcode_SETcc(e, info, EmuX86_HasFlag_ZF(e))) break; goto opcode_error; } - case I_SFENCE: { // = 4343 : Serializes store operations. - __asm { sfence }; // emulate as-is (doesn't cause exceptions) - break; - } + case I_SFENCE: { // = 4343 : Serializes store operations. + __asm { sfence }; // emulate as-is (doesn't cause exceptions) + break; + } case I_SHL: if (EmuX86_Opcode_SHL(e, info)) break; goto opcode_error; case I_SHR: if (EmuX86_Opcode_SHR(e, info)) break; goto opcode_error; - case I_STI: { - // Enable all interrupts - EmuX86_Opcode_STI(); - break; - } + case I_STI: { + // Enable all interrupts + EmuX86_Opcode_STI(); + break; + } case I_SUB: if (EmuX86_Opcode_SUB(e, info)) break; goto opcode_error; case I_TEST: if (EmuX86_Opcode_TEST(e, info)) break; - goto opcode_error; + goto opcode_error; case I_WBINVD: // Write back and flush internal caches; initiate writing-back and flushing of external caches. break; // Privileged Level (Ring 0) Instruction. Causes a priviledge instruction exception - We can safely ignore this case I_WRMSR: @@ -3236,34 +3236,34 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e) // This needs fixing eventually, but should be acceptible to ignore for now! // Chase: Hollywood Stunt Driver hits this EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "WRMSR instruction ignored"); - break; + break; case I_XOR: if (EmuX86_Opcode_XOR(e, info)) break; goto opcode_error; default: - EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "Unhandled instruction : %s (%u)", Distorm_OpcodeString(info.opcode), info.opcode); - // Fail if the first hit instruction couldn't be emulated, - // but let host CPU execute following (unhandled) instructions : - return (StartingEip != e->ContextRecord->Eip); - } // switch info.opcode - - e->ContextRecord->Eip += info.size; + EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "Unhandled instruction : %s (%u)", Distorm_OpcodeString(info.opcode), info.opcode); + // Fail if the first hit instruction couldn't be emulated, + // but let host CPU execute following (unhandled) instructions : + return (StartingEip != e->ContextRecord->Eip); + } // switch info.opcode + + e->ContextRecord->Eip += info.size; } // while true return true; opcode_error: - EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "0x%08X: Error while handling instruction %s (%u)", e->ContextRecord->Eip, Distorm_OpcodeString(info.opcode), info.opcode); - assert(false); + EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "0x%08X: Error while handling instruction %s (%u)", e->ContextRecord->Eip, Distorm_OpcodeString(info.opcode), info.opcode); + assert(false); return false; } void EmuX86_Init() -{ +{ DBG_PRINTF("Initializing distorm version %d\n", distorm_version()); AddVectoredExceptionHandler(/*FirstHandler=*/ULONG(true), lleException); - EmuX86_InitContextRecordOffsetByRegisterType(); + EmuX86_InitContextRecordOffsetByRegisterType(); EmuX86_InitMemoryBackedRegisters(); } diff --git a/src/core/HLE/D3D8/Direct3D9/Direct3D9.cpp b/src/core/HLE/D3D8/Direct3D9/Direct3D9.cpp index 87975ec75..089fbd8ff 100644 --- a/src/core/HLE/D3D8/Direct3D9/Direct3D9.cpp +++ b/src/core/HLE/D3D8/Direct3D9/Direct3D9.cpp @@ -3439,12 +3439,14 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateVertexShader) DWORD *pRecompiledDeclaration = NULL; DWORD *pRecompiledFunction = NULL; DWORD VertexShaderSize = 0; - DWORD DeclarationSize = 0; + DWORD OriginalDeclarationSize = 0; + DWORD HostDeclarationSize = 0; DWORD Handle = 0; HRESULT hRet = XTL::EmuRecompileVshDeclaration((DWORD*)pDeclaration, (XTL::D3DVERTEXELEMENT9**)&pRecompiledDeclaration, - &DeclarationSize, + &OriginalDeclarationSize, + &HostDeclarationSize, pFunction == NULL, &pVertexShader->VertexShaderInfo); @@ -3470,7 +3472,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateVertexShader) g_VertexShaderConstantMode == X_D3DSCM_NORESERVEDCONSTANTS, &bUseDeclarationOnly, pRecompiledDeclaration, - DeclarationSize); + HostDeclarationSize); if (SUCCEEDED(hRet)) { if (!bUseDeclarationOnly) @@ -3540,14 +3542,15 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateVertexShader) free(pRecompiledDeclaration); - pVertexShader->pDeclaration = (DWORD*)g_VMManager.Allocate(DeclarationSize); - memcpy(pVertexShader->pDeclaration, pDeclaration, DeclarationSize); + pVertexShader->pDeclaration = (DWORD*)g_VMManager.Allocate(HostDeclarationSize); + memcpy(pVertexShader->pDeclaration, pDeclaration, HostDeclarationSize); pVertexShader->FunctionSize = 0; pVertexShader->pFunction = NULL; pVertexShader->Type = X_VST_NORMAL; pVertexShader->Size = (VertexShaderSize - sizeof(VSH_SHADER_HEADER)) / VSH_INSTRUCTION_SIZE_BYTES; - pVertexShader->DeclarationSize = DeclarationSize; + pVertexShader->OriginalDeclarationSize = OriginalDeclarationSize; + pVertexShader->HostDeclarationSize = HostDeclarationSize; if(SUCCEEDED(hRet)) { @@ -5549,7 +5552,18 @@ VOID __stdcall XTL::EMUPATCH(D3DDevice_SetTextureState_TexCoordIndex_0) mov Value, eax } - return EMUPATCH(D3DDevice_SetTextureState_TexCoordIndex)(Stage, Value); + LOG_FUNC_BEGIN + LOG_FUNC_ARG(Stage) + LOG_FUNC_ARG(Value) + LOG_FUNC_END; + + if (Value >= 0x00040000) { + EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "EmuD3DDevice_SetTextureState_TexCoordIndex: Unknown TexCoordIndex Value (0x%.08X)", Value); + return; + } + + HRESULT hRet = g_pD3DDevice->SetTextureStageState(Stage, D3DTSS_TEXCOORDINDEX, Value); + DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetTextureStageState"); } // This uses a custom calling convention where parameter is passed in ESI @@ -5595,6 +5609,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetTextureState_TexCoordIndex) LOG_FUNC_ARG(Value) LOG_FUNC_END; + XB_trampoline(VOID, WINAPI, D3DDevice_SetTextureState_TexCoordIndex, (DWORD, DWORD)); + XB_D3DDevice_SetTextureState_TexCoordIndex(Stage, Value); + // TODO: Xbox Direct3D supports sphere mapping OpenGL style. // BUG FIX: The lower 16 bits were causing false Unknown TexCoordIndex errors. @@ -5619,6 +5636,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_TwoSidedLighting) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_TwoSidedLighting, (DWORD)); + XB_D3DDevice_SetRenderState_TwoSidedLighting(Value); + LOG_NOT_SUPPORTED(); } @@ -5642,6 +5662,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_BackFillMode) // of Direct3D was specifically created to take advantage of certain NVIDIA // GPU registers and provide more OpenGL-like features IHMO. LOG_NOT_SUPPORTED(); + + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_BackFillMode, (DWORD)); + XB_D3DDevice_SetRenderState_BackFillMode(Value); } // LTCG specific D3DDevice_SetTextureState_BorderColor function... @@ -5659,6 +5682,7 @@ VOID XTL::EMUPATCH(D3DDevice_SetTextureState_BorderColor_0) mov Value, ebx } + return EMUPATCH(D3DDevice_SetTextureState_BorderColor)(Stage, Value); } @@ -5698,6 +5722,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetTextureState_BorderColor) LOG_FUNC_ARG(Value) LOG_FUNC_END; + XB_trampoline(VOID, WINAPI, D3DDevice_SetTextureState_BorderColor, (DWORD, DWORD)); + XB_D3DDevice_SetTextureState_BorderColor(Stage, Value); + HRESULT hRet; hRet = g_pD3DDevice->SetSamplerState(Stage, D3DSAMP_BORDERCOLOR, Value); DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetTextureStageState"); @@ -5718,7 +5745,7 @@ VOID XTL::EMUPATCH(D3DDevice_SetTextureState_ColorKeyColor_0) mov Value, ebx } - return EMUPATCH(D3DDevice_SetTextureState_ColorKeyColor)(Stage, Value); + LOG_NOT_SUPPORTED(); } // This uses a custom calling convention where parameter is passed in EAX @@ -5731,7 +5758,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetTextureState_ColorKeyColor_4) DWORD Stage; __asm mov Stage, eax; - return EMUPATCH(D3DDevice_SetTextureState_ColorKeyColor)(Stage, Value); + LOG_NOT_SUPPORTED(); } // ****************************************************************** @@ -5748,6 +5775,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetTextureState_ColorKeyColor) LOG_FUNC_ARG(Value) LOG_FUNC_END; + XB_trampoline(VOID, WINAPI, D3DDevice_SetTextureState_ColorKeyColor, (DWORD, DWORD)); + XB_D3DDevice_SetTextureState_ColorKeyColor(Stage, Value); + LOG_NOT_SUPPORTED(); } @@ -5814,6 +5844,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetTextureState_BumpEnv) LOG_FUNC_ARG(Value) LOG_FUNC_END; + XB_trampoline(VOID, WINAPI, D3DDevice_SetTextureState_BumpEnv, (DWORD, X_D3DTEXTURESTAGESTATETYPE, DWORD)); + XB_D3DDevice_SetTextureState_BumpEnv(Stage, Type, Value); + HRESULT hRet = D3D_OK; switch(Type) @@ -5851,6 +5884,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_FrontFace) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_FrontFace, (DWORD)); + XB_D3DDevice_SetRenderState_FrontFace(Value); + LOG_NOT_SUPPORTED(); } @@ -5864,6 +5900,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_LogicOp) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_LogicOp, (DWORD)); + XB_D3DDevice_SetRenderState_LogicOp(Value); + LOG_NOT_SUPPORTED(); } @@ -5877,6 +5916,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_NormalizeNormals) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_NormalizeNormals, (DWORD)); + XB_D3DDevice_SetRenderState_NormalizeNormals(Value); + HRESULT hRet = g_pD3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, Value); DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetRenderState"); } @@ -5891,6 +5933,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_TextureFactor) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_TextureFactor, (DWORD)); + XB_D3DDevice_SetRenderState_TextureFactor(Value); + HRESULT hRet = g_pD3DDevice->SetRenderState(D3DRS_TEXTUREFACTOR, Value); DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetRenderState"); } @@ -5907,6 +5952,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_ZBias) HRESULT hRet; + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_ZBias, (DWORD)); + XB_D3DDevice_SetRenderState_ZBias(Value); + FLOAT Biased = static_cast(Value) * -0.000005f; Value = *reinterpret_cast(&Biased); @@ -5924,6 +5972,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_EdgeAntiAlias) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_EdgeAntiAlias, (DWORD)); + XB_D3DDevice_SetRenderState_EdgeAntiAlias(Value); + // TODO: Analyze performance and compatibility (undefined behavior on PC with triangles or points) // HRESULT hRet = g_pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, Value); // DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetRenderState"); @@ -5941,6 +5992,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_FillMode) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_FillMode, (DWORD)); + XB_D3DDevice_SetRenderState_FillMode(Value); + DWORD dwFillMode; if(Value != 0) @@ -5967,6 +6021,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_FogColor) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_FogColor, (DWORD)); + XB_D3DDevice_SetRenderState_FogColor(Value); + HRESULT hRet = g_pD3DDevice->SetRenderState(D3DRS_FOGCOLOR, Value); DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetRenderState"); } @@ -5981,6 +6038,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_Dxt1NoiseEnable) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_Dxt1NoiseEnable, (DWORD)); + XB_D3DDevice_SetRenderState_Dxt1NoiseEnable(Value); + LOG_UNIMPLEMENTED(); } @@ -5998,6 +6058,9 @@ VOID __fastcall XTL::EMUPATCH(D3DDevice_SetRenderState_Simple) LOG_FUNC_ARG(Value) LOG_FUNC_END; + XB_trampoline(VOID, __fastcall, D3DDevice_SetRenderState_Simple, (DWORD, DWORD)); + XB_D3DDevice_SetRenderState_Simple(Method, Value); + // Special Case: Handle PixelShader related Render States // TODO: Port over EmuMappedD3DRenderState and related code from Dxbx or Wip_LessVertexPatching // After this, we don't need to do this part anymore @@ -6207,6 +6270,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_VertexBlend) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_VertexBlend, (DWORD)); + XB_D3DDevice_SetRenderState_VertexBlend(Value); + // convert from Xbox direct3d to PC direct3d enumeration if(Value <= 1) { Value = Value; @@ -6233,6 +6299,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_PSTextureModes) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_PSTextureModes, (DWORD)); + XB_D3DDevice_SetRenderState_PSTextureModes(Value); + XTL::TemporaryPixelShaderRenderStates[XTL::X_D3DRS_PSTEXTUREMODES] = Value; } @@ -6246,6 +6315,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_CullMode) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_CullMode, (DWORD)); + XB_D3DDevice_SetRenderState_CullMode(Value); + // convert from Xbox D3D to PC D3D enumeration // TODO: XDK-Specific Tables? So far they are the same switch(Value) @@ -6277,6 +6349,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_LineWidth) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_LineWidth, (DWORD)); + XB_D3DDevice_SetRenderState_LineWidth(Value); + // TODO: Convert to PC format?? // g_pD3DDevice->SetRenderState(D3DRS_LINEPATTERN, Value); LOG_NOT_SUPPORTED(); @@ -6292,6 +6367,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_StencilFail) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_StencilFail, (DWORD)); + XB_D3DDevice_SetRenderState_StencilFail(Value); + HRESULT hRet = g_pD3DDevice->SetRenderState(D3DRS_STENCILFAIL, Value); DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetRenderState"); } @@ -6306,6 +6384,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_OcclusionCullEnable) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_OcclusionCullEnable, (DWORD)); + XB_D3DDevice_SetRenderState_OcclusionCullEnable(Value); + LOG_NOT_SUPPORTED(); } @@ -6319,6 +6400,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_StencilCullEnable) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_StencilCullEnable, (DWORD)); + XB_D3DDevice_SetRenderState_StencilCullEnable(Value); + LOG_NOT_SUPPORTED(); } @@ -6332,6 +6416,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_RopZCmpAlwaysRead) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_RopZCmpAlwaysRead, (DWORD)); + XB_D3DDevice_SetRenderState_RopZCmpAlwaysRead(Value); + LOG_NOT_SUPPORTED(); } @@ -6345,6 +6432,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_RopZRead) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_RopZRead, (DWORD)); + XB_D3DDevice_SetRenderState_RopZRead(Value); + LOG_NOT_SUPPORTED(); } @@ -6358,6 +6448,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_DoNotCullUncompressed) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_DoNotCullUncompressed, (DWORD)); + XB_D3DDevice_SetRenderState_DoNotCullUncompressed(Value); + LOG_NOT_SUPPORTED(); } @@ -6388,6 +6481,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_StencilEnable) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_StencilEnable, (DWORD)); + XB_D3DDevice_SetRenderState_StencilEnable(Value); + HRESULT hRet = g_pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, Value); DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetRenderState"); } @@ -6402,6 +6498,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_MultiSampleAntiAlias) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_MultiSampleAntiAlias, (DWORD)); + XB_D3DDevice_SetRenderState_MultiSampleAntiAlias(Value); + HRESULT hRet = g_pD3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, Value); DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetRenderState"); } @@ -6416,6 +6515,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_MultiSampleMask) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_MultiSampleMask, (DWORD)); + XB_D3DDevice_SetRenderState_MultiSampleMask(Value); + HRESULT hRet = g_pD3DDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, Value); DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetRenderState"); } @@ -6430,6 +6532,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_MultiSampleMode) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_MultiSampleMode, (DWORD)); + XB_D3DDevice_SetRenderState_MultiSampleMode(Value); + LOG_NOT_SUPPORTED(); } @@ -6443,6 +6548,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_MultiSampleRenderTargetMode) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_MultiSampleRenderTargetMode, (DWORD)); + XB_D3DDevice_SetRenderState_MultiSampleRenderTargetMode(Value); + LOG_NOT_SUPPORTED(); } @@ -6456,6 +6564,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_ShadowFunc) { LOG_FUNC_ONE_ARG(Value); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_ShadowFunc, (DWORD)); + XB_D3DDevice_SetRenderState_ShadowFunc(Value); + // ShadowFunc reflects the following Xbox-only extension // // typedef enum _D3DRENDERSTATETYPE { @@ -7561,24 +7672,6 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_DrawIndexedVerticesUP) } } -// ****************************************************************** -// * patch: D3DDevice_GetLight -// ****************************************************************** -VOID WINAPI XTL::EMUPATCH(D3DDevice_GetLight) -( - DWORD Index, - X_D3DLIGHT8 *pLight -) -{ - LOG_FUNC_BEGIN - LOG_FUNC_ARG(Index) - LOG_FUNC_ARG(pLight) - LOG_FUNC_END; - - HRESULT hRet = g_pD3DDevice->GetLight(Index, pLight); - DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetLight"); -} - // ****************************************************************** // * patch: D3DDevice_SetLight // ****************************************************************** @@ -7593,6 +7686,9 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_SetLight) LOG_FUNC_ARG(pLight) LOG_FUNC_END; + XB_trampoline(HRESULT, WINAPI, D3DDevice_SetLight, (DWORD, CONST X_D3DLIGHT8*)); + XB_D3DDevice_SetLight(Index, pLight); + HRESULT hRet = g_pD3DDevice->SetLight(Index, pLight); DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetLight"); @@ -7627,6 +7723,9 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_LightEnable) LOG_FUNC_ARG(bEnable) LOG_FUNC_END; + XB_trampoline(HRESULT, WINAPI, D3DDevice_LightEnable, (DWORD, BOOL)); + XB_D3DDevice_LightEnable(Index, bEnable); + HRESULT hRet = g_pD3DDevice->LightEnable(Index, bEnable); DEBUG_D3DRESULT(hRet, "g_pD3DDevice->LightEnable"); @@ -8243,9 +8342,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_LoadVertexShaderProgram) { DWORD hNewShader = 0; - // Save the contents of the existing vertex shader programLOG_TEST_CASE(LOG_PREFIX, - DWORD* pDeclaration = (DWORD*) malloc( pVertexShader->DeclarationSize ); - memmove( pDeclaration, pVertexShader->pDeclaration, pVertexShader->DeclarationSize ); + // Save the contents of the existing vertex shader program + DWORD* pDeclaration = (DWORD*) malloc( pVertexShader->OriginalDeclarationSize ); + memmove( pDeclaration, pVertexShader->pDeclaration, pVertexShader->OriginalDeclarationSize); // Create a new vertex shader with the new HRESULT hr = EMUPATCH(D3DDevice_CreateVertexShader)( pDeclaration, pFunction, &hNewShader, 0 ); @@ -8319,12 +8418,13 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_GetVertexShaderDeclaration) if (pSizeOfData) { CxbxVertexShader *pVertexShader = MapXboxVertexShaderHandleToCxbxVertexShader(Handle); if (pVertexShader) { - if (*pSizeOfData < pVertexShader->DeclarationSize || !pData) { - *pSizeOfData = pVertexShader->DeclarationSize; + DWORD sizeOfData = pVertexShader->OriginalDeclarationSize * sizeof(DWORD); + if (*pSizeOfData < sizeOfData || !pData) { + *pSizeOfData = sizeOfData; hRet = !pData ? D3D_OK : D3DERR_MOREDATA; } else { - memcpy(pData, pVertexShader->pDeclaration, pVertexShader->DeclarationSize); + memcpy(pData, pVertexShader->pDeclaration, pVertexShader->OriginalDeclarationSize); hRet = D3D_OK; } } @@ -8756,6 +8856,9 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_SampleAlpha) { LOG_FUNC_ONE_ARG(dwSampleAlpha); + XB_trampoline(VOID, WINAPI, D3DDevice_SetRenderState_SampleAlpha, (DWORD)); + XB_D3DDevice_SetRenderState_SampleAlpha(dwSampleAlpha); + // TODO: Implement? LOG_UNIMPLEMENTED(); diff --git a/src/core/HLE/D3D8/Direct3D9/Direct3D9.cpp.unused-patches b/src/core/HLE/D3D8/Direct3D9/Direct3D9.cpp.unused-patches index f595f729e..ceb50d473 100644 --- a/src/core/HLE/D3D8/Direct3D9/Direct3D9.cpp.unused-patches +++ b/src/core/HLE/D3D8/Direct3D9/Direct3D9.cpp.unused-patches @@ -2811,207 +2811,225 @@ VOID __fastcall XTL::EMUPATCH(D3DDevice_SetRenderState_Deferred) } - -// ****************************************************************** -// * patch: D3DDevice_GetViewport -// ****************************************************************** -VOID WINAPI XTL::EMUPATCH(D3DDevice_GetViewport) -( - X_D3DVIEWPORT8 *pViewport -) -{ - FUNC_EXPORTS - - LOG_FUNC_ONE_ARG(pViewport); - - D3DVIEWPORT HostViewPort; - - HRESULT hRet = g_pD3DDevice->GetViewport(&HostViewPort); - DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetViewport"); - - if (!g_ScaleViewport) { - *pViewport = HostViewPort; - } - else { - // Note : We cannot return the Xbox viewport as set in EMUPATCH(D3DDevice_SetViewport) - // because various Xbox D3D functions reset the Xbox viewport. Since we call comparable - // functions on host D3D, the host viewport is better suited as a return value; - // We just need to scale the host viewport back to Xbox dimensions - the exact opposite - // operation from the up-scaling that happens in EMUPATCH(D3DDevice_SetViewport). - - // Get current host render target dimensions - DWORD HostRenderTarget_Width; - DWORD HostRenderTarget_Height; - - if (GetHostRenderTargetDimensions(&HostRenderTarget_Width, &HostRenderTarget_Height)) { - - // Get current Xbox render target dimensions - DWORD XboxRenderTarget_Width = GetPixelContainerWidth(g_pXboxRenderTarget); - DWORD XboxRenderTarget_Height = GetPixelContainerHeigth(g_pXboxRenderTarget); - - // Scale host back to Xbox dimensions (avoiding hard-coding 640 x 480) - pViewport->X = ScaleDWORD(HostViewPort.X, HostRenderTarget_Width, XboxRenderTarget_Width); - pViewport->Y = ScaleDWORD(HostViewPort.Y, HostRenderTarget_Height, XboxRenderTarget_Height); - pViewport->Width = ScaleDWORD(HostViewPort.Width, HostRenderTarget_Width, XboxRenderTarget_Width); - pViewport->Height = ScaleDWORD(HostViewPort.Height, HostRenderTarget_Height, XboxRenderTarget_Height); - pViewport->MinZ = HostViewPort.MinZ; // No need scale Z for now - pViewport->MaxZ = HostViewPort.MaxZ; - } - else { - *pViewport = HostViewPort; - EmuWarning("GetHostRenderTargetDimensions failed - GetViewport returns host viewport instead!"); - } - } -} - -// ****************************************************************** -// * patch: D3D_BlockOnResource -// ****************************************************************** -void WINAPI XTL::EMUPATCH(D3D_BlockOnResource)( X_D3DResource* pResource ) -{ - FUNC_EXPORTS - - LOG_FUNC_ONE_ARG(pResource); - - // TODO: Implement - // NOTE: Azurik appears to call this directly from numerous points - LOG_UNIMPLEMENTED(); - -} - - -// ****************************************************************** -// * patch: IDirect3DResource8_IsBusy -// ****************************************************************** -BOOL WINAPI XTL::EMUPATCH(D3DResource_IsBusy) -( - X_D3DResource *pThis -) -{ - FUNC_EXPORTS - - /* too much output - LOG_FUNC_ONE_ARG(pThis); - //*/ - - return FALSE; -} - - -// ****************************************************************** -// * patch: D3DDevice_SetScissors -// ****************************************************************** -VOID WINAPI XTL::EMUPATCH(D3DDevice_SetScissors) -( - DWORD Count, - BOOL Exclusive, - CONST D3DRECT *pRects -) -{ - FUNC_EXPORTS - - LOG_FUNC_BEGIN - LOG_FUNC_ARG(Count) - LOG_FUNC_ARG(Exclusive) - LOG_FUNC_ARG(pRects) - LOG_FUNC_END; - - // TODO: Implement - LOG_UNIMPLEMENTED(); -} - -// ****************************************************************** -// * patch: D3DDevice_GetScissors -// ****************************************************************** -VOID WINAPI XTL::EMUPATCH(D3DDevice_GetScissors) -( - DWORD *pCount, - BOOL *pExclusive, - D3DRECT *pRects -) -{ - FUNC_EXPORTS - - LOG_FUNC_BEGIN - LOG_FUNC_ARG(pCount) - LOG_FUNC_ARG(pExclusive) - LOG_FUNC_ARG(pRects) - LOG_FUNC_END; - - // TODO: Save a copy of each scissor rect in case this function is called - // in conjunction with D3DDevice::SetScissors. So far, only Outrun2 uses - // this function. For now, just return the values within the current - // viewport. - - D3DVIEWPORT vp; - - HRESULT hRet = g_pD3DDevice->GetViewport( &vp ); - DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetViewport"); - - pRects->x1 = pRects->y1 = 0; - pRects->x2 = vp.Width; - pRects->y2 = vp.Height; - - pExclusive[0] = FALSE; -} - - -// ****************************************************************** -// * patch: D3DDevice_SetBackMaterial -// ****************************************************************** -VOID WINAPI XTL::EMUPATCH(D3DDevice_SetBackMaterial) -( - X_D3DMATERIAL8* pMaterial -) -{ - FUNC_EXPORTS - - LOG_FUNC_ONE_ARG(pMaterial); - - LOG_NOT_SUPPORTED(); -} - - - -// ****************************************************************** -// * patch: D3DDevice_GetBackMaterial -// ****************************************************************** -VOID WINAPI XTL::EMUPATCH(D3DDevice_GetBackMaterial) -( - X_D3DMATERIAL8* pMaterial -) -{ - FUNC_EXPORTS - - LOG_FUNC_ONE_ARG(pMaterial); - - LOG_NOT_SUPPORTED(); - - HRESULT hRet = D3D_OK; - - // TODO: HACK: This is wrong, but better than nothing, right? - if (pMaterial) - { - hRet = g_pD3DDevice->GetMaterial(pMaterial); - DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetMaterial"); - } - - if (FAILED(hRet)) - { - EmuWarning("We're lying about getting a back material!"); - hRet = D3D_OK; - } -} - -// ****************************************************************** -// * patch: D3DDevice_SetRenderState_YuvEnable -// ****************************************************************** -VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_YuvEnable) -( - BOOL Enable -) -{ - LOG_FUNC_ONE_ARG(Enable); - - g_bColorSpaceConvertYuvToRgb = (Enable != FALSE); -} + +// ****************************************************************** +// * patch: D3DDevice_GetViewport +// ****************************************************************** +VOID WINAPI XTL::EMUPATCH(D3DDevice_GetViewport) +( + X_D3DVIEWPORT8 *pViewport +) +{ + FUNC_EXPORTS + + LOG_FUNC_ONE_ARG(pViewport); + + D3DVIEWPORT HostViewPort; + + HRESULT hRet = g_pD3DDevice->GetViewport(&HostViewPort); + DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetViewport"); + + if (!g_ScaleViewport) { + *pViewport = HostViewPort; + } + else { + // Note : We cannot return the Xbox viewport as set in EMUPATCH(D3DDevice_SetViewport) + // because various Xbox D3D functions reset the Xbox viewport. Since we call comparable + // functions on host D3D, the host viewport is better suited as a return value; + // We just need to scale the host viewport back to Xbox dimensions - the exact opposite + // operation from the up-scaling that happens in EMUPATCH(D3DDevice_SetViewport). + + // Get current host render target dimensions + DWORD HostRenderTarget_Width; + DWORD HostRenderTarget_Height; + + if (GetHostRenderTargetDimensions(&HostRenderTarget_Width, &HostRenderTarget_Height)) { + + // Get current Xbox render target dimensions + DWORD XboxRenderTarget_Width = GetPixelContainerWidth(g_pXboxRenderTarget); + DWORD XboxRenderTarget_Height = GetPixelContainerHeigth(g_pXboxRenderTarget); + + // Scale host back to Xbox dimensions (avoiding hard-coding 640 x 480) + pViewport->X = ScaleDWORD(HostViewPort.X, HostRenderTarget_Width, XboxRenderTarget_Width); + pViewport->Y = ScaleDWORD(HostViewPort.Y, HostRenderTarget_Height, XboxRenderTarget_Height); + pViewport->Width = ScaleDWORD(HostViewPort.Width, HostRenderTarget_Width, XboxRenderTarget_Width); + pViewport->Height = ScaleDWORD(HostViewPort.Height, HostRenderTarget_Height, XboxRenderTarget_Height); + pViewport->MinZ = HostViewPort.MinZ; // No need scale Z for now + pViewport->MaxZ = HostViewPort.MaxZ; + } + else { + *pViewport = HostViewPort; + EmuWarning("GetHostRenderTargetDimensions failed - GetViewport returns host viewport instead!"); + } + } +} + +// ****************************************************************** +// * patch: D3D_BlockOnResource +// ****************************************************************** +void WINAPI XTL::EMUPATCH(D3D_BlockOnResource)( X_D3DResource* pResource ) +{ + FUNC_EXPORTS + + LOG_FUNC_ONE_ARG(pResource); + + // TODO: Implement + // NOTE: Azurik appears to call this directly from numerous points + LOG_UNIMPLEMENTED(); + +} + + +// ****************************************************************** +// * patch: IDirect3DResource8_IsBusy +// ****************************************************************** +BOOL WINAPI XTL::EMUPATCH(D3DResource_IsBusy) +( + X_D3DResource *pThis +) +{ + FUNC_EXPORTS + + /* too much output + LOG_FUNC_ONE_ARG(pThis); + //*/ + + return FALSE; +} + + +// ****************************************************************** +// * patch: D3DDevice_SetScissors +// ****************************************************************** +VOID WINAPI XTL::EMUPATCH(D3DDevice_SetScissors) +( + DWORD Count, + BOOL Exclusive, + CONST D3DRECT *pRects +) +{ + FUNC_EXPORTS + + LOG_FUNC_BEGIN + LOG_FUNC_ARG(Count) + LOG_FUNC_ARG(Exclusive) + LOG_FUNC_ARG(pRects) + LOG_FUNC_END; + + // TODO: Implement + LOG_UNIMPLEMENTED(); +} + +// ****************************************************************** +// * patch: D3DDevice_GetScissors +// ****************************************************************** +VOID WINAPI XTL::EMUPATCH(D3DDevice_GetScissors) +( + DWORD *pCount, + BOOL *pExclusive, + D3DRECT *pRects +) +{ + FUNC_EXPORTS + + LOG_FUNC_BEGIN + LOG_FUNC_ARG(pCount) + LOG_FUNC_ARG(pExclusive) + LOG_FUNC_ARG(pRects) + LOG_FUNC_END; + + // TODO: Save a copy of each scissor rect in case this function is called + // in conjunction with D3DDevice::SetScissors. So far, only Outrun2 uses + // this function. For now, just return the values within the current + // viewport. + + D3DVIEWPORT vp; + + HRESULT hRet = g_pD3DDevice->GetViewport( &vp ); + DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetViewport"); + + pRects->x1 = pRects->y1 = 0; + pRects->x2 = vp.Width; + pRects->y2 = vp.Height; + + pExclusive[0] = FALSE; +} + + +// ****************************************************************** +// * patch: D3DDevice_SetBackMaterial +// ****************************************************************** +VOID WINAPI XTL::EMUPATCH(D3DDevice_SetBackMaterial) +( + X_D3DMATERIAL8* pMaterial +) +{ + FUNC_EXPORTS + + LOG_FUNC_ONE_ARG(pMaterial); + + LOG_NOT_SUPPORTED(); +} + + + +// ****************************************************************** +// * patch: D3DDevice_GetBackMaterial +// ****************************************************************** +VOID WINAPI XTL::EMUPATCH(D3DDevice_GetBackMaterial) +( + X_D3DMATERIAL8* pMaterial +) +{ + FUNC_EXPORTS + + LOG_FUNC_ONE_ARG(pMaterial); + + LOG_NOT_SUPPORTED(); + + HRESULT hRet = D3D_OK; + + // TODO: HACK: This is wrong, but better than nothing, right? + if (pMaterial) + { + hRet = g_pD3DDevice->GetMaterial(pMaterial); + DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetMaterial"); + } + + if (FAILED(hRet)) + { + EmuWarning("We're lying about getting a back material!"); + hRet = D3D_OK; + } +} + +// ****************************************************************** +// * patch: D3DDevice_SetRenderState_YuvEnable +// ****************************************************************** +VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderState_YuvEnable) +( + BOOL Enable +) +{ + LOG_FUNC_ONE_ARG(Enable); + + g_bColorSpaceConvertYuvToRgb = (Enable != FALSE); +} + +// ****************************************************************** +// * patch: D3DDevice_GetLight +// ****************************************************************** +VOID WINAPI XTL::EMUPATCH(D3DDevice_GetLight) +( + DWORD Index, + X_D3DLIGHT8 *pLight +) +{ + LOG_FUNC_BEGIN + LOG_FUNC_ARG(Index) + LOG_FUNC_ARG(pLight) + LOG_FUNC_END; + + HRESULT hRet = g_pD3DDevice->GetLight(Index, pLight); + DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetLight"); +} diff --git a/src/core/HLE/D3D8/XbConvert.h b/src/core/HLE/D3D8/XbConvert.h index 21cf32530..b124c5476 100644 --- a/src/core/HLE/D3D8/XbConvert.h +++ b/src/core/HLE/D3D8/XbConvert.h @@ -201,7 +201,7 @@ inline D3DSTENCILOP EmuXB2PC_D3DSTENCILOP(X_D3DSTENCILOP Value) return D3DSTENCILOP_DECR; default: - CxbxKrnlCleanup(LOG_PREFIX_D3DCVT, "Unknown D3DSTENCILOP (0x%.08X)", Value); + EmuLog(LOG_PREFIX_D3DCVT, LOG_LEVEL::WARNING, "Unknown D3DSTENCILOP (0x%.08X)", Value); } return (D3DSTENCILOP) Value; diff --git a/src/core/HLE/D3D8/XbD3D8Types.h b/src/core/HLE/D3D8/XbD3D8Types.h index 9e6f9906a..db8c9f6dd 100644 --- a/src/core/HLE/D3D8/XbD3D8Types.h +++ b/src/core/HLE/D3D8/XbD3D8Types.h @@ -516,8 +516,9 @@ typedef struct _CxbxVertexShader // we save them to be able to return them when necessary. UINT Size; DWORD *pDeclaration; + DWORD OriginalDeclarationSize; XTL::LPDIRECT3DVERTEXDECLARATION9 pHostDeclaration; - DWORD DeclarationSize; + DWORD HostDeclarationSize; DWORD *pFunction; DWORD FunctionSize; DWORD Type; diff --git a/src/core/HLE/D3D8/XbVertexShader.cpp b/src/core/HLE/D3D8/XbVertexShader.cpp index 8c881d348..05eb6ea18 100644 --- a/src/core/HLE/D3D8/XbVertexShader.cpp +++ b/src/core/HLE/D3D8/XbVertexShader.cpp @@ -2361,7 +2361,8 @@ DWORD XTL::EmuRecompileVshDeclaration ( DWORD *pDeclaration, D3DVERTEXELEMENT **ppRecompiledDeclaration, - DWORD *pDeclarationSize, + DWORD *pOriginalDeclarationSize, + DWORD *pHostDeclarationSize, boolean IsFixedFunction, CxbxVertexShaderInfo *pVertexShaderInfo ) @@ -2378,6 +2379,8 @@ DWORD XTL::EmuRecompileVshDeclaration // Calculate size of declaration DWORD DeclarationSize = VshGetDeclarationSize(pDeclaration); + *pOriginalDeclarationSize = DeclarationSize; + // For Direct3D9, we need to reserve at least twice the number of elements, as one token can generate two registers (in and out) : DeclarationSize *= sizeof(D3DVERTEXELEMENT) * 2; @@ -2386,7 +2389,7 @@ DWORD XTL::EmuRecompileVshDeclaration uint8_t *pRecompiledBufferOverflow = ((uint8_t*)pRecompiled) + DeclarationSize; *ppRecompiledDeclaration = pRecompiled; - *pDeclarationSize = DeclarationSize; + *pHostDeclarationSize = DeclarationSize; CxbxVertexShaderPatch PatchData = { 0 }; PatchData.pVertexShaderInfoToSet = pVertexShaderInfo; diff --git a/src/core/HLE/D3D8/XbVertexShader.h b/src/core/HLE/D3D8/XbVertexShader.h index adf4f70dd..34bd75527 100644 --- a/src/core/HLE/D3D8/XbVertexShader.h +++ b/src/core/HLE/D3D8/XbVertexShader.h @@ -54,7 +54,8 @@ extern DWORD EmuRecompileVshDeclaration ( DWORD *pDeclaration, D3DVERTEXELEMENT **ppRecompiledDeclaration, - DWORD *pDeclarationSize, + DWORD *pOriginalDeclarationSize, + DWORD *pHostDeclarationSize, boolean IsFixedFunction, XTL::CxbxVertexShaderInfo *pVertexShaderInfo ); diff --git a/src/core/HLE/Patches.cpp b/src/core/HLE/Patches.cpp index 1079840dd..f9e174780 100644 --- a/src/core/HLE/Patches.cpp +++ b/src/core/HLE/Patches.cpp @@ -91,7 +91,6 @@ std::map g_PatchTable = { PATCH_ENTRY("D3DDevice_GetBackBuffer2", XTL::EMUPATCH(D3DDevice_GetBackBuffer2), PATCH_HLE_D3D), PATCH_ENTRY("D3DDevice_GetDisplayFieldStatus", XTL::EMUPATCH(D3DDevice_GetDisplayFieldStatus), PATCH_HLE_D3D), PATCH_ENTRY("D3DDevice_GetGammaRamp", XTL::EMUPATCH(D3DDevice_GetGammaRamp), PATCH_HLE_D3D), - PATCH_ENTRY("D3DDevice_GetLight", XTL::EMUPATCH(D3DDevice_GetLight), PATCH_HLE_D3D), PATCH_ENTRY("D3DDevice_GetMaterial", XTL::EMUPATCH(D3DDevice_GetMaterial), PATCH_HLE_D3D), PATCH_ENTRY("D3DDevice_GetModelView", XTL::EMUPATCH(D3DDevice_GetModelView), PATCH_HLE_D3D), PATCH_ENTRY("D3DDevice_GetOverlayUpdateStatus", XTL::EMUPATCH(D3DDevice_GetOverlayUpdateStatus), PATCH_HLE_D3D), @@ -438,7 +437,12 @@ void EmuInstallPatches() void* GetPatchedFunctionTrampoline(std::string functionName) { if (g_FunctionHooks.find(functionName) != g_FunctionHooks.end()) { - return g_FunctionHooks[functionName].GetTrampoline(); + auto trampoline = g_FunctionHooks[functionName].GetTrampoline(); + if (trampoline == nullptr) { + EmuLog(CXBXR_MODULE::HLE, LOG_LEVEL::WARNING, "Failed to get XB_Trampoline for %s", functionName.c_str()); + } + + return trampoline; } return nullptr;