4 Commits

Author SHA1 Message Date
luchak
bb3a6e36e4 Merge 1d89ef8613 into 8258bc1854 2023-09-13 11:33:50 -07:00
luchak
1d89ef8613 Support v128.const 2023-02-22 21:21:34 -08:00
luchak
c7be8be2c4 Remove dependency on curlywas SIMD fork 2023-02-13 18:54:02 -08:00
luchak
d9f9500b76 Add SIMD opcode support to uw8-tool 2023-02-13 18:48:19 -08:00
50 changed files with 2957 additions and 5377 deletions

View File

@@ -44,7 +44,7 @@ jobs:
- name: Build - name: Build
run: cargo build --release --verbose run: cargo build --release --verbose
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: uw8-${{ matrix.build }} name: uw8-${{ matrix.build }}
path: target/release/${{ matrix.exe }} path: target/release/${{ matrix.exe }}

2279
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "uw8" name = "uw8"
version = "0.4.1" version = "0.2.2"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -11,9 +11,9 @@ native = ["wasmtime", "uw8-window", "cpal", "rubato" ]
browser = ["warp", "tokio", "tokio-stream", "webbrowser"] browser = ["warp", "tokio", "tokio-stream", "webbrowser"]
[dependencies] [dependencies]
wasmtime = { git = "https://github.com/bytecodealliance/wasmtime.git", rev = "0f48f939b9870036562ca02ff21253547a9f1a5c", optional = true } wasmtime = { version = "12.0.0", optional = true }
anyhow = "1" anyhow = "1"
env_logger = "0.11.3" env_logger = "0.10"
log = "0.4" log = "0.4"
uw8-window = { path = "uw8-window", optional = true } uw8-window = { path = "uw8-window", optional = true }
notify-debouncer-mini = { version = "0.4.1", default-features = false } notify-debouncer-mini = { version = "0.4.1", default-features = false }
@@ -22,10 +22,10 @@ curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "0e7ea50"
wat = "1" wat = "1"
uw8-tool = { path = "uw8-tool" } uw8-tool = { path = "uw8-tool" }
same-file = "1" same-file = "1"
warp = { version = "0.3.6", optional = true } warp = { version = "0.3.5", optional = true }
tokio = { version = "1.37.0", features = ["sync", "rt"], optional = true } tokio = { version = "1.32.0", features = ["sync", "rt"], optional = true }
tokio-stream = { version = "0.1.15", features = ["sync"], optional = true } tokio-stream = { version = "0.1.14", features = ["sync"], optional = true }
webbrowser = { version = "0.8.13", optional = true } webbrowser = { version = "0.8.11", optional = true }
ansi_term = "0.12.1" ansi_term = "0.12.1"
cpal = { version = "0.15.3", optional = true } cpal = { version = "0.15.2", optional = true }
rubato = { version = "0.12.0", optional = true } rubato = { version = "0.14.0", optional = true }

View File

@@ -15,9 +15,9 @@ See [here](https://exoticorn.github.io/microw8/) for more information and docs.
## Downloads ## Downloads
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.4.1/microw8-0.4.1-linux.tgz) * [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.4.1/microw8-0.4.1-macos.tgz) * [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.4.1/microw8-0.4.1-windows.zip) * [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-windows.zip)
The download includes The download includes

View File

@@ -1,254 +0,0 @@
/*
This program renders a rotating 3D wireframe cube on a 2D screen using the MicroW8 platform.
code : zbyti
date : 2025.04.15
platform : MicroW8 0.4.1
https://exoticorn.github.io/microw8/
https://exoticorn.github.io/microw8/docs/
https://github.com/exoticorn/microw8
https://github.com/exoticorn/curlywas
https://developer.mozilla.org/en-US/docs/WebAssembly
https://en.wikipedia.org/wiki/Rotation_matrix
*/
//-----------------------------------------------------------------------------
// MicroW8 API
//-----------------------------------------------------------------------------
//include "../include/microw8-api.cwa"
// Import memory allocation: 4 pages (64KB) of memory (256KB total)
import "env.memory" memory(4);
// Import MicroW8 API functions for graphics and math operations
import "env.cls" fn cls(i32); // Clears the screen
import "env.time" fn time() -> f32; // Returns the current time as a float for animation
import "env.sin" fn sin(f32) -> f32; // Computes the sine of an angle (in radians)
import "env.cos" fn cos(f32) -> f32; // Computes the cosine of an angle (in radians)
import "env.line" fn line(f32, f32, f32, f32, i32); // Draws a line between two 2D points with a color
// Define the starting address for user memory
const USER_MEM = 0x14000;
//-----------------------------------------------------------------------------
// CONSTANTS
//-----------------------------------------------------------------------------
// Screen and rendering constants
const CENTER_X = 320.0 / 2.0; // X-coordinate of the screen center (320px width)
const CENTER_Y = 240.0 / 2.0; // Y-coordinate of the screen center (240px height)
const ROTATE_SPEED = 0.5; // Speed at which the cube rotates
const PI = 3.14159265; // Mathematical constant Pi for angle conversions
const RADIAN = PI / 180.0; // Conversion factor from degrees to radians
const SCALE = 65.0; // Scaling factor to adjust the size of the cube on screen
const PERSPECTIVE = SCALE * 0.5; // Perspective factor
const LINE_COLOR = 0xBF; // Color value for drawing the cube's edges (hexadecimal)
// Memory layout for vertex data
const V_BASE = USER_MEM; // Base vertices stored as 8-bit integers (i8)
const V_ROT = V_BASE + (3 * 8); // Rotated vertices stored as 32-bit floats (f32), offset after V_BASE
// Offsets for accessing X, Y, Z coordinates in memory (in bytes)
const X = 0; // Offset for X coordinate
const Y = 4; // Offset for Y coordinate
const Z = 8; // Offset for Z coordinate
// Memory offsets for each rotated vertex (8 vertices, 3 floats each, 12 bytes per vertex)
const VA = V_ROT + (0 * 3 * 4); // Vertex A (front-top-left)
const VB = V_ROT + (1 * 3 * 4); // Vertex B (front-top-right)
const VC = V_ROT + (2 * 3 * 4); // Vertex C (front-bottom-right)
const VD = V_ROT + (3 * 3 * 4); // Vertex D (front-bottom-left)
const VE = V_ROT + (4 * 3 * 4); // Vertex E (back-top-left)
const VF = V_ROT + (5 * 3 * 4); // Vertex F (back-top-right)
const VG = V_ROT + (6 * 3 * 4); // Vertex G (back-bottom-right)
const VH = V_ROT + (7 * 3 * 4); // Vertex H (back-bottom-left)
//-----------------------------------------------------------------------------
// Function to rotate the cube around X, Y, and Z axes based on time
//-----------------------------------------------------------------------------
fn rotate() {
// Calculate the rotation angle using the current time for continuous animation
let angle = time() * ROTATE_SPEED;
// Precompute sine and cosine values once for efficiency
let sn = sin(angle);
let cs = cos(angle);
let calc = 0;
loop calc { // Iterate over all 8 vertices
// Calculate memory offset for current vertex (12 bytes per vertex: 4 bytes each for X, Y, Z)
let v = calc * 12;
let inline vX = v + X;
let inline vY = v + Y;
let inline vZ = v + Z;
// Load original vertex coordinates from V_BASE (stored as i8, converted to f32)
let x = i32.load8_s(V_BASE+(calc * 3 + 0)) as f32; // X coordinate
let y = i32.load8_s(V_BASE+(calc * 3 + 1)) as f32; // Y coordinate
let z = i32.load8_s(V_BASE+(calc * 3 + 2)) as f32; // Z coordinate
// Rotate around Z-axis: updates X and Y, Z stays the same
(vX)$V_ROT = x * cs - y * sn;
(vY)$V_ROT = x * sn + y * cs;
(vZ)$V_ROT = z;
// Rotate around Y-axis: updates X and Z, Y stays the same
x = (vX)$V_ROT;
z = (vZ)$V_ROT;
(vX)$V_ROT = x * cs + z * sn;
(vZ)$V_ROT = z * cs - x * sn;
// Rotate around X-axis: updates Y and Z, X stays the same
y = (vY)$V_ROT;
z = (vZ)$V_ROT;
(vY)$V_ROT = y * cs - z * sn;
(vZ)$V_ROT = y * sn + z * cs;
// Move to the next vertex until all 8 are processed
branch_if (calc +:= 1) < 8: calc;
}
}
//-----------------------------------------------------------------------------
// Function to project 3D vertices to 2D screen space and draw the cube's edges
//-----------------------------------------------------------------------------
fn drawLines() {
let scale = 0;
loop scale { // Scale and center each vertex for 2D projection
// Calculate memory offset for current vertex (12 bytes per vertex: 4 bytes each for X, Y, Z)
let v = scale * 12;
let inline vX = v + X;
let inline vY = v + Y;
// Load Z coordinate of current vertex (from rotated vertex data)
let inline z = (v + Z)$V_ROT;
// Calculate perspective factor:
// - When z=0 (midpoint), factor=1.0 (no scaling)
// - Positive z (farther away) → factor<1.0 (objects appear smaller)
// - Negative z (closer) → factor>1.0 (objects appear larger)
let lazy factor = PERSPECTIVE / (PERSPECTIVE + z) * SCALE;
// Apply perspective projection, scaling and shift to center for X and Y coordinats:
// 1. Multiply by perspective factor
// 2. Apply global scaling (SCALE constant)
// 3. Center on screen (CENTER_X, CENTER_Y)
(vX)$V_ROT = (vX)$V_ROT * factor + CENTER_X; // X
(vY)$V_ROT = (vY)$V_ROT * factor + CENTER_Y; // Y
// Continue until all 8 vertices are scaled
branch_if (scale +:= 1) < 8: scale;
}
// Draw the front face of the cube (vertices A-B-C-D)
line(VA$X, VA$Y, VB$X, VB$Y, LINE_COLOR);
line(VB$X, VB$Y, VC$X, VC$Y, LINE_COLOR);
line(VC$X, VC$Y, VD$X, VD$Y, LINE_COLOR);
line(VD$X, VD$Y, VA$X, VA$Y, LINE_COLOR);
// Draw the back face of the cube (vertices E-F-G-H)
line(VE$X, VE$Y, VF$X, VF$Y, LINE_COLOR);
line(VF$X, VF$Y, VG$X, VG$Y, LINE_COLOR);
line(VG$X, VG$Y, VH$X, VH$Y, LINE_COLOR);
line(VH$X, VH$Y, VE$X, VE$Y, LINE_COLOR);
// Draw edges connecting front and back faces
line(VA$X, VA$Y, VE$X, VE$Y, LINE_COLOR);
line(VB$X, VB$Y, VF$X, VF$Y, LINE_COLOR);
line(VC$X, VC$Y, VG$X, VG$Y, LINE_COLOR);
line(VD$X, VD$Y, VH$X, VH$Y, LINE_COLOR);
}
//-----------------------------------------------------------------------------
// Entry point for INIT type function, starts first
//-----------------------------------------------------------------------------
/*
export fn start() {
let init = 0;
loop init {
// Calculate memory offset for current vertex (12 bytes per vertex: 4 bytes each for X, Y, Z)
let v = init * 12;
(v + X)$V_ROT = i32.load8_s(V_BASE+(init * 3) + 0) as f32;
(v + Y)$V_ROT = i32.load8_s(V_BASE+(init * 3) + 1) as f32;
(v + Z)$V_ROT = i32.load8_s(V_BASE+(init * 3) + 2) as f32;
branch_if (init +:= 1) < 8: init;
}
}
*/
//-----------------------------------------------------------------------------
// Main update function called every frame to refresh the screen
//-----------------------------------------------------------------------------
export fn upd() {
cls(0); // Clear the screen with color 0 (black)
rotate(); // Perform cube rotation calculations
drawLines(); // Draw the rotated cube on the screen
}
//-----------------------------------------------------------------------------
// DATA
//-----------------------------------------------------------------------------
/*
Initial vertex data for the cube (8 vertices, each with X, Y, Z as 8-bit signed integers)
Each vertex represents a corner of a unit cube centered at the origin
F - front, B - back, L - left, R - right, U - up, D - down
*/
data V_BASE { // 3 * 8 -> 3 bytes per vertex * 8 vertices = 24 bytes
i8(
// X Y Z
-1, -1, 1, // FLU Vertex A
1, -1, 1, // FRU Vertex B
1, 1, 1, // FRD Vertex C
-1, 1, 1, // FLD Vertex D
-1, -1, -1, // BLU Vertex E
1, -1, -1, // BRU Vertex F
1, 1, -1, // BRD Vertex G
-1, 1, -1 // BLD Vertex H
)
}
//-----------------------------------------------------------------------------
/*
Storage for rotated vertex data (8 vertices, each with X, Y, Z as 32-bit signed floats)
Initialized to zero and updated during rotation
*/
data V_ROT { // 4 * 3 * 8 -> 12 bytes per vertex * 8 vertices = 96 bytes
f32(
// X Y Z
0.0, 0.0, 0.0, // VA -> Vertex A
0.0, 0.0, 0.0, // VB -> Vertex B
0.0, 0.0, 0.0, // VC -> Vertex C
0.0, 0.0, 0.0, // VD -> Vertex D
0.0, 0.0, 0.0, // VE -> Vertex E
0.0, 0.0, 0.0, // VF -> Vertex F
0.0, 0.0, 0.0, // VG -> Vertex G
0.0, 0.0, 0.0 // VH -> Vertex H
)
}
//-----------------------------------------------------------------------------
// SNIPPETS
//-----------------------------------------------------------------------------
/*
let tmp: f32;
tmp = -123.0;
f32.store(tmp, V_ROT);
tmp = f32.load(V_ROT);
printInt(tmp as i32);
*/
//-----------------------------------------------------------------------------

View File

@@ -1,51 +0,0 @@
/*
Plasma effect (sizecoding)
Combines sine waves to create a 2D pixel pattern with intensity-based colors.
code : zbyti & Grok 3
date : 2025.04.17
platform : MicroW8 0.4.1
*/
include "../include/microw8-api.cwa"
// Constants for color, math, and screen dimensions
const BASE_COLOR = 0xF0; // Base color value for pixel coloring
const PI = 3.14159265; // Mathematical constant π
const RAD = PI / 180.0; // Conversion factor from degrees to radians
const SCR_X = 320; // Screen width in pixels
const SCR_Y = 240; // Screen height in pixels
const SCR_SIZE = SCR_X * SCR_Y; // Screen size in bytes
// Global variables to track animation phases
global mut phaseX = 0; // Phase offset for X-axis wave animation
global mut phaseY = 0; // Phase offset for Y-axis wave animation
// Update function called each frame to render the plasma effect
export fn upd() {
let i = 0;
loop i {
// Calculate pixel coordinates from linear index
let lazy x = i % SCR_X; // X-coordinate (column)
let lazy y = i / SCR_X; // Y-coordinate (row)
// Compute three sine waves with different frequencies and phases
let inline val1 = sin(RAD * 2.25 * (x + phaseX) as f32); // Wave along X-axis
let inline val2 = sin(RAD * 3.25 * (y + phaseY) as f32); // Wave along Y-axis
let inline val3 = sin(RAD * 1.25 * (x + y + phaseX) as f32); // Diagonal wave
// Combine waves, scale to color range, and convert to integer
let inline c = BASE_COLOR + ((val1 + val2 + val3) * 4.75) as i32;
// Set pixel color based on computed intensity
setPixel(x, y, c);
// Continue loop until all pixels are processed
branch_if (i +:= 1) < (SCR_SIZE): i;
}
// Update phase offsets for animation (different speeds for dynamic effect)
phaseX += 1; // Increment X-phase for horizontal wave movement
phaseY += 2; // Increment Y-phase for vertical wave movement
}

View File

@@ -1,168 +0,0 @@
/*
Plasma effect (chars)
Combines sine waves to create a 2D pattern, maps to custom characters,
and renders to the 40x30 character grid with intensity-based colors.
code : zbyti (conversion & optimizations)
original : https://github.com/tebe6502/Mad-Pascal/blob/origin/samples/a8/demoeffects/plasma_2.pas
date : 2025.04.16
platform : MicroW8 0.4.1
*/
include "../include/microw8-api.cwa"
//-----------------------------------------------------------------------------
// Constants defining memory layout, screen dimensions, and effect parameters
//-----------------------------------------------------------------------------
const MEM_END = 0x40000;
const CUSTOM_FONT = FONT + 0x100;
const CHARS = 0x20;
const BASE_COLOR = 0xF0;
const PI = 3.14159265;
const RAD = PI / 180.0;
const SCR_X = 320;
const SCR_Y = 240;
const SCR_W = SCR_X / 8; // 40
const SCR_H = SCR_Y / 8; // 30
const SCR_SIZE = SCR_X * SCR_Y;
const SIN_TABLE_SIZE = 128; // Number of entries in the sine lookup table
const SIN_TABLE_MASK = SIN_TABLE_SIZE - 1;
const SIN_TABLE = MEM_END - SIN_TABLE_SIZE; // Memory address for sine table
const ROW_BUFFER = SIN_TABLE - SCR_W; // Memory address for precomputed row buffer
//-----------------------------------------------------------------------------
// Global variables to track animation state
//-----------------------------------------------------------------------------
global mut phaseA = 1; // Phase offset for the first sine wave, controls animation
global mut phaseB = 5; // Phase offset for the second sine wave, controls animation
//-----------------------------------------------------------------------------
/*
Logs a value to the console (STDOUT) with a prefix for debugging purposes
Args:
prefix : 4-character identifier (i32) to label the output
log : Integer value to log (i32)
Prints to console and returns to screen output
*/
fn console(prefix: i32, log: i32) {
printChar('\6'); // Switch output to console
printChar(prefix); // Print the prefix
printInt(log); // Print the integer value
printChar('\n\4'); // Print newline and switch back to screen output
}
//-------------------------------------
/*
Fills a sine table with precomputed values for fast lookups
Args:
adr : Memory address where the sine table is stored
size : Number of entries in the table
Computes: sin(i * 180/size * radians) * 255 for i = 0 to size-1, scaled to 0-255
*/
fn fillSin(adr: i32, size: i32) {
let i = 0;
let inline f = 180.00 / size as f32 * RAD;
loop i {
(adr+i)?0 = (sin(f * i as f32) * 255.0) as i32;
branch_if (i +:= 1) < size: i;
}
}
//-----------------------------------------------------------------------------
/*
Initialization function called when the program starts
*/
export fn start() {
// Populate the sine table with values for fast wave calculations
fillSin(SIN_TABLE, SIN_TABLE_SIZE);
}
//-------------------------------------
/*
Update function called each frame to render the plasma effect
*/
export fn upd() {
let pA = phaseA; // Local copy of phaseA to avoid modifying global during frame
let pB = phaseB; // Local copy of phaseB for the same reason
let i = 0;
loop i {
// Wrap phase values to stay within sine table bounds using bitwise AND
pA &= SIN_TABLE_MASK;
pB &= SIN_TABLE_MASK;
// Combine two sine waves and store in row buffer
i?ROW_BUFFER = pA?SIN_TABLE + pB?SIN_TABLE;
pA += 3; // Shift phase for first sine wave (controls wave speed)
pB += 7; // Shift phase for second sine wave (different speed for variety)
branch_if (i +:= 1) < SCR_W: i;
}
i = 0;
loop i {
let j = 0;
loop j {
// Combine wave values from row buffer for current position
// Use bitwise AND to clamp to 0-255, then scale to 0-15 for character index
let c = ((j?ROW_BUFFER + i?ROW_BUFFER) & 255) >> 4;
// Set text color based on intensity (base color + scaled value)
setTextColor(BASE_COLOR + c);
// Draw custom character corresponding to intensity
printChar(CHARS + c);
branch_if (j +:= 1) < SCR_W: j;
}
branch_if (i +:= 1) < SCR_H: i;
}
// Update global phase offsets for the next frame to animate the pattern
phaseA += 0; // Increment phaseA to shift the pattern (+/- speed move)
phaseB += 1; // Increment phaseB to shift the pattern (+/- right/left move)
}
//-----------------------------------------------------------------------------
/*
Custom font data defining 16 characters (8x8 pixels each)
Each character represents a different intensity level for the plasma effect
Pixels range from empty (0x00) to nearly full (0xFE or 0x7F) to simulate gradients
*/
data CUSTOM_FONT {
i8(
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00,
0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00,
0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00,
0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
0x00, 0x00, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
)
}

