sketch out os api, binary stream writer in js, app sleep when no animation, local and universal time

This commit is contained in:
krzosa
2025-01-04 11:03:36 +01:00
parent 6f795b7ea6
commit dcd1266477
13 changed files with 316 additions and 87 deletions

View File

@@ -6,7 +6,6 @@
#include "src/meta/build_tool.c"
#include "src/meta/parser.c"
#include "src/meta/serialize.c"
#include "src/app/app.meta.c"
void list_files_recursive(sb8_t *sb, s8_t path) {
@@ -87,6 +86,7 @@ int main(int argc, char **argv) {
if (wasm_target) {
os_copy("../src/app/app_wasm.html", "../package/index.html", os_copy_overwrite);
ok = os_systemf(
"clang.exe ../src/wasm_app/main.c -o main.wasm"
" -Oz -g -I../src"
@@ -96,7 +96,6 @@ int main(int argc, char **argv) {
" -Wl,-export-dynamic,--allow-undefined,--import-memory,--no-entry,--initial-memory=131072000,--max-memory=4294967296"
);
os_copy("main.wasm", "../package/main.wasm", os_copy_overwrite);
os_copy("../src/app/app_wasm.html", "../package/index.html", os_copy_overwrite);
if (ok != 0) return ok;
}
return ok;

View File

@@ -33,6 +33,33 @@
</html>
<script>
class stream_t {
constructor(dataview, ptr, len) {
this.dv = dataview;
this.ptr = ptr;
this.len = len;
this.i = 0;
}
write_u32(value) {
if (this.i + 4 <= this.len) {
this.dv.setUint32(this.ptr + this.i, value, true);
this.i += 4;
} else {
console.log("reached end of buffer while stream writing");
}
}
write_u16(value) {
if (this.i + 2 <= this.len) {
this.dv.setUint16(this.ptr + this.i, value, true);
this.i += 2;
} else {
console.log("reached end of buffer while stream writing");
}
}
}
class memory_t {
exports = null; // this is set after wasm module created
constructor(wasm_memory) {
@@ -58,12 +85,16 @@ class memory_t {
this.u8[ptr + i] = 0;
}
write_string(temp, string) {
write_string_to_cglobal(temp, string) {
const ptr = this.exports[temp].value;
const len = this.data_view.getInt32(this.exports[temp + "_len"].value, true);
this.write_string_into_cmemory(ptr, len, string);
return ptr;
}
stream_write(ptr, len) {
return new stream_t(this.data_view, ptr, len);
}
}
const canvas = document.getElementById("canvas");
@@ -78,7 +109,36 @@ const mem = new memory_t(new WebAssembly['Memory']({ initial: 2000, maximum: 655
const request = await fetch('main.wasm');
const binary = await request.arrayBuffer();
const wasm_imports = {
const wasm_os_imports = {
wasm_local_time_now: (ptr, len) => {
const date = new Date();
const stream = mem.stream_write(ptr, len);
stream.write_u16(date.getMilliseconds());
stream.write_u16(date.getSeconds());
stream.write_u16(date.getMinutes());
stream.write_u16(date.getHours());
stream.write_u16(date.getDate());
stream.write_u16(date.getMonth());
stream.write_u16(date.getFullYear());
},
wasm_universal_time_now: (ptr, len) => {
const date = new Date();
const stream = mem.stream_write(ptr, len);
stream.write_u16(date.getUTCMilliseconds());
stream.write_u16(date.getUTCSeconds());
stream.write_u16(date.getUTCMinutes());
stream.write_u16(date.getUTCHours());
stream.write_u16(date.getUTCDate());
stream.write_u16(date.getUTCMonth());
stream.write_u16(date.getUTCFullYear());
},
wasm_milliseconds_now: () => { return performance.now(); },
};
let wasm_app_imports = {
// core
memory: mem.mem,
@@ -86,7 +146,6 @@ const mem = new memory_t(new WebAssembly['Memory']({ initial: 2000, maximum: 655
wasm_alert: (str, len) => { alert(mem.read_cstr(str,len)); },
wasm_trap: () => { throw new Error(); },
wasm_write_to_console: (str, len) => { console.log(mem.read_cstr(str, len)); },
wasm_get_milliseconds: () => { return performance.now(); },
// gfx
wasm_draw_text: (str, len, x, y, font_str, font_len, font_size, r, g, b, a) => {
@@ -125,37 +184,59 @@ const mem = new memory_t(new WebAssembly['Memory']({ initial: 2000, maximum: 655
};
const program = await WebAssembly['instantiate'](binary, { "env": wasm_imports });
Object.assign(wasm_app_imports, wasm_os_imports);
const program = await WebAssembly['instantiate'](binary, { "env": wasm_app_imports });
const instance = program['instance'];
const wasm_exports = instance['exports'];
mem.exports = wasm_exports;
wasm_exports['wasm_init']();
addEventListener("keydown", (event) => {
wasm_exports["wasm_key_down"](mem.write_string("wasm_temp_buff1", event.key), event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
});
addEventListener("keyup", (event) => {
wasm_exports["wasm_key_up"](mem.write_string("wasm_temp_buff1", event.key), event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
});
addEventListener("mousemove", (event) => {
wasm_exports["wasm_mouse_move"](event.clientX, event.clientY, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
});
addEventListener("mousedown", (event) => {
wasm_exports["wasm_mouse_down"](event.clientX, event.clientY, event.button, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
});
addEventListener("mouseup", (event) => {
wasm_exports["wasm_mouse_up"](event.clientX, event.clientY, event.button, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
});
addEventListener("wheel", (event) => {
wasm_exports["wasm_mouse_wheel"](event.clientX, event.clientY, event.deltaX, event.deltaY, event.deltaZ, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
});
let awake = false;
requestAnimationFrame(function update(time) {
function wasm_update(time) {
const dpr = window.devicePixelRatio;
canvas.width = canvas.getBoundingClientRect().width * dpr;
canvas.height = canvas.getBoundingClientRect().height * dpr;
wasm_exports['wasm_update'](canvas.width, canvas.height, dpr);
requestAnimationFrame(update);
let animating = wasm_exports['wasm_update'](time, canvas.width, canvas.height, dpr);
if (animating) {
requestAnimationFrame(wasm_update);
} else {
awake = false;
}
}
function wake_up() {
if (awake) return;
awake = true;
window.requestAnimationFrame(wasm_update);
}
addEventListener("keydown", (event) => {
wasm_exports["wasm_key_down"](mem.write_string_to_cglobal("wasm_temp_buff1", event.key), event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
wake_up();
});
addEventListener("keyup", (event) => {
wasm_exports["wasm_key_up"](mem.write_string_to_cglobal("wasm_temp_buff1", event.key), event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
wake_up();
});
addEventListener("mousemove", (event) => {
wasm_exports["wasm_mouse_move"](event.clientX, event.clientY, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
wake_up();
});
addEventListener("mousedown", (event) => {
wasm_exports["wasm_mouse_down"](event.clientX, event.clientY, event.button, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
wake_up();
});
addEventListener("mouseup", (event) => {
wasm_exports["wasm_mouse_up"](event.clientX, event.clientY, event.button, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
wake_up();
});
addEventListener("wheel", (event) => {
wasm_exports["wasm_mouse_wheel"](event.clientX, event.clientY, event.deltaX, event.deltaY, event.deltaZ, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
wake_up();
});
requestAnimationFrame(wasm_update);
})()
</script>

View File

@@ -36,8 +36,6 @@ while (true) {
}
*/
fn_wasm_import f64 wasm_get_milliseconds(void);
gb_wasm_export char wasm_temp_buff1[128] = {[127] = 0x13};
gb_wasm_export i32 wasm_temp_buff1_len = 127;
gb_wasm_export char wasm_temp_buff2[128] = {[127] = 0x13};
@@ -47,7 +45,6 @@ gb f64 wasm_dpr;
gb f64 wasm_delta_time;
gb f64 wasm_time;
gb f64 wasm_last_time;
gb f64 wasm_app_init_time;
gb app_event_list_t wasm_event_list;
typedef struct wasm_cached_t wasm_cached_t;
@@ -56,7 +53,7 @@ struct wasm_cached_t {
b8 ctrl, alt, meta, shift;
} wasm_cached;
fn void app_update(app_event_list_t eventswasm_event_list);
fn b32 app_update(app_event_list_t);
fn void app_init(void);
fn void wasm_add_event(app_event_t event) {
@@ -179,12 +176,8 @@ fn_wasm_export void wasm_key_up(char *key, b32 ctrl, b32 shift, b32 alt, b32 met
}
}
fn f64 wasm_seconds_now(void) {
return wasm_get_milliseconds() / 1000.0;
}
fn_wasm_export void wasm_update(f64 width, f64 height, f64 dpr) {
wasm_time = wasm_seconds_now();
fn_wasm_export void wasm_update(f64 time, f64 width, f64 height, f64 dpr) {
wasm_time = time;
wasm_delta_time = wasm_time - wasm_last_time;
v2f64_t window_size = (v2f64_t){width / dpr, height / dpr};
@@ -216,13 +209,12 @@ fn_wasm_export void wasm_update(f64 width, f64 height, f64 dpr) {
fn_wasm_export void wasm_init(void) {
core_init();
app_init();
wasm_app_init_time = wasm_seconds_now();
}
fn f64 app_get_anim_time(void) {
return wasm_time;
return wasm_time / 1000.0;
}
fn f64 app_get_anim_delta_time(void) {
return wasm_delta_time;
return wasm_delta_time / 1000.0;
}

View File

@@ -33,6 +33,33 @@
</html>
<script>
class stream_t {
constructor(dataview, ptr, len) {
this.dv = dataview;
this.ptr = ptr;
this.len = len;
this.i = 0;
}
write_u32(value) {
if (this.i + 4 <= this.len) {
this.dv.setUint32(this.ptr + this.i, value, true);
this.i += 4;
} else {
console.log("reached end of buffer while stream writing");
}
}
write_u16(value) {
if (this.i + 2 <= this.len) {
this.dv.setUint16(this.ptr + this.i, value, true);
this.i += 2;
} else {
console.log("reached end of buffer while stream writing");
}
}
}
class memory_t {
exports = null; // this is set after wasm module created
constructor(wasm_memory) {
@@ -58,12 +85,16 @@ class memory_t {
this.u8[ptr + i] = 0;
}
write_string(temp, string) {
write_string_to_cglobal(temp, string) {
const ptr = this.exports[temp].value;
const len = this.data_view.getInt32(this.exports[temp + "_len"].value, true);
this.write_string_into_cmemory(ptr, len, string);
return ptr;
}
stream_write(ptr, len) {
return new stream_t(this.data_view, ptr, len);
}
}
const canvas = document.getElementById("canvas");
@@ -78,7 +109,36 @@ const mem = new memory_t(new WebAssembly['Memory']({ initial: 2000, maximum: 655
const request = await fetch('main.wasm');
const binary = await request.arrayBuffer();
const wasm_imports = {
const wasm_os_imports = {
wasm_local_time_now: (ptr, len) => {
const date = new Date();
const stream = mem.stream_write(ptr, len);
stream.write_u16(date.getMilliseconds());
stream.write_u16(date.getSeconds());
stream.write_u16(date.getMinutes());
stream.write_u16(date.getHours());
stream.write_u16(date.getDate());
stream.write_u16(date.getMonth());
stream.write_u16(date.getFullYear());
},
wasm_universal_time_now: (ptr, len) => {
const date = new Date();
const stream = mem.stream_write(ptr, len);
stream.write_u16(date.getUTCMilliseconds());
stream.write_u16(date.getUTCSeconds());
stream.write_u16(date.getUTCMinutes());
stream.write_u16(date.getUTCHours());
stream.write_u16(date.getUTCDate());
stream.write_u16(date.getUTCMonth());
stream.write_u16(date.getUTCFullYear());
},
wasm_milliseconds_now: () => { return performance.now(); },
};
let wasm_app_imports = {
// core
memory: mem.mem,
@@ -86,7 +146,6 @@ const mem = new memory_t(new WebAssembly['Memory']({ initial: 2000, maximum: 655
wasm_alert: (str, len) => { alert(mem.read_cstr(str,len)); },
wasm_trap: () => { throw new Error(); },
wasm_write_to_console: (str, len) => { console.log(mem.read_cstr(str, len)); },
wasm_get_milliseconds: () => { return performance.now(); },
// gfx
wasm_draw_text: (str, len, x, y, font_str, font_len, font_size, r, g, b, a) => {
@@ -125,37 +184,59 @@ const mem = new memory_t(new WebAssembly['Memory']({ initial: 2000, maximum: 655
};
const program = await WebAssembly['instantiate'](binary, { "env": wasm_imports });
Object.assign(wasm_app_imports, wasm_os_imports);
const program = await WebAssembly['instantiate'](binary, { "env": wasm_app_imports });
const instance = program['instance'];
const wasm_exports = instance['exports'];
mem.exports = wasm_exports;
wasm_exports['wasm_init']();
addEventListener("keydown", (event) => {
wasm_exports["wasm_key_down"](mem.write_string("wasm_temp_buff1", event.key), event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
});
addEventListener("keyup", (event) => {
wasm_exports["wasm_key_up"](mem.write_string("wasm_temp_buff1", event.key), event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
});
addEventListener("mousemove", (event) => {
wasm_exports["wasm_mouse_move"](event.clientX, event.clientY, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
});
addEventListener("mousedown", (event) => {
wasm_exports["wasm_mouse_down"](event.clientX, event.clientY, event.button, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
});
addEventListener("mouseup", (event) => {
wasm_exports["wasm_mouse_up"](event.clientX, event.clientY, event.button, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
});
addEventListener("wheel", (event) => {
wasm_exports["wasm_mouse_wheel"](event.clientX, event.clientY, event.deltaX, event.deltaY, event.deltaZ, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
});
let awake = false;
requestAnimationFrame(function update(time) {
function wasm_update(time) {
const dpr = window.devicePixelRatio;
canvas.width = canvas.getBoundingClientRect().width * dpr;
canvas.height = canvas.getBoundingClientRect().height * dpr;
wasm_exports['wasm_update'](canvas.width, canvas.height, dpr);
requestAnimationFrame(update);
let animating = wasm_exports['wasm_update'](time, canvas.width, canvas.height, dpr);
if (animating) {
requestAnimationFrame(wasm_update);
} else {
awake = false;
}
}
function wake_up() {
if (awake) return;
awake = true;
window.requestAnimationFrame(wasm_update);
}
addEventListener("keydown", (event) => {
wasm_exports["wasm_key_down"](mem.write_string_to_cglobal("wasm_temp_buff1", event.key), event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
wake_up();
});
addEventListener("keyup", (event) => {
wasm_exports["wasm_key_up"](mem.write_string_to_cglobal("wasm_temp_buff1", event.key), event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
wake_up();
});
addEventListener("mousemove", (event) => {
wasm_exports["wasm_mouse_move"](event.clientX, event.clientY, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
wake_up();
});
addEventListener("mousedown", (event) => {
wasm_exports["wasm_mouse_down"](event.clientX, event.clientY, event.button, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
wake_up();
});
addEventListener("mouseup", (event) => {
wasm_exports["wasm_mouse_up"](event.clientX, event.clientY, event.button, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
wake_up();
});
addEventListener("wheel", (event) => {
wasm_exports["wasm_mouse_wheel"](event.clientX, event.clientY, event.deltaX, event.deltaY, event.deltaZ, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
wake_up();
});
requestAnimationFrame(wasm_update);
})()
</script>

View File

@@ -10,7 +10,6 @@
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "winmm.lib")
gb b32 w32_good_scheduling;
gb WNDCLASSW w32_wc;
gb HWND w32_window_handle;
@@ -43,6 +42,7 @@ fn f64 w32_get_dpr(HWND window_handle) {
///////////////////////////////
// event processing
gb app_event_list_t w32_event_list;
gb ma_arena_t *w32_event_arena;

View File

@@ -132,6 +132,24 @@ fn void sb8_indent(sb8_t *sb);
fn s8_t sb8_stmtf(sb8_t *sb, const char *str, ...);
fn int64_t sb8_char_size(sb8_t *sb);
#if 0
sb8_t *sbin_write_begin(ma_arena_t *arena);
s8_t sbin_write_end(sb8_t *sb);
void *sbin_write_data(sb8_t *sb, void *p, i64 size);
void *sbin_write_size(sb8_t *sb, i64 size);
void *sbin_write_u64(sb8_t *sb, u64 value);
void *sbin_write_u32(sb8_t *sb, u32 value);
void *sbin_write_u16(sb8_t *sb, u16 value);
void *sbin_write_u8(sb8_t *sb, u8 value);
s8_t *sbin_write_s8(sb8_t *sb, s8_t string);
char *sbin_write_str(sb8_t *sb, char *string);
stream_t sbin_read_begin(void *p, i64 size);
void sbin_read_end(stream_t *stream);
void *sbin_read_data(stream_t *stream, i64 size);
#endif
//
// other
#define s8_fmtspec(string) (int)(string).len, (string).str

View File

@@ -0,0 +1,7 @@
#if PLATFORM_WASM
#include "os_wasm.c"
#elif PLATFORM_WINDOWS
#include "os_win32.c"
#else
#include "os_unix.c"
#endif

View File

@@ -9,4 +9,42 @@ struct os_date_t {
u16 year;
};
fn os_date_t os_date_now(void);
fn os_date_t os_local_time_now(void);
fn os_date_t os_universal_time_now(void);
fn f64 os_milliseconds_now(void);
#if 0
fn u64 os_microseconds_now();
fn f64 os_seconds_now();
fn u32 os_unix_time_now();
fn os_date_t os_local_time_to_universal_time();
fn os_date_t os_universal_time_to_local_time();
fn void os_sleep_milliseconds();
fn s8_t os_list_files(arena, path, recursive);
fn os_file_iter_t os_iterate_files();
fn void os_advance()
fn b32 os_is_valid();
fn s8_t os_read_file(ma_arena_t *arena, s8_t path);
fn void os_write_file(s8_t path, s8_t content);
fn void os_make_dir(s8_t path);
fn os_result_t os_copy_file(s8_t from, s8_t to, b32 overwrite);
fn os_result_t os_delete_file(s8_t path);
fn i64 os_get_file_mod_time(s8_t path);
fn b32 os_path_exists(s8_t path);
fn b32 os_path_is_dir(s8_t path);
fn b32 os_path_is_file(s8_t path);
fn b32 os_path_is_abs(s8_t path);
fn b32 os_path_is_rel(s8_t path);
fn s8_t os_path_to_abs(ma_arena_t *arena, s8_t path);
fn s8_t os_path_exe(ma_arena_t *arena);
fn s8_t os_path_exe_dir(ma_arena_t *arena);
fn s8_t os_path_cwd(ma_arena_t *arena);
fn void os_path_set_cwd(s8_t path);
#endif

View File

@@ -1,4 +1,4 @@
fn os_date_t os_date_now(void) {
fn os_date_t os_local_time_now(void) {
os_date_t result = {0};
time_t time = time(NULL);
struct tm *lt = localtime(&time);

View File

@@ -1,4 +1,20 @@
fn os_date_t os_date_now(void) {
os_date_t result = {0}; // don't need timed logs in browser
fn_wasm_import void wasm_local_time_now(void *buff, i32 size);
fn_wasm_import void wasm_universal_time_now(void *buff, i32 size);
fn_wasm_import f64 wasm_milliseconds_now(void);
fn os_date_t os_local_time_now(void) {
os_date_t result = {0};
wasm_local_time_now(&result, sizeof(result));
return result;
}
fn os_date_t os_universal_time_now(void) {
os_date_t result = {0};
wasm_universal_time_now(&result, sizeof(result));
return result;
}
fn f64 os_milliseconds_now(void) {
return wasm_milliseconds_now();
}

View File

@@ -1,4 +1,4 @@
fn os_date_t os_date_now(void) {
fn os_date_t os_local_time_now(void) {
os_date_t result = {0};
SYSTEMTIME lt;
GetLocalTime(&lt);

View File

@@ -1,8 +1,12 @@
#include "core/core_inc.h"
#include "core/core_inc.c"
#include "app/app.h"
#include "os/os.h"
#include "core/core_inc.c"
#include "app/app.c"
#include "os/os.c"
#include "gfx2d/gfx2d.c"
// #include "ui.c"
gfx_t *gfx = NULL;
@@ -10,9 +14,14 @@ gfx_t *gfx = NULL;
void app_init(void) {
ma_arena_t *perm = &tcx._perm;
gfx = ma_push_type(perm, gfx_t);
os_date_t ldate = os_local_time_now();
os_date_t udate = os_universal_time_now();
assert(ldate.hour == (udate.hour + 1));
}
void app_update(app_event_list_t events) {
b32 app_update(app_event_list_t events) {
for (app_event_t *ev = events.first; ev; ev = ev->next) {
// update
}
@@ -31,4 +40,5 @@ void app_update(app_event_list_t events) {
gfx_end(gfx);
}
return false;
}

View File

@@ -20,23 +20,10 @@
[ ] change name, hard to type
[ ] core
[ ] remove dates and time from core
[x] remove dates and time from core
[ ] meta
[x] search for python snippets and execute meta.py script on that file
[ ] new simple format with tags
[x] revisit api
[ ] s8_bin
[ ] bin_write_begin - serialize binary data (sb8_bin_write?)
bin_write_end
bin_write_u64
bin_write_u32
bin_write_u16
bin_write_u8
bin_write_data
bin_write_size
bin_write_s8
bin_write_cs
[ ] bin_read_begin
bin_read_end
bin_read_...