libretro fixups.

This commit is contained in:
Themaister 2012-04-07 11:55:37 +02:00
parent cb3a65a358
commit 5d51942f69
15 changed files with 427 additions and 525 deletions

View file

@ -23,7 +23,7 @@
#define __CONFIG_DEF_H
#include "boolean.h"
#include "libsnes.hpp"
#include "libretro.h"
#include "driver.h"
#ifdef HAVE_CONFIG_H
@ -293,18 +293,18 @@ static const float axis_threshold = 0.5;
// Player 1
static const struct snes_keybind snes_keybinds_1[] = {
// SNES button | keyboard key | js btn | js axis |
{ true, SNES_DEVICE_ID_JOYPAD_B, SK_z, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_Y, SK_a, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_SELECT, SK_RSHIFT, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_START, SK_RETURN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_UP, SK_UP, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_DOWN, SK_DOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_LEFT, SK_LEFT, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_RIGHT, SK_RIGHT, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_A, SK_x, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_X, SK_s, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_L, SK_q, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_R, SK_w, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_B, SK_z, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_Y, SK_a, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_SELECT, SK_RSHIFT, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_START, SK_RETURN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_UP, SK_UP, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_DOWN, SK_DOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_LEFT, SK_LEFT, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_RIGHT, SK_RIGHT, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_A, SK_x, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_X, SK_s, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_L, SK_q, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_R, SK_w, NO_BTN, AXIS_NONE },
{ true, SSNES_FAST_FORWARD_KEY, SK_SPACE, NO_BTN, AXIS_NONE },
{ true, SSNES_FAST_FORWARD_HOLD_KEY, SK_l, NO_BTN, AXIS_NONE },
@ -335,18 +335,18 @@ static const struct snes_keybind snes_keybinds_1[] = {
// Player 2-5
static const struct snes_keybind snes_keybinds_rest[] = {
{ true, SNES_DEVICE_ID_JOYPAD_B, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_Y, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_SELECT, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_START, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_UP, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_DOWN, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_LEFT, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_RIGHT, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_A, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_X, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_L, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_R, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_B, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_Y, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_SELECT, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_START, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_UP, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_DOWN, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_LEFT, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_RIGHT, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_A, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_X, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_L, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_R, SK_UNKNOWN, NO_BTN, AXIS_NONE },
};
#endif

View file

@ -265,29 +265,20 @@ static void deinit_dsp_plugin(void)
static void adjust_audio_input_rate(void)
{
if (g_extern.system.timing_set)
{
float timing_skew = fabs(1.0f - g_extern.system.timing.fps / g_settings.video.refresh_rate);
if (timing_skew > 0.05f) // We don't want to adjust pitch too much. If we have extreme cases, just don't readjust at all.
{
SSNES_LOG("Timings deviate too much. Will not adjust. (Display = %.2f Hz, Game = %.2f Hz)\n",
g_settings.video.refresh_rate,
(float)g_extern.system.timing.fps);
const struct retro_system_timing *info = &g_extern.system.av_info.timing;
g_settings.video.refresh_rate = g_extern.system.timing.fps;
}
float timing_skew = fabs(1.0f - info->fps / g_settings.video.refresh_rate);
if (timing_skew > 0.05f) // We don't want to adjust pitch too much. If we have extreme cases, just don't readjust at all.
{
SSNES_LOG("Timings deviate too much. Will not adjust. (Display = %.2f Hz, Game = %.2f Hz)\n",
g_settings.video.refresh_rate,
(float)info->fps);
g_settings.video.refresh_rate = info->fps;
}
if (g_extern.system.timing_set)
{
g_settings.audio.in_rate = g_extern.system.timing.sample_rate *
(g_settings.video.refresh_rate / g_extern.system.timing.fps);
}
else
{
g_settings.audio.in_rate = 32040.5 *
(g_settings.video.refresh_rate / (21477272.0 / 357366.0)); // SNES metrics.
}
g_settings.audio.in_rate = info->sample_rate *
(g_settings.video.refresh_rate / info->fps);
SSNES_LOG("Set audio input rate to: %.2f Hz.\n", g_settings.audio.in_rate);
}
@ -426,8 +417,9 @@ static void init_filter(void)
g_extern.filter.active = true;
unsigned width = g_extern.system.geom.max_width;
unsigned height = g_extern.system.geom.max_height;
struct retro_game_geometry *geom = &g_extern.system.av_info.geometry;
unsigned width = geom->max_width;
unsigned height = geom->max_height;
g_extern.filter.psize(&width, &height);
unsigned pow2_x = next_pow2(width);
@ -508,7 +500,8 @@ void init_video_input(void)
init_shader_dir();
#endif
unsigned max_dim = max(g_extern.system.geom.max_width, g_extern.system.geom.max_height);
struct retro_game_geometry *geom = &g_extern.system.av_info.geometry;
unsigned max_dim = max(geom->max_width, geom->max_height);
unsigned scale = max_dim / SSNES_SCALE_BASE;
scale = max(scale, 1);
@ -526,19 +519,19 @@ void init_video_input(void)
{
if (g_settings.video.force_aspect && (g_settings.video.aspect_ratio > 0.0f))
{
width = roundf(g_extern.system.geom.base_height * g_settings.video.xscale * g_settings.video.aspect_ratio);
height = roundf(g_extern.system.geom.base_height * g_settings.video.yscale);
width = roundf(geom->base_height * g_settings.video.xscale * g_settings.video.aspect_ratio);
height = roundf(geom->base_height * g_settings.video.yscale);
}
else
{
width = roundf(g_extern.system.geom.base_width * g_settings.video.xscale);
height = roundf(g_extern.system.geom.base_height * g_settings.video.yscale);
width = roundf(geom->base_width * g_settings.video.xscale);
height = roundf(geom->base_height * g_settings.video.yscale);
}
}
if (g_settings.video.aspect_ratio < 0.0f)
{
g_settings.video.aspect_ratio = (float)g_extern.system.geom.base_width / g_extern.system.geom.base_height;
g_settings.video.aspect_ratio = (float)geom->base_width / geom->base_height;
SSNES_LOG("Adjusting aspect ratio to %.2f\n", g_settings.video.aspect_ratio);
}

View file

@ -29,7 +29,7 @@
#endif
#include "boolean.h"
#include "libsnes.hpp"
#include "libretro.h"
#ifdef NEED_DYNAMIC
#ifdef _WIN32
@ -41,7 +41,7 @@
#ifdef HAVE_DYNAMIC
#define SYM(x) do { \
function_t func = dylib_proc(lib, #x); \
function_t func = dylib_proc(lib_handle, #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)
@ -78,8 +78,8 @@ bool (*pretro_unserialize)(const void*, size_t);
void (*pretro_cheat_reset)(void);
void (*pretro_cheat_set)(unsigned, bool, const char*);
bool (*pretro_load_game)(const retro_game_info*);
bool (*pretro_load_game_special)(unsigned, const retro_game_info*, size_t);
bool (*pretro_load_game)(const struct retro_game_info*);
bool (*pretro_load_game_special)(unsigned, const struct retro_game_info*, size_t);
void (*pretro_unload_game)(void);
@ -236,12 +236,12 @@ static bool environment_cb(unsigned cmd, void *data)
{
switch (cmd)
{
case SNES_ENVIRONMENT_GET_OVERSCAN:
case RETRO_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_GET_CAN_DUPE:
case RETRO_ENVIRONMENT_GET_CAN_DUPE:
#ifdef HAVE_FFMPEG
*(bool*)data = true;
SSNES_LOG("Environ GET_CAN_DUPE: true\n");
@ -251,9 +251,9 @@ static bool environment_cb(unsigned cmd, void *data)
#endif
break;
case SNES_ENVIRONMENT_GET_VARIABLE:
case RETRO_ENVIRONMENT_GET_VARIABLE:
{
struct snes_variable *var = (struct snes_variable*)data;
struct retro_variable *var = (struct retro_variable*)data;
if (var->key)
{
// Split string has '\0' delimiters so we have to find the position in original string,
@ -278,11 +278,11 @@ static bool environment_cb(unsigned cmd, void *data)
break;
}
case SNES_ENVIRONMENT_SET_VARIABLES:
case RETRO_ENVIRONMENT_SET_VARIABLES:
{
SSNES_LOG("Environ SET_VARIABLES:\n");
SSNES_LOG("=======================\n");
const struct snes_variable *vars = (const struct snes_variable*)data;
const struct retro_variable *vars = (const struct retro_variable*)data;
while (vars->key)
{
SSNES_LOG("\t%s :: %s\n",
@ -295,16 +295,16 @@ static bool environment_cb(unsigned cmd, void *data)
break;
}
case SNES_ENVIRONMENT_SET_MESSAGE:
case RETRO_ENVIRONMENT_SET_MESSAGE:
{
const struct snes_message *msg = (const struct snes_message*)data;
const struct retro_message *msg = (const struct retro_message*)data;
SSNES_LOG("Environ SET_MESSAGE: %s\n", msg->msg);
if (g_extern.msg_queue)
msg_queue_push(g_extern.msg_queue, msg->msg, 1, msg->frames);
break;
}
case SNES_ENVIRONMENT_SET_ROTATION:
case RETRO_ENVIRONMENT_SET_ROTATION:
{
unsigned rotation = *(const unsigned*)data;
SSNES_LOG("Environ SET_ROTATION: %u\n", rotation);
@ -330,7 +330,6 @@ static bool environment_cb(unsigned cmd, void *data)
return true;
}
#endif
static void set_environment(void)
{

338
file.c
View file

@ -19,7 +19,7 @@
#include "general.h"
#include <stdlib.h>
#include "boolean.h"
#include "libsnes.hpp"
#include "libretro.h"
#include <string.h>
#include <time.h>
#include "dynamic.h"
@ -325,21 +325,21 @@ static const char *ramtype2str(int type)
{
switch (type)
{
case SNES_MEMORY_CARTRIDGE_RAM:
case SNES_MEMORY_GAME_BOY_RAM:
case SNES_MEMORY_BSX_RAM:
case RETRO_MEMORY_SAVE_RAM:
case RETRO_MEMORY_SNES_GAME_BOY_RAM:
case RETRO_MEMORY_SNES_BSX_RAM:
return ".srm";
case SNES_MEMORY_CARTRIDGE_RTC:
case SNES_MEMORY_GAME_BOY_RTC:
case RETRO_MEMORY_RTC:
case RETRO_MEMORY_SNES_GAME_BOY_RTC:
return ".rtc";
case SNES_MEMORY_BSX_PRAM:
case RETRO_MEMORY_SNES_BSX_PRAM:
return ".pram";
case SNES_MEMORY_SUFAMI_TURBO_A_RAM:
case RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM:
return ".aram";
case SNES_MEMORY_SUFAMI_TURBO_B_RAM:
case RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM:
return ".bram";
default:
@ -385,7 +385,7 @@ error:
bool save_state(const char *path)
{
SSNES_LOG("Saving state: \"%s\".\n", path);
size_t size = psnes_serialize_size();
size_t size = pretro_serialize_size();
if (size == 0)
return false;
@ -397,7 +397,7 @@ bool save_state(const char *path)
}
SSNES_LOG("State size: %d bytes.\n", (int)size);
bool ret = psnes_serialize((uint8_t*)data, size);
bool ret = pretro_serialize(data, size);
if (ret)
ret = dump_to_file(path, data, size);
@ -421,11 +421,11 @@ bool load_state(const char *path)
}
bool ret = true;
SSNES_LOG("State size: %d bytes.\n", (int)size);
SSNES_LOG("State size: %u bytes.\n", (unsigned)size);
uint8_t *block_buf[2] = {NULL, NULL};
void *block_buf[2] = {NULL, NULL};
int block_type[2] = {-1, -1};
unsigned block_size[2] = {0};
size_t block_size[2] = {0};
if (g_settings.block_sram_overwrite)
{
@ -433,55 +433,55 @@ bool load_state(const char *path)
switch (g_extern.game_type)
{
case SSNES_CART_NORMAL:
block_type[0] = SNES_MEMORY_CARTRIDGE_RAM;
block_type[1] = SNES_MEMORY_CARTRIDGE_RTC;
block_type[0] = RETRO_MEMORY_SAVE_RAM;
block_type[1] = RETRO_MEMORY_RTC;
break;
case SSNES_CART_BSX:
case SSNES_CART_BSX_SLOTTED:
block_type[0] = SNES_MEMORY_BSX_RAM;
block_type[1] = SNES_MEMORY_BSX_PRAM;
block_type[0] = RETRO_MEMORY_SNES_BSX_RAM;
block_type[1] = RETRO_MEMORY_SNES_BSX_PRAM;
break;
case SSNES_CART_SUFAMI:
block_type[0] = SNES_MEMORY_SUFAMI_TURBO_A_RAM;
block_type[1] = SNES_MEMORY_SUFAMI_TURBO_B_RAM;
block_type[0] = RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM;
block_type[1] = RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM;
break;
case SSNES_CART_SGB:
block_type[0] = SNES_MEMORY_GAME_BOY_RAM;
block_type[1] = SNES_MEMORY_GAME_BOY_RTC;
block_type[0] = RETRO_MEMORY_SNES_GAME_BOY_RAM;
block_type[1] = RETRO_MEMORY_SNES_GAME_BOY_RTC;
break;
}
}
for (unsigned i = 0; i < 2; i++)
if (block_type[i] != -1)
block_size[i] = psnes_get_memory_size(block_type[i]);
block_size[i] = pretro_get_memory_size(block_type[i]);
for (unsigned i = 0; i < 2; i++)
if (block_size[i])
block_buf[i] = (uint8_t*)malloc(block_size[i]);
block_buf[i] = malloc(block_size[i]);
// Backup current SRAM which is overwritten by unserialize.
for (unsigned i = 0; i < 2; i++)
{
if (block_buf[i])
{
const uint8_t *ptr = psnes_get_memory_data(block_type[i]);
const void *ptr = pretro_get_memory_data(block_type[i]);
if (ptr)
memcpy(block_buf[i], ptr, block_size[i]);
}
}
ret = psnes_unserialize((uint8_t*)buf, size);
ret = pretro_unserialize(buf, size);
// Flush back :D
for (unsigned i = 0; i < 2 && ret; i++)
{
if (block_buf[i])
{
uint8_t *ptr = psnes_get_memory_data(block_type[i]);
void *ptr = pretro_get_memory_data(block_type[i]);
if (ptr)
memcpy(ptr, block_buf[i], block_size[i]);
}
@ -497,8 +497,8 @@ bool load_state(const char *path)
void load_ram_file(const char *path, int type)
{
size_t size = psnes_get_memory_size(type);
uint8_t *data = psnes_get_memory_data(type);
size_t size = pretro_get_memory_size(type);
uint8_t *data = pretro_get_memory_data(type);
if (size == 0 || !data)
return;
@ -513,14 +513,14 @@ void load_ram_file(const char *path, int type)
void save_ram_file(const char *path, int type)
{
size_t size = psnes_get_memory_size(type);
uint8_t *data = psnes_get_memory_data(type);
size_t size = pretro_get_memory_size(type);
uint8_t *data = pretro_get_memory_data(type);
if (data && size > 0)
{
if (!dump_to_file(path, data, size))
{
SSNES_ERR("Failed to save SNES RAM.\n");
SSNES_ERR("Failed to save SRAM.\n");
SSNES_WARN("Attempting to recover ...\n");
dump_to_file_desperate(data, size, type);
}
@ -539,190 +539,25 @@ static char *load_xml_map(const char *path)
return xml_buf;
}
static bool load_sgb_rom(void)
{
void *rom_buf = NULL;
ssize_t rom_len = 0;
#define MAX_ROMS 4
FILE *extra_rom = NULL;
void *extra_rom_buf = NULL;
ssize_t extra_rom_len = 0;
char *xml_buf = 0;
static bool load_roms(unsigned rom_type, const char **rom_paths, size_t roms)
{
bool ret = true;
if ((rom_len = read_rom_file(g_extern.rom_file, &rom_buf)) == -1)
if (roms == 0)
return false;
if (roms > MAX_ROMS)
return false;
void *rom_buf[MAX_ROMS] = {NULL};
ssize_t rom_len[MAX_ROMS] = {0};
struct retro_game_info info[MAX_ROMS] = {{NULL}};
if (!g_extern.system.info.need_fullpath)
{
SSNES_ERR("Could not read ROM file.\n");
ret = false;
goto end;
}
if ((extra_rom_len = read_file(g_extern.gb_rom_path, &extra_rom_buf)) == -1)
{
SSNES_ERR("Cannot read GameBoy rom.\n");
ret = false;
goto end;
}
xml_buf = load_xml_map(g_extern.xml_name);
if (!psnes_load_cartridge_super_game_boy(
xml_buf, (const uint8_t*)rom_buf, rom_len,
NULL, (const uint8_t*)extra_rom_buf, extra_rom_len))
{
SSNES_ERR("Cannot load SGB/GameBoy rom.\n");
ret = false;
goto end;
}
if (xml_buf)
free(xml_buf);
end:
if (g_extern.rom_file)
fclose(g_extern.rom_file);
if (extra_rom)
fclose(extra_rom);
free(rom_buf);
free(extra_rom_buf);
return ret;
}
static bool load_bsx_rom(bool slotted)
{
void *rom_buf = NULL;
ssize_t rom_len = 0;
FILE *extra_rom = NULL;
void *extra_rom_buf = NULL;
ssize_t extra_rom_len = 0;
char *xml_buf = 0;
bool ret = true;
if ((rom_len = read_rom_file(g_extern.rom_file, &rom_buf)) == -1)
{
SSNES_ERR("Could not read ROM file.\n");
ret = false;
goto end;
}
if ((extra_rom_len = read_file(g_extern.bsx_rom_path, &extra_rom_buf)) == -1)
{
SSNES_ERR("Cannot read BSX game rom.\n");
ret = false;
goto end;
}
xml_buf = load_xml_map(g_extern.xml_name);
if (slotted)
{
if (!psnes_load_cartridge_bsx_slotted(
xml_buf, (const uint8_t*)rom_buf, rom_len,
NULL, (const uint8_t*)extra_rom_buf, extra_rom_len))
{
SSNES_ERR("Cannot load BSX slotted rom.\n");
ret = false;
goto end;
}
}
else
{
if (!psnes_load_cartridge_bsx(
NULL, (const uint8_t*)rom_buf, rom_len,
NULL, (const uint8_t*)extra_rom_buf, extra_rom_len))
{
SSNES_ERR("Cannot load BSX rom.\n");
ret = false;
goto end;
}
}
if (xml_buf)
free(xml_buf);
end:
if (g_extern.rom_file)
fclose(g_extern.rom_file);
if (extra_rom)
fclose(extra_rom);
free(rom_buf);
free(extra_rom_buf);
return ret;
}
static bool load_sufami_rom(void)
{
void *rom_buf = NULL;
ssize_t rom_len = 0;
FILE *extra_rom[2] = {NULL};
void *extra_rom_buf[2] = {NULL};
ssize_t extra_rom_len[2] = {0};
char *xml_buf = 0;
const char *roms[2] = {0};
bool ret = true;
if ((rom_len = read_rom_file(g_extern.rom_file, &rom_buf)) == -1)
{
SSNES_ERR("Could not read ROM file.\n");
ret = false;
goto end;
}
roms[0] = g_extern.sufami_rom_path[0];
roms[1] = g_extern.sufami_rom_path[1];
for (unsigned i = 0; i < 2; i++)
{
if (*(roms[i]))
{
if ((extra_rom_len[i] = read_file(roms[i], &extra_rom_buf[i])) == -1)
{
SSNES_ERR("Cannot read Sufami game rom.\n");
ret = false;
goto end;
}
}
}
xml_buf = load_xml_map(g_extern.xml_name);
if (!psnes_load_cartridge_sufami_turbo(
xml_buf, (const uint8_t*)rom_buf, rom_len,
NULL, (const uint8_t*)extra_rom_buf[0], extra_rom_len[0],
NULL, (const uint8_t*)extra_rom_buf[1], extra_rom_len[1]))
{
SSNES_ERR("Cannot load Sufami Turbo rom.\n");
ret = false;
goto end;
}
if (xml_buf)
free(xml_buf);
end:
if (g_extern.rom_file)
fclose(g_extern.rom_file);
for (unsigned i = 0; i < 2; i++)
{
if (extra_rom[i])
fclose(extra_rom[i]);
free(extra_rom_buf[i]);
}
free(rom_buf);
return ret;
}
static bool load_normal_rom(void)
{
void *rom_buf = NULL;
ssize_t rom_len = 0;
if (!g_extern.system.need_fullpath)
{
if ((rom_len = read_rom_file(g_extern.rom_file, &rom_buf)) == -1)
if ((rom_len[0] = read_rom_file(g_extern.rom_file, &rom_buf[0])) == -1)
{
SSNES_ERR("Could not read ROM file.\n");
return false;
@ -731,7 +566,7 @@ static bool load_normal_rom(void)
if (g_extern.rom_file)
fclose(g_extern.rom_file);
SSNES_LOG("ROM size: %d bytes\n", (int)rom_len);
SSNES_LOG("ROM size: %u bytes.\n", (unsigned)rom_len[0]);
}
else
{
@ -744,20 +579,81 @@ static bool load_normal_rom(void)
fclose(g_extern.rom_file);
SSNES_LOG("ROM loading skipped. Implementation will load it on its own.\n");
}
char *xml_buf = load_xml_map(g_extern.xml_name);
if (!psnes_load_cartridge_normal(xml_buf, (const uint8_t*)rom_buf, rom_len))
info[0].path = rom_paths[0];
info[0].data = rom_buf[0];
info[0].size = rom_len[0];
info[0].meta = xml_buf;
for (size_t i = 1; i < roms; i++)
{
SSNES_ERR("ROM file is not valid.\n");
free(rom_buf);
free(xml_buf);
return false;
if (rom_paths[i] &&
!g_extern.system.info.need_fullpath &&
(rom_len[i] = read_file(rom_paths[i], &rom_buf[i])) == -1)
{
SSNES_ERR("Could not read ROM file: \"%s\".\n", rom_paths[i]);
ret = false;
goto end;
}
info[i].path = rom_paths[i];
info[i].data = rom_buf[i];
info[i].size = rom_len[i];
}
if (rom_type == 0)
ret = retro_load_game(&info[0]);
else
ret = retro_load_game_special(rom_type, info, roms);
if (!ret)
SSNES_ERR("Failed to load game.\n");
end:
for (unsigned i = 0; i < MAX_ROMS; i++)
free(rom_buf[i]);
free(xml_buf);
free(rom_buf);
return true;
return ret;
}
static bool load_normal_rom(void)
{
const char *path = *g_extern.fullpath ? g_extern.fullpath : NULL;
return load_roms(0, &path, 1);
}
static bool load_sgb_rom(void)
{
const char *path[2] = {
*g_extern.fullpath ? g_extern.fullpath : NULL,
g_extern.gb_rom_path
};
return load_roms(RETRO_GAME_TYPE_SUPER_GAME_BOY, path, 2);
}
static bool load_bsx_rom(bool slotted)
{
const char *path[2] = {
*g_extern.fullpath ? g_extern.fullpath : NULL,
g_extern.bsx_rom_path
};
return load_roms(slotted ? RETRO_GAME_TYPE_BSX_SLOTTED : RETRO_GAME_TYPE_BSX, path, 2);
}
static bool load_sufami_rom(void)
{
const char *path[3] = {
*g_extern.fullpath ? g_extern.fullpath : NULL,
g_extern.sufami_rom_path[0] ? g_extern.sufami_rom_path[0] : NULL,
g_extern.sufami_rom_path[1] ? g_extern.sufami_rom_path[1] : NULL,
};
return load_roms(RETRO_GAME_TYPE_SUFAMI_TURBO, path, 3);
}
bool init_rom_file(enum ssnes_game_type type)

View file

@ -278,6 +278,7 @@ struct global
#endif
char basename[PATH_MAX];
char fullpath[PATH_MAX];
char savefile_name_srm[PATH_MAX];
char savefile_name_rtc[PATH_MAX]; // Make sure that fill_pathname has space.
char savefile_name_psrm[PATH_MAX];
@ -298,11 +299,8 @@ struct global
struct
{
struct retro_game_geometry geom;
struct retro_system_timing timing;
struct retro_system_info info;
char fullpath[PATH_MAX];
struct retro_system_av_info av_info;
char *environment;
char *environment_split;

View file

@ -19,7 +19,7 @@
#include "../driver.h"
#include <stdint.h>
#include "../libsnes.hpp"
#include "../libretro.h"
#include <stdio.h>
#include <string.h>
#include "../general.h"

View file

@ -467,8 +467,9 @@ static void *xv_init(const video_info_t *video, const input_driver_t **input, vo
attributes.border_pixel = 0;
attributes.event_mask = StructureNotifyMask | DestroyNotify | ClientMessage;
width = video->fullscreen ? ((video->width == 0) ? g_extern.system.geom.base_width : video->width) : video->width;
height = video->fullscreen ? ((video->height == 0) ? g_extern.system.geom.base_height : video->height) : video->height;
const struct retro_game_geometry *geom = &g_extern.system.av_info.geometry;
width = video->fullscreen ? ((video->width == 0) ? geom->base_width : video->width) : video->width;
height = video->fullscreen ? ((video->height == 0) ? geom->base_height : video->height) : video->height;
xv->window = XCreateWindow(xv->display, DefaultRootWindow(xv->display),
0, 0, width, height,
0, xv->depth, InputOutput, visualinfo->visual,
@ -492,8 +493,8 @@ static void *xv_init(const video_info_t *video, const input_driver_t **input, vo
atom = XInternAtom(xv->display, "XV_AUTOPAINT_COLORKEY", true);
if (atom != None) XvSetPortAttribute(xv->display, xv->port, atom, 1);
xv->width = g_extern.system.geom.max_width;
xv->height = g_extern.system.geom.max_height;
xv->width = geom->max_width;
xv->height = geom->max_height;
xv->image = XvShmCreateImage(xv->display, xv->port, xv->fourcc, NULL, xv->width, xv->height, &xv->shminfo);
if (!xv->image)

View file

@ -22,7 +22,7 @@
#include "../general.h"
#include <stdint.h>
#include <stdlib.h>
#include "../libsnes.hpp"
#include "../libretro.h"
#include "ssnes_sdl_input.h"
#include "keysym.h"
@ -293,78 +293,51 @@ static int16_t sdl_mouse_device_state(sdl_input_t *sdl, unsigned id)
{
switch (id)
{
case SNES_DEVICE_ID_MOUSE_LEFT:
case RETRO_DEVICE_ID_MOUSE_LEFT:
return sdl->mouse_l;
case SNES_DEVICE_ID_MOUSE_RIGHT:
case RETRO_DEVICE_ID_MOUSE_RIGHT:
return sdl->mouse_r;
case SNES_DEVICE_ID_MOUSE_X:
case RETRO_DEVICE_ID_MOUSE_X:
return sdl->mouse_x;
case SNES_DEVICE_ID_MOUSE_Y:
case RETRO_DEVICE_ID_MOUSE_Y:
return sdl->mouse_y;
default:
return 0;
}
}
// TODO: Missing some controllers, but hey :)
static int16_t sdl_scope_device_state(sdl_input_t *sdl, unsigned id)
static int16_t sdl_lightgun_device_state(sdl_input_t *sdl, unsigned id)
{
switch (id)
{
case SNES_DEVICE_ID_SUPER_SCOPE_X:
case RETRO_DEVICE_ID_LIGHTGUN_X:
return sdl->mouse_x;
case SNES_DEVICE_ID_SUPER_SCOPE_Y:
case RETRO_DEVICE_ID_LIGHTGUN_Y:
return sdl->mouse_y;
case SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER:
case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER:
return sdl->mouse_l;
case SNES_DEVICE_ID_SUPER_SCOPE_CURSOR:
case RETRO_DEVICE_ID_LIGHTGUN_CURSOR:
return sdl->mouse_m;
case SNES_DEVICE_ID_SUPER_SCOPE_TURBO:
case RETRO_DEVICE_ID_LIGHTGUN_TURBO:
return sdl->mouse_r;
default:
return 0;
}
}
// TODO: Support two players.
static int16_t sdl_justifier_device_state(sdl_input_t *sdl, unsigned index, unsigned id)
{
if (index == 0)
{
switch (id)
{
case SNES_DEVICE_ID_JUSTIFIER_X:
return sdl->mouse_x;
case SNES_DEVICE_ID_JUSTIFIER_Y:
return sdl->mouse_y;
case SNES_DEVICE_ID_JUSTIFIER_TRIGGER:
return sdl->mouse_l;
case SNES_DEVICE_ID_JUSTIFIER_START:
return sdl->mouse_r;
default:
return 0;
}
}
else
return 0;
}
static int16_t sdl_input_state(void *data_, const struct snes_keybind **binds, bool port, unsigned device, unsigned index, unsigned id)
{
sdl_input_t *data = (sdl_input_t*)data_;
switch (device)
{
case SNES_DEVICE_JOYPAD:
return sdl_joypad_device_state(data, binds, (port == SNES_PORT_1) ? 0 : 1, id);
case SNES_DEVICE_MULTITAP:
return sdl_joypad_device_state(data, binds, (port == SNES_PORT_2) ? 1 + index : 0, id);
case SNES_DEVICE_MOUSE:
case RETRO_DEVICE_JOYPAD:
return sdl_joypad_device_state(data, binds, port, id);
case RETRO_DEVICE_JOYPAD_MULTITAP:
return sdl_joypad_device_state(data, binds, (port == 1) ? 1 + index : 0, id);
case RETRO_DEVICE_MOUSE:
return sdl_mouse_device_state(data, id);
case SNES_DEVICE_SUPER_SCOPE:
return sdl_scope_device_state(data, id);
case SNES_DEVICE_JUSTIFIER:
case SNES_DEVICE_JUSTIFIERS:
return sdl_justifier_device_state(data, index, id);
case RETRO_DEVICE_LIGHTGUN:
return sdl_lightgun_device_state(data, id);
default:
return 0;

View file

@ -191,12 +191,12 @@ static int16_t x_input_state(void *data, const struct snes_keybind **binds, bool
switch (device)
{
case SNES_DEVICE_JOYPAD:
return x_is_pressed(x11, binds[(port == SNES_PORT_1) ? 0 : 1], id) ||
case RETRO_DEVICE_JOYPAD:
return x_is_pressed(x11, binds[port], id) ||
input_sdl.input_state(x11->sdl, binds, port, device, index, id);
case SNES_DEVICE_MULTITAP:
return x_is_pressed(x11, binds[(port == SNES_PORT_2) ? 1 + index : 0], id) ||
case RETRO_DEVICE_JOYPAD_MULTITAP:
return x_is_pressed(x11, binds[(port == 1) ? 1 + index : 0], id) ||
input_sdl.input_state(x11->sdl, binds, port, device, index, id);
default:

View file

@ -144,9 +144,14 @@ struct retro_variable
struct retro_game_info
{
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.
const char *path; // Path to game, UTF-8 encoded. Usually used as a reference.
// May be NULL if rom was loaded from stdin or similar.
// SET_NEED_FULLPATH path guaranteed that this path is valid.
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.
};

10
movie.c
View file

@ -82,8 +82,8 @@ static bool init_playback(bsv_movie_t *handle, const char *path)
return false;
}
if (psnes_serialize_size() == state_size)
psnes_unserialize(handle->state, state_size);
if (pretro_serialize_size() == state_size)
pretro_unserialize(handle->state, state_size);
else
SSNES_WARN("Movie format seems to have a different serializer version. Will most likely fail.\n");
}
@ -109,7 +109,7 @@ static bool init_record(bsv_movie_t *handle, const char *path)
header[CRC_INDEX] = swap_if_big32(g_extern.cart_crc);
uint32_t state_size = psnes_serialize_size();
uint32_t state_size = pretro_serialize_size();
header[STATE_SIZE_INDEX] = swap_if_big32(state_size);
fwrite(header, 4, sizeof(uint32_t), handle->file);
@ -123,7 +123,7 @@ static bool init_record(bsv_movie_t *handle, const char *path)
if (!handle->state)
return false;
psnes_serialize(handle->state, state_size);
pretro_serialize(handle->state, state_size);
fwrite(handle->state, 1, state_size, handle->file);
}
@ -224,7 +224,7 @@ void bsv_movie_frame_rewind(bsv_movie_t *handle)
if (!handle->playback)
{
fseek(handle->file, 4 * sizeof(uint32_t), SEEK_SET);
psnes_serialize(handle->state, handle->state_size);
pretro_serialize(handle->state, handle->state_size);
fwrite(handle->state, 1, handle->state_size, handle->file);
}
else

107
netplay.c
View file

@ -63,7 +63,6 @@ static int16_t netplay_input_state(netplay_t *handle, bool port, unsigned device
// If we're fast-forward replaying to resync, check if we should actually show frame.
static bool netplay_should_skip(netplay_t *handle);
static bool netplay_can_poll(netplay_t *handle);
static const struct snes_callbacks* netplay_callbacks(netplay_t *handle);
static void netplay_set_spectate_input(netplay_t *handle, int16_t input);
static bool netplay_send_cmd(netplay_t *handle, uint32_t cmd, const void *data, size_t size);
@ -74,7 +73,7 @@ static bool netplay_get_cmd(netplay_t *handle);
struct delta_frame
{
uint8_t *state;
void *state;
uint16_t real_input_state;
uint16_t simulated_input_state;
@ -96,7 +95,7 @@ struct netplay
char other_nick[32];
struct sockaddr_storage other_addr;
struct snes_callbacks cbs;
struct retro_callbacks cbs;
int fd; // TCP connection for state sending, etc. Also used for commands.
int udp_fd; // UDP connection for game state updates.
unsigned port; // Which port is governed by netplay (other player)?
@ -188,24 +187,32 @@ void input_poll_net(void)
netplay_poll(g_extern.netplay);
}
void video_frame_net(const uint16_t *data, unsigned width, unsigned height)
void video_frame_net(const void *data, unsigned width, unsigned height, size_t pitch)
{
if (!netplay_should_skip(g_extern.netplay))
netplay_callbacks(g_extern.netplay)->frame_cb(data, width, height);
g_extern.netplay->cbs.frame_cb(data, width, height, pitch);
}
void audio_sample_net(uint16_t left, uint16_t right)
void audio_sample_net(int16_t left, int16_t right)
{
if (!netplay_should_skip(g_extern.netplay))
netplay_callbacks(g_extern.netplay)->sample_cb(left, right);
g_extern.netplay->cbs.sample_cb(left, right);
}
int16_t input_state_net(bool port, unsigned device, unsigned index, unsigned id)
size_t audio_sample_batch_net(const int16_t *data, size_t frames)
{
if (!netplay_should_skip(g_extern.netplay))
return g_extern.netplay->cbs.sample_batch_cb(data, frames);
else
return frames;
}
int16_t input_state_net(unsigned port, unsigned device, unsigned index, unsigned id)
{
if (netplay_is_alive(g_extern.netplay))
return netplay_input_state(g_extern.netplay, port, device, index, id);
else
return netplay_callbacks(g_extern.netplay)->state_cb(port, device, index, id);
return g_extern.netplay->cbs.state_cb(port, device, index, id);
}
#ifndef HAVE_SOCKET_LEGACY
@ -447,18 +454,20 @@ bool netplay_can_poll(netplay_t *handle)
static uint32_t implementation_magic_value(void)
{
uint32_t res = 0;
unsigned major = psnes_library_revision_major();
unsigned minor = psnes_library_revision_minor();
unsigned api = pretro_api_version();
res |= (major & 0xf) << 0;
res |= (minor & 0xf) << 4;
res |= api;
// Shouldn't really use this, but oh well :) It'll do the job.
const char *lib = psnes_library_id();
const char *lib = g_extern.system.info.library_name;
size_t len = strlen(lib);
for (size_t i = 0; i < len; i++)
res ^= lib[i] << (i & 0xf);
lib = g_extern.system.info.library_version;
len = strlen(lib);
for (size_t i = 0; i < len; i++)
res ^= lib[i] << (i & 0xf);
const char *ver = PACKAGE_VERSION;
len = strlen(ver);
for (size_t i = 0; i < len; i++)
@ -516,7 +525,7 @@ static bool send_info(netplay_t *handle)
uint32_t header[3] = {
htonl(g_extern.cart_crc),
htonl(implementation_magic_value()),
htonl(psnes_get_memory_size(SNES_MEMORY_CARTRIDGE_RAM))
htonl(pretro_get_memory_size(RETRO_MEMORY_SAVE_RAM))
};
if (!send_all(handle->fd, header, sizeof(header)))
@ -528,9 +537,9 @@ static bool send_info(netplay_t *handle)
return false;
}
// Get SRAM data from Player 1 :)
uint8_t *sram = psnes_get_memory_data(SNES_MEMORY_CARTRIDGE_RAM);
unsigned sram_size = psnes_get_memory_size(SNES_MEMORY_CARTRIDGE_RAM);
// Get SRAM data from Player 1.
void *sram = pretro_get_memory_data(RETRO_MEMORY_SAVE_RAM);
unsigned sram_size = pretro_get_memory_size(RETRO_MEMORY_SAVE_RAM);
if (!recv_all(handle->fd, sram, sram_size))
{
@ -574,7 +583,7 @@ static bool get_info(netplay_t *handle)
return false;
}
if (psnes_get_memory_size(SNES_MEMORY_CARTRIDGE_RAM) != ntohl(header[2]))
if (pretro_get_memory_size(RETRO_MEMORY_SAVE_RAM) != ntohl(header[2]))
{
SSNES_ERR("Cartridge SRAM sizes do not correspond.\n");
return false;
@ -586,9 +595,9 @@ static bool get_info(netplay_t *handle)
return false;
}
// Send SRAM data to our Player 2 :)
const uint8_t *sram = psnes_get_memory_data(SNES_MEMORY_CARTRIDGE_RAM);
unsigned sram_size = psnes_get_memory_size(SNES_MEMORY_CARTRIDGE_RAM);
// Send SRAM data to our Player 2.
const void *sram = pretro_get_memory_data(RETRO_MEMORY_SAVE_RAM);
unsigned sram_size = pretro_get_memory_size(RETRO_MEMORY_SAVE_RAM);
if (!send_all(handle->fd, sram, sram_size))
{
SSNES_ERR("Failed to send SRAM data to client.\n");
@ -611,7 +620,7 @@ static bool get_info(netplay_t *handle)
static uint32_t *bsv_header_generate(size_t *size, uint32_t magic)
{
uint32_t bsv_header[4] = {0};
unsigned serialize_size = psnes_serialize_size();
size_t serialize_size = pretro_serialize_size();
size_t header_size = sizeof(bsv_header) + serialize_size;
*size = header_size;
@ -624,7 +633,7 @@ static uint32_t *bsv_header_generate(size_t *size, uint32_t magic)
bsv_header[CRC_INDEX] = swap_if_big32(g_extern.cart_crc);
bsv_header[STATE_SIZE_INDEX] = swap_if_big32(serialize_size);
if (serialize_size && !psnes_serialize((uint8_t*)header + sizeof(bsv_header), serialize_size))
if (serialize_size && !pretro_serialize(header + sizeof(bsv_header), serialize_size))
{
free(header);
return NULL;
@ -659,10 +668,10 @@ static bool bsv_parse_header(const uint32_t *header, uint32_t magic)
}
uint32_t in_state_size = swap_if_big32(header[STATE_SIZE_INDEX]);
if (in_state_size != psnes_serialize_size())
if (in_state_size != pretro_serialize_size())
{
SSNES_ERR("Serialization size mismatch, got 0x%x, expected 0x%x.\n",
in_state_size, psnes_serialize_size());
(unsigned)in_state_size, (unsigned)pretro_serialize_size());
return false;
}
@ -696,30 +705,29 @@ static bool get_info_spectate(netplay_t *handle)
return false;
}
unsigned save_state_size = psnes_serialize_size();
size_t save_state_size = pretro_serialize_size();
if (!bsv_parse_header(header, implementation_magic_value()))
{
SSNES_ERR("Received invalid BSV header from host.\n");
return false;
}
uint8_t *buf = (uint8_t*)malloc(save_state_size);
void *buf = malloc(save_state_size);
if (!buf)
return false;
size_t size = save_state_size;
uint8_t *tmp_buf = buf;
if (!recv_all(handle->fd, tmp_buf, size))
if (!recv_all(handle->fd, buf, size))
{
SSNES_ERR("Failed to receive save state from host.\n");
free(tmp_buf);
free(buf);
return false;
}
bool ret = true;
if (save_state_size)
ret = psnes_unserialize(buf, save_state_size);
ret = pretro_unserialize(buf, save_state_size);
free(buf);
return ret;
@ -728,16 +736,16 @@ static bool get_info_spectate(netplay_t *handle)
static void init_buffers(netplay_t *handle)
{
handle->buffer = (struct delta_frame*)calloc(handle->buffer_size, sizeof(*handle->buffer));
handle->state_size = psnes_serialize_size();
handle->state_size = pretro_serialize_size();
for (unsigned i = 0; i < handle->buffer_size; i++)
{
handle->buffer[i].state = (uint8_t*)malloc(handle->state_size);
handle->buffer[i].state = malloc(handle->state_size);
handle->buffer[i].is_simulated = true;
}
}
netplay_t *netplay_new(const char *server, uint16_t port,
unsigned frames, const struct snes_callbacks *cb,
unsigned frames, const struct retro_callbacks *cb,
bool spectate,
const char *nick)
{
@ -896,11 +904,11 @@ static bool get_self_input_state(netplay_t *handle)
uint32_t state = 0;
if (handle->frame_count > 0) // First frame we always give zero input since relying on input from first frame screws up when we use -F 0.
{
snes_input_state_t cb = handle->cbs.state_cb;
retro_input_state_t cb = handle->cbs.state_cb;
for (unsigned i = 0; i < SSNES_FIRST_META_KEY; i++)
{
int16_t tmp = cb(g_settings.input.netplay_client_swap_input ? 0 : !handle->port,
SNES_DEVICE_JOYPAD, 0, i);
RETRO_DEVICE_JOYPAD, 0, i);
state |= tmp ? 1 << i : 0;
}
}
@ -1221,11 +1229,6 @@ void netplay_free(netplay_t *handle)
free(handle);
}
static const struct snes_callbacks* netplay_callbacks(netplay_t *handle)
{
return &handle->cbs;
}
static bool netplay_should_skip(netplay_t *handle)
{
return handle->is_replay && handle->has_connection;
@ -1233,7 +1236,7 @@ static bool netplay_should_skip(netplay_t *handle)
static void netplay_pre_frame_net(netplay_t *handle)
{
psnes_serialize(handle->buffer[handle->self_ptr].state, handle->state_size);
pretro_serialize(handle->buffer[handle->self_ptr].state, handle->state_size);
handle->can_poll = true;
input_poll_net();
@ -1252,9 +1255,9 @@ static void netplay_set_spectate_input(netplay_t *handle, int16_t input)
handle->spectate_input[handle->spectate_input_ptr++] = swap_if_big16(input);
}
int16_t input_state_spectate(bool port, unsigned device, unsigned index, unsigned id)
int16_t input_state_spectate(unsigned port, unsigned device, unsigned index, unsigned id)
{
int16_t res = netplay_callbacks(g_extern.netplay)->state_cb(port, device, index, id);
int16_t res = g_extern.netplay->cbs.state_cb(port, device, index, id);
netplay_set_spectate_input(g_extern.netplay, res);
return res;
}
@ -1270,12 +1273,12 @@ static int16_t netplay_get_spectate_input(netplay_t *handle, bool port, unsigned
msg_queue_clear(g_extern.msg_queue);
msg_queue_push(g_extern.msg_queue, "Connection with host was cut.", 1, 180);
psnes_set_input_state(netplay_callbacks(g_extern.netplay)->state_cb);
return netplay_callbacks(g_extern.netplay)->state_cb(port, device, index, id);
pretro_set_input_state(g_extern.netplay->cbs.state_cb);
return g_extern.netplay->cbs.state_cb(port, device, index, id);
}
}
int16_t input_state_spectate_client(bool port, unsigned device, unsigned index, unsigned id)
int16_t input_state_spectate_client(unsigned port, unsigned device, unsigned index, unsigned id)
{
return netplay_get_spectate_input(g_extern.netplay, port, device, index, id);
}
@ -1397,15 +1400,15 @@ static void netplay_post_frame_net(netplay_t *handle)
handle->tmp_ptr = handle->other_ptr;
handle->tmp_frame_count = handle->other_frame_count;
psnes_unserialize(handle->buffer[handle->other_ptr].state, handle->state_size);
pretro_unserialize(handle->buffer[handle->other_ptr].state, handle->state_size);
bool first = true;
while (first || (handle->tmp_ptr != handle->self_ptr))
{
psnes_serialize(handle->buffer[handle->tmp_ptr].state, handle->state_size);
pretro_serialize(handle->buffer[handle->tmp_ptr].state, handle->state_size);
#ifdef HAVE_THREADS
lock_autosave();
#endif
psnes_run();
pretro_run();
#ifdef HAVE_THREADS
unlock_autosave();
#endif

View file

@ -26,9 +26,9 @@
void input_poll_net(void);
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 video_frame_net(const void *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);
size_t audio_sample_batch_net(const int16_t *data, size_t frames);
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);

View file

@ -525,35 +525,35 @@ struct bind_map
#define DECLARE_BIND(x, bind) { true, "input_" #x, "input_" #x "_btn", "input_" #x "_axis", bind }
#define DECL_PLAYER(P) \
{ \
DECLARE_BIND(player##P##_b, SNES_DEVICE_ID_JOYPAD_B), \
DECLARE_BIND(player##P##_y, SNES_DEVICE_ID_JOYPAD_Y), \
DECLARE_BIND(player##P##_select, SNES_DEVICE_ID_JOYPAD_SELECT), \
DECLARE_BIND(player##P##_start, SNES_DEVICE_ID_JOYPAD_START), \
DECLARE_BIND(player##P##_up, SNES_DEVICE_ID_JOYPAD_UP), \
DECLARE_BIND(player##P##_down, SNES_DEVICE_ID_JOYPAD_DOWN), \
DECLARE_BIND(player##P##_left, SNES_DEVICE_ID_JOYPAD_LEFT), \
DECLARE_BIND(player##P##_right, SNES_DEVICE_ID_JOYPAD_RIGHT), \
DECLARE_BIND(player##P##_a, SNES_DEVICE_ID_JOYPAD_A), \
DECLARE_BIND(player##P##_x, SNES_DEVICE_ID_JOYPAD_X), \
DECLARE_BIND(player##P##_l, SNES_DEVICE_ID_JOYPAD_L), \
DECLARE_BIND(player##P##_r, SNES_DEVICE_ID_JOYPAD_R), \
DECLARE_BIND(player##P##_b, RETRO_DEVICE_ID_JOYPAD_B), \
DECLARE_BIND(player##P##_y, RETRO_DEVICE_ID_JOYPAD_Y), \
DECLARE_BIND(player##P##_select, RETRO_DEVICE_ID_JOYPAD_SELECT), \
DECLARE_BIND(player##P##_start, RETRO_DEVICE_ID_JOYPAD_START), \
DECLARE_BIND(player##P##_up, RETRO_DEVICE_ID_JOYPAD_UP), \
DECLARE_BIND(player##P##_down, RETRO_DEVICE_ID_JOYPAD_DOWN), \
DECLARE_BIND(player##P##_left, RETRO_DEVICE_ID_JOYPAD_LEFT), \
DECLARE_BIND(player##P##_right, RETRO_DEVICE_ID_JOYPAD_RIGHT), \
DECLARE_BIND(player##P##_a, RETRO_DEVICE_ID_JOYPAD_A), \
DECLARE_BIND(player##P##_x, RETRO_DEVICE_ID_JOYPAD_X), \
DECLARE_BIND(player##P##_l, RETRO_DEVICE_ID_JOYPAD_L), \
DECLARE_BIND(player##P##_r, RETRO_DEVICE_ID_JOYPAD_R), \
}
// Big and nasty bind map... :)
static const struct bind_map bind_maps[MAX_PLAYERS][SSNES_BIND_LIST_END] = {
{
DECLARE_BIND(player1_b, SNES_DEVICE_ID_JOYPAD_B),
DECLARE_BIND(player1_y, SNES_DEVICE_ID_JOYPAD_Y),
DECLARE_BIND(player1_select, SNES_DEVICE_ID_JOYPAD_SELECT),
DECLARE_BIND(player1_start, SNES_DEVICE_ID_JOYPAD_START),
DECLARE_BIND(player1_up, SNES_DEVICE_ID_JOYPAD_UP),
DECLARE_BIND(player1_down, SNES_DEVICE_ID_JOYPAD_DOWN),
DECLARE_BIND(player1_left, SNES_DEVICE_ID_JOYPAD_LEFT),
DECLARE_BIND(player1_right, SNES_DEVICE_ID_JOYPAD_RIGHT),
DECLARE_BIND(player1_a, SNES_DEVICE_ID_JOYPAD_A),
DECLARE_BIND(player1_x, SNES_DEVICE_ID_JOYPAD_X),
DECLARE_BIND(player1_l, SNES_DEVICE_ID_JOYPAD_L),
DECLARE_BIND(player1_r, SNES_DEVICE_ID_JOYPAD_R),
DECLARE_BIND(player1_b, RETRO_DEVICE_ID_JOYPAD_B),
DECLARE_BIND(player1_y, RETRO_DEVICE_ID_JOYPAD_Y),
DECLARE_BIND(player1_select, RETRO_DEVICE_ID_JOYPAD_SELECT),
DECLARE_BIND(player1_start, RETRO_DEVICE_ID_JOYPAD_START),
DECLARE_BIND(player1_up, RETRO_DEVICE_ID_JOYPAD_UP),
DECLARE_BIND(player1_down, RETRO_DEVICE_ID_JOYPAD_DOWN),
DECLARE_BIND(player1_left, RETRO_DEVICE_ID_JOYPAD_LEFT),
DECLARE_BIND(player1_right, RETRO_DEVICE_ID_JOYPAD_RIGHT),
DECLARE_BIND(player1_a, RETRO_DEVICE_ID_JOYPAD_A),
DECLARE_BIND(player1_x, RETRO_DEVICE_ID_JOYPAD_X),
DECLARE_BIND(player1_l, RETRO_DEVICE_ID_JOYPAD_L),
DECLARE_BIND(player1_r, RETRO_DEVICE_ID_JOYPAD_R),
DECLARE_BIND(toggle_fast_forward, SSNES_FAST_FORWARD_KEY),
DECLARE_BIND(hold_fast_forward, SSNES_FAST_FORWARD_HOLD_KEY),

220
ssnes.c
View file

@ -341,13 +341,22 @@ static bool audio_flush(const int16_t *data, size_t samples)
}
#endif
static void audio_sample_rewind(uint16_t left, uint16_t right)
static void audio_sample_rewind(int16_t left, int16_t right)
{
g_extern.audio_data.rewind_buf[--g_extern.audio_data.rewind_ptr] = right;
g_extern.audio_data.rewind_buf[--g_extern.audio_data.rewind_ptr] = left;
}
static void audio_sample(uint16_t left, uint16_t right)
size_t audio_sample_batch_rewind(const int16_t *data, size_t frames)
{
size_t samples = frames << 1;
for (size_t i = 0; i < samples; i++)
g_extern.audio_data.rewind_buf[--g_extern.audio_data.rewind_ptr] = data[i];
return frames;
}
static void audio_sample(int16_t left, int16_t right)
{
g_extern.audio_data.conv_outsamples[g_extern.audio_data.data_ptr++] = left;
g_extern.audio_data.conv_outsamples[g_extern.audio_data.data_ptr++] = right;
@ -361,9 +370,7 @@ static void audio_sample(uint16_t left, uint16_t right)
g_extern.audio_data.data_ptr = 0;
}
// Non-standard, alternative callback better suited for systems that process audio in batch.
// Avoids tons of calls to audio_sample() ...
unsigned audio_sample_batch(const int16_t *data, unsigned frames)
size_t audio_sample_batch(const int16_t *data, size_t frames)
{
if (frames > (AUDIO_CHUNK_SIZE_NONBLOCKING >> 1))
frames = AUDIO_CHUNK_SIZE_NONBLOCKING >> 1;
@ -377,8 +384,10 @@ static void input_poll(void)
input_poll_func();
}
static int16_t input_state(bool port, unsigned device, unsigned index, unsigned id)
static int16_t input_state(unsigned port, unsigned device, unsigned index, unsigned id)
{
device &= RETRO_DEVICE_MASK;
#ifdef HAVE_BSV_MOVIE
if (g_extern.bsv.movie && g_extern.bsv.movie_playback)
{
@ -544,7 +553,7 @@ static void print_help(void)
static void set_basename(const char *path)
{
strlcpy(g_extern.system.fullpath, path, sizeof(g_extern.system.fullpath));
strlcpy(g_extern.fullpath, path, sizeof(g_extern.fullpath));
strlcpy(g_extern.basename, path, sizeof(g_extern.basename));
char *dst = strrchr(g_extern.basename, '.');
@ -1027,24 +1036,24 @@ static inline void load_save_files(void)
switch (g_extern.game_type)
{
case SSNES_CART_NORMAL:
load_ram_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM);
load_ram_file(g_extern.savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC);
load_ram_file(g_extern.savefile_name_srm, RETRO_MEMORY_SAVE_RAM);
load_ram_file(g_extern.savefile_name_rtc, RETRO_MEMORY_RTC);
break;
case SSNES_CART_SGB:
save_ram_file(g_extern.savefile_name_srm, SNES_MEMORY_GAME_BOY_RAM);
save_ram_file(g_extern.savefile_name_rtc, SNES_MEMORY_GAME_BOY_RTC);
save_ram_file(g_extern.savefile_name_srm, RETRO_MEMORY_SNES_GAME_BOY_RAM);
save_ram_file(g_extern.savefile_name_rtc, RETRO_MEMORY_SNES_GAME_BOY_RTC);
break;
case SSNES_CART_BSX:
case SSNES_CART_BSX_SLOTTED:
load_ram_file(g_extern.savefile_name_srm, SNES_MEMORY_BSX_RAM);
load_ram_file(g_extern.savefile_name_psrm, SNES_MEMORY_BSX_PRAM);
load_ram_file(g_extern.savefile_name_srm, RETRO_MEMORY_SNES_BSX_RAM);
load_ram_file(g_extern.savefile_name_psrm, RETRO_MEMORY_SNES_BSX_PRAM);
break;
case SSNES_CART_SUFAMI:
load_ram_file(g_extern.savefile_name_asrm, SNES_MEMORY_SUFAMI_TURBO_A_RAM);
load_ram_file(g_extern.savefile_name_bsrm, SNES_MEMORY_SUFAMI_TURBO_B_RAM);
load_ram_file(g_extern.savefile_name_asrm, RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM);
load_ram_file(g_extern.savefile_name_bsrm, RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM);
break;
default:
@ -1058,27 +1067,27 @@ static inline void save_files(void)
{
case SSNES_CART_NORMAL:
SSNES_LOG("Saving regular SRAM.\n");
save_ram_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM);
save_ram_file(g_extern.savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC);
save_ram_file(g_extern.savefile_name_srm, RETRO_MEMORY_SAVE_RAM);
save_ram_file(g_extern.savefile_name_rtc, RETRO_MEMORY_RTC);
break;
case SSNES_CART_SGB:
SSNES_LOG("Saving Gameboy SRAM.\n");
save_ram_file(g_extern.savefile_name_srm, SNES_MEMORY_GAME_BOY_RAM);
save_ram_file(g_extern.savefile_name_rtc, SNES_MEMORY_GAME_BOY_RTC);
save_ram_file(g_extern.savefile_name_srm, RETRO_MEMORY_SNES_GAME_BOY_RAM);
save_ram_file(g_extern.savefile_name_rtc, RETRO_MEMORY_SNES_GAME_BOY_RTC);
break;
case SSNES_CART_BSX:
case SSNES_CART_BSX_SLOTTED:
SSNES_LOG("Saving BSX (P)RAM.\n");
save_ram_file(g_extern.savefile_name_srm, SNES_MEMORY_BSX_RAM);
save_ram_file(g_extern.savefile_name_psrm, SNES_MEMORY_BSX_PRAM);
save_ram_file(g_extern.savefile_name_srm, RETRO_MEMORY_SNES_BSX_RAM);
save_ram_file(g_extern.savefile_name_psrm, RETRO_MEMORY_SNES_BSX_PRAM);
break;
case SSNES_CART_SUFAMI:
SSNES_LOG("Saving Sufami turbo A/B RAM.\n");
save_ram_file(g_extern.savefile_name_asrm, SNES_MEMORY_SUFAMI_TURBO_A_RAM);
save_ram_file(g_extern.savefile_name_bsrm, SNES_MEMORY_SUFAMI_TURBO_B_RAM);
save_ram_file(g_extern.savefile_name_asrm, RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM);
save_ram_file(g_extern.savefile_name_bsrm, RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM);
break;
default:
@ -1093,26 +1102,21 @@ static void init_recording(void)
if (!g_extern.recording)
return;
// Canonical values.
double fps = psnes_get_region() == SNES_REGION_NTSC ? 60.00 : 50.00;
double samplerate = 32000.0;
if (g_extern.system.timing_set)
{
fps = g_extern.system.timing.fps;
samplerate = g_extern.system.timing.sample_rate;
SSNES_LOG("Custom timing given: FPS: %.4f, Sample rate: %.4f\n", (float)fps, (float)samplerate);
}
double fps = g_extern.system.av_info.timing.fps;
double samplerate = g_extern.system.av_info.timing.sample_rate;
SSNES_LOG("Custom timing given: FPS: %.4f, Sample rate: %.4f\n", (float)fps, (float)samplerate);
struct ffemu_params params = {0};
params.out_width = g_extern.system.geom.base_width;
params.out_height = g_extern.system.geom.base_height;
params.fb_width = g_extern.system.geom.max_width;
params.fb_height = g_extern.system.geom.max_height;
params.channels = 2;
params.filename = g_extern.record_path;
params.fps = fps;
const struct retro_system_av_info *info = &g_extern.system.av_info;
params.out_width = info->geometry.base_width;
params.out_height = info->geometry.base_height;
params.fb_width = info->geometry.max_width;
params.fb_height = info->geometry.max_height;
params.channels = 2;
params.filename = g_extern.record_path;
params.fps = fps;
params.samplerate = samplerate;
params.rgb32 = false;
params.rgb32 = false;
if (g_extern.record_width || g_extern.record_height)
{
@ -1191,7 +1195,7 @@ static void init_rewind(void)
if (!g_settings.rewind_enable)
return;
g_extern.state_size = psnes_serialize_size();
g_extern.state_size = pretro_serialize_size();
// Make sure we allocate at least 4-byte multiple.
size_t aligned_state_size = (g_extern.state_size + 3) & ~3;
@ -1203,7 +1207,7 @@ static void init_rewind(void)
return;
}
if (!psnes_serialize((uint8_t*)g_extern.state_buf, g_extern.state_size))
if (!pretro_serialize(g_extern.state_buf, g_extern.state_size))
{
SSNES_ERR("Failed to perform initial serialization for rewind.\n");
free(g_extern.state_buf);
@ -1279,9 +1283,10 @@ static void init_netplay(void)
if (!g_extern.netplay_enable)
return;
struct snes_callbacks cbs = {0};
struct retro_callbacks cbs = {0};
cbs.frame_cb = video_frame;
cbs.sample_cb = audio_sample;
cbs.sample_batch_cb = audio_sample_batch;
cbs.state_cb = input_state;
if (*g_extern.netplay_server)
@ -1318,32 +1323,37 @@ static void deinit_netplay(void)
}
#endif
static void init_libsnes_cbs_plain(void)
{
pretro_set_video_refresh(video_frame);
pretro_set_audio_sample(audio_sample);
pretro_set_audio_sample_batch(audio_sample_batch);
pretro_set_input_state(input_state);
pretro_set_input_poll(input_poll);
}
static void init_libsnes_cbs(void)
{
#ifdef HAVE_NETPLAY
if (g_extern.netplay)
{
psnes_set_video_refresh(g_extern.netplay_is_spectate ?
pretro_set_video_refresh(g_extern.netplay_is_spectate ?
video_frame : video_frame_net);
psnes_set_audio_sample(g_extern.netplay_is_spectate ?
audio_sample : audio_sample_net);
psnes_set_input_state(g_extern.netplay_is_spectate ?
pretro_set_audio_sample(g_extern.netplay_is_spectate ?
audio_sample : audio_sample_net);
pretro_set_audio_sample_batch(g_extern.netplay_is_spectate ?
audio_sample_batch : audio_sample_batch_net);
pretro_set_input_state(g_extern.netplay_is_spectate ?
(g_extern.netplay_is_client ? input_state_spectate_client : input_state_spectate)
: input_state_net);
}
else
{
psnes_set_video_refresh(video_frame);
psnes_set_audio_sample(audio_sample);
psnes_set_input_state(input_state);
}
init_libsnes_cbs_plain();
#else
psnes_set_video_refresh(video_frame);
psnes_set_audio_sample(audio_sample);
psnes_set_input_state(input_state);
init_libsnes_cbs_plain();
#endif
psnes_set_input_poll(input_poll);
}
#ifdef HAVE_THREADS
@ -1356,42 +1366,42 @@ static void init_autosave(void)
{
case SSNES_CART_BSX:
case SSNES_CART_BSX_SLOTTED:
ram_types[0] = SNES_MEMORY_BSX_RAM;
ram_types[1] = SNES_MEMORY_BSX_PRAM;
ram_types[0] = RETRO_MEMORY_SNES_BSX_RAM;
ram_types[1] = RETRO_MEMORY_SNES_BSX_PRAM;
ram_paths[0] = g_extern.savefile_name_srm;
ram_paths[1] = g_extern.savefile_name_psrm;
break;
case SSNES_CART_SUFAMI:
ram_types[0] = SNES_MEMORY_SUFAMI_TURBO_A_RAM;
ram_types[1] = SNES_MEMORY_SUFAMI_TURBO_B_RAM;
ram_types[0] = RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM;
ram_types[1] = RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM;
ram_paths[0] = g_extern.savefile_name_asrm;
ram_paths[1] = g_extern.savefile_name_bsrm;
break;
case SSNES_CART_SGB:
ram_types[0] = SNES_MEMORY_GAME_BOY_RAM;
ram_types[1] = SNES_MEMORY_GAME_BOY_RTC;
ram_types[0] = RETRO_MEMORY_SNES_GAME_BOY_RAM;
ram_types[1] = RETRO_MEMORY_SNES_GAME_BOY_RTC;
ram_paths[0] = g_extern.savefile_name_srm;
ram_paths[1] = g_extern.savefile_name_rtc;
break;
default:
ram_types[0] = SNES_MEMORY_CARTRIDGE_RAM;
ram_types[1] = SNES_MEMORY_CARTRIDGE_RTC;
ram_types[0] = RETRO_MEMORY_SAVE_RAM;
ram_types[1] = RETRO_MEMORY_RTC;
ram_paths[0] = g_extern.savefile_name_srm;
ram_paths[1] = g_extern.savefile_name_rtc;
}
if (g_settings.autosave_interval > 0)
{
for (unsigned i = 0; i < sizeof(g_extern.autosave)/sizeof(g_extern.autosave[0]); i++)
for (unsigned i = 0; i < sizeof(g_extern.autosave) / sizeof(g_extern.autosave[0]); i++)
{
if (ram_paths[i] && strlen(ram_paths[i]) > 0 && psnes_get_memory_size(ram_types[i]) > 0)
if (ram_paths[i] && *ram_paths[i] && pretro_get_memory_size(ram_types[i]) > 0)
{
g_extern.autosave[i] = autosave_new(ram_paths[i],
psnes_get_memory_data(ram_types[i]),
psnes_get_memory_size(ram_types[i]),
pretro_get_memory_data(ram_types[i]),
pretro_get_memory_size(ram_types[i]),
g_settings.autosave_interval);
if (!g_extern.autosave[i])
SSNES_WARN("Could not initialize autosave.\n");
@ -1402,7 +1412,7 @@ static void init_autosave(void)
static void deinit_autosave(void)
{
for (unsigned i = 0; i < sizeof(g_extern.autosave)/sizeof(g_extern.autosave[0]); i++)
for (unsigned i = 0; i < sizeof(g_extern.autosave) / sizeof(g_extern.autosave[0]); i++)
{
if (g_extern.autosave[i])
autosave_free(g_extern.autosave[i]);
@ -1786,7 +1796,7 @@ static void check_rewind(void)
setup_rewind_audio();
msg_queue_push(g_extern.msg_queue, "Rewinding.", 0, g_extern.is_paused ? 1 : 30);
psnes_unserialize((uint8_t*)buf, g_extern.state_size);
pretro_unserialize(buf, g_extern.state_size);
#ifdef HAVE_BSV_MOVIE
if (g_extern.bsv.movie)
@ -1806,12 +1816,15 @@ static void check_rewind(void)
if (cnt == 0)
#endif
{
psnes_serialize((uint8_t*)g_extern.state_buf, g_extern.state_size);
pretro_serialize(g_extern.state_buf, g_extern.state_size);
state_manager_push(g_extern.state_manager, g_extern.state_buf);
}
}
psnes_set_audio_sample(g_extern.frame_is_reverse ? audio_sample_rewind : audio_sample);
pretro_set_audio_sample(g_extern.frame_is_reverse ?
audio_sample_rewind : audio_sample);
pretro_set_audio_sample_batch(g_extern.frame_is_reverse ?
audio_sample_batch_rewind : audio_sample_batch);
}
static void check_slowmotion(void)
@ -1980,7 +1993,7 @@ void ssnes_game_reset(void)
SSNES_LOG("Resetting game.\n");
msg_queue_clear(g_extern.msg_queue);
msg_queue_push(g_extern.msg_queue, "Reset.", 1, 120);
psnes_reset();
pretro_reset();
init_controllers(); // bSNES since v073r01 resets controllers to JOYPAD after a reset, so just enforce it here.
}
@ -2206,11 +2219,6 @@ static void do_state_checks(void)
check_input_rate();
}
static void fill_title_buf(void)
{
snprintf(g_extern.title_buf, sizeof(g_extern.title_buf), "SSNES : %s", psnes_library_id());
}
static void init_state(void)
{
g_extern.video_active = true;
@ -2233,6 +2241,33 @@ void ssnes_main_clear_state(void)
init_state();
}
static void init_system_info(void)
{
struct retro_system_info *info = &g_extern.system.info;
retro_get_system_info(info);
if (!info->library_name)
info->library_name = "Unknown";
if (!info->library_version)
info->library_version = "v0";
snprintf(g_extern.title_buf, sizeof(g_extern.title_buf), "SSNES : %s %s",
info->library_name, info->library_version);
}
static void init_system_av_info(void)
{
retro_get_system_av_info(&g_extern.system.av_info);
}
static void verify_api_version(void)
{
SSNES_LOG("Version of libretro API: %u\n", pretro_api_version());
SSNES_LOG("Compiled against API: %u\n", RETRO_API_VERSION);
if (pretro_api_version() != RETRO_API_VERSION)
SSNES_WARN("SSNES is compiled against a different version of libretro than this libretro implementation.\n");
}
int ssnes_main_init(int argc, char *argv[])
{
init_state();
@ -2254,16 +2289,14 @@ int ssnes_main_init(int argc, char *argv[])
}
config_load();
init_libsnes_sym();
fill_title_buf();
init_libretro_sym();
init_system_info();
init_drivers_pre();
psnes_init();
if (*g_extern.basename)
psnes_set_cartridge_basename(g_extern.basename);
SSNES_LOG("Version of libretro API: %u.%u\n",
psnes_library_revision_major(), psnes_library_revision_minor());
verify_api_version();
pretro_init();
g_extern.use_sram = true;
#ifdef HAVE_XML
@ -2276,6 +2309,7 @@ int ssnes_main_init(int argc, char *argv[])
if (!init_rom_file(g_extern.game_type))
goto error;
init_system_av_info();
init_msg_queue();
if (!g_extern.sram_load_disable)
@ -2335,10 +2369,10 @@ int ssnes_main_init(int argc, char *argv[])
return 0;
error:
psnes_unload_cartridge();
psnes_term();
pretro_unload_game();
pretro_deinit();
uninit_drivers();
uninit_libsnes_sym();
uninit_libretro_sym();
return 1;
}
@ -2378,7 +2412,7 @@ bool ssnes_main_iterate(void)
bsv_movie_set_frame_start(g_extern.bsv.movie);
#endif
psnes_run();
pretro_run();
#ifdef HAVE_BSV_MOVIE
if (g_extern.bsv.movie)
@ -2437,10 +2471,10 @@ void ssnes_main_deinit(void)
#endif
deinit_msg_queue();
psnes_unload_cartridge();
psnes_term();
pretro_unload_game();
pretro_deinit();
uninit_drivers();
uninit_libsnes_sym();
uninit_libretro_sym();
}
#ifndef SSNES_CONSOLE