View File

@@ -1,14 +0,0 @@
include "../include/microw8-api.cwa"
export fn upd() {
printString(USER_MEM);
}
data USER_MEM {
// clear screen, switch to graphics text mode, text scale 4
i8(12, 5, 30, 4)
// text color, position, print two lines
i8(15, 86, 31, 8, 80) "Hello," i8(8, 8, 8, 8, 8, 10) "MicroW8!"
// print same two lines with different color and slight offset
i8(15, 47, 31, 10, 82) "Hello," i8(8, 8, 8, 8, 8, 10) "MicroW8!" i8(0)
}

View File

@@ -1,21 +0,0 @@
include "../include/microw8-api.cwa"
const SPRITE = 0x20000;
export fn upd() {
cls(0);
let t = time() / 2_f;
let i: i32;
loop spriteLoop {
let inline x = sin(t * -1.3 + i as f32 * (3.141 / 30_f)) * 180_f + 160_f;
let inline y = sin(t * 1.7 + i as f32 * (3.141 / 40_f)) * 140_f + 120_f;
blitSprite(SPRITE, 16, x as i32, y as i32, (i & 3) * 0x200 + 0x100);
branch_if (i +:= 1) < 100: spriteLoop;
}
}
start fn start() {
printChar('OO');
circle(8_f, 8_f, 6_f, 75);
grabSprite(SPRITE, 16, 0, 0, 0);
}

View File

@@ -3,14 +3,12 @@ include "../include/microw8-api.cwa"
export fn upd() { export fn upd() {
let i: i32; let i: i32;
loop pixels { loop pixels {
let inline t = 16!56; let inline t = time() * 63 as f32;
let inline x = (i % 320 - 160) as f32; let lazy x = (i % 320 - 160) as f32;
let inline y = (i #/ 320 - 120) as f32; let lazy y = (i / 320 - 120) as f32;
let inline d = 0xa000 as f32 / sqrt(x * x + y * y); let inline d = 40000 as f32 / sqrt(x * x + y * y);
let inline a = atan2(x, y) * 163_f; // (512 / pi) let inline u = atan2(x, y) * (512.0 / 3.141);
let inline u = i32.trunc_sat_f32_s(a) + t; let inline c = ((i32.trunc_sat_f32_s(d + t * 2 as f32) ^ i32.trunc_sat_f32_s(u + t)) & 255) >> 4;
let inline v = i32.trunc_sat_f32_s(d) + t * 2;
let inline c = ((v ^ u) #/ 16) % 16;
i?FRAMEBUFFER = c; i?FRAMEBUFFER = c;
branch_if (i := i + 1) < 320*240: pixels; branch_if (i := i + 1) < 320*240: pixels;

View File

@@ -30,13 +30,11 @@ import "env.printInt" fn printInt(i32);
import "env.setTextColor" fn setTextColor(i32); import "env.setTextColor" fn setTextColor(i32);
import "env.setBackgroundColor" fn setBackgroundColor(i32); import "env.setBackgroundColor" fn setBackgroundColor(i32);
import "env.setCursorPosition" fn setCursorPosition(i32, i32); import "env.setCursorPosition" fn setCursorPosition(i32, i32);
import "env.rectangleOutline" fn rectangleOutline(f32, f32, f32, f32, i32); import "env.rectangle_outline" fn rectangle_outline(f32, f32, f32, f32, i32);
import "env.circleOutline" fn circleOutline(f32, f32, f32, i32); import "env.circle_outline" fn circle_outline(f32, f32, f32, i32);
import "env.exp" fn exp(f32) -> f32; import "env.exp" fn exp(f32) -> f32;
import "env.playNote" fn playNote(i32, i32); import "env.playNote" fn playNote(i32, i32);
import "env.sndGes" fn sndGes(i32) -> f32; import "env.sndGes" fn sndGes(i32) -> f32;
import "env.blitSprite" fn blitSprite(i32, i32, i32, i32, i32);
import "env.grabSprite" fn grabSprite(i32, i32, i32, i32, i32);
const TIME_MS = 0x40; const TIME_MS = 0x40;
const GAMEPAD = 0x44; const GAMEPAD = 0x44;

View File

@@ -30,13 +30,11 @@
(import "env" "setTextColor" (func $setTextColor (param i32))) (import "env" "setTextColor" (func $setTextColor (param i32)))
(import "env" "setBackgroundColor" (func $setBackgroundColor (param i32))) (import "env" "setBackgroundColor" (func $setBackgroundColor (param i32)))
(import "env" "setCursorPosition" (func $setCursorPosition (param i32) (param i32))) (import "env" "setCursorPosition" (func $setCursorPosition (param i32) (param i32)))
(import "env" "rectangleOutline" (func $rectangleOutline (param f32) (param f32) (param f32) (param f32) (param i32))) (import "env" "rectangle_outline" (func $rectangle_outline (param f32) (param f32) (param f32) (param f32) (param i32)))
(import "env" "circleOutline" (func $circleOutline (param f32) (param f32) (param f32) (param i32))) (import "env" "circle_outline" (func $circle_outline (param f32) (param f32) (param f32) (param i32)))
(import "env" "exp" (func $exp (param f32) (result f32))) (import "env" "exp" (func $exp (param f32) (result f32)))
(import "env" "playNote" (func $playNote (param i32) (param i32))) (import "env" "playNote" (func $playNote (param i32) (param i32)))
(import "env" "sndGes" (func $sndGes (param i32) (result f32))) (import "env" "sndGes" (func $sndGes (param i32) (result f32)))
(import "env" "blitSprite" (func $blitSprite (param i32) (param i32) (param i32) (param i32) (param i32)))
(import "env" "grabSprite" (func $grabSprite (param i32) (param i32) (param i32) (param i32) (param i32)))
;; to use defines, include this file with a preprocessor ;; to use defines, include this file with a preprocessor
;; like gpp (https://logological.org/gpp). ;; like gpp (https://logological.org/gpp).

380
platform/Cargo.lock generated
View File

@@ -19,54 +19,47 @@ dependencies = [
[[package]] [[package]]
name = "ahash" name = "ahash"
version = "0.8.11" version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [ dependencies = [
"cfg-if", "getrandom",
"once_cell", "once_cell",
"version_check", "version_check",
"zerocopy",
] ]
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.81" version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3"
[[package]] [[package]]
name = "ariadne" name = "ariadne"
version = "0.1.5" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1cb2a2046bea8ce5e875551f5772024882de0b540c7f93dfc5d6cf1ca8b030c" checksum = "7080ae01b2f0c312065d4914cd0f0de045eb8832e9415b355106a6cff3073cb4"
dependencies = [ dependencies = [
"yansi", "yansi",
] ]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.2.0" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.15.0" version = "1.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.92" version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]] [[package]]
name = "cdivsufsort" name = "cdivsufsort"
@@ -95,47 +88,54 @@ dependencies = [
[[package]] [[package]]
name = "const-random" name = "const-random"
version = "0.1.18" version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" checksum = "f590d95d011aa80b063ffe3253422ed5aa462af4e9867d43ce8337562bac77c4"
dependencies = [ dependencies = [
"const-random-macro", "const-random-macro",
"proc-macro-hack",
] ]
[[package]] [[package]]
name = "const-random-macro" name = "const-random-macro"
version = "0.1.16" version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" checksum = "615f6e27d000a2bffbc7f2f6a8669179378fa27ee4d0a509e985dfc0a7defb40"
dependencies = [ dependencies = [
"getrandom", "getrandom",
"once_cell", "lazy_static",
"proc-macro-hack",
"tiny-keccak", "tiny-keccak",
] ]
[[package]] [[package]]
name = "crc32fast" name = "crc32fast"
version = "1.4.0" version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]] [[package]]
name = "crossbeam-channel" name = "crossbeam-channel"
version = "0.5.12" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
dependencies = [ dependencies = [
"cfg-if",
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.19" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"cfg-if",
"lazy_static",
]
[[package]] [[package]]
name = "crunchy" name = "crunchy"
@@ -156,80 +156,54 @@ dependencies = [
"wasmparser 0.83.0", "wasmparser 0.83.0",
] ]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]] [[package]]
name = "fallible_collections" name = "fallible_collections"
version = "0.4.9" version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd" checksum = "3f57ccc32870366ae684be48b32a1a2e196f98a42a9b4361fe77e13fd4a34755"
dependencies = [ dependencies = [
"hashbrown 0.13.2", "hashbrown",
] ]
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.28" version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
dependencies = [ dependencies = [
"crc32fast", "crc32fast",
"miniz_oxide", "miniz_oxide",
] ]
[[package]] [[package]]
name = "getrandom" name = "form_urlencoded"
version = "0.2.14" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
dependencies = [
"percent-encoding",
]
[[package]]
name = "getrandom"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"wasi", "wasi",
] ]
[[package]]
name = "gimli"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
dependencies = [
"fallible-iterator",
"indexmap 1.9.3",
"stable_deref_trait",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
dependencies = [ dependencies = [
"ahash 0.8.11", "ahash 0.7.6",
] ]
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.3.3" version = "0.3.3"
@@ -246,25 +220,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]] [[package]]
name = "indexmap" name = "idna"
version = "1.9.3" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
dependencies = [ dependencies = [
"autocfg", "unicode-bidi",
"hashbrown 0.12.3", "unicode-normalization",
] ]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.2.6" version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [ dependencies = [
"equivalent", "autocfg",
"hashbrown 0.14.3", "hashbrown",
] ]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "leb128" name = "leb128"
version = "0.2.5" version = "0.2.5"
@@ -279,15 +259,15 @@ checksum = "478ee9e62aaeaf5b140bd4138753d1f109765488581444218d3ddda43234f3e8"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.153" version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]] [[package]]
name = "lodepng" name = "lodepng"
version = "3.10.1" version = "3.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a42d298694b14401847de29abd44adf278b42e989e516deac7b72018400002d8" checksum = "f0ad39f75bbaa4b10bb6f2316543632a8046a5bcf9c785488d79720b21f044f8"
dependencies = [ dependencies = [
"crc32fast", "crc32fast",
"fallible_collections", "fallible_collections",
@@ -298,45 +278,55 @@ dependencies = [
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.21" version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.7.2" version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [ dependencies = [
"adler", "adler",
] ]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.18" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.19.0" version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
[[package]] [[package]]
name = "pbr" name = "pbr"
version = "1.1.1" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5827dfa0d69b6c92493d6c38e633bbaa5937c153d0d7c28bf12313f8c6d514" checksum = "ff5751d87f7c00ae6403eb1fcbba229b9c76c9a30de8c1cf87182177b168cea2"
dependencies = [ dependencies = [
"crossbeam-channel", "crossbeam-channel",
"libc", "libc",
"time",
"winapi", "winapi",
] ]
[[package]]
name = "percent-encoding"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]] [[package]]
name = "pico-args" name = "pico-args"
version = "0.4.2" version = "0.4.2"
@@ -360,28 +350,34 @@ dependencies = [
] ]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro-hack"
version = "1.0.79" version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
dependencies = [ dependencies = [
"unicode-ident", "unicode-xid",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.35" version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]] [[package]]
name = "rgb" name = "rgb"
version = "0.8.37" version = "0.8.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" checksum = "3603b7d71ca82644f79b5a06d1220e9a58ede60bd32255f698cb1af8838b8db3"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
] ]
@@ -395,58 +391,45 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "semver"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"unicode-ident", "unicode-xid",
]
[[package]]
name = "syn"
version = "2.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
] ]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.58" version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.58" version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.58", "syn",
]
[[package]]
name = "time"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
dependencies = [
"libc",
"winapi",
] ]
[[package]] [[package]]
@@ -459,16 +442,46 @@ dependencies = [
] ]
[[package]] [[package]]
name = "unicode-ident" name = "tinyvec"
version = "1.0.12" version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "unicode-bidi"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]] [[package]]
name = "unicode-segmentation" name = "unicode-segmentation"
version = "1.11.0" version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]] [[package]]
name = "upkr" name = "upkr"
@@ -481,6 +494,17 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "url"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]] [[package]]
name = "uw8-tool" name = "uw8-tool"
version = "0.1.0" version = "0.1.0"
@@ -490,30 +514,28 @@ dependencies = [
"pico-args 0.5.0", "pico-args 0.5.0",
"upkr", "upkr",
"walrus", "walrus",
"wasm-encoder 0.201.0", "wasm-encoder 0.22.0",
"wasmparser 0.201.0", "wasmparser 0.99.0",
] ]
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.4" version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]] [[package]]
name = "walrus" name = "walrus"
version = "0.20.3" version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c03529cd0c4400a2449f640d2f27cd1b48c3065226d15e26d98e4429ab0adb7" checksum = "4eb08e48cde54c05f363d984bb54ce374f49e242def9468d2e1b6c2372d291f8"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"gimli",
"id-arena", "id-arena",
"leb128", "leb128",
"log", "log",
"walrus-macro", "walrus-macro",
"wasm-encoder 0.29.0", "wasmparser 0.77.0",
"wasmparser 0.80.2",
] ]
[[package]] [[package]]
@@ -525,14 +547,14 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.109", "syn",
] ]
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]] [[package]]
name = "wasm-encoder" name = "wasm-encoder"
@@ -545,27 +567,18 @@ dependencies = [
[[package]] [[package]]
name = "wasm-encoder" name = "wasm-encoder"
version = "0.29.0" version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18c41dbd92eaebf3612a39be316540b8377c871cb9bde6b064af962984912881" checksum = "ef126be0e14bdf355ac1a8b41afc89195289e5c7179f80118e3abddb472f0810"
dependencies = [
"leb128",
]
[[package]]
name = "wasm-encoder"
version = "0.201.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a"
dependencies = [ dependencies = [
"leb128", "leb128",
] ]
[[package]] [[package]]
name = "wasmparser" name = "wasmparser"
version = "0.80.2" version = "0.77.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "449167e2832691a1bff24cde28d2804e90e09586a448c8e76984792c44334a6b" checksum = "b35c86d22e720a07d954ebbed772d01180501afe7d03d464f413bb5f8914a8d6"
[[package]] [[package]]
name = "wasmparser" name = "wasmparser"
@@ -575,13 +588,12 @@ checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a"
[[package]] [[package]]
name = "wasmparser" name = "wasmparser"
version = "0.201.0" version = "0.99.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84e5df6dba6c0d7fafc63a450f1738451ed7a0b52295d83e868218fa286bf708" checksum = "9ef3b717afc67f848f412d4f02c127dd3e35a0eecd58c684580414df4fde01d3"
dependencies = [ dependencies = [
"bitflags", "indexmap",
"indexmap 2.2.6", "url",
"semver",
] ]
[[package]] [[package]]
@@ -608,26 +620,6 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]] [[package]]
name = "yansi" name = "yansi"
version = "0.5.1" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" checksum = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71"
[[package]]
name = "zerocopy"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]

Binary file not shown.

Binary file not shown.

View File

