/* dhae_marker.d - Dhaedalida RabbitStart / RabbitEnd virtualization markers for the D
 * programming language. Covers BOTH x86-64 (PE32+) and 32-bit x86 (PE32).
 *
 * Each marker is a naked function that emits the 8 magic bytes of
 * sdk/dhae_marker_sig.h verbatim into .text, so the Dhaedalida GUI detects a
 * caller exactly like the C binding. The db values below MUST equal
 * DHAE_SIG_RABBITSTART / DHAE_SIG_RABBITEND there.
 *
 *     x64:  48 B8 <magic> C3      movabs rax, magic ; ret
 *     x86:  EB 08 <magic> C3      jmp short $+10 ; <data> ; ret
 *
 * On 32-bit there is no 64-bit immediate to hide the magic in, so it is emitted
 * as inline DATA and jumped over - the EB 08 branch lands exactly on the C3.
 * `naked` means no prologue at all, so the magic sits at offset +2 either way.
 *
 * Usage - bracket the function you want protected:
 *
 *     import dhae_marker;
 *     bool validateLicense(string key) {
 *         RabbitStart();
 *         // ... sensitive code ...
 *         RabbitEnd();
 *         return true;
 *     }
 *
 * Build with DMD or LDC: `dmd -c dhae_marker.d` (64-bit) or `dmd -m32mscoff -c
 * dhae_marker.d` / `ldc2 -m32 -c dhae_marker.d` (32-bit), then link into your
 * program. Use -m32mscoff rather than -m32 on DMD older than 2.099, whose -m32
 * emits legacy OMF objects that will not link with MSVC-produced ones.
 * extern(C) gives the C-ABI symbol names the toolchain expects for the target.
 */
module dhae_marker;

extern(C):

version (X86_64)
{
    pragma(inline, false)
    void RabbitStart()
    {
        asm { naked;
            db 0x48, 0xB8, 0x01, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1;  // movabs rax, magic
            db 0xC3;                                                          // ret
        }
    }

    pragma(inline, false)
    void RabbitEnd()
    {
        asm { naked;
            db 0x48, 0xB8, 0x02, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1;  // movabs rax, magic
            db 0xC3;                                                          // ret
        }
    }

    pragma(inline, false)
    void BearStart()
    {
        asm { naked;
            db 0x48, 0xB8, 0x05, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1;  // movabs rax, magic
            db 0xC3;                                                          // ret
        }
    }

    pragma(inline, false)
    void BearEnd()
    {
        asm { naked;
            db 0x48, 0xB8, 0x06, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1;  // movabs rax, magic
            db 0xC3;                                                          // ret
        }
    }
}
else version (X86)
{
    pragma(inline, false)
    void RabbitStart()
    {
        asm { naked;
            db 0xEB, 0x08;                                                    // jmp short $+10
            db 0x01, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1;                // DHAE_SIG_RABBITSTART
            db 0xC3;                                                          // ret
        }
    }

    pragma(inline, false)
    void RabbitEnd()
    {
        asm { naked;
            db 0xEB, 0x08;                                                    // jmp short $+10
            db 0x02, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1;                // DHAE_SIG_RABBITEND
            db 0xC3;                                                          // ret
        }
    }

    pragma(inline, false)
    void BearStart()
    {
        asm { naked;
            db 0xEB, 0x08;                                                    // jmp short $+10
            db 0x05, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1;                // DHAE_SIG_BEARSTART
            db 0xC3;                                                          // ret
        }
    }

    pragma(inline, false)
    void BearEnd()
    {
        asm { naked;
            db 0xEB, 0x08;                                                    // jmp short $+10
            db 0x06, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1;                // DHAE_SIG_BEAREND
            db 0xC3;                                                          // ret
        }
    }
}
else
{
    static assert(0, "Dhaedalida markers require x86-64 (PE32+) or 32-bit x86 (PE32).");
}
