Add RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME.

Allows libretro core to not require a ROM to be loaded.
Kill stdin ROM loading support (pointless these days).
Replace "no ROM on CLI" behavior to be attempting to load a core with no
ROM.
This commit is contained in:
Themaister 2013-05-01 00:56:13 +02:00
parent e2229ec3c3
commit 197c4db204
8 changed files with 61 additions and 146 deletions

View File

@ -20,7 +20,7 @@ libretro provides emulation of a game system, and can be implemented by any fron
.TP
\fB[rom file]\fR
If no rom file path is defined on the command line, \fBretroarch\fR will try to load a rom from \fBstdin\fR.
If no rom file path is defined on the command line, \fBretroarch\fR will try to load a core with no rom. This will only work with some libretro cores.
\fBretroarch\fR use uncompressed ROMs, but can uncompress roms in the .zip/deflate format if support for it is compiled in.
ROM types supported depend on the libretro implementation used.
@ -53,17 +53,13 @@ If two or more different implementations claim to support a certain ROM extensio
\fB--save PATH, -s PATH\fR
Overrides the path used for save ram (*.srm).
Without this flag, the save ram path will be inferred from the rom path name, and put in the same directory as the rom file with the extention replaced with '.srm'.
When rom is loaded from \fBstdin\fR, this flag is mandatory to define as no path can be inferred.
If PATH is a directory, RetroArch will treat this as the save file directory, where the save file name will be inferred from the rom name.
When loading a rom from stdin, the path must be a full path, however.
.TP
\fB--savestate PATH, -S PATH\fR
Overrides the path used for save states.
Without this flag, the save state path will be inferred from the rom path name, and put in the same directory as the rom file with the extention replace with '.state'.
When rom is loaded from \fBstdin\fR, this flag is mandatory to define as no path can be inferred.
If PATH is a directory, RetroArch will treat this as the save state directory, where the state file name will be inferred from the rom name.
When loading a rom from stdin, the path must be a full path, however.
Do note that save states are bound to the libretro implementation being used. Using a different libretro could invalidate the save state file.
.TP
@ -76,7 +72,6 @@ Sets the configuration file path. \fBretroarch\fR will use this path to load the
Should this not be defined, \fBretroarch\fR will look in platform specific paths to attempt finding the config file.
/etc/retroarch.cfg (when installed), or retroarch.cfg in the source tarball serves as a skeleton configuration file.
If PATH is a directory, RetroArch will treat this as the config file directory, where the state file name will be inferred from the rom name (*.cfg).
When loading a rom from stdin, the path must be a full path, however.
If a config cannot be found when using directory path, the default config path will be used instead.
.IP

View File

@ -130,9 +130,10 @@ bool libretro_get_system_info(const char *path, struct retro_system_info *info)
return false;
memcpy(info, &dummy_info, sizeof(*info));
info->library_name = strdup(dummy_info.library_name);
info->library_version = strdup(dummy_info.library_version);
info->valid_extensions = strdup(dummy_info.valid_extensions);
info->library_name = strdup(dummy_info.library_name);
info->library_version = strdup(dummy_info.library_version);
if (dummy_info.valid_extensions)
info->valid_extensions = strdup(dummy_info.valid_extensions);
dylib_close(lib);
return true;
}
@ -371,6 +372,8 @@ void uninit_libretro_sym(void)
memset(&g_extern.system.av_info, 0, sizeof(g_extern.system.av_info));
memset(&g_extern.frame_cache, 0, sizeof(g_extern.frame_cache));
g_extern.system.pix_fmt = RETRO_PIXEL_FORMAT_0RGB1555;
g_extern.system.no_game = false;
g_extern.system.shutdown = false;
}
#ifdef NEED_DYNAMIC
@ -637,6 +640,14 @@ static bool environment_cb(unsigned cmd, void *data)
break;
}
case RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME:
{
bool state = *(const bool*)data;
RARCH_LOG("Environ SET_SUPPORT_NO_GAME: %s.\n", state ? "yes" : "no");
g_extern.system.no_game = state;
break;
}
default:
RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd);
return false;

115
file.c
View File

