// dhae_marker.zig - Dhaedalida RabbitStart / RabbitEnd virtualization markers for Zig.
// Covers BOTH x86-64 (PE32+) and 32-bit x86 (PE32).
//
// Each marker is an exported C-ABI function whose body is a single volatile
// `.byte` sequence. Using `.byte` makes it syntax- and Zig-version-neutral, and
// emitting no `ret` of our own lets Zig's own epilogue return normally - so this
// is a plain, callable function with the magic within its first bytes. The 8
// magic bytes land in .text and the Dhaedalida GUI detects a caller exactly like
// the C binding (see sdk/dhae_marker_sig.h). The .byte values below MUST equal
// DHAE_SIG_RABBITSTART / DHAE_SIG_RABBITEND there.
//
//     x64:  48 B8 <magic>      movabs rax, magic
//     x86:  EB 08 <magic>      jmp short $+10 ; <data>
//
// On 32-bit there is no 64-bit immediate to hide the magic in, so it is emitted
// as inline DATA and jumped over. Leaving the `ret` to the compiler is what
// makes that safe with or without a prologue: the EB 08 branch lands on whatever
// epilogue Zig generated, which returns correctly. A hand-written `ret` would
// skip a `pop ebp` if a prologue were present.
//
// Usage - import and bracket the function you want protected:
//
//     const dhae = @import("dhae_marker.zig");
//     fn validateLicense(key: []const u8) bool {
//         dhae.RabbitStart();
//         // ... sensitive code ...
//         dhae.RabbitEnd();
//         return true;
//     }
//
// Build: `zig build-exe yourapp.zig` (host target), or for 32-bit Windows
// `zig build-exe yourapp.zig -target x86-windows-gnu` (or -target x86-windows-msvc).
//
// `export` gives external linkage (not inlined, C-ABI name); the volatile asm is
// an observable side effect the optimizer keeps.

const builtin = @import("builtin");

export fn RabbitStart() callconv(.C) void {
    switch (builtin.cpu.arch) {
        .x86_64 => asm volatile (".byte 0x48, 0xB8, 0x01, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1" // movabs rax, 0xD11AE5C0DE765401
            :
            :
            : "rax"),
        .x86 => asm volatile (".byte 0xEB, 0x08, 0x01, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1"), // jmp short $+10 ; DHAE_SIG_RABBITSTART
        else => @compileError("Dhaedalida markers require x86-64 (PE32+) or 32-bit x86 (PE32)."),
    }
}

export fn RabbitEnd() callconv(.C) void {
    switch (builtin.cpu.arch) {
        .x86_64 => asm volatile (".byte 0x48, 0xB8, 0x02, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1" // movabs rax, 0xD11AE5C0DE765402
            :
            :
            : "rax"),
        .x86 => asm volatile (".byte 0xEB, 0x08, 0x02, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1"), // jmp short $+10 ; DHAE_SIG_RABBITEND
        else => @compileError("Dhaedalida markers require x86-64 (PE32+) or 32-bit x86 (PE32)."),
    }
}

export fn BearStart() callconv(.C) void {
    switch (builtin.cpu.arch) {
        .x86_64 => asm volatile (".byte 0x48, 0xB8, 0x05, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1" // movabs rax, 0xD11AE5C0DE765405
            :
            :
            : "rax"),
        .x86 => asm volatile (".byte 0xEB, 0x08, 0x05, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1"), // jmp short $+10 ; DHAE_SIG_BEARSTART
        else => @compileError("Dhaedalida markers require x86-64 (PE32+) or 32-bit x86 (PE32)."),
    }
}

export fn BearEnd() callconv(.C) void {
    switch (builtin.cpu.arch) {
        .x86_64 => asm volatile (".byte 0x48, 0xB8, 0x06, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1" // movabs rax, 0xD11AE5C0DE765406
            :
            :
            : "rax"),
        .x86 => asm volatile (".byte 0xEB, 0x08, 0x06, 0x54, 0x76, 0xDE, 0xC0, 0xE5, 0x1A, 0xD1"), // jmp short $+10 ; DHAE_SIG_BEAREND
        else => @compileError("Dhaedalida markers require x86-64 (PE32+) or 32-bit x86 (PE32)."),
    }
}
