133 lines
3.2 KiB
Zig
133 lines
3.2 KiB
Zig
const video = @import("video.zig");
|
|
const audio = @import("audio.zig");
|
|
const input = @import("input.zig");
|
|
const storage = @import("storage.zig");
|
|
|
|
pub const Spec = struct {
|
|
name: []const u8,
|
|
|
|
video_outputs: []const video.VideoOutputSpec = &.{},
|
|
|
|
audio_outputs: []const audio.StreamSpec = &.{},
|
|
audio_inputs: []const audio.StreamSpec = &.{},
|
|
|
|
input_devices: []const input.DeviceSpec = &.{},
|
|
|
|
storage_devices: []const storage.Spec = &.{},
|
|
};
|
|
|
|
pub fn validate(comptime System: type) void {
|
|
comptime {
|
|
if (!@hasDecl(System, "spec")) {
|
|
@compileError(
|
|
"System must expose `pub const spec: contract.SystemSpec`",
|
|
);
|
|
}
|
|
|
|
if (@TypeOf(System.spec) != Spec) {
|
|
@compileError(
|
|
"`System.spec` must have type contract.SystemSpec",
|
|
);
|
|
}
|
|
|
|
requireFunction(
|
|
System,
|
|
"reset",
|
|
fn (*System) void,
|
|
);
|
|
|
|
requireFunction(
|
|
System,
|
|
"runFrame",
|
|
fn (*System) void,
|
|
);
|
|
|
|
if (System.spec.video_outputs.len != 0) {
|
|
requireFunction(
|
|
System,
|
|
"videoFrame",
|
|
fn (*const System, usize) video.VideoFrame,
|
|
);
|
|
}
|
|
|
|
if (System.spec.audio_outputs.len != 0) {
|
|
requireFunction(
|
|
System,
|
|
"audioBuffer",
|
|
fn (*const System, usize) audio.Buffer,
|
|
);
|
|
}
|
|
|
|
if (System.spec.audio_inputs.len != 0) {
|
|
requireFunction(
|
|
System,
|
|
"submitAudioInput",
|
|
fn (*System, usize, audio.Buffer) void,
|
|
);
|
|
}
|
|
|
|
if (System.spec.input_devices.len != 0) {
|
|
requireFunction(
|
|
System,
|
|
"setInput",
|
|
fn (*System, usize, input.DeviceInput) void,
|
|
);
|
|
}
|
|
|
|
var has_haptics = false;
|
|
|
|
for (System.spec.input_devices) |device| {
|
|
if (device.haptic_count != 0) {
|
|
has_haptics = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (has_haptics) {
|
|
requireFunction(
|
|
System,
|
|
"deviceFeedback",
|
|
fn (*const System, usize) input.DeviceFeedback,
|
|
);
|
|
}
|
|
|
|
if (System.spec.storage_devices.len != 0) {
|
|
requireFunction(
|
|
System,
|
|
"storageView",
|
|
fn (*const System, usize) storage.View,
|
|
);
|
|
|
|
requireFunction(
|
|
System,
|
|
"loadStorage",
|
|
fn (
|
|
*System,
|
|
usize,
|
|
[]const u8,
|
|
) storage.LoadError!void,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn requireFunction(
|
|
comptime System: type,
|
|
comptime name: []const u8,
|
|
comptime Expected: type,
|
|
) void {
|
|
if (!@hasDecl(System, name)) {
|
|
@compileError(
|
|
"System must implement `" ++ name ++ "`",
|
|
);
|
|
}
|
|
|
|
const Actual = @TypeOf(@field(System, name));
|
|
|
|
if (Actual != Expected) {
|
|
@compileError(
|
|
"`" ++ name ++ "` has an invalid signature",
|
|
);
|
|
}
|
|
}
|