add palette support (default is still greyscale for now)

This commit is contained in:
dranke committed 2021-11-13 22:29:20 +01:00
1 parent 944856b267
commit 294b9f5634
6 files changed
+49 -17

No files matched your search

+12 -4
View File
@@ -26,15 +26,15 @@ export fn randomSeed(s: i32) {
}
export fn fmod(a: f32, b: f32) -> f32 {
let lazy t = a / b;
(t - floor(t)) * b
a - floor(a / b) * b
}
export fn cls(col: i32) {
let i: i32;
col = (col & 255) * 0x1010101;
loop pixels {
i?120 = col;
branch_if (i := i + 1) < 320*256: pixels;
i!120 = col;
branch_if (i := i + 4) < 320*256: pixels;
}
}
@@ -106,3 +106,11 @@ export fn circle(cx: f32, cy: f32, radius: f32, col: i32) {
}
}
}
start fn setup() {
let i: i32;
loop colors {
(i*4)!(120+320*256) = i * 0x10101;
branch_if (i := i + 1) < 256: colors
}
}
+17 -3
View File
@@ -4,13 +4,14 @@
## Versions
* [v0.1pre1](v0.1pre1)
* [v0.1pre2](v0.1pre2)
## Spec
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.
After calling `tic` MicroW8 will display the 320x256 8bpp framebuffer located
at offset 120 in memory.
at offset 120 in memory with the 32bpp palette located at 82040.
The memory has to be imported as `"env" "memory"` and has a maximum size of 256kb (4 pages).
@@ -26,6 +27,18 @@ Other imports provided by the platform, also all in module `env`:
* `fn sin(f32) -> f32`
* `fn tan(f32) -> f32`
* `fn pow(f32) -> f32`
* `fn fmod(f32, f32) -> f32`
* `fn random() -> i32`
* `fn randomf() -> f32`
* `fn randomSeed(i32)`
* `fn cls(color: i32)`
* `fn setPixel(x: i32, y: i32, color: i32)`
* `fn getPixel(x: i32, y: i32) -> i32`
* `fn hline(left: i32, right: i32, y: i32, color: i32)`
* `fn rectangle(x1: f32, y1: f32, x2: f32, y2: f32, color: i32)`
* `fn circle(cx: f32, cy: f32, radius: f32, color: i32)`
## `.uw8` format
@@ -70,5 +83,6 @@ possible but no examples are provided, yet.
## Examples
* [Technotunnel](v0.1pre1#AQrDAQHAAQIBfwp9A0AgAUEAsiABQcACb7JDmhkgQ5MiBCAEIASUIAFBwAJtQYABa7IiBSAFlJKRIgaVIgcgByAAskHQD7KVIgIQAEPNzEw/lCIDlCAHIAeUIAOUIAOUQQGykiADIAOUk5GSIgiUIAOTQQqylCACkiIJqCAFIAaVIAiUQQqylCACkiIKqHMgCEEyspQgBpUiCyACkkEUspSocUEFcbJBArIgC5OUQRaylJeoOgB4IAFBAWoiAUGAgAVIDQALCw==) (199 bytes): A port of my [entry](https://tic80.com/play?cart=1873) in the Outline'21 bytebattle quater final
* [XorScroll](v0.1pre1#AQovAS0BAX8DQCABIAFBwAJvIABBCm1qIAFBwAJtczoAeCABQQFqIgFBgIAFSA0ACws=) (50 bytes): A simple scrolling XOR pattern. Fun fact: This is the pre-loaded effect when entering a bytebattle.
* [Technotunnel](v0.1pre2#AQrDAQHAAQIBfwp9A0AgAUEAsiABQcACb7JDmhkgQ5MiBCAEIASUIAFBwAJtQYABa7IiBSAFlJKRIgaVIgcgByAAskHQD7KVIgIQAEPNzEw/lCIDlCAHIAeUIAOUIAOUQQGykiADIAOUk5GSIgiUIAOTQQqylCACkiIJqCAFIAaVIAiUQQqylCACkiIKqHMgCEEyspQgBpUiCyACkkEUspSocUEFcbJBArIgC5OUQRaylJeoOgB4IAFBAWoiAUGAgAVIDQALCw==) (199 bytes): A port of my [entry](https://tic80.com/play?cart=1873) in the Outline'21 bytebattle quater final
* [XorScroll](v0.1pre2#AQovAS0BAX8DQCABIAFBwAJvIABBCm1qIAFBwAJtczoAeCABQQFqIgFBgIAFSA0ACws=) (50 bytes): A simple scrolling XOR pattern. Fun fact: This is the pre-loaded effect when entering a bytebattle.
* [CircleWorm](v0.1pre2#AQp7AXkCAX8CfUEgEA0DQCABskEEspUiAkECspUgALJBiCeylSIDQQWylJIQAEEBspJBoAGylCACQQOylSADQQSylJIQAEEBspJBgAGylCADQRGylCACQQKylJIQAEECspJBELKUIAFBAmxBP2oQEiABQQFqIgFBP0gNAAsL) (126 bytes): Just a test for the circle fill function.
+1
View File
@@ -0,0 +1 @@
<!doctype html><html><head><meta charset="utf8"><title>MicroW8</title><link href="https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@500&display=swap" rel="stylesheet"><style>body,canvas,html{margin:0;padding:0}html{background-color:#202024;color:#808070;font-family:Josefin Sans,Verdana,Arial Black,sans-serif}body,html{height:100%}body{display:grid;grid-template-rows:1fr 0fr}#centered{align-self:center;justify-self:center}.footer{color:#202420}a{color:#303630}a:hover{color:#405040}canvas{background-color:#202428;border:4px solid #303040;box-shadow:5px 5px 20px #000}#message,canvas{margin-bottom:8px}.error{color:#e04030}button{background-color:#303440;border:1px solid #404040;border-radius:4px;color:#808070;font-family:inherit;padding:4px}button:hover{background-color:#202010}button:active{background-color:#504450}</style></head><body> <div id="centered"> <canvas id="screen" width="640" height="512"></canvas> <div id="message"></div> <button id="cartButton">Load cart...</button> </div> <div id="footer"> <a href="http://unlicense.org/" ref="license">Unlicense</a> </div> </body><script type="module">function A(A){return A&&A.__esModule?A.default:A}async function n(A,n){let e=await(await fetch(A)).arrayBuffer(),g=await WebAssembly.compile(e);return new WebAssembly.Instance(g,n)}function e(A,n){let e=A?`${A} bytes`:"Insert cart";n&&(e+=` - <span class="error">${n.replaceAll("<","&lt;")}</span>`),document.getElementById("message").innerHTML=e}let g=document.createElement("canvas");g.width=320,g.height=256;let l,t=g.getContext("2d"),f=t.createImageData(320,256),Z=document.getElementById("screen"),B=Z.getContext("2d");async function Q(Q){l&&(l(),l=null);let a=Q.byteLength;if(e(a),0==a)return;let c=new Uint8Array(Q),X=window.location.pathname;if(a<=1024){let A="";for(let n of c)A+=String.fromCharCode(n);X+="#"+btoa(A)}X!=window.location.pathname+window.location.hash&&history.pushState(null,null,X),Z.width=Z.width;try{let Z={env:{memory:new WebAssembly.Memory({initial:9})}},X=Z.env.memory.buffer,C=await n(A("data:application/wasm;base64,AGFzbQEAAAABGgRgBH9%2Ff38Bf2ABfwF%2FYAJ%2FfwF%2FYAN%2Ff38AAg8BA2VudgZtZW1vcnkCAAgDBQQAAQIDBwwBCGxvYWRfdXc4AAAKtAIErwEBBX8gAC0AAEEARgRAIAMgACABIABrIgQQAyADIARqDwsgAyACQQgQAyACQQhqIQIgA0EIaiEFIABBAWohBgNAIAYgAUggAiADTiAGLQAAIAItAABMcnEEQCAFIAUgBhACIgdqIQUgAiADSCAGLQAAIAItAABGcQRAIAIgAhABaiECCyAGIAdqIQYMAQsgAiADSARAIAUgBSACEAIiCGohBSACIAhqIQIMAQsLIAULRwEEfyAAQQFqIQFBACECQQAhAwNAIAIgAS0AACIEQf8AcSADdHIhAiADQQdqIQMgAUEBaiEBIARBgAFxDQALIAEgAGsgAmoLEgEBfyAAIAEgARABIgIQAyACCyYAIAJBAEoEQANAIAAgAkEBayICaiABIAJqLQAAOgAAIAINAAsLCw%3D%3D"),Z),F=await(await fetch(A("data:application/wasm;base64,AGFzbQEAAAABugM%2FYAAAYAABf2AAAX1gAX8AYAF%2FAX9gAX8BfWABfQBgAX0Bf2ABfQF9YAJ%2FfwBgAn9%2FAX9gAn9%2FAX1gAn1%2FAGACfX8Bf2ACfX8BfWACfX0AYAJ9fQF%2FYAJ9fQF9YAN%2Ff38AYAN%2Ff38Bf2ADf39%2FAX1gA31%2FfwBgA31%2FfwF%2FYAN9f38BfWADfX1%2FAGADfX1%2FAX9gA319fwF9YAN9fX0AYAN9fX0Bf2ADfX19AX1gBH9%2Ff38AYAR%2Ff39%2FAX9gBH9%2Ff38BfWAEfX9%2FfwBgBH1%2Ff38Bf2AEfX9%2FfwF9YAR9fX9%2FAGAEfX1%2FfwF%2FYAR9fX9%2FAX1gBH19fX8AYAR9fX1%2FAX9gBH19fX8BfWAEfX19fQBgBH19fX0Bf2AEfX19fQF9YAV%2Ff39%2FfwBgBX9%2Ff39%2FAX9gBX9%2Ff39%2FAX1gBX1%2Ff39%2FAGAFfX9%2Ff38Bf2AFfX9%2Ff38BfWAFfX1%2Ff38AYAV9fX9%2FfwF%2FYAV9fX9%2FfwF9YAV9fX1%2FfwBgBX19fX9%2FAX9gBX19fX9%2FAX1gBX19fX1%2FAGAFfX19fX8Bf2AFfX19fX8BfWAFfX19fX0AYAV9fX19fQF%2FYAV9fX19fQF9AqkKUQNlbnYDc2luAAgDZW52A2NvcwAIA2VudgN0YW4ACANlbnYEYXNpbgAIA2VudgRhY29zAAgDZW52BGF0YW4ACANlbnYFYXRhbjIAEQNlbnYDcG93ABEDZW52A2xvZwAIA2VudgRmbW9kABEDZW52BnJhbmRvbQABA2VudgdyYW5kb21mAAIDZW52CnJhbmRvbVNlZWQAAwNlbnYDY2xzAAMDZW52CHNldFBpeGVsABIDZW52CGdldFBpeGVsAAoDZW52BWhsaW5lAB4DZW52CXJlY3RhbmdsZQA5A2VudgZjaXJjbGUAJwNlbnYKcmVzZXJ2ZWQxOQAAA2VudgpyZXNlcnZlZDIwAAADZW52CnJlc2VydmVkMjEAAANlbnYKcmVzZXJ2ZWQyMgAAA2VudgpyZXNlcnZlZDIzAAADZW52CnJlc2VydmVkMjQAAANlbnYKcmVzZXJ2ZWQyNQAAA2VudgpyZXNlcnZlZDI2AAADZW52CnJlc2VydmVkMjcAAANlbnYKcmVzZXJ2ZWQyOAAAA2VudgpyZXNlcnZlZDI5AAADZW52CnJlc2VydmVkMzAAAANlbnYKcmVzZXJ2ZWQzMQAAA2VudgpyZXNlcnZlZDMyAAADZW52CnJlc2VydmVkMzMAAANlbnYKcmVzZXJ2ZWQzNAAAA2VudgpyZXNlcnZlZDM1AAADZW52CnJlc2VydmVkMzYAAANlbnYKcmVzZXJ2ZWQzNwAAA2VudgpyZXNlcnZlZDM4AAADZW52CnJlc2VydmVkMzkAAANlbnYKcmVzZXJ2ZWQ0MAAAA2VudgpyZXNlcnZlZDQxAAADZW52CnJlc2VydmVkNDIAAANlbnYKcmVzZXJ2ZWQ0MwAAA2VudgpyZXNlcnZlZDQ0AAADZW52CnJlc2VydmVkNDUAAANlbnYKcmVzZXJ2ZWQ0NgAAA2VudgpyZXNlcnZlZDQ3AAADZW52CnJlc2VydmVkNDgAAANlbnYKcmVzZXJ2ZWQ0OQAAA2VudgpyZXNlcnZlZDUwAAADZW52CnJlc2VydmVkNTEAAANlbnYKcmVzZXJ2ZWQ1MgAAA2VudgpyZXNlcnZlZDUzAAADZW52CnJlc2VydmVkNTQAAANlbnYKcmVzZXJ2ZWQ1NQAAA2VudgpyZXNlcnZlZDU2AAADZW52CnJlc2VydmVkNTcAAANlbnYKcmVzZXJ2ZWQ1OAAAA2VudgpyZXNlcnZlZDU5AAADZW52CnJlc2VydmVkNjAAAANlbnYKcmVzZXJ2ZWQ2MQAAA2VudgpyZXNlcnZlZDYyAAADZW52CnJlc2VydmVkNjMAAANlbnYLZ19yZXNlcnZlZDADfwADZW52C2dfcmVzZXJ2ZWQxA38AA2VudgtnX3Jlc2VydmVkMgN%2FAANlbnYLZ19yZXNlcnZlZDMDfwADZW52C2dfcmVzZXJ2ZWQ0A38AA2VudgtnX3Jlc2VydmVkNQN%2FAANlbnYLZ19yZXNlcnZlZDYDfwADZW52C2dfcmVzZXJ2ZWQ3A38AA2VudgtnX3Jlc2VydmVkOAN%2FAANlbnYLZ19yZXNlcnZlZDkDfwADZW52DGdfcmVzZXJ2ZWQxMAN%2FAANlbnYMZ19yZXNlcnZlZDExLine truncated
+1 -1
View File
@@ -4,7 +4,7 @@
<section>
<h1 class="text-center heading-text">A WebAssembly based sizecoding platform</h1>
</section>
<a href="v0.1pre1">
<a href="v0.1pre2">
<div class="demonstration-gif" style="width:640px;height:512px;background-color:black"></div>
</a>
</div>
+15 -4
View File
@@ -61,7 +61,8 @@ fn main() -> Result<()> {
let mut loader = Loader::new(&engine)?;
let platform_module = wasmtime::Module::new(&engine, include_bytes!("../platform/platform.wasm"))?;
let platform_module =
wasmtime::Module::new(&engine, include_bytes!("../platform/platform.wasm"))?;
let module = wasmtime::Module::new(&engine, loader.load(&uw8_module)?)?;
@@ -98,7 +99,13 @@ fn main() -> Result<()> {
let platform_instance = linker.instantiate(&mut store, &platform_module)?;
for export in platform_instance.exports(&mut store) {
linker.define("env", export.name(), export.into_func().expect("platform surely only exports functions"))?;
linker.define(
"env",
export.name(),
export
.into_func()
.expect("platform surely only exports functions"),
)?;
}
let instance = linker.instantiate(&mut store, &module)?;
@@ -114,9 +121,13 @@ fn main() -> Result<()> {
tic.call(&mut store, start_time.elapsed().as_millis() as i32)?;
let framebuffer = &memory.data(&store)[120..];
let palette = &framebuffer[320 * 256..];
for i in 0..320 * 256 {
let c = framebuffer[i];
buffer[i] = (c as u32) * 0x01010101;
let offset = framebuffer[i] as usize * 4;
buffer[i] = 0xff000000
| ((palette[offset + 2] as u32) << 16)
| ((palette[offset + 1] as u32) << 8)
| palette[offset] as u32;
}
window.update_with_buffer(&buffer, 320, 256)?;
+3 -5
View File
@@ -105,7 +105,7 @@ async function runModule(data) {
let instance = new WebAssembly.Instance(await WebAssembly.compile(data), importObject);
let buffer = imageData.data;
let buffer = new Uint32Array(imageData.data.buffer);
let startTime = Date.now();
@@ -121,11 +121,9 @@ async function runModule(data) {
instance.exports.tic(Date.now() - startTime);
let framebuffer = new Uint8Array(importObject.env.memory.buffer.slice(120, 120 + 320 * 256));
let palette = new Uint32Array(importObject.env.memory.buffer.slice(82040, 82040 + 1024));
for (let i = 0; i < 320 * 256; ++i) {
buffer[i * 4] = framebuffer[i];
buffer[i * 4 + 1] = framebuffer[i];
buffer[i * 4 + 2] = framebuffer[i];
buffer[i * 4 + 3] = 255;
buffer[i] = palette[framebuffer[i]] | 0xff000000;
}
framebufferCanvasCtx.putImageData(imageData, 0, 0);
canvasCtx.imageSmoothingEnabled = false;