diff --git a/dynamic.c b/dynamic.c index f78e36e066..98e722c6f9 100644 --- a/dynamic.c +++ b/dynamic.c @@ -39,80 +39,61 @@ #endif #endif -#ifdef NEED_DYNAMIC -#define DLSYM(lib, x) dylib_proc(lib, #x) - -#define SYM(type, x) do { \ - p##x = (type)DLSYM(lib_handle, x); \ +#ifdef HAVE_DYNAMIC +#define SYM(x) do { \ + function_t func = dylib_proc(lib, #x); \ + memcpy(&p##x, &func, sizeof(func)); \ if (p##x == NULL) { SSNES_ERR("Failed to load symbol: \"%s\"\n", #x); ssnes_fail(1, "init_libsnes_sym()"); } \ } while (0) -#define OPT_SYM(type, x) do { \ - p##x = (type)DLSYM(lib_handle, x); \ -} while (0) - -#endif - -#ifdef HAVE_DYNAMIC static dylib_t lib_handle = NULL; +#else +#define SYM(x) p##x = x #endif -void (*psnes_init)(void); +void (*pretro_init)(void); +void (*pretro_deinit)(void); -void (*psnes_set_video_refresh)(snes_video_refresh_t); -void (*psnes_set_audio_sample)(snes_audio_sample_t); -void (*psnes_set_input_poll)(snes_input_poll_t); -void (*psnes_set_input_state)(snes_input_state_t); +unsigned (*pretro_api_version)(void); -void (*psnes_reset)(void); -void (*psnes_run)(void); +void (*pretro_get_system_info)(struct retro_system_info*); +void (*pretro_get_system_av_info)(struct retro_system_av_info*); -void (*psnes_cheat_reset)(void); -void (*psnes_cheat_set)(unsigned, bool, const char*); +void (*pretro_set_environment)(retro_environment_t); +void (*pretro_set_video_refresh)(retro_video_refresh_t); +void (*pretro_set_audio_sample)(retro_audio_sample_t); +void (*pretro_set_audio_sample_batch)(retro_audio_sample_batch_t); +void (*pretro_set_input_poll)(retro_input_poll_t); +void (*pretro_set_input_state)(retro_input_state_t); -const char *(*psnes_library_id)(void) = NULL; -unsigned (*psnes_library_revision_minor)(void); -unsigned (*psnes_library_revision_major)(void); +void (*pretro_set_controller_port_device)(bool, unsigned); -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); -bool (*psnes_load_cartridge_bsx)( - const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned); -bool (*psnes_load_cartridge_bsx_slotted)( - const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned); -bool (*psnes_load_cartridge_sufami_turbo)( - const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned); +void (*pretro_reset)(void); +void (*pretro_run)(void); -void (*psnes_set_controller_port_device)(bool, unsigned); +size_t (*pretro_serialize_size)(void); +bool (*pretro_serialize)(void*, size_t); +bool (*pretro_unserialize)(const void*, size_t); -bool (*psnes_get_region)(void); +void (*pretro_cheat_reset)(void); +void (*pretro_cheat_set)(unsigned, bool, const char*); -unsigned (*psnes_serialize_size)(void); -bool (*psnes_serialize)(uint8_t*, unsigned); -bool (*psnes_unserialize)(const uint8_t*, unsigned); +bool (*pretro_load_game)(const retro_game_info*); +bool (*pretro_load_game_special)(unsigned, const retro_game_info*, size_t); -void (*psnes_set_cartridge_basename)(const char*); +void (*pretro_unload_game)(void); -uint8_t* (*psnes_get_memory_data)(unsigned); -unsigned (*psnes_get_memory_size)(unsigned); +unsigned (*pretro_get_region)(void); -void (*psnes_unload_cartridge)(void); -void (*psnes_term)(void); +void *(*pretro_get_memory_data)(unsigned); +size_t (*pretro_get_memory_size)(unsigned); -#if defined(NEED_DYNAMIC) || defined(SSNES_CONSOLE) static void set_environment(void); -#endif static void set_environment_defaults(void); -#ifdef HAVE_DYNAMIC -static void load_dynamic(void) +static void load_symbols(void) { +#ifdef HAVE_DYNAMIC SSNES_LOG("Loading dynamic libsnes from: \"%s\"\n", g_settings.libsnes); lib_handle = dylib_load(g_settings.libsnes); if (!lib_handle) @@ -120,77 +101,43 @@ static void load_dynamic(void) SSNES_ERR("Failed to open dynamic library: \"%s\"\n", g_settings.libsnes); ssnes_fail(1, "load_dynamic()"); } - - SYM(void (*)(void), snes_init); - SYM(void (*)(snes_video_refresh_t), snes_set_video_refresh); - SYM(void (*)(snes_audio_sample_t), snes_set_audio_sample); - SYM(void (*)(snes_input_poll_t), snes_set_input_poll); - SYM(void (*)(snes_input_state_t), snes_set_input_state); - SYM(const char *(*)(void), snes_library_id); - SYM(unsigned (*)(void), snes_library_revision_minor); - SYM(unsigned (*)(void), snes_library_revision_major); - SYM(void (*)(void), snes_cheat_reset); - SYM(void (*)(unsigned, bool, const char*), snes_cheat_set); - SYM(void (*)(void), snes_reset); - SYM(void (*)(void), snes_run); - SYM(bool (*)(void), snes_get_region); - SYM(bool (*)(const char*, const uint8_t*, unsigned), snes_load_cartridge_normal); - SYM(bool (*)(const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned), snes_load_cartridge_super_game_boy); - SYM(bool (*)(const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned), snes_load_cartridge_bsx); - SYM(bool (*)(const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned), snes_load_cartridge_bsx_slotted); - SYM(bool (*)(const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned), snes_load_cartridge_sufami_turbo); - SYM(void (*)(bool, unsigned), snes_set_controller_port_device); - SYM(unsigned (*)(void), snes_serialize_size); - SYM(bool (*)(uint8_t*, unsigned), snes_serialize); - SYM(bool (*)(const uint8_t*, unsigned), snes_unserialize); - SYM(void (*)(const char*), snes_set_cartridge_basename); - SYM(uint8_t *(*)(unsigned), snes_get_memory_data); - SYM(unsigned (*)(unsigned), snes_get_memory_size); - SYM(void (*)(void), snes_unload_cartridge); - SYM(void (*)(void), snes_term); -} -#else -#define SSYM(x) do { \ - p##x = x; \ -} while (0) - -static void set_statics(void) -{ - SSYM(snes_init); - SSYM(snes_set_video_refresh); - SSYM(snes_set_audio_sample); - SSYM(snes_set_input_poll); - SSYM(snes_set_input_state); - SSYM(snes_library_revision_minor); - SSYM(snes_library_revision_major); - SSYM(snes_library_id); - SSYM(snes_cheat_reset); - SSYM(snes_cheat_set); - SSYM(snes_reset); - SSYM(snes_run); - SSYM(snes_get_region); - SSYM(snes_load_cartridge_normal); - SSYM(snes_load_cartridge_super_game_boy); - SSYM(snes_load_cartridge_bsx); - SSYM(snes_load_cartridge_bsx_slotted); - SSYM(snes_load_cartridge_sufami_turbo); - SSYM(snes_set_controller_port_device); - SSYM(snes_serialize_size); - SSYM(snes_serialize); - SSYM(snes_unserialize); - SSYM(snes_set_cartridge_basename); - SSYM(snes_get_memory_data); - SSYM(snes_get_memory_size); - SSYM(snes_unload_cartridge); - SSYM(snes_term); -} #endif + SYM(retro_init); + SYM(retro_deinit); + + SYM(retro_api_version); + SYM(retro_get_system_info); + SYM(retro_get_system_av_info); + + SYM(retro_set_environment); + SYM(retro_set_video_refresh); + SYM(retro_set_audio_sample); + SYM(retro_set_audio_sample_batch); + SYM(retro_set_input_poll); + SYM(retro_set_input_state); + + SYM(retro_set_controller_port_device); + + SYM(retro_reset); + SYM(retro_run); + + SYM(retro_serialize_size); + SYM(retro_serialize); + SYM(retro_unserialize); + + SYM(retro_cheat_reset); + SYM(retro_cheat_set); + + SYM(retro_load_game); + SYM(retro_load_game_special); + + SYM(retro_unload_game); + SYM(retro_get_region); + SYM(retro_get_memory_data); + SYM(retro_get_memory_size); +} + void init_libsnes_sym(void) { // Guarantee that we can do "dirty" casting. @@ -200,7 +147,7 @@ void init_libsnes_sym(void) #ifdef HAVE_DYNAMIC // Try to verify that -lsnes was not linked in from other modules // since loading it dynamically and with -l will fail hard. - function_t sym = dylib_proc(NULL, "snes_init"); + function_t sym = dylib_proc(NULL, "retro_init"); if (sym) { SSNES_ERR("Serious problem. SSNES wants to load libsnes dyamically, but it is already linked.\n"); @@ -212,23 +159,19 @@ void init_libsnes_sym(void) if (!*g_settings.libsnes) { #if defined(_WIN32) - strlcpy(g_settings.libsnes, "snes.dll", sizeof(g_settings.libsnes)); + strlcpy(g_settings.libsnes, "retro.dll", sizeof(g_settings.libsnes)); #elif defined(__APPLE__) - strlcpy(g_settings.libsnes, "libsnes.dylib", sizeof(g_settings.libsnes)); + strlcpy(g_settings.libsnes, "libretro.dylib", sizeof(g_settings.libsnes)); #else - strlcpy(g_settings.libsnes, "libsnes.so", sizeof(g_settings.libsnes)); + strlcpy(g_settings.libsnes, "libretro.so", sizeof(g_settings.libsnes)); #endif } - - load_dynamic(); -#else - set_statics(); #endif + load_symbols(); + set_environment_defaults(); -#if defined(NEED_DYNAMIC) || defined(SSNES_CONSOLE) set_environment(); -#endif } void uninit_libsnes_sym(void) @@ -289,46 +232,15 @@ void dylib_close(dylib_t lib) } #endif -unsigned audio_sample_batch(const int16_t *, unsigned); - -#if defined(NEED_DYNAMIC) || defined(SSNES_CONSOLE) static bool environment_cb(unsigned cmd, void *data) { switch (cmd) { - case SNES_ENVIRONMENT_GET_FULLPATH: - *(const char**)data = g_extern.system.fullpath; - SSNES_LOG("Environ FULLPATH: \"%s\"\n", g_extern.system.fullpath); - break; - - case SNES_ENVIRONMENT_SET_GEOMETRY: - g_extern.system.geom = *(const struct snes_geometry*)data; - g_extern.system.geom.max_width = next_pow2(g_extern.system.geom.max_width); - g_extern.system.geom.max_height = next_pow2(g_extern.system.geom.max_height); - SSNES_LOG("Environ SET_GEOMETRY: (%ux%u) / (%ux%u)\n", - g_extern.system.geom.base_width, - g_extern.system.geom.base_height, - g_extern.system.geom.max_width, - g_extern.system.geom.max_height); - break; - - case SNES_ENVIRONMENT_SET_PITCH: - g_extern.system.pitch = *(const unsigned*)data; - SSNES_LOG("Environ SET_PITCH: %u\n", g_extern.system.pitch); - break; - case SNES_ENVIRONMENT_GET_OVERSCAN: *(bool*)data = !g_settings.video.crop_overscan; SSNES_LOG("Environ GET_OVERSCAN: %u\n", (unsigned)!g_settings.video.crop_overscan); break; - case SNES_ENVIRONMENT_SET_TIMING: - g_extern.system.timing = *(const struct snes_system_timing*)data; - g_extern.system.timing_set = true; - SSNES_LOG("Environ SET_TIMING: %.3f Hz/ %.3f Hz\n", - (float)g_extern.system.timing.fps, (float)g_extern.system.timing.sample_rate); - break; - case SNES_ENVIRONMENT_GET_CAN_DUPE: #ifdef HAVE_FFMPEG *(bool*)data = true; @@ -339,16 +251,6 @@ static bool environment_cb(unsigned cmd, void *data) #endif break; - case SNES_ENVIRONMENT_SET_NEED_FULLPATH: - g_extern.system.need_fullpath = *(const bool*)data; - SSNES_LOG("Environ SET_NEED_FULLPATH: %s\n", g_extern.system.need_fullpath ? "true" : "false"); - break; - - case SNES_ENVIRONMENT_GET_CAN_REWIND: - *(bool*)data = g_settings.rewind_enable; - SSNES_LOG("Environ GET_CAN_REWIND: %s\n", g_settings.rewind_enable ? "true" : "false"); - break; - case SNES_ENVIRONMENT_GET_VARIABLE: { struct snes_variable *var = (struct snes_variable*)data; @@ -393,16 +295,6 @@ static bool environment_cb(unsigned cmd, void *data) break; } -#ifdef SSNES_CONSOLE - case SNES_ENVIRONMENT_SET_BATCH_LOAD: - g_console.block_zip_extract = *(const bool*)data; - break; - - case SNES_ENVIRONMENT_SET_ROM_FORMATS: - ssnes_console_set_rom_ext((const char*)data); - break; -#endif - case SNES_ENVIRONMENT_SET_MESSAGE: { const struct snes_message *msg = (const struct snes_message*)data; @@ -412,11 +304,6 @@ static bool environment_cb(unsigned cmd, void *data) break; } - case SNES_ENVIRONMENT_GET_AUDIO_BATCH_CB: - SSNES_LOG("Environ GET_AUDIO_BATCH_CB\n"); - *(snes_audio_sample_batch_t*)data = audio_sample_batch; - break; - case SNES_ENVIRONMENT_SET_ROTATION: { unsigned rotation = *(const unsigned*)data; @@ -436,11 +323,6 @@ static bool environment_cb(unsigned cmd, void *data) break; } - case SNES_ENVIRONMENT_SET_CORE_VERSION: - strlcpy(g_extern.system.version, (const char*)data, sizeof(g_extern.system.version)); - SSNES_LOG("Environ SET_CORE_VERSION: %s\n", g_extern.system.version); - break; - default: SSNES_LOG("Environ UNSUPPORTED (#%u).\n", cmd); return false; @@ -450,40 +332,14 @@ static bool environment_cb(unsigned cmd, void *data) } #endif -#ifdef NEED_DYNAMIC -// SSNES extension hooks. Totally optional 'n shizz :) static void set_environment(void) { -#ifdef HAVE_DYNAMIC - dylib_t lib = lib_handle; -#else - dylib_t lib = NULL; -#endif - - void (*psnes_set_environment)(snes_environment_t) = - (void (*)(snes_environment_t))dylib_proc(lib, "snes_set_environment"); - - if (psnes_set_environment) - psnes_set_environment(environment_cb); + pretro_set_environment(environment_cb); } -#elif defined(SSNES_CONSOLE) -// Not very optional when we're running on a console without dynamic loading support. -static void set_environment(void) -{ - snes_set_environment(environment_cb); -} -#endif // Assume SNES as defaults. static void set_environment_defaults(void) { - SSNES_LOG("Setting environment defaults (SNES)\n"); - g_extern.system.pitch = 0; // 0 is classic libsnes semantics. - g_extern.system.geom.base_width = 256; - g_extern.system.geom.base_height = 224; - g_extern.system.geom.max_width = 512; - g_extern.system.geom.max_height = 512; - // Split up environment variables beforehand. if (g_extern.system.environment_split && strtok(g_extern.system.environment_split, ";")) while (strtok(NULL, ";")); diff --git a/dynamic.h b/dynamic.h index 92310260cc..32b2905d04 100644 --- a/dynamic.h +++ b/dynamic.h @@ -19,7 +19,7 @@ #define __DYNAMIC_H #include "boolean.h" -#include "libsnes.hpp" +#include "libretro.h" #ifdef HAVE_CONFIG_H #include "config.h" @@ -31,8 +31,8 @@ #undef NEED_DYNAMIC #endif -void init_libsnes_sym(void); -void uninit_libsnes_sym(void); +void init_libretro_sym(void); +void uninit_libretro_sym(void); typedef void *dylib_t; #ifdef NEED_DYNAMIC @@ -43,53 +43,42 @@ void dylib_close(dylib_t lib); function_t dylib_proc(dylib_t lib, const char *proc); #endif -extern void (*psnes_init)(void); +extern void (*pretro_init)(void); +extern void (*pretro_deinit)(void); -extern void (*psnes_set_video_refresh)(snes_video_refresh_t); -extern void (*psnes_set_audio_sample)(snes_audio_sample_t); -extern void (*psnes_set_input_poll)(snes_input_poll_t); -extern void (*psnes_set_input_state)(snes_input_state_t); +extern unsigned (*pretro_api_version)(void); -extern void (*psnes_cheat_reset)(void); -extern void (*psnes_cheat_set)(unsigned, bool, const char*); +extern void (*pretro_get_system_info)(struct retro_system_info*); +extern void (*pretro_get_system_av_info)(struct retro_system_av_info*); -extern const char *(*psnes_library_id)(void); -extern unsigned (*psnes_library_revision_minor)(void); -extern unsigned (*psnes_library_revision_major)(void); +extern void (*pretro_set_environment)(retro_environment_t); +extern void (*pretro_set_video_refresh)(retro_video_refresh_t); +extern void (*pretro_set_audio_sample)(retro_audio_sample_t); +extern void (*pretro_set_audio_sample_batch)(retro_audio_sample_batch_t); +extern void (*pretro_set_input_poll)(retro_input_poll_t); +extern void (*pretro_set_input_state)(retro_input_state_t); -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 bool (*psnes_load_cartridge_bsx)( - const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned); -extern bool (*psnes_load_cartridge_bsx_slotted)( - const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned); -extern bool (*psnes_load_cartridge_sufami_turbo)( - const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned, - const char*, const uint8_t*, unsigned); +extern void (*pretro_set_controller_port_device)(bool, unsigned); -extern void (*psnes_set_controller_port_device)(bool, unsigned); +extern void (*pretro_reset)(void); +extern void (*pretro_run)(void); -extern bool (*psnes_get_region)(void); +extern size_t (*pretro_serialize_size)(void); +extern bool (*pretro_serialize)(void*, size_t); +extern bool (*pretro_unserialize)(const void*, size_t); -extern unsigned (*psnes_serialize_size)(void); -extern bool (*psnes_serialize)(uint8_t*, unsigned); -extern bool (*psnes_unserialize)(const uint8_t*, unsigned); +extern void (*pretro_cheat_reset)(void); +extern void (*pretro_cheat_set)(unsigned, bool, const char*); -extern void (*psnes_reset)(void); -extern void (*psnes_run)(void); +extern bool (*pretro_load_game)(const struct retro_game_info*); +extern bool (*pretro_load_game_special)(unsigned, const struct retro_game_info*, size_t); -extern void (*psnes_set_cartridge_basename)(const char*); +extern void (*pretro_unload_game)(void); -extern uint8_t* (*psnes_get_memory_data)(unsigned); -extern unsigned (*psnes_get_memory_size)(unsigned); +extern unsigned (*pretro_get_region)(void); -extern void (*psnes_unload_cartridge)(void); -extern void (*psnes_term)(void); +extern void *(*pretro_get_memory_data)(unsigned); +extern size_t (*pretro_get_memory_size)(unsigned); #endif diff --git a/general.h b/general.h index 4af0e4eae6..6f566ede51 100644 --- a/general.h +++ b/general.h @@ -298,18 +298,16 @@ struct global struct { - struct snes_geometry geom; - unsigned pitch; // If 0, has classic libsnes semantics. + struct retro_game_geometry geom; + struct retro_system_timing timing; + struct retro_system_info info; + char fullpath[PATH_MAX]; - struct snes_system_timing timing; - bool timing_set; - bool need_fullpath; char *environment; char *environment_split; unsigned rotation; - char version[64]; } system; struct @@ -416,9 +414,10 @@ struct global struct { - const uint16_t *data; + const void *data; unsigned width; unsigned height; + size_t pitch; } frame_cache; char title_buf[64]; diff --git a/libretro.h b/libretro.h index 1dcf765e49..32f56c4391 100755 --- a/libretro.h +++ b/libretro.h @@ -19,6 +19,7 @@ extern "C" { #define RETRO_DEVICE_KEYBOARD 3 #define RETRO_DEVICE_LIGHTGUN 4 +#define RETRO_DEVICE_JOYPAD_MULTITAP ((1 << 8) | RETRO_DEVICE_JOYPAD) #define RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE ((1 << 8) | RETRO_DEVICE_LIGHTGUN) #define RETRO_DEVICE_LIGHTGUN_JUSTIFIER ((2 << 8) | RETRO_DEVICE_LIGHTGUN) #define RETRO_DEVICE_LIGHTGUN_JUSTIFIERS ((3 << 8) | RETRO_DEVICE_LIGHTGUN) @@ -51,9 +52,9 @@ extern "C" { #define RETRO_REGION_NTSC 0 #define RETRO_REGION_PAL 1 -#define RETRO_MEMORY_SAVE_RAM 0 -#define RETRO_MEMORY_RTC 1 -#define RETRO_MEMORY_SYSTEM_RAM 2 +#define RETRO_MEMORY_SAVE_RAM 0 +#define RETRO_MEMORY_RTC 1 +#define RETRO_MEMORY_SYSTEM_RAM 2 #define RETRO_MEMORY_SNES_BSX_RAM 0x100 #define RETRO_MEMORY_SNES_BSX_PRAM 0x101 @@ -62,52 +63,45 @@ extern "C" { #define RETRO_MEMORY_SNES_GAME_BOY_RAM 0x104 #define RETRO_MEMORY_SNES_GAME_BOY_RTC 0x105 -#define RETRO_GAME_TYPE_BSX 0x100 -#define RETRO_GAME_TYPE_BSX_SLOTTED 0x101 -#define RETRO_GAME_TYPE_SUFAMI_TURBO 0x102 -#define RETRO_GAME_TYPE_SUPER_GAME_BOY 0x103 +#define RETRO_GAME_TYPE_BSX 0x100 +#define RETRO_GAME_TYPE_BSX_SLOTTED 0x101 +#define RETRO_GAME_TYPE_SUFAMI_TURBO 0x102 +#define RETRO_GAME_TYPE_SUPER_GAME_BOY 0x103 // Environment commands. -#define RETRO_ENVIRONMENT_SET_GEOMETRY 1 // const struct retro_geometry * -- - // Window geometry information for the system/game. - // -#define RETRO_ENVIRONMENT_SET_TIMING 2 // const struct retro_system_timing * -- - // Set exact timings of the system. Used primarily for video recording. - // -#define RETRO_ENVIRONMENT_SET_ROTATION 3 // const unsigned * -- +#define RETRO_ENVIRONMENT_SET_ROTATION 1 // const unsigned * -- // Sets screen rotation of graphics. // Is only implemented if rotation can be accelerated by hardware. // Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, 270 degrees // counter-clockwise respectively. // -#define RETRO_ENVIRONMENT_GET_OVERSCAN 4 // bool * -- - // Boolean value whether or not the implementation should use overscan. +#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 // bool * -- + // Boolean value whether or not the implementation should use overscan, or crop away overscan. // -#define RETRO_ENVIRONMENT_GET_CAN_DUPE 5 // bool * -- +#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 // bool * -- // Boolean value whether or not SSNES supports frame duping, // passing NULL to video frame callback. // - // -#define RETRO_ENVIRONMENT_GET_VARIABLE 6 // struct retro_variable * -- +#define RETRO_ENVIRONMENT_GET_VARIABLE 4 // struct retro_variable * -- // Interface to aquire user-defined information from environment // that cannot feasibly be supported in a multi-system way. // Mostly used for obscure, // specific features that the user can tap into when neseccary. // -#define RETRO_ENVIRONMENT_SET_VARIABLES 7 // const struct retro_variable * -- +#define RETRO_ENVIRONMENT_SET_VARIABLES 5 // const struct retro_variable * -- // Allows an implementation to signal the environment // which variables it might want to check for later using GET_VARIABLE. // 'data' points to an array of retro_variable structs terminated by a { NULL, NULL } element. // retro_variable::value should contain a human readable description of the key. // -#define RETRO_ENVIRONMENT_SET_MESSAGE 8 // const struct retro_message * -- +#define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * -- // Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'. struct retro_message { const char *msg; - unsigned frames; + unsigned frames; }; struct retro_system_info @@ -115,7 +109,27 @@ struct retro_system_info const char *library_name; const char *library_version; const char *valid_extensions; - bool need_fullpath; + bool need_fullpath; +}; + +struct retro_game_geometry +{ + unsigned base_width; // Nominal video width of game. + unsigned base_height; // Nominal video height of game. + unsigned max_width; // Maximum possible width of game. + unsigned max_height; // Maximum possible height of game. +}; + +struct retro_system_timing +{ + double fps; // FPS of video content. + double sample_rate; // Sampling rate of audio. +}; + +struct retro_system_av_info +{ + struct retro_game_geometry geometry; + struct retro_system_timing timing; }; struct retro_variable @@ -127,26 +141,13 @@ struct retro_variable const char *value; // Value to be obtained. If key does not exist, it is set to NULL. }; -struct retro_game_geometry -{ - unsigned base_width; // Nominal video width of system. - unsigned base_height; // Nominal video height of system. - unsigned max_width; // Maximum possible width of system. - unsigned max_height; // Maximum possible height of system. -}; - struct retro_game_info { - const char *path; - const void *game_data; - size_t game_size; - const char *game_meta; -}; - -struct retro_system_timing -{ - double fps; - double sample_rate; + const char *path; // Path to game. Usually used as a reference. + const void *data; // Memory buffer of loaded game. If the game is too big to load in one go. SET_NEED_FULLPATH should be used. + // In this case, data and size will be 0, and game can be loaded from path. + size_t size; // Size of memory buffer. + const char *meta; // String of implementation specific meta-data. }; typedef bool (*retro_environment_t)(unsigned cmd, void *data); @@ -157,9 +158,13 @@ typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, size_t frames) typedef void (*retro_input_poll_t)(void); typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); +void retro_init(void); +void retro_deinit(void); + unsigned retro_api_version(void); void retro_get_system_info(struct retro_system_info *info); +void retro_get_system_av_info(struct retro_system_av_info *info); void retro_set_environment(retro_environment_t); void retro_set_video_refresh(retro_video_refresh_t); @@ -170,9 +175,6 @@ void retro_set_input_state(retro_input_state_t); void retro_set_controller_port_device(unsigned port, unsigned device); -void retro_init(void); -void retro_deinit(void); - void retro_reset(void); void retro_run(void); @@ -183,10 +185,7 @@ bool retro_unserialize(const void *data, size_t size); void retro_cheat_reset(void); void retro_cheat_set(unsigned index, bool enabled, const char *code); -bool retro_load_game(const char *game_path, - const void *game_data, size_t game_size, - const char *game_meta -); +bool retro_load_game(const struct retro_game_info *game); bool retro_load_game_special( unsigned game_type, diff --git a/netplay.h b/netplay.h index 96d6a85a62..ae3be470e5 100644 --- a/netplay.h +++ b/netplay.h @@ -20,30 +20,33 @@ #define __SSNES_NETPLAY_H #include +#include #include "boolean.h" -#include "libsnes.hpp" +#include "libretro.h" void input_poll_net(void); -int16_t input_state_net(bool port, unsigned device, unsigned index, unsigned id); -void video_frame_net(const uint16_t *data, unsigned width, unsigned height); -void audio_sample_net(uint16_t left, uint16_t right); +int16_t input_state_net(unsigned port, unsigned device, unsigned index, unsigned id); +void video_frame_net(const uint16_t *data, unsigned width, unsigned height, size_t pitch); +void audio_sample_net(int16_t left, int16_t right); +void audio_sample_batch_net(const int16_t *data, size_t frames); -int16_t input_state_spectate(bool port, unsigned device, unsigned index, unsigned id); -int16_t input_state_spectate_client(bool port, unsigned device, unsigned index, unsigned id); +int16_t input_state_spectate(unsigned port, unsigned device, unsigned index, unsigned id); +int16_t input_state_spectate_client(unsigned port, unsigned device, unsigned index, unsigned id); typedef struct netplay netplay_t; -struct snes_callbacks +struct retro_callbacks { - snes_video_refresh_t frame_cb; - snes_audio_sample_t sample_cb; - snes_input_state_t state_cb; + retro_video_refresh_t frame_cb; + retro_audio_sample_t sample_cb; + retro_audio_sample_batch_t sample_batch_cb; + retro_input_state_t state_cb; }; // Creates a new netplay handle. A NULL host means we're hosting (player 1). :) netplay_t *netplay_new(const char *server, uint16_t port, unsigned frames, - const struct snes_callbacks *cb, bool spectate, + const struct retro_callbacks *cb, bool spectate, const char *nick); void netplay_free(netplay_t *handle); diff --git a/ssnes.c b/ssnes.c index 4994f2c0cc..e91904ee09 100644 --- a/ssnes.c +++ b/ssnes.c @@ -16,7 +16,7 @@ */ #include "boolean.h" -#include "libsnes.hpp" +#include "libretro.h" #include #include #include @@ -88,14 +88,6 @@ static void set_fast_forward_button(bool new_button_state, bool new_hold_button_ old_hold_button_state = new_hold_button_state; } -static inline unsigned lines_to_pitch(unsigned height) -{ - if (g_extern.system.pitch == 0) // SNES semantics - return ((height == 448) || (height == 478)) ? 1024 : 2048; - else - return g_extern.system.pitch; -} - #ifdef HAVE_SCREENSHOTS static void take_screenshot(void) { @@ -108,10 +100,10 @@ static void take_screenshot(void) const uint16_t *data = g_extern.frame_cache.data; unsigned width = g_extern.frame_cache.width; unsigned height = g_extern.frame_cache.height; + size_t pitch = g_extern.frame_cache.pitch; ret = screenshot_dump(g_settings.screenshot_directory, data, - width, height, - lines_to_pitch(height)); + width, height, pitch); } const char *msg = NULL; @@ -138,27 +130,6 @@ static void take_screenshot(void) } #endif -#ifndef SSNES_CONSOLE -static inline void adjust_crop(const uint16_t **data, unsigned *height) -{ - // Rather SNES specific. - unsigned pixel_pitch = lines_to_pitch(*height) >> 1; - if (g_settings.video.crop_overscan) - { - if (*height == 239) - { - *data += 7 * pixel_pitch; // Skip 7 top scanlines. - *height = 224; - } - else if (*height == 478) - { - *data += 15 * pixel_pitch; // Skip 15 top scanlines. - *height = 448; - } - } -} -#endif - static void readjust_audio_input_rate(void) { int avail = audio_write_avail_func(); @@ -177,15 +148,11 @@ static void readjust_audio_input_rate(void) // g_extern.audio_data.src_ratio, g_extern.audio_data.orig_src_ratio); } -// libsnes: 0.065 -// Format received is 16-bit 0RRRRRGGGGGBBBBB -static void video_frame(const uint16_t *data, unsigned width, unsigned height) +static void video_frame(const void *data, unsigned width, unsigned height, size_t pitch) { #ifndef SSNES_CONSOLE if (!g_extern.video_active) return; - - adjust_crop(&data, &height); #endif // Slightly messy code, @@ -197,7 +164,7 @@ static void video_frame(const uint16_t *data, unsigned width, unsigned height) { struct ffemu_video_data ffemu_data = {0}; ffemu_data.data = data; - ffemu_data.pitch = lines_to_pitch(height); + ffemu_data.pitch = pitch; ffemu_data.width = width; ffemu_data.height = height; ffemu_data.is_dupe = is_dupe; @@ -217,7 +184,7 @@ static void video_frame(const uint16_t *data, unsigned width, unsigned height) unsigned oheight = height; g_extern.filter.psize(&owidth, &oheight); g_extern.filter.prender(g_extern.filter.colormap, g_extern.filter.buffer, - g_extern.filter.pitch, data, lines_to_pitch(height), width, height); + g_extern.filter.pitch, data, pitch, width, height); #ifdef HAVE_FFMPEG if (g_extern.recording && g_settings.video.post_filter_record) @@ -234,16 +201,17 @@ static void video_frame(const uint16_t *data, unsigned width, unsigned height) if (!video_frame_func(g_extern.filter.buffer, owidth, oheight, g_extern.filter.pitch, msg)) g_extern.video_active = false; } - else if (!video_frame_func(data, width, height, lines_to_pitch(height), msg)) + else if (!video_frame_func(data, width, height, pitch, msg)) g_extern.video_active = false; #else - if (!video_frame_func(data, width, height, lines_to_pitch(height), msg)) + if (!video_frame_func(data, width, height, pitch, msg)) g_extern.video_active = false; #endif g_extern.frame_cache.data = data; g_extern.frame_cache.width = width; g_extern.frame_cache.height = height; + g_extern.frame_cache.pitch = pitch; } #ifdef HAVE_GRIFFIN @@ -266,7 +234,8 @@ void ssnes_render_cached_frame(void) { video_frame(g_extern.frame_cache.data, g_extern.frame_cache.width, - g_extern.frame_cache.height); + g_extern.frame_cache.height, + g_extern.frame_cache.pitch); } #ifdef HAVE_FFMPEG @@ -1018,17 +987,17 @@ static void init_controllers(void) if (g_extern.has_justifier) { SSNES_LOG("Connecting Justifier to port 2.\n"); - psnes_set_controller_port_device(SNES_PORT_2, SNES_DEVICE_JUSTIFIER); + pretro_set_controller_port_device(1, RETRO_DEVICE_LIGHTGUN_JUSTIFIER); } else if (g_extern.has_justifiers) { SSNES_LOG("Connecting Justifiers to port 2.\n"); - psnes_set_controller_port_device(SNES_PORT_2, SNES_DEVICE_JUSTIFIERS); + pretro_set_controller_port_device(1, RETRO_DEVICE_LIGHTGUN_JUSTIFIERS); } else if (g_extern.has_multitap) { SSNES_LOG("Connecting Multitap to port 2.\n"); - psnes_set_controller_port_device(SNES_PORT_2, SNES_DEVICE_MULTITAP); + pretro_set_controller_port_device(1, RETRO_DEVICE_JOYPAD_MULTITAP); } else { @@ -1037,17 +1006,17 @@ static void init_controllers(void) if (g_extern.disconnect_device[i]) { SSNES_LOG("Disconnecting device from port %u.\n", i + 1); - psnes_set_controller_port_device(i, SNES_DEVICE_NONE); + pretro_set_controller_port_device(i, RETRO_DEVICE_NONE); } else if (g_extern.has_mouse[i]) { SSNES_LOG("Connecting mouse to port %u.\n", i + 1); - psnes_set_controller_port_device(i, SNES_DEVICE_MOUSE); + pretro_set_controller_port_device(i, RETRO_DEVICE_MOUSE); } else if (g_extern.has_scope[i]) { SSNES_LOG("Connecting scope to port %u.\n", i + 1); - psnes_set_controller_port_device(i, SNES_DEVICE_SUPER_SCOPE); + pretro_set_controller_port_device(i, RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE); } } }