diff --git a/assets/assets-template b/assets/assets-template new file mode 100644 index 0000000..690e8ed --- /dev/null +++ b/assets/assets-template @@ -0,0 +1,8 @@ +{{#sprites}} +// {{name}} +pub const {{name}}_width = {{width}}; +pub const {{name}}_height = {{height}}; +pub const {{name}}_flags = {{flags}}; // {{flagsHumanReadable}} +pub const {{name}} = [{{length}}]u8{ {{bytes}} }; + +{{/sprites}} diff --git a/assets/assets.zig b/assets/assets.zig new file mode 100644 index 0000000..8e6d3d7 --- /dev/null +++ b/assets/assets.zig @@ -0,0 +1,2 @@ +// pub const tiles = @import("tiles.zig"); +pub usingnamespace @import("sprites.zig"); diff --git a/assets/sprites.png b/assets/sprites.png new file mode 100644 index 0000000..e087bc7 Binary files /dev/null and b/assets/sprites.png differ diff --git a/assets/sprites.zig b/assets/sprites.zig new file mode 100644 index 0000000..8fefa5f --- /dev/null +++ b/assets/sprites.zig @@ -0,0 +1,6 @@ +// sprites +pub const sprites_width = 128; +pub const sprites_height = 128; +pub const sprites_flags = 0; // BLIT_1BPP +pub const sprites = [2048]u8{ 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x7e,0x3c,0x3c,0x7e,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x7e,0xbd,0x7e,0x3c,0xbd,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0xbd,0x3c,0xbd,0x3c,0x3e,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x18,0x18,0x1c,0x24,0x22,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x08,0x18,0x10,0x24,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + diff --git a/assets/tiles.png b/assets/tiles.png new file mode 100644 index 0000000..9811d38 Binary files /dev/null and b/assets/tiles.png differ diff --git a/assets/tiles.zig b/assets/tiles.zig new file mode 100644 index 0000000..4e70e5b --- /dev/null +++ b/assets/tiles.zig @@ -0,0 +1,6 @@ +// tiles +pub const tiles_width = 128; +pub const tiles_height = 128; +pub const tiles_flags = 1; // BLIT_2BPP +pub const tiles = [4096]u8{ 0x00,0x00,0x40,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x50,0x05,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x04,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x41,0x41,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x55,0x55,0x54,0x55,0x55,0x40,0x01,0x15,0x55,0x55,0x55,0x55,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x01,0x15,0x11,0x14,0x04,0x50,0x05,0x54,0x01,0x10,0x11,0x15,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0x00,0x01,0x00,0x00,0x40,0x11,0x40,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x04,0x05,0x04,0x00,0x40,0x01,0x40,0x00,0x04,0x00,0x04,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x01,0x00,0x00,0x40,0x01,0x40,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x00,0x00,0x41,0x00,0x10,0x51,0x05,0x51,0x00,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x05,0x04,0x04,0x50,0x01,0x50,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0x55,0x55,0x40,0x01,0x40,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x01,0x40,0x01,0x15,0x54,0x40,0x01,0x40,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x05,0x44,0x05,0x00,0x50,0x41,0x00,0x01,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x05,0x40,0x05,0x00,0x00,0x50,0x00,0x00,0x04,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x41,0x40,0x41,0x10,0x00,0x40,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x10,0x01,0x50,0x01,0x00,0x00,0x41,0x00,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x01,0x40,0x01,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x01,0x11,0x15,0x50,0x11,0x00,0x10,0x50,0x00,0x00,0x01,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x55,0x55,0x54,0x15,0x54,0x40,0x01,0x50,0x00,0x40,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x54,0x15,0x55,0x44,0x01,0x55,0x54,0x44,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x05,0x55,0x10,0x40,0x01,0x14,0x05,0x40,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x11,0x40,0x00,0x50,0x05,0x00,0x05,0x50,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x44,0x44,0x50,0x01,0x00,0x41,0x50,0x00,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x00,0x40,0x41,0x10,0x01,0x40,0x40,0x01,0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x05,0x40,0x40,0x40,0x01,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x01,0x41,0x04,0x51,0x05,0x11,0x15,0x51,0x01,0x14,0x11,0x11,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x15,0x55,0x15,0x54,0x55,0x54,0x15,0x55,0x55,0x55,0x55,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x55,0x40,0x01,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x50,0x00,0x51,0x40,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x01,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x11,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x55,0x55,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x95,0x56,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5d,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5d,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5d,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5d,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5d,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x95,0x56 }; + diff --git a/build-assets.sh b/build-assets.sh new file mode 100755 index 0000000..9aad5ff --- /dev/null +++ b/build-assets.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +w4 png2src --template assets/assets-template --zig assets/tiles.png -o assets/tiles.zig +w4 png2src --template assets/assets-template --zig assets/sprites.png -o assets/sprites.zig diff --git a/build.zig b/build.zig index d415388..228e09c 100644 --- a/build.zig +++ b/build.zig @@ -45,9 +45,15 @@ test "stack version check" { } pub fn build(b: *std.build.Builder) !void { + const assets = std.build.Pkg{ + .name = "assets", + .path = .{ .path = "assets/assets.zig" }, + }; + const zig_version = @import("builtin").zig_version; const mode = b.standardReleaseOptions(); const lib = b.addSharedLibrary("cart", "src/main.zig", .unversioned); + lib.addPackage(assets); lib.setBuildMode(mode); lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }); lib.import_memory = true; diff --git a/src/ecs.zig b/src/ecs.zig new file mode 100644 index 0000000..099e3b3 --- /dev/null +++ b/src/ecs.zig @@ -0,0 +1,169 @@ +const std = @import("std"); +const ArgsTuple = std.meta.Tuple; +const Tuple = std.meta.Tuple; + +pub fn World(comptime ComponentBase: type) type { + // Build a component type at comptime based off of ComponentBase. It makes all the fields + // nullable so they are easy to pull out of the store. + const Component = componentConstructor: { + var fields = std.meta.fields(ComponentBase); + var newFields: [fields.len]std.builtin.TypeInfo.StructField = undefined; + inline for (fields) |field, i| { + const T = field.field_type; + const default: ?T = null; + newFields[i] = std.builtin.TypeInfo.StructField{ + .name = field.name, + .field_type = ?T, + .default_value = default, + .is_comptime = false, + .alignment = if (@sizeOf(T) > 0) @alignOf(T) else 0, + }; + } + break :componentConstructor @Type(.{ .Struct = .{ + .layout = .Auto, + .fields = &newFields, + .decls = &[_]std.builtin.TypeInfo.Declaration{}, + .is_tuple = false, + } }); + }; + return struct { + components: ComponentPool, + alloc: std.mem.Allocator, + pub const Query = ComponentQuery; + + const ComponentPool = std.MultiArrayList(Component); + const ComponentEnum = std.meta.FieldEnum(Component); + const ComponentSet = std.EnumSet(ComponentEnum); + const ComponentQuery = struct { + required: ComponentSet = ComponentSet.init(.{}), + excluded: ComponentSet = ComponentSet.init(.{}), + + pub fn init() @This() { + return @This(){}; + } + + pub fn query(require_set: []const ComponentEnum, exclude_set: []const ComponentEnum) @This() { + var this = @This(){}; + for (require_set) |f| { + this.required.insert(f); + } + for (exclude_set) |f| { + this.excluded.insert(f); + } + return this; + } + + pub fn require(set: []const ComponentEnum) @This() { + var this = @This(){}; + for (set) |f| { + this.required.insert(f); + } + return this; + } + + pub fn exclude(set: []const ComponentEnum) @This() { + var this = @This(){}; + for (set) |f| { + this.excluded.insert(f); + } + return this; + } + }; + + const fields = std.meta.fields(Component); + + pub fn init(alloc: std.mem.Allocator) @This() { + return @This(){ + .components = ComponentPool{}, + .alloc = alloc, + }; + } + + pub fn create(this: *@This(), component: Component) usize { + const len = this.components.len; + this.components.append(this.alloc, component) catch unreachable; + return len; + } + + pub fn destroy(this: *@This(), entity: usize) void { + // TODO + _ = this; + _ = entity; + @compileError("unimplemented"); + } + + pub fn get(this: *@This(), entity: usize, component: ComponentEnum) *Component { + return this.components.items(component)[entity]; + } + + fn enum2type(comptime enumList: []const ComponentEnum) []type { + var t: [enumList.len]type = undefined; + inline for (enumList) |e, i| { + const field_type = @typeInfo(fields[@enumToInt(e)].field_type); + t[i] = *field_type.Optional.child; + } + return &t; + } + + pub fn process(this: *@This(), dt: f32, comptime comp: []const ComponentEnum, func: anytype) void { + const Args = Tuple([_]type{f32} ++ enum2type(comp)); + var i = this.iter(Query.require(comp)); + while (i.next()) |e| { + var args: Args = undefined; + args[0] = dt; + inline for (comp) |f, j| { + args[j + 1] = &(@field(e, @tagName(f)).?); + } + @call(.{}, func, args); + } + } + + pub fn iterAll(this: *@This()) Iterator { + return Iterator.init(this, ComponentQuery{}); + } + + pub fn iter(this: *@This(), query: ComponentQuery) Iterator { + return Iterator.init(this, query); + } + + const Self = @This(); + const Iterator = struct { + world: *Self, + lastComponent: ?Component, + index: usize, + query: ComponentQuery, + + pub fn init(w: *Self, q: ComponentQuery) @This() { + return @This(){ + .world = w, + .lastComponent = null, + .index = 0, + .query = q, + }; + } + + pub fn next(this: *@This()) ?*Component { + if (this.lastComponent) |e| this.world.components.set(this.index - 1, e); + if (this.index == this.world.components.len) return null; + var match = false; + while (!match) { + if (this.index == this.world.components.len) return null; + this.lastComponent = this.world.components.get(this.index); + match = true; + inline for (fields) |f| { + const fenum = std.meta.stringToEnum(ComponentEnum, f.name) orelse unreachable; + const required = this.query.required.contains(fenum); + const excluded = this.query.excluded.contains(fenum); + const has = @field(this.lastComponent.?, f.name) != null; + if ((required and !has) or (excluded and has)) { + match = false; + break; + } + } + this.index += 1; + } + return &this.lastComponent.?; + } + }; + }; +} diff --git a/src/main.zig b/src/main.zig index 15628b4..cf44573 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,25 +1,52 @@ +const std = @import("std"); const w4 = @import("wasm4.zig"); +const ecs = @import("ecs.zig"); +const assets = @import("assets"); -const smiley = [8]u8{ - 0b11000011, - 0b10000001, - 0b00100100, - 0b00100100, - 0b00000000, - 0b00100100, - 0b10011001, - 0b11000011, +const Vec2f = std.meta.Vector(2, f32); +const Pos = Vec2f; +const Control = enum { player }; +const Component = struct { + pos: Pos, + control: Control, }; +const World = ecs.World(Component); + +const KB = 1024; +var heap: [1 * KB]u8 = undefined; +var fba = std.heap.FixedBufferAllocator.init(&heap); +var world: World = World.init(fba.allocator()); + +export fn start() void { + _ = world.create(.{ .pos = .{ 76, 76 }, .control = .player }); +} export fn update() void { w4.DRAW_COLORS.* = 2; - w4.text("Hello from Zig!", 10, 10); + w4.text("Hello from Zig!", .{ 10, 10 }); - const gamepad = w4.GAMEPAD1.*; - if (gamepad & w4.BUTTON_1 != 0) { + if (w4.GAMEPAD1.button_1) { w4.DRAW_COLORS.* = 4; } - w4.blit(&smiley, 76, 76, 8, 8, w4.BLIT_1BPP); - w4.text("Press X to blink", 16, 90); + world.process(1, &.{ .pos, .control }, controlProcess); + world.process(1, &.{.pos}, drawProcess); + + w4.DRAW_COLORS.* = 2; + // w4.blit(&smiley, .{ 76, 76 }, .{ 8, 8 }, .{ .bpp = .b1 }); + w4.text("Press X to blink", .{ 16, 90 }); +} + +fn drawProcess(_: f32, pos: *Pos) void { + w4.DRAW_COLORS.* = 0x0030; + w4.externs.blitSub(&assets.sprites, @floatToInt(i32, pos.*[0]), @floatToInt(i32, pos.*[1]), 8, 8, 0, 0, 128, assets.sprites_flags); +} + +fn controlProcess(_: f32, pos: *Pos, control: *Control) void { + _ = control; + if (w4.GAMEPAD1.button_up) pos.*[1] -= 1; + if (w4.GAMEPAD1.button_down) pos.*[1] += 1; + if (w4.GAMEPAD1.button_left) pos.*[0] -= 1; + if (w4.GAMEPAD1.button_right) pos.*[0] += 1; + // w4.trace("here", .{}); } diff --git a/src/wasm4.zig b/src/wasm4.zig index 322dc92..2bc015b 100644 --- a/src/wasm4.zig +++ b/src/wasm4.zig @@ -1,13 +1,102 @@ -// -// WASM-4: https://wasm4.org/docs +//! Stolen from pfgithub's wasm4-zig repo +//! https://github.com/pfgithub/wasm4-zig -// ┌───────────────────────────────────────────────────────────────────────────┐ -// │ │ -// │ Platform Constants │ -// │ │ -// └───────────────────────────────────────────────────────────────────────────┘ +const w4 = @This(); +const std = @import("std"); -pub const CANVAS_SIZE: u32 = 160; +/// PLATFORM CONSTANTS +pub const CANVAS_SIZE = 160; + +/// Helpers +pub const Vec2 = @import("std").meta.Vector(2, i32); +pub const x = 0; +pub const y = 1; + +pub fn texLen(size: Vec2) usize { + return @intCast(usize, std.math.divCeil(i32, size[x] * size[y] * 2, 8) catch unreachable); +} + +pub const Mbl = enum { mut, cons }; +pub fn Tex(comptime mbl: Mbl) type { + return struct { + // oh that's really annoying… + // ideally there would be a way to have a readonly Tex and a mutable Tex + // and the mutable should implicit cast to readonly + data: switch (mbl) { + .mut => [*]u8, + .cons => [*]const u8, + }, + size: Vec2, + + pub fn wrapSlice(slice: switch (mbl) { + .mut => []u8, + .cons => []const u8, + }, size: Vec2) Tex(mbl) { + if (slice.len != texLen(size)) { + unreachable; + } + return .{ + .data = slice.ptr, + .size = size, + }; + } + + pub fn cons(tex: Tex(.mut)) Tex(.cons) { + return .{ + .data = tex.data, + .size = tex.size, + }; + } + + pub fn blit(dest: Tex(.mut), dest_ul: Vec2, src: Tex(.cons), src_ul: Vec2, src_wh: Vec2, remap_colors: [4]u3, scale: Vec2) void { + for (range(@intCast(usize, src_wh[y]))) |_, y_usz| { + const yp = @intCast(i32, y_usz); + for (range(@intCast(usize, src_wh[x]))) |_, x_usz| { + const xp = @intCast(i32, x_usz); + const pos = Vec2{ xp, yp }; + + const value = remap_colors[src.get(src_ul + pos)]; + if (value <= std.math.maxInt(u2)) { + dest.rect(pos * scale + dest_ul, scale, @intCast(u2, value)); + } + } + } + } + pub fn rect(dest: Tex(.mut), ul: Vec2, wh: Vec2, color: u2) void { + for (range(std.math.lossyCast(usize, wh[y]))) |_, y_usz| { + const yp = @intCast(i32, y_usz); + for (range(std.math.lossyCast(usize, wh[x]))) |_, x_usz| { + const xp = @intCast(i32, x_usz); + + dest.set(ul + Vec2{ xp, yp }, color); + } + } + } + pub fn get(tex: Tex(mbl), pos: Vec2) u2 { + if (@reduce(.Or, pos < w4.Vec2{ 0, 0 })) return 0; + if (@reduce(.Or, pos >= tex.size)) return 0; + const index_unscaled = pos[w4.x] + (pos[w4.y] * tex.size[w4.x]); + const index = @intCast(usize, @divFloor(index_unscaled, 4)); + const byte_idx = @intCast(u3, (@mod(index_unscaled, 4)) * 2); + return @truncate(u2, tex.data[index] >> byte_idx); + } + pub fn set(tex: Tex(.mut), pos: Vec2, value: u2) void { + if (@reduce(.Or, pos < w4.Vec2{ 0, 0 })) return; + if (@reduce(.Or, pos >= tex.size)) return; + const index_unscaled = pos[w4.x] + (pos[w4.y] * tex.size[w4.x]); + const index = @intCast(usize, @divFloor(index_unscaled, 4)); + const byte_idx = @intCast(u3, (@mod(index_unscaled, 4)) * 2); + tex.data[index] &= ~(@as(u8, 0b11) << byte_idx); + tex.data[index] |= @as(u8, value) << byte_idx; + } + }; +} + +pub fn range(len: usize) []const void { + return @as([*]const void, &[_]void{})[0..len]; +} + +// pub const Tex1BPP = struct {…}; // ┌───────────────────────────────────────────────────────────────────────────┐ // │ │ @@ -17,26 +106,71 @@ pub const CANVAS_SIZE: u32 = 160; pub const PALETTE: *[4]u32 = @intToPtr(*[4]u32, 0x04); pub const DRAW_COLORS: *u16 = @intToPtr(*u16, 0x14); -pub const GAMEPAD1: *const u8 = @intToPtr(*const u8, 0x16); -pub const GAMEPAD2: *const u8 = @intToPtr(*const u8, 0x17); -pub const GAMEPAD3: *const u8 = @intToPtr(*const u8, 0x18); -pub const GAMEPAD4: *const u8 = @intToPtr(*const u8, 0x19); -pub const MOUSE_X: *const i16 = @intToPtr(*const i16, 0x1a); -pub const MOUSE_Y: *const i16 = @intToPtr(*const i16, 0x1c); -pub const MOUSE_BUTTONS: *const u8 = @intToPtr(*const u8, 0x1e); -pub const SYSTEM_FLAGS: *u8 = @intToPtr(*u8, 0x1f); -pub const FRAMEBUFFER: *[6400]u8 = @intToPtr(*[6400]u8, 0xA0); +pub const GAMEPAD1: *const Gamepad = @intToPtr(*const Gamepad, 0x16); +pub const GAMEPAD2: *const Gamepad = @intToPtr(*const Gamepad, 0x17); +pub const GAMEPAD3: *const Gamepad = @intToPtr(*const Gamepad, 0x18); +pub const GAMEPAD4: *const Gamepad = @intToPtr(*const Gamepad, 0x19); -pub const BUTTON_1: u8 = 1; -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; +pub const MOUSE: *const Mouse = @intToPtr(*const Mouse, 0x1a); +pub const SYSTEM_FLAGS: *SystemFlags = @intToPtr(*SystemFlags, 0x1f); +pub const FRAMEBUFFER: *[CANVAS_SIZE * CANVAS_SIZE / 4]u8 = @intToPtr(*[6400]u8, 0xA0); +pub const ctx = Tex(.mut){ + .data = @intToPtr([*]u8, 0xA0), // apparently casting *[N]u8 to [*]u8 at comptime causes a compiler crash + .size = .{ CANVAS_SIZE, CANVAS_SIZE }, +}; -pub const MOUSE_LEFT: u8 = 1; -pub const MOUSE_RIGHT: u8 = 2; -pub const MOUSE_MIDDLE: u8 = 4; +pub const Gamepad = packed struct { + button_1: bool, + button_2: bool, + _: u2 = 0, + button_left: bool, + button_right: bool, + button_up: bool, + button_down: bool, + comptime { + if (@sizeOf(@This()) != @sizeOf(u8)) unreachable; + } + + pub fn format(value: @This(), comptime _: []const u8, _: @import("std").fmt.FormatOptions, writer: anytype) !void { + if (value.button_1) try writer.writeAll("1"); + if (value.button_2) try writer.writeAll("2"); + if (value.button_left) try writer.writeAll("<"); //"←"); + if (value.button_right) try writer.writeAll(">"); + if (value.button_up) try writer.writeAll("^"); + if (value.button_down) try writer.writeAll("v"); + } +}; + +pub const Mouse = packed struct { + x: i16, + y: i16, + buttons: MouseButtons, + pub fn pos(mouse: Mouse) Vec2 { + return .{ mouse.x, mouse.y }; + } + comptime { + if (@sizeOf(@This()) != 5) unreachable; + } +}; + +pub const MouseButtons = packed struct { + left: bool, + right: bool, + middle: bool, + _: u5 = 0, + comptime { + if (@sizeOf(@This()) != @sizeOf(u8)) unreachable; + } +}; + +pub const SystemFlags = packed struct { + preserve_framebuffer: bool, + hide_gamepad_overlay: bool, + _: u6 = 0, + comptime { + if (@sizeOf(@This()) != @sizeOf(u8)) unreachable; + } +}; pub const SYSTEM_PRESERVE_FRAMEBUFFER: u8 = 1; pub const SYSTEM_HIDE_GAMEPAD_OVERLAY: u8 = 2; @@ -47,38 +181,68 @@ pub const SYSTEM_HIDE_GAMEPAD_OVERLAY: u8 = 2; // │ │ // └───────────────────────────────────────────────────────────────────────────┘ +pub const externs = struct { + pub extern fn blit(sprite: [*]const u8, x: i32, y: i32, width: i32, height: i32, flags: u32) void; + pub extern fn blitSub(sprite: [*]const u8, x: i32, y: i32, width: i32, height: i32, src_x: u32, src_y: u32, strie: i32, flags: u32) void; + pub extern fn line(x1: i32, y1: i32, x2: i32, y2: i32) void; + pub extern fn oval(x: i32, y: i32, width: i32, height: i32) void; + pub extern fn rect(x: i32, y: i32, width: i32, height: i32) void; + pub extern fn textUtf8(strPtr: [*]const u8, strLen: usize, x: i32, y: i32) void; + + /// Draws a vertical line + extern fn vline(x: i32, y: i32, len: u32) void; + + /// Draws a horizontal line + extern fn hline(x: i32, y: i32, len: u32) void; + + pub extern fn tone(frequency: u32, duration: u32, volume: u32, flags: u32) void; +}; + /// Copies pixels to the framebuffer. -pub extern fn blit(sprite: [*]const u8, x: i32, y: i32, width: i32, height: i32, flags: u32) void; +pub fn blit(sprite: []const u8, pos: Vec2, size: Vec2, flags: BlitFlags) void { + if (sprite.len * 8 != size[x] * size[y]) unreachable; + externs.blit(sprite.ptr, pos[x], pos[y], size[x], size[y], @bitCast(u32, flags)); +} /// Copies a subregion within a larger sprite atlas to the framebuffer. -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; +pub fn blitSub(sprite: []const u8, pos: Vec2, size: Vec2, src: Vec2, strie: i32, flags: BlitFlags) void { + if (sprite.len * 8 >= size[x] * size[y]) trace("Sprite not large enough {}", .{sprite.len}); + externs.blitSub(sprite.ptr, pos[x], pos[y], size[x], size[y], @intCast(u32, src[x]), @intCast(u32, src[y]), strie, @bitCast(u32, flags)); +} -pub const BLIT_2BPP: u32 = 1; -pub const BLIT_1BPP: u32 = 0; -pub const BLIT_FLIP_X: u32 = 2; -pub const BLIT_FLIP_Y: u32 = 4; -pub const BLIT_ROTATE: u32 = 8; +pub const BlitFlags = packed struct { + bpp: enum(u1) { + b1, + b2, + }, + flip_x: bool = false, + flip_y: bool = false, + rotate: bool = false, + _: u28 = 0, + comptime { + if (@sizeOf(@This()) != @sizeOf(u32)) unreachable; + } +}; /// Draws a line between two points. -pub extern fn line(x1: i32, y1: i32, x2: i32, y2: i32) void; +pub fn line(pos1: Vec2, pos2: Vec2) void { + externs.line(pos1[x], pos1[y], pos2[x], pos2[y]); +} /// Draws an oval (or circle). -pub extern fn oval(x: i32, y: i32, width: i32, height: i32) void; +pub fn oval(ul: Vec2, size: Vec2) void { + externs.oval(ul[x], ul[y], size[x], size[y]); +} /// Draws a rectangle. -pub extern fn rect(x: i32, y: i32, width: u32, height: u32) void; +pub fn rect(ul: Vec2, size: Vec2) void { + externs.rect(ul[x], ul[y], size[x], size[y]); +} /// Draws text using the built-in system font. -pub fn text(str: []const u8, x: i32, y: i32) void { - textUtf8(str.ptr, str.len, x, y); +pub fn text(str: []const u8, pos: Vec2) void { + externs.textUtf8(str.ptr, str.len, pos[x], pos[y]); } -extern fn textUtf8(strPtr: [*]const u8, strLen: usize, x: i32, y: i32) void; - -/// Draws a vertical line -pub extern fn vline(x: i32, y: i32, len: u32) void; - -/// Draws a horizontal line -pub extern fn hline(x: i32, y: i32, len: u32) void; // ┌───────────────────────────────────────────────────────────────────────────┐ // │ │ @@ -87,16 +251,51 @@ pub extern fn hline(x: i32, y: i32, len: u32) void; // └───────────────────────────────────────────────────────────────────────────┘ /// Plays a sound tone. -pub extern fn tone(frequency: u32, duration: u32, volume: u32, flags: u32) void; +pub fn tone(frequency: ToneFrequency, duration: ToneDuration, volume: u32, flags: ToneFlags) void { + return externs.tone(@bitCast(u32, frequency), @bitCast(u32, duration), volume, @bitCast(u8, flags)); +} +pub const ToneFrequency = packed struct { + start: u16, + end: u16 = 0, -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; + comptime { + if (@sizeOf(@This()) != @sizeOf(u32)) unreachable; + } +}; + +pub const ToneDuration = packed struct { + sustain: u8 = 0, + release: u8 = 0, + decay: u8 = 0, + attack: u8 = 0, + + comptime { + if (@sizeOf(@This()) != @sizeOf(u32)) unreachable; + } +}; + +pub const ToneFlags = packed struct { + pub const Channel = enum(u2) { + pulse1, + pulse2, + triangle, + noise, + }; + pub const Mode = enum(u2) { + p12_5, + p25, + p50, + p75, + }; + + channel: Channel, + mode: Mode = .p12_5, + _: u4 = 0, + + comptime { + if (@sizeOf(@This()) != @sizeOf(u8)) unreachable; + } +}; // ┌───────────────────────────────────────────────────────────────────────────┐ // │ │ @@ -117,10 +316,25 @@ pub extern fn diskw(src: [*]const u8, size: u32) u32; // └───────────────────────────────────────────────────────────────────────────┘ /// Prints a message to the debug console. -pub fn trace(x: []const u8) void { - traceUtf8(x.ptr, x.len); +/// Disabled in release builds. +pub fn trace(comptime fmt: []const u8, args: anytype) void { + if (@import("builtin").mode != .Debug) @compileError("trace not allowed in release builds."); + + // stack size is [8192]u8 + var buffer: [100]u8 = undefined; + var fbs = std.io.fixedBufferStream(&buffer); + const writer = fbs.writer(); + writer.print(fmt, args) catch { + const err_msg = switch (@import("builtin").mode) { + .Debug => "[trace err] " ++ fmt, + else => "[trace err]", // max 100 bytes in trace message. + }; + return traceUtf8(err_msg, err_msg.len); + }; + + traceUtf8(&buffer, fbs.pos); } -extern fn traceUtf8(strPtr: [*]const u8, strLen: usize) void; +extern fn traceUtf8(str_ptr: [*]const u8, str_len: usize) void; /// Use with caution, as there's no compile-time type checking. ///