add input to web runtime, add v0.1pre3 to site

This commit is contained in:
2021-12-01 23:36:39 +01:00
parent 04c2c1aeb0
commit aba00b1cae
9 changed files with 122 additions and 28 deletions

View File

@@ -38,12 +38,6 @@ export fn upd() {
if y == 180 & py > zero { if y == 180 & py > zero {
if x > w | x < zero { if x > w | x < zero {
if btn(5) {
pz = 5;
px = 2 as f32;
}
return; return;
} }
py = zero; py = zero;

View File

@@ -13,6 +13,7 @@ theme = "juice"
# Whether to do syntax highlighting # Whether to do syntax highlighting
# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola # Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola
highlight_code = true highlight_code = true
highlight_theme = "ascetic-white"
[extra] [extra]
# Put all your custom variables here # Put all your custom variables here

View File

@@ -5,13 +5,14 @@
* [v0.1pre1](v0.1pre1) * [v0.1pre1](v0.1pre1)
* [v0.1pre2](v0.1pre2) * [v0.1pre2](v0.1pre2)
* [v0.1pre3](v0.1pre3)
## Spec ## Spec
MicroW8 loads WebAssembly modules with a maximum size of 256kb. You module needs to export MicroW8 loads WebAssembly modules with a maximum size of 256kb. You module needs to export
a function `fn tic(time: i32)` which will be called once per frame. a function `fn upd()` which will be called once per frame.
After calling `tic` MicroW8 will display the 320x256 8bpp framebuffer located After calling `upd` MicroW8 will display the 320x240 8bpp framebuffer located
at offset 120 in memory with the 32bpp palette located at 82040. 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). The memory has to be imported as `"env" "memory"` and has a maximum size of 256kb (4 pages).
@@ -40,6 +41,29 @@ Other imports provided by the platform, also all in module `env`:
* `fn rectangle(x1: f32, y1: f32, x2: f32, y2: f32, color: i32)` * `fn rectangle(x1: f32, y1: f32, x2: f32, y2: f32, color: i32)`
* `fn circle(cx: f32, cy: f32, radius: f32, color: i32)` * `fn circle(cx: f32, cy: f32, radius: f32, color: i32)`
* `fn time() -> f32`
* `fn isButtonPressed(btn: i32) -> i32`
* `fn isButtonTriggered(btn: i32) -> i32`
* `fn printChar(char: i32)`
* `fn printString(ptr: i32)`
* `fn printInt(num: i32)`
### 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
```
## `.uw8` format ## `.uw8` format
The first byte of the file specifies the format version: The first byte of the file specifies the format version:
@@ -62,7 +86,12 @@ types with up to 5 parameters (i32 or f32) where the
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
`(i32) -> void` and an export section that exports `(i32) -> void` and an export section that exports
the first function in the file under the name `tic`. 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).
## Tooling ## Tooling
@@ -82,7 +111,9 @@ Writing code for MicroW8 in C, Rust, AssemblyScript etc. should absolutely
possible but no examples are provided, yet. possible but no examples are provided, yet.
## Examples ## Examples
* [Skip Ahead](v0.1pre3#Agj9nQYWw+yYP6xi7SUL2urlNtvh2dOZFuYL4PUxAUz5qqATDey0JsAVat2VQKEOyXK1bE+3WiFK0GGhdi4VAd8Tlf3YuU7xfvvBwN4oNuIoY29jbbuEnEnPZFjC4ym9L2QDUmig+RsF++FubWcyqOt7CAFGNEaAiMISCIM43bfPQriE6sD3orstkMjH3LPOqeuUPpitgzaIsAf860CYHlrAG2t5CSjRGobcPLJ+CSeYjzZSLYs7+u2xpthsfoIvBnk1+xxwEWYfZOJ3Madfo5BME5nceVCQVOEBMCTLSE+xVCkyelOW) (231 bytes): A port of my [TIC-80 256byte game](http://tic80.com/play?cart=1735) from LoveByte'21
* [Technotunnel](v0.1pre2#AQrDAQHAAQIBfwp9A0AgAUEAsiABQcACb7JDmhkgQ5MiBCAEIASUIAFBwAJtQfgAa7IiBSAFlJKRIgaVIgcgByAAskHQD7KVIgIQAEPNzEw/lCIDlCAHIAeUIAOUIAOUQQGykiADIAOUk5GSIgiUIAOTQQqylCACkiIJqCAFIAaVIAiUQQqylCACkiIKqHMgCEEyspQgBpUiCyACkkEUspSocUEFcbJBArIgC5OUQRaylJeoOgB4IAFBAWoiAUGA2ARIDQALCw==) (199 bytes): A port of my [entry](https://tic80.com/play?cart=1873) in the Outline'21 bytebattle quater final * [OhNoAnotherTunnel](v0.1pre3#Apr9u4e6Rsy7tRABjq4o7dCGPLQR9dVTSGK9FWXemB7tybsZHT+TxtfHlarRbcekGcg7qZY/eK6/VVCp9ceNBXlh4v0QGS63LTzfEjb8XC4jg5KifbYBodSIS0DPVjwq32PbgjL2+C+QOCx6ZxqRYP0KQpcTxuBUKx1NXVM2EV4l0rEWBQW9SjLcbURKHYaRLcI4FOcLOfASFiQ4wFWgEBA0VD6hGdemN0tPYp9BfUaN) (177 bytes): A port of my [entry](http://tic80.com/play?cart=1871) in the Outline'21 bytebattle final
* [XorScroll](v0.1pre2#AQovAS0BAX8DQCABIAFBwAJvIABBCm1qIAFBwAJtczoAeCABQQFqIgFBgNgESA0ACws=) (50 bytes): A simple scrolling XOR pattern. Fun fact: This is the pre-loaded effect when entering a bytebattle. * [Technotunnel](v0.1pre3#AkL/tETJ+XRrvcB8gD9brftZ26zjwEsiATnAd+szCtw3Haq41srEMFO8aDS71c2CX8W87RQ9EY3V+YuTn/2CPRfn6CpgxMHUnIxOEWhVDRULXeYGP70dTiL8tYLAc8LrBWay9h8jCX/4Jbb39XVnISlZNd7In4Mts9LvSkSIz/E0sBfhjwp65aeoSU8BNFZpyKlxU+u5DdBtuxx3bFE=) (158 bytes): A port of my [entry](https://tic80.com/play?cart=1873) in the Outline'21 bytebattle quater final
* [CircleWorm](v0.1pre2#AQp7AXkCAX8CfUEgEA0DQCABskEEspUiAkECspUgALJBiCeylSIDQQWylJIQAEEBspJBoAGylCACQQOylSADQQSylJIQAEEBspJB+ACylCADQRGylCACQQKylJIQAEECspJBELKUIAFBAmxBP2oQEiABQQFqIgFBP0gNAAsL) (126 bytes): Just a test for the circle fill function. * [Technotunnel B/W](v0.1pre2#AQrDAQHAAQIBfwp9A0AgAUEAsiABQcACb7JDmhkgQ5MiBCAEIASUIAFBwAJtQfgAa7IiBSAFlJKRIgaVIgcgByAAskHQD7KVIgIQAEPNzEw/lCIDlCAHIAeUIAOUIAOUQQGykiADIAOUk5GSIgiUIAOTQQqylCACkiIJqCAFIAaVIAiUQQqylCACkiIKqHMgCEEyspQgBpUiCyACkkEUspSocUEFcbJBArIgC5OUQRaylJeoOgB4IAFBAWoiAUGA2ARIDQALCw==) (199 bytes uncompressed): A port of my [entry](https://tic80.com/play?cart=1873) in the Outline'21 bytebattle quater final (older MicroW8 version with monochrome palette)
* [XorScroll](v0.1pre2#AQovAS0BAX8DQCABIAFBwAJvIABBCm1qIAFBwAJtczoAeCABQQFqIgFBgNgESA0ACws=) (50 bytes uncompressed): A simple scrolling XOR pattern. Fun fact: This is the pre-loaded effect when entering a bytebattle.
* [CircleWorm](v0.1pre2#AQp7AXkCAX8CfUEgEA0DQCABskEEspUiAkECspUgALJBiCeylSIDQQWylJIQAEEBspJBoAGylCACQQOylSADQQSylJIQAEEBspJB+ACylCADQRGylCACQQKylJIQAEECspJBELKUIAFBAmxBP2oQEiABQQFqIgFBP0gNAAsL) (126 bytes uncompressed): Just a test for the circle fill function.

File diff suppressed because one or more lines are too long

View File

@@ -7,8 +7,8 @@
/* Primary theme link color */ /* Primary theme link color */
--primary-link-color: #8080a0; --primary-link-color: #8080a0;
/* Secondary color: the background body color */ /* Secondary color: the background body color */
--secondary-color: #e4dfd7; --secondary-color: #e0e0e8;
--secondary-text-color: #303030; --secondary-text-color: #1a1818;
/* Highlight text color of table of content */ /* Highlight text color of table of content */
--toc-highlight-text-color: #d46e13; --toc-highlight-text-color: #d46e13;
} }

View File

@@ -4,7 +4,7 @@
<section> <section>
<h1 class="text-center heading-text">A WebAssembly based sizecoding platform</h1> <h1 class="text-center heading-text">A WebAssembly based sizecoding platform</h1>
</section> </section>
<a href="v0.1pre2"> <a href="v0.1pre3">
<div class="demonstration-gif" style="width:640px;height:512px;background-color:black"></div> <div class="demonstration-gif" style="width:640px;height:512px;background-color:black"></div>
</a> </a>
</div> </div>

View File

@@ -24,6 +24,7 @@ struct UW8Instance {
end_frame: TypedFunc<(), ()>, end_frame: TypedFunc<(), ()>,
update: TypedFunc<(), ()>, update: TypedFunc<(), ()>,
start_time: Instant, start_time: Instant,
module: Vec<u8>
} }
impl MicroW8 { impl MicroW8 {
@@ -68,7 +69,7 @@ impl MicroW8 {
self.load_from_memory(&module) self.load_from_memory(&module)
} }
pub fn load_from_memory(&mut self, module: &[u8]) -> Result<()> { pub fn load_from_memory(&mut self, module_data: &[u8]) -> Result<()> {
self.reset(); self.reset();
let mut store = wasmtime::Store::new(&self.engine, ()); let mut store = wasmtime::Store::new(&self.engine, ());
@@ -88,8 +89,8 @@ impl MicroW8 {
let platform_module = let platform_module =
wasmtime::Module::new(&self.engine, &memory.data(&store)[..platform_length])?; wasmtime::Module::new(&self.engine, &memory.data(&store)[..platform_length])?;
memory.data_mut(&mut store)[..module.len()].copy_from_slice(module); memory.data_mut(&mut store)[..module_data.len()].copy_from_slice(module_data);
let module_length = load_uw8.call(&mut store, module.len() as i32)? as u32 as usize; let module_length = load_uw8.call(&mut store, module_data.len() as i32)? as u32 as usize;
let module = wasmtime::Module::new(&self.engine, &memory.data(&store)[..module_length])?; let module = wasmtime::Module::new(&self.engine, &memory.data(&store)[..module_length])?;
linker.func_wrap("env", "acos", |v: f32| v.acos())?; linker.func_wrap("env", "acos", |v: f32| v.acos())?;
@@ -139,6 +140,7 @@ impl MicroW8 {
end_frame, end_frame,
update, update,
start_time: Instant::now(), start_time: Instant::now(),
module: module_data.into()
}); });
Ok(()) Ok(())
@@ -174,7 +176,11 @@ impl MicroW8 {
| palette[offset + 2] as u32; | palette[offset + 2] as u32;
} }
self.instance = Some(instance); if self.window.is_key_pressed(Key::R, minifb::KeyRepeat::No) {
self.load_from_memory(&instance.module)?;
} else {
self.instance = Some(instance);
}
} }
self.window self.window

View File

@@ -15,7 +15,56 @@ let imageData = canvasCtx.createImageData(320, 240);
let cancelFunction; let cancelFunction;
let currentData;
let U8 = (d) => new Uint8Array(d); let U8 = (d) => new Uint8Array(d);
let U32 = (d) => new Uint32Array(d);
let pad = 0;
let keyHandler = (e) => {
let isKeyDown = e.type == 'keydown';
let mask;
switch(e.code) {
case 'ArrowUp':
mask = 1;
break;
case 'ArrowDown':
mask = 2;
break;
case 'ArrowLeft':
mask = 4;
break;
case 'ArrowRight':
mask = 8;
break;
case 'KeyZ':
mask = 16;
break;
case 'KeyX':
mask = 32;
break;
case 'KeyA':
mask = 64;
break;
case 'KeyS':
mask = 128;
break;
case 'KeyR':
if(isKeyDown)
{
runModule(currentData);
}
break;
}
if(isKeyDown) {
pad |= mask;
} else {
pad &= ~mask;
}
};
window.onkeydown = keyHandler;
window.onkeyup = keyHandler;
async function runModule(data) { async function runModule(data) {
if (cancelFunction) { if (cancelFunction) {
@@ -30,6 +79,8 @@ async function runModule(data) {
return; return;
} }
currentData = data;
let newURL = window.location.pathname; let newURL = window.location.pathname;
if (cartridgeSize <= 1024) { if (cartridgeSize <= 1024) {
let dataString = ''; let dataString = '';
@@ -94,27 +145,36 @@ async function runModule(data) {
let instance = await instantiate(data); let instance = await instantiate(data);
let buffer = new Uint32Array(imageData.data.buffer); let buffer = U32(imageData.data.buffer);
let startTime = Date.now(); let startTime = Date.now();
let keepRunning = true; let keepRunning = true;
cancelFunction = () => keepRunning = false; cancelFunction = () => keepRunning = false;
const timePerFrame = 1000 / 60;
let nextFrame = startTime;
function mainloop() { function mainloop() {
if (!keepRunning) { if (!keepRunning) {
return; return;
} }
try { try {
new Uint32Array(memory.buffer)[16] = Date.now() - startTime; let now = Date.now();
instance.exports.upd(); if(now >= nextFrame) {
let u32Mem = U32(memory.buffer);
u32Mem[16] = now - startTime;
u32Mem[17] = pad;
instance.exports.upd();
let palette = new Uint32Array(memory.buffer.slice(0x13000, 0x13000 + 1024)); let palette = U32(memory.buffer.slice(0x13000, 0x13000 + 1024));
for (let i = 0; i < 320 * 240; ++i) { for (let i = 0; i < 320 * 240; ++i) {
buffer[i] = palette[memU8[i + 120]] | 0xff000000; buffer[i] = palette[memU8[i + 120]] | 0xff000000;
}
canvasCtx.putImageData(imageData, 0, 0);
nextFrame = Math.max(nextFrame + timePerFrame, now);
} }
canvasCtx.putImageData(imageData, 0, 0);
window.requestAnimationFrame(mainloop); window.requestAnimationFrame(mainloop);
} catch (err) { } catch (err) {

View File

@@ -41,6 +41,7 @@ a:hover {
margin-bottom: 8px; margin-bottom: 8px;
border: 4px solid #303040; border: 4px solid #303040;
box-shadow: 5px 5px 20px black; box-shadow: 5px 5px 20px black;
cursor: none;
} }
#message { #message {