initial commit
Signed-off-by: Xe Iaso <me@christine.website>
This commit is contained in:
parent
f47b8b1754
commit
56cde0fcf6
|
@ -1,4 +1,4 @@
|
||||||
# snek
|
# tamamo
|
||||||
|
|
||||||
A game written in Zig for the [WASM-4](https://wasm4.org) fantasy console.
|
A game written in Zig for the [WASM-4](https://wasm4.org) fantasy console.
|
||||||
|
|
||||||
|
|
68
build.zig
68
build.zig
|
@ -1,27 +1,69 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn build(b: *std.build.Builder) void {
|
// Returns true if the version includes https://github.com/ziglang/zig/pull/10572/commits.
|
||||||
const mode = b.standardReleaseOptions();
|
// When this is false, trying to place the stack first will result in data corruption.
|
||||||
|
fn version_supports_stack_first(zig_version: std.SemanticVersion) !bool {
|
||||||
|
if (zig_version.order(try std.SemanticVersion.parse("0.10.0")).compare(.gte)) {
|
||||||
|
// Merged here: https://github.com/ziglang/zig/pull/10572
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (zig_version.major == 0 and zig_version.minor == 10) {
|
||||||
|
// Check for 0.10.0-dev.258+. Conservatively check the prefix of the tag
|
||||||
|
// in case zig uses other prefixes that don't respect semver ordering.
|
||||||
|
if (zig_version.pre) |pre| {
|
||||||
|
// Merged here: https://github.com/ziglang/zig/pull/10572
|
||||||
|
return std.mem.startsWith(u8, pre, "dev.") and zig_version.order(try std.SemanticVersion.parse("0.10.0-dev.258")).compare(.gte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Backported here: https://github.com/ziglang/zig/commit/6f49233ac6a6569b909b689f22fc260dc8c19234
|
||||||
|
return zig_version.order(try std.SemanticVersion.parse("0.9.1")).compare(.gte);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "stack version check" {
|
||||||
|
const expect = std.testing.expect;
|
||||||
|
const parse = std.SemanticVersion.parse;
|
||||||
|
try expect(!try version_supports_stack_first(try parse("0.8.0")));
|
||||||
|
|
||||||
|
try expect(!try version_supports_stack_first(try parse("0.9.0")));
|
||||||
|
try expect(!try version_supports_stack_first(try parse("0.9.1-dev.259")));
|
||||||
|
try expect(try version_supports_stack_first(try parse("0.9.1")));
|
||||||
|
|
||||||
|
// Conservatively don't recognize tags other than 'dev'.
|
||||||
|
try expect(!try version_supports_stack_first(try parse("0.10.0-aev.259")));
|
||||||
|
try expect(!try version_supports_stack_first(try parse("0.10.0-zev.259")));
|
||||||
|
|
||||||
|
try expect(!try version_supports_stack_first(try parse("0.10.0-dev.257")));
|
||||||
|
try expect(try version_supports_stack_first(try parse("0.10.0-dev.258")));
|
||||||
|
try expect(try version_supports_stack_first(try parse("0.10.0-dev.259")));
|
||||||
|
try expect(try version_supports_stack_first(try parse("0.10.0")));
|
||||||
|
|
||||||
|
try expect(try version_supports_stack_first(try parse("0.10.1-dev.100")));
|
||||||
|
try expect(try version_supports_stack_first(try parse("0.10.1-dev.300")));
|
||||||
|
try expect(try version_supports_stack_first(try parse("0.10.1")));
|
||||||
|
|
||||||
|
try expect(try version_supports_stack_first(try parse("1.0.0")));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(b: *std.build.Builder) !void {
|
||||||
|
const zig_version = @import("builtin").zig_version;
|
||||||
|
const mode = b.standardReleaseOptions();
|
||||||
const lib = b.addSharedLibrary("cart", "src/main.zig", .unversioned);
|
const lib = b.addSharedLibrary("cart", "src/main.zig", .unversioned);
|
||||||
lib.setBuildMode(mode);
|
lib.setBuildMode(mode);
|
||||||
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||||
lib.import_memory = true;
|
lib.import_memory = true;
|
||||||
lib.initial_memory = 65536;
|
lib.initial_memory = 65536;
|
||||||
lib.max_memory = 65536;
|
lib.max_memory = 65536;
|
||||||
|
if (try version_supports_stack_first(zig_version)) {
|
||||||
|
lib.stack_size = 14752;
|
||||||
|
} else {
|
||||||
|
// `--stack-first` option have been reenabled on wasm targets with https://github.com/ziglang/zig/pull/10572
|
||||||
|
std.log.warn("Update to Zig >=0.9.1 (or >=0.10.0-dev.258 for nightly) to detect stack overflows at runtime.", .{});
|
||||||
lib.global_base = 6560;
|
lib.global_base = 6560;
|
||||||
lib.stack_size = 8192;
|
lib.stack_size = 8192;
|
||||||
|
}
|
||||||
|
// Workaround https://github.com/ziglang/zig/issues/2910, preventing
|
||||||
|
// functions from compiler_rt getting incorrectly marked as exported, which
|
||||||
|
// prevents them from being removed even if unused.
|
||||||
lib.export_symbol_names = &[_][]const u8{ "start", "update" };
|
lib.export_symbol_names = &[_][]const u8{ "start", "update" };
|
||||||
lib.install();
|
lib.install();
|
||||||
|
|
||||||
const lib_artifact = b.addInstallArtifact(lib);
|
|
||||||
|
|
||||||
const run_command = b.addSystemCommand(&.{
|
|
||||||
"w4", "run", "zig-out/lib/cart.wasm",
|
|
||||||
"--no-open",
|
|
||||||
});
|
|
||||||
run_command.step.dependOn(&lib_artifact.step);
|
|
||||||
|
|
||||||
const run_step = b.step("run", "Run the app");
|
|
||||||
run_step.dependOn(&run_command.step);
|
|
||||||
}
|
}
|
Binary file not shown.
After Width: | Height: | Size: 395 B |
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<tileset version="1.8" tiledversion="1.8.2" name="TownTiles" tilewidth="8" tileheight="8" tilecount="288" columns="24">
|
||||||
|
<image source="TownTiles.png" width="192" height="96"/>
|
||||||
|
</tileset>
|
12
src/main.zig
12
src/main.zig
|
@ -11,17 +11,15 @@ const smiley = [8]u8{
|
||||||
0b11000011,
|
0b11000011,
|
||||||
};
|
};
|
||||||
|
|
||||||
export fn start() void {}
|
|
||||||
|
|
||||||
export fn update() void {
|
export fn update() void {
|
||||||
w4.m.colors._0 = .p1;
|
w4.DRAW_COLORS.* = 2;
|
||||||
w4.text("Hello from Zig!", 10, 10);
|
w4.text("Hello from Zig!", 10, 10);
|
||||||
|
|
||||||
const gamepad = w4.m.gamepads[0];
|
const gamepad = w4.GAMEPAD1.*;
|
||||||
if (gamepad.a) {
|
if (gamepad & w4.BUTTON_1 != 0) {
|
||||||
w4.m.colors._0 = .p3;
|
w4.DRAW_COLORS.* = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
w4.blit(&smiley, 76, 76, 8, 8, .{});
|
w4.blit(&smiley, 76, 76, 8, 8, w4.BLIT_1BPP);
|
||||||
w4.text("Press X to blink", 16, 90);
|
w4.text("Press X to blink", 16, 90);
|
||||||
}
|
}
|
||||||
|
|
260
src/wasm4.zig
260
src/wasm4.zig
|
@ -1,25 +1,13 @@
|
||||||
//
|
//
|
||||||
// WASM-4: https://wasm4.org/docs
|
// 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 │
|
// │ Platform Constants │
|
||||||
// │ │
|
// │ │
|
||||||
// └───────────────────────────────────────────────────────────────────────────┘
|
// └───────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
pub const SCREEN_SIZE: u32 = 160;
|
pub const CANVAS_SIZE: u32 = 160;
|
||||||
|
|
||||||
// ┌───────────────────────────────────────────────────────────────────────────┐
|
// ┌───────────────────────────────────────────────────────────────────────────┐
|
||||||
// │ │
|
// │ │
|
||||||
|
@ -27,99 +15,31 @@ pub const SCREEN_SIZE: u32 = 160;
|
||||||
// │ │
|
// │ │
|
||||||
// └───────────────────────────────────────────────────────────────────────────┘
|
// └───────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
pub const Memory = packed struct {
|
pub const PALETTE: *[4]u32 = @intToPtr(*[4]u32, 0x04);
|
||||||
_padding: [4]u8,
|
pub const DRAW_COLORS: *u16 = @intToPtr(*u16, 0x14);
|
||||||
palette: [4]Color,
|
pub const GAMEPAD1: *const u8 = @intToPtr(*const u8, 0x16);
|
||||||
colors: DrawColors,
|
pub const GAMEPAD2: *const u8 = @intToPtr(*const u8, 0x17);
|
||||||
gamepads: [4]GamePad,
|
pub const GAMEPAD3: *const u8 = @intToPtr(*const u8, 0x18);
|
||||||
mouse: Mouse,
|
pub const GAMEPAD4: *const u8 = @intToPtr(*const u8, 0x19);
|
||||||
system: SystemFlags,
|
pub const MOUSE_X: *const i16 = @intToPtr(*const i16, 0x1a);
|
||||||
_reserved: [128]u8,
|
pub const MOUSE_Y: *const i16 = @intToPtr(*const i16, 0x1c);
|
||||||
framebuffer: [6400]u8,
|
pub const MOUSE_BUTTONS: *const u8 = @intToPtr(*const u8, 0x1e);
|
||||||
userdata: [58976]u8,
|
pub const SYSTEM_FLAGS: *u8 = @intToPtr(*u8, 0x1f);
|
||||||
};
|
pub const FRAMEBUFFER: *[6400]u8 = @intToPtr(*[6400]u8, 0xA0);
|
||||||
|
|
||||||
comptime {
|
pub const BUTTON_1: u8 = 1;
|
||||||
assert_equal(@bitSizeOf(Memory), 64 * 1024 * 8, "Memory layout wrong");
|
pub const BUTTON_2: u8 = 2;
|
||||||
}
|
pub const BUTTON_LEFT: u8 = 16;
|
||||||
|
pub const BUTTON_RIGHT: u8 = 32;
|
||||||
|
pub const BUTTON_UP: u8 = 64;
|
||||||
|
pub const BUTTON_DOWN: u8 = 128;
|
||||||
|
|
||||||
const dummym: Memory = undefined;
|
pub const MOUSE_LEFT: u8 = 1;
|
||||||
|
pub const MOUSE_RIGHT: u8 = 2;
|
||||||
|
pub const MOUSE_MIDDLE: u8 = 4;
|
||||||
|
|
||||||
pub const m = struct {
|
pub const SYSTEM_PRESERVE_FRAMEBUFFER: u8 = 1;
|
||||||
pub const palette = @intToPtr(*@TypeOf(dummym.palette ), 0 + @offsetOf(Memory, "palette" ));
|
pub const SYSTEM_HIDE_GAMEPAD_OVERLAY: u8 = 2;
|
||||||
pub const colors = @intToPtr(*@TypeOf(dummym.colors ), 0 + @offsetOf(Memory, "colors" ));
|
|
||||||
pub const gamepads = @intToPtr(*@TypeOf(dummym.gamepads ), 0 + @offsetOf(Memory, "gamepads" ));
|
|
||||||
pub const mouse = @intToPtr(*@TypeOf(dummym.mouse ), 0 + @offsetOf(Memory, "mouse" ));
|
|
||||||
pub const system = @intToPtr(*@TypeOf(dummym.system ), 0 + @offsetOf(Memory, "system" ));
|
|
||||||
pub const framebuffer = @intToPtr(*@TypeOf(dummym.framebuffer), 0 + @offsetOf(Memory, "framebuffer"));
|
|
||||||
pub const userdata = @intToPtr(*@TypeOf(dummym.userdata ), 0 + @offsetOf(Memory, "userdata" ));
|
|
||||||
};
|
|
||||||
|
|
||||||
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,
|
|
||||||
/// Use palette[0]
|
|
||||||
p0 = 1,
|
|
||||||
/// Use palette[1]
|
|
||||||
p1 = 2,
|
|
||||||
/// Use palette[2]
|
|
||||||
p2 = 3,
|
|
||||||
/// Use palette[3]
|
|
||||||
p3 = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const GamePad = packed struct {
|
|
||||||
a: bool,
|
|
||||||
b: bool,
|
|
||||||
_reserved: u2,
|
|
||||||
left: bool,
|
|
||||||
right: bool,
|
|
||||||
up: bool,
|
|
||||||
down: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Mouse = packed struct {
|
|
||||||
x: i16,
|
|
||||||
y: i16,
|
|
||||||
/// primary button
|
|
||||||
b0: bool,
|
|
||||||
/// secondary button
|
|
||||||
b1: bool,
|
|
||||||
/// third button
|
|
||||||
b2: bool,
|
|
||||||
_reserved: u5,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const SystemFlags = packed struct {
|
|
||||||
preserve_framebuffer: bool,
|
|
||||||
hide_gamepad_overlay: bool,
|
|
||||||
_reserved: u6,
|
|
||||||
};
|
|
||||||
|
|
||||||
// ┌───────────────────────────────────────────────────────────────────────────┐
|
|
||||||
// │ │
|
|
||||||
// │ Raw Functions │
|
|
||||||
// │ │
|
|
||||||
// └───────────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
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;
|
|
||||||
extern fn tone(frequency: u32, duration: u32, volume: u32, flags: u32) void;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ┌───────────────────────────────────────────────────────────────────────────┐
|
// ┌───────────────────────────────────────────────────────────────────────────┐
|
||||||
// │ │
|
// │ │
|
||||||
|
@ -127,49 +47,38 @@ const raw_api = struct {
|
||||||
// │ │
|
// │ │
|
||||||
// └───────────────────────────────────────────────────────────────────────────┘
|
// └───────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
pub const BlitFlags = packed struct {
|
|
||||||
/// one or two bits per pixel
|
|
||||||
two_bits: bool = false,
|
|
||||||
flip_x: bool = false,
|
|
||||||
flip_y: bool = false,
|
|
||||||
rotate: bool = false,
|
|
||||||
_reserved: u28 = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Copies pixels to the framebuffer.
|
/// Copies pixels to the framebuffer.
|
||||||
pub fn blit(sprite: []const u8, x: u32, y: u32, width: u32, height: u32, flags: BlitFlags) void {
|
pub extern fn blit(sprite: [*]const u8, x: i32, y: i32, width: i32, height: i32, flags: u32) void;
|
||||||
|
|
||||||
raw_api.blit(sprite.ptr, x, y, width, height, @bitCast(u32, flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Copies a subregion within a larger sprite atlas to the framebuffer.
|
/// Copies a subregion within a larger sprite atlas to the framebuffer.
|
||||||
/// srcX: Source X position of the sprite region.
|
pub extern fn blitSub(sprite: [*]const u8, x: i32, y: i32, width: i32, height: i32, src_x: u32, src_y: u32, stride: i32, flags: u32) void;
|
||||||
/// srcY: Source Y position of the sprite region.
|
|
||||||
/// stride: Total width of the overall sprite atlas. This is typically larger than width.
|
pub const BLIT_2BPP: u32 = 1;
|
||||||
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 {
|
pub const BLIT_1BPP: u32 = 0;
|
||||||
raw_api.blitSub(sprite.ptr, x, y, width, height, src_x, src_y, stride, @bitCast(u32, flags));
|
pub const BLIT_FLIP_X: u32 = 2;
|
||||||
}
|
pub const BLIT_FLIP_Y: u32 = 4;
|
||||||
|
pub const BLIT_ROTATE: u32 = 8;
|
||||||
|
|
||||||
/// Draws a line between two points.
|
/// Draws a line between two points.
|
||||||
pub extern fn line(x1: u32, y1: u32, x2: u32, y2: u32) void;
|
pub extern fn line(x1: i32, y1: i32, x2: i32, y2: i32) void;
|
||||||
|
|
||||||
/// Draws an oval (or circle).
|
/// Draws an oval (or circle).
|
||||||
pub extern fn oval(x: u32, y: u32, width: u32, height: u32) void;
|
pub extern fn oval(x: i32, y: i32, width: i32, height: i32) void;
|
||||||
|
|
||||||
/// Draws a rectangle.
|
/// Draws a rectangle.
|
||||||
pub extern fn rect(x: u32, y: u32, width: u32, height: u32) void;
|
pub extern fn rect(x: i32, y: i32, width: u32, height: u32) void;
|
||||||
|
|
||||||
/// Draws text using the built-in system font.
|
/// Draws text using the built-in system font.
|
||||||
pub fn text(str: []const u8, x: u32, y: u32) void {
|
pub fn text(str: []const u8, x: i32, y: i32) void {
|
||||||
textUtf8(str.ptr, str.len, x, y);
|
textUtf8(str.ptr, str.len, x, y);
|
||||||
}
|
}
|
||||||
extern fn textUtf8(strPtr: [*]const u8, strLen: usize, x: u32, y: u32) void;
|
extern fn textUtf8(strPtr: [*]const u8, strLen: usize, x: i32, y: i32) void;
|
||||||
|
|
||||||
/// Draws a vertical line
|
/// Draws a vertical line
|
||||||
pub extern fn vline(x: u32, y: u32, len: u32) void;
|
pub extern fn vline(x: i32, y: i32, len: u32) void;
|
||||||
|
|
||||||
/// Draws a horizontal line
|
/// Draws a horizontal line
|
||||||
pub extern fn hline(x: u32, y: u32, len: u32) void;
|
pub extern fn hline(x: i32, y: i32, len: u32) void;
|
||||||
|
|
||||||
// ┌───────────────────────────────────────────────────────────────────────────┐
|
// ┌───────────────────────────────────────────────────────────────────────────┐
|
||||||
// │ │
|
// │ │
|
||||||
|
@ -178,81 +87,16 @@ pub extern fn hline(x: u32, y: u32, len: u32) void;
|
||||||
// └───────────────────────────────────────────────────────────────────────────┘
|
// └───────────────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
/// Plays a sound tone.
|
/// Plays a sound tone.
|
||||||
/// frequency: Wave frequency in hertz.
|
pub extern fn tone(frequency: u32, duration: u32, volume: u32, flags: u32) void;
|
||||||
/// duration: Duration of the tone in frames (1/60th of a second), up to 255 frames.
|
|
||||||
/// volume: Volume of the sustain and attack durations, between 0 and 100.
|
|
||||||
pub fn tone(frequency: Tone.Frequency, duration: Tone.Duration, volume: Tone.Volume, flags: Tone.Flags) void {
|
|
||||||
std.debug.assert(volume.is_valid());
|
|
||||||
tone(@bitCast(u32, frequency), @bitCast(u32, duration), @bitCast(u32, volume), @bitCast(u32, flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const Tone = struct {
|
pub const TONE_PULSE1: u32 = 0;
|
||||||
/// Wave frequency in hertz.
|
pub const TONE_PULSE2: u32 = 1;
|
||||||
pub const Frequency = packed struct {
|
pub const TONE_TRIANGLE: u32 = 2;
|
||||||
start: u16,
|
pub const TONE_NOISE: u32 = 3;
|
||||||
end: u16 = 0,
|
pub const TONE_MODE1: u32 = 0;
|
||||||
};
|
pub const TONE_MODE2: u32 = 4;
|
||||||
|
pub const TONE_MODE3: u32 = 8;
|
||||||
/// Duration of ADSR of note (unit: frames)
|
pub const TONE_MODE4: u32 = 12;
|
||||||
///
|
|
||||||
/// ^
|
|
||||||
/// / \ decay
|
|
||||||
/// attack / \
|
|
||||||
/// / \--------
|
|
||||||
/// / sustain \ release
|
|
||||||
/// / \
|
|
||||||
pub const Duration = packed struct {
|
|
||||||
sustain : u8 = 0,
|
|
||||||
release : u8 = 0,
|
|
||||||
decay : u8 = 0,
|
|
||||||
attack : u8 = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Volume of note (0 to 100)
|
|
||||||
///
|
|
||||||
/// ^ <-- attack volume
|
|
||||||
/// / \
|
|
||||||
/// / \
|
|
||||||
/// / \-------- <-- sustain valume
|
|
||||||
/// / \
|
|
||||||
/// / \
|
|
||||||
pub const Volume = packed struct {
|
|
||||||
sustain : u8,
|
|
||||||
attack : u8 = 100,
|
|
||||||
|
|
||||||
pub fn is_valid(volume: @This()) bool {
|
|
||||||
return (0 <= volume.sustain) and (volume.sustain <= 100)
|
|
||||||
and (0 <= volume.attack ) and (volume.attack <= 100);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Flags = packed struct {
|
|
||||||
channel: Channel,
|
|
||||||
pulse_duty: DutyCycle = 2,
|
|
||||||
pan: Pan = .both,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Channel = enum(u2) {
|
|
||||||
pulse0 = 0,
|
|
||||||
pulse1 = 1,
|
|
||||||
triangle = 2,
|
|
||||||
noise = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const DutyCycle = enum(u2) {
|
|
||||||
@"1/8" = 0,
|
|
||||||
@"1/4" = 1,
|
|
||||||
@"1/2" = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Which stereo channel(s) to play audio in
|
|
||||||
pub const Pan = enum(u2) {
|
|
||||||
/// play audio in both stereo channels
|
|
||||||
both = 0,
|
|
||||||
left = 1,
|
|
||||||
right = 2,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// ┌───────────────────────────────────────────────────────────────────────────┐
|
// ┌───────────────────────────────────────────────────────────────────────────┐
|
||||||
// │ │
|
// │ │
|
||||||
|
@ -277,3 +121,13 @@ pub fn trace(x: []const u8) void {
|
||||||
traceUtf8(x.ptr, x.len);
|
traceUtf8(x.ptr, x.len);
|
||||||
}
|
}
|
||||||
extern fn traceUtf8(strPtr: [*]const u8, strLen: usize) void;
|
extern fn traceUtf8(strPtr: [*]const u8, strLen: usize) void;
|
||||||
|
|
||||||
|
/// Use with caution, as there's no compile-time type checking.
|
||||||
|
///
|
||||||
|
/// * %c, %d, and %x expect 32-bit integers.
|
||||||
|
/// * %f expects 64-bit floats.
|
||||||
|
/// * %s expects a *zero-terminated* string pointer.
|
||||||
|
///
|
||||||
|
/// See https://github.com/aduros/wasm4/issues/244 for discussion and type-safe
|
||||||
|
/// alternatives.
|
||||||
|
pub extern fn tracef(x: [*:0]const u8, ...) void;
|
||||||
|
|
Loading…
Reference in New Issue