mirror of
https://github.com/ARMSX2/ARMSX1.git
synced 2026-08-24 16:53:35 -07:00
803 lines
22 KiB
C
803 lines
22 KiB
C
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <limits.h>
|
|
#include <ctype.h>
|
|
#include <dirent.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <errno.h>
|
|
#ifdef _WIN32
|
|
#include <direct.h>
|
|
#endif
|
|
|
|
#include "config.h"
|
|
#include "common.h"
|
|
|
|
#include "../psx/log.h"
|
|
#include "SDL.h"
|
|
|
|
static char* g_pref_path = NULL;
|
|
static char* g_settings_path = NULL;
|
|
static char* g_bios_path = NULL;
|
|
|
|
static const char* g_version_text =
|
|
#ifdef _WIN32
|
|
"armsx.exe (" STR(OS_INFO) ") " STR(REP_VERSION) "-" STR(REP_COMMIT_HASH) "\n"
|
|
#elif __linux__
|
|
"armsx (" STR(OS_INFO) ") " STR(REP_VERSION) "-" STR(REP_COMMIT_HASH) "\n"
|
|
#else
|
|
"armsx (" STR(OS_INFO) ") " STR(REP_VERSION) "-" STR(REP_COMMIT_HASH) "\n"
|
|
#endif
|
|
"\nARMSX - A simple, fast and portable Sony PlayStation emulator.\n\n"
|
|
"ARMSX modifications Copyright (C) 2026 Moon. All rights reserved.\n"
|
|
"Original psxe Copyright (C) 2023 Allkern (Lisandro Alarcon).\n"
|
|
"Moon-owned material is proprietary and requires Moon's prior written\n"
|
|
"permission. Other components retain their existing licenses. See LICENSE.\n"
|
|
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n"
|
|
"PARTICULAR PURPOSE.\n";
|
|
|
|
static const char g_default_settings[] =
|
|
"# Settings file generated by ARMSX\n"
|
|
"\n"
|
|
"# Don't change please, reserved for future use\n"
|
|
"psxe_version = \"" STR(REP_VERSION) "\"\n"
|
|
"\n"
|
|
"# BIOS-related settings:\n"
|
|
"[bios]\n"
|
|
" search_path = \"bios\"\n"
|
|
" preferred_model = \"SCPH-1001\"\n"
|
|
" override_file = \"\"\n"
|
|
"\n"
|
|
"# Console settings\n"
|
|
"[console]\n"
|
|
" region = \"auto\"\n"
|
|
"\n"
|
|
"# CPU settings\n"
|
|
"[cpu]\n"
|
|
" execution_mode = \"cached\" # cached | interpreter\n"
|
|
"\n"
|
|
"# Runtime settings\n"
|
|
"[runtime]\n"
|
|
" display_scale = 3\n"
|
|
" logging_enabled = false\n"
|
|
" log_level = 2\n"
|
|
" quiet = true\n"
|
|
"\n"
|
|
"# Launch path defaults\n"
|
|
"[paths]\n"
|
|
" expansion_rom = \"\"\n"
|
|
" default_psx_exe = \"\"\n"
|
|
"\n"
|
|
"# Video settings\n"
|
|
"[video]\n"
|
|
" vsync = "
|
|
#if defined(UWP_TARGET)
|
|
"false"
|
|
#else
|
|
"true"
|
|
#endif
|
|
"\n"
|
|
#ifdef USE_HARDWARE
|
|
" gpu_backend = \"software\" # software | sdl-accelerated\n"
|
|
#endif
|
|
" texture_scale_mode = false\n"
|
|
" presentation_upscale = 1 # 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8\n"
|
|
" debug_panel = false\n"
|
|
" stretch_mode = false\n"
|
|
" display_aspect = \"classic\" # classic | square | wide16x9\n"
|
|
" wide_upscale = \"480p\" # 480p | 720p | 1080p | 1440p | 2160p\n"
|
|
"\n"
|
|
"[input]\n"
|
|
#if defined(__ANDROID__) || defined(IOS_TARGET)
|
|
" mobile_controls = true\n"
|
|
#else
|
|
" mobile_controls = false\n"
|
|
#endif
|
|
"\n"
|
|
"# Library folders used by ARMSX\n"
|
|
"[library]\n"
|
|
" folders = []\n"
|
|
" recursive_folders = []\n";
|
|
|
|
static const char* g_models_text =
|
|
"Available console models:\n"
|
|
"\"scph1000\" (SCPH-1000) [NTSC-J]\n"
|
|
"\"scph1001\" (SCPH-1001) [NTSC-U/C]\n"
|
|
"\"scph1002\" (SCPH-1002) [PAL]\n"
|
|
"\"scph3000\" (SCPH-3000) [NTSC-J]\n"
|
|
"\"scph3500\" (SCPH-3500) [NTSC-J]\n"
|
|
"\"scph5000\" (SCPH-5000) [NTSC-U/C]\n"
|
|
"\"scph5501\" (SCPH-5501) [NTSC-U/C]\n"
|
|
"\"scph5500\" (SCPH-5500) [NTSC-J]\n"
|
|
"\"scph5502\" (SCPH-5502) [PAL]\n"
|
|
"\"scph5552\" (SCPH-5552) [PAL]\n"
|
|
"\"scph7000\" (SCPH-7000) [NTSC-J]\n"
|
|
"\"scph7001\" (SCPH-7001) [NTSC-U/C]\n"
|
|
"\"scph7002\" (SCPH-7002) [PAL]\n"
|
|
"\"scph7003\" (SCPH-7003) [NTSC-J]\n"
|
|
"\"scph7501\" (SCPH-7501) [NTSC]\n"
|
|
"\"scph7502\" (SCPH-7502) [PAL]\n"
|
|
"\"scph9002\" (SCPH-9002) [PAL]\n"
|
|
"\"scph100\" (SCPH-100) [NTSC-J]\n"
|
|
"\"scph101\" (SCPH-101) [NTSC-U/C]\n"
|
|
"\"scph102a\" (SCPH-102A) [PAL]\n"
|
|
"\"scph102b\" (SCPH-102B) [PAL]\n"
|
|
"\"scph102c\" (SCPH-102C) [?]\n";
|
|
|
|
static const char* g_regions_text =
|
|
"Available region options: \"ntsc\", \"pal\", \"auto\"\n";
|
|
|
|
static const char* g_desc_text =
|
|
"\nPlease report any bugs to <https://github.com/allkern/psxe/issues>\n";
|
|
|
|
static int psxe_file_exists(const char* path) {
|
|
if (!path || !path[0])
|
|
return 0;
|
|
|
|
FILE* file = fopen(path, "rb");
|
|
|
|
if (!file)
|
|
return 0;
|
|
|
|
fclose(file);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int psxe_is_path_separator(char c) {
|
|
return (c == '/') || (c == '\\');
|
|
}
|
|
|
|
static void psxe_normalize_model_name(const char* src, char* dst, size_t dst_size) {
|
|
size_t out = 0;
|
|
|
|
if (!dst_size)
|
|
return;
|
|
|
|
if (!src) {
|
|
dst[0] = '\0';
|
|
return;
|
|
}
|
|
|
|
while (*src && (out + 1) < dst_size) {
|
|
unsigned char ch = (unsigned char)*src++;
|
|
|
|
if (!isalnum(ch))
|
|
continue;
|
|
|
|
dst[out++] = (char)tolower(ch);
|
|
}
|
|
|
|
dst[out] = '\0';
|
|
}
|
|
|
|
static const char* psxe_basename_no_ext(const char* path) {
|
|
const char* base = path ? path : "";
|
|
const char* scan = base;
|
|
|
|
while (*scan) {
|
|
if (psxe_is_path_separator(*scan))
|
|
base = scan + 1;
|
|
scan++;
|
|
}
|
|
|
|
return base;
|
|
}
|
|
|
|
static int psxe_extension_matches(const char* ext, const char* expected) {
|
|
if (!ext || !expected)
|
|
return 0;
|
|
|
|
return !strcasecmp(ext, expected);
|
|
}
|
|
|
|
static char* psxe_join_path(const char* dir, const char* leaf) {
|
|
size_t dir_len = dir ? strlen(dir) : 0;
|
|
size_t leaf_len = leaf ? strlen(leaf) : 0;
|
|
int needs_sep = dir_len && !psxe_is_path_separator(dir[dir_len - 1]);
|
|
char* path = (char*)malloc(dir_len + leaf_len + (needs_sep ? 2 : 1));
|
|
|
|
if (!path)
|
|
return NULL;
|
|
|
|
if (dir_len)
|
|
memcpy(path, dir, dir_len);
|
|
|
|
if (needs_sep)
|
|
path[dir_len++] = '/';
|
|
|
|
if (leaf_len)
|
|
memcpy(path + dir_len, leaf, leaf_len);
|
|
|
|
path[dir_len + leaf_len] = '\0';
|
|
|
|
return path;
|
|
}
|
|
|
|
static char* psxe_find_bios_in_dir(const char* dir_path, const char* model) {
|
|
char normalized_model[128];
|
|
char normalized_name[128];
|
|
char* fallback = NULL;
|
|
DIR* dir;
|
|
|
|
if (!dir_path || !dir_path[0])
|
|
return NULL;
|
|
|
|
dir = opendir(dir_path);
|
|
|
|
if (!dir)
|
|
return NULL;
|
|
|
|
psxe_normalize_model_name(model, normalized_model, sizeof(normalized_model));
|
|
|
|
struct dirent* entry;
|
|
|
|
while ((entry = readdir(dir)) != NULL) {
|
|
const char* name = entry->d_name;
|
|
const char* ext;
|
|
char* full_path;
|
|
|
|
if (!name || !name[0] || !strcmp(name, ".") || !strcmp(name, ".."))
|
|
continue;
|
|
|
|
ext = strrchr(name, '.');
|
|
|
|
if (!ext)
|
|
continue;
|
|
|
|
if (!psxe_extension_matches(ext, ".bin") && !psxe_extension_matches(ext, ".rom"))
|
|
continue;
|
|
|
|
full_path = psxe_join_path(dir_path, name);
|
|
|
|
if (!full_path)
|
|
continue;
|
|
|
|
if (!psxe_file_exists(full_path)) {
|
|
free(full_path);
|
|
continue;
|
|
}
|
|
|
|
if (!fallback && !strcasecmp(name, "bios.bin")) {
|
|
fallback = full_path;
|
|
continue;
|
|
}
|
|
|
|
psxe_normalize_model_name(psxe_basename_no_ext(name), normalized_name, sizeof(normalized_name));
|
|
|
|
if (normalized_model[0] && !strcmp(normalized_model, normalized_name)) {
|
|
if (fallback)
|
|
free(fallback);
|
|
|
|
closedir(dir);
|
|
return full_path;
|
|
}
|
|
|
|
free(full_path);
|
|
}
|
|
|
|
closedir(dir);
|
|
|
|
return fallback;
|
|
}
|
|
|
|
static void psxe_ensure_dir(const char* dir_path) {
|
|
if (!dir_path || !dir_path[0])
|
|
return;
|
|
|
|
struct stat st;
|
|
if (stat(dir_path, &st) == 0)
|
|
return;
|
|
|
|
#ifdef _WIN32
|
|
_mkdir(dir_path);
|
|
#else
|
|
mkdir(dir_path, 0755);
|
|
#endif
|
|
}
|
|
|
|
static void psxe_ensure_parent_dir(const char* path) {
|
|
if (!path)
|
|
return;
|
|
|
|
#ifdef PSVITA_TARGET
|
|
const size_t path_len = strlen(path);
|
|
if (path_len == 0)
|
|
return;
|
|
|
|
char* tmp = malloc(path_len + 1);
|
|
if (!tmp)
|
|
return;
|
|
|
|
memcpy(tmp, path, path_len + 1);
|
|
#else
|
|
char tmp[PATH_MAX];
|
|
strncpy(tmp, path, sizeof(tmp) - 1);
|
|
tmp[sizeof(tmp) - 1] = '\0';
|
|
#endif
|
|
|
|
char* slash = strrchr(tmp, '/');
|
|
#ifdef _WIN32
|
|
char* bslash = strrchr(tmp, '\\');
|
|
if (!slash || (bslash && bslash > slash))
|
|
slash = bslash;
|
|
#endif
|
|
|
|
if (slash && slash != tmp) {
|
|
*slash = '\0';
|
|
psxe_ensure_dir(tmp);
|
|
}
|
|
|
|
#ifdef PSVITA_TARGET
|
|
free(tmp);
|
|
#endif
|
|
}
|
|
|
|
static const char* psxe_pref_path(void) {
|
|
if (g_pref_path)
|
|
return g_pref_path;
|
|
|
|
#ifdef PSVITA_TARGET
|
|
const char* pref_base = "ux0:data/armsx/";
|
|
size_t len = strlen(pref_base) + 1;
|
|
g_pref_path = (char*)malloc(len);
|
|
if (g_pref_path)
|
|
memcpy(g_pref_path, pref_base, len);
|
|
#else
|
|
char* pref_base = SDL_GetPrefPath("nanodata", "armsx");
|
|
|
|
if (pref_base) {
|
|
size_t len = strlen(pref_base) + 1;
|
|
g_pref_path = (char*)malloc(len);
|
|
|
|
if (g_pref_path)
|
|
memcpy(g_pref_path, pref_base, len);
|
|
|
|
SDL_free(pref_base);
|
|
}
|
|
#endif
|
|
|
|
return g_pref_path;
|
|
}
|
|
|
|
static const char* psxe_prefixed_path(const char* leaf, char** cache) {
|
|
if (!leaf)
|
|
return NULL;
|
|
|
|
const char* base = psxe_pref_path();
|
|
|
|
if (base && cache && !*cache) {
|
|
size_t len = strlen(base) + strlen(leaf) + 1;
|
|
*cache = (char*)malloc(len);
|
|
|
|
if (*cache)
|
|
snprintf(*cache, len, "%s%s", base, leaf);
|
|
}
|
|
|
|
if (cache && *cache)
|
|
return *cache;
|
|
|
|
return leaf;
|
|
}
|
|
|
|
psxe_config_t* psxe_cfg_create(void) {
|
|
return (psxe_config_t*)malloc(sizeof(psxe_config_t));
|
|
}
|
|
|
|
void psxe_cfg_init(psxe_config_t* cfg) {
|
|
memset(cfg, 0, sizeof(psxe_config_t));
|
|
}
|
|
|
|
void psxe_cfg_destroy(psxe_config_t* cfg) {
|
|
free(cfg);
|
|
}
|
|
|
|
void psxe_cfg_load_defaults(psxe_config_t* cfg) {
|
|
cfg->bios = "bios.bin";
|
|
cfg->bios_search = "bios";
|
|
cfg->exe = NULL;
|
|
cfg->help_model = 0;
|
|
cfg->help_region = 0;
|
|
cfg->model = "scph1001";
|
|
cfg->cpu_engine = 1;
|
|
cfg->scale = 3;
|
|
cfg->psxe_version = STR(REP_VERSION);
|
|
cfg->region = "ntsc";
|
|
cfg->settings_path = NULL;
|
|
cfg->use_args = 0;
|
|
cfg->version = 0;
|
|
cfg->log_level = LOG_INFO;
|
|
cfg->quiet = 1;
|
|
cfg->cd_path = NULL;
|
|
cfg->exp_path = NULL;
|
|
#if defined(UWP_TARGET)
|
|
cfg->vsync_enabled = 0;
|
|
#else
|
|
cfg->vsync_enabled = 1;
|
|
#endif
|
|
#ifdef USE_HARDWARE
|
|
cfg->gpu_backend = 0;
|
|
#endif
|
|
cfg->texture_scale_mode = 0;
|
|
cfg->debug_panel = 0;
|
|
cfg->stretch_mode = 0;
|
|
cfg->display_aspect = 0;
|
|
cfg->upscale_height = 480;
|
|
}
|
|
|
|
void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) {
|
|
log_set_level(LOG_INFO);
|
|
|
|
// macOS .app bundles can inject a "-psn_*" argument; drop it before parsing
|
|
const char** argv_filtered = (const char**)malloc(sizeof(char*) * argc);
|
|
int argc_filtered = 0;
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
if (strncmp(argv[i], "-psn_", 5) == 0)
|
|
continue;
|
|
|
|
argv_filtered[argc_filtered++] = argv[i];
|
|
}
|
|
|
|
int use_args = 0;
|
|
int version = 0;
|
|
int help_model = 0;
|
|
int help_region = 0;
|
|
int log_level = 0;
|
|
int quiet = cfg->quiet;
|
|
int console_source = 0;
|
|
int cpu_engine = cfg->cpu_engine;
|
|
int scale = 0;
|
|
int vsync_enabled = cfg->vsync_enabled;
|
|
#ifdef USE_HARDWARE
|
|
int gpu_backend = cfg->gpu_backend;
|
|
#endif
|
|
int texture_scale_mode = 0;
|
|
int debug_panel = 0;
|
|
int stretch_mode = 0;
|
|
int display_aspect = 0;
|
|
int upscale_height = 480;
|
|
const char* settings_path = NULL;
|
|
const char* bios = NULL;
|
|
int bios_from_cli = 0;
|
|
const char* bios_search = NULL;
|
|
const char* model = NULL;
|
|
const char* exe = NULL;
|
|
const char* region = NULL;
|
|
const char* psxe_version = NULL;
|
|
const char* cd_path = NULL;
|
|
const char* exp_path = NULL;
|
|
const char* cpu_engine_name = NULL;
|
|
|
|
static const char *const usages[] = {
|
|
"psxe [options] path-to-cdrom",
|
|
NULL,
|
|
};
|
|
|
|
struct argparse_option options[] = {
|
|
OPT_BOOLEAN ('h', "help" , NULL , "Display this information", argparse_help_cb, 0, 0),
|
|
OPT_BOOLEAN (0 , "help-model" , &help_model , "Display available console models", NULL, 0, 0),
|
|
OPT_BOOLEAN (0 , "help-region" , &help_region , "Display available region options", NULL, 0, 0),
|
|
OPT_BOOLEAN ('v', "version" , &version , "Display version and build information", NULL, 0, 0),
|
|
OPT_GROUP("Basic options"),
|
|
OPT_BOOLEAN ('a', "use-args" , &use_args , "Ignore settings file, use CLI args instead", NULL, 0, 0),
|
|
OPT_STRING ('b', "bios" , &bios , "Specify a BIOS file (ignores -B, -M)", NULL, 0, 0),
|
|
OPT_BOOLEAN ('B', "bios-folder" , &bios_search , "Specify a BIOS search folder", NULL, 0, 0),
|
|
OPT_STRING ('c', "console-source", &console_source, "Select console source (auto, null, kernel, atcons)"),
|
|
OPT_STRING (0 , "cpu-engine" , &cpu_engine_name, "Select CPU engine (cached or interpreter)", NULL, 0, 0),
|
|
OPT_STRING ('e', "exp-rom" , &exp_path , "Specify an expansion ROM file"),
|
|
OPT_INTEGER ('L', "log-level" , &log_level , "Set log level"),
|
|
OPT_STRING ('M', "model" , &model , "Specify console model (SPCH-XXXX)", NULL, 0, 0),
|
|
OPT_STRING ('r', "region" , ®ion , "Specify console region"),
|
|
OPT_INTEGER ('s', "scale" , &scale , "Display scaling factor", NULL, 0, 0),
|
|
OPT_STRING ('S', "settings-file" , &settings_path , "Specify settings file path", NULL, 0, 0),
|
|
OPT_BOOLEAN ('q', "quiet" , &quiet , "Silence all logs (ignores -L)"),
|
|
OPT_STRING ('x', "exe" , &exe , "Launch a PS-X EXE file"),
|
|
OPT_STRING (0 , "cdrom" , &cd_path , "Specify a CDROM image"),
|
|
OPT_END()
|
|
};
|
|
|
|
struct argparse argparse;
|
|
|
|
argparse_init(&argparse, options, usages, 0);
|
|
argparse_describe(&argparse, NULL, g_desc_text);
|
|
|
|
argc = argparse_parse(&argparse, argc_filtered, argv_filtered);
|
|
|
|
if (bios)
|
|
bios_from_cli = 1;
|
|
|
|
if (help_model) {
|
|
printf("%s\n", g_models_text);
|
|
|
|
exit(0);
|
|
}
|
|
|
|
if (help_region) {
|
|
printf("%s\n", g_regions_text);
|
|
|
|
exit(0);
|
|
}
|
|
|
|
if (version) {
|
|
printf("%s\n", g_version_text);
|
|
|
|
exit(0);
|
|
}
|
|
|
|
log_set_quiet(quiet);
|
|
|
|
if (!use_args) {
|
|
if (!settings_path) {
|
|
settings_path = psxe_prefixed_path("settings.toml", &g_settings_path);
|
|
}
|
|
if (!settings_path)
|
|
settings_path = "settings.toml";
|
|
|
|
psxe_ensure_parent_dir(settings_path);
|
|
FILE* settings = fopen(settings_path, "rb");
|
|
|
|
char error[0x100];
|
|
|
|
if (!settings) {
|
|
log_info("Settings file not found; attempting to create one at %s", settings_path ? settings_path : "settings.toml");
|
|
if (settings_path)
|
|
settings = fopen(settings_path, "w+b");
|
|
else
|
|
settings = fopen("settings.toml", "w+b");
|
|
|
|
if (!settings) {
|
|
log_error("Couldn't create settings file %s, loading default settings", settings_path ? settings_path : "settings.toml");
|
|
|
|
psxe_cfg_load_defaults(cfg);
|
|
|
|
return;
|
|
}
|
|
|
|
fwrite(g_default_settings, 1, sizeof(g_default_settings) - 1, settings);
|
|
|
|
fseek(settings, 0, 0);
|
|
}
|
|
|
|
log_info("Parsing settings file...");
|
|
|
|
toml_table_t* conf = toml_parse_file(settings, error, sizeof(error));
|
|
|
|
if (!conf) {
|
|
log_error("Couldn't parse settings file");
|
|
|
|
exit(1);
|
|
}
|
|
|
|
toml_datum_t s_version = toml_string_in(conf, "psxe_version");
|
|
|
|
if (!s_version.ok) {
|
|
log_error("Settings file lacking version number");
|
|
|
|
exit(1);
|
|
}
|
|
|
|
toml_table_t* s_bios_table = toml_table_in(conf, "bios");
|
|
|
|
if (s_bios_table) {
|
|
toml_datum_t s_bios_search_path = toml_string_in(s_bios_table, "search_path");
|
|
|
|
if (s_bios_search_path.ok)
|
|
bios_search = s_bios_search_path.u.s;
|
|
|
|
toml_datum_t s_bios_preferred_model = toml_string_in(s_bios_table, "preferred_model");
|
|
|
|
if (s_bios_preferred_model.ok)
|
|
model = s_bios_preferred_model.u.s;
|
|
|
|
toml_datum_t s_bios_override_file = toml_string_in(s_bios_table, "override_file");
|
|
|
|
if (!bios_from_cli && s_bios_override_file.ok && s_bios_override_file.u.s[0])
|
|
bios = s_bios_override_file.u.s;
|
|
}
|
|
|
|
toml_table_t* s_console_table = toml_table_in(conf, "console");
|
|
|
|
if (s_console_table) {
|
|
toml_datum_t s_console_region = toml_string_in(s_console_table, "region");
|
|
|
|
if (s_console_region.ok)
|
|
region = s_console_region.u.s;
|
|
}
|
|
|
|
toml_table_t* s_cpu_table = toml_table_in(conf, "cpu");
|
|
|
|
if (s_cpu_table && !cpu_engine_name) {
|
|
toml_datum_t s_cpu_engine = toml_string_in(s_cpu_table, "execution_mode");
|
|
|
|
if (s_cpu_engine.ok && s_cpu_engine.u.s) {
|
|
cpu_engine = !strcasecmp(s_cpu_engine.u.s, "interpreter") ? 0 : 1;
|
|
free(s_cpu_engine.u.s);
|
|
}
|
|
}
|
|
|
|
toml_table_t* s_video_table = toml_table_in(conf, "video");
|
|
|
|
if (s_video_table) {
|
|
toml_datum_t s_vsync = toml_bool_in(s_video_table, "vsync");
|
|
|
|
if (s_vsync.ok)
|
|
vsync_enabled = s_vsync.u.b;
|
|
|
|
#ifdef USE_HARDWARE
|
|
toml_datum_t s_gpu_backend = toml_string_in(s_video_table, "gpu_backend");
|
|
|
|
if (s_gpu_backend.ok && s_gpu_backend.u.s) {
|
|
const char* backend = s_gpu_backend.u.s;
|
|
|
|
if (!strcasecmp(backend, "sdl-accelerated") || !strcasecmp(backend, "hardware") || !strcasecmp(backend, "hardware (experimental)") || !strcasecmp(backend, "hw") || !strcasecmp(backend, "hw-renderer")) {
|
|
gpu_backend = 1;
|
|
} else {
|
|
gpu_backend = 0;
|
|
}
|
|
|
|
free(s_gpu_backend.u.s);
|
|
}
|
|
#endif
|
|
|
|
toml_datum_t s_texture_scale_mode = toml_bool_in(s_video_table, "texture_scale_mode");
|
|
|
|
if (s_texture_scale_mode.ok)
|
|
texture_scale_mode = s_texture_scale_mode.u.b;
|
|
|
|
toml_datum_t s_debug_panel = toml_bool_in(s_video_table, "debug_panel");
|
|
|
|
if (s_debug_panel.ok)
|
|
debug_panel = s_debug_panel.u.b;
|
|
|
|
toml_datum_t s_stretch_mode = toml_bool_in(s_video_table, "stretch_mode");
|
|
|
|
if (s_stretch_mode.ok)
|
|
stretch_mode = s_stretch_mode.u.b;
|
|
|
|
toml_datum_t s_display_aspect = toml_string_in(s_video_table, "display_aspect");
|
|
|
|
if (s_display_aspect.ok) {
|
|
if (!strcasecmp(s_display_aspect.u.s, "square")) {
|
|
display_aspect = 1;
|
|
} else if (!strcasecmp(s_display_aspect.u.s, "wide16x9")) {
|
|
display_aspect = 2;
|
|
} else {
|
|
display_aspect = 0;
|
|
}
|
|
}
|
|
|
|
toml_datum_t s_wide_upscale = toml_string_in(s_video_table, "wide_upscale");
|
|
|
|
if (s_wide_upscale.ok) {
|
|
if (!strcasecmp(s_wide_upscale.u.s, "720p")) upscale_height = 720;
|
|
else if (!strcasecmp(s_wide_upscale.u.s, "1080p")) upscale_height = 1080;
|
|
else if (!strcasecmp(s_wide_upscale.u.s, "1440p")) upscale_height = 1440;
|
|
else if (!strcasecmp(s_wide_upscale.u.s, "2160p")) upscale_height = 2160;
|
|
else upscale_height = 480;
|
|
}
|
|
}
|
|
|
|
psxe_version = s_version.u.s;
|
|
|
|
log_info("Settings file parsed. ARMSX version: %s", psxe_version);
|
|
|
|
fclose(settings);
|
|
}
|
|
|
|
if (argc) {
|
|
if (argc > 1) {
|
|
log_error("Unrecognized parameter \'%s\'", argv[1]);
|
|
|
|
exit(1);
|
|
}
|
|
|
|
cd_path = argv[0];
|
|
}
|
|
|
|
if (cd_path)
|
|
cfg->cd_path = cd_path;
|
|
|
|
if (settings_path)
|
|
cfg->settings_path = settings_path;
|
|
|
|
if (log_level)
|
|
cfg->log_level = log_level - 1;
|
|
|
|
if (bios)
|
|
cfg->bios = bios;
|
|
|
|
if (!cfg->bios) {
|
|
const char* bios_default = psxe_prefixed_path("bios.bin", &g_bios_path);
|
|
|
|
#ifdef IOS_TARGET
|
|
if (!g_pref_path && !g_bios_path) {
|
|
char* base_path = SDL_GetBasePath();
|
|
|
|
if (base_path) {
|
|
size_t len = strlen(base_path) + strlen("bios.bin") + 1;
|
|
g_bios_path = (char*)malloc(len);
|
|
|
|
if (g_bios_path)
|
|
snprintf(g_bios_path, len, "%sbios.bin", base_path);
|
|
|
|
SDL_free(base_path);
|
|
bios_default = g_bios_path ? g_bios_path : bios_default;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
cfg->bios = bios_default ? bios_default : "bios.bin";
|
|
}
|
|
|
|
if (bios_search)
|
|
cfg->bios_search = bios_search;
|
|
|
|
if (model)
|
|
cfg->model = model;
|
|
|
|
if (exe)
|
|
cfg->exe = exe;
|
|
|
|
if (region)
|
|
cfg->region = region;
|
|
|
|
if (psxe_version)
|
|
cfg->psxe_version = psxe_version;
|
|
|
|
if (exp_path)
|
|
cfg->exp_path = exp_path;
|
|
|
|
if (cpu_engine_name)
|
|
cpu_engine = !strcasecmp(cpu_engine_name, "interpreter") ? 0 : 1;
|
|
|
|
if (scale)
|
|
cfg->scale = scale;
|
|
|
|
cfg->vsync_enabled = vsync_enabled;
|
|
cfg->cpu_engine = cpu_engine;
|
|
#ifdef USE_HARDWARE
|
|
cfg->gpu_backend = gpu_backend;
|
|
#endif
|
|
cfg->texture_scale_mode = texture_scale_mode;
|
|
cfg->debug_panel = debug_panel;
|
|
cfg->stretch_mode = stretch_mode;
|
|
cfg->display_aspect = display_aspect;
|
|
cfg->upscale_height = upscale_height;
|
|
cfg->quiet = quiet;
|
|
cfg->use_args = use_args;
|
|
|
|
log_info("Using BIOS path: %s", cfg->bios ? cfg->bios : "(none)");
|
|
|
|
free(argv_filtered);
|
|
}
|
|
|
|
char* psxe_cfg_get_bios_path(psxe_config_t* cfg) {
|
|
char* bios_path = NULL;
|
|
|
|
if (!cfg)
|
|
return NULL;
|
|
|
|
if (cfg->bios && psxe_file_exists(cfg->bios))
|
|
return strdup(cfg->bios);
|
|
|
|
if (cfg->bios_search && cfg->bios_search[0])
|
|
bios_path = psxe_find_bios_in_dir(cfg->bios_search, cfg->model);
|
|
|
|
if (bios_path)
|
|
return bios_path;
|
|
|
|
if (cfg->bios)
|
|
return strdup(cfg->bios);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const char* psxe_cfg_get_pref_path(void) {
|
|
return psxe_pref_path();
|
|
}
|
|
|
|
#undef STR1
|
|
#undef STR
|