#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 | -B ] [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); }