mirror of
https://github.com/exoticorn/microw8.git
synced 2026-01-20 11:16:42 +01:00
354 lines
12 KiB
Markdown
354 lines
12 KiB
Markdown
+++
|
|
title = "Docs"
|
|
description = "Docs"
|
|
+++
|
|
|
|
# Overview
|
|
|
|
MicroW8 loads WebAssembly modules with a maximum size of 256kb. You module needs to export
|
|
a function `fn upd()` which will be called once per frame.
|
|
After calling `upd` MicroW8 will display the 320x240 8bpp framebuffer located
|
|
at offset 120 in memory with the 32bpp palette located at 0x13000.
|
|
|
|
The memory has to be imported as `env` `memory` and has a maximum size of 256kb (4 pages).
|
|
|
|
# Memory map
|
|
|
|
```
|
|
00000-00040: user memory
|
|
00040-00044: time since module start in ms
|
|
00044-0004c: gamepad state
|
|
0004c-00078: reserved
|
|
00078-12c78: frame buffer
|
|
12c78-13000: reserved
|
|
13000-13400: palette
|
|
13400-13c00: font
|
|
13c00-14000: reserved
|
|
14000-40000: user memory
|
|
```
|
|
|
|
# API
|
|
|
|
All API functions are found in the `env` module.
|
|
|
|
## Math
|
|
|
|
These all do what you'd expect them to. All angles are in radians.
|
|
|
|
### fn asin(x: f32) -> f32
|
|
|
|
Returns the arcsine of `x`.
|
|
|
|
### fn acos(x: f32) -> f32
|
|
|
|
Returns the arccosine of `x`.
|
|
|
|
### fn atan(f32) -> f32
|
|
|
|
Returns the arctangent of `x`.
|
|
|
|
### fn atan2(y: f32, y: f32) -> f32
|
|
|
|
Returns the angle between the point `(x, y)` and the positive x-axis.
|
|
|
|
### fn sin(angle: f32) -> f32
|
|
|
|
Returns the sine of `angle`.
|
|
|
|
### fn tan(angle: f32) -> f32
|
|
|
|
Returns the tangent of `angle`.
|
|
|
|
### fn cos(angle: f32) -> f32
|
|
|
|
Returns the cosine of `angle`.
|
|
|
|
### fn exp(x: f32) -> f32
|
|
|
|
Returns `e^x`.
|
|
|
|
### fn log(x: f32) -> f32
|
|
|
|
Returns the natural logarithmus of `x`. Ie. `e^log(x) == x`.
|
|
|
|
### fn pow(x: f32, y: f32) -> f32
|
|
|
|
Returns `x^y`.
|
|
|
|
### fn fmod(x: f32, y: f32) -> f32
|
|
|
|
Returns `x` modulo `y`, ie. `x - floor(x / y) * y`. This means the sign of the result of `fmod` is the same as `y`.
|
|
|
|
## Random
|
|
|
|
MicroW8 provides a pretty good PRNG, namely xorshift64*. It is initialized to a constant seed at each startup, so if you
|
|
want to vary the random sequence you'll need to provide a seed yourself.
|
|
|
|
### fn random() -> i32
|
|
|
|
Returns a (pseudo-)random 32bit integer.
|
|
|
|
### fn randomf() -> f32
|
|
|
|
Returns a (pseudo-)random float equally distributed in `[0,1)`.
|
|
|
|
### fn randomSeed(seed: i32)
|
|
|
|
Seeds the PRNG with the given seed. The seed function is reasonably strong so that you can use
|
|
|
|
```
|
|
randomSeed(index);
|
|
random()
|
|
```
|
|
|
|
as a cheap random-access PRNG (aka noise function).
|
|
|
|
## Graphics
|
|
|
|
The default palette can be seen [here](../v0.1pre4#AgKaeeOuwg5gCKvFIeiitEwMpUI2rymEcu+DDB1vMu9uBoufvUxIr4Y5p4Jj2ukoNO4PE7QS5cN1ZyDMCRfSzYIGZxKlN2J6NKEWK7KVPk9wVUgn1Ip+hsMinWgEO8ETKfPuHoIa4kjI+ULFOMad7vd3rt/lh1Vy9w+R2MXG/7T61d3c7C6KY+eQNS0eW3ys4iU8R6SycuWZuuZ2Sg3Qxp826s+Kt+2qBojpzNOSoyFqyrVyYMTKEkSl0BZOj59Cs1hPm5bq0F1MmVhGAzMhW9V4YeAe). (Press Z on the keyboard to switch to palette.)
|
|
|
|
The palette can be changed by writing 32bit rgba colors to addresses 0x13000-0x13400.
|
|
|
|
The drawing functions are sub-pixel accurate where applicable (line, circle). Pixel centers lie halfway between integer
|
|
coordinates. Ie. the top-left pixel covers the area `0,0 - 1,1`, with `0.5,0.5` being the pixel center.
|
|
|
|
### fn cls(color: i32)
|
|
|
|
Clears the screen to the given color index. Also sets the text cursor to `0, 0` and disables graphical text mode.
|
|
|
|
### fn setPixel(x: i32, y: i32, color: i32)
|
|
|
|
Sets the pixel at `x, y` to the given color index.
|
|
|
|
### fn getPixel(x: i32, y: i32) -> i32
|
|
|
|
Returns the color index at `x, y`. Returns `0` if the given coordinates are outside the screen.
|
|
|
|
### fn hline(left: i32, right: i32, y: i32, color: i32)
|
|
|
|
Fills the horizontal line `[left, right), y` with the given color index.
|
|
|
|
### fn rectangle(x: f32, y: f32, w: f32, h: f32, color: i32)
|
|
|
|
Fills the rectangle `x,y - x+w,y+h` with the given color index.
|
|
|
|
(Sets all pixels where the pixel center lies inside the rectangle.)
|
|
|
|
### fn circle(cx: f32, cy: f32, radius: f32, color: i32)
|
|
|
|
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.)
|
|
|
|
### 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 the outermost pixels that are still inside the rectangle area.)
|
|
|
|
### fn circle_outline(cx: f32, cy: f32, radius: f32, color: i32)
|
|
|
|
Draws a one pixel outline on the inside of the given circle.
|
|
|
|
(Draws the outermost pixels that are still inside the circle area.)
|
|
|
|
### fn line(x1: f32, y1: f32, x2: f32, y2: f32, color: i32)
|
|
|
|
Draws a line from `x1,y1` to `x2,y2` in the given color index.
|
|
|
|
## Input
|
|
|
|
MicroW8 provides input from a gamepad with one D-Pad and 4 buttons, or a keyboard emulation thereof.
|
|
|
|
The buttons are numbered
|
|
|
|
| Button | Keyboard | Index |
|
|
| ------ | ----------- | ----- |
|
|
| Up | Arrow-Up | 0 |
|
|
| Down | Arrow-Down | 1 |
|
|
| Left | Arrow-Left | 2 |
|
|
| Right | Arrow-Right | 3 |
|
|
| A | Z | 4 |
|
|
| B | X | 5 |
|
|
| X | A | 6 |
|
|
| Y | S | 7 |
|
|
|
|
In addition to using the API functions below, the gamepad state can also be read as a bitfield of
|
|
pressed buttons at address 0x44. 0x48 holds the buttons that were pressed last frame.
|
|
|
|
### fn isButtonPressed(btn: i32) -> i32
|
|
|
|
Returns whether the buttons with the given index is pressed this frame.
|
|
|
|
### fn isButtonTriggered(btn: i32) -> i32
|
|
|
|
Returns whether the given button is newly pressed this frame.
|
|
|
|
### fn time() -> f32
|
|
|
|
Returns the time in seconds since the start of the cart.
|
|
|
|
The integer time in milliseconds can also be read at address 0x40.
|
|
|
|
## Text output
|
|
|
|
The default font can be seen [here](../v0.1pre4#AgKaeeOuwg5gCKvFIeiitEwMpUI2rymEcu+DDB1vMu9uBoufvUxIr4Y5p4Jj2ukoNO4PE7QS5cN1ZyDMCRfSzYIGZxKlN2J6NKEWK7KVPk9wVUgn1Ip+hsMinWgEO8ETKfPuHoIa4kjI+ULFOMad7vd3rt/lh1Vy9w+R2MXG/7T61d3c7C6KY+eQNS0eW3ys4iU8R6SycuWZuuZ2Sg3Qxp826s+Kt+2qBojpzNOSoyFqyrVyYMTKEkSl0BZOj59Cs1hPm5bq0F1MmVhGAzMhW9V4YeAe).
|
|
|
|
The font can be changed by writing 1bpp 8x8 characters to addresses 0x13400-0x13c00.
|
|
|
|
All text printing is done at the cursor position, which is advanced after printing each character.
|
|
The cursor is not visible.
|
|
|
|
Text printing can operate in two modes - normal and graphics. After startup and after `cls()` normal mode is active.
|
|
|
|
### Normal mode
|
|
|
|
In normal mode, text printing is constrained to an 8x8 character grid. Setting the cursor position to `2,3` will start printing at pixel coordinates `16,24`.
|
|
|
|
When printing characters, the full 8x8 pixels are painted with the text and background colors according to the character graphics in the font.
|
|
|
|
When moving/printing past the left or right border the cursor will automatically wrap to the previous/next line. When moving/printing past the upper/lower border, the screen will be scrolled down/up 8 pixels, filling the fresh line with the background color.
|
|
|
|
### Graphics mode
|
|
|
|
In graphics mode, text can be printed to any pixel position, the cursor position is set in pixel coordinates.
|
|
|
|
When printing characters only the foreground pixels are set, the background is "transparent".
|
|
|
|
Moving/printing past any border does not cause any special operation, the cursor just goes off-screen.
|
|
|
|
### Control chars
|
|
|
|
Characters 0-31 are control characters and don't print by default. They take the next 0-2 following characters as parameters.
|
|
Avoid the reserved control chars, they are currently NOPs but their behavior can change in later MicroW8 versions.
|
|
|
|
| Code | Parameters | Operation |
|
|
| ----- | ---------- | ------------------------------------ |
|
|
| 0 | - | Nop |
|
|
| 1 | char | Print char (including control chars) |
|
|
| 2-3 | - | Reserved |
|
|
| 4 | - | Switch to normal mode |
|
|
| 5 | - | Switch to graphics mode |
|
|
| 6-7 | - | Reserved |
|
|
| 8 | - | Move cursor left |
|
|
| 9 | - | Move cursor right |
|
|
| 10 | - | Move cursor down |
|
|
| 11 | - | Move cursor up |
|
|
| 12 | - | do `cls(background_color)` |
|
|
| 13 | - | Move cursor to the left border |
|
|
| 14 | color | Set the background color |
|
|
| 15 | color | Set the text color |
|
|
| 16-23 | - | Reserved |
|
|
| 24 | - | Swap text/background colors |
|
|
| 25-30 | - | Reserved |
|
|
| 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.
|
|
|
|
### fn printChar(char: i32)
|
|
|
|
Prints the character in the lower 8 bits of `char`. If the upper 24 bits are non-zero, right-shifts `char` by 8 bits and loops back to the beginning.
|
|
|
|
### fn printString(ptr: i32)
|
|
|
|
Prints the zero-terminated string at the given memory address.
|
|
|
|
### fn printInt(num: i32)
|
|
|
|
Prints `num` as a signed decimal number.
|
|
|
|
### fn setTextColor(color: i32)
|
|
|
|
Sets the text color.
|
|
|
|
### fn setBackgroundColor(color: i32)
|
|
|
|
Sets the background color.
|
|
|
|
### fn setCursorPosition(x: i32, y: i32)
|
|
|
|
Sets the cursor position. In normal mode `x` and `y` are multiplied by 8 to get the pixel position, in graphics mode they are used as is.
|
|
|
|
# The `uw8` tool
|
|
|
|
The `uw8` tool included in the MicroW8 download includes a number of useful tools for developing MicroW8 carts. For small productions written in
|
|
wat or CurlyWas you don't need anything apart from `uw8` and a text editor of your choice.
|
|
|
|
## `uw8 run`
|
|
|
|
Usage:
|
|
|
|
`uw8 run [<options>] <file>`
|
|
|
|
Runs `<file>` which can be a binary WebAssembly module, an `.uw8` cart, a wat (WebAssembly text format) source file or a [CurlyWas](https://github.com/exoticorn/curlywas) source file.
|
|
|
|
Options:
|
|
|
|
* `-w`, `--watch`: Reloads the given file every time it changes on disk.
|
|
* `-p`, `--pack`: Pack the file into an `.uw8` cart before running it and print the resulting size.
|
|
* `-u`, `--uncompressed`: Use the uncompressed `uw8` format for packing.
|
|
* `-l LEVEL`, `--level LEVEL`: Compression level (0-9). Higher compression levels are really slow.
|
|
* `-o FILE`, `--output FILE`: Write the loaded and optionally packed cart back to disk.
|
|
|
|
## `uw8 pack`
|
|
|
|
Usage:
|
|
|
|
`uw8 pack [<options>] <infile> <outfile>`
|
|
|
|
Packs the WebAssembly module or text file, or [CurlyWas](https://github.com/exoticorn/curlywas) source file into a `.uw8` cart.
|
|
|
|
Options:
|
|
|
|
* `-u`, `--uncompressed`: Use the uncompressed `uw8` format for packing.
|
|
* `-l LEVEL`, `--level LEVEL`: Compression level (0-9). Higher compression levels are really slow.
|
|
|
|
## `uw8 filter-exports`
|
|
|
|
Usage:
|
|
|
|
`uw8 filter-exports <infile> <outfile>`
|
|
|
|
Reads a binary WebAssembly module, removes all exports not used by the MicroW8 platform + everything that is unreachable without those exports and writes the resulting module to `outfile`.
|
|
|
|
When compiling C code (or Rust, zig or others) to WebAssembly, you end up with a few exported global variables that are used for managing the heap and C stack, even if the code doesn't actually use those features. You can use this command to automatically remove those and gain a few bytes. See the C, Rust and zig examples in the MicroW8 repository.
|
|
|
|
# Distribution
|
|
|
|
## Base64 encoded link
|
|
|
|
## url parameter
|
|
|
|
## `.html` + `.uw8`
|
|
|
|
## Itch.io
|
|
|
|
# `.uw8` format
|
|
|
|
The first byte of the file specifies the format version:
|
|
|
|
## Format version `00`:
|
|
|
|
This file is simply a standard WebAssembly module
|
|
|
|
## Format version `01`:
|
|
|
|
The rest of this file is the same as a WebAssembly
|
|
module with the 8 byte header removed. This module
|
|
can leave out sections which are then taken from
|
|
a base module provided by MicroW8.
|
|
|
|
You can generate this base module yourself using
|
|
`uw8-tool`. As a quick summary, it provides all function
|
|
types with up to 5 parameters (i32 or f32) where the
|
|
`f32` parameters always preceed the `i32` parameters.
|
|
Then it includes all imports that MicroW8 provides,
|
|
a function section with a single function of type
|
|
`() -> void` and an export section that exports
|
|
the first function in the file under the name `upd`.
|
|
|
|
## Format version `02`:
|
|
|
|
Same as version `01` except everything after the first byte is compressed
|
|
using a [custom LZ compression scheme](https://github.com/exoticorn/upkr).
|