Files
armorpaint/base/sources/backends/data/wasm/start.js
T
2026-02-06 20:43:39 +01:00

975 lines
31 KiB
JavaScript

let memory = null;
let heapu8 = null;
let heapu16 = null;
let heapu32 = null;
let heapi32 = null;
let heapf32 = null;
let heapf64 = null;
let module = null;
let instance = null;
let wgpu_objects = [ null ];
let wgpu_free_ids = [];
let file_buffer = null;
let file_buffer_pos = 0;
let file_dropped = null;
let config_json = "";
function ptr_to_id(ptr) {
if (ptr === null) {
return 0;
}
if (wgpu_free_ids.length > 0) {
let id = wgpu_free_ids.pop();
wgpu_objects[id] = ptr;
return id;
}
wgpu_objects.push(ptr);
return wgpu_objects.length - 1;
}
function id_to_ptr(id) {
return wgpu_objects[id];
}
function release_id(id) {
wgpu_objects[id] = null;
wgpu_free_ids.push(id);
}
function read_string(ptr) {
let str = '';
for (let i = 0; heapu8[ptr + i] != 0; ++i) {
str += String.fromCharCode(heapu8[ptr + i]);
}
return str;
}
function read_string_n(ptr, n) {
let str = '';
for (let i = 0; i < n; ++i) {
str += String.fromCharCode(heapu8[ptr + i]);
}
return str;
}
function read_u32(ptr) {
return heapu32[ptr / 4];
}
function read_f64(ptr) {
return heapf64[ptr / 8];
}
function write_string(ptr, str) {
for (let i = 0; i < str.length; ++i) {
heapu8[ptr + i] = str.charCodeAt(i);
}
heapu8[ptr + str.length] = 0;
}
function id_to_texture_format(id) {
if (id === 0x00000001)
return "r8unorm";
if (id === 0x00000016)
return "rgba8unorm";
if (id === 0x00000030)
return "depth32float";
if (id === 0x0000001B)
return "bgra8unorm";
if (id === 0x00000028)
return "rgba16float";
if (id === 0x00000029)
return "rgba16float";
// return "rgba32float"; // Total color attachment bytes per sample (48) exceeds maximum (32)
if (id === 0x00000009)
return "r16float";
if (id === 0x0000000E)
return "r32float";
}
function id_to_vertex_format(id) {
if (id === 0x0000001C)
return "float32";
if (id === 0x0000001D)
return "float32x2";
if (id === 0x0000001E)
return "float32x3";
if (id === 0x0000001F)
return "float32x4";
if (id === 0x00000017)
return "snorm16x2";
if (id === 0x00000018)
return "snorm16x4";
}
function id_to_blend_factor(id) {
if (id === 0x00000001)
return "zero";
if (id === 0x00000002)
return "one";
if (id === 0x00000005)
return "src-alpha";
if (id === 0x00000009)
return "dst-alpha";
if (id === 0x00000006)
return "one-minus-src-alpha";
if (id === 0x0000000A)
return "one-minus-dst-alpha";
}
function id_to_filter_mode(id) {
if (id === 0x00000001)
return "nearest";
if (id === 0x00000002)
return "linear";
}
async function init() {
let wasm_bytes = null;
await fetch("./start.wasm").then(res => res.arrayBuffer()).then(buffer => wasm_bytes = new Uint8Array(buffer));
memory = new WebAssembly.Memory({initial : 10240, maximum : 10240, shared : true}); // * 65536 = 671088640 (make.js --initial-memory)
heapu8 = new Uint8Array(memory.buffer);
heapu16 = new Uint16Array(memory.buffer);
heapu32 = new Uint32Array(memory.buffer);
heapi32 = new Int32Array(memory.buffer);
heapf32 = new Float32Array(memory.buffer);
heapf64 = new Float64Array(memory.buffer);
if (!navigator.gpu) {
throw new Error('WebGPU not supported');
}
let adapter = await navigator.gpu.requestAdapter();
let device = await adapter.requestDevice();
let canvas = document.getElementById('iron');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
let context = canvas.getContext('webgpu');
let format = navigator.gpu.getPreferredCanvasFormat();
context.configure({device, format});
let result = await WebAssembly.instantiate(wasm_bytes, {
env : {memory},
imports : {
wgpuCreateInstance : function(pdescriptor) {
let inst = navigator.gpu;
return ptr_to_id(inst);
},
// wgpuInstanceRequestAdapter : function(pinstance, poptions, pcallback_info) {
// let callback_index = heapu32[(pcallback_info + 12) >> 2];
// instance.exports.__indirect_function_table.get(callback_index)(0, ptr_to_id(adapter), null, null, null);
// return 0n;
// },
wgpuInstanceRequestAdapterSync : function() {
return ptr_to_id(adapter);
},
wgpuAdapterGetInfo : function(padapter, pinfo) {
return 0;
},
wgpuAdapterInfoFreeMembers : function(padapter_info) {},
// wgpuAdapterRequestDevice : function(padapter, pdescriptor, pcallback_info) {
// return 0;
// },
wgpuAdapterRequestDeviceSync : function() {
return ptr_to_id(device);
},
wgpuDeviceCreateTexture : function(pdevice, pdescriptor) {
let device = id_to_ptr(pdevice);
// WGPUTextureDescriptor
let desc = {
usage : read_u32(pdescriptor + 16),
dimension : "2d",
size : {width : read_u32(pdescriptor + 28), height : read_u32(pdescriptor + 32), depthOrArrayLayers : 1},
format : id_to_texture_format(read_u32(pdescriptor + 40)),
mipLevelCount : 1,
sampleCount : 1
};
let texture = device.createTexture(desc);
return ptr_to_id(texture);
},
wgpuTextureCreateView : function(ptexture, pdescriptor) {
let texture = id_to_ptr(ptexture);
// WGPUTextureViewDescriptor
let desc =
{format : id_to_texture_format(read_u32(pdescriptor + 12)), dimension : "2d", mipLevelCount : 1, arrayLayerCount : 1, aspect : "all"};
let view = texture.createView(desc);
return ptr_to_id(view);
},
wgpuDeviceGetQueue : function(pdevice) {
let device = id_to_ptr(pdevice);
return ptr_to_id(device.queue);
},
wgpuDeviceCreateBindGroupLayout : function(pdevice, pdescriptor) {
let device = id_to_ptr(pdevice);
// WGPUBindGroupLayoutDescriptor
let desc = {entryCount : read_u32(pdescriptor + 12), entries : []};
let pentries = read_u32(pdescriptor + 16);
// WGPUBindGroupLayoutEntry
for (let i = 0; i < desc.entryCount; ++i) {
let e = {
binding : read_u32(i * 88 + pentries + 4),
visibility : read_u32(i * 88 + pentries + 8),
};
if (read_u32(i * 88 + pentries + 28) != 0x00000000) { // WGPUBufferBindingType_BindingNotUsed
e.buffer = {
type : read_u32(i * 88 + pentries + 28),
hasDynamicOffset : read_u32(i * 88 + pentries + 32),
minBindingSize : read_u32(i * 88 + pentries + 36)
};
if (e.buffer.type === 0x00000002)
e.buffer.type = "uniform";
}
if (read_u32(i * 88 + pentries + 52) != 0x00000000) { // WGPUSamplerBindingType_BindingNotUsed
e.sampler = {type : read_u32(i * 88 + pentries + 52)};
if (e.sampler.type === 0x00000002)
e.sampler.type = "filtering";
else if (e.sampler.type === 0x00000003)
e.sampler.type = "non-filtering";
}
if (read_u32(i * 88 + pentries + 60) != 0x00000000) { // WGPUTextureSampleType_BindingNotUsed
e.texture = {
sampleType : read_u32(i * 88 + pentries + 60),
viewDimension : "2d", // read_u32(i * 88 + pentries + 64),
multisampled : read_u32(i * 88 + pentries + 68)
};
if (e.texture.sampleType === 0x00000002)
e.texture.sampleType = "float";
else if (e.texture.sampleType === 0x00000003)
e.texture.sampleType = "unfilterable-float";
}
desc.entries.push(e);
}
let bgl = device.createBindGroupLayout(desc);
return ptr_to_id(bgl);
},
wgpuDeviceCreateBuffer : function(pdevice, pdescriptor) {
let device = id_to_ptr(pdevice);
// WGPUBufferDescriptor
let desc = {usage : read_u32(pdescriptor + 16), size : read_u32(pdescriptor + 24), mappedAtCreation : read_u32(pdescriptor + 32)};
let buffer = device.createBuffer(desc);
return ptr_to_id(buffer);
},
wgpuBufferGetMappedRange : function(pbuffer, offset, size) {
let buffer = id_to_ptr(pbuffer);
let ptr = instance.exports.wasm_malloc(size);
let ab = buffer.getMappedRange(offset, size);
let u8 = new Uint8Array(ab);
for (let i = 0; i < u8.length; ++i) {
heapu8[ptr + i] = u8[i];
}
return ptr;
},
wgpuBufferUnmap : function(pbuffer) {
let buffer = id_to_ptr(pbuffer);
buffer.unmap();
},
wgpuBufferUnmap2 : function(pbuffer, pdata, start, count) {
let buffer = id_to_ptr(pbuffer);
let ab = buffer.getMappedRange(start, count);
let u8 = new Uint8Array(ab);
for (let i = 0; i < u8.length; ++i) {
u8[i] = heapu8[pdata + i];
}
buffer.unmap();
},
wgpuDeviceCreateCommandEncoder : function(pdevice, pdescriptor) {
let device = id_to_ptr(pdevice);
// WGPUCommandBufferDescriptor
let desc = null;
let encoder = device.createCommandEncoder(desc);
return ptr_to_id(encoder);
},
wgpuCommandEncoderCopyBufferToTexture : function(pcommand_encoder, psource, pdestination, pcopysize) {
let encoder = id_to_ptr(pcommand_encoder);
// WGPUTexelCopyBufferInfo
let source = {bytesPerRow : read_u32(psource + 8), rowsPerImage : read_u32(psource + 12), buffer : id_to_ptr(read_u32(psource + 16))};
// WGPUTexelCopyTextureInfo
let destination = {texture : id_to_ptr(read_u32(pdestination))};
// WGPUExtent3D
let copysize = {width : read_u32(pcopysize), height : read_u32(pcopysize + 4), depthOrArrayLayers : read_u32(pcopysize + 8)};
encoder.copyBufferToTexture(source, destination, copysize);
},
wgpuCommandEncoderFinish : function(pcommand_encoder, pdescriptor) {
let encoder = id_to_ptr(pcommand_encoder);
// WGPUCommandBufferDescriptor
let desc = null;
let command_buffer = encoder.finish(desc);
return ptr_to_id(command_buffer);
},
wgpuQueueSubmit : function(pqueue, command_buffer_count, pcommand_buffers) {
let queue = id_to_ptr(pqueue);
let command_buffers = [];
for (let i = 0; i < command_buffer_count; i++) {
let c = id_to_ptr(read_u32(pcommand_buffers + i * 4));
command_buffers.push(c);
}
queue.submit(command_buffers);
},
wgpuBufferRelease : function(pbuffer) {
release_id(pbuffer);
},
wgpuDeviceCreateSampler : function(pdevice, pdescriptor) {
let device = id_to_ptr(pdevice);
// WGPUSamplerDescriptor
let desc = {
addressModeU : "repeat",
addressModeV : "repeat",
addressModeW : "repeat",
magFilter : id_to_filter_mode(read_u32(pdescriptor + 24)),
minFilter : id_to_filter_mode(read_u32(pdescriptor + 28)),
mipmapFilter : id_to_filter_mode(read_u32(pdescriptor + 32)),
maxAnisotropy : 1
};
let sampler = device.createSampler(desc);
return ptr_to_id(sampler);
},
wgpuSurfaceGetCapabilities : function(psurface, padapter, pcapabilities) {
return 0;
},
wgpuSurfaceCapabilitiesFreeMembers : function(pcapabilities) {},
wgpuBufferDestroy : function(pbuffer) {
let buffer = id_to_ptr(pbuffer);
buffer.destroy();
},
wgpuSurfaceGetCurrentTexture : function(psurface, psurface_texture) {
let surface = id_to_ptr(psurface) || context;
let texture = surface.getCurrentTexture();
// WGPUSurfaceTexture
heapu32[psurface_texture / 4 + 1] = ptr_to_id(texture);
},
wgpuCommandEncoderBeginRenderPass : function(pcommand_encoder, pdescriptor) {
let encoder = id_to_ptr(pcommand_encoder);
// WGPURenderPassDescriptor
let desc = {colorAttachmentCount : read_u32(pdescriptor + 12), colorAttachments : []};
let pcas = read_u32(pdescriptor + 16);
for (let i = 0; i < desc.colorAttachmentCount; ++i) {
// WGPURenderPassColorAttachment
let ca = {
view : id_to_ptr(read_u32(pcas + 4 + i * 56)),
loadOp : read_u32(pcas + 16 + i * 56) == 0x00000001 ? "load" : "clear",
storeOp : "store",
clearValue : [ read_f64(pcas + 24 + i * 56), read_f64(pcas + 32 + i * 56), read_f64(pcas + 40 + i * 56), read_f64(pcas + 48 + i * 56) ]
};
desc.colorAttachments.push(ca);
}
// WGPURenderPassDepthStencilAttachment
let pdsa = read_u32(pdescriptor + 20);
if (pdsa !== 0) {
desc.depthStencilAttachment = {
view : id_to_ptr(read_u32(pdsa + 4)),
depthLoadOp : read_u32(pdsa + 8) == 0x00000001 ? "load" : "clear",
depthStoreOp : "store",
depthClearValue : 1.0
};
}
let render_pass = encoder.beginRenderPass(desc);
return ptr_to_id(render_pass);
},
wgpuRenderPassEncoderSetViewport : function(prender_pass_encoder, x, y, width, height, min_depth, max_depth) {
let render_pass = id_to_ptr(prender_pass_encoder);
render_pass.setViewport(x, y, width, height, min_depth, max_depth);
},
wgpuRenderPassEncoderSetScissorRect : function(prender_pass_encoder, x, y, width, height) {
let render_pass = id_to_ptr(prender_pass_encoder);
render_pass.setScissorRect(x, y, width, height);
},
wgpuRenderPassEncoderEnd : function(prender_pass_encoder) {
let render_pass = id_to_ptr(prender_pass_encoder);
render_pass.end();
},
wgpuRenderPassEncoderRelease : function(prender_pass_encoder) {
release_id(prender_pass_encoder);
},
wgpuCommandBufferRelease : function(pcommand_buffer) {
release_id(pcommand_buffer);
},
wgpuCommandEncoderRelease : function(pcommand_encoder) {
release_id(pcommand_encoder);
},
wgpuSurfacePresent : function(psurface) {
return 0;
},
wgpuRenderPassEncoderDrawIndexed : function(prender_pass_encoder, index_count, instance_count, first_index, base_vertex, first_instance) {
let render_pass = id_to_ptr(prender_pass_encoder);
render_pass.drawIndexed(index_count, instance_count, first_index, base_vertex, first_instance);
},
wgpuRenderPassEncoderSetPipeline : function(prender_pass_encoder, ppipeline) {
let render_pass = id_to_ptr(prender_pass_encoder);
let pipeline = id_to_ptr(ppipeline);
render_pass.setPipeline(pipeline);
},
wgpuRenderPassEncoderSetVertexBuffer : function(prender_pass_encoder, slot, pbuffer, offset, size) {
let render_pass = id_to_ptr(prender_pass_encoder);
let buffer = id_to_ptr(pbuffer);
render_pass.setVertexBuffer(slot, buffer, Number(offset), Number(size));
},
wgpuRenderPassEncoderSetIndexBuffer : function(prender_pass_encoder, pbuffer, format, offset, size) {
let render_pass = id_to_ptr(prender_pass_encoder);
let buffer = id_to_ptr(pbuffer);
render_pass.setIndexBuffer(buffer, 'uint32', Number(offset), Number(size));
},
wgpuDeviceCreateBindGroup : function(pdevice, pdescriptor) {
let device = id_to_ptr(pdevice);
// WGPUBindGroupDescriptor
let desc = {layout : id_to_ptr(read_u32(pdescriptor + 12)), entryCount : read_u32(pdescriptor + 16), entries : []};
let pentries = read_u32(pdescriptor + 20);
for (let i = 0; i < desc.entryCount; i++) {
// WGPUBindGroupEntry
let e = {
binding : read_u32(pentries + 4 + i * 40),
};
if (read_u32(pentries + 8 + i * 40) !== 0) {
e.resource = {
buffer : id_to_ptr(read_u32(pentries + 8 + i * 40)),
offset : read_u32(pentries + 16 + i * 40),
size : read_u32(pentries + 24 + i * 40)
}
}
if (read_u32(pentries + 32 + i * 40) !== 0) {
e.resource = id_to_ptr(read_u32(pentries + 32 + i * 40));
}
if (read_u32(pentries + 36 + i * 40) !== 0) {
e.resource = id_to_ptr(read_u32(pentries + 36 + i * 40));
}
desc.entries.push(e);
}
let bg = device.createBindGroup(desc);
return ptr_to_id(bg);
},
wgpuRenderPassEncoderSetBindGroup : function(prender_pass_encoder, group_index, pgroup, dynamic_offset_count, pdynamic_offsets) {
let render_pass = id_to_ptr(prender_pass_encoder);
let group = id_to_ptr(pgroup);
let dynamic_offsets = [];
for (let i = 0; i < dynamic_offset_count; i++) {
let doff = read_u32(pdynamic_offsets + i * 4);
dynamic_offsets.push(doff);
}
render_pass.setBindGroup(group_index, group, dynamic_offsets);
},
wgpuBindGroupRelease : function(pbind_group) {
release_id(pbind_group);
},
wgpuRenderPipelineRelease : function(prender_pipeline) {
release_id(prender_pipeline);
},
wgpuPipelineLayoutRelease : function(ppipeline_layout) {
release_id(ppipeline_layout);
},
wgpuDeviceCreatePipelineLayout : function(pdevice, pdescriptor) {
let device = id_to_ptr(pdevice);
// WGPUPipelineLayoutDescriptor
let desc = {bindGroupLayoutCount : read_u32(pdescriptor + 12), bindGroupLayouts : []};
let pbgl = read_u32(pdescriptor + 16);
for (let i = 0; i < desc.bindGroupLayoutCount; ++i) {
// WGPUBindGroupLayout
let bgl = id_to_ptr(read_u32(pbgl + i * 4));
desc.bindGroupLayouts.push(bgl);
}
let pl = device.createPipelineLayout(desc);
return ptr_to_id(pl);
},
wgpuDeviceCreateShaderModule : function(pdevice, pdescriptor) {
let device = id_to_ptr(pdevice);
// WGPUShaderSourceWGSL
let pwgsl = read_u32(pdescriptor);
let wgsl = {chain : {sType : read_u32(pwgsl + 4)}, code : {data : read_u32(pwgsl + 8), length : read_u32(pwgsl + 12)}};
// WGPUShaderModuleDescriptor
let desc = {code : read_string_n(wgsl.code.data, wgsl.code.length)};
let sm = device.createShaderModule(desc);
return ptr_to_id(sm);
},
wgpuDeviceCreateRenderPipeline : function(pdevice, pdescriptor) {
let device = id_to_ptr(pdevice);
// WGPUFragmentState
let pfrag = read_u32(pdescriptor + 92);
let frag = {module : id_to_ptr(read_u32(pfrag + 4)), entryPoint : "main", targetCount : read_u32(pfrag + 24), targets : []};
let ptragets = read_u32(pfrag + 28);
for (let i = 0; i < frag.targetCount; ++i) {
// WGPUColorTargetState
let t = {format : id_to_texture_format(read_u32(ptragets + 4 + i * 24)), writeMask : read_u32(ptragets + 16 + i * 24)};
let pbs = read_u32(ptragets + 8 + i * 24); // WGPUBlendState
if (pbs != 0) {
t.blend = {
color : {operation : "add", srcFactor : id_to_blend_factor(read_u32(pbs + 4)), dstFactor : id_to_blend_factor(read_u32(pbs + 8))},
alpha : {operation : "add", srcFactor : id_to_blend_factor(read_u32(pbs + 16)), dstFactor : id_to_blend_factor(read_u32(pbs + 20))}
};
}
frag.targets.push(t);
}
// WGPURenderPipelineDescriptor
let desc = {
layout : id_to_ptr(read_u32(pdescriptor + 12)),
// WGPUVertexState
vertex : {module : id_to_ptr(read_u32(pdescriptor + 20)), entryPoint : "main", bufferCount : 1, buffers : []},
primitive : {topology : "triangle-list", frontFace : "ccw", cullMode : read_u32(pdescriptor + 64)},
fragment : frag,
};
if (desc.primitive.cullMode === 0x00000001)
desc.primitive.cullMode = "none";
else if (desc.primitive.cullMode === 0x00000002)
desc.primitive.cullMode = "front";
else if (desc.primitive.cullMode === 0x00000003)
desc.primitive.cullMode = "back";
// WGPUDepthStencilState
let pds = read_u32(pdescriptor + 72);
if (pds != 0) {
let ds = {format : id_to_texture_format(read_u32(pds + 4)), depthWriteEnabled : read_u32(pds + 8), depthCompare : read_u32(pds + 12)};
if (ds.depthCompare === 0x00000002)
ds.depthCompare = "less";
else if (ds.depthCompare === 0x00000008)
ds.depthCompare = "always";
desc.depthStencil = ds;
}
let pbuffers = read_u32(pdescriptor + 44);
for (let i = 0; i < desc.vertex.bufferCount; ++i) {
// WGPUVertexBufferLayout
let b = {arrayStride : read_u32(pbuffers + 8 + i * 24), attributeCount : read_u32(pbuffers + 16 + i * 24), attributes : []};
let pattributes = read_u32(pbuffers + 20 + i * 24);
for (let i = 0; i < b.attributeCount; ++i) {
// WGPUVertexAttribute
let a = {
format : id_to_vertex_format(read_u32(pattributes + 4 + i * 24)),
offset : read_u32(pattributes + 8 + i * 24),
shaderLocation : read_u32(pattributes + 16 + i * 24)
};
b.attributes.push(a);
}
desc.vertex.buffers.push(b);
}
let rp = device.createRenderPipeline(desc);
return ptr_to_id(rp);
},
wgpuShaderModuleRelease : function(pshader_module) {
release_id(pshader_module);
},
wgpuQueueWriteBuffer : function(pqueue, pbuffer, buffer_offset, pdata, size) {
let queue = id_to_ptr(pqueue);
let buffer = id_to_ptr(pbuffer);
let data = heapu8.subarray(pdata, pdata + size);
queue.writeBuffer(buffer, Number(buffer_offset), data);
},
wgpuTextureDestroy : function(ptexture) {
let texture = id_to_ptr(ptexture);
texture.destroy();
},
wgpuTextureRelease : function(ptexture) {
release_id(ptexture);
},
wgpuTextureViewRelease : function(ptexture_view) {
release_id(ptexture_view);
},
wgpuCommandEncoderCopyBufferToBuffer : function(pcommand_encoder, psource, source_offset, pdestination, destination_offset, size) {
let encoder = id_to_ptr(pcommand_encoder);
let source = id_to_ptr(psource);
let destination = id_to_ptr(pdestination);
encoder.copyBufferToBuffer(source, Number(source_offset), destination, Number(destination_offset), Number(size));
},
wgpuSurfaceConfigure : function(psurface, pconfig) {
let surface = id_to_ptr(psurface) || context;
// WGPUSurfaceConfiguration
let config = {
device : id_to_ptr(read_u32(pconfig + 4)),
format : id_to_texture_format(read_u32(pconfig + 8)),
usage : read_u32(pconfig + 16),
width : read_u32(pconfig + 24),
height : read_u32(pconfig + 28),
viewFormatCount : read_u32(pconfig + 32),
viewFormats : [],
alphaMode : read_u32(pconfig + 40),
presentMode : read_u32(pconfig + 44)
};
if (config.alphaMode === 0x00000001)
config.alphaMode = "opaque";
if (config.presentMode === 0x00000001)
config.presentMode = "fifo";
if (config.presentMode === 0x00000004)
config.presentMode = "mailbox";
let pview_formats = read_u32(pconfig + 36);
for (let i = 0; i < config.viewFormatCount; ++i) {
let f = id_to_texture_format(read_u32(pview_formats + i * 4));
config.viewFormats.push(f);
}
surface.configure(config);
},
js_printf : function(format) {
console.log(read_string(format));
},
js_fopen : function(filename) {
let str;
if (read_string(filename) === "/./data/config.json" || read_string(filename) === "/./data//config.json") { ////
str = config_json;
}
else {
let req = new XMLHttpRequest();
req.open("GET", read_string(filename), false);
req.overrideMimeType("text/plain; charset=x-user-defined");
req.send();
str = req.response;
}
file_buffer_pos = 0;
if (file_dropped != null) {
file_buffer = file_dropped;
file_dropped = null;
}
else {
file_buffer = new ArrayBuffer(str.length);
let buf_view = new Uint8Array(file_buffer);
for (let i = 0; i < str.length; ++i) {
buf_view[i] = str.charCodeAt(i);
}
}
return 1;
},
js_ftell : function(stream) {
return file_buffer_pos;
},
js_fseek : function(stream, offset, origin) {
file_buffer_pos = offset;
if (origin == 1)
file_buffer_pos += file_buffer.byteLength; // SEEK_END
return 0;
},
js_fread : function(ptr, size, count, stream) {
let buf_view = new Uint8Array(file_buffer);
for (let i = 0; i < count; ++i) {
heapu8[ptr + i] = buf_view[file_buffer_pos++];
}
return count;
},
js_fwrite : function(ptr, size, count, stream) {
config_json = read_string_n(ptr, count); ////
},
js_time : function() {
return window.performance.now();
},
js_pow : function(x) {
return Math.pow(x);
},
js_sin : function(x) {
return Math.sin(x);
},
js_cos : function(x) {
return Math.cos(x);
},
js_tan : function(x) {
return Math.tan(x);
},
js_log : function(base, exponent) {
return Math.log(base, exponent);
},
js_exp : function(x) {
return Math.exp(x);
},
js_sqrt : function(x) {
return Math.sqrt(x);
},
js_acos : function(x) {
return Math.acos(x);
},
js_asin : function(x) {
return Math.asin(x);
},
js_atan : function(x) {
return Math.atan(x);
},
js_atan2 : function(x, y) {
return Math.atan2(x, y);
},
js_eval : function(str) {
(1, eval)(read_string(str));
},
js_canvas_w : function() {
return canvas.width;
},
js_canvas_h : function() {
return canvas.height;
},
js_mouse_set_cursor : function(i) {
if (i == 0) // arrow
canvas.style.cursor = 'default';
else if (i == 1) // hand
canvas.style.cursor = 'pointer';
else if (i == 2) // ibeam
canvas.style.cursor = 'text';
else if (i == 3) // sizewe
canvas.style.cursor = 'ew-resize';
else if (i == 4) // sizens
canvas.style.cursor = 'ns-resize';
},
js_mouse_show : function() {
canvas.style.cursor = 'default';
},
js_mouse_hide : function() {
canvas.style.cursor = 'none';
},
js_window_set_title : function(str) {
document.title = read_string(str);
},
js_window_change_mode : function(i) {
i == 0 ? document.exitFullscreen() : canvas.requestFullscreen();
},
js_load_url : function(str) {
window.open(read_string(str), "_blank");
},
js_open_dialog : async function() {
let [handle] = await window.showOpenFilePicker({multiple : false});
let file = await handle.getFile();
file_dropped = await file.arrayBuffer();
let ptr = instance.exports.wasm_malloc(file.name.length + 1);
write_string(ptr, file.name)
instance.exports.wasm_drop_files(ptr);
},
js_save_dialog : function() {
alert("Not implemented yet.")
},
js_net_request : function(purl_base, purl_path, pdata, port, method, callback_id, callbackdata, pdst_path) {
let url_base = read_string(purl_base);
let url_path = read_string(purl_path);
let dst_path = pdst_path !== 0 ? read_string(pdst_path) : null;
let url = `https://${url_base}:${port}/${url_path}`;
let options = {method : 'GET', headers : {}};
fetch(url, options)
.then(response => {
if (dst_path) {
}
else {
return response.text();
}
})
.then(text => {
let buffer_ptr = 0;
if (text !== null) {
buffer_ptr = instance.exports.wasm_malloc(text.length + 1);
write_string(buffer_ptr, text);
}
instance.exports.wasm_net_callback(callback_id, buffer_ptr);
});
},
}
});
module = result.module;
instance = result.instance;
instance.exports.wasm_start();
function update() {
instance.exports.wasm_update();
window.requestAnimationFrame(update);
}
window.requestAnimationFrame(update);
canvas.addEventListener('contextmenu', (event) => { event.preventDefault(); });
canvas.addEventListener('mousedown', (event) => { instance.exports.wasm_mousedown(button_to_iron_button(event.button), event.clientX, event.clientY); });
canvas.addEventListener('mouseup', (event) => { instance.exports.wasm_mouseup(button_to_iron_button(event.button), event.clientX, event.clientY); });
canvas.addEventListener('mousemove', (event) => { instance.exports.wasm_mousemove(event.clientX, event.clientY); });
canvas.addEventListener('wheel', (event) => { instance.exports.wasm_wheel(event.deltaY); });
canvas.addEventListener('keydown', (event) => {
if (event.repeat) {
event.preventDefault();
return;
}
instance.exports.wasm_keydown(key_to_iron_key(event.key));
instance.exports.wasm_keypress(key_to_iron_key(event.key, true));
});
canvas.addEventListener('keyup', (event) => {
if (event.repeat) {
event.preventDefault();
return;
}
instance.exports.wasm_keyup(key_to_iron_key(event.key));
});
canvas.addEventListener('dragover', (event) => {
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
});
canvas.addEventListener('drop', async (event) => {
event.preventDefault();
const files = event.dataTransfer.files;
if (files.length > 0) {
let file = files[0];
file_dropped = await file.arrayBuffer();
let ptr = instance.exports.wasm_malloc(file.name.length + 1);
write_string(ptr, file.name)
instance.exports.wasm_drop_files(ptr);
}
});
}
function key_to_iron_key(key, is_press = false) {
if (key === ":")
return 58;
if (key === ";")
return 59;
if (key === "<")
return 60;
if (key === "=")
return 61;
if (key === ">")
return 62;
if (key === "?")
return 63;
if (key === "@")
return 64;
if (key === "^")
return 160;
if (key === "!")
return 161;
if (key === '"')
return 162;
if (key === "#")
return 163;
if (key === "$")
return 164;
if (key === "%")
return 165;
if (key === "&")
return 166;
if (key === "_")
return 167;
if (key === "(")
return 168;
if (key === ")")
return 169;
if (key === "*")
return 170;
if (key === "+")
return 171;
if (key === "|")
return 172;
if (key === "-")
return 173;
if (key === "{")
return 174;
if (key === "}")
return 175;
if (key === "~")
return 176;
if (key === ",")
return 188;
if (key === ".")
return 190;
if (key === "/")
return 191;
if (key === "`")
return 192;
if (key === "[")
return 219;
if (key === "\\")
return 220;
if (key === "]")
return 221;
if (key === "'")
return 222;
if (key === " ")
return 32;
if (key.length === 1 && is_press)
return key.charCodeAt(0);
if (key.length === 1)
return key.toUpperCase().charCodeAt(0);
if (key === "Backspace")
return 8;
if (key === "Tab")
return 9;
if (key === "Enter")
return 13;
if (key === "Shift")
return 16;
if (key === "Control")
return 17;
if (key === "Alt")
return 18;
if (key === "CapsLock")
return 20;
if (key === "Escape")
return 27;
if (key === "PageUp")
return 33;
if (key === "PageDown")
return 34;
if (key === "End")
return 35;
if (key === "Home")
return 36;
if (key === "ArrowLeft")
return 37;
if (key === "ArrowUp")
return 38;
if (key === "ArrowRight")
return 39;
if (key === "ArrowDown")
return 40;
if (key === "PrintScreen")
return 44;
if (key === "Insert")
return 45;
if (key === "Delete")
return 46;
if (key === "Meta")
return 224;
if (key === "AltGraph")
return 225;
if (key === "F1")
return 112;
if (key === "F2")
return 113;
if (key === "F3")
return 114;
if (key === "F4")
return 115;
if (key === "F5")
return 116;
if (key === "F6")
return 117;
if (key === "F7")
return 118;
if (key === "F8")
return 119;
if (key === "F9")
return 120;
if (key === "F10")
return 121;
if (key === "F11")
return 122;
if (key === "F12")
return 123;
return -1;
}
function button_to_iron_button(button) {
if (button === 1)
return 2;
if (button === 2)
return 1;
return button;
}
init();