Add asynchronous web game loading and simple pack

This commit is contained in:
John Alanbrook 2024-04-17 06:32:25 -05:00
parent e6ec506512
commit 3b3cb14421
7 changed files with 112 additions and 45 deletions

View file

@ -4,6 +4,10 @@ MAKEDIR != pwd
# Options # Options
# NDEBUG --- build with debugging symbols and logging # NDEBUG --- build with debugging symbols and logging
ifeq ($(ARCH),)
ARCH != uname -m
endif
CXX:=$(CC) CXX:=$(CC)
# Temp to strip long emcc paths to just emcc # Temp to strip long emcc paths to just emcc
@ -17,13 +21,13 @@ LD = $(CC)
STEAM = steam/sdk STEAM = steam/sdk
STEAMAPI = STEAMAPI =
ifeq ($(CC), emcc) ifeq ($(CC), emcc)
LDFLAGS += --preload-file game.zip --preload-file config.js --preload-file game.js LDFLAGS += -sUSE_WEBGPU --shell-file shell.html
CPPFLAGS += -Wbad-function-cast -Wcast-function-type -sSTACK_SIZE=5MB -sALLOW_MEMORY_GROWTH CPPFLAGS += -Wbad-function-cast -Wcast-function-type -sSTACK_SIZE=5MB -sALLOW_MEMORY_GROWTH
OPT = 0 OPT = 0
NDEBUG = 1 NDEBUG = 1
AR = emar AR = emar
ARCH:= wasm
endif endif
CCC != $(CC) -v CCC != $(CC) -v
@ -90,11 +94,7 @@ PKGCMD = tar --directory --exclude="./*.a" --exclude="./obj" -czf $(DISTDIR)/$(D
ZIP = .tar.gz ZIP = .tar.gz
UNZIP = cp $(DISTDIR)/$(DIST) $(DESTDIR) && tar xzf $(DESTDIR)/$(DIST) -C $(DESTDIR) && rm $(DESTDIR)/$(DIST) UNZIP = cp $(DISTDIR)/$(DIST) $(DESTDIR) && tar xzf $(DESTDIR)/$(DIST) -C $(DESTDIR) && rm $(DESTDIR)/$(DIST)
ifeq ($(ARCH),) INFO := $(INFO)_$(ARCH)
ARCH != uname -m
endif
INFO :=$(INFO)_$(ARCH)
ifeq ($(OS), Windows_NT) # then WINDOWS ifeq ($(OS), Windows_NT) # then WINDOWS
PLATFORM := win64 PLATFORM := win64
@ -167,6 +167,9 @@ includeflag := $(addprefix -I, $(includeflag))
WARNING_FLAGS = -Wno-incompatible-function-pointer-types -Wno-incompatible-pointer-types WARNING_FLAGS = -Wno-incompatible-function-pointer-types -Wno-incompatible-pointer-types
ifeq ($(INFO),_)
INFO :=
endif
APP = prosperon APP = prosperon
NAME = $(APP)$(INFO)$(EXT) NAME = $(APP)$(INFO)$(EXT)
SEM != git describe --tags --abbrev=0 SEM != git describe --tags --abbrev=0
@ -271,6 +274,7 @@ crossmac: Prosperon.icns
crossweb: crossweb:
make CC=emcc make CC=emcc
mv $(APP).html index.html
clean: clean:
@echo Cleaning project @echo Cleaning project

View file

@ -230,7 +230,7 @@ Cmdline.register_order("debug", function() {
Cmdline.register_order("play", function(argv) { Cmdline.register_order("play", function(argv) {
if (argv[0]) if (argv[0])
io.chdir(argv[0]); io.chdir(argv[0]);
game.loadurs(); game.loadurs();
if (!io.exists(projectfile)) { if (!io.exists(projectfile)) {
@ -267,9 +267,17 @@ Cmdline.register_order("pack", function(str) {
packname = str[0]; packname = str[0];
say(`Packing into ${packname}`); say(`Packing into ${packname}`);
// io.pack_engine(packname); io.pack_start(packname);
io.chmod(packname, 666); var files = io.ls('.');
files = files.filter(f => !f.startsWith('.git'));
files = files.filter(f => !f.startsWith('.nova'));
files = files.filter(f => !f.includes('.DS_Store'));
files = files.filter(f => !f.startsWith('.gitignore'));
say(files);
for (var f of files)
io.pack_add(f);
io.pack_end();
}, "Pack the game into the given name.", "NAME"); }, "Pack the game into the given name.", "NAME");
Cmdline.register_order("cdb", function(argv) { Cmdline.register_order("cdb", function(argv) {

View file

@ -120,6 +120,11 @@ JSValue strarr2js(char **c)
return arr; return arr;
} }
JSValue js2strarr(JSValue v)
{
}
JSValue number2js(double g) { return JS_NewFloat64(js,g); } JSValue number2js(double g) { return JS_NewFloat64(js,g); }
double js2number(JSValue v) { double js2number(JSValue v) {
double g; double g;
@ -869,6 +874,10 @@ JSValue js_io_chmod(JSContext *js, JSValue this, int argc, JSValue *argv)
JSC_SCALL(io_save_qoa, save_qoa(str)) JSC_SCALL(io_save_qoa, save_qoa(str))
JSC_SCALL(io_pack_start, pack_start(str))
JSC_SCALL(io_pack_add, pack_add(str))
JSC_CCALL(io_pack_end, pack_end())
static const JSCFunctionListEntry js_io_funcs[] = { static const JSCFunctionListEntry js_io_funcs[] = {
MIST_FUNC_DEF(io, exists,1), MIST_FUNC_DEF(io, exists,1),
MIST_FUNC_DEF(io, ls, 0), MIST_FUNC_DEF(io, ls, 0),
@ -882,6 +891,9 @@ static const JSCFunctionListEntry js_io_funcs[] = {
MIST_FUNC_DEF(io, slurpbytes, 1), MIST_FUNC_DEF(io, slurpbytes, 1),
MIST_FUNC_DEF(io, slurpwrite, 2), MIST_FUNC_DEF(io, slurpwrite, 2),
MIST_FUNC_DEF(io, save_qoa,1), MIST_FUNC_DEF(io, save_qoa,1),
MIST_FUNC_DEF(io, pack_start, 1),
MIST_FUNC_DEF(io, pack_add, 1),
MIST_FUNC_DEF(io, pack_end, 0)
}; };
JSC_CCALL(debug_draw_gameobject, gameobject_draw_debug(js2gameobject(argv[0]));) JSC_CCALL(debug_draw_gameobject, gameobject_draw_debug(js2gameobject(argv[0]));)

View file

@ -45,46 +45,57 @@ static mz_zip_archive game_cdb;
int LOADED_GAME = 0; int LOADED_GAME = 0;
uint8_t *gamebuf; uint8_t *gamebuf;
void *zipbuf;
sfetch_handle_t game_h;
static void response_cb(const sfetch_response_t *r) static void response_cb(const sfetch_response_t *r)
{ {
if (r->fetched) { if (r->fetched) {
mz_zip_reader_init_mem(&game_cdb, r->data.ptr, r->data.size,0); zipbuf = malloc(r->data.size);
LOADED_GAME = 1; memcpy(zipbuf, r->data.ptr, r->data.size);
mz_zip_reader_init_mem(&game_cdb, zipbuf, r->data.size,0);
} }
if (r->finished) { if (r->finished) {
LOADED_GAME = -1; LOADED_GAME = 1;
if (r->failed) { void *buf = sfetch_unbind_buffer(r->handle);
free(buf);
if (r->failed)
LOADED_GAME = -1; LOADED_GAME = -1;
}
} }
} }
void *gamedata; void *gamedata;
void resources_init() { void resources_init() {
/*
sfetch_setup(&(sfetch_desc_t){ sfetch_setup(&(sfetch_desc_t){
.max_requests = 1024, .max_requests = 1024,
.num_channels = 4, .num_channels = 4,
.num_lanes = 8, .num_lanes = 8,
.logger = { .func = sg_logging }, .logger = { .func = sg_logging },
}); });
gamebuf = malloc(64*1024*1024); mz_zip_reader_init_mem(&corecdb, core_cdb, core_cdb_len, 0);
sfetch_handle_t h = sfetch_send(&(sfetch_request_t){ #ifdef __EMSCRIPTEN__
gamebuf = malloc(8*1024*1024);
game_h = sfetch_send(&(sfetch_request_t){
.path="game.zip", .path="game.zip",
.callback = response_cb, .callback = response_cb,
.buffer = { .buffer = {
.ptr = gamebuf, .ptr = gamebuf,
.size = 64*1024*1024 .size = 8*1024*1024
} }
}); });
*/ #else
mz_zip_reader_init_mem(&corecdb, core_cdb, core_cdb_len, 0);
size_t gamesize; size_t gamesize;
gamedata = slurp_file("game.zip", &gamesize); gamebuf = slurp_file("game.zip", &gamesize);
mz_zip_reader_init_mem(&game_cdb, gamedata, gamesize, 0); if (gamebuf) {
mz_zip_reader_init_mem(&game_cdb, gamebuf, gamesize, 0);
free(gamebuf);
return;
}
#endif
} }
char *get_filename_from_path(char *path, int extension) { char *get_filename_from_path(char *path, int extension) {
@ -163,10 +174,31 @@ char **ls(const char *path)
return ls_paths; return ls_paths;
} }
static mz_zip_archive ar;
void pack_start(const char *name)
{
memset(&ar, 0, sizeof(ar));
int status = mz_zip_writer_init_file(&ar, name, 0);
}
void pack_add(const char *path)
{
mz_zip_writer_add_file(&ar, path, path, NULL, 0, MZ_BEST_COMPRESSION);
}
void pack_end()
{
mz_zip_writer_finalize_archive(&ar);
mz_zip_writer_end(&ar);
}
#else #else
void fill_extensions(char *paths, const char *path, const char *ext) void fill_extensions(char *paths, const char *path, const char *ext)
{}; {};
char **ls(const char *path) { return NULL; } char **ls(const char *path) { return NULL; }
void pack(const char *name, const char *dir) {}
#endif #endif
char *str_replace_ext(const char *s, const char *newext) { char *str_replace_ext(const char *s, const char *newext) {

View file

@ -18,6 +18,9 @@ char **ls(const char *path);
int cp(const char *p1, const char *p2); int cp(const char *p1, const char *p2);
int fexists(const char *path); int fexists(const char *path);
time_t file_mod_secs(const char *file); time_t file_mod_secs(const char *file);
void pack_start(const char *name);
void pack_add(const char *path);
void pack_end();
char *dirname(const char *path); char *dirname(const char *path);
@ -27,14 +30,4 @@ int slurp_write(const char *txt, const char *filename, size_t len);
char *seprint(char *fmt, ...); char *seprint(char *fmt, ...);
static inline void *stbarrdup(void *mem, size_t size, int len) {
void *out = NULL;
arrsetlen(out, len);
memcpy(out,mem,size*len);
return out;
}
#define arrconcat(a,b) do{for (int i = 0; i < arrlen(b); i++) arrput(a,b[i]);}while(0)
#define arrdup(a) (stbarrdup(a, sizeof(*a), arrlen(a)))
#endif #endif

View file

@ -20,6 +20,8 @@ struct window mainwin = {
.vsync = 1, .vsync = 1,
.enable_clipboard = 0, .enable_clipboard = 0,
.enable_dragndrop = 0, .enable_dragndrop = 0,
.size = (HMM_Vec2){640,400},
.rendersize = (HMM_Vec2){640,400},
}; };
static struct window *windows = NULL; static struct window *windows = NULL;

View file

@ -53,8 +53,10 @@ static int sim_play = SIM_PLAY;
static int argc; static int argc;
static char **args; static char **args;
static JSValue c_start; static JSValue c_start = JS_UNDEFINED;
static JSValue c_process_fn; static JSValue c_process_fn = JS_UNDEFINED;
static int PLAYSTART = 0;
void c_init() { void c_init() {
mainwin.start = 1; mainwin.start = 1;
@ -62,13 +64,28 @@ void c_init() {
phys2d_init(); phys2d_init();
render_init(); render_init();
particle_init(); particle_init();
script_call_sym(c_start,0,NULL); if (!JS_IsUndefined(c_start)) {
JS_FreeValue(js, c_start); script_call_sym(c_start,0,NULL);
JS_FreeValue(js, c_start);
}
} }
void c_frame() { void c_frame() {
sfetch_dowork();
#ifdef __EMSCRIPTEN__
if (PLAYSTART)
script_call_sym(c_process_fn,0,NULL);
else if (LOADED_GAME) {
PLAYSTART = 1;
printf("LOADED GAME\n");
script_evalf("cmd_args('play');");
script_call_sym(c_start,0,NULL);
JS_FreeValue(js, c_start);
window_resize(sapp_width(), sapp_height());
}
#else
script_call_sym(c_process_fn,0,NULL); script_call_sym(c_process_fn,0,NULL);
fflush(stdout); #endif
} }
void cleanup() void cleanup()
@ -216,6 +233,7 @@ sapp_desc sokol_main(int argc, char **argv) {
stm_setup(); /* time */ stm_setup(); /* time */
script_startup(); script_startup();
#ifndef __EMSCRIPTEN__
int argsize = 0; int argsize = 0;
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
argsize += strlen(argv[i]); argsize += strlen(argv[i]);
@ -225,15 +243,13 @@ sapp_desc sokol_main(int argc, char **argv) {
char cmdstr[argsize+1]; char cmdstr[argsize+1];
cmdstr[0] = '\0'; cmdstr[0] = '\0';
for (int i = 0; i < argc; i++) for (int i = 0; i < argc; i++) {
{
strcat(cmdstr, argv[i]); strcat(cmdstr, argv[i]);
if (argc > i+1) strcat(cmdstr, " "); if (argc > i+1) strcat(cmdstr, " ");
} }
//while (!LOADED_GAME)
// sfetch_dowork();
script_evalf("cmd_args('%s');", cmdstr); script_evalf("cmd_args('%s');", cmdstr);
#endif
return start_desc; return start_desc;
} }