@@ -62,7 +62,6 @@ export fn cls(col: i32) {
textCursorX = 0; textCursorX = 0;
textCursorY = 0; textCursorY = 0;
outputChannel = 0; outputChannel = 0;
textScale = 1;
memory.fill(120, col, 320*240); memory.fill(120, col, 320*240);
} }
@@ -172,7 +171,7 @@ export fn rectangle(x: f32, y: f32, w: f32, h: f32, col: i32) {
} }
} }
export fn rectangleOutline(x: f32, y: f32, w: f32, h: f32, col: i32) { export fn rectangle_outline(x: f32, y: f32, w: f32, h: f32, col: i32) {
let xl = nearest(x) as i32; let xl = nearest(x) as i32;
let xr = nearest(x + w) as i32; let xr = nearest(x + w) as i32;
let yt = nearest(y) as i32; let yt = nearest(y) as i32;
@@ -213,7 +212,7 @@ export fn circle(cx: f32, cy: f32, radius: f32, col: i32) {
} }
} }
export fn circleOutline(cx: f32, cy: f32, radius: f32, col: i32) { export fn circle_outline(cx: f32, cy: f32, radius: f32, col: i32) {
let prev_w: f32; let prev_w: f32;
let y = clamp(nearest(cy - radius) as i32, -1, 241); let y = clamp(nearest(cy - radius) as i32, -1, 241);
let maxY = clamp(nearest(cy + radius) as i32, -1, 241); let maxY = clamp(nearest(cy + radius) as i32, -1, 241);
@@ -353,92 +352,6 @@ export fn line(x1: f32, y1: f32, x2: f32, y2: f32, col: i32) {
setPixel(i32.trunc_sat_f32_s(x1 + f * dx), i32.trunc_sat_f32_s(y1 + f * dy), col); setPixel(i32.trunc_sat_f32_s(x1 + f * dx), i32.trunc_sat_f32_s(y1 + f * dy), col);
} }
export fn blitSprite(sprite: i32, size: i32, x: i32, y: i32, control: i32) {
let lazy width = size & 65535;
let lazy height = select(size >> 16, size >> 16, width);
let lazy x0 = select(x < 0, -x, 0);
let lazy x1 = select(x + width > 320, 320 - x, width);
let lazy y0 = select(y < 0, -y, 0);
let lazy y1 = select(y + height > 240, 240 - y, height);
let lazy numRows = y1 - y0;
let lazy numCols = x1 - x0;
if numRows <= 0 | numCols <= 0 {
return;
}
let trans = (control & 511) - 256;
let lazy flip_x = 1 - ((control >> 8) & 2);
let lazy flip_y = 1 - ((control >> 9) & 2);
if flip_x < 0 {
sprite += width - 1;
}
if flip_y < 0 {
sprite += (height - 1) * width;
}
let spriteRow = sprite + x0 * flip_x + y0 * flip_y * width;
let screenRow = x + x0 + (y + y0) * 320;
loop yloop {
let lx = 0;
loop xloop {
let lazy col = (spriteRow + lx * flip_x)?0;
if col != trans {
(screenRow + lx)?120 = col;
}
branch_if (lx +:= 1) < numCols: xloop;
}
spriteRow += width * flip_y;
screenRow += 320;
branch_if numRows -:= 1: yloop;
}
}
export fn grabSprite(sprite: i32, size: i32, x: i32, y: i32, control: i32) {
let lazy width = size & 65535;
let lazy height = select(size >> 16, size >> 16, width);
let lazy x0 = select(x < 0, -x, 0);
let lazy x1 = select(x + width > 320, 320 - x, width);
let lazy y0 = select(y < 0, -y, 0);
let lazy y1 = select(y + height > 240, 240 - y, height);
let lazy numRows = y1 - y0;
let lazy numCols = x1 - x0;
if numRows <= 0 | numCols <= 0 {
return;
}
let trans = (control & 511) - 256;
let lazy flip_x = 1 - ((control >> 8) & 2);
let lazy flip_y = 1 - ((control >> 9) & 2);
if flip_x < 0 {
sprite += width - 1;
}
if flip_y < 0 {
sprite += (height - 1) * width;
}
let spriteRow = sprite + x0 * flip_x + y0 * flip_y * width;
let screenRow = x + x0 + (y + y0) * 320;
loop yloop {
let lx = 0;
loop xloop {
let lazy col = (screenRow + lx)?120;
if col != trans {
(spriteRow + lx * flip_x)?0 = col;
}
branch_if (lx +:= 1) < numCols: xloop;
}
spriteRow += width * flip_y;
screenRow += 320;
branch_if numRows -:= 1: yloop;
}
}
////////// //////////
// TEXT // // TEXT //
////////// //////////
@@ -448,7 +361,6 @@ global mut textCursorY = 0;
global mut textColor = 15; global mut textColor = 15;
global mut bgColor = 0; global mut bgColor = 0;
global mut outputChannel = 0; global mut outputChannel = 0;
global mut textScale = 1;
export fn printChar(char: i32) { export fn printChar(char: i32) {
loop chars { loop chars {
@@ -460,8 +372,6 @@ export fn printChar(char: i32) {
global mut controlCodeLength = 0; global mut controlCodeLength = 0;
fn printSingleChar(char: i32) { fn printSingleChar(char: i32) {
let charSize = 8 * textScale;
if outputChannel >= 2 & (char < 4 | char > 6) { if outputChannel >= 2 & (char < 4 | char > 6) {
logChar(char); logChar(char);
return; return;
@@ -495,9 +405,9 @@ fn printSingleChar(char: i32) {
} }
if char == 8 { if char == 8 {
textCursorX = textCursorX - charSize; textCursorX = textCursorX - 8;
if !outputChannel & textCursorX < 0 { if !outputChannel & textCursorX < 0 {
textCursorX = 320-charSize; textCursorX = 320-8;
printSingleChar(11); printSingleChar(11);
} }
return; return;
@@ -507,34 +417,34 @@ fn printSingleChar(char: i32) {
if !outputChannel & textCursorX >= 320 { if !outputChannel & textCursorX >= 320 {
printChar(0xd0a); printChar(0xd0a);
} }
textCursorX = textCursorX + charSize; textCursorX = textCursorX + 8;
return; return;
} }
if char == 10 { if char == 10 {
textCursorY = textCursorY + charSize; textCursorY = textCursorY + 8;
if !outputChannel & textCursorY >= 240 { if !outputChannel & textCursorY >= 240 {
textCursorY = 240 - charSize; textCursorY = 240 - 8;
let i: i32; let i: i32;
loop scroll_copy { loop scroll_copy {
i!120 = (i + 320 * charSize)!120; i!120 = i!(120 + 320 * 8);
branch_if (i := i + 4) < 320 * (240 - charSize): scroll_copy; branch_if (i := i + 4) < 320 * (240 - 8): scroll_copy;
} }
rectangle(0 as f32, (240 - charSize) as f32, 320 as f32, charSize as f32, bgColor); rectangle(0 as f32, (240 - 8) as f32, 320 as f32, 8 as f32, bgColor);
} }
return; return;
} }
if char == 11 { if char == 11 {
textCursorY = textCursorY - charSize; textCursorY = textCursorY - 8;
if !outputChannel & textCursorY < 0 { if !outputChannel & textCursorY < 0 {
textCursorY = 0; textCursorY = 0;
let i = 320 * (240 - charSize); let i = 320 * (240 - 8);
loop scroll_copy { loop scroll_copy {
(i + 320 * charSize)!116 = i!116; i!(116 + 320 * 8) = i!116;
branch_if (i := i - 4): scroll_copy; branch_if (i := i - 4): scroll_copy;
} }
rectangle(0 as f32, 0 as f32, 320 as f32, charSize as f32, bgColor); rectangle(0 as f32, 0 as f32, 320 as f32, 8 as f32, bgColor);
} }
return; return;
} }
@@ -566,12 +476,6 @@ fn printSingleChar(char: i32) {
return; return;
} }
if char == 30 {
let scale = 0x12d20?1;
textScale = select(scale > 0 & scale <= 16, scale, 1);
return;
}
if char == 31 { if char == 31 {
textCursorX = 0x12d20?1 * (8 - outputChannel * 6); textCursorX = 0x12d20?1 * (8 - outputChannel * 6);
textCursorY = 0x12d20?2 * (8 - outputChannel * 7); textCursorY = 0x12d20?2 * (8 - outputChannel * 7);
@@ -594,7 +498,7 @@ data(0x12d00) {
1, 1, 1, 1, // 16-19, 1, 1, 1, 1, // 16-19,
1, 1, 1, 1, // 20-23, 1, 1, 1, 1, // 20-23,
1, 1, 1, 1, // 24-27, 1, 1, 1, 1, // 24-27,
1, 1, 2, 3 // 28-31 1, 1, 1, 3 // 28-31
) )
} }
@@ -603,28 +507,26 @@ fn drawChar(char: i32) {
printChar(0xd0a); printChar(0xd0a);
} }
let charSize = 8 * textScale;
let y: i32; let y: i32;
loop rows { loop rows {
let bits = (char * 8 + y / textScale)?0x13400; let bits = (char * 8 + y)?0x13400;
let x = 0; let x = 0;
if outputChannel { if outputChannel {
loop pixels { loop pixels {
if (bits << (x / textScale)) & 128 { if (bits := bits << 1) & 256 {
setPixel(textCursorX + x, textCursorY + y, textColor); setPixel(textCursorX + x, textCursorY + y, textColor);
} }
branch_if (x := x + 1) < charSize: pixels; branch_if (x := x + 1) < 8: pixels;
} }
} else { } else {
loop pixels { loop pixels {
setPixel(textCursorX + x, textCursorY + y, select((bits << (x / textScale)) & 128, textColor, bgColor)); setPixel(textCursorX + x, textCursorY + y, select((bits := bits << 1) & 256, textColor, bgColor));
branch_if (x := x + 1) < charSize: pixels; branch_if (x := x + 1) < 8: pixels;
} }
} }
branch_if (y := y + 1) < charSize: rows; branch_if (y := y + 1) < 8: rows;
} }
textCursorX = textCursorX + charSize; textCursorX = textCursorX + 8;
} }
export fn printString(ptr: i32) { export fn printString(ptr: i32) {

View File

@@ -31,19 +31,50 @@ Examplers for older versions:
## Versions ## Versions
### v0.4.1 ### v0.2.2
* [Web runtime](../v0.4.1) * [Web runtime](v0.2.2)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.4.1/microw8-0.4.1-linux.tgz) * [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.4.1/microw8-0.4.1-macos.tgz) * [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.4.1/microw8-0.4.1-windows.zip) * [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-windows.zip)
Changes: Changes:
* Windows: fix bad/inconsistent frame rate * call `start` function after loading cart if the cart exports one
* fix choppy sound on devices with sample rates != 44100 kHz * fix `sndGes` having the wrong name and not being included in the auto imports
* add scale mode 'fill' option * fix control codes 4-6 (change text output mode) being invoked when used as parameters in other control sequences
* only open browser window once a cart was compiled sucessfully when running with `-b`
### v0.2.1
* [Web runtime](v0.2.1)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.1/microw8-0.2.1-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.1/microw8-0.2.1-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.1/microw8-0.2.1-windows.zip)
Changes:
* new gpu accelerated renderer with (optional) crt filter
* optimized `hline` function, a big speed-up when drawing large filled circles or rectangles
* print fractional size of packed `uw8` cart
### v0.2.0
* [Web runtime](v0.2.0)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.0/microw8-0.2.0-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.0/microw8-0.2.0-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.0/microw8-0.2.0-windows.zip)
Changes:
* [add sound support!](docs#sound)
* add support to redirect text output to the console for debugging using control code 6
* update curlywas:
* add support for `else if`
* add support for escape sequences in strings
* add support for char literals
* add support for binop-assignment, eg. `+=`, `^=`, `<<=` etc. (also support for the tee operator: `+:=`)
* "integer constant cast to float" literal syntax in CurlyWas (ex. `1_f` is equivalent to `1 as f32`)
### Older versions ### Older versions

View File

@@ -21,7 +21,7 @@ loaded.
00000-00040: user memory 00000-00040: user memory
00040-00044: time since module start in ms 00040-00044: time since module start in ms
00044-0004c: gamepad state 00044-0004c: gamepad state
0004c-00050: number of frames since module start 0004c-00050: reserved
00050-00070: sound data (synced to sound thread) 00050-00070: sound data (synced to sound thread)
00070-00078: reserved 00070-00078: reserved
00078-12c78: frame buffer 00078-12c78: frame buffer
@@ -146,13 +146,13 @@ Fills the circle at `cx, cy` and with `radius` with the given color index.
(Sets all pixels where the pixel center lies inside the circle.) (Sets all pixels where the pixel center lies inside the circle.)
### fn rectangleOutline(x: f32, y: f32, w: f32, h: f32, color: i32) ### fn rectangle_outline(x: f32, y: f32, w: f32, h: f32, color: i32)
Draws a one pixel outline on the inside of the given rectangle. Draws a one pixel outline on the inside of the given rectangle.
(Draws the outermost pixels that are still inside the rectangle area.) (Draws the outermost pixels that are still inside the rectangle area.)
### fn circleOutline(cx: f32, cy: f32, radius: f32, color: i32) ### fn circle_outline(cx: f32, cy: f32, radius: f32, color: i32)
Draws a one pixel outline on the inside of the given circle. Draws a one pixel outline on the inside of the given circle.
@@ -162,21 +162,6 @@ Draws a one pixel outline on the inside of the given circle.
Draws a line from `x1,y1` to `x2,y2` in the given color index. Draws a line from `x1,y1` to `x2,y2` in the given color index.
### fn blitSprite(spriteData: i32, size: i32, x: i32, y: i32, control: i32)
Copies the pixel data at `spriteData` onto the screen at `x`, `y`. The size of the sprite is passed as `width | (height << 16)`.
If the height is given as 0, the sprite is is treated as square (width x width).
The control parameter controls masking and flipping of the sprite:
* bits 0-7: color mask index
* bit 8: switch on masked blit (pixel with color mask index are treated as transparent)
* bit 9: flip sprite x
* bit 10: flip sprite y
### fn grabSprite(spriteData: i32, size: i32, x: i32, y: i32, control: i32)
Copies the pixel data on the screen at `x`, `y` to `spriteData`. Parameters are exactly the same as `blitSprite`.
## Input ## Input
MicroW8 provides input from a gamepad with one D-Pad and 4 buttons, or a keyboard emulation thereof. MicroW8 provides input from a gamepad with one D-Pad and 4 buttons, or a keyboard emulation thereof.
@@ -238,13 +223,6 @@ When printing characters only the foreground pixels are set, the background is "
Moving/printing past any border does not cause any special operation, the cursor just goes off-screen. Moving/printing past any border does not cause any special operation, the cursor just goes off-screen.
### Text scale
An integer text scale factor in the range 1x-16x can be set with control char 30. An attempt to
set a scale outside that range will reset the scale to 1x.
After startup and `cls` the scale is initialized to 1x.
### Control chars ### Control chars
Characters 0-31 are control characters and don't print by default. They take the next 0-2 following characters as parameters. Characters 0-31 are control characters and don't print by default. They take the next 0-2 following characters as parameters.
@@ -269,8 +247,7 @@ Avoid the reserved control chars, they are currently NOPs but their behavior can
| 15 | color | Set the text color | | 15 | color | Set the text color |
| 16-23 | - | Reserved | | 16-23 | - | Reserved |
| 24 | - | Swap text/background colors | | 24 | - | Swap text/background colors |
| 25-29 | - | Reserved | | 25-30 | - | Reserved |
| 30 | scale | Set text scale (1-16) |
| 31 | x, y | Set cursor position (*) | | 31 | x, y | Set cursor position (*) |
(*) In graphics mode, the x coordinate is doubled when using control char 31 to be able to cover the whole screen with one byte. (*) In graphics mode, the x coordinate is doubled when using control char 31 to be able to cover the whole screen with one byte.
@@ -279,7 +256,7 @@ Avoid the reserved control chars, they are currently NOPs but their behavior can
Control code 6 switches all text output (except codes 4 and 5 to switch output back to the screen) to the console. Where exactly this ends Control code 6 switches all text output (except codes 4 and 5 to switch output back to the screen) to the console. Where exactly this ends
up (if at all) is an implementation detail of the runtimes. The native dev-runtime writes the debug output to `stdout`, the web runtime to up (if at all) is an implementation detail of the runtimes. The native dev-runtime writes the debug output to `stdout`, the web runtime to
the debug console using `console.log`. Both implementations buffer the output until they encounter a newline character (10) in the output stream. the debug console using `console.log`. Both implementation buffer the output until they encounter a newline character (10) in the output stream.
There may be future runtimes that ignore the debug output completely. There may be future runtimes that ignore the debug output completely.
@@ -468,7 +445,6 @@ when using the native runtime:
* `--no-gpu`: Force old cpu-only window code * `--no-gpu`: Force old cpu-only window code
* `--filter FILTER`: Select an upscale filter at startup * `--filter FILTER`: Select an upscale filter at startup
* `--fullscreen`: Start in fullscreen mode * `--fullscreen`: Start in fullscreen mode
* `--scale-fill`: Scale to fill whole screen, potentially cropping parts of the frame buffer.
Note that the cpu-only window does not support fullscreen nor upscale filters. Note that the cpu-only window does not support fullscreen nor upscale filters.
@@ -485,7 +461,7 @@ The upscale filter options are:
5, auto_crt (default) : ss_crt below 960x720, chromatic_crt otherwise 5, auto_crt (default) : ss_crt below 960x720, chromatic_crt otherwise
``` ```
You can switch the upscale filter at any time using the keys 1-5. You can toggle fullscreen with F. You can toggle between scale modes 'fit' and 'fill' with M. You can switch the upscale filter at any time using the keys 1-5. You can toggle fullscreen with F.
## `uw8 pack` ## `uw8 pack`
@@ -595,7 +571,7 @@ a base module provided by MicroW8.
You can generate this base module yourself using You can generate this base module yourself using
`uw8-tool`. As a quick summary, it provides all function `uw8-tool`. As a quick summary, it provides all function
types with up to 7 parameters (i32 or f32) where the types with up to 5 parameters (i32 or f32) where the
`f32` parameters always preceed the `i32` parameters. `f32` parameters always preceed the `i32` parameters.
Then it includes all imports that MicroW8 provides, Then it includes all imports that MicroW8 provides,
a function section with a single function of type a function section with a single function of type

View File

@@ -2,77 +2,9 @@
description = "Versions" description = "Versions"
+++ +++
### v0.4.1
* [Web runtime](../v0.4.1)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.4.1/microw8-0.4.1-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.4.1/microw8-0.4.1-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.4.1/microw8-0.4.1-windows.zip)
Changes:
* Windows: fix bad/inconsistent frame rate
* fix choppy sound on devices with sample rates != 44100 kHz
* add scale mode 'fill' option
### v0.4.0
* [Web runtime](../v0.4.0)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.4.0/microw8-0.4.0-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.4.0/microw8-0.4.0-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.4.0/microw8-0.4.0-windows.zip)
Changes:
* add support for sound on mono- and surround-only devices
* update wasmtime dependency to fix performance regression in 0.3.0
* add frame counter since module start at location 72
* add 6 and 7 parameter function types to base module
### v0.3.0
* [Web runtime](../v0.3.0)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.3.0/microw8-0.3.0-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.3.0/microw8-0.3.0-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.3.0/microw8-0.3.0-windows.zip)
Changes:
* add blitSprite and grabSprite API calls
* add support for integer scaling up to 16x for printing text
* fix incompatibility with sound devices only offering 16bit audio formats
* add support for br_table instruction in packed carts
### v0.2.2
* [Web runtime](../v0.2.2)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-windows.zip)
Changes:
* call `start` function after loading cart if the cart exports one
* fix `sndGes` having the wrong name and not being included in the auto imports
* fix control codes 4-6 (change text output mode) being invoked when used as parameters in other control sequences
* only open browser window once a cart was compiled sucessfully when running with `-b`
### v0.2.1
* [Web runtime](../v0.2.1)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.1/microw8-0.2.1-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.1/microw8-0.2.1-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.1/microw8-0.2.1-windows.zip)
Changes:
* new gpu accelerated renderer with (optional) crt filter
* optimized `hline` function, a big speed-up when drawing large filled circles or rectangles
* print fractional size of packed `uw8` cart
### v0.2.0 ### v0.2.0
* [Web runtime](../v0.2.0) * [Web runtime](v0.2.0)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.0/microw8-0.2.0-linux.tgz) * [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.0/microw8-0.2.0-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.0/microw8-0.2.0-macos.tgz) * [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.0/microw8-0.2.0-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.0/microw8-0.2.0-windows.zip) * [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.0/microw8-0.2.0-windows.zip)
@@ -90,7 +22,7 @@ Changes:
### v0.2.0-rc3 ### v0.2.0-rc3
* [Web runtime](../v0.2.0-rc3) * [Web runtime](v0.2.0-rc3)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc3/microw8-0.2.0-rc3-linux.tgz) * [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc3/microw8-0.2.0-rc3-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc3/microw8-0.2.0-rc3-macos.tgz) * [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc3/microw8-0.2.0-rc3-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc3/microw8-0.2.0-rc3-windows.zip) * [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc3/microw8-0.2.0-rc3-windows.zip)
@@ -108,7 +40,7 @@ Changes:
### v0.2.0-rc2 ### v0.2.0-rc2
* [Web runtime](../v0.2.0-rc2) * [Web runtime](v0.2.0-rc2)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc2/microw8-0.2.0-rc2-linux.tgz) * [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc2/microw8-0.2.0-rc2-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc2/microw8-0.2.0-rc2-macos.tgz) * [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc2/microw8-0.2.0-rc2-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc2/microw8-0.2.0-rc2-windows.zip) * [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc2/microw8-0.2.0-rc2-windows.zip)
@@ -119,7 +51,7 @@ Changes:
### v0.2.0-rc1 ### v0.2.0-rc1
* [Web runtime](../v0.2.0-rc1) * [Web runtime](v0.2.0-rc1)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc1/microw8-0.2.0-rc1-linux.tgz) * [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc1/microw8-0.2.0-rc1-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc1/microw8-0.2.0-rc1-macos.tgz) * [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc1/microw8-0.2.0-rc1-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc1/microw8-0.2.0-rc1-windows.zip) * [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.0-rc1/microw8-0.2.0-rc1-windows.zip)
@@ -135,7 +67,7 @@ Known issues:
### v0.1.2 ### v0.1.2
* [Web runtime](../v0.1.2) * [Web runtime](v0.1.2)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-linux.tgz) * [Linux](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-macos.tgz) * [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-windows.zip) * [Windows](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-windows.zip)
@@ -143,13 +75,13 @@ Known issues:
Changes: Changes:
* add option to `uw8 run` to run the cart in the browser using the web runtime * add option to `uw8 run` to run the cart in the browser using the web runtime
*../ CurlyWas: implement `include` support * CurlyWas: implement `include` support
* CurlyWas: implement support for constants * CurlyWas: implement support for constants
* fix crash when trying to draw zero sized line * fix crash when trying to draw zero sized line
### v0.1.1 ### v0.1.1
* [Web runtime](../v0.1.1) * [Web runtime](v0.1.1)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.1.1/microw8-0.1.1-linux.tgz) * [Linux](https://github.com/exoticorn/microw8/releases/download/v0.1.1/microw8-0.1.1-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.1.1/microw8-0.1.1-macos.tgz) * [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.1.1/microw8-0.1.1-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.1.1/microw8-0.1.1-windows.zip) * [Windows](https://github.com/exoticorn/microw8/releases/download/v0.1.1/microw8-0.1.1-windows.zip)
@@ -158,16 +90,16 @@ Changes:
* implement more robust file watcher * implement more robust file watcher
* add basic video recording on F10 in web runtime * add basic video recording on F10 in web runtime
*../ add screenshot on F9 * add screenshot on F9
* add watchdog to interrupt hanging update in native runtime * add watchdog to interrupt hanging update in native runtime
* add devkit mode to web runtime * add devkit mode to web runtime
*../ add unpack and compile commands to uw8 * add unpack and compile commands to uw8
* add support for table/element section in pack command * add support for table/element section in pack command
* disable wayland support (caused missing window decorations in gnome) * disable wayland support (caused missing window decorations in gnome)
### v0.1.0 ### v0.1.0
* [Web runtime](../v0.1.0) * [Web runtime](v0.1.0)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.1.0/microw8-0.1.0-linux.tgz) * [Linux](https://github.com/exoticorn/microw8/releases/download/v0.1.0/microw8-0.1.0-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.1.0/microw8-0.1.0-macos.tgz) * [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.1.0/microw8-0.1.0-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.1.0/microw8-0.1.0-windows.zip) * [Windows](https://github.com/exoticorn/microw8/releases/download/v0.1.0/microw8-0.1.0-windows.zip)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
<section> <section>
<h1 class="text-center heading-text">A WebAssembly based fantasy console</h1> <h1 class="text-center heading-text">A WebAssembly based fantasy console</h1>
</section> </section>
<a href="v0.4.1"> <a href="v0.2.2">
<img class="demonstration-gif" style="width:640px;height:480px;image-rendering:pixelated" src="img/technotunnel.png"></img> <img class="demonstration-gif" style="width:640px;height:480px;image-rendering:pixelated" src="img/technotunnel.png"></img>
</a> </a>
</div> </div>

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,7 @@ use std::sync::{mpsc, Arc, Mutex};
use std::time::Duration; use std::time::Duration;
use std::{thread, time::Instant}; use std::{thread, time::Instant};
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, Result};
use cpal::traits::*; use cpal::traits::*;
use rubato::Resampler; use rubato::Resampler;
use uw8_window::{Window, WindowConfig}; use uw8_window::{Window, WindowConfig};
@@ -27,7 +27,6 @@ struct UW8Instance {
end_frame: TypedFunc<(), ()>, end_frame: TypedFunc<(), ()>,
update: Option<TypedFunc<(), ()>>, update: Option<TypedFunc<(), ()>>,
start_time: Instant, start_time: Instant,
frame_counter: u32,
watchdog: Arc<Mutex<UW8WatchDog>>, watchdog: Arc<Mutex<UW8WatchDog>>,
sound_tx: Option<mpsc::SyncSender<RegisterUpdate>>, sound_tx: Option<mpsc::SyncSender<RegisterUpdate>>,
} }
@@ -160,7 +159,6 @@ impl super::Runtime for MicroW8 {
end_frame, end_frame,
update, update,
start_time: Instant::now(), start_time: Instant::now(),
frame_counter: 0,
watchdog, watchdog,
sound_tx, sound_tx,
}); });
@@ -193,11 +191,8 @@ impl super::Runtime for MicroW8 {
let mem = instance.memory.data_mut(&mut instance.store); let mem = instance.memory.data_mut(&mut instance.store);
mem[64..68].copy_from_slice(&time.to_le_bytes()); mem[64..68].copy_from_slice(&time.to_le_bytes());
mem[68..72].copy_from_slice(&input.gamepads); mem[68..72].copy_from_slice(&input.gamepads);
mem[72..76].copy_from_slice(&instance.frame_counter.to_le_bytes());
} }
instance.frame_counter = instance.frame_counter.wrapping_add(1);
instance.store.set_epoch_deadline(self.timeout as u64); instance.store.set_epoch_deadline(self.timeout as u64);
if let Some(ref update) = instance.update { if let Some(ref update) = instance.update {
if let Err(err) = update.call(&mut instance.store, ()) { if let Err(err) = update.call(&mut instance.store, ()) {
@@ -333,37 +328,26 @@ fn init_sound(
let mut configs: Vec<_> = device let mut configs: Vec<_> = device
.supported_output_configs()? .supported_output_configs()?
.filter(|config| { .filter(|config| {
config.sample_format() == cpal::SampleFormat::F32 config.channels() == 2
|| config.sample_format() == cpal::SampleFormat::I16 && (config.sample_format() == cpal::SampleFormat::F32
|| config.sample_format() == cpal::SampleFormat::I16)
}) })
.collect(); .collect();
if configs.is_empty() {
eprintln!(
"No suitable audio output config found on device \"{}\", available configs:",
device.name()?
);
for config in device.supported_output_configs()? {
eprintln!(" {}ch {}", config.channels(), config.sample_format());
}
bail!("Failed to configure audio out");
}
configs.sort_by_key(|config| { configs.sort_by_key(|config| {
let rate = 44100 let rate = 44100
.max(config.min_sample_rate().0) .max(config.min_sample_rate().0)
.min(config.max_sample_rate().0); .min(config.max_sample_rate().0);
let rate_prio = if rate >= 44100 { let prio = if rate >= 44100 {
rate - 44100 rate - 44100
} else { } else {
(44100 - rate) * 1000 (44100 - rate) * 1000
}; };
let format_prio = (config.sample_format() == cpal::SampleFormat::I16) as u32; prio + (config.sample_format() == cpal::SampleFormat::I16) as u32
let channels_prio = (config.channels() != 2) as u32 * 16777216;
rate_prio + format_prio + channels_prio
}); });
let config = configs.into_iter().next().unwrap(); let config = configs
.into_iter()
.next()
.ok_or_else(|| anyhow!("Could not find float or 16bit signed output config"))?;
let sample_rate = cpal::SampleRate(44100) let sample_rate = cpal::SampleRate(44100)
.max(config.min_sample_rate()) .max(config.min_sample_rate())
.min(config.max_sample_rate()); .min(config.max_sample_rate());
@@ -375,7 +359,6 @@ fn init_sound(
} }
}; };
let sample_format = config.sample_format(); let sample_format = config.sample_format();
let num_channels = config.channels();
let config = cpal::StreamConfig { let config = cpal::StreamConfig {
buffer_size, buffer_size,
..config.config() ..config.config()
@@ -395,8 +378,8 @@ fn init_sound(
None None
} else { } else {
let rs = rubato::FftFixedIn::new(44100, sample_rate, 128, 1, 2)?; let rs = rubato::FftFixedIn::new(44100, sample_rate, 128, 1, 2)?;
let input_buffers = rs.input_buffer_allocate(); let input_buffers = rs.input_buffer_allocate(true);
let output_buffers = rs.output_buffer_allocate(); let output_buffers = rs.output_buffer_allocate(true);
Some(Resampler { Some(Resampler {
resampler: rs, resampler: rs,
input_buffers, input_buffers,
@@ -409,7 +392,7 @@ fn init_sound(
let mut pending_updates: Vec<RegisterUpdate> = Vec::with_capacity(30); let mut pending_updates: Vec<RegisterUpdate> = Vec::with_capacity(30);
let mut current_time = 0; let mut current_time = 0;
let mut callback = move |mut outer_buffer: &mut [f32]| { let mut callback = move |mut outer_buffer: &mut [f32], _: &_| {
let mut first_update = true; let mut first_update = true;
while let Ok(update) = rx.try_recv() { while let Ok(update) = rx.try_recv() {
if first_update { if first_update {
@@ -501,126 +484,36 @@ fn init_sound(
current_time = current_time.wrapping_add((step_size * 500 / sample_rate).max(1) as i32); current_time = current_time.wrapping_add((step_size * 500 / sample_rate).max(1) as i32);
} }
}; };
let stream = if sample_format == cpal::SampleFormat::F32 {
fn f32_to_i16<F>(mut buffer: &mut [i16], callback: &mut F) device.build_output_stream(
where &config,
F: FnMut(&mut [f32]), callback,
{ move |err| {
dbg!(err);
},
None,
)?
} else {
device.build_output_stream(
&config,
move |mut buffer: &mut [i16], info| {
let mut float_buffer = [0f32; 256]; let mut float_buffer = [0f32; 256];
while !buffer.is_empty() { while !buffer.is_empty() {
let step_size = buffer.len().min(float_buffer.len()); let step_size = buffer.len().min(float_buffer.len());
let step_buffer = &mut float_buffer[..step_size]; let step_buffer = &mut float_buffer[..step_size];
callback(step_buffer); callback(step_buffer, info);
for (dest, src) in buffer.iter_mut().take(step_size).zip(step_buffer.iter()) { for (dest, src) in buffer.iter_mut().take(step_size).zip(step_buffer.iter()) {
*dest = (src.max(-1.0).min(1.0) * 32767.0) as i16; *dest = (src.max(-1.0).min(1.0) * 32767.0) as i16;
} }
buffer = &mut buffer[step_size..]; buffer = &mut buffer[step_size..];
} }
}
fn stereo_to_mono<F>(mut buffer: &mut [f32], callback: &mut F)
where
F: FnMut(&mut [f32]),
{
let mut in_buffer = [0f32; 256];
while !buffer.is_empty() {
let step_size = buffer.len().min(in_buffer.len() / 2);
let step_buffer = &mut in_buffer[..step_size * 2];
callback(step_buffer);
for (index, dest) in buffer.iter_mut().take(step_size).enumerate() {
*dest = (step_buffer[index * 2] + step_buffer[index * 2 + 1]) * 0.5;
}
buffer = &mut buffer[step_size..];
}
}
fn stereo_to_surround<F>(mut buffer: &mut [f32], num_channels: usize, callback: &mut F)
where
F: FnMut(&mut [f32]),
{
let mut in_buffer = [0f32; 256];
buffer.fill(0.);
while !buffer.is_empty() {
let step_size = (buffer.len() / num_channels).min(in_buffer.len() / 2);
let step_buffer = &mut in_buffer[..step_size * 2];
callback(step_buffer);
for index in 0..step_size {
buffer[index * num_channels + 0] = step_buffer[index * 2 + 0];
buffer[index * num_channels + 1] = step_buffer[index * 2 + 1];
}
buffer = &mut buffer[step_size * num_channels..];
}
}
let stream = if sample_format == cpal::SampleFormat::F32 {
if num_channels == 2 {
device.build_output_stream(
&config,
move |buffer: &mut [f32], _| callback(buffer),
move |err| {
dbg!(err);
},
None,
)?
} else if num_channels == 1 {
device.build_output_stream(
&config,
move |buffer: &mut [f32], _| stereo_to_mono(buffer, &mut callback),
move |err| {
dbg!(err);
},
None,
)?
} else {
device.build_output_stream(
&config,
move |buffer: &mut [f32], _| {
stereo_to_surround(buffer, num_channels as usize, &mut callback)
}, },
move |err| { move |err| {
dbg!(err); dbg!(err);
}, },
None, None,
)? )?
}
} else {
if num_channels == 2 {
device.build_output_stream(
&config,
move |buffer: &mut [i16], _| f32_to_i16(buffer, &mut callback),
move |err| {
dbg!(err);
},
None,
)?
} else if num_channels == 1 {
device.build_output_stream(
&config,
move |buffer: &mut [i16], _| {
f32_to_i16(buffer, &mut |b| stereo_to_mono(b, &mut callback))
},
move |err| {
dbg!(err);
},
None,
)?
} else {
device.build_output_stream(
&config,
move |buffer: &mut [i16], _| {
f32_to_i16(buffer, &mut |b| {
stereo_to_surround(b, num_channels as usize, &mut callback)
})
},
move |err| {
dbg!(err);
},
None,
)?
}
}; };
Ok(Uw8Sound { stream, tx }) Ok(Uw8Sound { stream, tx })

View File

@@ -1,789 +0,0 @@
{
"scope": "source.curlywasm",
"completions": [
// Keywords
{
"trigger": "if",
"contents": "if ${1:condition} {\n\t${2:// Your start code here}\n}",
"details": "if (condition) { block }",
"kind": "keyword"
},
{
"trigger": "else",
"contents": "else {\n\t${1:// Your start code here}\n}",
"details": "else { block }",
"kind": "keyword"
},
{
"trigger": "loop",
"contents": "loop ${1:label} {\n\t${2:// Your start code here}\n}",
"details": "loop label { block }",
"kind": "keyword"
},
{
"trigger": "fn",
"contents": "fn ${1:name}(${2:params}) {\n\t${3:// Your start code here}\n}",
"details": "fn name(params) [-> return_type] { block }",
"kind": "keyword"
},
{
"trigger": "let",
"contents": "let ${1:variable} = ${2:value};",
"details": "let variable[: type] = value;",
"kind": "keyword"
},
{
"trigger": "const",
"contents": "const ${1:name} = ${2:value};",
"details": "const name[: type] = value;",
"kind": "keyword"
},
{
"trigger": "branch_if",
"contents": "branch_if ${1:condition}: ${2:label};",
"details": "branch_if (condition): label;",
"kind": "keyword"
},
{
"trigger": "global",
"contents": "global mut ${1:name} = ${2:value};",
"details": "global mut name[: type] = value;",
"kind": "keyword"
},
{
"trigger": "import",
"contents": "import \"${1:module.name}\" ${2:|memory(min_pages)|global var_name: type|fn fun_name(param_types) [-> return_type]};",
"details": "import \"module.name\" memory(min_pages); import \"module.name\" global var_name: type; import \"module.name\" fn fun_name(param_types) [-> return_type];",
"kind": "keyword"
},
{
"trigger": "include",
"contents": "include \"${1:path}\"",
"details": "include \"path\"",
"kind": "keyword"
},
{
"trigger": "api",
"contents": "include \"../include/microw8-api.cwa\"",
"details": "include \"path\"",
"kind": "keyword"
},
{
"trigger": "common",
"contents": "include \"../include/common.cwa\"",
"details": "include \"path\"",
"kind": "keyword"
},
{
"trigger": "export",
"contents": "export fn ${1:name}(${2:params}) ${3:-> ${4:return_type}} { ${5:block} }",
"details": "export fn name(params) [-> return_type] { block }",
"kind": "keyword"
},
{
"trigger": "block",
"contents": "block ${1:label} {\n\t${2://content}\n}",
"details": "block label { block }",
"kind": "keyword"
},
{
"trigger": "branch",
"contents": "branch ${1:label};",
"details": "branch label;",
"kind": "keyword"
},
{
"trigger": "data",
"contents": "data ${1:address} {\n\t${2:type}(\n\t\t${3:values}\n\t)\n}",
"details": "data address { content }",
"kind": "keyword"
},
{
"trigger": "mut",
"contents": "mut",
"details": "Mutable variable modifier",
"kind": "storage.modifier"
},
{
"trigger": "lazy",
"contents": "lazy",
"details": "Lazy variable modifier",
"kind": "storage.modifier"
},
{
"trigger": "inline",
"contents": "inline",
"details": "Inline variable modifier",
"kind": "storage.modifier"
},
// Operators
{
"trigger": "as",
"contents": "as",
"details": "Type cast",
"kind": "keyword.operator.type"
},
{
"trigger": "?",
"contents": "?",
"details": "Load byte",
"kind": "keyword.operator.memory"
},
{
"trigger": "!",
"contents": "!",
"details": "Load word",
"kind": "keyword.operator.memory"
},
{
"trigger": "$",
"contents": "$",
"details": "Load float",
"kind": "keyword.operator.memory"
},
{
"trigger": "<|",
"contents": "<|",
"details": "Take first (sequencing operator)",
"kind": "keyword.operator.misc"
},
// Memory access intrinsic functions (i32 and f32 only)
{
"trigger": "i32.load",
"contents": "i32.load(${1:base}, ${2:offset}${3:, ${4:align}})",
"details": "i32.load(base: i32, offset: i32 = 0, align: i32 = 2) -> i32: Load 32-bit word",
"kind": "support.function"
},
{
"trigger": "i32.load8_u",
"contents": "i32.load8_u(${1:base}, ${2:offset}${3:, ${4:align}})",
"details": "i32.load8_u(base: i32, offset: i32 = 0, align: i32 = 0) -> i32: Load 8-bit unsigned",
"kind": "support.function"
},
{
"trigger": "i32.load8_s",
"contents": "i32.load8_s(${1:base}, ${2:offset}${3:, ${4:align}})",
"details": "i32.load8_s(base: i32, offset: i32 = 0, align: i32 = 0) -> i32: Load 8-bit signed",
"kind": "support.function"
},
{
"trigger": "i32.load16_u",
"contents": "i32.load16_u(${1:base}, ${2:offset}${3:, ${4:align}})",
"details": "i32.load16_u(base: i32, offset: i32 = 0, align: i32 = 1) -> i32: Load 16-bit unsigned",
"kind": "support.function"
},
{
"trigger": "i32.load16_s",
"contents": "i32.load16_s(${1:base}, ${2:offset}${3:, ${4:align}})",
"details": "i32.load16_s(base: i32, offset: i32 = 0, align: i32 = 1) -> i32: Load 16-bit signed",
"kind": "support.function"
},
{
"trigger": "i32.store",
"contents": "i32.store(${1:value}, ${2:base}, ${3:offset}${4:, ${5:align}});",
"details": "i32.store(value: i32, base: i32, offset: i32 = 0, align: i32 = 2): Store 32-bit word",
"kind": "support.function"
},
{
"trigger": "i32.store8",
"contents": "i32.store8(${1:value}, ${2:base}, ${3:offset}${4:, ${5:align}});",
"details": "i32.store8(value: i32, base: i32, offset: i32 = 0, align: i32 = 0): Store 8-bit",
"kind": "support.function"
},
{
"trigger": "i32.store16",
"contents": "i32.store16(${1:value}, ${2:base}, ${3:offset}${4:, ${5:align}});",
"details": "i32.store16(value: i32, base: i32, offset: i32 = 0, align: i32 = 1): Store 16-bit",
"kind": "support.function"
},
{
"trigger": "f32.load",
"contents": "f32.load(${1:base}, ${2:offset}${3:, ${4:align}})",
"details": "f32.load(base: i32, offset: i32 = 0, align: i32 = 2) -> f32: Load 32-bit float",
"kind": "support.function"
},
{
"trigger": "f32.store",
"contents": "f32.store(${1:value}, ${2:base}, ${3:offset}${4:, ${5:align}});",
"details": "f32.store(value: f32, base: i32, offset: i32 = 0, align: i32 = 2): Store 32-bit float",
"kind": "support.function"
},
// API functions
{
"trigger": "sin",
"contents": "sin(${1:x})",
"details": "sin(x: f32) -> f32: Returns the sine of x (radians)",
"kind": "support.function"
},
{
"trigger": "cos",
"contents": "cos(${1:x})",
"details": "cos(x: f32) -> f32: Returns the cosine of x (radians)",
"kind": "support.function"
},
{
"trigger": "tan",
"contents": "tan(${1:x})",
"details": "tan(x: f32) -> f32: Returns the tangent of x (radians)",
"kind": "support.function"
},
{
"trigger": "asin",
"contents": "asin(${1:x})",
"details": "asin(x: f32) -> f32: Returns the arcsine of x (radians)",
"kind": "support.function"
},
{
"trigger": "acos",
"contents": "acos(${1:x})",
"details": "acos(x: f32) -> f32: Returns the arccosine of x (radians)",
"kind": "support.function"
},
{
"trigger": "atan",
"contents": "atan(${1:x})",
"details": "atan(x: f32) -> f32: Returns the arctangent of x (radians)",
"kind": "support.function"
},
{
"trigger": "atan2",
"contents": "atan2(${1:y}, ${2:x})",
"details": "atan2(y: f32, x: f32) -> f32: Returns the angle in radians of the point (x, y)",
"kind": "support.function"
},
{
"trigger": "pow",
"contents": "pow(${1:x}, ${2:y})",
"details": "pow(x: f32, y: f32) -> f32: Returns x raised to the power of y",
"kind": "support.function"
},
{
"trigger": "log",
"contents": "log(${1:x})",
"details": "log(x: f32) -> f32: Returns the natural logarithm of x",
"kind": "support.function"
},
{
"trigger": "fmod",
"contents": "fmod(${1:x}, ${2:y})",
"details": "fmod(x: f32, y: f32) -> f32: Returns the remainder of x/y",
"kind": "support.function"
},
{
"trigger": "random",
"contents": "random()",
"details": "random() -> i32: Returns a random 32-bit integer",
"kind": "support.function"
},
{
"trigger": "randomf",
"contents": "randomf()",
"details": "randomf() -> f32: Returns a random float [0, 1)",
"kind": "support.function"
},
{
"trigger": "randomSeed",
"contents": "randomSeed(${1:seed});",
"details": "randomSeed(seed: i32): Seeds the random number generator",
"kind": "support.function"
},
{
"trigger": "cls",
"contents": "cls(${1:color});",
"details": "cls(color: i32): Clears the screen with the given color, resets cursor to 0,0, disables graphics mode",
"kind": "support.function"
},
{
"trigger": "setPixel",
"contents": "setPixel(${1:x}, ${2:y}, ${3:color});",
"details": "setPixel(x: i32, y: i32, color: i32): Sets the pixel at (x, y) to color",
"kind": "support.function"
},
{
"trigger": "getPixel",
"contents": "getPixel(${1:x}, ${2:y})",
"details": "getPixel(x: i32, y: i32) -> i32: Gets the color of the pixel at (x, y) (returns 0 if out of bounds)",
"kind": "support.function"
},
{
"trigger": "hline",
"contents": "hline(${1:left}, ${2:right}, ${3:y}, ${4:color});",
"details": "hline(left: i32, right: i32, y: i32, color: i32): Fills the horizontal line [left, right), y",
"kind": "support.function"
},
{
"trigger": "rectangle",
"contents": "rectangle(${1:x}, ${2:y}, ${3:width}, ${4:height}, ${5:color});",
"details": "rectangle(x: f32, y: f32, w: f32, h: f32, color: i32): Fills the rectangle x,y - x+w,y+h",
"kind": "support.function"
},
{
"trigger": "circle",
"contents": "circle(${1:cx}, ${2:cy}, ${3:radius}, ${4:color});",
"details": "circle(cx: f32, cy: f32, radius: f32, color: i32): Fills the circle at cx, cy with radius",
"kind": "support.function"
},
{
"trigger": "line",
"contents": "line(${1:x1}, ${2:y1}, ${3:x2}, ${4:y2}, ${5:color});",
"details": "line(x1: f32, y1: f32, x2: f32, y2: f32, color: i32): Draws a line from x1,y1 to x2,y2",
"kind": "support.function"
},
{
"trigger": "time",
"contents": "time()",
"details": "time() -> f32: Returns the current time in seconds",
"kind": "support.function"
},
{
"trigger": "isButtonPressed",
"contents": "isButtonPressed(${1:button})",
"details": "isButtonPressed(button: i32) -> bool: Checks if a button is pressed this frame (returns i32)",
"kind": "support.function"
},
{
"trigger": "isButtonTriggered",
"contents": "isButtonTriggered(${1:button})",
"details": "isButtonTriggered(button: i32) -> bool: Checks if a button is newly pressed this frame (returns i32)",
"kind": "support.function"
},
{
"trigger": "printChar",
"contents": "printChar(${1:char});",
"details": "printChar(char: i32): Prints the character in the lower 8 bits",
"kind": "support.function"
},
{
"trigger": "printString",
"contents": "printString(${1:ptr});",
"details": "printString(ptr: i32): Prints the zero-terminated string at memory address ptr",
"kind": "support.function"
},
{
"trigger": "printInt",
"contents": "printInt(${1:value});",
"details": "printInt(value: i32): Prints an integer as a signed decimal number",
"kind": "support.function"
},
{
"trigger": "setTextColor",
"contents": "setTextColor(${1:color});",
"details": "setTextColor(color: i32): Sets the text color",
"kind": "support.function"
},
{
"trigger": "setBackgroundColor",
"contents": "setBackgroundColor(${1:color});",
"details": "setBackgroundColor(color: i32): Sets the background color",
"kind": "support.function"
},
{
"trigger": "setCursorPosition",
"contents": "setCursorPosition(${1:x}, ${2:y});",
"details": "setCursorPosition(x: i32, y: i32): Sets the cursor position (character or pixel coords depending on mode)",
"kind": "support.function"
},
{
"trigger": "rectangleOutline",
"contents": "rectangleOutline(${1:x}, ${2:y}, ${3:width}, ${4:height}, ${5:color});",
"details": "rectangleOutline(x: f32, y: f32, w: f32, h: f32, color: i32): Draws a rectangle outline",
"kind": "support.function"
},
{
"trigger": "circleOutline",
"contents": "circleOutline(${1:cx}, ${2:cy}, ${3:radius}, ${4:color});",
"details": "circleOutline(cx: f32, cy: f32, radius: f32, color: i32): Draws a circle outline",
"kind": "support.function"
},
{
"trigger": "exp",
"contents": "exp(${1:x})",
"details": "exp(x: f32) -> f32: Returns e raised to the power of x",
"kind": "support.function"
},
{
"trigger": "playNote",
"contents": "playNote(${1:channel}, ${2:note}${3:, ${4:duration}${5:, ${6:volume}}});",
"details": "playNote(channel: i32, note: i32): Triggers a note on the given channel (note 0 stops, 128-255 triggers attack+release)",
"kind": "support.function"
},
{
"trigger": "sndGes",
"contents": "sndGes(${1:sampleIndex})",
"details": "sndGes(sampleIndex: i32) -> f32: Sound generator function (uses 32 bytes at 0x50 by default)",
"kind": "support.function"
},
{
"trigger": "blitSprite",
"contents": "blitSprite(${1:spriteData}, ${2:size}, ${3:x}, ${4:y}, ${5:control});",
"details": "blitSprite(spriteData: i32, size: i32, x: i32, y: i32, control: i32): Copies sprite data to screen",
"kind": "support.function"
},
{
"trigger": "grabSprite",
"contents": "grabSprite(${1:spriteData}, ${2:size}, ${3:x}, ${4:y}, ${5:control});",
"details": "grabSprite(spriteData: i32, size: i32, x: i32, y: i32, control: i32): Copies screen data to sprite",
"kind": "support.function"
},
// Built-in functions (or commonly used intrinsics)
{
"trigger": "start",
"contents": "export fn start() {\n\t${1:// Your start code here}\n}",
"details": "export fn start(): Called once after module is loaded",
"kind": "support.function"
},
{
"trigger": "upd",
"contents": "export fn upd() {\n\t${1:// Your update code here}\n}",
"details": "export fn upd(): Called once per frame",
"kind": "support.function"
},
{
"trigger": "memory.fill",
"contents": "memory.fill(${1:dest}, ${2:value}, ${3:size});",
"details": "memory.fill(dest: i32, value: i32, size: i32): Fills a memory area",
"kind": "support.function"
},
{
"trigger": "memory.copy",
"contents": "memory.copy(${1:dest}, ${2:src}, ${3:size});",
"details": "memory.copy(dest: i32, src: i32, size: i32): Copies a memory block",
"kind": "support.function"
},
{
"trigger": "sqrt",
"contents": "sqrt(${1:x})",
"details": "sqrt(x: f32) -> f32: Returns the square root of x",
"kind": "support.function"
},
{
"trigger": "min",
"contents": "min(${1:x}, ${2:y})",
"details": "min(x: f32, y: f32) -> f32: Returns the minimum of x and y",
"kind": "support.function"
},
{
"trigger": "max",
"contents": "max(${1:x}, ${2:y})",
"details": "max(x: f32, y: f32) -> f32: Returns the maximum of x and y",
"kind": "support.function"
},
{
"trigger": "ceil",
"contents": "ceil(${1:x})",
"details": "ceil(x: f32) -> f32: Returns the smallest integer >= x",
"kind": "support.function"
},
{
"trigger": "floor",
"contents": "floor(${1:x})",
"details": "floor(x: f32) -> f32: Returns the largest integer <= x",
"kind": "support.function"
},
{
"trigger": "trunc",
"contents": "trunc(${1:x})",
"details": "trunc(x: f32) -> f32: Returns the nearest integer to x toward zero",
"kind": "support.function"
},
{
"trigger": "nearest",
"contents": "nearest(${1:x})",
"details": "nearest(x: f32) -> f32: Returns the nearest integer to x (round to nearest, ties to even)",
"kind": "support.function"
},
{
"trigger": "abs",
"contents": "abs(${1:x})",
"details": "abs(x: f32) -> f32: Returns the absolute value of x",
"kind": "support.function"
},
{
"trigger": "copysign",
"contents": "copysign(${1:x}, ${2:y})",
"details": "copysign(x: f32, y: f32) -> f32: Returns x with the sign of y",
"kind": "support.function"
},
{
"trigger": "select",
"contents": "select(${1:a}, ${2:b}, ${3:c})",
"details": "select(a: f32, b: f32, c: f32) -> f32: Selects b if a is non-zero, otherwise selects c (equivalent to a != 0 ? b : c)",
"kind": "support.function"
},
{
"trigger": "i32.clz",
"contents": "i32.clz(${1:value})",
"details": "i32.clz(value: i32) -> i32: Count Leading Zeros",
"kind": "support.function"
},
{
"trigger": "i32.ctz",
"contents": "i32.ctz(${1:value})",
"details": "i32.ctz(value: i32) -> i32: Count Trailing Zeros",
"kind": "support.function"
},
{
"trigger": "i32.popcnt",
"contents": "i32.popcnt(${1:value})",
"details": "i32.popcnt(value: i32) -> i32: Population Count (number of set bits)",
"kind": "support.function"
},
{
"trigger": "i32.bswap",
"contents": "i32.bswap(${1:value})",
"details": "i32.bswap(value: i32) -> i32: Byte Swap",
"kind": "support.function"
},
{
"trigger": "i32.trunc_sat_f32_u",
"contents": "i32.trunc_sat_f32_u(${1:value})",
"details": "i32.trunc_sat_f32_u(value: f32) -> i32: Truncate f32 to i32 unsigned, saturating",
"kind": "support.function"
},
{
"trigger": "i32.trunc_sat_f32_s",
"contents": "i32.trunc_sat_f32_s(${1:value})",
"details": "i32.trunc_sat_f32_s(value: f32) -> i32: Truncate f32 to i32 signed, saturating",
"kind": "support.function"
},
// Added Constants
{
"trigger": "TIME_MS",
"contents": "TIME_MS",
"details": "0x40 Time since module start in ms",
"kind": "constant"
},
{
"trigger": "GAMEPAD",
"contents": "GAMEPAD",
"details": "0x44 Gamepad state",
"kind": "constant"
},
{
"trigger": "FRAMEBUFFER",
"contents": "FRAMEBUFFER",
"details": "0x78 Frame buffer address",
"kind": "constant"
},
{
"trigger": "PALETTE",
"contents": "PALETTE",
"details": "0x13000 Palette address",
"kind": "constant"
},
{
"trigger": "FONT",
"contents": "FONT",
"details": "0x13400 Font address",
"kind": "constant"
},
{
"trigger": "USER_MEM",
"contents": "USER_MEM",
"details": "0x14000 Start of general user memory",
"kind": "constant"
},
{
"trigger": "BUTTON_UP",
"contents": "BUTTON_UP",
"details": "0x00 Gamepad button Up",
"kind": "constant"
},
{
"trigger": "BUTTON_DOWN",
"contents": "BUTTON_DOWN",
"details": "0x01 Gamepad button Down",
"kind": "constant"
},
{
"trigger": "BUTTON_LEFT",
"contents": "BUTTON_LEFT",
"details": "0x02 Gamepad button Left",
"kind": "constant"
},
{
"trigger": "BUTTON_RIGHT",
"contents": "BUTTON_RIGHT",
"details": "0x03 Gamepad button Right",
"kind": "constant"
},
{
"trigger": "BUTTON_A",
"contents": "BUTTON_A",
"details": "0x04 Gamepad button A (Z on keyboard)",
"kind": "constant"
},
{
"trigger": "BUTTON_B",
"contents": "BUTTON_B",
"details": "0x05 Gamepad button B (X on keyboard)",
"kind": "constant"
},
{
"trigger": "BUTTON_X",
"contents": "BUTTON_X",
"details": "0x06 Gamepad button X (A on keyboard)",
"kind": "constant"
},
{
"trigger": "BUTTON_Y",
"contents": "BUTTON_Y",
"details": "0x07 Gamepad button Y (S on keyboard)",
"kind": "constant"
},
{
"trigger": "PI",
"contents": "PI",
"details": "Mathematical constant π",
"kind": "constant"
},
{
"trigger": "RAD",
"contents": "RAD",
"details": "One radian value",
"kind": "constant"
},
{
"trigger": "SCR_X",
"contents": "SCR_X",
"details": "Screen width in pixels",
"kind": "constant"
},
{
"trigger": "SCR_Y",
"contents": "SCR_Y",
"details": "Screen height in pixels",
"kind": "constant"
},
{
"trigger": "SCR_W",
"contents": "SCR_W",
"details": "Screen width in chars (40)",
"kind": "constant"
},
{
"trigger": "SCR_H",
"contents": "SCR_H",
"details": "Screen height in chars (30)",
"kind": "constant"
},
{
"trigger": "CENTER_X",
"contents": "CENTER_X",
"details": "X-coordinate of the screen center (160)",
"kind": "constant"
},
{
"trigger": "CENTER_Y",
"contents": "CENTER_Y",
"details": "Y-coordinate of the screen center (120)",
"kind": "constant"
},
{
"trigger": "SCR_SIZE",
"contents": "SCR_SIZE",
"details": "Total screen size in pixels (76800)",
"kind": "constant"
},
{
"trigger": "MEM_END",
"contents": "MEM_END",
"details": "End of available memory",
"kind": "constant"
},
{
"trigger": "CUSTOM_FONT",
"contents": "CUSTOM_FONT",
"details": "Address for a custom font",
"kind": "constant"
},
{
"trigger": "COLOR_BLACK",
"contents": "COLOR_BLACK",
"details": "0x00 Black",
"kind": "constant"
},
{
"trigger": "COLOR_DARK_BLUE",
"contents": "COLOR_DARK_BLUE",
"details": "0x17 Dark Blue",
"kind": "constant"
},
{
"trigger": "COLOR_DARK_PURPLE",
"contents": "COLOR_DARK_PURPLE",
"details": "0x27 Dark Purple",
"kind": "constant"
},
{
"trigger": "COLOR_CYAN",
"contents": "COLOR_CYAN",
"details": "0x37 Cyan",
"kind": "constant"
},
{
"trigger": "COLOR_BRIGHT_RED",
"contents": "COLOR_BRIGHT_RED",
"details": "0x47 Bright Red",
"kind": "constant"
},
{
"trigger": "COLOR_MAGENTA",
"contents": "COLOR_MAGENTA",
"details": "0x57 Magenta",
"kind": "constant"
},
{
"trigger": "COLOR_ORANGE",
"contents": "COLOR_ORANGE",
"details": "0x58 Orange",
"kind": "constant"
},
{
"trigger": "COLOR_BRIGHT_YELLOW",
"contents": "COLOR_BRIGHT_YELLOW",
"details": "0x67 Bright Yellow",
"kind": "constant"
},
{
"trigger": "COLOR_MEDIUM_GREY",
"contents": "COLOR_MEDIUM_GREY",
"details": "0x78 Medium Grey",
"kind": "constant"
},
{
"trigger": "COLOR_LIGHT_GREY",
"contents": "COLOR_LIGHT_GREY",
"details": "0x7C Light Grey",
"kind": "constant"
},
{
"trigger": "COLOR_WHITE",
"contents": "COLOR_WHITE",
"details": "0xF8 White",
"kind": "constant"
},
{
"trigger": "COLOR_BRIGHT_GREEN",
"contents": "COLOR_BRIGHT_GREEN",
"details": "0x87 Bright Green",
"kind": "constant"
},
{
"trigger": "COLOR_BROWN",
"contents": "COLOR_BROWN",
"details": "0xD4 Brown",
"kind": "constant"
},
{
"trigger": "COLOR_DARK_GREY",
"contents": "COLOR_DARK_GREY",
"details": "0xE1 Dark Grey",
"kind": "constant"
}
]
}

View File

@@ -1,234 +0,0 @@
%YAML 1.2
---
# ==========================================================
# http://www.sublimetext.com/docs/syntax.html
# created by: zbyti & various AI
# ==========================================================
# For best results, use with Rust-themed color schemes like:
# - "RustEnhanced"
# - "Atomized"
# - "Solarized Rust"
# ==========================================================
name: CurlyWASM
file_extensions: [cwa]
scope: source.curlywasm
contexts:
main:
# Comments
- match: /\*
scope: comment.block.curlywasm
push: block_comment
- match: //
scope: comment.line.curlywasm
push: line_comment
# Module system
- match: \b(import|include|export)\b
scope: keyword.control.import.curlywasm
# Declarations and definitions
- match: \b(fn)\b
scope: keyword.declaration.function.curlywasm
- match: \b(const)\b
scope: storage.modifier.const.curlywasm
- match: \b(global|mut|let|lazy|inline)\b
scope: storage.modifier.curlywasm
# Control flow
- match: \b(if|else|block|loop|branch|branch_if)\b
scope: keyword.control.flow.curlywasm
# Type conversion
- match: \b(as)\b
scope: keyword.operator.type.curlywasm
# WASM memory access operators
- match: \b(load|store)\b
scope: keyword.operator.memory.curlywasm
# API functions
- match: \b(sin|cos|tan|asin|acos|atan|atan2|pow|log|fmod|random|randomf|randomSeed|cls|setPixel|getPixel|hline|rectangle|circle|line|time|isButtonPressed|isButtonTriggered|printChar|printString|printInt|setTextColor|setBackgroundColor|setCursorPosition|rectangleOutline|circleOutline|exp|playNote|sndGes|blitSprite|grabSprite)\b
scope: support.function.curlywasm
# Built-in functions
- match: \b(start|upd|sqrt|min|max|ceil|floor|trunc|nearest|abs|copysign|select)\b
scope: support.function.curlywasm
# Data blocks - Match 'data {' together and push context
- match: \b(data)\s*(\{)
captures:
1: storage.type.data.curlywasm
2: punctuation.section.block.begin.curlywasm
push: data_content
# Base types
- match: \b(i8|i16|i32|i64|f32|f64)\b
scope: storage.type.primitive.curlywasm
# Memory access operators
- match: (\?|\$|\!)
scope: keyword.operator.memory.curlywasm
# Operators
- match: (->)
scope: keyword.operator.arrow.curlywasm
# Assignment operators
- match: (=|:=|\+=|-=|\*=|/=|%=|&=|\|=|\^=|#/=)
scope: keyword.operator.assignment.curlywasm
# Arithmetic operators
- match: (\+|-|\*|/|%|#/|#%)
scope: keyword.operator.arithmetic.curlywasm
# Bitwise operators
- match: (\&|\||\^|<<|>>|#>>)
scope: keyword.operator.bitwise.curlywasm
# Comparison operators
- match: (<|>|<=|>=|#<|#<=|#>|#>=|==|!=)
scope: keyword.operator.comparison.curlywasm
# Other operators
- match: (<\|)
scope: keyword.operator.misc.curlywasm
# Numeric literals
- match: \b(0x[0-9a-fA-F]+)\b
scope: constant.numeric.hex.curlywasm
- match: '\b\d+(_f)\b'
scope: constant.numeric.float.curlywasm
- match: \b0x[0-9a-fA-F]+_f\b
scope: constant.numeric.float.curlywasm
- match: \b([0-9]+\.[0-9]+)\b
scope: constant.numeric.float.curlywasm
- match: \b([0-9]+)\b
scope: constant.numeric.integer.curlywasm
# String literals
- match: \"
scope: punctuation.definition.string.begin.curlywasm
push: double_quoted_string
- match: \'
scope: punctuation.definition.string.begin.curlywasm
push: single_quoted_string
# Function calls
- match: \b([a-zA-Z_][a-zA-Z0-9_]*)\s*\(
captures:
1: entity.name.function.call.curlywasm
# Function declarations
- match: \bfn\s+([a-zA-Z_][a-zA-Z0-9_]*)\b
captures:
1: entity.name.function.declaration.curlywasm
# Constants (Upper case convention)
- match: \b([A-Z_][A-Z0-9_]*)\b
scope: constant.other.curlywasm
# Variables (Lower case convention)
- match: \b([a-z_][a-zA-Z0-9_]*)\b
scope: variable.other.curlywasm
# Punctuation
- match: \{
scope: punctuation.section.block.begin.curlywasm
- match: \}
scope: punctuation.section.block.end.curlywasm
- match: \(
scope: punctuation.section.group.begin.curlywasm
- match: \)
scope: punctuation.section.group.end.curlywasm
- match: \[
scope: punctuation.section.brackets.begin.curlywasm
- match: \]
scope: punctuation.section.brackets.end.curlywasm
- match: ;
scope: punctuation.terminator.curlywasm
- match: \,
scope: punctuation.separator.curlywasm
- match: ':'
scope: punctuation.separator.type.curlywasm
# Context for /* ... */ block comments
block_comment:
- meta_scope: comment.block.curlywasm
- match: \*/
scope: punctuation.definition.comment.end.curlywasm
pop: true
# Context for // ... line comments
line_comment:
- meta_scope: comment.line.double-slash.curlywasm
- match: $ # Pop at the end of the line
pop: true
# Context for "..." strings
double_quoted_string:
- meta_scope: string.quoted.double.curlywasm
- match: \"
scope: punctuation.definition.string.end.curlywasm
pop: true
- match: \\. # Escape sequences
scope: constant.character.escape.curlywasm
# Context for '...' strings
single_quoted_string:
- meta_scope: string.quoted.single.curlywasm
- match: \'
scope: punctuation.definition.string.end.curlywasm
pop: true
- match: \\. # Escape sequences
scope: constant.character.escape.curlywasm
# Context for the content inside data { ... }
data_content:
- meta_scope: meta.data.content.curlywasm
# Match the closing brace to pop the context
- match: \}
scope: punctuation.section.block.end.curlywasm
pop: true
# Include rules for literals within the data block
- include: literals
# Specific types/keywords allowed inside data blocks
- match: \b(i8|i16|i32|i64|f32|f64)\b
scope: storage.type.primitive.curlywasm
- match: \b(file)\b
scope: keyword.control.curlywasm
# Punctuation inside data blocks
- match: \(
scope: punctuation.section.group.begin.curlywasm
- match: \)
scope: punctuation.section.group.end.curlywasm
- match: \,
scope: punctuation.separator.curlywasm
# Potentially allow comments inside data blocks
- include: block_comment
- include: line_comment
# Reusable patterns for literals (used via include)
literals:
# Numeric literals
- match: \b(0x[0-9a-fA-F]+)\b
scope: constant.numeric.hex.curlywasm
- match: '\b\d+(_f)\b'
scope: constant.numeric.float.curlywasm
- match: \b([0-9]+\.[0-9]+)\b
scope: constant.numeric.float.curlywasm
- match: \b([0-9]+)\b
scope: constant.numeric.integer.curlywasm
# String literals
- match: \"
scope: punctuation.definition.string.begin.curlywasm
push: double_quoted_string
- match: \'
scope: punctuation.definition.string.begin.curlywasm
push: single_quoted_string

View File

@@ -1,11 +0,0 @@
<snippet>
<content><![CDATA[
data ${1:address} {
${2:type}(
${3:values}
)
}
]]></content>
<tabTrigger>datatype</tabTrigger>
<description>Data block definition</description>
</snippet>

View File

@@ -1,9 +0,0 @@
<snippet>
<content><![CDATA[
export fn ${1:name}(${2:params}) -> ${3:return_type} {
${4:// Function body}
}
]]></content>
<tabTrigger>fnexport</tabTrigger>
<description>Exported function definition</description>
</snippet>

View File

@@ -1,11 +0,0 @@
<snippet>
<content><![CDATA[
if ${1:condition} {
${2:// Your if code here}
} else {
${3:// Your else code here}
}
]]></content>
<tabTrigger>ifelse</tabTrigger>
<description>If-else statement</description>
</snippet>

View File

@@ -1,7 +0,0 @@
<snippet>
<content><![CDATA[
let inline ${1:variable} = ${2:value};
]]></content>
<tabTrigger>letinline</tabTrigger>
<description>Lazy variable declaration</description>
</snippet>

View File

@@ -1,7 +0,0 @@
<snippet>
<content><![CDATA[
let lazy ${1:variable} = ${2:value};
]]></content>
<tabTrigger>letlazy</tabTrigger>
<description>Lazy variable declaration</description>
</snippet>

View File

@@ -1,11 +0,0 @@
<snippet>
<content><![CDATA[
${1:label} = 0;
loop ${1:label} {
${2:// Your loop code here}
branch_if ${3:condition}: ${1:label};
}
]]></content>
<tabTrigger>loopbr</tabTrigger>
<description>Loop with branch_if</description>
</snippet>

274
uw8-tool/Cargo.lock generated
View File

@@ -4,27 +4,21 @@ version = 3
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.81" version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.2.0" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.92" version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]] [[package]]
name = "cdivsufsort" name = "cdivsufsort"
@@ -37,41 +31,38 @@ dependencies = [
] ]
[[package]] [[package]]
name = "crossbeam-channel" name = "cfg-if"
version = "0.5.12" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
dependencies = [ dependencies = [
"cfg-if",
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.19" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
name = "gimli"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
dependencies = [ dependencies = [
"fallible-iterator", "cfg-if",
"indexmap 1.9.3", "lazy_static",
"stable_deref_trait", ]
[[package]]
name = "form_urlencoded"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
dependencies = [
"percent-encoding",
] ]
[[package]] [[package]]
@@ -80,12 +71,6 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.3.3" version = "0.3.3"
@@ -102,25 +87,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]] [[package]]
name = "indexmap" name = "idna"
version = "1.9.3" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
dependencies = [ dependencies = [
"autocfg", "unicode-bidi",
"hashbrown 0.12.3", "unicode-normalization",
] ]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.2.6" version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [ dependencies = [
"equivalent", "autocfg",
"hashbrown 0.14.3", "hashbrown",
] ]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "leb128" name = "leb128"
version = "0.2.5" version = "0.2.5"
@@ -135,36 +126,46 @@ checksum = "478ee9e62aaeaf5b140bd4138753d1f109765488581444218d3ddda43234f3e8"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.153" version = "0.2.112"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.21" version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.18" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
[[package]] [[package]]
name = "pbr" name = "pbr"
version = "1.1.1" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5827dfa0d69b6c92493d6c38e633bbaa5937c153d0d7c28bf12313f8c6d514" checksum = "ff5751d87f7c00ae6403eb1fcbba229b9c76c9a30de8c1cf87182177b168cea2"
dependencies = [ dependencies = [
"crossbeam-channel", "crossbeam-channel",
"libc", "libc",
"time",
"winapi", "winapi",
] ]
[[package]]
name = "percent-encoding"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]] [[package]]
name = "pico-args" name = "pico-args"
version = "0.5.0" version = "0.5.0"
@@ -173,18 +174,18 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.79" version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
dependencies = [ dependencies = [
"unicode-ident", "unicode-xid",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.35" version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -198,71 +199,89 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "semver"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "1.0.84"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" checksum = "ecb2e6da8ee5eb9a61068762a32fa9619cc591ceb055b3687f4cd4051ec2e06b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"unicode-ident", "unicode-xid",
]
[[package]]
name = "syn"
version = "2.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
] ]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.58" version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.58" version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.58", "syn",
] ]
[[package]] [[package]]
name = "unicode-ident" name = "time"
version = "1.0.12" version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi",
"winapi",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "unicode-bidi"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]] [[package]]
name = "unicode-segmentation" name = "unicode-segmentation"
version = "1.11.0" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]] [[package]]
name = "upkr" name = "upkr"
@@ -275,6 +294,17 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "url"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]] [[package]]
name = "uw8-tool" name = "uw8-tool"
version = "0.1.0" version = "0.1.0"
@@ -284,24 +314,22 @@ dependencies = [
"pico-args", "pico-args",
"upkr", "upkr",
"walrus", "walrus",
"wasm-encoder 0.201.0", "wasm-encoder",
"wasmparser 0.201.0", "wasmparser 0.99.0",
] ]
[[package]] [[package]]
name = "walrus" name = "walrus"
version = "0.20.3" version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c03529cd0c4400a2449f640d2f27cd1b48c3065226d15e26d98e4429ab0adb7" checksum = "4eb08e48cde54c05f363d984bb54ce374f49e242def9468d2e1b6c2372d291f8"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"gimli",
"id-arena", "id-arena",
"leb128", "leb128",
"log", "log",
"walrus-macro", "walrus-macro",
"wasm-encoder 0.29.0", "wasmparser 0.77.0",
"wasmparser 0.80.2",
] ]
[[package]] [[package]]
@@ -313,42 +341,38 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.109", "syn",
] ]
[[package]] [[package]]
name = "wasm-encoder" name = "wasi"
version = "0.29.0" version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18c41dbd92eaebf3612a39be316540b8377c871cb9bde6b064af962984912881" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
dependencies = [
"leb128",
]
[[package]] [[package]]
name = "wasm-encoder" name = "wasm-encoder"
version = "0.201.0" version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a" checksum = "ef126be0e14bdf355ac1a8b41afc89195289e5c7179f80118e3abddb472f0810"
dependencies = [ dependencies = [
"leb128", "leb128",
] ]
[[package]] [[package]]
name = "wasmparser" name = "wasmparser"
version = "0.80.2" version = "0.77.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "449167e2832691a1bff24cde28d2804e90e09586a448c8e76984792c44334a6b" checksum = "b35c86d22e720a07d954ebbed772d01180501afe7d03d464f413bb5f8914a8d6"
[[package]] [[package]]
name = "wasmparser" name = "wasmparser"
version = "0.201.0" version = "0.99.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84e5df6dba6c0d7fafc63a450f1738451ed7a0b52295d83e868218fa286bf708" checksum = "9ef3b717afc67f848f412d4f02c127dd3e35a0eecd58c684580414df4fde01d3"
dependencies = [ dependencies = [
"bitflags", "indexmap",
"indexmap 2.2.6", "url",
"semver",
] ]
[[package]] [[package]]

View File

@@ -6,9 +6,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
wasmparser = "0.201" wasmparser = "0.99"
wasm-encoder = "0.201" wasm-encoder = "0.22"
walrus = { version = "0.20.3", default-features = false } walrus = "0.19"
anyhow = "1" anyhow = "1"
pico-args = "0.5" pico-args = "0.5"
upkr = { git = "https://github.com/exoticorn/upkr.git", rev = "080db40d0088bbee2bdf3c5c75288ac7853d6b7a" } upkr = { git = "https://github.com/exoticorn/upkr.git", rev = "080db40d0088bbee2bdf3c5c75288ac7853d6b7a" }

View File

@@ -37,7 +37,7 @@ impl BaseModule {
let mut types = vec![]; let mut types = vec![];
let mut type_map = HashMap::new(); let mut type_map = HashMap::new();
for num_params in 0..8 { for num_params in 0..6 {
for num_f32 in 0..=num_params { for num_f32 in 0..=num_params {
for &result in &[None, Some(ValType::I32), Some(ValType::F32)] { for &result in &[None, Some(ValType::I32), Some(ValType::F32)] {
let mut params = vec![]; let mut params = vec![];
@@ -152,14 +152,14 @@ impl BaseModule {
add_function( add_function(
&mut functions, &mut functions,
&type_map, &type_map,
"rectangleOutline", "rectangle_outline",
&[F32, F32, F32, F32, I32], &[F32, F32, F32, F32, I32],
None, None,
); );
add_function( add_function(
&mut functions, &mut functions,
&type_map, &type_map,
"circleOutline", "circle_outline",
&[F32, F32, F32, I32], &[F32, F32, F32, I32],
None, None,
); );
@@ -169,21 +169,6 @@ impl BaseModule {
add_function(&mut functions, &type_map, "playNote", &[I32, I32], None); add_function(&mut functions, &type_map, "playNote", &[I32, I32], None);
add_function(&mut functions, &type_map, "sndGes", &[I32], Some(F32)); add_function(&mut functions, &type_map, "sndGes", &[I32], Some(F32));
add_function(
&mut functions,
&type_map,
"blitSprite",
&[I32, I32, I32, I32, I32],
None,
);
add_function(
&mut functions,
&type_map,
"grabSprite",
&[I32, I32, I32, I32, I32],
None,
);
for i in functions.len()..64 { for i in functions.len()..64 {
add_function( add_function(
&mut functions, &mut functions,

View File

@@ -143,6 +143,7 @@ fn to_val_type(type_: &wasmparser::ValType) -> Result<ValType> {
I64 => ValType::I64, I64 => ValType::I64,
F32 => ValType::F32, F32 => ValType::F32,
F64 => ValType::F64, F64 => ValType::F64,
V128 => ValType::V128,
_ => bail!("Type {:?} isn't a value type", type_), _ => bail!("Type {:?} isn't a value type", type_),
}) })
} }
@@ -490,6 +491,7 @@ impl<'a> ParsedModule<'a> {
element_section.active( element_section.active(
None, None,
&wasm_encoder::ConstExpr::i32_const(element.start_index as i32), &wasm_encoder::ConstExpr::i32_const(element.start_index as i32),
ValType::FuncRef,
wasm_encoder::Elements::Functions(&functions), wasm_encoder::Elements::Functions(&functions),
); );
} }
@@ -535,10 +537,9 @@ fn copy_section(module: &mut wasm_encoder::Module, data: &[u8]) -> Result<()> {
fn read_type_section(reader: TypeSectionReader) -> Result<Vec<base_module::FunctionType>> { fn read_type_section(reader: TypeSectionReader) -> Result<Vec<base_module::FunctionType>> {
let mut function_types = vec![]; let mut function_types = vec![];
for rec_group in reader { for type_def in reader {
for sub_type in rec_group?.into_types() { match type_def? {
match sub_type.composite_type { wasmparser::Type::Func(fnc) => {
wasmparser::CompositeType::Func(fnc) => {
if fnc.results().len() > 1 { if fnc.results().len() > 1 {
bail!("Multi-value not supported"); bail!("Multi-value not supported");
} }
@@ -546,8 +547,6 @@ fn read_type_section(reader: TypeSectionReader) -> Result<Vec<base_module::Funct
let result = to_val_type_vec(fnc.results())?.into_iter().next(); let result = to_val_type_vec(fnc.results())?.into_iter().next();
function_types.push(FunctionType { params, result }); function_types.push(FunctionType { params, result });
} }
_ => bail!("Only function types are supported"),
}
} }
} }
@@ -559,8 +558,8 @@ fn validate_table_section(reader: TableSectionReader) -> Result<()> {
bail!("Only up to one table supported"); bail!("Only up to one table supported");
} }
let table = reader.into_iter().next().unwrap()?; let type_ = reader.into_iter().next().unwrap()?;
if !table.ty.element_type.is_func_ref() { if type_.element_type != wasmparser::ValType::FuncRef {
bail!("Only one funcref table is supported"); bail!("Only one funcref table is supported");
} }
@@ -649,12 +648,9 @@ impl Element {
wasmparser::ElementItems::Functions(funcs_reader) => { wasmparser::ElementItems::Functions(funcs_reader) => {
let start_index = if let wasmparser::ElementKind::Active { let start_index = if let wasmparser::ElementKind::Active {
offset_expr, offset_expr,
table_index, table_index: 0,
} = element.kind } = element.kind
{ {
if table_index.map(|i| i > 0).unwrap_or(false) {
bail!("Only function table with index 0 is supported");
}
let mut init_reader = offset_expr.get_operators_reader(); let mut init_reader = offset_expr.get_operators_reader();
if let wasmparser::Operator::I32Const { value: start_index } = if let wasmparser::Operator::I32Const { value: start_index } =
init_reader.read()? init_reader.read()?
@@ -972,6 +968,244 @@ fn remap_function(
De::I64TruncSatF64U => En::I64TruncSatF64U, De::I64TruncSatF64U => En::I64TruncSatF64U,
De::MemoryCopy { src_mem, dst_mem } => En::MemoryCopy { src_mem, dst_mem }, De::MemoryCopy { src_mem, dst_mem } => En::MemoryCopy { src_mem, dst_mem },
De::MemoryFill { mem } => En::MemoryFill(mem), De::MemoryFill { mem } => En::MemoryFill(mem),
De::V128Const { value } => En::V128Const(value.i128()),
De::V128Load { memarg } => En::V128Load(mem(memarg)),
De::V128Store { memarg } => En::V128Store(mem(memarg)),
De::V128Load8x8S { memarg } => En::V128Load8x8S(mem(memarg)),
De::V128Load8x8U { memarg } => En::V128Load8x8U(mem(memarg)),
De::V128Load16x4S { memarg } => En::V128Load16x4S(mem(memarg)),
De::V128Load16x4U { memarg } => En::V128Load16x4U(mem(memarg)),
De::V128Load32x2S { memarg } => En::V128Load32x2S(mem(memarg)),
De::V128Load32x2U { memarg } => En::V128Load32x2U(mem(memarg)),
De::V128Load8Splat { memarg } => En::V128Load8Splat(mem(memarg)),
De::V128Load16Splat { memarg } => En::V128Load16Splat(mem(memarg)),
De::V128Load32Splat { memarg } => En::V128Load32Splat(mem(memarg)),
De::V128Load64Splat { memarg } => En::V128Load64Splat(mem(memarg)),
De::V128Load32Zero { memarg } => En::V128Load32Zero(mem(memarg)),
De::V128Load64Zero { memarg } => En::V128Load64Zero(mem(memarg)),
De::V128Load8Lane { memarg, lane } => En::V128Load8Lane { memarg: mem(memarg), lane },
De::V128Load16Lane { memarg, lane } => En::V128Load16Lane { memarg: mem(memarg), lane },
De::V128Load32Lane { memarg, lane } => En::V128Load32Lane { memarg: mem(memarg), lane },
De::V128Load64Lane { memarg, lane } => En::V128Load64Lane { memarg: mem(memarg), lane },
De::V128Store8Lane { memarg, lane } => En::V128Store8Lane { memarg: mem(memarg), lane },
De::V128Store16Lane { memarg, lane } => En::V128Store16Lane { memarg: mem(memarg), lane },
De::V128Store32Lane { memarg, lane } => En::V128Store32Lane { memarg: mem(memarg), lane },
De::V128Store64Lane { memarg, lane } => En::V128Store64Lane { memarg: mem(memarg), lane },
De::I8x16ExtractLaneS { lane } => En::I8x16ExtractLaneS(lane),
De::I8x16ExtractLaneU { lane } => En::I8x16ExtractLaneU(lane),
De::I8x16ReplaceLane { lane } => En::I8x16ReplaceLane(lane),
De::I16x8ExtractLaneS { lane } => En::I16x8ExtractLaneS(lane),
De::I16x8ExtractLaneU { lane } => En::I16x8ExtractLaneU(lane),
De::I16x8ReplaceLane { lane } => En::I16x8ReplaceLane(lane),
De::I32x4ExtractLane { lane } => En::I32x4ExtractLane(lane),
De::I32x4ReplaceLane { lane } => En::I32x4ReplaceLane(lane),
De::I64x2ExtractLane { lane } => En::I64x2ExtractLane(lane),
De::I64x2ReplaceLane { lane } => En::I64x2ReplaceLane(lane),
De::F32x4ExtractLane { lane } => En::F32x4ExtractLane(lane),
De::F32x4ReplaceLane { lane } => En::F32x4ReplaceLane(lane),
De::F64x2ExtractLane { lane } => En::F64x2ExtractLane(lane),
De::F64x2ReplaceLane { lane } => En::F64x2ReplaceLane(lane),
De::I8x16Splat => En::I8x16Splat,
De::I16x8Splat => En::I16x8Splat,
De::I32x4Splat => En::I32x4Splat,
De::I64x2Splat => En::I64x2Splat,
De::F32x4Splat => En::F32x4Splat,
De::F64x2Splat => En::F64x2Splat,
De::I8x16Swizzle => En::I8x16Swizzle,
De::I8x16Add => En::I8x16Add,
De::I16x8Add => En::I16x8Add,
De::I32x4Add => En::I32x4Add,
De::I64x2Add => En::I64x2Add,
De::F32x4Add => En::F32x4Add,
De::F64x2Add => En::F64x2Add,
De::I8x16Sub => En::I8x16Sub,
De::I16x8Sub => En::I16x8Sub,
De::I32x4Sub => En::I32x4Sub,
De::I64x2Sub => En::I64x2Sub,
De::F32x4Sub => En::F32x4Sub,
De::F64x2Sub => En::F64x2Sub,
De::I16x8Mul => En::I16x8Mul,
De::I32x4Mul => En::I32x4Mul,
De::I64x2Mul => En::I64x2Mul,
De::F32x4Mul => En::F32x4Mul,
De::F64x2Mul => En::F64x2Mul,
De::I32x4DotI16x8S => En::I32x4DotI16x8S,
De::I8x16Neg => En::I8x16Neg,
De::I16x8Neg => En::I16x8Neg,
De::I32x4Neg => En::I32x4Neg,
De::I64x2Neg => En::I64x2Neg,
De::F32x4Neg => En::F32x4Neg,
De::F64x2Neg => En::F64x2Neg,
De::I16x8ExtMulLowI8x16S => En::I16x8ExtMulLowI8x16S,
De::I16x8ExtMulHighI8x16S => En::I16x8ExtMulHighI8x16S,
De::I16x8ExtMulLowI8x16U => En::I16x8ExtMulLowI8x16U,
De::I16x8ExtMulHighI8x16U => En::I16x8ExtMulHighI8x16U,
De::I32x4ExtMulLowI16x8S => En::I32x4ExtMulLowI16x8S,
De::I32x4ExtMulHighI16x8S => En::I32x4ExtMulHighI16x8S,
De::I32x4ExtMulLowI16x8U => En::I32x4ExtMulLowI16x8U,
De::I32x4ExtMulHighI16x8U => En::I32x4ExtMulHighI16x8U,
De::I64x2ExtMulLowI32x4S => En::I64x2ExtMulLowI32x4S,
De::I64x2ExtMulHighI32x4S => En::I64x2ExtMulHighI32x4S,
De::I64x2ExtMulLowI32x4U => En::I64x2ExtMulLowI32x4U,
De::I64x2ExtMulHighI32x4U => En::I64x2ExtMulHighI32x4U,
De::I16x8ExtAddPairwiseI8x16S => En::I16x8ExtAddPairwiseI8x16S,
De::I16x8ExtAddPairwiseI8x16U => En::I16x8ExtAddPairwiseI8x16U,
De::I32x4ExtAddPairwiseI16x8S => En::I32x4ExtAddPairwiseI16x8S,
De::I32x4ExtAddPairwiseI16x8U => En::I32x4ExtAddPairwiseI16x8U,
De::I8x16AddSatS => En::I8x16AddSatS,
De::I8x16AddSatU => En::I8x16AddSatU,
De::I16x8AddSatS => En::I16x8AddSatS,
De::I16x8AddSatU => En::I16x8AddSatU,
De::I8x16SubSatS => En::I8x16SubSatS,
De::I8x16SubSatU => En::I8x16SubSatU,
De::I16x8SubSatS => En::I16x8SubSatS,
De::I16x8SubSatU => En::I16x8SubSatU,
De::I16x8Q15MulrSatS => En::I16x8Q15MulrSatS,
De::I8x16MinS => En::I8x16MinS,
De::I8x16MinU => En::I8x16MinU,
De::I16x8MinS => En::I16x8MinS,
De::I16x8MinU => En::I16x8MinU,
De::I32x4MinS => En::I32x4MinS,
De::I32x4MinU => En::I32x4MinU,
De::F32x4Min => En::F32x4Min,
De::F64x2Min => En::F64x2Min,
De::F32x4PMin => En::F32x4PMin,
De::F64x2PMin => En::F64x2PMin,
De::I8x16MaxS => En::I8x16MaxS,
De::I8x16MaxU => En::I8x16MaxU,
De::I16x8MaxS => En::I16x8MaxS,
De::I16x8MaxU => En::I16x8MaxU,
De::I32x4MaxS => En::I32x4MaxS,
De::I32x4MaxU => En::I32x4MaxU,
De::F32x4Max => En::F32x4Max,
De::F64x2Max => En::F64x2Max,
De::F32x4PMax => En::F32x4PMax,
De::F64x2PMax => En::F64x2PMax,
De::I8x16AvgrU => En::I8x16AvgrU,
De::I16x8AvgrU => En::I16x8AvgrU,
De::I8x16Abs => En::I8x16Abs,
De::I16x8Abs => En::I16x8Abs,
De::I32x4Abs => En::I32x4Abs,
De::I64x2Abs => En::I64x2Abs,
De::F32x4Abs => En::F32x4Abs,
De::F64x2Abs => En::F64x2Abs,
De::I8x16Shl => En::I8x16Shl,
De::I16x8Shl => En::I16x8Shl,
De::I32x4Shl => En::I32x4Shl,
De::I64x2Shl => En::I64x2Shl,
De::I8x16ShrS => En::I8x16ShrS,
De::I8x16ShrU => En::I8x16ShrU,
De::I16x8ShrS => En::I16x8ShrS,
De::I16x8ShrU => En::I16x8ShrU,
De::I32x4ShrS => En::I32x4ShrS,
De::I32x4ShrU => En::I32x4ShrU,
De::I64x2ShrS => En::I64x2ShrS,
De::I64x2ShrU => En::I64x2ShrU,
De::V128And => En::V128And,
De::V128Or => En::V128Or,
De::V128Xor => En::V128Xor,
De::V128Not => En::V128Not,
De::V128AndNot => En::V128AndNot,
De::V128Bitselect => En::V128Bitselect,
De::I8x16Popcnt => En::I8x16Popcnt,
De::V128AnyTrue => En::V128AnyTrue,
De::I8x16AllTrue => En::I8x16AllTrue,
De::I16x8AllTrue => En::I16x8AllTrue,
De::I32x4AllTrue => En::I32x4AllTrue,
De::I64x2AllTrue => En::I64x2AllTrue,
De::I8x16Bitmask => En::I8x16Bitmask,
De::I16x8Bitmask => En::I16x8Bitmask,
De::I32x4Bitmask => En::I32x4Bitmask,
De::I64x2Bitmask => En::I64x2Bitmask,
De::I8x16Eq => En::I8x16Eq,
De::I16x8Eq => En::I16x8Eq,
De::I32x4Eq => En::I32x4Eq,
De::I64x2Eq => En::I64x2Eq,
De::F32x4Eq => En::F32x4Eq,
De::F64x2Eq => En::F64x2Eq,
De::I8x16Ne => En::I8x16Ne,
De::I16x8Ne => En::I16x8Ne,
De::I32x4Ne => En::I32x4Ne,
De::I64x2Ne => En::I64x2Ne,
De::F32x4Ne => En::F32x4Ne,
De::F64x2Ne => En::F64x2Ne,
De::I8x16LtS => En::I8x16LtS,
De::I8x16LtU => En::I8x16LtU,
De::I16x8LtS => En::I16x8LtS,
De::I16x8LtU => En::I16x8LtU,
De::I32x4LtS => En::I32x4LtS,
De::I32x4LtU => En::I32x4LtU,
De::F32x4Lt => En::F32x4Lt,
De::F64x2Lt => En::F64x2Lt,
De::I8x16LeS => En::I8x16LeS,
De::I8x16LeU => En::I8x16LeU,
De::I16x8LeS => En::I16x8LeS,
De::I16x8LeU => En::I16x8LeU,
De::I32x4LeS => En::I32x4LeS,
De::I32x4LeU => En::I32x4LeU,
De::F32x4Le => En::F32x4Le,
De::F64x2Le => En::F64x2Le,
De::I8x16GtS => En::I8x16GtS,
De::I8x16GtU => En::I8x16GtU,
De::I16x8GtS => En::I16x8GtS,
De::I16x8GtU => En::I16x8GtU,
De::I32x4GtS => En::I32x4GtS,
De::I32x4GtU => En::I32x4GtU,
De::F32x4Gt => En::F32x4Gt,
De::F64x2Gt => En::F64x2Gt,
De::I8x16GeS => En::I8x16GeS,
De::I8x16GeU => En::I8x16GeU,
De::I16x8GeS => En::I16x8GeS,
De::I16x8GeU => En::I16x8GeU,
De::I32x4GeS => En::I32x4GeS,
De::I32x4GeU => En::I32x4GeU,
De::F32x4Ge => En::F32x4Ge,
De::F64x2Ge => En::F64x2Ge,
De::F32x4Div => En::F32x4Div,
De::F64x2Div => En::F64x2Div,
De::F32x4Sqrt => En::F32x4Sqrt,
De::F64x2Sqrt => En::F64x2Sqrt,
De::F32x4Ceil => En::F32x4Ceil,
De::F64x2Ceil => En::F64x2Ceil,
De::F32x4Floor => En::F32x4Floor,
De::F64x2Floor => En::F64x2Floor,
De::F32x4Trunc => En::F32x4Trunc,
De::F64x2Trunc => En::F64x2Trunc,
De::F32x4Nearest => En::F32x4Nearest,
De::F64x2Nearest => En::F64x2Nearest,
De::F32x4ConvertI32x4S => En::F32x4ConvertI32x4S,
De::F32x4ConvertI32x4U => En::F32x4ConvertI32x4U,
De::F64x2ConvertLowI32x4S => En::F64x2ConvertLowI32x4S,
De::F64x2ConvertLowI32x4U => En::F64x2ConvertLowI32x4U,
De::I32x4TruncSatF32x4S => En::I32x4TruncSatF32x4S,
De::I32x4TruncSatF32x4U => En::I32x4TruncSatF32x4U,
De::I32x4TruncSatF64x2SZero => En::I32x4TruncSatF64x2SZero,
De::I32x4TruncSatF64x2UZero => En::I32x4TruncSatF64x2UZero,
De::F32x4DemoteF64x2Zero => En::F32x4DemoteF64x2Zero,
De::F64x2PromoteLowF32x4 => En::F64x2PromoteLowF32x4,
De::I8x16NarrowI16x8S => En::I8x16NarrowI16x8S,
De::I8x16NarrowI16x8U => En::I8x16NarrowI16x8U,
De::I16x8NarrowI32x4S => En::I16x8NarrowI32x4S,
De::I16x8NarrowI32x4U => En::I16x8NarrowI32x4U,
De::I16x8ExtendLowI8x16S => En::I16x8ExtendLowI8x16S,
De::I16x8ExtendHighI8x16S => En::I16x8ExtendHighI8x16S,
De::I16x8ExtendLowI8x16U => En::I16x8ExtendLowI8x16U,
De::I16x8ExtendHighI8x16U => En::I16x8ExtendHighI8x16U,
De::I32x4ExtendLowI16x8S => En::I32x4ExtendLowI16x8S,
De::I32x4ExtendHighI16x8S => En::I32x4ExtendHighI16x8S,
De::I32x4ExtendLowI16x8U => En::I32x4ExtendLowI16x8U,
De::I32x4ExtendHighI16x8U => En::I32x4ExtendHighI16x8U,
De::I64x2ExtendLowI32x4S => En::I64x2ExtendLowI32x4S,
De::I64x2ExtendHighI32x4S => En::I64x2ExtendHighI32x4S,
De::I64x2ExtendLowI32x4U => En::I64x2ExtendLowI32x4U,
De::I64x2ExtendHighI32x4U => En::I64x2ExtendHighI32x4U,
De::I8x16Shuffle { lanes } => En::I8x16Shuffle(lanes),
other => bail!("Unsupported instruction {:?}", other), other => bail!("Unsupported instruction {:?}", other),
}); });
} }

1048
uw8-window/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,13 +6,13 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
env_logger = "0.11.3"
winit = "0.28.6" winit = "0.28.6"
env_logger = "0.10"
log = "0.4" log = "0.4"
pico-args = "0.5" pico-args = "0.5"
wgpu = "0.17" wgpu = "0.17"
pollster = "0.3.0" pollster = "0.3.0"
bytemuck = { version = "1.15", features = [ "derive" ] } bytemuck = { version = "1.13", features = [ "derive" ] }
anyhow = "1" anyhow = "1"
minifb = { version = "0.25.0", default-features = false, features = ["x11"] } minifb = { version = "0.25.0", default-features = false, features = ["x11"] }
winapi = { version = "0.3.9", features = [ "timeapi" ] } winapi = { version = "0.3.9", features = [ "timeapi" ] }

View File

@@ -1,7 +1,7 @@
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
use winit::dpi::PhysicalSize; use winit::dpi::PhysicalSize;
use super::{scale_mode::ScaleMode, Filter}; use super::Filter;
pub struct CrtFilter { pub struct CrtFilter {
uniform_buffer: wgpu::Buffer, uniform_buffer: wgpu::Buffer,
@@ -15,10 +15,9 @@ impl CrtFilter {
screen: &wgpu::TextureView, screen: &wgpu::TextureView,
resolution: PhysicalSize<u32>, resolution: PhysicalSize<u32>,
surface_format: wgpu::TextureFormat, surface_format: wgpu::TextureFormat,
scale_mode: ScaleMode,
) -> CrtFilter { ) -> CrtFilter {
let uniforms = Uniforms { let uniforms = Uniforms {
texture_scale: scale_mode.texture_scale_from_resolution(resolution), texture_scale: texture_scale_from_resolution(resolution),
}; };
let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
@@ -113,9 +112,9 @@ impl CrtFilter {
} }
impl Filter for CrtFilter { impl Filter for CrtFilter {
fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize<u32>, scale_mode: ScaleMode) { fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize<u32>) {
let uniforms = Uniforms { let uniforms = Uniforms {
texture_scale: scale_mode.texture_scale_from_resolution(new_size), texture_scale: texture_scale_from_resolution(new_size),
}; };
queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[uniforms])); queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[uniforms]));
} }
@@ -127,6 +126,16 @@ impl Filter for CrtFilter {
} }
} }
fn texture_scale_from_resolution(res: PhysicalSize<u32>) -> [f32; 4] {
let scale = ((res.width as f32) / 160.0).min((res.height as f32) / 120.0);
[
res.width as f32 / scale,
res.height as f32 / scale,
2.0 / scale,
0.0,
]
}
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
struct Uniforms { struct Uniforms {

View File

@@ -17,7 +17,7 @@ fn vs_main(
let i = in_vertex_index / 3u + in_vertex_index % 3u; let i = in_vertex_index / 3u + in_vertex_index % 3u;
let x = -1.0 + f32(i % 2u) * 322.0; let x = -1.0 + f32(i % 2u) * 322.0;
let y = -1.0 + f32(i / 2u) * 242.0; let y = -1.0 + f32(i / 2u) * 242.0;
out.clip_position = vec4<f32>((vec2<f32>(x, y) - vec2<f32>(160.0, 120.0)) * uniforms.texture_scale.xy, 0.0, 1.0); out.clip_position = vec4<f32>((vec2<f32>(x, y) - vec2<f32>(160.0, 120.0)) / uniforms.texture_scale.xy, 0.0, 1.0);
out.tex_coords = vec2<f32>(x, y); out.tex_coords = vec2<f32>(x, y);
return out; return out;
} }

View File

@@ -1,7 +1,7 @@
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
use winit::dpi::PhysicalSize; use winit::dpi::PhysicalSize;
use super::{scale_mode::ScaleMode, Filter}; use super::Filter;
pub struct FastCrtFilter { pub struct FastCrtFilter {
uniform_buffer: wgpu::Buffer, uniform_buffer: wgpu::Buffer,
@@ -16,10 +16,9 @@ impl FastCrtFilter {
resolution: PhysicalSize<u32>, resolution: PhysicalSize<u32>,
surface_format: wgpu::TextureFormat, surface_format: wgpu::TextureFormat,
chromatic: bool, chromatic: bool,
scale_mode: ScaleMode,
) -> FastCrtFilter { ) -> FastCrtFilter {
let uniforms = Uniforms { let uniforms = Uniforms {
texture_scale: scale_mode.texture_scale_from_resolution(resolution), texture_scale: texture_scale_from_resolution(resolution),
}; };
let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
@@ -132,9 +131,9 @@ impl FastCrtFilter {
} }
impl Filter for FastCrtFilter { impl Filter for FastCrtFilter {
fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize<u32>, scale_mode: ScaleMode) { fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize<u32>) {
let uniforms = Uniforms { let uniforms = Uniforms {
texture_scale: scale_mode.texture_scale_from_resolution(new_size), texture_scale: texture_scale_from_resolution(new_size),
}; };
queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[uniforms])); queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[uniforms]));
} }
@@ -146,6 +145,16 @@ impl Filter for FastCrtFilter {
} }
} }
fn texture_scale_from_resolution(res: PhysicalSize<u32>) -> [f32; 4] {
let scale = ((res.width as f32) / 160.0).min((res.height as f32) / 120.0);
[
scale / res.width as f32,
scale / res.height as f32,
2.0 / scale,
0.0,
]
}
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
struct Uniforms { struct Uniforms {

View File

@@ -1,6 +1,5 @@
use crate::{Input, WindowConfig, WindowImpl}; use crate::{Input, WindowConfig, WindowImpl};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use scale_mode::ScaleMode;
use std::time::Instant; use std::time::Instant;
use winit::{ use winit::{
@@ -14,7 +13,6 @@ use winit::platform::run_return::EventLoopExtRunReturn;
mod crt; mod crt;
mod fast_crt; mod fast_crt;
pub mod scale_mode;
mod square; mod square;
use crt::CrtFilter; use crt::CrtFilter;
@@ -36,7 +34,6 @@ pub struct Window {
next_frame: Instant, next_frame: Instant,
is_fullscreen: bool, is_fullscreen: bool,
is_open: bool, is_open: bool,
scale_mode: ScaleMode,
} }
impl Window { impl Window {
@@ -93,7 +90,6 @@ impl Window {
window.inner_size(), window.inner_size(),
surface_config.format, surface_config.format,
window_config.filter, window_config.filter,
window_config.scale_mode,
); );
surface.configure(&device, &surface_config); surface.configure(&device, &surface_config);
@@ -113,7 +109,6 @@ impl Window {
next_frame: Instant::now(), next_frame: Instant::now(),
is_fullscreen: window_config.fullscreen, is_fullscreen: window_config.fullscreen,
is_open: true, is_open: true,
scale_mode: window_config.scale_mode,
}) })
} }
@@ -133,7 +128,7 @@ impl WindowImpl for Window {
self.surface_config.width = new_size.width; self.surface_config.width = new_size.width;
self.surface_config.height = new_size.height; self.surface_config.height = new_size.height;
self.surface.configure(&self.device, &self.surface_config); self.surface.configure(&self.device, &self.surface_config);
self.filter.resize(&self.queue, new_size, self.scale_mode); self.filter.resize(&self.queue, new_size);
} }
WindowEvent::CloseRequested => { WindowEvent::CloseRequested => {
self.is_open = false; self.is_open = false;
@@ -170,20 +165,6 @@ impl WindowImpl for Window {
self.is_fullscreen = fullscreen.is_some(); self.is_fullscreen = fullscreen.is_some();
self.window.set_fullscreen(fullscreen); self.window.set_fullscreen(fullscreen);
} }
Some(VirtualKeyCode::M) => {
self.scale_mode = match self.scale_mode {
ScaleMode::Fit => ScaleMode::Fill,
ScaleMode::Fill => ScaleMode::Fit,
};
self.filter.resize(
&self.queue,
PhysicalSize {
width: self.surface_config.width,
height: self.surface_config.height,
},
self.scale_mode,
);
}
Some(VirtualKeyCode::R) => reset = true, Some(VirtualKeyCode::R) => reset = true,
Some(VirtualKeyCode::Key1) => new_filter = Some(1), Some(VirtualKeyCode::Key1) => new_filter = Some(1),
Some(VirtualKeyCode::Key2) => new_filter = Some(2), Some(VirtualKeyCode::Key2) => new_filter = Some(2),
@@ -217,7 +198,6 @@ impl WindowImpl for Window {
self.window.inner_size(), self.window.inner_size(),
self.surface_config.format, self.surface_config.format,
new_filter, new_filter,
self.scale_mode,
); );
} }
}); });
@@ -280,7 +260,6 @@ fn create_filter(
window_size: PhysicalSize<u32>, window_size: PhysicalSize<u32>,
surface_format: wgpu::TextureFormat, surface_format: wgpu::TextureFormat,
filter: u32, filter: u32,
scale_mode: ScaleMode,
) -> Box<dyn Filter> { ) -> Box<dyn Filter> {
match filter { match filter {
1 => Box::new(SquareFilter::new( 1 => Box::new(SquareFilter::new(
@@ -288,7 +267,6 @@ fn create_filter(
screen_texture, screen_texture,
window_size, window_size,
surface_format, surface_format,
scale_mode,
)), )),
2 => Box::new(FastCrtFilter::new( 2 => Box::new(FastCrtFilter::new(
device, device,
@@ -296,14 +274,12 @@ fn create_filter(
window_size, window_size,
surface_format, surface_format,
false, false,
scale_mode,
)), )),
3 => Box::new(CrtFilter::new( 3 => Box::new(CrtFilter::new(
device, device,
screen_texture, screen_texture,
window_size, window_size,
surface_format, surface_format,
scale_mode,
)), )),
4 => Box::new(FastCrtFilter::new( 4 => Box::new(FastCrtFilter::new(
device, device,
@@ -311,20 +287,18 @@ fn create_filter(
window_size, window_size,
surface_format, surface_format,
true, true,
scale_mode,
)), )),
_ => Box::new(AutoCrtFilter::new( _ => Box::new(AutoCrtFilter::new(
device, device,
screen_texture, screen_texture,
window_size, window_size,
surface_format, surface_format,
scale_mode,
)), )),
} }
} }
trait Filter { trait Filter {
fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize<u32>, scale_mode: ScaleMode); fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize<u32>);
fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>); fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>);
} }
@@ -340,11 +314,9 @@ impl AutoCrtFilter {
screen: &wgpu::TextureView, screen: &wgpu::TextureView,
resolution: PhysicalSize<u32>, resolution: PhysicalSize<u32>,
surface_format: wgpu::TextureFormat, surface_format: wgpu::TextureFormat,
scale_mode: ScaleMode,
) -> AutoCrtFilter { ) -> AutoCrtFilter {
let small = CrtFilter::new(device, screen, resolution, surface_format, scale_mode); let small = CrtFilter::new(device, screen, resolution, surface_format);
let large = let large = FastCrtFilter::new(device, screen, resolution, surface_format, true);
FastCrtFilter::new(device, screen, resolution, surface_format, true, scale_mode);
AutoCrtFilter { AutoCrtFilter {
small, small,
large, large,
@@ -354,9 +326,9 @@ impl AutoCrtFilter {
} }
impl Filter for AutoCrtFilter { impl Filter for AutoCrtFilter {
fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize<u32>, scale_mode: ScaleMode) { fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize<u32>) {
self.small.resize(queue, new_size, scale_mode); self.small.resize(queue, new_size);
self.large.resize(queue, new_size, scale_mode); self.large.resize(queue, new_size);
self.resolution = new_size; self.resolution = new_size;
} }

View File

@@ -1,28 +0,0 @@
use winit::dpi::PhysicalSize;
#[derive(Debug, Copy, Clone)]
pub enum ScaleMode {
Fit,
Fill,
}
impl Default for ScaleMode {
fn default() -> ScaleMode {
ScaleMode::Fit
}
}
impl ScaleMode {
pub fn texture_scale_from_resolution(&self, res: PhysicalSize<u32>) -> [f32; 4] {
let scale = match self {
ScaleMode::Fit => ((res.width as f32) / 160.0).min((res.height as f32) / 120.0),
ScaleMode::Fill => ((res.width as f32) / 160.0).max((res.height as f32) / 120.0),
};
[
scale / res.width as f32,
scale / res.height as f32,
2.0 / scale,
0.0,
]
}
}

View File

@@ -1,7 +1,7 @@
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
use winit::dpi::PhysicalSize; use winit::dpi::PhysicalSize;
use super::{scale_mode::ScaleMode, Filter}; use super::Filter;
pub struct SquareFilter { pub struct SquareFilter {
uniform_buffer: wgpu::Buffer, uniform_buffer: wgpu::Buffer,
@@ -15,10 +15,9 @@ impl SquareFilter {
screen: &wgpu::TextureView, screen: &wgpu::TextureView,
resolution: PhysicalSize<u32>, resolution: PhysicalSize<u32>,
surface_format: wgpu::TextureFormat, surface_format: wgpu::TextureFormat,
scale_mode: ScaleMode,
) -> SquareFilter { ) -> SquareFilter {
let uniforms = Uniforms { let uniforms = Uniforms {
texture_scale: scale_mode.texture_scale_from_resolution(resolution), texture_scale: texture_scale_from_resolution(resolution),
}; };
let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
@@ -127,9 +126,9 @@ impl SquareFilter {
} }
impl Filter for SquareFilter { impl Filter for SquareFilter {
fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize<u32>, scale_mode: ScaleMode) { fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize<u32>) {
let uniforms = Uniforms { let uniforms = Uniforms {
texture_scale: scale_mode.texture_scale_from_resolution(new_size), texture_scale: texture_scale_from_resolution(new_size),
}; };
queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[uniforms])); queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[uniforms]));
} }
@@ -141,6 +140,16 @@ impl Filter for SquareFilter {
} }
} }
fn texture_scale_from_resolution(res: PhysicalSize<u32>) -> [f32; 4] {
let scale = ((res.width as f32) / 160.0).min((res.height as f32) / 120.0);
[
scale / res.width as f32,
scale / res.height as f32,
2.0 / scale,
0.0,
]
}
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
struct Uniforms { struct Uniforms {

View File

@@ -1,5 +1,4 @@
use anyhow::Result; use anyhow::Result;
use gpu::scale_mode::ScaleMode;
use std::time::Instant; use std::time::Instant;
mod cpu; mod cpu;
@@ -74,7 +73,6 @@ pub struct WindowConfig {
fullscreen: bool, fullscreen: bool,
fps_counter: bool, fps_counter: bool,
scale: f32, scale: f32,
scale_mode: ScaleMode,
} }
impl Default for WindowConfig { impl Default for WindowConfig {
@@ -85,7 +83,6 @@ impl Default for WindowConfig {
fullscreen: false, fullscreen: false,
fps_counter: false, fps_counter: false,
scale: 2., scale: 2.,
scale_mode: ScaleMode::Fit,
} }
} }
} }
@@ -112,9 +109,6 @@ impl WindowConfig {
.opt_value_from_str("--scale") .opt_value_from_str("--scale")
.unwrap() .unwrap()
.unwrap_or(self.scale); .unwrap_or(self.scale);
if args.contains("--scale-fill") {
self.scale_mode = ScaleMode::Fill;
}
} }
} }

