import type { MachineInterface } from './core/types.js'; import type { CallingConvention, ArgValue, ArgType, RetType } from './calling-convention/types.js'; export interface CallOptions { /** Arguments to pass (bare numbers are u8, use { type: 'u16', value } for 16-bit) */ args?: ArgValue[]; /** Return type — determines which register to read (default: 'void') */ ret?: RetType; /** Calling convention (default: sdcccall1) */ cc?: CallingConvention; /** Maximum T-states before aborting */ cycleLimit?: number; } export interface CallResult { /** Return value (0 for void) */ value: number; /** Number of T-states consumed */ tStates: number; } /** * Call a foreign function by address. * * Arguments are placed according to the calling convention (default: SDCC __sdcccall(1)), * the function is executed, and the return value is extracted from the appropriate register. */ declare function call(m: MachineInterface, addr: number, opts?: CallOptions): CallResult; /** Maps ArgType strings to TypeScript types */ type ArgTypeTs = { u8: number; u16: number; }; /** Maps a tuple of ArgType strings to a tuple of TS value types */ type MapArgs = { -readonly [K in keyof T]: T[K] extends ArgType ? ArgTypeTs[T[K]] : never; }; /** Maps a RetType string to the corresponding TS return type */ type MapRet = R extends 'void' ? void : number; /** A bound function — callable with argument values */ export interface BoundFunction { (...args: MapArgs): MapRet; /** Call and return full result with tStates */ detailed(...args: MapArgs): CallResult; } /** An unbound function schema — bind to a machine, or invoke one-shot */ export interface FnSchema { /** Bind to a machine, returning a reusable callable */ bind(m: MachineInterface): BoundFunction; /** One-shot: invoke against a machine without keeping a bound reference */ call(m: MachineInterface, ...args: MapArgs): MapRet; /** One-shot with detailed result (value + tStates) */ callDetailed(m: MachineInterface, ...args: MapArgs): CallResult; } export interface DefOptions { /** Calling convention (default: sdcccall1) */ cc?: CallingConvention; /** Maximum T-states before aborting */ cycleLimit?: number; } /** * Define a foreign function binding. Declares the signature once, then bind to a machine * or invoke one-shot. * * @example * const paddleHeightSchema = ffi.fn(symbols.get('paddle_height'), ['u8'], 'u8') * const paddleHeight = paddleHeightSchema.bind(m) * expect(paddleHeight(0)).toBe(16) * * @example * // One-shot * const schema = ffi.fn(symbols.get('paddle_height'), ['u8'], 'u8') * expect(schema.call(m, 0)).toBe(16) * expect(schema.callDetailed(m, 0).tStates).toBeGreaterThan(0) */ declare function fn(addr: number, args: A, ret: R, opts?: DefOptions): FnSchema; /** Variable type discriminator */ export type VarType = 'u8' | 'i8' | 'u16' | 'i16'; /** Maps VarType to the TypeScript type returned by get() */ type MapVarType = number; /** A bound variable — read/write a typed value at a fixed address */ export interface BoundVariable { /** Read the current value */ get(): MapVarType; /** Write a new value */ set(value: MapVarType): void; /** The memory address of this variable */ readonly addr: number; } /** An unbound variable schema — bind to a machine, or read/write one-shot */ export interface VarSchema { /** Bind to a machine, returning a reusable accessor */ bind(m: MachineInterface): BoundVariable; /** One-shot read against a machine */ get(m: MachineInterface): MapVarType; /** One-shot write against a machine */ set(m: MachineInterface, value: MapVarType): void; /** The memory address of this variable */ readonly addr: number; } /** * Define a typed global variable binding. Declares the type once, then bind to a machine * or read/write one-shot. * * @example * const score = ffi.var(symbols.get('score'), 'u8').bind(m) * score.set(42) * expect(score.get()).toBe(42) * * @example * // One-shot * const velocity = ffi.var(symbols.get('velocity'), 'i8') * velocity.set(m, -5) * expect(velocity.get(m)).toBe(-5) */ declare function varDef(addr: number, type: T): VarSchema; export declare const ffi: { readonly fn: typeof fn; readonly call: typeof call; readonly var: typeof varDef; }; export {}; //# sourceMappingURL=ffi.d.ts.map