tamamo/src/wasm4.zig

188 lines
8.3 KiB
Zig

//
// WASM-4: https://wasm4.org/docs
const std = @import("std");
fn assert_equal(a: anytype, b: anytype, comptime error_msg: []const u8) void {
if (a != b) @compileError(std.fmt.comptimePrint("{} != {} {s}", .{a, b, error_msg}));
}
comptime {
const builtin = @import("builtin");
const native_endian = builtin.target.cpu.arch.endian();
assert_equal(native_endian, .Little, "Bit flags need little endian");
}
// ┌───────────────────────────────────────────────────────────────────────────┐
// │ │
// │ Platform Constants │
// │ │
// └───────────────────────────────────────────────────────────────────────────┘
pub const SCREEN_SIZE: u32 = 160;
// ┌───────────────────────────────────────────────────────────────────────────┐
// │ │
// │ Memory Addresses │
// │ │
// └───────────────────────────────────────────────────────────────────────────┘
pub const Memory = packed struct {
_padding: [4]u8,
palette: [4]Color,
colors: DrawColors,
gamepads: [4]GamePad,
mouse: Mouse,
system: SystemFlags,
_reserved: [128]u8,
framebuffer: [6400]u8,
userdata: [58976]u8,
};
comptime {
assert_equal(@bitSizeOf(Memory), 64 * 1024 * 8, "Memory layout wrong");
}
pub const m = @intToPtr(*allowzero Memory, 0);
pub const Color = packed struct {
blue : u8,
green : u8,
red : u8,
_reserved: u8 = 0,
};
pub const DrawColors = packed struct {
_0: ColorIndex,
_1: ColorIndex,
_2: ColorIndex,
_3: ColorIndex,
};
pub const ColorIndex = enum(u4) {
transparent = 0,
_0 = 1,
_1 = 2,
_2 = 3,
_3 = 4,
};
pub const GamePad = packed struct {
x: bool,
z: bool,
_reserved: u2,
left: bool,
right: bool,
up: bool,
down: bool,
};
pub const Mouse = packed struct {
x: i16,
y: i16,
_0: bool, // primary button
_1: bool, // secondary button
_2: bool, // third button
_reserved: u5,
};
pub const SystemFlags = packed struct {
preserve_framebuffer: bool,
hide_gamepad_overlay: bool,
_reserved: u6,
};
// ┌───────────────────────────────────────────────────────────────────────────┐
// │ │
// │ Drawing Functions │
// │ │
// └───────────────────────────────────────────────────────────────────────────┘
pub const BlitFlags = packed struct {
_2bpp: bool = false,
flip_x: bool = false,
flip_y: bool = false,
rotate: bool = false,
_reserved: u28 = 0,
};
/// Copies pixels to the framebuffer.
pub fn blit(sprite: [*]const u8, x: u32, y: u32, width: u32, height: u32, flags: BlitFlags) void {
raw_api.blit(sprite, x, y, width, height, @bitCast(u32, flags));
}
/// Copies a subregion within a larger sprite atlas to the framebuffer.
pub fn blitSub(sprite: [*]const u8, x: u32, y: u32, width: u32, height: u32, src_x: u32, src_y: u32, stride: u32, flags: BlitFlags) void {
raw_api.blitSub(sprite, x, y, width, height, src_x, src_y, stride, @bitCast(u32, flags));
}
const raw_api = struct {
extern fn blit(sprite: [*]const u8, x: u32, y: u32, width: u32, height: u32, flags: u32) void;
extern fn blitSub(sprite: [*]const u8, x: u32, y: u32, width: u32, height: u32, src_x: u32, src_y: u32, stride: u32, flags: u32) void;
};
/// Draws a line between two points.
pub extern fn line(x1: u32, y1: u32, x2: u32, y2: u32) void;
/// Draws an oval (or circle).
pub extern fn oval(x: u32, y: u32, width: u32, height: u32) void;
/// Draws a rectangle.
pub extern fn rect(x: u32, y: u32, width: u32, height: u32) void;
/// Draws text using the built-in system font.
pub fn text(str: []const u8, x: u32, y: u32) void {
textUtf8(str.ptr, str.len, x, y);
}
extern fn textUtf8(strPtr: [*]const u8, strLen: usize, x: u32, y: u32) void;
/// Draws a vertical line
pub extern fn vline(x: u32, y: u32, len: u32) void;
/// Draws a horizontal line
pub extern fn hline(x: u32, y: u32, len: u32) void;
// ┌───────────────────────────────────────────────────────────────────────────┐
// │ │
// │ Sound Functions │
// │ │
// └───────────────────────────────────────────────────────────────────────────┘
/// Plays a sound tone.
pub extern fn tone(frequency: u32, duration: u32, volume: u32, flags: u32) void;
pub const TONE_PULSE1: u32 = 0;
pub const TONE_PULSE2: u32 = 1;
pub const TONE_TRIANGLE: u32 = 2;
pub const TONE_NOISE: u32 = 3;
pub const TONE_MODE1: u32 = 0;
pub const TONE_MODE2: u32 = 4;
pub const TONE_MODE3: u32 = 8;
pub const TONE_MODE4: u32 = 12;
pub const TONE_PAN_LEFT: u32 = 16;
pub const TONE_PAN_RIGHT: u32 = 32;
// ┌───────────────────────────────────────────────────────────────────────────┐
// │ │
// │ Storage Functions │
// │ │
// └───────────────────────────────────────────────────────────────────────────┘
/// Reads up to `size` bytes from persistent storage into the pointer `dest`.
pub extern fn diskr(dest: [*]u8, size: u32) u32;
/// Writes up to `size` bytes from the pointer `src` into persistent storage.
pub extern fn diskw(src: [*]const u8, size: u32) u32;
// ┌───────────────────────────────────────────────────────────────────────────┐
// │ │
// │ Other Functions │
// │ │
// └───────────────────────────────────────────────────────────────────────────┘
/// Prints a message to the debug console.
pub fn trace(x: []const u8) void {
traceUtf8(x.ptr, x.len);
}
extern fn traceUtf8(strPtr: [*]const u8, strLen: usize) void;