]> git.seodisparate.com - LD53/commitdiff
Init skeleton project
authorStephen Seo <seo.disparate@gmail.com>
Sat, 29 Apr 2023 02:02:19 +0000 (11:02 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Sat, 29 Apr 2023 02:02:19 +0000 (11:02 +0900)
.cargo/config.toml [new file with mode: 0644]
.gitignore [new file with mode: 0644]
Cargo.lock [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
README.md [new file with mode: 0644]
src/alloc.rs [new file with mode: 0644]
src/lib.rs [new file with mode: 0644]
src/wasm4.rs [new file with mode: 0644]

diff --git a/.cargo/config.toml b/.cargo/config.toml
new file mode 100644 (file)
index 0000000..2c694b5
--- /dev/null
@@ -0,0 +1,15 @@
+[build]
+target = "wasm32-unknown-unknown"
+
+[target.wasm32-unknown-unknown]
+rustflags = [
+    # Import memory from WASM-4
+    "-C", "link-arg=--import-memory",
+    "-C", "link-arg=--initial-memory=65536",
+    "-C", "link-arg=--max-memory=65536",
+
+    # Temporary workaround for #255 issue.
+    # Reserve 8192 bytes of Rust stack space, offset from 6560.
+    # Bump this value, 16-byte aligned, if the framebuffer gets corrupted.
+    "-C", "link-arg=-zstack-size=14752",
+]
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..ea8c4bf
--- /dev/null
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644 (file)
index 0000000..d7837fe
--- /dev/null
@@ -0,0 +1,16 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "buddy-alloc"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3240a4cb09cf0da6a51641bd40ce90e96ea6065e3a1adc46434029254bcc2d09"
+
+[[package]]
+name = "cart"
+version = "0.1.0"
+dependencies = [
+ "buddy-alloc",
+]
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..9e57f16
--- /dev/null
@@ -0,0 +1,19 @@
+[package]
+name = "cart"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+buddy-alloc = { version = "0.4.1", optional = true }
+
+[profile.release]
+opt-level = "z"
+lto = true
+
+[features]
+# use `--no-default-features` or comment out next line to disable allocator
+default = ["buddy-alloc"]
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..f429c8e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,26 @@
+# ld53
+
+A game written in Rust for the [WASM-4](https://wasm4.org) fantasy console.
+
+## Building
+
+Build the cart by running:
+
+```shell
+cargo build --release
+```
+
+Then run it with:
+
+```shell
+w4 run target/wasm32-unknown-unknown/release/cart.wasm
+```
+
+For more info about setting up WASM-4, see the [quickstart guide](https://wasm4.org/docs/getting-started/setup?code-lang=rust#quickstart).
+
+## Links
+
+- [Documentation](https://wasm4.org/docs): Learn more about WASM-4.
+- [Snake Tutorial](https://wasm4.org/docs/tutorials/snake/goal): Learn how to build a complete game
+  with a step-by-step tutorial.
+- [GitHub](https://github.com/aduros/wasm4): Submit an issue or PR. Contributions are welcome!
diff --git a/src/alloc.rs b/src/alloc.rs
new file mode 100644 (file)
index 0000000..92d488e
--- /dev/null
@@ -0,0 +1,16 @@
+use buddy_alloc::{BuddyAllocParam, FastAllocParam, NonThreadsafeAlloc};
+
+// These values can be tuned
+const FAST_HEAP_SIZE: usize = 4 * 1024; // 4 KB
+const HEAP_SIZE: usize = 16 * 1024; // 16 KB
+const LEAF_SIZE: usize = 16;
+
+static mut FAST_HEAP: [u8; FAST_HEAP_SIZE] = [0u8; FAST_HEAP_SIZE];
+static mut HEAP: [u8; HEAP_SIZE] = [0u8; HEAP_SIZE];
+
+#[global_allocator]
+static ALLOC: NonThreadsafeAlloc = unsafe {
+    let fast_param = FastAllocParam::new(FAST_HEAP.as_ptr(), FAST_HEAP_SIZE);
+    let buddy_param = BuddyAllocParam::new(HEAP.as_ptr(), HEAP_SIZE, LEAF_SIZE);
+    NonThreadsafeAlloc::new(fast_param, buddy_param)
+};
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644 (file)
index 0000000..d1c7f30
--- /dev/null
@@ -0,0 +1,30 @@
+#[cfg(feature = "buddy-alloc")]
+mod alloc;
+mod wasm4;
+use wasm4::*;
+
+#[rustfmt::skip]
+const SMILEY: [u8; 8] = [
+    0b11000011,
+    0b10000001,
+    0b00100100,
+    0b00100100,
+    0b00000000,
+    0b00100100,
+    0b10011001,
+    0b11000011,
+];
+
+#[no_mangle]
+fn update() {
+    unsafe { *DRAW_COLORS = 2 }
+    text("Hello from Rust!", 10, 10);
+
+    let gamepad = unsafe { *GAMEPAD1 };
+    if gamepad & BUTTON_1 != 0 {
+        unsafe { *DRAW_COLORS = 4 }
+    }
+
+    blit(&SMILEY, 76, 76, 8, 8, BLIT_1BPP);
+    text("Press X to blink", 16, 90);
+}
diff --git a/src/wasm4.rs b/src/wasm4.rs
new file mode 100644 (file)
index 0000000..78503c9
--- /dev/null
@@ -0,0 +1,225 @@
+//
+// WASM-4: https://wasm4.org/docs
+
+#![allow(unused)]
+
+// ┌───────────────────────────────────────────────────────────────────────────┐
+// │                                                                           │
+// │ Platform Constants                                                        │
+// │                                                                           │
+// └───────────────────────────────────────────────────────────────────────────┘
+
+pub const SCREEN_SIZE: u32 = 160;
+
+// ┌───────────────────────────────────────────────────────────────────────────┐
+// │                                                                           │
+// │ Memory Addresses                                                          │
+// │                                                                           │
+// └───────────────────────────────────────────────────────────────────────────┘
+
+pub const PALETTE: *mut [u32; 4] = 0x04 as *mut [u32; 4];
+pub const DRAW_COLORS: *mut u16 = 0x14 as *mut u16;
+pub const GAMEPAD1: *const u8 = 0x16 as *const u8;
+pub const GAMEPAD2: *const u8 = 0x17 as *const u8;
+pub const GAMEPAD3: *const u8 = 0x18 as *const u8;
+pub const GAMEPAD4: *const u8 = 0x19 as *const u8;
+pub const MOUSE_X: *const i16 = 0x1a as *const i16;
+pub const MOUSE_Y: *const i16 = 0x1c as *const i16;
+pub const MOUSE_BUTTONS: *const u8 = 0x1e as *const u8;
+pub const SYSTEM_FLAGS: *mut u8 = 0x1f as *mut u8;
+pub const NETPLAY: *const u8 = 0x20 as *const u8;
+pub const FRAMEBUFFER: *mut [u8; 6400] = 0xa0 as *mut [u8; 6400];
+
+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_LEFT: u8 = 1;
+pub const MOUSE_RIGHT: u8 = 2;
+pub const MOUSE_MIDDLE: u8 = 4;
+
+pub const SYSTEM_PRESERVE_FRAMEBUFFER: u8 = 1;
+pub const SYSTEM_HIDE_GAMEPAD_OVERLAY: u8 = 2;
+
+// ┌───────────────────────────────────────────────────────────────────────────┐
+// │                                                                           │
+// │ Drawing Functions                                                         │
+// │                                                                           │
+// └───────────────────────────────────────────────────────────────────────────┘
+
+/// Copies pixels to the framebuffer.
+pub fn blit(sprite: &[u8], x: i32, y: i32, width: u32, height: u32, flags: u32) {
+    unsafe { extern_blit(sprite.as_ptr(), x, y, width, height, flags) }
+}
+extern "C" {
+    #[link_name = "blit"]
+    fn extern_blit(sprite: *const u8, x: i32, y: i32, width: u32, height: u32, flags: u32);
+}
+
+/// Copies a subregion within a larger sprite atlas to the framebuffer.
+#[allow(clippy::too_many_arguments)]
+pub fn blit_sub(
+    sprite: &[u8],
+    x: i32,
+    y: i32,
+    width: u32,
+    height: u32,
+    src_x: u32,
+    src_y: u32,
+    stride: u32,
+    flags: u32,
+) {
+    unsafe {
+        extern_blit_sub(
+            sprite.as_ptr(),
+            x,
+            y,
+            width,
+            height,
+            src_x,
+            src_y,
+            stride,
+            flags,
+        )
+    }
+}
+extern "C" {
+    #[link_name = "blitSub"]
+    fn extern_blit_sub(
+        sprite: *const u8,
+        x: i32,
+        y: i32,
+        width: u32,
+        height: u32,
+        src_x: u32,
+        src_y: u32,
+        stride: u32,
+        flags: u32,
+    );
+}
+
+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;
+
+/// Draws a line between two points.
+pub fn line(x1: i32, y1: i32, x2: i32, y2: i32) {
+    unsafe { extern_line(x1, y1, x2, y2) }
+}
+extern "C" {
+    #[link_name = "line"]
+    fn extern_line(x1: i32, y1: i32, x2: i32, y2: i32);
+}
+
+/// Draws an oval (or circle).
+pub fn oval(x: i32, y: i32, width: u32, height: u32) {
+    unsafe { extern_oval(x, y, width, height) }
+}
+extern "C" {
+    #[link_name = "oval"]
+    fn extern_oval(x: i32, y: i32, width: u32, height: u32);
+}
+
+/// Draws a rectangle.
+pub fn rect(x: i32, y: i32, width: u32, height: u32) {
+    unsafe { extern_rect(x, y, width, height) }
+}
+extern "C" {
+    #[link_name = "rect"]
+    fn extern_rect(x: i32, y: i32, width: u32, height: u32);
+}
+
+/// Draws text using the built-in system font.
+pub fn text<T: AsRef<[u8]>>(text: T, x: i32, y: i32) {
+    let text_ref = text.as_ref();
+    unsafe { extern_text(text_ref.as_ptr(), text_ref.len(), x, y) }
+}
+extern "C" {
+    #[link_name = "textUtf8"]
+    fn extern_text(text: *const u8, length: usize, x: i32, y: i32);
+}
+
+/// Draws a vertical line
+pub fn vline(x: i32, y: i32, len: u32) {
+    unsafe {
+        extern_vline(x, y, len);
+    }
+}
+
+extern "C" {
+    #[link_name = "vline"]
+    fn extern_vline(x: i32, y: i32, len: u32);
+}
+
+/// Draws a horizontal line
+pub fn hline(x: i32, y: i32, len: u32) {
+    unsafe {
+        extern_hline(x, y, len);
+    }
+}
+
+extern "C" {
+    #[link_name = "hline"]
+    fn extern_hline(x: i32, y: i32, len: u32);
+}
+
+// ┌───────────────────────────────────────────────────────────────────────────┐
+// │                                                                           │
+// │ Sound Functions                                                           │
+// │                                                                           │
+// └───────────────────────────────────────────────────────────────────────────┘
+
+/// Plays a sound tone.
+pub fn tone(frequency: u32, duration: u32, volume: u32, flags: u32) {
+    unsafe { extern_tone(frequency, duration, volume, flags) }
+}
+extern "C" {
+    #[link_name = "tone"]
+    fn extern_tone(frequency: u32, duration: u32, volume: u32, flags: u32);
+}
+
+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                                                         │
+// │                                                                           │
+// └───────────────────────────────────────────────────────────────────────────┘
+
+extern "C" {
+    /// Reads up to `size` bytes from persistent storage into the pointer `dest`.
+    pub fn diskr(dest: *mut u8, size: u32) -> u32;
+
+    /// Writes up to `size` bytes from the pointer `src` into persistent storage.
+    pub fn diskw(src: *const u8, size: u32) -> u32;
+}
+
+// ┌───────────────────────────────────────────────────────────────────────────┐
+// │                                                                           │
+// │ Other Functions                                                           │
+// │                                                                           │
+// └───────────────────────────────────────────────────────────────────────────┘
+
+/// Prints a message to the debug console.
+pub fn trace<T: AsRef<str>>(text: T) {
+    let text_ref = text.as_ref();
+    unsafe { extern_trace(text_ref.as_ptr(), text_ref.len()) }
+}
+extern "C" {
+    #[link_name = "traceUtf8"]
+    fn extern_trace(trace: *const u8, length: usize);
+}