Archived
1
0
Fork 0
This repository has been archived on 2025-09-02. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
skcblitz/console.h

454 lines
12 KiB
C
Raw Permalink Normal View History

2025-09-02 14:43:36 +02:00
#define logcu(fmt, args ...) logu(LOG_CON, fmt, args)
#define logci(fmt, args ...) logi(LOG_CON, fmt, args)
#define logcw(fmt, args ...) logw(LOG_CON, fmt, args)
#define logce(fmt, args ...) loge(LOG_CON, fmt, args)
int str_tokenize(char *arg, char **args, const char *str) {
// if(str[0] == 0) {
// return 0;
// }
int pos = 0;
int apos = 0;
int argc = 0;
int last = 0;
byte space = 1;
byte quote = 0;
byte escape = 0;
char c;
while(c = str[pos++]) {
if(escape) {
escape = 0;
switch(c) {
case '\\':
case ' ':
case '"':
arg[apos++] = c;
break;
default:
logce(STR_PARSER_ESC_UNKNOWN, pos, c);
return 0;
}
}
else if(c == '\\') {
space = 0;
escape = 1;
}
else if(c == '"') {
space = 0;
quote = !quote;
last = pos;
}
else if(c == ' ' && !quote) {
if(!space) {
args[argc++] = arg;
arg[apos++] = 0;
arg += apos;
apos = 0;
}
space = 1;
}
else {
space = 0;
arg[apos++] = c;
}
}
if(escape) {
logce(STR_PARSER_ESC_SHORT, pos);
return 0;
}
if(quote) {
logce(STR_PARSER_NO_QUOTE, last);
return 0;
}
if(!space) {
args[argc++] = arg;
arg[apos] = 0;
}
return argc;
}
ccmd_t *con_get(const char *key) {
return (ccmd_t*)smap_get(&sys.ccmd_map, key);
}
void con_exec(const char *line) {
char str[64];
int argc;
char **argv;
cvar_t *cv;
ccmd_t *cmd;
if(!(argc = str_tokenize(sys.con_tok, sys.con_arg, line)))
return;
argv = sys.con_arg;
cv = cvar_get(argv[0]);
if(cv && argc == 1) {
cvar_format(cv, str);
logcu("%s = %s", cv->name, str);
return;
}
else if(cv && argc == 2) {
if(cv->readonly) {
logce(STR_CVAR_READONLY, cv->name);
}
else if(cvar_set(cv, argv[1], 0)) {
cvar_format(cv, str);
logcu("%s = %s", cv->name, str);
}
else {
logce(STR_CVAR_INVALID, cv->name, argv[1]);
}
return;
}
else if(cv) {
logce(STR_CVAR_MOREARGS, argc);
return;
}
cmd = con_get(argv[0]);
if(!cmd) {
logce(STR_CVAR_CCMD_UNKNOWN, argv[0]);
return;
}
if(--argc < cmd->min) {
logce(STR_CCMD_LESSARGS, argv[0], cmd->min, argc);
return;
}
else if(argc > cmd->max) {
logce(STR_CCMD_MOREARGS, argv[0], cmd->max, argc);
return;
}
logcu("# %s", line);
cmd->func(cmd, (const char **)&argv[1], argc);
}
void con_reset() {
sys.log_len = sprintf(sys.con_buf, COL_NEON "*** " SYS_PROGRAM_FULL " ***");
// for(int z = 0; z < sys.con_size; z++) {
// sys.con_msgs[z].message = NULL;
// }
// sys.con_pos = 0;
}
ccmd_t *con_add(const char *name, const char *args, ccmd_func *func, ushort min, ushort max) {
ccmd_t *cmd = &sys.ccmds[sys.n_ccmds];
cmd->func = func;
cmd->args = args;
cmd->min = min;
cmd->max = max;
cmd->id = sys.n_ccmds;
cmd->name = name;
sys.n_ccmds += 1;
return cmd;
}
void con_fmt_cvar(cvar_t *cv, char *str) {
int pos;
if(cv->type == CVAR_ENUM) {
pos = sprintf(str, "%s "COL_DGRAY"["COL_GRAY"D "COL_CRIMSON"%s"COL_DGRAY"] ["COL_LGRAY, ((const char**)cv->aux_data)[cv->value], ((const char**)cv->aux_data)[cv->def]);
for(int z = 0; z < cv->max; z++) {
pos += sprintf(str+pos, z ? ", %s" : "%s", ((const char**)cv->aux_data)[z]);
}
pos += sprintf(str+pos, COL_DGRAY"]");
}
else {
cvar_fmt[cv->type](str, cv->value);
pos = strlen(str);
pos += sprintf(str+pos, " "COL_DGRAY"["COL_GRAY"D "COL_CRIMSON);
cvar_fmt[cv->type](str+pos, cv->def);
pos += strlen(str+pos);
pos += sprintf(str+pos, COL_DGRAY"]");
if(cv->type == CVAR_INT)
pos += sprintf(str+pos, " ["COL_LGRAY"%d .. %d"COL_DGRAY"]", cv->min, cv->max);
else if(cv->type == CVAR_FLOAT)
pos += sprintf(str+pos, " ["COL_LGRAY"%.3f .. %.3f"COL_DGRAY"]", cvar_itf(cv->min), cvar_itf(cv->max));
}
logcu("%s "COL_NEON"%s "COL_DGRAY"[%s"COL_DGRAY"]"COL_GRAY" = "COL_WHITE"%s%s", cvar_types[cv->type], cv->name, cvar_categories[cv->category], str, cv->readonly ? " "COL_DGRAY"["COL_RED"RO"COL_DGRAY"]" : "");
}
void con_cmd_cvar(ccmd_t *cmd, const char **argv, int argc) {
cvar_t *cv;
char fmt[512];
if(argc) {
for(int z = 0; z < argc; z++) {
cv = cvar_get(argv[z]);
if(!cv) {
logce(STR_CVAR_UNKNOWN, argv[z]);
continue;
}
con_fmt_cvar(cv, fmt);
}
}
else {
int ro = 0;
for(int z = 0; z < sys.n_cvars; z++) {
cv = &sys.cvars[z];
con_fmt_cvar(cv, fmt);
ro += cv->readonly ? 1 : 0;
}
logcu(STR_CMD_CVARLIST, sys.n_cvars, ro);
}
}
void con_fmt_ccmd(ccmd_t *cmd, char *str) {
logcu("%s "COL_NEON"%s "COL_DGRAY"["COL_LGRAY"%d .. %d"COL_DGRAY"]", cmd->name, cmd->args, cmd->min, cmd->max);
}
void con_cmd_ccmd(ccmd_t *cmd, const char **argv, int argc) {
ccmd_t *ccmd;
char fmt[128];
if(argc) {
for(int z = 0; z < argc; z++) {
ccmd = con_get(argv[z]);
if(!ccmd) {
logce(STR_CCMD_UNKNOWN, argv[z]);
continue;
}
con_fmt_ccmd(ccmd, fmt);
}
}
else {
for(int z = 0; z < sys.n_ccmds; z++) {
ccmd = &sys.ccmds[z];
con_fmt_ccmd(ccmd, fmt);
}
logcu(STR_CMD_CCMDLIST, sys.n_ccmds);
}
}
void con_cmd_memdump(ccmd_t *cmd, const char **argv, int argc) {
logcu("base : %12.3f MB (%5.2f %%), 1 block (%5.2f %%)", ((float)SYS_BASE) / 1024.0f / 1024.0f, ((float)SYS_BASE) / ((float)sys.mem_alloc) * 100.0f, 100.0f / ((float)sys.mem_blocks));
for(int z = 0; z < MEM_CATS; z++) {
logcu("%-10s: %12.3f MB (%5.2f %%), %6lld block%c (%5.2f %%)", mem_types[z], ((float)sys.mem_pool_sizes[z]) / 1024.0f / 1024.0f, ((float)sys.mem_pool_sizes[z]) / ((float)sys.mem_alloc) * 100.0f,
sys.mem_pool_blocks[z], sys.mem_pool_blocks[z] == 1 ? ' ' : 's', ((float)sys.mem_pool_blocks[z]) / ((float)sys.mem_blocks) * 100.0f);
}
logcu("total : %12.3f MB (peak: %.3f MB), %lld blocks", ((float)sys.mem_alloc) / 1024.0f / 1024.0f, ((float)sys.mem_peak) / 1024.0f / 1024.0f, sys.mem_blocks);
}
byte plr_queue(const char *dmxname, const char *drumname, const char **files, int count);
void plr_end();
void con_cmd_play(ccmd_t *cmd, const char **argv, int argc) {
const char *bank = NULL;
const char *drum = NULL;
int id = snd.mid_bank;
if(argc) {
if(!strcmp(argv[0], "-b")) {
if(argc < 2) {
logce(STR_CMD_ARGREQ, "-b");
for(int z = 0; z < 32; z++) {
logce("#%02d -- %s", z, z < 31 ? snd_banknames[z] : "[custom]");
}
return;
}
if(!str_parse_enum(argv[1], snd_banknames, 31, &id)) {
bank = argv[1];
}
argv += 2;
argc -= 2;
}
else if(!strcmp(argv[0], "-B")) {
if(argc < 3) {
logce(STR_CMD_ARGREQS, "-B", 2);
return;
}
bank = argv[1];
drum = argv[2];
argv += 3;
argc -= 3;
}
if(!argc) {
logcu(STR_CMD_PLAY_BANKID, bank ? 31 : id);
return;
}
if(plr_queue(bank ? bank : snd_bankfiles[id], drum, argv, argc))
logcu(STR_CMD_PLAY_QUEUED, argc);
}
else {
if(snd.mid_queued) {
logcu(STR_CMD_PLAY_PLAYING, snd.mid_queued);
for(int z = 0; z < snd.mid_queued; z++) {
if(z != (snd.mid_queued - 1))
snd.mid_queue[z+1][-1] = 0;
logcu("%d. -- %s", z + 1, &(snd.mid_queue[z])[6]);
if(z != (snd.mid_queued - 1))
snd.mid_queue[z+1][-1] = '\n';
}
}
else {
logcu(STR_CMD_PLAY_STOPPED, NULL);
}
}
}
void con_cmd_stop(ccmd_t *cmd, const char **argv, int argc) {
if(snd.mid_queued)
logcu(STR_CMD_PLAY_ENDED, NULL);
else
logcu(STR_CMD_PLAY_STOPPED, NULL);
plr_end();
}
#define theme_add(str) \
style = (style_t*)tbl_push(&sys.themes);\
style->name = str;
#define theme_window(bdrtop, bdrbtm, top, btm, text) \
style->wbrdr_top = bdrtop;\
style->wbrdr_btm = bdrbtm;\
style->win_top = top;\
style->win_btm = btm;\
style->text_win = text;
#define theme_border(top, btm, size) \
style->brdr_top = top;\
style->brdr_btm = btm;\
style->border = size;
#define theme_background(top, btm) \
style->bg_top = top;\
style->bg_btm = btm;
#define theme_base(top, btm, text, label) \
style->fill_top = top;\
style->fill_btm = btm;\
style->text_base = text;\
style->text_label = label;
#define theme_field(top, btm, text) \
style->field_top = top;\
style->field_btm = btm;\
style->text_field = text;
#define theme_slider(handle) \
style->slider_width = handle;
#define theme_select(presstop, pressbtm, hovertop, hoverbtm, sel, cur) \
style->press_top = presstop;\
style->press_btm = pressbtm;\
style->hover_top = hovertop;\
style->hover_btm = hoverbtm;\
style->select = sel;\
style->cursor = cur;
void con_cmd_themedump(ccmd_t *cmd, const char **argv, int argc) {
logcu("theme_add(STR_THEME_%s);", argc ? argv[0] : "");
logcu("theme_window(0x%06x, 0x%06x, 0x%06x, 0x%06x, 0x%06x);", sys.style.wbrdr_top & 0xffffff, sys.style.wbrdr_btm & 0xffffff, sys.style.win_top & 0xffffff, sys.style.win_btm & 0xffffff, sys.style.text_win & 0xffffff);
logcu("theme_border(0x%06x, 0x%06x, %d);", sys.style.brdr_top & 0xffffff, sys.style.brdr_btm & 0xffffff, sys.style.border);
logcu("theme_background(0x%06x, 0x%06x);", sys.style.bg_top & 0xffffff, sys.style.bg_btm & 0xffffff);
logcu("theme_base(0x%06x, 0x%06x, 0x%06x, 0x%06x);", sys.style.fill_top & 0xffffff, sys.style.fill_btm & 0xffffff, sys.style.text_base & 0xffffff, sys.style.text_label & 0xffffff);
logcu("theme_field(0x%06x, 0x%06x, 0x%06x);", sys.style.field_top & 0xffffff, sys.style.field_btm & 0xffffff, sys.style.text_field & 0xffffff);
logcu("theme_slider(%d);", sys.style.slider_width);
logcu("theme_select(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x);", sys.style.press_top, sys.style.press_btm, sys.style.hover_top, sys.style.hover_btm, sys.style.select, sys.style.cursor);
}
void con_reg() {
con_add("cvar", "[cvar ...]", con_cmd_cvar, 0, CCMD_UNLIMITED);
con_add("ccmd", "[ccmd ...]", con_cmd_ccmd, 0, CCMD_UNLIMITED);
con_add("memdump", "", con_cmd_memdump, 0, 0);
con_add("play", "[-b <bank|id> | -B <bank> <drum>] [midi ...]", con_cmd_play, 0, CCMD_UNLIMITED);
con_add("stop", "", con_cmd_stop, 0, 0);
con_add("themedump", "[id]", con_cmd_themedump, 0, 1);
}
void con_init() {
ccmd_t *cmd;
con_reg();
smap_init(&sys.ccmd_map, 1, MEM_SYSTEM);
for(int z = 0; z < sys.n_ccmds; z++) {
cmd = &sys.ccmds[z];
smap_put(&sys.ccmd_map, cmd->name, cmd);
}
}
void con_end() {
smap_clear(&sys.ccmd_map);
}
void con_resize(int size) {
for(int z = sys.hud_size; z < size; z++) {
sys.hud_msgs[z].message = NULL;
}
sys.hud_size = size;
if(sys.hud_pos >= sys.hud_size)
sys.hud_pos = 0;
}
gui_t *gui_get(window_t *win, int id);
void gui_update_text(gui_t *elem);
void gui_text_update_cur(gui_t *elem, int offset, byte shift);
void log_sys(const char *msg, int length, int offset) {
char c;
if(sys.con_timestamps ^ 1) {
length -= offset;
msg += offset;
offset = 0;
}
if((sys.log_len + length + 2) > CON_BUF) {
offset = (length + 2) > 1024 ? (length + 2) : 1024;
while(c = sys.con_buf[offset++]) {
if(c == '\n')
break;
}
offset -= c ? 0 : 1;
sys.log_len -= offset;
memmove(sys.con_buf, &sys.con_buf[offset], sys.log_len);
}
sys.con_buf[sys.log_len] = '\n';
sys.log_len += 1;
memcpy(&sys.con_buf[sys.log_len], msg, length);
sys.log_len += length;
sys.con_buf[sys.log_len] = 0;
if(sys.console && sys.console->open) {
gui_t *elem = gui_get(sys.console, 5);
if(sys.con_autoscroll)
elem->sel_start = elem->sel_end = elem->sel_drag = sys.log_len;
gui_update_text(elem);
if(elem->sel_start >= 0)
gui_text_update_cur(elem, elem->sel_start, 1);
}
}
void log_hud(window_t *win, const char *fmt, ...) {
conmsg_t *con;
va_list ap;
va_start(ap, fmt);
int length = vsnprintf(sys.log_buf, LOG_BUF, fmt, ap);
if((sys.hud_len + length + 2) > HUD_BUF) {
char c;
int offset = (length + 2) > 1024 ? (length + 2) : 1024;
while(c = sys.hud_buf[offset++]) {
if(c == '\n')
break;
}
offset -= c ? 0 : 1;
sys.hud_len -= offset;
memmove(sys.hud_buf, &sys.hud_buf[offset], sys.hud_len);
for(int z = 0; z < sys.hud_size; z++) {
con = &sys.hud_msgs[z];
if(con->message) {
if((con->offset -= offset) < 0)
con->message = NULL;
else
con->message -= offset;
}
}
}
sys.hud_buf[sys.hud_len] = '\n';
sys.hud_len += 1;
memcpy(&sys.hud_buf[sys.hud_len], sys.log_buf, length);
if(sys.hud_size) {
con = &sys.hud_msgs[sys.hud_pos];
con->message = &sys.hud_buf[sys.hud_len];
con->offset = sys.hud_len;
con->length = length;
con->time = sys.tmr_current;
con->window = win;
if(++(sys.hud_pos) >= sys.hud_size)
sys.hud_pos = 0;
}
sys.hud_len += length;
sys.hud_buf[sys.hud_len] = 0;
va_end(ap);
}