cdb command line options; packing and playing game; add stb_vorbis

This commit is contained in:
John Alanbrook 2024-03-02 06:00:35 +00:00
parent 1e9b5f6341
commit 0054c7ab2e
12 changed files with 5334 additions and 25 deletions

View file

@ -178,7 +178,7 @@ endif
WARNING_FLAGS = -Wno-incompatible-function-pointer-types WARNING_FLAGS = -Wno-incompatible-function-pointer-types
NAME = primum$(EXT) NAME = primum$(EXT)
SEM = 0.0.1 SEM = 0.3.0
COM != fossil describe COM != fossil describe
VER = $(SEM) VER = $(SEM)

View file

@ -146,6 +146,8 @@ Object.assign(performance, {
}, },
}); });
performance.now = performance.tick_now;
performance.test = { performance.test = {
barecall() { performance(0); }, barecall() { performance(0); },
unpack_num(n) { performance(1,n); }, unpack_num(n) { performance(1,n); },

View file

@ -376,7 +376,7 @@ Window.doc = {};
Window.doc.width = "Width of the game window."; Window.doc.width = "Width of the game window.";
Window.doc.height = "Height of the game window."; Window.doc.height = "Height of the game window.";
Window.doc.dimensions = "Window width and height packaged in an array [width,height]"; Window.doc.dimensions = "Window width and height packaged in an array [width,height]";
Window.doc.name = "Name in the title bar of the window."; Window.doc.title = "Name in the title bar of the window.";
Window.doc.boundingbox = "Boundingbox of the window, with top and right being its height and width."; Window.doc.boundingbox = "Boundingbox of the window, with top and right being its height and width.";
Register.update.register(Game.exec, Game); Register.update.register(Game.exec, Game);

View file

@ -780,8 +780,14 @@ var resani = function(ur, path)
return restry; return restry;
} }
var ur = {}; var ur;
ur._list = [];
if (io.exists(".prosperon/ur.json"))
ur = json.decode(io.slurp(".prosperon/ur.json"));
else {
ur = {};
ur._list = [];
}
/* UR OBJECT /* UR OBJECT
ur { ur {
@ -852,15 +858,19 @@ function file2fqn(file)
/* FIND ALL URS IN A PROJECT */ /* FIND ALL URS IN A PROJECT */
for (var file of io.glob("**.jso")) { for (var file of io.glob("**.jso")) {
if (file[0] === '.' || file[0] === '_') continue;
var topur = file2fqn(file); var topur = file2fqn(file);
topur.text = file; topur.text = file;
} }
for (var file of io.glob("**.json")) { for (var file of io.glob("**.json")) {
if (file[0] === '.' || file[0] === '_') continue;
var topur = file2fqn(file); var topur = file2fqn(file);
topur.data = file; topur.data = file;
} }
io.slurpwrite(".prosperon/ur.json", json.encode(ur));
ur.empty = { ur.empty = {
name: "empty" name: "empty"
}; };

View file

