From 3e8a62c5c634a74a7a0af8ba78befc8c0a1ff585 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Nov 2025 01:32:58 +0100 Subject: [PATCH] Implemented the infrastructure for the non-ROM assets to go with the new repository. --- src/86box.c | 57 +++++++++++++++-- src/include/86box/plat.h | 1 + src/include/86box/rom.h | 9 +++ src/mem/rom.c | 132 +++++++++++++++++++++++++++++++++++++++ src/qt/qt_platform.cpp | 24 +++++++ 5 files changed, 219 insertions(+), 4 deletions(-) diff --git a/src/86box.c b/src/86box.c index efa9e84bf..c425d1f50 100644 --- a/src/86box.c +++ b/src/86box.c @@ -143,10 +143,12 @@ int confirm_exit_cmdl = 1; /* (O) do not ask for confirmation on quit if set to uint64_t unique_id = 0; uint64_t source_hwnd = 0; #endif -char rom_path[1024] = { '\0' }; /* (O) full path to ROMs */ -rom_path_t rom_paths = { "", NULL }; /* (O) full paths to ROMs */ -char log_path[1024] = { '\0' }; /* (O) full path of logfile */ -char vm_name[1024] = { '\0' }; /* (O) display name of the VM */ +char rom_path[1024] = { '\0' }; /* (O) full path to ROMs */ +rom_path_t rom_paths = { "", NULL }; /* (O) full paths to ROMs */ +char asset_path[1024] = { '\0' }; /* (O) full path to assets */ +rom_path_t asset_paths = { "", NULL }; /* (O) full paths to assets */ +char log_path[1024] = { '\0' }; /* (O) full path of logfile */ +char vm_name[1024] = { '\0' }; /* (O) display name of the VM */ int do_nothing = 0; int dump_missing = 0; int clear_cmos = 0; @@ -662,6 +664,7 @@ pc_show_usage(char *s) "\n%sUsage: 86box [options] [cfg-file]\n\n" "Valid options are:\n\n" "-? or --help\t\t\t- show this information\n" + "-A or --assetpath path\t\t- set 'path' to be asset path\n" #ifdef SHOW_EXTRA_PARAMS "-C or --config path\t\t- set 'path' to be config file\n" #endif @@ -732,6 +735,7 @@ pc_init(int argc, char *argv[]) { char *ppath = NULL; char *rpath = NULL; + char *apath = NULL; char *cfg = NULL; char *global = NULL; char *p; @@ -798,6 +802,7 @@ pc_init(int argc, char *argv[]) */ plat_getcwd(usr_path, sizeof(usr_path) - 1); plat_getcwd(rom_path, sizeof(rom_path) - 1); + plat_getcwd(asset_path, sizeof(asset_path) - 1); for (c = 1; c < argc; c++) { if (argv[c][0] != '-') @@ -851,6 +856,12 @@ usage: rpath = argv[++c]; rom_add_path(rpath); + } else if (!strcasecmp(argv[c], "--assetpath") || !strcasecmp(argv[c], "-A")) { + if ((c + 1) == argc) + goto usage; + + apath = argv[++c]; + asset_add_path(apath); } else if (!strcasecmp(argv[c], "--config") || !strcasecmp(argv[c], "-C")) { if ((c + 1) == argc || plat_dir_check(argv[c + 1])) goto usage; @@ -974,6 +985,7 @@ usage: path_slash(usr_path); path_slash(rom_path); + path_slash(asset_path); /* * If the user provided a path for files, use that @@ -1013,6 +1025,7 @@ usage: rom_add_path(temp); plat_init_rom_paths(); + plat_init_asset_paths(); /* * If the user provided a path for ROMs, use that @@ -1044,6 +1057,36 @@ usage: } else rom_path[0] = '\0'; + /* + * If the user provided a path for ROMs, use that + * instead of the current working directory. We do + * make sure that if that was a relative path, we + * make it absolute. + */ + if (apath != NULL) { + if (!path_abs(apath)) { + /* + * This looks like a relative path. + * + * Add it to the current working directory + * to convert it (back) to an absolute path. + */ + strcat(asset_path, apath); + } else { + /* + * The user-provided path seems like an + * absolute path, so just use that. + */ + strcpy(asset_path, apath); + } + + /* If the specified path does not yet exist, + create it. */ + if (!plat_dir_check(asset_path)) + plat_dir_create(asset_path); + } else + asset_path[0] = '\0'; + /* Grab the name of the configuration file. */ if (cfg == NULL) cfg = CONFIG_FILE; @@ -1081,6 +1124,8 @@ usage: path_slash(usr_path); if (rom_path[0] != '\0') path_slash(rom_path); + if (asset_path[0] != '\0') + path_slash(asset_path); /* At this point, we can safely create the full path name. */ path_append_filename(cfg_path, usr_path, p); @@ -1182,6 +1227,10 @@ usage: pclog("# ROM path: %s\n", rom_path->path); } + for (rom_path_t *asset_path = &asset_paths; asset_path != NULL; asset_path = asset_path->next) { + pclog("# Asset path: %s\n", asset_path->path); + } + /* * We are about to read the configuration file, which MAY * put data into global variables (the hard- and floppy diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 7835fe3a2..dcf7e4d53 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -147,6 +147,7 @@ extern void plat_get_global_data_dir(char *outbuf, size_t len); extern void plat_get_temp_dir(char *outbuf, uint8_t len); extern void plat_get_vmm_dir(char *outbuf, size_t len); extern void plat_init_rom_paths(void); +extern void plat_init_asset_paths(void); extern int plat_dir_check(char *path); extern int plat_file_check(const char *path); extern int plat_dir_create(char *path); diff --git a/src/include/86box/rom.h b/src/include/86box/rom.h index 6865277c6..0caee9e1f 100644 --- a/src/include/86box/rom.h +++ b/src/include/86box/rom.h @@ -42,6 +42,9 @@ typedef struct rom_path_t { } rom_path_t; extern rom_path_t rom_paths; +extern rom_path_t asset_paths; + +extern void asset_add_path(const char *path); extern void rom_add_path(const char *path); @@ -53,8 +56,14 @@ extern void rom_write(uint32_t addr, uint8_t val, void *priv); extern void rom_writew(uint32_t addr, uint16_t val, void *priv); extern void rom_writel(uint32_t addr, uint32_t val, void *priv); +extern void asset_get_full_path(char *dest, const char *fn); + extern void rom_get_full_path(char *dest, const char *fn); +extern FILE *asset_fopen(const char *fn, char *mode); +extern int asset_getfile(const char *fn, char *s, int size); +extern int asset_present(const char *fn); + extern FILE *rom_fopen(const char *fn, char *mode); extern int rom_getfile(const char *fn, char *s, int size); extern int rom_present(const char *fn); diff --git a/src/mem/rom.c b/src/mem/rom.c index cee00cb0f..6943b53d3 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -85,6 +85,36 @@ rom_add_path(const char *path) path_slash(rom_path->path); } +void +asset_add_path(const char *path) +{ + char cwd[1024] = { 0 }; + + rom_path_t *asset_path = &asset_paths; + + if (asset_paths.path[0] != '\0') { + // Iterate to the end of the list. + while (asset_path->next != NULL) { + asset_path = asset_path->next; + } + + // Allocate the new entry. + asset_path = asset_path->next = calloc(1, sizeof(rom_path_t)); + } + + // Save the path, turning it into absolute if needed. + if (!path_abs((char *) path)) { + plat_getcwd(cwd, sizeof(cwd)); + path_slash(cwd); + snprintf(asset_path->path, sizeof(asset_path->path), "%s%s", cwd, path); + } else { + snprintf(asset_path->path, sizeof(asset_path->path), "%s", path); + } + + // Ensure the path ends with a separator. + path_slash(asset_path->path); +} + static int rom_check(const char *fn) { @@ -129,6 +159,31 @@ rom_get_full_path(char *dest, const char *fn) } } +void +asset_get_full_path(char *dest, const char *fn) +{ + char temp[1024] = { 0 }; + + dest[0] = 0x00; + + if (!strncmp(fn, "assets/", 5)) { + /* Relative path */ + for (rom_path_t *asset_path = &asset_paths; asset_path != NULL; asset_path = asset_path->next) { + path_append_filename(temp, asset_path->path, fn + 5); + + if (rom_check(temp)) { + strcpy(dest, temp); + return; + } + } + + return; + } else { + /* Absolute path */ + strcpy(dest, fn); + } +} + FILE * rom_fopen(const char *fn, char *mode) { @@ -154,6 +209,31 @@ rom_fopen(const char *fn, char *mode) } } +FILE * +asset_fopen(const char *fn, char *mode) +{ + char temp[1024]; + FILE *fp = NULL; + + if ((fn == NULL) || (mode == NULL)) + return NULL; + + if (!strncmp(fn, "assets/", 5)) { + /* Relative path */ + for (rom_path_t *asset_path = &asset_paths; asset_path != NULL; asset_path = asset_path->next) { + path_append_filename(temp, asset_path->path, fn + 5); + + if ((fp = plat_fopen(temp, mode)) != NULL) + return fp; + } + + return fp; + } else { + /* Absolute path */ + return plat_fopen(fn, mode); + } +} + int rom_getfile(const char *fn, char *s, int size) { @@ -182,6 +262,34 @@ rom_getfile(const char *fn, char *s, int size) } } +int +asset_getfile(const char *fn, char *s, int size) +{ + char temp[1024]; + + if (!strncmp(fn, "assets/", 5)) { + /* Relative path */ + for (rom_path_t *asset_path = &asset_paths; asset_path != NULL; asset_path = asset_path->next) { + path_append_filename(temp, asset_path->path, fn + 5); + + if (plat_file_check(temp)) { + strncpy(s, temp, size); + return 1; + } + } + + return 0; + } else { + /* Absolute path */ + if (plat_file_check(fn)) { + strncpy(s, fn, size); + return 1; + } + + return 0; + } +} + int rom_present(const char *fn) { @@ -206,6 +314,30 @@ rom_present(const char *fn) } } +int +asset_present(const char *fn) +{ + char temp[1024]; + + if (fn == NULL) + return 0; + + if (!strncmp(fn, "assets/", 5)) { + /* Relative path */ + for (rom_path_t *asset_path = &asset_paths; asset_path != NULL; asset_path = asset_path->next) { + path_append_filename(temp, asset_path->path, fn + 5); + + if (plat_file_check(temp)) + return 1; + } + + return 0; + } else { + /* Absolute path */ + return plat_file_check(fn); + } +} + uint8_t rom_read(uint32_t addr, void *priv) { diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 31eb09e56..d4aa7ad78 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -836,6 +836,30 @@ plat_init_rom_paths(void) } } +void +plat_init_asset_paths(void) +{ + auto paths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); + +#ifdef _WIN32 + // HACK: The standard locations returned for GenericDataLocation include + // the EXE path and a `data` directory within it as the last two entries. + + // Remove the entries as we don't need them. + paths.removeLast(); + paths.removeLast(); +#endif + + for (auto &path : paths) { +#ifdef __APPLE__ + rom_add_path(QDir(path).filePath("net.86Box.86Box/asset").toUtf8().constData()); + rom_add_path(QDir(path).filePath("86Box/asset").toUtf8().constData()); +#else + rom_add_path(QDir(path).filePath("86Box/asset").toUtf8().constData()); +#endif + } +} + void plat_get_cpu_string(char *outbuf, uint8_t len) {