@ -209,83 +209,21 @@ static void patch_rom(uint8_t **buf, ssize_t *size)
*size = target_size;
}
if (patch_data)
free(patch_data);
free(patch_data);
return;
error:
*buf = ret_buf;
*size = ret_size;
if (patch_data)
free(patch_data);
free(patch_data);
}
static ssize_t read_rom_file(FILE *file, void **buf)
static ssize_t read_rom_file(const char *path, void **buf)
{
ssize_t ret = 0;
uint8_t *ret_buf = NULL;
if (file == NULL) // stdin
{
#if defined(_WIN32) && !defined(_XBOX)
_setmode(0, O_BINARY);
#endif
RARCH_LOG("Reading ROM from stdin ...\n");
size_t buf_size = 0xfffff; // Some initial guesstimate.
size_t buf_ptr = 0;
uint8_t *rom_buf = (uint8_t*)malloc(buf_size);
if (rom_buf == NULL)
{
RARCH_ERR("Couldn't allocate memory.\n");
return -1;
}
for (;;)
{
size_t ret = fread(rom_buf + buf_ptr, 1, buf_size - buf_ptr, stdin);
buf_ptr += ret;
// We've reached the end
if (buf_ptr < buf_size)
break;
rom_buf = (uint8_t*)realloc(rom_buf, buf_size * 2);
if (rom_buf == NULL)
{
RARCH_ERR("Couldn't allocate memory.\n");
return -1;
}
buf_size *= 2;
}
ret_buf = rom_buf;
ret = buf_ptr;
}
else
{
fseek(file, 0, SEEK_END);
ret = ftell(file);
rewind(file);
void *rom_buf = malloc(ret);
if (rom_buf == NULL)
{
RARCH_ERR("Couldn't allocate memory.\n");
return -1;
}
if (fread(rom_buf, 1, ret, file) < (size_t)ret)
{
RARCH_ERR("Didn't read whole file.\n");
free(rom_buf);
return -1;
}
ret_buf = (uint8_t*)rom_buf;
}
ssize_t ret = read_file(path, (void**)&ret_buf);
if (ret <= 0)
return ret;
if (!g_extern.block_patch)
{
@ -539,22 +477,10 @@ static bool load_roms(unsigned rom_type, const char **rom_paths, size_t roms)
struct retro_game_info info[MAX_ROMS] = {{NULL}};
char *xml_buf = load_xml_map(g_extern.xml_name);
FILE *rom_file = NULL;
if (rom_paths[0])
{
RARCH_LOG("Loading ROM file: %s.\n", rom_paths[0]);
rom_file = fopen(rom_paths[0], "rb");
if (!rom_file)
{
RARCH_ERR("Failed to load ROM file: %s.\n", rom_paths[0]);
ret = false;
goto end;
}
}
if (!g_extern.system.info.need_fullpath)
{
if ((rom_len[0] = read_rom_file(rom_file, &rom_buf[0])) == -1)
RARCH_LOG("Loading ROM file: %s.\n", rom_paths[0]);
if ((rom_len[0] = read_rom_file(rom_paths[0], &rom_buf[0])) == -1)
{
RARCH_ERR("Could not read ROM file.\n");
ret = false;
@ -564,16 +490,7 @@ static bool load_roms(unsigned rom_type, const char **rom_paths, size_t roms)
RARCH_LOG("ROM size: %u bytes.\n", (unsigned)rom_len[0]);
}
else
{
if (!rom_file)
{
RARCH_ERR("Implementation requires a full path to be set, cannot load ROM from stdin. Aborting ...\n");
ret = false;
goto end;
}
RARCH_LOG("ROM loading skipped. Implementation will load it on its own.\n");
}
info[0].path = rom_paths[0];
info[0].data = rom_buf[0];
@ -608,16 +525,24 @@ end:
for (unsigned i = 0; i < MAX_ROMS; i++)
free(rom_buf[i]);
free(xml_buf);
if (rom_file)
fclose(rom_file);
return ret;
}
static bool load_normal_rom(void)
{
const char *path = *g_extern.fullpath ? g_extern.fullpath : NULL;
return load_roms(0, &path, 1);
if (g_extern.libretro_no_rom && g_extern.system.no_game)
return pretro_load_game(NULL);
else if (g_extern.libretro_no_rom && !g_extern.system.no_game)
{
RARCH_ERR("No ROM is used, but libretro core does not support this.\n");
return false;
}
else
{
const char *path = g_extern.fullpath;
return load_roms(0, &path, 1);
}
}
static bool load_sgb_rom(void)

View File

@ -369,6 +369,7 @@ struct global
bool block_extract;
bool force_nonblock;
bool no_game;
const char *input_desc_btn[MAX_PLAYERS][RARCH_FIRST_CUSTOM_BIND];
char valid_extensions[PATH_MAX];
@ -379,6 +380,7 @@ struct global
struct retro_hw_render_callback hw_render_callback;
core_option_manager_t *core_options;
} system;
struct
@ -597,6 +599,7 @@ struct global
jmp_buf error_sjlj_context;
unsigned menu_toggle_behavior;
bool libretro_no_rom;
bool libretro_dummy;
};

