/* dhae_sdk.h - Dhaedalida virtualization marker SDK
 *
 * Tag a function for protection by Dhaedalida. Wrap the region you
 * want protected between RabbitStart() and RabbitEnd(); the Dhaedalida GUI detects any
 * function that calls these markers and auto-selects the WHOLE enclosing
 * function for virtualization (Dhaedalida protects at method granularity, so
 * the markers tag the function rather than carving out a sub-region).
 *
 *     #include "dhae_sdk.h"
 *
 *     int validate_license(const char* key) {
 *         RabbitStart();
 *         ... sensitive code ...
 *         RabbitEnd();
 *         return ok;
 *     }
 *
 * The markers compile to ordinary C-ABI calls into the no-op functions
 * defined in dhae_sdk.c (link that file, or a .obj/.lib built from it, into
 * your program). They cost a single call each and are harmless if left in the
 * final binary.
 *
 * Multi-language note: the marker is detected by a byte-signature scan (see
 * dhae_marker_sig.h), so it works regardless of source language. This header is
 * the C/C++ binding; ready-made bindings for Rust, Delphi/Object Pascal, Go,
 * assembly (MASM/FASM/NASM), D, Zig, and Nim ship under sdk/bindings/. Any other
 * language with a C FFI can declare these four externs and link dhae_sdk.c. See
 * the SDK README beside this file for the byte contract and the binding index.
 *
 * Bitness: both x86-64 (PE32+) and 32-bit x86 (PE32) targets are supported, from
 * this one header and one .c - the build line never changes:
 *
 *     cl /O2 yourapp.c dhae_sdk.c        (x64 dev prompt -> PE32+)
 *     cl /O2 yourapp.c dhae_sdk.c        (x86 dev prompt -> PE32)
 */
#ifndef DHAE_SDK_H
#define DHAE_SDK_H

/* Calling convention of the markers.
 *
 * On x86-64 there is exactly one convention, so this expands to NOTHING and the
 * macro itself contributes no bytes.
 *
 * ⚠ THIS PARAGRAPH USED TO CLAIM MORE THAN THAT, AND THE EXTRA CLAIM IS NOW FALSE.
 * It said the object Dhaedalida.vcxproj compiles into the CLI "stays byte-identical
 * BY CONSTRUCTION rather than by inspection" -- true of the macro, and it was being
 * read as true of the file. Withdrawing a marker pair removed two declarations from
 * this header and four definitions from dhae_sdk.c, so the x64 object DOES change in
 * this version. What is byte-identical by construction is the expansion of DHAE_CALL on
 * x64, nothing more; whether the unreferenced marker bodies survive the link is a
 * question for dhae-marker-scan, not for a sentence here.
 *
 * On 32-bit x86 it pins __cdecl, so the symbol is always `_RabbitStart` / `_RabbitEnd`
 * whatever the consumer's default-convention switch is (MSVC /Gd /Gr /Gz, GCC
 * -mrtd). The markers take no arguments and return void, so cdecl is always
 * CORRECT - and pinning it is what lets a prebuilt dhae_sdk.obj link into a /Gz
 * project instead of failing with an unresolved `_RabbitStart@0`. */
#if defined(_M_IX86)
#  define DHAE_CALL __cdecl
#elif defined(__i386__) && (defined(__GNUC__) || defined(__clang__))
#  define DHAE_CALL __attribute__((cdecl))
#else
#  define DHAE_CALL
#endif

#ifdef __cplusplus
extern "C" {
#endif

/* Marks the start of a region to virtualize. The enclosing function is what
 * gets protected. */
void DHAE_CALL RabbitStart(void);

/* Marks the end of a region to virtualize. */
void DHAE_CALL RabbitEnd(void);

/* Marks the start of a region to protect with the STACK VM -- the strongest of
 * the three modes and by far the slowest. The enclosing function becomes a
 * bytecode program run by a per-method interpreter: its operations are not
 * relocated but DESTROYED (rebuilt from NOR and ADD at build time), and its
 * control flow becomes data rather than branches. Budget roughly 80 times
 * native, so this is the marker for a licence check or a key schedule, never for
 * a hot loop. Like the other two pairs these tag the ENCLOSING FUNCTION; they do
 * not delimit a sub-region.
 *
 * Both bitnesses. On a 32-bit (PE32) target a Bear-marked function that
 * makes an external call, that needs the native escape hatch, or that ends
 * in `ret imm16` is refused by name and left native; everything else is
 * protected with Bear exactly as on x86-64.
 *
 * ⚠ THE TWO PAIRS MAY BE USED IN ONE PROGRAM, BUT NOT IN ONE FUNCTION. A
 * function carrying both pairs is ambiguous about which protection it wants, and
 * the protector refuses to guess: the GUI names it and declines the job rather
 * than silently applying one of them. (This is a change of behaviour -- an
 * earlier release resolved a RabbitStart+BearStart function to virtualization.
 * Remove one pair.) */
void DHAE_CALL BearStart(void);

/* Marks the end of a region to protect with Bear. */
void DHAE_CALL BearEnd(void);

#ifdef __cplusplus
}
#endif

#endif /* DHAE_SDK_H */
