summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--default.cfg7
-rw-r--r--menu.c11
-rw-r--r--util.c86
-rw-r--r--util.h2
4 files changed, 99 insertions, 7 deletions
diff --git a/default.cfg b/default.cfg
index 0ff4e37..424a93d 100644
--- a/default.cfg
+++ b/default.cfg
@@ -195,9 +195,12 @@ clocks {
}
ui {
+ #specifies the ROM that implements the Menu UI
rom menu.bin
- #initial_path defaults to your home/user profile directory if not specified
- #screenshot_path behaves the same way
+ #starting path for ROM browsing, accepts special variables $HOME, $EXEDIR
+ #and variables defined in the OS environment
+ initial_path $HOME
+ #screenshot_path defaults to the user's home/profile directory if not specified
#see strftime for the format specifiers valid in screenshot_template
screenshot_template blastem_%c.ppm
}
diff --git a/menu.c b/menu.c
index 44c33ee..277697e 100644
--- a/menu.c
+++ b/menu.c
@@ -167,15 +167,16 @@ void * menu_write_w(uint32_t address, void * context, uint16_t value)
if (!menu) {
gen->extra = menu = calloc(1, sizeof(menu_context));
menu->curpath = tern_find_path(config, "ui\0initial_path\0").ptrval;
- if (menu->curpath) {
- menu->curpath = strdup(menu->curpath);
- } else {
+ if (!menu->curpath){
#ifdef __ANDROID__
- menu->curpath = strdup(get_external_storage_path());
+ menu->curpath = get_external_storage_path();
#else
- menu->curpath = strdup(get_home_dir());
+ menu->curpath = "$HOME";
#endif
}
+ tern_node *vars = tern_insert_ptr(NULL, "HOME", get_home_dir());
+ vars = tern_insert_ptr(vars, "EXEDIR", get_exe_dir());
+ menu->curpath = replace_vars(menu->curpath, vars, 1);
}
if (menu->state) {
uint32_t dst = menu->latch << 16 | value;
diff --git a/util.c b/util.c
index a5aae2e..c6aa91e 100644
--- a/util.c
+++ b/util.c
@@ -57,6 +57,92 @@ char * alloc_concat_m(int num_parts, char const ** parts)
return ret;
}
+typedef struct {
+ uint32_t start;
+ uint32_t end;
+ char *value;
+} var_pos;
+
+char *replace_vars(char *base, tern_node *vars, uint8_t allow_env)
+{
+ uint32_t num_vars = 0;
+ for (char *cur = base; *cur; ++cur)
+ {
+ //TODO: Support escaping $ and allow brace syntax
+ if (*cur == '$') {
+ num_vars++;
+ }
+ }
+ var_pos *positions = calloc(num_vars, sizeof(var_pos));
+ num_vars = 0;
+ uint8_t in_var = 0;
+ uint32_t max_var_len = 0;
+ for (char *cur = base; *cur; ++cur)
+ {
+ if (in_var) {
+ if (!(*cur == '_' || isalnum(*cur))) {
+ positions[num_vars].end = cur-base;
+ if (positions[num_vars].end - positions[num_vars].start > max_var_len) {
+ max_var_len = positions[num_vars].end - positions[num_vars].start;
+ }
+ num_vars++;
+ in_var = 0;
+ }
+ } else if (*cur == '$') {
+ positions[num_vars].start = cur-base+1;
+ in_var = 1;
+ }
+ }
+ if (in_var) {
+ positions[num_vars].end = strlen(base);
+ if (positions[num_vars].end - positions[num_vars].start > max_var_len) {
+ max_var_len = positions[num_vars].end - positions[num_vars].start;
+ }
+ num_vars++;
+ }
+ char *varname = malloc(max_var_len+1);
+ uint32_t total_len = 0;
+ uint32_t cur = 0;
+ for (uint32_t i = 0; i < num_vars; i++)
+ {
+ total_len += (positions[i].start - 1) - cur;
+ cur = positions[i].start;
+ memcpy(varname, base + positions[i].start, positions[i].end-positions[i].start);
+ varname[positions[i].end-positions[i].start] = 0;
+ positions[i].value = tern_find_ptr(vars, varname);
+ if (!positions[i].value && allow_env) {
+ positions[i].value = getenv(varname);
+ }
+ if (positions[i].value) {
+ total_len += strlen(positions[i].value);
+ }
+ }
+ total_len += strlen(base+cur);
+ free(varname);
+ char *output = malloc(total_len+1);
+ cur = 0;
+ char *curout = output;
+ for (uint32_t i = 0; i < num_vars; i++)
+ {
+ if (positions[i].start-1 > cur) {
+ memcpy(curout, base + cur, (positions[i].start-1) - cur);
+ curout += (positions[i].start-1) - cur;
+ }
+ if (positions[i].value) {
+ strcpy(curout, positions[i].value);
+ curout += strlen(curout);
+ }
+ cur = positions[i].end;
+ };
+ if (base[cur]) {
+ strcpy(curout, base+cur);
+ } else {
+ *curout = 0;
+ }
+ free(positions);
+ return output;
+}
+
void byteswap_rom(int filesize, uint16_t *cart)
{
for(uint16_t *cur = cart; cur - cart < filesize/2; ++cur)
diff --git a/util.h b/util.h
index c29d040..fc3762e 100644
--- a/util.h
+++ b/util.h
@@ -21,6 +21,8 @@ typedef struct {
char * alloc_concat(char const * first, char const * second);
//Allocates a new string containing the concatenation of the strings pointed to by parts
char * alloc_concat_m(int num_parts, char const ** parts);
+//Returns a newly allocated string in which all variables in based are replaced with values from vars or the environment
+char *replace_vars(char *base, tern_node *vars, uint8_t allow_env);
//Byteswaps a ROM image in memory
void byteswap_rom(int filesize, uint16_t *cart);
//Returns the size of a file using fseek and ftell