View File

@ -190,6 +190,9 @@ static retro_input_state_t input_state_cb;
void retro_set_environment(retro_environment_t cb)
{
environ_cb = cb;
bool no_rom = true;
cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &no_rom);
}
void retro_set_audio_sample(retro_audio_sample_t cb)

View File

@ -73,6 +73,9 @@ void retro_set_environment(retro_environment_t cb)
};
cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars);
bool no_rom = true;
cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &no_rom);
}
void retro_set_audio_sample(retro_audio_sample_t cb)

View File

@ -452,6 +452,12 @@ enum retro_mod
// Result is set to true if some variables are updated by
// frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE.
// Variables should be queried with GET_VARIABLE.
//
#define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18
// const bool * --
// If true, the libretro implementation supports calls to retro_load_game() with NULL as argument.
// Used by cores which can run without particular game data.
// Pass this to retro_video_refresh_t if rendering to hardware.
// Passing NULL to retro_video_refresh_t is still a frame dupe as normal.

View File

@ -646,7 +646,7 @@ static void print_help(void)
puts("\t--menu: Do not require ROM or libretro core to be loaded, starts directly in menu.");
puts("\t\tIf no arguments are passed to RetroArch, it is equivalent to using --menu as only argument.");
puts("\t--features: Prints available features compiled into RetroArch.");
puts("\t-s/--save: Path for save file (*.srm). Required when rom is input from stdin.");
puts("\t-s/--save: Path for save file (*.srm).");
puts("\t-f/--fullscreen: Start RetroArch in fullscreen regardless of config settings.");
puts("\t-S/--savestate: Path to use for save states. If not selected, *.state will be assumed.");
puts("\t-c/--config: Path for config file." RARCH_DEFAULT_CONF_PATH_STR);
@ -753,45 +753,9 @@ static void set_paths(const char *path)
}
}
static void verify_stdin_paths(void)
{
if (!*g_extern.savefile_name_srm)
{
RARCH_ERR("Need savefile path argument (--save) when reading rom from stdin.\n");
print_help();
rarch_fail(1, "verify_stdin_paths()");
}
else if (!*g_extern.savestate_name)
{
RARCH_ERR("Need savestate path argument (--savestate) when reading rom from stdin.\n");
print_help();
rarch_fail(1, "verify_stdin_paths()");
}
if (path_is_directory(g_extern.savefile_name_srm))
{
RARCH_ERR("Cannot specify directory for path argument (--save) when reading from stdin.\n");
print_help();
rarch_fail(1, "verify_stdin_paths()");
}
else if (path_is_directory(g_extern.savestate_name))
{
RARCH_ERR("Cannot specify directory for path argument (--savestate) when reading from stdin.\n");
print_help();
rarch_fail(1, "verify_stdin_paths()");
}
else if (path_is_directory(g_extern.config_path))
{
RARCH_ERR("Cannot specify directory for config file (--config) when reading from stdin.\n");
print_help();
rarch_fail(1, "verify_stdin_paths()");
}
driver.stdin_claimed = true;
}
static void parse_input(int argc, char *argv[])
{
g_extern.libretro_no_rom = false;
g_extern.libretro_dummy = false;
g_extern.has_set_save_path = false;
g_extern.has_set_state_path = false;
@ -1177,7 +1141,7 @@ static void parse_input(int argc, char *argv[])
else if (optind < argc)
set_paths(argv[optind]);
else
verify_stdin_paths();
g_extern.libretro_no_rom = true;
// Copy SRM/state dirs used, so they can be reused on reentrancy.
if (g_extern.has_set_save_path && path_is_directory(g_extern.savefile_name_srm))
@ -2907,10 +2871,15 @@ int rarch_main_init(int argc, char *argv[])
verify_api_version();
pretro_init();
g_extern.use_sram = !g_extern.libretro_dummy;
g_extern.use_sram = !g_extern.libretro_dummy && !g_extern.libretro_no_rom;
bool allow_cheats = true;
if (!g_extern.libretro_dummy)
if (g_extern.libretro_no_rom && !g_extern.libretro_dummy)
{
if (!init_rom_file(g_extern.game_type))
goto error;
}
else if (!g_extern.libretro_dummy)
{
fill_pathnames();
@ -3123,7 +3092,7 @@ void rarch_main_deinit(void)
deinit_movie();
#endif
if (!g_extern.libretro_dummy)
if (!g_extern.libretro_dummy && !g_extern.libretro_no_rom)
save_auto_state();
pretro_unload_game();