offload miniz to quickjs; simplify resources.c so it no longer handles the core db; refactor making textures to use arraybuffers

This commit is contained in:
2024-11-09 13:51:43 -06:00
parent 140c61ab9b
commit d05948be47
16 changed files with 124 additions and 9469 deletions

View File

@@ -45,6 +45,7 @@ deps += dependency('qjs-layout',static:true)
deps += dependency('qjs-nota',static:true)
deps += dependency('qjs-miniz',static:true)
deps += dependency('qjs-soloud',static:true)
deps += dependency('qjs-dmon',static:true)
deps += dependency('threads')
@@ -62,7 +63,7 @@ if storefront == 'steam'
endif
sources = []
src = ['anim.c', 'config.c', 'datastream.c','font.c','gameobject.c','HandmadeMath.c','input.c', 'jsffi.c','log.c','miniz.c','model.c','render.c','script.c','resources.c','simplex.c','spline.c','texture.c', 'timer.c', 'transform.c','warp.c','window.c','yugine.c']
src = ['anim.c', 'config.c', 'datastream.c','font.c','gameobject.c','HandmadeMath.c','input.c', 'jsffi.c','log.c','model.c','render.c','script.c','resources.c','simplex.c','spline.c','texture.c', 'timer.c', 'transform.c','warp.c','window.c','yugine.c']
imsrc = ['GraphEditor.cpp','ImCurveEdit.cpp','ImGradient.cpp','imgui_draw.cpp','imgui_tables.cpp','imgui_widgets.cpp','imgui.cpp','ImGuizmo.cpp','imnodes.cpp','implot_items.cpp','implot.cpp']

View File

