Files
microw8/docs/index.html
2022-01-11 23:04:42 +00:00

432 lines
23 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Docs | </title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="icon" type="image/png" href="/favicon.ico">
<style>
:root {
/* Primary theme color */
--primary-color: #202024;
/* Primary theme text color */
--primary-text-color: #808070;
/* Primary theme link color */
--primary-link-color: #8080a0;
/* Secondary color: the background body color */
--secondary-color: #e0e0e8;
--secondary-text-color: #1a1818;
/* Highlight text color of table of content */
--toc-highlight-text-color: #d46e13;
}
</style>
<link href="https://fonts.googleapis.com/css?family=Alfa+Slab+One&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Fira+Sans:400,500,600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/normalize.css">
<link rel="stylesheet" href="https://exoticorn.github.io/microw8/juice.css">
</head>
<body>
<header class="box-shadow">
<a href="https:&#x2F;&#x2F;exoticorn.github.io&#x2F;microw8&#x2F;">
<div class="logo">
<img src="https://exoticorn.github.io/microw8/microw8.svg" alt="logo">
MicroW8
</div>
</a>
<nav>
<a class="nav-item subtitle-text" href="https:&#x2F;&#x2F;exoticorn.github.io&#x2F;microw8&#x2F;docs&#x2F;">Docs</a>
<a class="nav-item subtitle-text" href="https:&#x2F;&#x2F;github.com&#x2F;exoticorn&#x2F;microw8">Github</a>
</nav>
</header>
<main>
<div class="toc">
<div class="toc-sticky">
<div class="toc-item">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#overview">Overview</a>
</div>
<div class="toc-item">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#memory-map">Memory map</a>
</div>
<div class="toc-item">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#api">API</a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#math"><small>- Math</small></a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#random"><small>- Random</small></a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#graphics"><small>- Graphics</small></a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#input"><small>- Input</small></a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#text-output"><small>- Text output</small></a>
</div>
<div class="toc-item">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#the-uw8-tool">The uw8 tool</a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#uw8-run"><small>- uw8 run</small></a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#uw8-pack"><small>- uw8 pack</small></a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#uw8-filter-exports"><small>- uw8 filter-exports</small></a>
</div>
<div class="toc-item">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#distribution">Distribution</a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#base64-encoded-link"><small>- Base64 encoded link</small></a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#url-parameter"><small>- url parameter</small></a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#html-uw8"><small>- .html + .uw8</small></a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#itch-io"><small>- Itch.io</small></a>
</div>
<div class="toc-item">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#uw8-format">.uw8 format</a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#format-version-00"><small>- Format version 00:</small></a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#format-version-01"><small>- Format version 01:</small></a>
</div>
<div class="toc-item-child">
<a class="subtext" href="https://exoticorn.github.io/microw8/docs/#format-version-02"><small>- Format version 02:</small></a>
</div>
</div>
</div>
<div class="content text">
<div class="heading-text">Docs</div>
<h1 id="overview">Overview</h1>
<p>MicroW8 loads WebAssembly modules with a maximum size of 256kb. You module needs to export
a function <code>fn upd()</code> which will be called once per frame.
After calling <code>upd</code> MicroW8 will display the 320x240 8bpp framebuffer located
at offset 120 in memory with the 32bpp palette located at 0x13000.</p>
<p>The memory has to be imported as <code>env</code> <code>memory</code> and has a maximum size of 256kb (4 pages).</p>
<h1 id="memory-map">Memory map</h1>
<pre style="background-color:#ffffff;color:#202020;"><code><span>00000-00040: user memory
</span><span>00040-00044: time since module start in ms
</span><span>00044-0004c: gamepad state
</span><span>0004c-00078: reserved
</span><span>00078-12c78: frame buffer
</span><span>12c78-13000: reserved
</span><span>13000-13400: palette
</span><span>13400-13c00: font
</span><span>13c00-14000: reserved
</span><span>14000-40000: user memory
</span></code></pre>
<h1 id="api">API</h1>
<p>All API functions are found in the <code>env</code> module.</p>
<h2 id="math">Math</h2>
<p>These all do what you'd expect them to. All angles are in radians.</p>
<h3 id="fn-asin-x-f32-f32">fn asin(x: f32) -&gt; f32</h3>
<p>Returns the arcsine of <code>x</code>.</p>
<h3 id="fn-acos-x-f32-f32">fn acos(x: f32) -&gt; f32</h3>
<p>Returns the arccosine of <code>x</code>.</p>
<h3 id="fn-atan-f32-f32">fn atan(f32) -&gt; f32</h3>
<p>Returns the arctangent of <code>x</code>.</p>
<h3 id="fn-atan2-y-f32-y-f32-f32">fn atan2(y: f32, y: f32) -&gt; f32</h3>
<p>Returns the angle between the point <code>(x, y)</code> and the positive x-axis.</p>
<h3 id="fn-sin-angle-f32-f32">fn sin(angle: f32) -&gt; f32</h3>
<p>Returns the sine of <code>angle</code>.</p>
<h3 id="fn-tan-angle-f32-f32">fn tan(angle: f32) -&gt; f32</h3>
<p>Returns the tangent of <code>angle</code>.</p>
<h3 id="fn-cos-angle-f32-f32">fn cos(angle: f32) -&gt; f32</h3>
<p>Returns the cosine of <code>angle</code>.</p>
<h3 id="fn-exp-x-f32-f32">fn exp(x: f32) -&gt; f32</h3>
<p>Returns <code>e^x</code>.</p>
<h3 id="fn-log-x-f32-f32">fn log(x: f32) -&gt; f32</h3>
<p>Returns the natural logarithmus of <code>x</code>. Ie. <code>e^log(x) == x</code>.</p>
<h3 id="fn-pow-x-f32-y-f32-f32">fn pow(x: f32, y: f32) -&gt; f32</h3>
<p>Returns <code>x^y</code>.</p>
<h3 id="fn-fmod-x-f32-y-f32-f32">fn fmod(x: f32, y: f32) -&gt; f32</h3>
<p>Returns <code>x</code> modulo <code>y</code>, ie. <code>x - floor(x / y) * y</code>. This means the sign of the result of <code>fmod</code> is the same as <code>y</code>.</p>
<h2 id="random">Random</h2>
<p>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.</p>
<h3 id="fn-random-i32">fn random() -&gt; i32</h3>
<p>Returns a (pseudo-)random 32bit integer.</p>
<h3 id="fn-randomf-f32">fn randomf() -&gt; f32</h3>
<p>Returns a (pseudo-)random float equally distributed in <code>[0,1)</code>.</p>
<h3 id="fn-randomseed-seed-i32">fn randomSeed(seed: i32)</h3>
<p>Seeds the PRNG with the given seed. The seed function is reasonably strong so that you can use</p>
<pre style="background-color:#ffffff;color:#202020;"><code><span>randomSeed(index);
</span><span>random()
</span></code></pre>
<p>as a cheap random-access PRNG (aka noise function).</p>
<h2 id="graphics">Graphics</h2>
<p>The default palette can be seen <a href="../v0.1pre4#AgKaeeOuwg5gCKvFIeiitEwMpUI2rymEcu+DDB1vMu9uBoufvUxIr4Y5p4Jj2ukoNO4PE7QS5cN1ZyDMCRfSzYIGZxKlN2J6NKEWK7KVPk9wVUgn1Ip+hsMinWgEO8ETKfPuHoIa4kjI+ULFOMad7vd3rt/lh1Vy9w+R2MXG/7T61d3c7C6KY+eQNS0eW3ys4iU8R6SycuWZuuZ2Sg3Qxp826s+Kt+2qBojpzNOSoyFqyrVyYMTKEkSl0BZOj59Cs1hPm5bq0F1MmVhGAzMhW9V4YeAe">here</a>. (Press Z on the keyboard to switch to palette.)</p>
<p>The palette can be changed by writing 32bit rgba colors to addresses 0x13000-0x13400.</p>
<p>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 <code>0,0 - 1,1</code>, with <code>0.5,0.5</code> being the pixel center.</p>
<h3 id="fn-cls-color-i32">fn cls(color: i32)</h3>
<p>Clears the screen to the given color index. Also sets the text cursor to <code>0, 0</code> and disables graphical text mode.</p>
<h3 id="fn-setpixel-x-i32-y-i32-color-i32">fn setPixel(x: i32, y: i32, color: i32)</h3>
<p>Sets the pixel at <code>x, y</code> to the given color index.</p>
<h3 id="fn-getpixel-x-i32-y-i32-i32">fn getPixel(x: i32, y: i32) -&gt; i32</h3>
<p>Returns the color index at <code>x, y</code>. Returns <code>0</code> if the given coordinates are outside the screen.</p>
<h3 id="fn-hline-left-i32-right-i32-y-i32-color-i32">fn hline(left: i32, right: i32, y: i32, color: i32)</h3>
<p>Fills the horizontal line <code>[left, right), y</code> with the given color index.</p>
<h3 id="fn-rectangle-x-f32-y-f32-w-f32-h-f32-color-i32">fn rectangle(x: f32, y: f32, w: f32, h: f32, color: i32)</h3>
<p>Fills the rectangle <code>x,y - x+w,y+h</code> with the given color index.</p>
<p>(Sets all pixels where the pixel center lies inside the rectangle.)</p>
<h3 id="fn-circle-cx-f32-cy-f32-radius-f32-color-i32">fn circle(cx: f32, cy: f32, radius: f32, color: i32)</h3>
<p>Fills the circle at <code>cx, cy</code> and with <code>radius</code> with the given color index.</p>
<p>(Sets all pixels where the pixel center lies inside the circle.)</p>
<h3 id="fn-rectangle-outline-x-f32-y-f32-w-f32-h-f32-color-i32">fn rectangle_outline(x: f32, y: f32, w: f32, h: f32, color: i32)</h3>
<p>Draws a one pixel outline on the inside of the given rectangle.</p>
<p>(Draws the outermost pixels that are still inside the rectangle area.)</p>
<h3 id="fn-circle-outline-cx-f32-cy-f32-radius-f32-color-i32">fn circle_outline(cx: f32, cy: f32, radius: f32, color: i32)</h3>
<p>Draws a one pixel outline on the inside of the given circle.</p>
<p>(Draws the outermost pixels that are still inside the circle area.)</p>
<h3 id="fn-line-x1-f32-y1-f32-x2-f32-y2-f32-color-i32">fn line(x1: f32, y1: f32, x2: f32, y2: f32, color: i32)</h3>
<p>Draws a line from <code>x1,y1</code> to <code>x2,y2</code> in the given color index.</p>
<h2 id="input">Input</h2>
<p>MicroW8 provides input from a gamepad with one D-Pad and 4 buttons, or a keyboard emulation thereof.</p>
<p>The buttons are numbered</p>
<table><thead><tr><th>Button</th><th>Keyboard</th><th>Index</th></tr></thead><tbody>
<tr><td>Up</td><td>Arrow-Up</td><td>0</td></tr>
<tr><td>Down</td><td>Arrow-Down</td><td>1</td></tr>
<tr><td>Left</td><td>Arrow-Left</td><td>2</td></tr>
<tr><td>Right</td><td>Arrow-Right</td><td>3</td></tr>
<tr><td>A</td><td>Z</td><td>4</td></tr>
<tr><td>B</td><td>X</td><td>5</td></tr>
<tr><td>X</td><td>A</td><td>6</td></tr>
<tr><td>Y</td><td>S</td><td>7</td></tr>
</tbody></table>
<p>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.</p>
<h3 id="fn-isbuttonpressed-btn-i32-i32">fn isButtonPressed(btn: i32) -&gt; i32</h3>
<p>Returns whether the buttons with the given index is pressed this frame.</p>
<h3 id="fn-isbuttontriggered-btn-i32-i32">fn isButtonTriggered(btn: i32) -&gt; i32</h3>
<p>Returns whether the given button is newly pressed this frame.</p>
<h3 id="fn-time-f32">fn time() -&gt; f32</h3>
<p>Returns the time in seconds since the start of the cart.</p>
<p>The integer time in milliseconds can also be read at address 0x40.</p>
<h2 id="text-output">Text output</h2>
<p>The default font can be seen <a href="../v0.1pre4#AgKaeeOuwg5gCKvFIeiitEwMpUI2rymEcu+DDB1vMu9uBoufvUxIr4Y5p4Jj2ukoNO4PE7QS5cN1ZyDMCRfSzYIGZxKlN2J6NKEWK7KVPk9wVUgn1Ip+hsMinWgEO8ETKfPuHoIa4kjI+ULFOMad7vd3rt/lh1Vy9w+R2MXG/7T61d3c7C6KY+eQNS0eW3ys4iU8R6SycuWZuuZ2Sg3Qxp826s+Kt+2qBojpzNOSoyFqyrVyYMTKEkSl0BZOj59Cs1hPm5bq0F1MmVhGAzMhW9V4YeAe">here</a>.</p>
<p>The font can be changed by writing 1bpp 8x8 characters to addresses 0x13400-0x13c00.</p>
<p>All text printing is done at the cursor position, which is advanced after printing each character.
The cursor is not visible.</p>
<p>Text printing can operate in two modes - normal and graphics. After startup and after <code>cls()</code> normal mode is active.</p>
<h3 id="normal-mode">Normal mode</h3>
<p>In normal mode, text printing is constrained to an 8x8 character grid. Setting the cursor position to <code>2,3</code> will start printing at pixel coordinates <code>16,24</code>.</p>
<p>When printing characters, the full 8x8 pixels are painted with the text and background colors according to the character graphics in the font.</p>
<p>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.</p>
<h3 id="graphics-mode">Graphics mode</h3>
<p>In graphics mode, text can be printed to any pixel position, the cursor position is set in pixel coordinates.</p>
<p>When printing characters only the foreground pixels are set, the background is &quot;transparent&quot;.</p>
<p>Moving/printing past any border does not cause any special operation, the cursor just goes off-screen.</p>
<h3 id="control-chars">Control chars</h3>
<p>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.</p>
<table><thead><tr><th>Code</th><th>Parameters</th><th>Operation</th></tr></thead><tbody>
<tr><td>0</td><td>-</td><td>Nop</td></tr>
<tr><td>1</td><td>char</td><td>Print char (including control chars)</td></tr>
<tr><td>2-3</td><td>-</td><td>Reserved</td></tr>
<tr><td>4</td><td>-</td><td>Switch to normal mode</td></tr>
<tr><td>5</td><td>-</td><td>Switch to graphics mode</td></tr>
<tr><td>6-7</td><td>-</td><td>Reserved</td></tr>
<tr><td>8</td><td>-</td><td>Move cursor left</td></tr>
<tr><td>9</td><td>-</td><td>Move cursor right</td></tr>
<tr><td>10</td><td>-</td><td>Move cursor down</td></tr>
<tr><td>11</td><td>-</td><td>Move cursor up</td></tr>
<tr><td>12</td><td>-</td><td>do <code>cls(background_color)</code></td></tr>
<tr><td>13</td><td>-</td><td>Move cursor to the left border</td></tr>
<tr><td>14</td><td>color</td><td>Set the background color</td></tr>
<tr><td>15</td><td>color</td><td>Set the text color</td></tr>
<tr><td>16-23</td><td>-</td><td>Reserved</td></tr>
<tr><td>24</td><td>-</td><td>Swap text/background colors</td></tr>
<tr><td>25-30</td><td>-</td><td>Reserved</td></tr>
<tr><td>31</td><td>x, y</td><td>Set cursor position (*)</td></tr>
</tbody></table>
<p>(*) In graphics mode, the x coordinate is doubled when using control char 31 to be able to cover the whole screen with one byte.</p>
<h3 id="fn-printchar-char-i32">fn printChar(char: i32)</h3>
<p>Prints the character in the lower 8 bits of <code>char</code>. If the upper 24 bits are non-zero, right-shifts <code>char</code> by 8 bits and loops back to the beginning.</p>
<h3 id="fn-printstring-ptr-i32">fn printString(ptr: i32)</h3>
<p>Prints the zero-terminated string at the given memory address.</p>
<h3 id="fn-printint-num-i32">fn printInt(num: i32)</h3>
<p>Prints <code>num</code> as a signed decimal number.</p>
<h3 id="fn-settextcolor-color-i32">fn setTextColor(color: i32)</h3>
<p>Sets the text color.</p>
<h3 id="fn-setbackgroundcolor-color-i32">fn setBackgroundColor(color: i32)</h3>
<p>Sets the background color.</p>
<h3 id="fn-setcursorposition-x-i32-y-i32">fn setCursorPosition(x: i32, y: i32)</h3>
<p>Sets the cursor position. In normal mode <code>x</code> and <code>y</code> are multiplied by 8 to get the pixel position, in graphics mode they are used as is.</p>
<h1 id="the-uw8-tool">The <code>uw8</code> tool</h1>
<p>The <code>uw8</code> 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 <code>uw8</code> and a text editor of your choice.</p>
<h2 id="uw8-run"><code>uw8 run</code></h2>
<p>Usage:</p>
<p><code>uw8 run [&lt;options&gt;] &lt;file&gt;</code></p>
<p>Runs <code>&lt;file&gt;</code> which can be a binary WebAssembly module, an <code>.uw8</code> cart, a wat (WebAssembly text format) source file or a <a href="https://github.com/exoticorn/curlywas">CurlyWas</a> source file.</p>
<p>Options:</p>
<ul>
<li><code>-w</code>, <code>--watch</code>: Reloads the given file every time it changes on disk.</li>
<li><code>-p</code>, <code>--pack</code>: Pack the file into an <code>.uw8</code> cart before running it and print the resulting size.</li>
<li><code>-u</code>, <code>--uncompressed</code>: Use the uncompressed <code>uw8</code> format for packing.</li>
<li><code>-l LEVEL</code>, <code>--level LEVEL</code>: Compression level (0-9). Higher compression levels are really slow.</li>
<li><code>-o FILE</code>, <code>--output FILE</code>: Write the loaded and optionally packed cart back to disk.</li>
</ul>
<h2 id="uw8-pack"><code>uw8 pack</code></h2>
<p>Usage:</p>
<p><code>uw8 pack [&lt;options&gt;] &lt;infile&gt; &lt;outfile&gt;</code></p>
<p>Packs the WebAssembly module or text file, or <a href="https://github.com/exoticorn/curlywas">CurlyWas</a> source file into a <code>.uw8</code> cart.</p>
<p>Options:</p>
<ul>
<li><code>-u</code>, <code>--uncompressed</code>: Use the uncompressed <code>uw8</code> format for packing.</li>
<li><code>-l LEVEL</code>, <code>--level LEVEL</code>: Compression level (0-9). Higher compression levels are really slow.</li>
</ul>
<h2 id="uw8-filter-exports"><code>uw8 filter-exports</code></h2>
<p>Usage:</p>
<p><code>uw8 filter-exports &lt;infile&gt; &lt;outfile&gt;</code></p>
<p>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 <code>outfile</code>.</p>
<p>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.</p>
<h1 id="distribution">Distribution</h1>
<h2 id="base64-encoded-link">Base64 encoded link</h2>
<h2 id="url-parameter">url parameter</h2>
<h2 id="html-uw8"><code>.html</code> + <code>.uw8</code></h2>
<h2 id="itch-io">Itch.io</h2>
<h1 id="uw8-format"><code>.uw8</code> format</h1>
<p>The first byte of the file specifies the format version:</p>
<h2 id="format-version-00">Format version <code>00</code>:</h2>
<p>This file is simply a standard WebAssembly module</p>
<h2 id="format-version-01">Format version <code>01</code>:</h2>
<p>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.</p>
<p>You can generate this base module yourself using
<code>uw8-tool</code>. As a quick summary, it provides all function
types with up to 5 parameters (i32 or f32) where the
<code>f32</code> parameters always preceed the <code>i32</code> parameters.
Then it includes all imports that MicroW8 provides,
a function section with a single function of type
<code>() -&gt; void</code> and an export section that exports
the first function in the file under the name <code>upd</code>.</p>
<h2 id="format-version-02">Format version <code>02</code>:</h2>
<p>Same as version <code>01</code> except everything after the first byte is compressed
using a <a href="https://github.com/exoticorn/upkr">custom LZ compression scheme</a>.</p>
</div>
</main>
</body>
<script>
function highlightNav(heading) {
let pathname = location.pathname;
document.querySelectorAll(".toc a").forEach((item) => {
item.classList.remove("active");
});
document.querySelector(".toc a[href$='" + pathname + "#" + heading + "']").classList.add("active");
}
let currentHeading = "";
window.onscroll = function () {
let h = document.querySelectorAll("h1,h2,h3,h4,h5,h6");
let elementArr = [];
h.forEach(item => {
if (item.id !== "") {
elementArr[item.id] = item.getBoundingClientRect().top;
}
});
elementArr.sort();
for (let key in elementArr) {
if (!elementArr.hasOwnProperty(key)) {
continue;
}
if (elementArr[key] > 0 && elementArr[key] < 300) {
if (currentHeading !== key) {
highlightNav(key);
currentHeading = key;
}
break;
}
}
}
</script>
</html>