mirror of
https://github.com/libretro/RetroArch
synced 2025-03-03 04:14:00 +00:00
Add some more abstractions for file loading. Also add initial SGB rom
loading!
This commit is contained in:
parent
90a5059b5b
commit
e6aa065781
@ -52,6 +52,10 @@ unsigned (*psnes_library_revision_minor)(void);
|
||||
unsigned (*psnes_library_revision_major)(void);
|
||||
|
||||
bool (*psnes_load_cartridge_normal)(const char*, const uint8_t*, unsigned);
|
||||
bool (*psnes_load_cartridge_super_game_boy)(
|
||||
const char*, const uint8_t*, unsigned,
|
||||
const char*, const uint8_t*, unsigned);
|
||||
|
||||
void (*psnes_set_controller_port_device)(bool, unsigned);
|
||||
|
||||
bool (*psnes_get_region)(void);
|
||||
@ -89,6 +93,7 @@ static void load_dynamic(void)
|
||||
SYM(snes_run);
|
||||
SYM(snes_get_region);
|
||||
SYM(snes_load_cartridge_normal);
|
||||
SYM(snes_load_cartridge_super_game_boy);
|
||||
SYM(snes_set_controller_port_device);
|
||||
SYM(snes_serialize_size);
|
||||
SYM(snes_serialize);
|
||||
@ -118,6 +123,7 @@ static void set_statics(void)
|
||||
SSYM(snes_run);
|
||||
SSYM(snes_get_region);
|
||||
SSYM(snes_load_cartridge_normal);
|
||||
SSYM(snes_load_cartridge_super_game_boy);
|
||||
SSYM(snes_set_controller_port_device);
|
||||
SSYM(snes_serialize_size);
|
||||
SSYM(snes_serialize);
|
||||
|
@ -35,6 +35,10 @@ extern unsigned (*psnes_library_revision_minor)(void);
|
||||
extern unsigned (*psnes_library_revision_major)(void);
|
||||
|
||||
extern bool (*psnes_load_cartridge_normal)(const char*, const uint8_t*, unsigned);
|
||||
extern bool (*psnes_load_cartridge_super_game_boy)(
|
||||
const char*, const uint8_t*, unsigned,
|
||||
const char*, const uint8_t*, unsigned);
|
||||
|
||||
extern void (*psnes_set_controller_port_device)(bool, unsigned);
|
||||
|
||||
extern bool (*psnes_get_region)(void);
|
||||
|
104
file.c
104
file.c
@ -165,3 +165,107 @@ void save_file(const char* path, int type)
|
||||
if ( data && size > 0 )
|
||||
write_file(path, data, size);
|
||||
}
|
||||
|
||||
static bool load_sgb_rom(void)
|
||||
{
|
||||
void *rom_buf;
|
||||
ssize_t rom_len = 0;
|
||||
|
||||
FILE *extra_rom;
|
||||
void *extra_rom_buf;
|
||||
ssize_t extra_rom_len = 0;
|
||||
|
||||
if ((rom_len = read_file(g_extern.rom_file, &rom_buf)) == -1)
|
||||
{
|
||||
SSNES_ERR("Could not read ROM file.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
extra_rom = fopen(g_extern.gb_rom_path, "rb");
|
||||
if (!extra_rom)
|
||||
{
|
||||
SSNES_ERR("Couldn't open GameBoy ROM!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((extra_rom_len = read_file(extra_rom, &extra_rom_buf)) == -1)
|
||||
{
|
||||
SSNES_ERR("Cannot read GameBoy rom.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!psnes_load_cartridge_super_game_boy(
|
||||
NULL, rom_buf, rom_len,
|
||||
NULL, extra_rom_buf, extra_rom_len))
|
||||
{
|
||||
SSNES_ERR("Cannot load SGB/GameBoy rom.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (g_extern.rom_file)
|
||||
fclose(g_extern.rom_file);
|
||||
if (extra_rom)
|
||||
fclose(extra_rom);
|
||||
free(rom_buf);
|
||||
free(extra_rom_buf);
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (g_extern.rom_file)
|
||||
fclose(g_extern.rom_file);
|
||||
if (extra_rom)
|
||||
fclose(extra_rom);
|
||||
free(rom_buf);
|
||||
free(extra_rom_buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool load_normal_rom(void)
|
||||
{
|
||||
void *rom_buf;
|
||||
ssize_t rom_len = 0;
|
||||
|
||||
if ((rom_len = read_file(g_extern.rom_file, &rom_buf)) == -1)
|
||||
{
|
||||
SSNES_ERR("Could not read ROM file.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_extern.rom_file != NULL)
|
||||
fclose(g_extern.rom_file);
|
||||
|
||||
SSNES_LOG("ROM size: %d bytes\n", (int)rom_len);
|
||||
|
||||
if (!psnes_load_cartridge_normal(NULL, rom_buf, rom_len))
|
||||
{
|
||||
SSNES_ERR("ROM file is not valid!\n");
|
||||
free(rom_buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
free(rom_buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool init_rom_file(void)
|
||||
{
|
||||
switch (g_extern.game_type)
|
||||
{
|
||||
case SSNES_CART_SGB:
|
||||
if (!load_sgb_rom())
|
||||
return false;
|
||||
break;
|
||||
|
||||
case SSNES_CART_NORMAL:
|
||||
if (!load_normal_rom())
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
SSNES_ERR("Invalid ROM type!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
3
file.h
3
file.h
@ -19,6 +19,7 @@
|
||||
#ifndef __SSNES_FILE_H
|
||||
#define __SSNES_FILE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
@ -31,4 +32,6 @@ void write_file(const char* path, uint8_t* data, size_t size);
|
||||
void load_save_file(const char* path, int type);
|
||||
void save_file(const char* path, int type);
|
||||
|
||||
bool init_rom_file(void);
|
||||
|
||||
#endif
|
||||
|
11
general.h
11
general.h
@ -78,6 +78,12 @@ struct settings
|
||||
char libsnes[256];
|
||||
};
|
||||
|
||||
enum ssnes_game_type
|
||||
{
|
||||
SSNES_CART_NORMAL = 0,
|
||||
SSNES_CART_SGB
|
||||
};
|
||||
|
||||
struct global
|
||||
{
|
||||
bool verbose;
|
||||
@ -92,10 +98,15 @@ struct global
|
||||
bool has_multitap;
|
||||
|
||||
FILE *rom_file;
|
||||
enum ssnes_game_type game_type;
|
||||
|
||||
char gb_rom_path[256];
|
||||
|
||||
char config_path[256];
|
||||
|
||||
char basename[256];
|
||||
char savefile_name_srm[256];
|
||||
char savefile_name_rtc[260]; // Make sure that fill_pathname has space.
|
||||
char savestate_name[256];
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
|
137
ssnes.c
137
ssnes.c
@ -36,6 +36,7 @@
|
||||
struct global g_extern = {
|
||||
.video_active = true,
|
||||
.audio_active = true,
|
||||
.game_type = SSNES_CART_NORMAL,
|
||||
};
|
||||
|
||||
// To avoid continous switching if we hold the button down, we require that the button must go from pressed, unpressed back to pressed to be able to toggle between then.
|
||||
@ -237,11 +238,12 @@ static void print_help(void)
|
||||
puts("=================================================");
|
||||
puts("ssnes: Simple Super Nintendo Emulator (libsnes)");
|
||||
puts("=================================================");
|
||||
puts("Usage: ssnes [rom file] [-h/--help | -c/--config | -v/--verbose | -4/--multitap | -j/--justifier | -k/--justifiers | -t/--savestate | -m/--mouse | -p/--scope | -s/--save" FFMPEG_HELP_QUARK "]");
|
||||
puts("Usage: ssnes [rom file] [-h/--help | -c/--config | -v/--verbose | -4/--multitap | -j/--justifier | -k/--justifiers | -t/--savestate | -m/--mouse | -g/--gameboy | -p/--scope | -s/--save" FFMPEG_HELP_QUARK "]");
|
||||
puts("\t-h/--help: Show this help message");
|
||||
puts("\t-s/--save: Path for save file (*.srm). Required when rom is input from stdin");
|
||||
puts("\t-t/--savestate: Path to use for save states. If not selected, *.state will be assumed.");
|
||||
puts("\t-c/--config: Path for config file." SSNES_DEFAULT_CONF_PATH_STR);
|
||||
puts("\t-g/--gameboy: Path to Gameboy ROM. Load SuperGameBoy as the regular rom.");
|
||||
puts("\t-m/--mouse: Connect a virtual mouse into designated port of the SNES (1 or 2).");
|
||||
puts("\t\tThis argument can be specified several times to connect more mice.");
|
||||
puts("\t-p/--scope: Connect a virtual SuperScope into port 2 of the SNES.");
|
||||
@ -270,6 +272,7 @@ static void parse_input(int argc, char *argv[])
|
||||
{ "record", 1, NULL, 'r' },
|
||||
#endif
|
||||
{ "verbose", 0, NULL, 'v' },
|
||||
{ "gameboy", 1, NULL, 'g' },
|
||||
{ "config", 0, NULL, 'c' },
|
||||
{ "mouse", 1, NULL, 'm' },
|
||||
{ "scope", 0, NULL, 'p' },
|
||||
@ -288,7 +291,7 @@ static void parse_input(int argc, char *argv[])
|
||||
#define FFMPEG_RECORD_ARG
|
||||
#endif
|
||||
|
||||
char optstring[] = "hs:vc:t:m:p4jk" FFMPEG_RECORD_ARG;
|
||||
char optstring[] = "hs:vc:t:m:p4jkg:" FFMPEG_RECORD_ARG;
|
||||
for(;;)
|
||||
{
|
||||
int c = getopt_long(argc, argv, optstring, opts, &option_index);
|
||||
@ -319,6 +322,11 @@ static void parse_input(int argc, char *argv[])
|
||||
strncpy(g_extern.savefile_name_srm, optarg, sizeof(g_extern.savefile_name_srm) - 1);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
strncpy(g_extern.gb_rom_path, optarg, sizeof(g_extern.gb_rom_path) - 1);
|
||||
g_extern.game_type = SSNES_CART_SGB;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
strncpy(g_extern.savestate_name, optarg, sizeof(g_extern.savestate_name) - 1);
|
||||
break;
|
||||
@ -443,63 +451,21 @@ static void init_controllers(void)
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
static inline void load_save_files(void)
|
||||
{
|
||||
parse_input(argc, argv);
|
||||
parse_config();
|
||||
init_dlsym();
|
||||
|
||||
psnes_init();
|
||||
if (strlen(g_extern.basename) > 0)
|
||||
psnes_set_cartridge_basename(g_extern.basename);
|
||||
|
||||
SSNES_LOG("Version of libsnes API: %u.%u\n", psnes_library_revision_major(), psnes_library_revision_minor());
|
||||
void *rom_buf;
|
||||
ssize_t rom_len = 0;
|
||||
if ((rom_len = read_file(g_extern.rom_file, &rom_buf)) == -1)
|
||||
{
|
||||
SSNES_ERR("Could not read ROM file.\n");
|
||||
exit(1);
|
||||
}
|
||||
SSNES_LOG("ROM size: %d bytes\n", (int)rom_len);
|
||||
|
||||
if (g_extern.rom_file != NULL)
|
||||
fclose(g_extern.rom_file);
|
||||
|
||||
// Infer .rtc save path from save ram path.
|
||||
char savefile_name_rtc[strlen(g_extern.savefile_name_srm)+strlen(".rtc")+1];
|
||||
fill_pathname(savefile_name_rtc, g_extern.savefile_name_srm, ".rtc");
|
||||
|
||||
init_drivers();
|
||||
|
||||
psnes_set_video_refresh(video_frame);
|
||||
psnes_set_audio_sample(audio_sample);
|
||||
psnes_set_input_poll(input_poll);
|
||||
psnes_set_input_state(input_state);
|
||||
|
||||
// TODO: Load other types of ROMs as well!
|
||||
if (!psnes_load_cartridge_normal(NULL, rom_buf, rom_len))
|
||||
{
|
||||
SSNES_ERR("ROM file is not valid!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
free(rom_buf);
|
||||
|
||||
init_controllers();
|
||||
|
||||
unsigned serial_size = psnes_serialize_size();
|
||||
uint8_t *serial_data = malloc(serial_size);
|
||||
if (serial_data == NULL)
|
||||
{
|
||||
SSNES_ERR("Failed to allocate memory for states!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
load_save_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM);
|
||||
load_save_file(savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC);
|
||||
load_save_file(g_extern.savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC);
|
||||
}
|
||||
|
||||
static inline void save_files(void)
|
||||
{
|
||||
save_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM);
|
||||
save_file(g_extern.savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC);
|
||||
}
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
static void init_recording(void)
|
||||
{
|
||||
// Hardcode these options at the moment. Should be specificed in the config file later on.
|
||||
if (g_extern.recording)
|
||||
{
|
||||
@ -525,6 +491,58 @@ int main(int argc, char *argv[])
|
||||
g_extern.recording = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void deinit_recording(void)
|
||||
{
|
||||
if (g_extern.recording)
|
||||
{
|
||||
ffemu_finalize(g_extern.rec);
|
||||
ffemu_free(g_extern.rec);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
parse_input(argc, argv);
|
||||
parse_config();
|
||||
init_dlsym();
|
||||
|
||||
psnes_init();
|
||||
if (strlen(g_extern.basename) > 0)
|
||||
psnes_set_cartridge_basename(g_extern.basename);
|
||||
|
||||
SSNES_LOG("Version of libsnes API: %u.%u\n", psnes_library_revision_major(), psnes_library_revision_minor());
|
||||
|
||||
// Infer .rtc save path from save ram path.
|
||||
fill_pathname(g_extern.savefile_name_rtc, g_extern.savefile_name_srm, ".rtc");
|
||||
|
||||
if (!init_rom_file())
|
||||
goto error;
|
||||
|
||||
init_drivers();
|
||||
|
||||
psnes_set_video_refresh(video_frame);
|
||||
psnes_set_audio_sample(audio_sample);
|
||||
psnes_set_input_poll(input_poll);
|
||||
psnes_set_input_state(input_state);
|
||||
|
||||
init_controllers();
|
||||
|
||||
unsigned serial_size = psnes_serialize_size();
|
||||
uint8_t *serial_data = malloc(serial_size);
|
||||
if (serial_data == NULL)
|
||||
{
|
||||
SSNES_ERR("Failed to allocate memory for states!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
load_save_files();
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
init_recording();
|
||||
#endif
|
||||
|
||||
// Main loop
|
||||
@ -556,16 +574,11 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
if (g_extern.recording)
|
||||
{
|
||||
ffemu_finalize(g_extern.rec);
|
||||
ffemu_free(g_extern.rec);
|
||||
}
|
||||
deinit_recording();
|
||||
#endif
|
||||
|
||||
// Flush out SRAM (and RTC)
|
||||
save_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM);
|
||||
save_file(savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC);
|
||||
save_files();
|
||||
|
||||
psnes_unload_cartridge();
|
||||
psnes_term();
|
||||
|
Loading…
x
Reference in New Issue
Block a user