View File

@@ -4,6 +4,5 @@
"@parcel/optimizer-data-url": "^2.0.0", "@parcel/optimizer-data-url": "^2.0.0",
"@parcel/transformer-inline-string": "^2.0.0", "@parcel/transformer-inline-string": "^2.0.0",
"parcel": "^2.0.0" "parcel": "^2.0.0"
}, }
"dependencies": {}
} }

View File

@@ -10,7 +10,7 @@
</head> </head>
<body> <body>
<div id="uw8"> <div id="uw8">
<a href="https://exoticorn.github.io/microw8">MicroW8</a> 0.4.1 <a href="https://exoticorn.github.io/microw8">MicroW8</a> 0.2.2
</div> </div>
<div id="centered"> <div id="centered">
<canvas class="screen" id="screen" width="320" height="240"> <canvas class="screen" id="screen" width="320" height="240">

View File

@@ -240,7 +240,6 @@ export default function MicroW8(screen, config = {}) {
await audioReadyPromise; await audioReadyPromise;
let startTime = Date.now(); let startTime = Date.now();
let frameCounter = 0;
const timePerFrame = 1000 / 60; const timePerFrame = 1000 / 60;
@@ -307,7 +306,6 @@ export default function MicroW8(screen, config = {}) {
let time = Date.now() - startTime; let time = Date.now() - startTime;
u32Mem[16] = time; u32Mem[16] = time;
u32Mem[17] = pad | gamepad; u32Mem[17] = pad | gamepad;
u32Mem[18] = frameCounter++;
if(instance.exports.upd) { if(instance.exports.upd) {
instance.exports.upd(); instance.exports.upd();
} }

File diff suppressed because it is too large Load Diff