mirror of
https://github.com/exoticorn/microw8.git
synced 2026-01-20 11:16:42 +01:00
improve file selection button, first version of uw8-tool to build base.wasm
This commit is contained in:
39
uw8-tool/Cargo.lock
generated
Normal file
39
uw8-tool/Cargo.lock
generated
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee10e43ae4a853c0a3591d4e2ada1719e553be18199d9da9d4a83f5927c2f5c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "leb128"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uw8-tool"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"wasm-encoder",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-encoder"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db0c351632e46cc06a58a696a6c11e4cf90cad4b9f8f07a0b59128d616c29bb0"
|
||||||
|
dependencies = [
|
||||||
|
"leb128",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasmparser"
|
||||||
|
version = "0.81.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "98930446519f63d00a836efdc22f67766ceae8dbcc1571379f2bcabc6b2b9abc"
|
||||||
11
uw8-tool/Cargo.toml
Normal file
11
uw8-tool/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "uw8-tool"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wasmparser = "0.81"
|
||||||
|
wasm-encoder = "0.8"
|
||||||
|
anyhow = "1"
|
||||||
152
uw8-tool/src/base_module.rs
Normal file
152
uw8-tool/src/base_module.rs
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
use std::{collections::HashMap, fs::File, path::Path};
|
||||||
|
|
||||||
|
use wasm_encoder::{
|
||||||
|
CodeSection, EntityType, Export, ExportSection, Function, FunctionSection,
|
||||||
|
ImportSection, Instruction, MemoryType, Module, TypeSection, ValType,
|
||||||
|
};
|
||||||
|
use ValType::*;
|
||||||
|
use anyhow::{Result, bail};
|
||||||
|
use std::io::prelude::*;
|
||||||
|
|
||||||
|
pub struct BaseModule {
|
||||||
|
pub types: Vec<FunctionType>,
|
||||||
|
pub function_imports: Vec<(&'static str, &'static str, u32)>,
|
||||||
|
pub functions: Vec<u32>,
|
||||||
|
pub exports: Vec<(&'static str, u32)>,
|
||||||
|
pub memory: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct FunctionType {
|
||||||
|
pub params: Vec<ValType>,
|
||||||
|
pub result: Option<ValType>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BaseModule {
|
||||||
|
pub fn for_format_version(version: u32) -> Result<BaseModule> {
|
||||||
|
if version != 1 {
|
||||||
|
bail!("Unsupported format version ({})", version);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut types = vec![];
|
||||||
|
let mut type_map = HashMap::new();
|
||||||
|
for num_params in 0..6 {
|
||||||
|
for num_f32 in 0..=num_params {
|
||||||
|
for &result in &[None, Some(ValType::I32), Some(ValType::F32)] {
|
||||||
|
let mut params = vec![];
|
||||||
|
for _ in 0..num_f32 {
|
||||||
|
params.push(F32);
|
||||||
|
}
|
||||||
|
for _ in num_f32..num_params {
|
||||||
|
params.push(I32);
|
||||||
|
}
|
||||||
|
let type_ = FunctionType { params, result };
|
||||||
|
type_map.insert(type_.clone(), types.len() as u32);
|
||||||
|
types.push(type_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut functions = vec![];
|
||||||
|
add_function(&mut functions, &type_map, "math","sin", &[F32], Some(F32));
|
||||||
|
add_function(&mut functions, &type_map, "math", "cos", &[F32], Some(F32));
|
||||||
|
add_function(&mut functions, &type_map, "math", "tan", &[F32], Some(F32));
|
||||||
|
add_function(&mut functions, &type_map, "math", "asin", &[F32], Some(F32));
|
||||||
|
add_function(&mut functions, &type_map, "math", "acos", &[F32], Some(F32));
|
||||||
|
add_function(&mut functions, &type_map, "math", "atan", &[F32], Some(F32));
|
||||||
|
add_function(&mut functions, &type_map, "math", "atan2", &[F32, F32], Some(F32));
|
||||||
|
add_function(&mut functions, &type_map, "math", "pow", &[F32, F32], Some(F32));
|
||||||
|
add_function(&mut functions, &type_map, "math", "log", &[F32], Some(F32));
|
||||||
|
|
||||||
|
let first_function = functions.len() as u32;
|
||||||
|
|
||||||
|
Ok(BaseModule {
|
||||||
|
types,
|
||||||
|
function_imports: functions,
|
||||||
|
functions: vec![lookup_type(&type_map, &[I32], None)],
|
||||||
|
exports: vec![("tic", first_function)],
|
||||||
|
memory: 4
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
|
||||||
|
fn inner(m: &BaseModule, path: &Path) -> Result<()> {
|
||||||
|
let mut module = Module::new();
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut types = TypeSection::new();
|
||||||
|
for type_ in &m.types {
|
||||||
|
types.function(type_.params.iter().cloned(), type_.result.iter().cloned());
|
||||||
|
}
|
||||||
|
module.section(&types);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut imports = ImportSection::new();
|
||||||
|
|
||||||
|
for (module, name, type_) in &m.function_imports {
|
||||||
|
imports.import(*module, Some(*name), EntityType::Function(*type_));
|
||||||
|
}
|
||||||
|
|
||||||
|
imports.import("env", Some("memory"), MemoryType {
|
||||||
|
minimum: m.memory as u64,
|
||||||
|
maximum: None,
|
||||||
|
memory64: false
|
||||||
|
});
|
||||||
|
|
||||||
|
module.section(&imports);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut functions = FunctionSection::new();
|
||||||
|
|
||||||
|
for type_ in &m.functions {
|
||||||
|
functions.function(*type_);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.section(&functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut exports = ExportSection::new();
|
||||||
|
|
||||||
|
for (name, fnc) in &m.exports {
|
||||||
|
exports.export(*name, Export::Function(*fnc));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.section(&exports);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut code = CodeSection::new();
|
||||||
|
|
||||||
|
for _ in &m.functions {
|
||||||
|
let mut function = Function::new([]);
|
||||||
|
function.instruction(&Instruction::End);
|
||||||
|
code.function(&function);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.section(&code);
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = module.finish();
|
||||||
|
|
||||||
|
File::create(path)?.write_all(&data)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
inner(self, path.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_function(functions: &mut Vec<(&'static str, &'static str, u32)>, type_map: &HashMap<FunctionType, u32>, module: &'static str, name: &'static str, params: &[ValType], result: Option<ValType>) {
|
||||||
|
functions.push((module, name, lookup_type(type_map, params, result)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_type(type_map: &HashMap<FunctionType, u32>, params: &[ValType], result: Option<ValType>) -> u32 {
|
||||||
|
let key = FunctionType {
|
||||||
|
params: params.to_vec(),
|
||||||
|
result
|
||||||
|
};
|
||||||
|
*type_map.get(&key).unwrap()
|
||||||
|
}
|
||||||
9
uw8-tool/src/main.rs
Normal file
9
uw8-tool/src/main.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
mod base_module;
|
||||||
|
|
||||||
|
use base_module::BaseModule;
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
BaseModule::for_format_version(1)?.write_to_file("base.wasm")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -12,8 +12,7 @@
|
|||||||
<div id="centered">
|
<div id="centered">
|
||||||
<canvas id="screen" width="640" height="512"></canvas>
|
<canvas id="screen" width="640" height="512"></canvas>
|
||||||
<div id="message"></div>
|
<div id="message"></div>
|
||||||
<button onclick="document.getElementById('cart').click()">Load cart...</button>
|
<button id="cartButton">Load cart...</button>
|
||||||
<input id="cart" style="visibility: hidden" type="file" accept=".wasm,.uw8,application/wasm">
|
|
||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<a href="http://unlicense.org/" ref="license">Unlicense</a>
|
<a href="http://unlicense.org/" ref="license">Unlicense</a>
|
||||||
|
|||||||
@@ -80,14 +80,15 @@ async function runModule(data) {
|
|||||||
|
|
||||||
let importObject = {
|
let importObject = {
|
||||||
env: {
|
env: {
|
||||||
memory: new WebAssembly.Memory({ initial: 8, maximum: 8 }),
|
memory: new WebAssembly.Memory({ initial: 4, maximum: 4 }),
|
||||||
},
|
},
|
||||||
math: {
|
math: {}
|
||||||
sin: Math.sin,
|
|
||||||
cos: Math.cos
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for(let n of ['acos','asin','atan','atan2','cos','exp','log','sin','tan']) {
|
||||||
|
importObject.math[n] = Math[n];
|
||||||
|
}
|
||||||
|
|
||||||
let instance = new WebAssembly.Instance(await WebAssembly.compile(data), importObject);
|
let instance = new WebAssembly.Instance(await WebAssembly.compile(data), importObject);
|
||||||
|
|
||||||
let buffer = imageData.data;
|
let buffer = imageData.data;
|
||||||
@@ -141,12 +142,17 @@ function runModuleFromHash() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let fileInput = document.getElementById('cart');
|
|
||||||
fileInput.onchange = () => {
|
|
||||||
if(fileInput.files.length > 0) {
|
|
||||||
runModuleFromURL(URL.createObjectURL(fileInput.files[0]));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
window.onhashchange = runModuleFromHash;
|
window.onhashchange = runModuleFromHash;
|
||||||
runModuleFromHash();
|
runModuleFromHash();
|
||||||
|
|
||||||
|
document.getElementById('cartButton').onclick = () => {
|
||||||
|
let fileInput = document.createElement('input');
|
||||||
|
fileInput.type = 'file';
|
||||||
|
fileInput.accept = '.wasm,.uw8,application/wasm';
|
||||||
|
fileInput.onchange = () => {
|
||||||
|
if(fileInput.files.length > 0) {
|
||||||
|
runModuleFromURL(URL.createObjectURL(fileInput.files[0]));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fileInput.click();
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user