@@ -318,9 +318,53 @@ globalThis.use = function use(file) {
return ret;
};
globalThis.spinup = function spinup(file)
var allpaths = io.ls();
io.exists = function(path)
{
// spin up this file into its own entity
return allpaths.includes(path) || core_db.exists(path);
}
var tmpslurp = io.slurp;
io.slurp = function(path)
{
path = Resources.replpath(path);
var ret = tmpslurp(path, true) || core_db.slurp(path, true);
if (!ret) console.info(`could not slurp ${path}`);
return ret;
}
io.slurpbytes = function(path)
{
path = Resources.replpath(path);
var ret = tmpslurp(path) || core_db.slurp(path);
if (!ret) throw new Error(`Could not find file ${path} anywhere`);
return ret;
}
var coredata = tmpslurp("core.zip");
var core_db = miniz.read(coredata);
io.globToRegex = function (glob) {
// Escape special regex characters
// Replace glob characters with regex equivalents
let regexStr = glob
.replace(/[\.\\]/g, "\\$&") // Escape literal backslashes and dots
.replace(/([^\*])\*/g, "$1[^/]*") // * matches any number of characters except /
.replace(/\*\*/g, ".*") // ** matches any number of characters, including none
.replace(/\[(.*?)\]/g, "[$1]") // Character sets
.replace(/\?/g, "."); // ? matches any single character
// Ensure the regex matches the whole string
regexStr = "^" + regexStr + "$";
// Create and return the regex object
return new RegExp(regexStr);
};
io.glob = function(pat) {
var regex = io.globToRegex(pat);
return allpaths.filter(str => str.match(regex)).sort();
}
function stripped_use(file, script) {
@@ -367,7 +411,7 @@ if (!profile.enabled) use = stripped_use;
Object.assign(globalThis, use("prosperon.js"));
app.interval(_ => {
/*app.interval(_ => {
profile.report("hotreload");
actor.hotreload();
render.hotreload();
@@ -375,3 +419,4 @@ app.interval(_ => {
repl.hotreload();
profile.endreport("hotreload");
}, 1);
*/

View File

@@ -61,7 +61,9 @@ game.engine_start = function (s) {
function () {
// global.mixin("sound.js");
world_start();
window.set_icon(game.texture("moon").texture);
var moon = game.texture('moon');
if (moon) window.set_icon(moon.texture);
Object.readonly(window.__proto__, "vsync");
Object.readonly(window.__proto__, "enable_dragndrop");
Object.readonly(window.__proto__, "enable_clipboard");
@@ -355,7 +357,7 @@ game.texture = function (path) {
}
if (ext === 'gif') {
anim = os.make_gif(path);
anim = os.make_gif(io.slurp(path));
if (!anim) return;
if (anim.frames.length === 1) {
// in this case, it's just a single image
@@ -371,9 +373,8 @@ game.texture = function (path) {
return anim;
}
var tex = os.make_texture(path);
if (!tex) return;
var tex = os.make_texture(io.slurpbytes(path));
if (!tex) throw new Error(`Could not make texture from ${path}`);
var image;
var anim;

View File

@@ -1040,6 +1040,7 @@ function calc_image_size(img)
}
render.image = function image(image, rect = [0,0], rotation = 0, color = Color.white) {
if (!image) throw Error ('Need an image to render.')
if (typeof image === "string")
image = game.texture(image);
@@ -1386,6 +1387,7 @@ var imgui_fn = function () {
*/
prosperon.render = function () {
try{
render.glue_pass();
render.set_view(prosperon.camera.transform);
render.set_projection_ortho({
@@ -1432,16 +1434,33 @@ prosperon.render = function () {
if (debug.show) imgui_fn();
profile.endreport("imgui");
// render.end_pass();
// render.commit();
// profile.report_frame(profile.secs(profile.now()) - frame_t);
// endframe();
} catch(e) {
throw e;
} finally {
render.end_pass();
render.commit();
profile.report_frame(profile.secs(profile.now()) - frame_t);
endframe();
}
};
dmon.watch('.');
function dmon_cb(e)
{
if (e.file.startsWith('.')) return;
console.info(json.encode(e))
}
prosperon.process = function process() {
layout.newframe();
// check for hot reloading
dmon.poll(dmon_cb);
profile.report("frame");
var dt = profile.secs(profile.now()) - frame_t;
frame_t = profile.secs(profile.now());
@@ -1497,7 +1516,6 @@ prosperon.process = function process() {
profile.endreport('frame');
profile.capture_data();
};
return { render };

View File

@@ -3,7 +3,6 @@ os.env.doc = "Return the value of the environment variable v.";
if (os.sys() === "windows") os.user = os.env("USERNAME");
else os.user = os.env("USER");
var allpaths = io.ls();
/*var ignore;
if (ignore = io.slurp('.prosperonignore')) {
ignore = ignore.split('\n');
@@ -89,24 +88,6 @@ io.chmod = function (file, mode) {
return tmpchm(file, parseInt(mode, 8));
};
var tmpfex = io.exists;
io.exists = function(path)
{
return allpaths.includes(path) || tmpfex(path);
}
var tmpslurp = io.slurp;
io.slurp = function (path) {
path = Resources.replpath(path);
return tmpslurp(path);
};
var tmpslurpb = io.slurpbytes;
io.slurpbytes = function (path) {
path = Resources.replpath(path);
return tmpslurpb(path);
};
io.mkpath = function (dir) {
if (!dir) return;
var mkstack = [];
@@ -139,28 +120,6 @@ io.rm = function (f) {
tmprm(Resources.replpath(f));
};
io.globToRegex = function (glob) {
// Escape special regex characters
// Replace glob characters with regex equivalents
let regexStr = glob
.replace(/[\.\\]/g, "\\$&") // Escape literal backslashes and dots
.replace(/([^\*])\*/g, "$1[^/]*") // * matches any number of characters except /
.replace(/\*\*/g, ".*") // ** matches any number of characters, including none
.replace(/\[(.*?)\]/g, "[$1]") // Character sets
.replace(/\?/g, "."); // ? matches any single character
// Ensure the regex matches the whole string
regexStr = "^" + regexStr + "$";
// Create and return the regex object
return new RegExp(regexStr);
};
io.glob = function(pat) {
var regex = io.globToRegex(pat);
return allpaths.filter(str => str.match(regex)).sort();
}
io.doc = {
doc: "Functions for filesystem input/output commands.",
exists: "Returns true if a file exists.",
@@ -275,7 +234,8 @@ Cmdline.register_order(
if (io.exists("game.js")) global.app = actor.spawn("game.js");
else global.app = actor.spawn("nogame.js");
if (project.icon) window.set_icon(game.texture(project.icon).texture);
var icon = game.texture(project.icon);
if (icon) window.set_icon(game.texture(icon.texture));
game.camera = world.spawn("camera2d");
});
},

View File

@@ -7,7 +7,6 @@
#include "sokol/sokol_args.h"
#include "sokol/sokol_gfx.h"
#include "sokol/sokol_app.h"
#include "sokol/sokol_fetch.h"
#include "sokol/util/sokol_gl.h"
#define CUTE_ASEPRITE_IMPLEMENTATION

View File

@@ -1707,7 +1707,6 @@ static const JSCFunctionListEntry js_profile_funcs[] = {
MIST_FUNC_DEF(profile,secs,1),
};
JSC_SCALL(io_exists, ret = boolean2js(fexists(str)))
JSC_CCALL(io_ls, return strarr2js(ls(".")))
JSC_SSCALL(io_cp, ret = number2js(cp(str,str2)))
JSC_SSCALL(io_mv, ret = number2js(rename(str,str2)))
@@ -1715,34 +1714,29 @@ JSC_SCALL(io_chdir, ret = number2js(chdir(str)))
JSC_SCALL(io_rm, ret = number2js(remove(str)))
JSC_SCALL(io_mkdir, ret = number2js(mkdir(str,0777)))
JSValue js_io_slurpbytes(JSContext *js, JSValue self, int argc, JSValue *argv)
{
const char *f = js2str(argv[0]);
size_t len;
unsigned char *d = slurp_file(f,&len);
if (!d) {
JS_FreeCString(js,f);
return JS_UNDEFINED;
}
JSValue ret = JS_NewArrayBufferCopy(js,d,len);
JS_FreeCString(js,f);
free(d);
return ret;
}
JSValue js_io_slurp(JSContext *js, JSValue self, int argc, JSValue *argv)
{
const char *file = js2str(argv[0]);
FILE *f = fopen(file, "rb");
JS_FreeCString(js,file);
if (!f)
return JS_UNDEFINED;
const char *f = js2str(argv[0]);
size_t len;
fseek(f,0,SEEK_END);
size_t fsize = ftell(f);
rewind(f);
void *slurp = malloc(fsize);
fread(slurp,fsize,1,f);
fclose(f);
char *s = slurp_text(f,&len);
JS_FreeCString(js,f);
JSValue ret;
if (JS_ToBool(js,argv[1]))
ret = JS_NewStringLen(js, slurp, fsize);
else
ret = JS_NewArrayBufferCopy(js, slurp, fsize);
if (!s) return JS_UNDEFINED;
free(slurp);
JSValue ret = JS_NewStringLen(js, s, len);
free(s);
return ret;
}
@@ -1778,7 +1772,6 @@ JSC_SCALL(io_mod,
)
static const JSCFunctionListEntry js_io_funcs[] = {
MIST_FUNC_DEF(io, exists,1),
MIST_FUNC_DEF(io, ls, 0),
MIST_FUNC_DEF(io, cp, 2),
MIST_FUNC_DEF(io, mv, 2),
@@ -1786,8 +1779,7 @@ static const JSCFunctionListEntry js_io_funcs[] = {
MIST_FUNC_DEF(io, chdir, 1),
MIST_FUNC_DEF(io, mkdir, 1),
MIST_FUNC_DEF(io, chmod, 2),
MIST_FUNC_DEF(io, slurp, 1),
MIST_FUNC_DEF(io, slurpbytes, 1),
MIST_FUNC_DEF(io, slurp, 2),
MIST_FUNC_DEF(io, slurpwrite, 2),
MIST_FUNC_DEF(io, mod,1)
};
@@ -2398,15 +2390,24 @@ JSC_CCALL(os_obj_size,
)
JSC_SCALL(os_make_texture,
ret = texture2js(texture_from_file(str));
JSC_CCALL(os_make_texture,
size_t len;
void *raw = JS_GetArrayBuffer(js, &len, argv[0]);
if (!raw) {
JS_ThrowReferenceError(js, "could not load texture with array buffer");
return JS_EXCEPTION;
}
ret = texture2js(texture_fromdata(raw, len));
JS_SetPropertyStr(js, ret, "path", JS_DupValue(js,argv[0]));
)
JSC_SCALL(os_make_gif,
JSC_CCALL(os_make_gif,
size_t rawlen;
unsigned char *raw = slurp_file(str, &rawlen);
if (!raw) goto END;
void *raw = JS_GetArrayBuffer(js, &rawlen, argv[0]);
if (!raw) {
JS_ThrowReferenceError(js, "could not load gif from supplied array buffer");
return JS_UNDEFINED;
}
int n;
texture *tex = calloc(1,sizeof(*tex));
int frames;
@@ -2414,8 +2415,6 @@ JSC_SCALL(os_make_gif,
tex->data = stbi_load_gif_from_memory(raw, rawlen, &delays, &tex->width, &tex->height, &frames, &n, 4);
tex->height *= frames;
printf("making gif with %s\n", str);
JSValue gif = JS_NewObject(js);
JSValue delay_arr = JS_NewArray(js);
JSValue jstex = texture2js(tex);
@@ -2441,14 +2440,13 @@ JSC_SCALL(os_make_gif,
free(delays);
ret = gif;
free(raw);
END:
)
JSC_SCALL(os_make_aseprite,
JSC_CCALL(os_make_aseprite,
size_t rawlen;
unsigned char *raw = slurp_file(str, &rawlen);
void *raw = JS_GetArrayBuffer(js,&rawlen,argv[0]);
if (!raw) return JS_UNDEFINED;
ase_t *ase = cute_aseprite_load_from_memory(raw, rawlen, NULL);
JSValue obj = JS_NewObject(js);
@@ -2832,9 +2830,10 @@ JS_SetPropertyFunctionList(js, js_##NAME, js_##NAME##_funcs, countof(js_##NAME##
JS_SetPrototype(js, js_##NAME, PARENT); \
JSValue js_layout_use(JSContext *js);
JSValue js_miniz(JSContext *js);
JSValue js_miniz_use(JSContext *js);
JSValue js_soloud_use(JSContext *js);
JSValue js_chipmunk2d_use(JSContext *js);
JSValue js_dmon_use(JSContext *js);
#ifndef NEDITOR
JSValue js_imgui(JSContext *js);
@@ -2885,9 +2884,11 @@ void ffi_load() {
srand(stm_now());
JS_SetPropertyStr(js, globalThis, "layout", js_layout_use(js));
JS_SetPropertyStr(js, globalThis, "miniz", js_miniz(js));
JS_SetPropertyStr(js, globalThis, "miniz", js_miniz_use(js));
JS_SetPropertyStr(js, globalThis, "soloud", js_soloud_use(js));
JS_SetPropertyStr(js, globalThis, "chipmunk2d", js_chipmunk2d_use(js));
JS_SetPropertyStr(js, globalThis, "dmon", js_dmon_use(js));
#ifndef NEDITOR
JS_SetPropertyStr(js, globalThis, "imgui", js_imgui(js));

View File

@@ -44,19 +44,9 @@ int stdout_lvl = LOG_ERROR;
void log_init()
{
#ifndef NDEBUG
if (!fexists(".prosperon")) {
logout = tmpfile();
writeout = tmpfile();
dump = tmpfile();
}
else {
logout = fopen(".prosperon/log.txt", "w");
writeout = fopen(".prosperon/transcript.txt", "w");
dump = fopen(".prosperon/quickjs.txt", "w");
quickjs_set_dumpout(dump);
}
quickjs_set_dumpout(dump);
logout = fopen(".prosperon/log.txt", "w");
writeout = fopen(".prosperon/transcript.txt", "w");
dump = fopen(".prosperon/quickjs.txt", "w");
#endif
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -16,8 +16,6 @@
#include <fcntl.h>
#include "miniz.h"
#ifndef __EMSCRIPTEN__
#include <ftw.h>
#endif
@@ -37,19 +35,10 @@ struct dirent *c_dirent = NULL;
char pathbuf[MAXPATH + 1];
static mz_zip_archive core_res;
int LOADED_GAME = 0;
uint8_t *gamebuf;
void *zipbuf;
sfetch_handle_t game_h;
void *os_slurp(const char *file, size_t *size)
{
FILE *f;
jump:
f = fopen(file, "rb");
if (!f) return NULL;
@@ -66,27 +55,6 @@ void *os_slurp(const char *file, size_t *size)
return slurp;
}
#define MAXGAMESIZE 15*1024*1024
static void response_cb(const sfetch_response_t *r)
{
if (r->fetched) {
YughInfo("FINISHED FETCH\n");
zipbuf = malloc(r->data.size);
memcpy(zipbuf, r->data.ptr, r->data.size);
}
if (r->finished) {
YughInfo("FINISHED RESPONSE\n");
LOADED_GAME = 1;
void *buf = sfetch_unbind_buffer(r->handle);
free(buf);
if (r->failed)
LOADED_GAME = -1;
}
}
#if defined(__linux__)
#include <unistd.h>
#include <stdio.h>
@@ -116,46 +84,6 @@ int get_executable_path(char *buffer, unsigned int buffer_size) {
}
void *gamedata;
void resources_init() {
sfetch_setup(&(sfetch_desc_t){
.max_requests = 1024,
.num_channels = 4,
.num_lanes = 8,
.logger = { .func = sg_logging },
});
size_t coresize;
void *core = os_slurp("core.zip", &coresize);
mz_zip_reader_init_mem(&core_res, core, coresize, 0);
#ifdef __EMSCRIPTEN__
gamebuf = malloc(MAXGAMESIZE);
game_h = sfetch_send(&(sfetch_request_t){
.path="game.zip",
.callback = response_cb,
.buffer = {
.ptr = gamebuf,
.size = MAXGAMESIZE
}
});
#endif
}
char *seprint(char *fmt, ...)
{
va_list args;
va_start (args, fmt);
char test[128];
int len = vsnprintf(test, 128, fmt, args);
if (len > 128) {
char *test = malloc(len+1);
vsnprintf(test, len+1, fmt, args);
return strdup(test);
}
return strdup(test);
}
static char *ext_paths = NULL;
#ifndef __EMSCRIPTEN__
@@ -171,16 +99,9 @@ static int ls_ftw(const char *path, const struct stat *sb, int typeflag)
time_t file_mod_secs(const char *file) {
struct stat attr;
mz_uint index;
mz_zip_archive_file_stat pstat;
if (!stat(file,&attr))
return attr.st_mtime;
else if ((index = mz_zip_reader_locate_file(&core_res, file, NULL, 0)) != -1) {
mz_zip_reader_file_stat(&core_res, index, &pstat);
return pstat.m_time;
}
return -1;
}
@@ -216,21 +137,10 @@ char *str_replace_ext(const char *s, const char *newext) {
return ret;
}
int fexists(const char *path)
{
int len = strlen(path);
if (mz_zip_reader_locate_file(&core_res, path, NULL, 0) != -1) return 1;
return 0;
}
void *slurp_file(const char *filename, size_t *size)
{
if (!access(filename, R_OK))
return os_slurp(filename, size);
else
return mz_zip_reader_extract_file_to_heap(&core_res, filename, size, 0);
}
char *slurp_text(const char *filename, size_t *size)

View File

@@ -9,12 +9,10 @@
extern char *DATA_PATH;
extern int LOADED_GAME;
void resources_init();
char *str_replace_ext(const char *s, const char *newext);
FILE *res_open(char *path, const char *tag);
char **ls(const char *path);
int cp(const char *p1, const char *p2);
int fexists(const char *path);
time_t file_mod_secs(const char *file);
void pack_start(const char *name);
void pack_add(const char *path);
@@ -24,6 +22,4 @@ void *slurp_file(const char *filename, size_t *size);
char *slurp_text(const char *filename, size_t *size);
int slurp_write(void *txt, const char *filename, size_t len);
char *seprint(char *fmt, ...);
#endif

View File

@@ -247,8 +247,6 @@ struct texture *texture_fromdata(void *raw, long size)
tex->data = data;
texture_load_gpu(tex);
return tex;
}

View File

@@ -48,11 +48,6 @@ void window_suspended(int s)
script_evalf("prosperon.suspended(%d);", s);
}
void set_icon(const char *png) {
icon = texture_from_file(png);
window_seticon(&mainwin, icon);
}
void window_setfullscreen(window *w, int f)
{
if (w->fullscreen == f) return;

View File

@@ -34,7 +34,6 @@ void window_apply(window *w);
void window_free(window *w);
void window_setfullscreen(window *w, int f);
void set_icon(const char *png);
void window_seticon(struct window *w, struct texture *icon);
#endif

View File

@@ -19,7 +19,6 @@
#include "sokol/sokol_audio.h"
#include "sokol/sokol_time.h"
#include "sokol/sokol_args.h"
#include "sokol/sokol_fetch.h"
#include <stb_ds.h>
#include <stb_truetype.h>
#include "stb_image.h"
@@ -44,7 +43,6 @@ void c_init() {
}
void c_frame() {
sfetch_dowork();
script_call_sym(c_process_fn,0,NULL);
}
@@ -193,7 +191,6 @@ sapp_desc sokol_main(int argc, char **argv) {
signal(SIGFPE, seghandle);
#endif
resources_init();
stm_setup(); /* time */
script_startup();