@ -9,7 +9,7 @@ audio.sound = {
return; return;
} }
var src = audio.dsp.source(file); var src = audio.dsp.source(file);
bus ??= sound.bus.master; bus ??= audio.sound.bus.master;
// src.plugin(bus); // src.plugin(bus);
return src; return src;
}, },
@ -106,6 +106,8 @@ Object.mixin(cmd(180).__proto__, {
set volume(x) { this.gain = x; }, set volume(x) { this.gain = x; },
}); });
audio.sound.bus.master = cmd(180);
/*Object.mixin(audio.dsp.source().__proto__, { /*Object.mixin(audio.dsp.source().__proto__, {
frames() { return cmd(197,this); }, frames() { return cmd(197,this); },
length() { return this.frames()/sound.samplerate(); }, length() { return this.frames()/sound.samplerate(); },

View file

@ -1,9 +1,11 @@
os.cwd.doc = "Get the absolute path of the current working directory."; os.cwd.doc = "Get the absolute path of the current working directory.";
os.env.doc = "Return the value of the environment variable v."; os.env.doc = "Return the value of the environment variable v.";
var projectfile = ".prosperon/project.json";
var Resources = {}; var Resources = {};
Resources.images = ["png", "jpg", "jpeg", "gif"]; Resources.images = ["png", "jpg", "jpeg", "gif"];
Resources.sounds = ["wav", "mp3", "flac"]; Resources.sounds = ["wav", "mp3", "flac", "qoa"];
Resources.scripts = "js"; Resources.scripts = "js";
Resources.is_image = function(path) { Resources.is_image = function(path) {
var ext = path.ext(); var ext = path.ext();
@ -109,7 +111,6 @@ var console = {
console.write(err.name); console.write(err.name);
console.write(err.message); console.write(err.message);
console.write(err.stack); console.write(err.stack);
// console.write(stack);
}, },
clear() { clear() {
@ -147,6 +148,11 @@ console.doc = {
"@": user path "@": user path
"/": game path "/": game path
*/ */
var tmp = io.chmod;
io.chmod = function(file,mode) {
return tmp(file,parseInt(mode,8));
}
io.mixin({ io.mixin({
extensions(ext) { extensions(ext) {
@ -213,7 +219,7 @@ Cmdline.register_order("edit", function() {
} }
Game.engine_start(function() { Game.engine_start(function() {
global.mixin(use("scripts/editor.js")); global.mixin("scripts/editor.js");
use("editorconfig.js"); use("editorconfig.js");
editor.enter_editor(); editor.enter_editor();
}); });
@ -234,7 +240,7 @@ Cmdline.register_order("init", function() {
var project = {}; var project = {};
project.version = prosperon.version; project.version = prosperon.version;
project.revision = prosperon.revision; project.revision = prosperon.revision;
io.slurpwrite(".prosperon/project", json.encode(project)); io.slurpwrite(projectfile, json.encode(project));
}, "Turn the directory into a Prosperon game."); }, "Turn the directory into a Prosperon game.");
@ -243,25 +249,25 @@ Cmdline.register_order("debug", function() {
}, "Play the game with debugging enabled."); }, "Play the game with debugging enabled.");
Cmdline.register_order("play", function() { Cmdline.register_order("play", function() {
if (!io.exists(".prosperon/project")) { if (!io.exists(projectfile)) {
say("No game to play. Try making one with 'prosperon init'."); say("No game to play. Try making one with 'prosperon init'.");
return; return;
} }
var project = json.decode(io.slurp(".prosperon/project")); var project = json.decode(io.slurp(projectfile));
global.mixin("config.js");
if (project.title) Window.title(project.title);
Game.engine_start(function() { Game.engine_start(function() {
global.mixin("config.js");
global.mixin("game.js"); global.mixin("game.js");
if (project.icon) Window.icon(project.icon); if (project.icon) Window.icon(project.icon);
if (project.title) Window.title(project.title);
}); });
}, "Play the game present in this folder."); }, "Play the game present in this folder.");
Cmdline.register_order("pack", function(str) { Cmdline.register_order("pack", function(str) {
var packname; var packname;
if (str.length === 0) if (str.length === 0)
packname = "test.cdb"; packname = "game.cdb";
else if (str.length > 1) { else if (str.length > 1) {
console.warn("Give me a single filename for the pack."); console.warn("Give me a single filename for the pack.");
return; return;
@ -271,8 +277,71 @@ Cmdline.register_order("pack", function(str) {
say(`Packing into ${packname}`); say(`Packing into ${packname}`);
cmd(124, packname); cmd(124, packname);
io.chmod(packname, 666);
}, "Pack the game into the given name.", "NAME"); }, "Pack the game into the given name.", "NAME");
Cmdline.register_order("cdb", function(argv) {
var cdb = "game.cdb";
if (!io.exists(cdb)) {
say(`No 'game.cdb' present.`);
return;
}
if (argv.length === 0) {
say(`cdb name: ${cdb}`);
}
}, "CDB commands.");
Cmdline.register_order("qoa", function(argv) {
var sounds = Resources.sounds.filter(x => x !== "qoa");
for (var file of argv) {
if (!sounds.includes(file.ext())) continue;
say(`converting ${file}`);
cmd(262,file);
}
}, "Convert file(s) to qoa.");
Cmdline.register_order("about", function(argv) {
if (!argv[0]) {
say('About your game');
say(`Prosperon version ${prosperon.version}`);
say(`Total entities ${ur._list.length}`);
}
switch (argv[0]) {
case "entities":
for (var i of ur._list) say(i);
break;
}
}, "Get information about this game.");
Cmdline.register_order("ur", function(argv) {
for (var i of ur._list.sort()) say(i);
}, "Get information about the ur types in your game.");
Cmdline.register_order("env", function(argv) {
if (argv.length > 2) return;
var gg = json.decode(io.slurp(projectfile));
if (argv.length === 0) {
say(json.encode(gg,null,1));
return;
}
if (argv.length === 1) {
var v = gg[argv[0]];
if (!v) {
say(`Value ${argv[0]} not found.`);
return;
}
say(`${argv[0]}:${v}`);
} else {
gg[argv[0]] = argv[1];
say(`Set ${argv[0]}:${v}`);
say(json.encode(gg,null,1));
io.slurpwrite(projectfile, json.encode(gg));
}
}, "Get or set game variables.");
Cmdline.register_order("unpack", function() { Cmdline.register_order("unpack", function() {
say("Unpacking not implemented."); say("Unpacking not implemented.");
}, "Unpack this binary's contents into this folder for editing."); }, "Unpack this binary's contents into this folder for editing.");
@ -281,6 +350,32 @@ Cmdline.register_order("build", function() {
say("Building not implemented."); say("Building not implemented.");
}, "Build static assets for this project."); }, "Build static assets for this project.");
Cmdline.register_order("nota", function(argv) {
for (var file of argv) {
if (!io.exists(file)) {
say(`File ${file} does not exist.`);
continue;
}
var obj = json.decode(io.slurp(file));
var nn = nota.encode(obj);
io.slurpwrite(file.set_ext(".nota"), nn);
}
}, "Create a nota file from a json.");
Cmdline.register_order("json", function(argv) {
for (var file of argv) {
if (!io.exists(file)) {
say(`File ${file} does not exist.`);
continue;
}
say(file.ext());
var obj = nota.decode(io.slurp(file));
var nn = json.encode(obj);
io.slurpwrite(file.set_ext(".json", nn));
}
}, "Create a JSON from a nota.");
Cmdline.register_order("api", function(obj) { Cmdline.register_order("api", function(obj) {
if (!obj[0]) { if (!obj[0]) {
Cmdline.print_order("api"); Cmdline.print_order("api");
@ -381,6 +476,7 @@ function cmd_args(cmdargs)
Cmdline.orders[cmds[0]](cmds.slice(1)); Cmdline.orders[cmds[0]](cmds.slice(1));
} }
Cmdline.register_order("clean", function(argv) { Cmdline.register_order("clean", function(argv) {
say("Cleaning not implemented."); say("Cleaning not implemented.");
}, "Clean up a given object file.", "JSON ..."); }, "Clean up a given object file.", "JSON ...");

View file

@ -1448,6 +1448,10 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
d1 = slurp_file(str, &plen); d1 = slurp_file(str, &plen);
return script_run_bytecode(d1, plen); return script_run_bytecode(d1, plen);
break; break;
case 262:
str = js2str(argv[1]);
save_qoa(str);
break;
} }
if (str) JS_FreeCString(js, str); if (str) JS_FreeCString(js, str);
@ -1999,6 +2003,14 @@ JSValue js_io_slurpwrite(JSContext *js, JSValueConst this, int argc, JSValue *ar
return ret; return ret;
} }
JSValue js_io_chmod(JSContext *js, JSValueConst this, int argc, JSValue *argv)
{
char *f = js2str(argv[0]);
int mod = js2int(argv[1]);
chmod(f, mod);
return JS_UNDEFINED;
}
static const JSCFunctionListEntry js_io_funcs[] = { static const JSCFunctionListEntry js_io_funcs[] = {
MIST_CFUNC_DEF("exists", 1, js_io_exists), MIST_CFUNC_DEF("exists", 1, js_io_exists),
MIST_CFUNC_DEF("ls", 0, js_io_ls), MIST_CFUNC_DEF("ls", 0, js_io_ls),
@ -2006,6 +2018,7 @@ static const JSCFunctionListEntry js_io_funcs[] = {
MIST_CFUNC_DEF("mv", 2, js_io_mv), MIST_CFUNC_DEF("mv", 2, js_io_mv),
MIST_CFUNC_DEF("rm", 1, js_io_rm), MIST_CFUNC_DEF("rm", 1, js_io_rm),
MIST_CFUNC_DEF("mkdir", 1, js_io_mkdir), MIST_CFUNC_DEF("mkdir", 1, js_io_mkdir),
MIST_CFUNC_DEF("chmod", 2, js_io_chmod),
MIST_CFUNC_DEF("slurp", 1, js_io_slurp), MIST_CFUNC_DEF("slurp", 1, js_io_slurp),
MIST_CFUNC_DEF("slurpbytes", 1, js_io_slurpbytes), MIST_CFUNC_DEF("slurpbytes", 1, js_io_slurpbytes),
MIST_CFUNC_DEF("slurpwrite", 2, js_io_slurpwrite), MIST_CFUNC_DEF("slurpwrite", 2, js_io_slurpwrite),

View file

@ -36,7 +36,7 @@ static struct cdb corecdb;
static struct cdb game_cdb; static struct cdb game_cdb;
void resources_init() { void resources_init() {
int fd = open("test.cdb", O_RDONLY); int fd = open("game.cdb", O_RDONLY);
cdb_init(&game_cdb, fd); cdb_init(&game_cdb, fd);
cdb_initf(&corecdb, core_cdb, core_cdb_len); cdb_initf(&corecdb, core_cdb, core_cdb_len);
} }
@ -254,7 +254,7 @@ int slurp_write(const char *txt, const char *filename, size_t len) {
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
static struct cdb_make cdbm; static struct cdb_make cdbm;
static const char *pack_ext[] = {".qoi", ".qoa", ".js", ".wav", ".mp3", ".png", ".sf2", ".midi", ".lvl", ".glsl", ".ttf"}; static const char *pack_ext[] = {".qoi", ".qoa", ".js", ".wav", ".mp3", ".png", ".sf2", ".midi", ".lvl", ".glsl", ".ttf", ".json", ".jso"};
static int ftw_pack(const char *path, const struct stat *sb, int flag) static int ftw_pack(const char *path, const struct stat *sb, int flag)
{ {
@ -265,7 +265,7 @@ static int ftw_pack(const char *path, const struct stat *sb, int flag)
if (!ext) if (!ext)
return 0; return 0;
for (int i = 0; i < 11; i++) { for (int i = 0; i < 13; i++) {
if (!strcmp(ext, pack_ext[i])) { if (!strcmp(ext, pack_ext[i])) {
pack = 1; pack = 1;
break; break;
@ -288,10 +288,15 @@ void pack_engine(const char *fname)
int fd; int fd;
char *key, *va; char *key, *va;
unsigned klen, vlen; unsigned klen, vlen;
fd = open(fname, O_RDWR|O_CREAT); fd = creat(fname, O_RDWR);
if (fd == -1) {
YughError("Couldn't make file at %s.", fname);
return;
}
cdb_make_start(&cdbm, fd); cdb_make_start(&cdbm, fd);
ftw(".", ftw_pack, 20); ftw(".", ftw_pack, 20);
cdb_make_finish(&cdbm); cdb_make_finish(&cdbm);
close(fd);
} }
#else #else
void pack_engine(const char *fname){ void pack_engine(const char *fname){

View file

@ -4,7 +4,6 @@
#include "math.h" #include "math.h"
#include "music.h" #include "music.h"
#include "resources.h" #include "resources.h"
#include "stb_vorbis.h"
#include "string.h" #include "string.h"
#include "time.h" #include "time.h"
#include <stdlib.h> #include <stdlib.h>
@ -182,7 +181,6 @@ struct wav *make_sound(const char *wav) {
if (!strcmp(ext, "wav")) if (!strcmp(ext, "wav"))
mwav->data = drwav_open_memory_and_read_pcm_frames_f32(raw, rawlen, &mwav->ch, &mwav->samplerate, &mwav->frames, NULL); mwav->data = drwav_open_memory_and_read_pcm_frames_f32(raw, rawlen, &mwav->ch, &mwav->samplerate, &mwav->frames, NULL);
else if (!strcmp(ext, "flac")) { else if (!strcmp(ext, "flac")) {
#ifndef NFLAC #ifndef NFLAC
mwav->data = drflac_open_memory_and_read_pcm_frames_f32(raw, rawlen, &mwav->ch, &mwav->samplerate, &mwav->frames, NULL); mwav->data = drflac_open_memory_and_read_pcm_frames_f32(raw, rawlen, &mwav->ch, &mwav->samplerate, &mwav->frames, NULL);
@ -230,6 +228,22 @@ struct wav *make_sound(const char *wav) {
return mwav; return mwav;
} }
void save_qoa(char *file)
{
wav *wav = make_sound(file);
qoa_desc q;
q.channels = wav->ch;
q.samples = wav->frames;
q.samplerate = wav->samplerate;
unsigned int len;
void *raw = qoa_encode(wav->data, &q, &len);
file = str_replace_ext(file, ".qoa");
slurp_write(raw, file, len);
free(raw);
free_sound(wav);
}
void free_sound(const char *wav) { void free_sound(const char *wav) {
struct wav *w = shget(wavhash, wav); struct wav *w = shget(wavhash, wav);
if (w == NULL) return; if (w == NULL) return;

View file

@ -33,10 +33,6 @@ typedef struct mp3 {
} mp3; } mp3;
typedef struct qoa {
// struct qoa_desc desc;
} qoa;
void sound_init(); void sound_init();
void audio_open(const char *device); void audio_open(const char *device);
void audio_close(); void audio_close();
@ -61,4 +57,6 @@ float db2float(float db);
float pct2db(float pct); float pct2db(float pct);
float pct2mult(float pct); float pct2mult(float pct);
void save_qoa(char *file);
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -259,7 +259,10 @@ static sapp_desc start_desc = {
.logger.func = sg_logging, .logger.func = sg_logging,
}; };
void app_name(const char *name) { sapp_set_window_title(name); } void app_name(const char *name) {
start_desc.window_title = strdup(name);
sapp_set_window_title(name);
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
#ifndef NDEBUG #ifndef NDEBUG