2012-04-10 21:06:17 +00:00
# include "libretro.h"
2012-01-02 00:48:51 +00:00
# include "snes9x.h"
# include "memmap.h"
# include "srtc.h"
# include "apu/apu.h"
2012-03-25 17:47:12 +00:00
# include "apu/bapu/snes/snes.hpp"
2012-01-02 00:48:51 +00:00
# include "gfx.h"
# include "snapshot.h"
# include "controls.h"
# include "cheats.h"
2018-05-26 13:15:06 +00:00
# include "movie.h"
2012-01-02 00:48:51 +00:00
# include "logger.h"
# include "display.h"
# include "conffile.h"
# include <stdio.h>
2018-05-25 21:56:02 +00:00
# ifdef _WIN32
# include <direct.h>
# else
2012-01-02 00:48:51 +00:00
# include <unistd.h>
# endif
# include <sys/stat.h>
# include <sys/types.h>
# include <fcntl.h>
2018-05-25 21:56:02 +00:00
# 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)
2014-06-02 20:20:19 +00:00
2018-05-25 21:56:02 +00:00
# define RETRO_MEMORY_SNES_BSX_RAM ((1 << 8) | RETRO_MEMORY_SAVE_RAM)
# define RETRO_MEMORY_SNES_BSX_PRAM ((2 << 8) | RETRO_MEMORY_SAVE_RAM)
# define RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM ((3 << 8) | RETRO_MEMORY_SAVE_RAM)
# define RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM ((4 << 8) | RETRO_MEMORY_SAVE_RAM)
# define RETRO_MEMORY_SNES_GAME_BOY_RAM ((5 << 8) | RETRO_MEMORY_SAVE_RAM)
# define RETRO_MEMORY_SNES_GAME_BOY_RTC ((6 << 8) | RETRO_MEMORY_RTC)
2014-06-02 20:20:19 +00:00
# define RETRO_GAME_TYPE_BSX 0x101
# define RETRO_GAME_TYPE_BSX_SLOTTED 0x102
# define RETRO_GAME_TYPE_SUFAMI_TURBO 0x103
# define RETRO_GAME_TYPE_SUPER_GAME_BOY 0x104
2017-07-23 19:11:47 +00:00
# define SNES_4_3 4.0f / 3.0f
2018-05-26 13:15:06 +00:00
# define SNES_8_7 8.0f / 7.0f
2017-07-23 19:11:47 +00:00
2018-05-25 21:56:02 +00:00
char g_rom_dir [ 1024 ] ;
char g_basename [ 1024 ] ;
2017-07-23 19:11:47 +00:00
2018-05-25 21:56:02 +00:00
retro_log_printf_t log_cb = NULL ;
2016-10-08 15:52:38 +00:00
static retro_video_refresh_t video_cb = NULL ;
static retro_audio_sample_t audio_cb = NULL ;
static retro_audio_sample_batch_t audio_batch_cb = NULL ;
static retro_input_poll_t poll_cb = NULL ;
static retro_input_state_t input_state_cb = NULL ;
2012-01-02 00:48:51 +00:00
2017-07-23 19:11:47 +00:00
static void extract_basename ( char * buf , const char * path , size_t size )
{
const char * base = strrchr ( path , ' / ' ) ;
if ( ! base )
base = strrchr ( path , ' \\ ' ) ;
if ( ! base )
base = path ;
if ( * base = = ' \\ ' | | * base = = ' / ' )
base + + ;
strncpy ( buf , base , size - 1 ) ;
buf [ size - 1 ] = ' \0 ' ;
char * ext = strrchr ( buf , ' . ' ) ;
if ( ext )
* ext = ' \0 ' ;
}
static void extract_directory ( char * buf , const char * path , size_t size )
{
strncpy ( buf , path , size - 1 ) ;
buf [ size - 1 ] = ' \0 ' ;
char * base = strrchr ( buf , ' / ' ) ;
if ( ! base )
base = strrchr ( buf , ' \\ ' ) ;
if ( base )
* base = ' \0 ' ;
else
buf [ 0 ] = ' \0 ' ;
}
2012-04-10 21:06:17 +00:00
void retro_set_video_refresh ( retro_video_refresh_t cb )
2012-01-02 00:48:51 +00:00
{
2016-10-08 15:52:38 +00:00
video_cb = cb ;
2012-01-02 00:48:51 +00:00
}
2012-04-10 21:06:17 +00:00
void retro_set_audio_sample ( retro_audio_sample_t cb )
2012-01-02 00:48:51 +00:00
{
2016-10-08 15:52:38 +00:00
audio_cb = cb ;
2012-01-02 00:48:51 +00:00
}
2012-04-10 21:06:17 +00:00
void retro_set_audio_sample_batch ( retro_audio_sample_batch_t cb )
{
2016-10-08 15:52:38 +00:00
audio_batch_cb = cb ;
2012-04-10 21:06:17 +00:00
}
void retro_set_input_poll ( retro_input_poll_t cb )
2012-01-02 00:48:51 +00:00
{
2016-10-08 15:52:38 +00:00
poll_cb = cb ;
2012-01-02 00:48:51 +00:00
}
2012-04-10 21:06:17 +00:00
void retro_set_input_state ( retro_input_state_t cb )
2012-01-02 00:48:51 +00:00
{
2016-10-08 15:52:38 +00:00
input_state_cb = cb ;
2012-01-02 00:48:51 +00:00
}
2018-05-26 13:15:06 +00:00
enum overscan_mode {
OVERSCAN_CROP_ON ,
OVERSCAN_CROP_OFF ,
OVERSCAN_CROP_AUTO
} ;
enum aspect_mode {
ASPECT_RATIO_4_3 ,
ASPECT_RATIO_8_7 ,
ASPECT_RATIO_NTSC ,
ASPECT_RATIO_PAL ,
ASPECT_RATIO_AUTO
} ;
2012-04-10 21:06:17 +00:00
static retro_environment_t environ_cb ;
2018-05-26 13:15:06 +00:00
static overscan_mode crop_overscan_mode = OVERSCAN_CROP_ON ; // default to crop
static aspect_mode aspect_ratio_mode = ASPECT_RATIO_4_3 ; // default to 4:3
2012-05-07 22:03:20 +00:00
static bool rom_loaded = false ;
2012-04-10 21:06:17 +00:00
void retro_set_environment ( retro_environment_t cb )
2012-01-02 00:48:51 +00:00
{
environ_cb = cb ;
2016-12-10 16:52:05 +00:00
2017-07-23 19:11:47 +00:00
struct retro_variable variables [ ] = {
2013-07-26 14:02:06 +00:00
// These variable names and possible values constitute an ABI with ZMZ (ZSNES Libretro player).
2013-07-26 18:11:56 +00:00
// Changing "Show layer 1" is fine, but don't change "layer_1"/etc or the possible values ("Yes|No").
2013-07-26 14:02:06 +00:00
// Adding more variables and rearranging them is safe.
2018-05-25 21:56:02 +00:00
{ " snes9x_up_down_allowed " , " Allow Opposing Directions; disabled|enabled " } ,
{ " snes9x_overclock " , " SuperFX Frequency; 100%|200%|400%|600%|800%|1000% " } ,
//{ "snes9x_overclock_cycles", "Reduce Slowdown (Hack, Unsafe); disabled|compatible|max" },
//{ "snes9x_reduce_sprite_flicker", "Reduce Flickering (Hack, Unsafe); disabled|enabled" },
2017-07-23 19:11:47 +00:00
{ " snes9x_layer_1 " , " Show layer 1; enabled|disabled " } ,
{ " snes9x_layer_2 " , " Show layer 2; enabled|disabled " } ,
{ " snes9x_layer_3 " , " Show layer 3; enabled|disabled " } ,
{ " snes9x_layer_4 " , " Show layer 4; enabled|disabled " } ,
{ " snes9x_layer_5 " , " Show sprite layer; enabled|disabled " } ,
{ " snes9x_gfx_clip " , " Enable graphic clip windows; enabled|disabled " } ,
{ " snes9x_gfx_transp " , " Enable transparency effects; enabled|disabled " } ,
2018-05-25 21:56:02 +00:00
{ " snes9x_gfx_hires " , " Enable hires mode; enabled|disabled " } ,
2017-07-23 19:11:47 +00:00
{ " snes9x_sndchan_1 " , " Enable sound channel 1; enabled|disabled " } ,
{ " snes9x_sndchan_2 " , " Enable sound channel 2; enabled|disabled " } ,
{ " snes9x_sndchan_3 " , " Enable sound channel 3; enabled|disabled " } ,
{ " snes9x_sndchan_4 " , " Enable sound channel 4; enabled|disabled " } ,
{ " snes9x_sndchan_5 " , " Enable sound channel 5; enabled|disabled " } ,
{ " snes9x_sndchan_6 " , " Enable sound channel 6; enabled|disabled " } ,
{ " snes9x_sndchan_7 " , " Enable sound channel 7; enabled|disabled " } ,
{ " snes9x_sndchan_8 " , " Enable sound channel 8; enabled|disabled " } ,
2018-05-26 13:15:06 +00:00
{ " snes9x_overscan " , " Crop overscan; enabled|disabled|auto " } ,
{ " snes9x_aspect " , " Preferred aspect ratio; 4:3|8:7|auto|ntsc|pal " } ,
2013-07-25 13:26:55 +00:00
{ NULL , NULL } ,
} ;
2016-12-10 16:52:05 +00:00
2017-07-23 19:11:47 +00:00
environ_cb ( RETRO_ENVIRONMENT_SET_VARIABLES , variables ) ;
2014-06-02 20:20:19 +00:00
2018-05-26 13:15:06 +00:00
const struct retro_controller_description port_1 [ ] = {
2014-06-02 20:20:19 +00:00
{ " SNES Joypad " , RETRO_DEVICE_JOYPAD } ,
{ " SNES Mouse " , RETRO_DEVICE_MOUSE } ,
{ " Multitap " , RETRO_DEVICE_JOYPAD_MULTITAP } ,
} ;
2018-05-26 13:15:06 +00:00
const struct retro_controller_description port_2 [ ] = {
2014-06-02 20:20:19 +00:00
{ " SNES Joypad " , RETRO_DEVICE_JOYPAD } ,
{ " SNES Mouse " , RETRO_DEVICE_MOUSE } ,
{ " Multitap " , RETRO_DEVICE_JOYPAD_MULTITAP } ,
{ " SuperScope " , RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE } ,
{ " Justifier " , RETRO_DEVICE_LIGHTGUN_JUSTIFIER } ,
} ;
2018-05-26 13:15:06 +00:00
const struct retro_controller_info ports [ ] = {
2014-06-02 20:20:19 +00:00
{ port_1 , 3 } ,
{ port_2 , 5 } ,
2018-05-25 21:56:02 +00:00
{ 0 , 0 } ,
2014-06-02 20:20:19 +00:00
} ;
environ_cb ( RETRO_ENVIRONMENT_SET_CONTROLLER_INFO , ( void * ) ports ) ;
2013-07-25 13:26:55 +00:00
}
2017-07-23 19:11:47 +00:00
void update_geometry ( )
{
struct retro_system_av_info av_info ;
retro_get_system_av_info ( & av_info ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_GEOMETRY , & av_info ) ;
}
2013-07-25 13:26:55 +00:00
static void update_variables ( void )
{
2017-07-23 19:11:47 +00:00
bool geometry_update = false ;
2016-10-08 15:52:38 +00:00
char key [ 256 ] ;
2013-07-25 13:26:55 +00:00
struct retro_variable var ;
2018-05-25 21:56:02 +00:00
var . key = " snes9x_overclock " ;
var . value = NULL ;
2016-12-10 16:52:05 +00:00
2018-05-25 21:56:02 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) )
{
int freq = atoi ( var . value ) ;
Settings . SuperFXClockMultiplier = freq ;
}
var . key = " snes9x_up_down_allowed " ;
var . value = NULL ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) )
{
Settings . UpAndDown = ! strcmp ( var . value , " disabled " ) ? false : true ;
}
else
Settings . UpAndDown = false ;
2013-07-25 13:26:55 +00:00
int disabled_channels = 0 ;
2016-10-08 15:52:38 +00:00
strcpy ( key , " snes9x_sndchan_x " ) ;
2018-05-25 21:56:02 +00:00
var . key = key ;
2013-07-25 13:26:55 +00:00
for ( int i = 0 ; i < 8 ; i + + )
{
2016-10-08 15:52:38 +00:00
key [ strlen ( " snes9x_sndchan_ " ) ] = ' 1 ' + i ;
2013-07-25 13:26:55 +00:00
var . value = NULL ;
2018-05-25 21:56:02 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & ! strcmp ( " disabled " , var . value ) )
2017-07-23 19:11:47 +00:00
disabled_channels | = 1 < < i ;
2013-07-25 13:26:55 +00:00
}
S9xSetSoundControl ( disabled_channels ^ 0xFF ) ;
2016-12-10 16:52:05 +00:00
2017-07-23 19:11:47 +00:00
2013-07-25 13:26:55 +00:00
int disabled_layers = 0 ;
2016-10-08 15:52:38 +00:00
strcpy ( key , " snes9x_layer_x " ) ;
2013-07-25 13:26:55 +00:00
for ( int i = 0 ; i < 5 ; i + + )
{
2016-10-08 15:52:38 +00:00
key [ strlen ( " snes9x_layer_ " ) ] = ' 1 ' + i ;
2013-07-25 13:26:55 +00:00
var . value = NULL ;
2018-05-25 21:56:02 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & ! strcmp ( " disabled " , var . value ) )
2017-07-23 19:11:47 +00:00
disabled_layers | = 1 < < i ;
2013-07-25 13:26:55 +00:00
}
Settings . BG_Forced = disabled_layers ;
2016-12-10 16:52:05 +00:00
2013-07-25 13:26:55 +00:00
//for some reason, Transparency seems to control both the fixed color and the windowing registers?
2016-10-08 15:52:38 +00:00
var . key = " snes9x_gfx_clip " ;
2013-07-25 13:26:55 +00:00
var . value = NULL ;
2018-05-25 21:56:02 +00:00
Settings . DisableGraphicWindows = ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & ! strcmp ( " disabled " , var . value ) ) ;
2016-10-08 15:52:38 +00:00
var . key = " snes9x_gfx_transp " ;
2013-07-25 13:26:55 +00:00
var . value = NULL ;
2018-05-25 21:56:02 +00:00
Settings . Transparency = ! ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & ! strcmp ( " disabled " , var . value ) ) ;
var . key = " snes9x_gfx_hires " ;
var . value = NULL ;
Settings . SupportHiRes = ! ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & ! strcmp ( " disabled " , var . value ) ) ;
2017-07-23 19:11:47 +00:00
var . key = " snes9x_overscan " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2018-05-26 13:15:06 +00:00
overscan_mode newval = OVERSCAN_CROP_AUTO ;
2017-07-23 19:11:47 +00:00
if ( strcmp ( var . value , " enabled " ) = = 0 )
2018-05-26 13:15:06 +00:00
newval = OVERSCAN_CROP_ON ;
2017-07-23 19:11:47 +00:00
else if ( strcmp ( var . value , " disabled " ) = = 0 )
2018-05-26 13:15:06 +00:00
newval = OVERSCAN_CROP_OFF ;
2018-05-25 21:56:02 +00:00
2017-07-23 19:11:47 +00:00
if ( newval ! = crop_overscan_mode )
{
crop_overscan_mode = newval ;
geometry_update = true ;
}
}
var . key = " snes9x_aspect " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2018-05-26 13:15:06 +00:00
aspect_mode newval = ASPECT_RATIO_AUTO ;
2017-07-23 19:11:47 +00:00
if ( strcmp ( var . value , " ntsc " ) = = 0 )
2018-05-26 13:15:06 +00:00
newval = ASPECT_RATIO_NTSC ;
2017-07-23 19:11:47 +00:00
else if ( strcmp ( var . value , " pal " ) = = 0 )
2018-05-26 13:15:06 +00:00
newval = ASPECT_RATIO_PAL ;
2017-07-23 19:11:47 +00:00
else if ( strcmp ( var . value , " 4:3 " ) = = 0 )
2018-05-26 13:15:06 +00:00
newval = ASPECT_RATIO_4_3 ;
else if ( strcmp ( var . value , " 8:7 " ) = = 0 )
newval = ASPECT_RATIO_8_7 ;
2017-07-23 19:11:47 +00:00
if ( newval ! = aspect_ratio_mode )
{
aspect_ratio_mode = newval ;
geometry_update = true ;
}
}
if ( geometry_update )
update_geometry ( ) ;
2012-01-02 00:48:51 +00:00
}
static void S9xAudioCallback ( void * )
{
2018-05-25 21:56:02 +00:00
const int BUFFER_SIZE = 256 ;
// This is called every time 128 to 132 samples are generated, which happens about 8 times per frame. A buffer size of 256 samples is enough here.
static int16_t audio_buf [ BUFFER_SIZE ] ;
2012-01-02 00:48:51 +00:00
S9xFinalizeSamples ( ) ;
size_t avail = S9xGetSampleCount ( ) ;
2018-05-25 21:56:02 +00:00
while ( avail > = BUFFER_SIZE )
{
//this loop will never be entered, but handle oversized sample counts just in case
S9xMixSamples ( ( uint8 * ) audio_buf , BUFFER_SIZE ) ;
audio_batch_cb ( audio_buf , BUFFER_SIZE > > 1 ) ;
avail - = BUFFER_SIZE ;
}
if ( avail > 0 )
{
S9xMixSamples ( ( uint8 * ) audio_buf , avail ) ;
audio_batch_cb ( audio_buf , avail > > 1 ) ;
}
2012-01-02 00:48:51 +00:00
}
2012-04-10 21:06:17 +00:00
void retro_get_system_info ( struct retro_system_info * info )
2012-01-02 00:48:51 +00:00
{
2012-04-10 21:06:17 +00:00
memset ( info , 0 , sizeof ( retro_system_info ) ) ;
2016-10-08 15:52:38 +00:00
info - > library_name = " Snes9x " ;
2018-05-25 21:56:02 +00:00
# ifndef GIT_VERSION
# define GIT_VERSION ""
# endif
info - > library_version = VERSION GIT_VERSION ;
info - > valid_extensions = " smc|sfc|swc|fig " ;
2012-04-10 21:06:17 +00:00
info - > need_fullpath = false ;
2016-10-08 15:52:38 +00:00
info - > block_extract = false ;
2012-01-02 00:48:51 +00:00
}
2017-07-23 19:11:47 +00:00
float get_aspect_ratio ( unsigned width , unsigned height )
{
2018-05-26 13:15:06 +00:00
if ( aspect_ratio_mode = = ASPECT_RATIO_4_3 )
2017-07-23 19:11:47 +00:00
{
return SNES_4_3 ;
}
2018-05-26 13:15:06 +00:00
else if ( aspect_ratio_mode = = ASPECT_RATIO_8_7 )
{
return SNES_8_7 ;
}
2017-07-23 19:11:47 +00:00
2018-05-26 13:15:06 +00:00
// OV2: not sure if these really make sense - NTSC is similar to 4:3, PAL looks weird
float sample_frequency_ntsc = 135000000.0f / 11.0f ;
2017-07-23 19:11:47 +00:00
float sample_frequency_pal = 14750000.0 ;
float sample_freq = retro_get_region ( ) = = RETRO_REGION_NTSC ? sample_frequency_ntsc : sample_frequency_pal ;
float dot_rate = SNES : : cpu . frequency / 4.0 ;
2018-05-26 13:15:06 +00:00
if ( aspect_ratio_mode = = ASPECT_RATIO_NTSC ) // ntsc
2017-07-23 19:11:47 +00:00
{
sample_freq = sample_frequency_ntsc ;
dot_rate = NTSC_MASTER_CLOCK / 4.0 ;
}
2018-05-26 13:15:06 +00:00
else if ( aspect_ratio_mode = = ASPECT_RATIO_PAL ) // pal
2017-07-23 19:11:47 +00:00
{
sample_freq = sample_frequency_pal ;
dot_rate = PAL_MASTER_CLOCK / 4.0 ;
}
float par = sample_freq / 2.0 / dot_rate ;
return ( float ) width * par / ( float ) height ;
}
2012-04-10 21:06:17 +00:00
void retro_get_system_av_info ( struct retro_system_av_info * info )
2012-01-02 00:48:51 +00:00
{
2012-04-10 21:06:17 +00:00
memset ( info , 0 , sizeof ( retro_system_av_info ) ) ;
2017-07-23 19:11:47 +00:00
unsigned width = SNES_WIDTH ;
unsigned height = PPU . ScreenHeight ;
2018-05-26 13:15:06 +00:00
if ( crop_overscan_mode = = OVERSCAN_CROP_ON )
2017-07-23 19:11:47 +00:00
height = SNES_HEIGHT ;
2018-05-26 13:15:06 +00:00
else if ( crop_overscan_mode = = OVERSCAN_CROP_OFF )
2017-07-23 19:11:47 +00:00
height = SNES_HEIGHT_EXTENDED ;
info - > geometry . base_width = width ;
info - > geometry . base_height = height ;
2012-04-10 21:06:17 +00:00
info - > geometry . max_width = MAX_SNES_WIDTH ;
info - > geometry . max_height = MAX_SNES_HEIGHT ;
2017-07-23 19:11:47 +00:00
info - > geometry . aspect_ratio = get_aspect_ratio ( width , height ) ;
2016-12-10 16:52:05 +00:00
info - > timing . sample_rate = 32040 ;
2012-04-10 21:06:17 +00:00
info - > timing . fps = retro_get_region ( ) = = RETRO_REGION_NTSC ? 21477272.0 / 357366.0 : 21281370.0 / 425568.0 ;
2012-01-02 00:48:51 +00:00
}
2012-04-10 21:06:17 +00:00
unsigned retro_api_version ( )
2012-01-02 00:48:51 +00:00
{
2012-04-10 21:06:17 +00:00
return RETRO_API_VERSION ;
2012-01-02 00:48:51 +00:00
}
2012-04-10 21:06:17 +00:00
void retro_reset ( )
2012-01-02 00:48:51 +00:00
{
S9xSoftReset ( ) ;
}
static unsigned snes_devices [ 2 ] ;
2012-04-10 21:06:17 +00:00
void retro_set_controller_port_device ( unsigned port , unsigned device )
2012-01-02 00:48:51 +00:00
{
2018-05-25 21:56:02 +00:00
if ( port < 2 )
2012-01-02 00:48:51 +00:00
{
2018-05-25 21:56:02 +00:00
int offset = snes_devices [ 0 ] = = RETRO_DEVICE_JOYPAD_MULTITAP ? 4 : 1 ;
switch ( device )
{
case RETRO_DEVICE_JOYPAD :
S9xSetController ( port , CTL_JOYPAD , port * offset , 0 , 0 , 0 ) ;
snes_devices [ port ] = RETRO_DEVICE_JOYPAD ;
break ;
case RETRO_DEVICE_JOYPAD_MULTITAP :
S9xSetController ( port , CTL_MP5 , port * offset , port * offset + 1 , port * offset + 2 , port * offset + 3 ) ;
snes_devices [ port ] = RETRO_DEVICE_JOYPAD_MULTITAP ;
break ;
case RETRO_DEVICE_MOUSE :
S9xSetController ( port , CTL_MOUSE , port , 0 , 0 , 0 ) ;
snes_devices [ port ] = RETRO_DEVICE_MOUSE ;
break ;
case RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE :
S9xSetController ( port , CTL_SUPERSCOPE , 0 , 0 , 0 , 0 ) ;
snes_devices [ port ] = RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE ;
break ;
case RETRO_DEVICE_LIGHTGUN_JUSTIFIER :
S9xSetController ( port , CTL_JUSTIFIER , 0 , 0 , 0 , 0 ) ;
snes_devices [ port ] = RETRO_DEVICE_LIGHTGUN_JUSTIFIER ;
break ;
default :
if ( log_cb )
2018-05-26 13:15:06 +00:00
log_cb ( RETRO_LOG_ERROR , " [libretro]: Invalid device (%d). \n " , device ) ;
2018-05-25 21:56:02 +00:00
}
if ( ! port )
retro_set_controller_port_device ( 1 , snes_devices [ 1 ] ) ;
2012-01-02 00:48:51 +00:00
}
2014-05-29 14:19:31 +00:00
else if ( device ! = RETRO_DEVICE_NONE )
2018-05-25 21:56:02 +00:00
log_cb ( RETRO_LOG_INFO , " [libretro]: Nonexistent Port (%d). \n " , port ) ;
2012-01-02 00:48:51 +00:00
}
2012-04-10 21:06:17 +00:00
void retro_cheat_reset ( )
2013-07-26 17:48:55 +00:00
{
S9xDeleteCheats ( ) ;
}
2012-01-02 00:48:51 +00:00
2017-07-23 19:11:47 +00:00
void retro_cheat_set ( unsigned index , bool enabled , const char * codeline )
2013-07-26 17:48:55 +00:00
{
2017-07-23 19:11:47 +00:00
char codeCopy [ 256 ] ;
char * code ;
2016-12-10 16:52:05 +00:00
2017-07-23 19:11:47 +00:00
if ( codeline = = ( char * ) ' \0 ' ) return ;
2016-12-10 16:52:05 +00:00
2017-07-23 19:11:47 +00:00
strcpy ( codeCopy , codeline ) ;
code = strtok ( codeCopy , " +,.; " ) ;
while ( code ! = NULL ) {
//Convert GH RAW to PAR
if ( strlen ( code ) = = 9 & & code [ 6 ] = = ' : ' )
{
code [ 6 ] = code [ 7 ] ;
code [ 7 ] = code [ 8 ] ;
code [ 8 ] = ' \0 ' ;
}
2016-12-10 16:52:05 +00:00
2018-04-26 20:57:04 +00:00
/* Goldfinger was broken and nobody noticed. Removed */
if ( S9xAddCheatGroup ( " retro " , code ) > = 0 )
2017-07-23 19:11:47 +00:00
{
2018-04-26 20:57:04 +00:00
if ( enabled )
S9xEnableCheatGroup ( Cheat . g . size ( ) - 1 ) ;
2017-07-23 19:11:47 +00:00
}
else
{
printf ( " CHEAT: Failed to recognize %s \n " , code ) ;
}
2018-04-26 20:57:04 +00:00
2017-07-23 19:11:47 +00:00
code = strtok ( NULL , " +,.; " ) ; // bad code, ignore
}
2018-04-26 20:57:04 +00:00
S9xCheatsEnable ( ) ;
2013-07-26 17:48:55 +00:00
}
2012-01-02 00:48:51 +00:00
2016-10-08 15:52:38 +00:00
static void init_descriptors ( void )
{
struct retro_input_descriptor desc [ ] = {
{ 0 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_LEFT , " D-Pad Left " } ,
{ 0 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_UP , " D-Pad Up " } ,
{ 0 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_DOWN , " D-Pad Down " } ,
{ 0 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_RIGHT , " D-Pad Right " } ,
{ 0 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_B , " B " } ,
{ 0 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_A , " A " } ,
{ 0 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_X , " X " } ,
{ 0 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_Y , " Y " } ,
{ 0 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_L , " L " } ,
{ 0 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_R , " R " } ,
{ 0 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_SELECT , " Select " } ,
{ 0 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_START , " Start " } ,
{ 1 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_LEFT , " D-Pad Left " } ,
{ 1 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_UP , " D-Pad Up " } ,
{ 1 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_DOWN , " D-Pad Down " } ,
{ 1 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_RIGHT , " D-Pad Right " } ,
{ 1 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_B , " B " } ,
{ 1 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_A , " A " } ,
{ 1 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_X , " X " } ,
{ 1 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_Y , " Y " } ,
{ 1 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_L , " L " } ,
{ 1 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_R , " R " } ,
{ 1 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_SELECT , " Select " } ,
{ 1 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_START , " Start " } ,
{ 2 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_LEFT , " D-Pad Left " } ,
{ 2 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_UP , " D-Pad Up " } ,
{ 2 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_DOWN , " D-Pad Down " } ,
{ 2 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_RIGHT , " D-Pad Right " } ,
{ 2 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_B , " B " } ,
{ 2 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_A , " A " } ,
{ 2 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_X , " X " } ,
{ 2 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_Y , " Y " } ,
{ 2 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_L , " L " } ,
{ 2 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_R , " R " } ,
{ 2 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_SELECT , " Select " } ,
{ 2 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_START , " Start " } ,
{ 3 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_LEFT , " D-Pad Left " } ,
{ 3 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_UP , " D-Pad Up " } ,
{ 3 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_DOWN , " D-Pad Down " } ,
{ 3 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_RIGHT , " D-Pad Right " } ,
{ 3 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_B , " B " } ,
{ 3 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_A , " A " } ,
{ 3 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_X , " X " } ,
{ 3 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_Y , " Y " } ,
{ 3 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_L , " L " } ,
{ 3 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_R , " R " } ,
{ 3 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_SELECT , " Select " } ,
{ 3 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_START , " Start " } ,
{ 4 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_LEFT , " D-Pad Left " } ,
{ 4 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_UP , " D-Pad Up " } ,
{ 4 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_DOWN , " D-Pad Down " } ,
{ 4 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_RIGHT , " D-Pad Right " } ,
{ 4 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_B , " B " } ,
{ 4 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_A , " A " } ,
{ 4 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_X , " X " } ,
{ 4 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_Y , " Y " } ,
{ 4 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_L , " L " } ,
{ 4 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_R , " R " } ,
{ 4 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_SELECT , " Select " } ,
{ 4 , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_START , " Start " } ,
2018-05-25 21:56:02 +00:00
{ 0 , 0 , 0 , 0 , NULL } ,
2016-10-08 15:52:38 +00:00
} ;
environ_cb ( RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS , desc ) ;
}
2012-04-10 21:06:17 +00:00
bool retro_load_game ( const struct retro_game_info * game )
2012-01-02 00:48:51 +00:00
{
2016-10-08 15:52:38 +00:00
init_descriptors ( ) ;
2017-07-23 19:11:47 +00:00
update_variables ( ) ;
2013-07-26 17:48:55 +00:00
if ( game - > data = = NULL & & game - > size = = 0 & & game - > path ! = NULL )
2012-05-07 22:03:20 +00:00
rom_loaded = Memory . LoadROM ( game - > path ) ;
2012-04-10 21:06:17 +00:00
else
2017-07-23 19:11:47 +00:00
{
if ( game - > path ! = NULL )
{
extract_basename ( g_basename , game - > path , sizeof ( g_basename ) ) ;
extract_directory ( g_rom_dir , game - > path , sizeof ( g_rom_dir ) ) ;
}
2012-05-07 22:03:20 +00:00
rom_loaded = Memory . LoadROMMem ( ( const uint8_t * ) game - > data , game - > size ) ;
2017-07-23 19:11:47 +00:00
}
2012-01-06 19:13:16 +00:00
2018-05-25 21:56:02 +00:00
int pixel_format = RGB555 ;
if ( environ_cb ) {
pixel_format = RGB565 ;
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565 ;
if ( ! environ_cb ( RETRO_ENVIRONMENT_SET_PIXEL_FORMAT , & fmt ) )
pixel_format = RGB555 ;
2016-10-08 15:52:38 +00:00
}
S9xGraphicsDeinit ( ) ;
2018-05-25 21:56:02 +00:00
S9xSetRenderPixelFormat ( pixel_format ) ;
2016-10-08 15:52:38 +00:00
S9xGraphicsInit ( ) ;
2013-12-16 14:18:53 +00:00
if ( ! rom_loaded & & log_cb )
log_cb ( RETRO_LOG_ERROR , " [libretro]: Rom loading failed... \n " ) ;
2016-12-10 16:52:05 +00:00
2012-05-07 22:03:20 +00:00
return rom_loaded ;
2012-04-10 21:06:17 +00:00
}
2012-01-06 19:13:16 +00:00
2012-04-10 21:06:17 +00:00
void retro_unload_game ( void )
{ }
2012-01-06 19:13:16 +00:00
2012-04-10 21:06:17 +00:00
bool retro_load_game_special ( unsigned game_type ,
const struct retro_game_info * info , size_t num_info ) {
2012-01-02 00:48:51 +00:00
2017-07-23 19:11:47 +00:00
init_descriptors ( ) ;
update_variables ( ) ;
2012-04-10 21:06:17 +00:00
switch ( game_type ) {
case RETRO_GAME_TYPE_BSX :
2016-12-10 16:52:05 +00:00
2012-04-10 21:06:17 +00:00
if ( num_info = = 1 ) {
2012-05-07 22:03:20 +00:00
rom_loaded = Memory . LoadROMMem ( ( const uint8_t * ) info [ 0 ] . data , info [ 0 ] . size ) ;
2012-04-10 21:06:17 +00:00
} else if ( num_info = = 2 ) {
memcpy ( Memory . BIOSROM , ( const uint8_t * ) info [ 0 ] . data , info [ 0 ] . size ) ;
2012-05-07 22:03:20 +00:00
rom_loaded = Memory . LoadROMMem ( ( const uint8_t * ) info [ 1 ] . data , info [ 1 ] . size ) ;
2012-04-10 21:06:17 +00:00
}
2012-01-02 00:48:51 +00:00
2013-12-16 14:18:53 +00:00
if ( ! rom_loaded & & log_cb )
log_cb ( RETRO_LOG_ERROR , " [libretro]: BSX ROM loading failed... \n " ) ;
2012-01-06 19:13:16 +00:00
2012-05-07 22:03:20 +00:00
break ;
2016-12-10 16:52:05 +00:00
2012-04-10 21:06:17 +00:00
case RETRO_GAME_TYPE_BSX_SLOTTED :
2012-01-06 19:13:16 +00:00
2012-04-10 21:06:17 +00:00
if ( num_info = = 2 )
2012-05-07 22:03:20 +00:00
rom_loaded = Memory . LoadMultiCartMem ( ( const uint8_t * ) info [ 0 ] . data , info [ 0 ] . size ,
2013-07-26 17:48:55 +00:00
( const uint8_t * ) info [ 1 ] . data , info [ 1 ] . size , NULL , 0 ) ;
2012-01-02 00:48:51 +00:00
2013-12-16 14:18:53 +00:00
if ( ! rom_loaded & & log_cb )
log_cb ( RETRO_LOG_ERROR , " [libretro]: Multirom loading failed... \n " ) ;
2012-04-10 21:06:17 +00:00
2012-05-07 22:03:20 +00:00
break ;
2012-04-10 21:06:17 +00:00
case RETRO_GAME_TYPE_SUFAMI_TURBO :
if ( num_info = = 3 )
2012-05-07 22:03:20 +00:00
rom_loaded = Memory . LoadMultiCartMem ( ( const uint8_t * ) info [ 1 ] . data , info [ 1 ] . size ,
2012-04-10 21:06:17 +00:00
( const uint8_t * ) info [ 2 ] . data , info [ 2 ] . size , ( const uint8_t * ) info [ 0 ] . data , info [ 0 ] . size ) ;
2013-12-16 14:18:53 +00:00
if ( ! rom_loaded & & log_cb )
log_cb ( RETRO_LOG_ERROR , " [libretro]: Sufami Turbo ROM loading failed... \n " ) ;
2012-04-10 21:06:17 +00:00
2012-05-07 22:03:20 +00:00
break ;
2012-04-10 21:06:17 +00:00
default :
2012-05-07 22:03:20 +00:00
rom_loaded = false ;
break ;
2012-04-10 21:06:17 +00:00
}
2012-05-07 22:03:20 +00:00
return rom_loaded ;
2012-01-02 00:48:51 +00:00
}
static void map_buttons ( ) ;
2016-10-08 15:52:38 +00:00
static void check_system_specs ( void )
{
/* TODO - might have to variably set performance level based on SuperFX/SA-1/etc */
unsigned level = 12 ;
environ_cb ( RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL , & level ) ;
}
2012-01-02 00:48:51 +00:00
2018-05-25 21:56:02 +00:00
void retro_init ( void )
2012-01-02 00:48:51 +00:00
{
2013-12-16 14:18:53 +00:00
struct retro_log_callback log ;
2012-01-02 00:48:51 +00:00
2014-01-02 01:20:23 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_LOG_INTERFACE , & log ) )
2013-12-16 14:18:53 +00:00
log_cb = log . log ;
2014-01-02 01:20:23 +00:00
else
log_cb = NULL ;
2013-12-16 14:18:53 +00:00
2012-01-02 00:48:51 +00:00
memset ( & Settings , 0 , sizeof ( Settings ) ) ;
Settings . MouseMaster = TRUE ;
Settings . SuperScopeMaster = TRUE ;
Settings . JustifierMaster = TRUE ;
Settings . MultiPlayer5Master = TRUE ;
Settings . FrameTimePAL = 20000 ;
Settings . FrameTimeNTSC = 16667 ;
Settings . SixteenBitSound = TRUE ;
Settings . Stereo = TRUE ;
2016-12-10 16:52:05 +00:00
Settings . SoundPlaybackRate = 32040 ;
Settings . SoundInputRate = 32040 ;
2012-01-02 00:48:51 +00:00
Settings . SupportHiRes = TRUE ;
Settings . Transparency = TRUE ;
Settings . AutoDisplayMessages = TRUE ;
Settings . InitialInfoStringTimeout = 120 ;
Settings . HDMATimingHack = 100 ;
Settings . BlockInvalidVRAMAccessMaster = TRUE ;
Settings . CartAName [ 0 ] = 0 ;
Settings . CartBName [ 0 ] = 0 ;
Settings . AutoSaveDelay = 1 ;
2012-06-04 17:03:07 +00:00
Settings . DontSaveOopsSnapshot = TRUE ;
2012-01-02 00:48:51 +00:00
CPU . Flags = 0 ;
if ( ! Memory . Init ( ) | | ! S9xInitAPU ( ) )
{
Memory . Deinit ( ) ;
S9xDeinitAPU ( ) ;
2013-12-16 14:18:53 +00:00
if ( log_cb )
log_cb ( RETRO_LOG_ERROR , " [libretro]: Failed to init Memory or APU. \n " ) ;
2012-01-02 00:48:51 +00:00
exit ( 1 ) ;
}
2018-05-25 21:56:02 +00:00
//very slow devices will still pop
//this needs to be applied to all snes9x cores
//increasing the buffer size does not cause extra lag(tested with 1000ms buffer)
//bool8 S9xInitSound (int buffer_ms, int lag_ms)
S9xInitSound ( 32 , 0 ) ; //give it a 1.9 frame long buffer, or 1026 samples. The audio buffer is flushed every 128-132 samples anyway, so it won't get anywhere near there.
2012-01-02 00:48:51 +00:00
S9xSetSoundMute ( FALSE ) ;
S9xSetSamplesAvailableCallback ( S9xAudioCallback , NULL ) ;
2012-04-10 21:06:17 +00:00
GFX . Pitch = MAX_SNES_WIDTH * sizeof ( uint16 ) ;
GFX . Screen = ( uint16 * ) calloc ( 1 , GFX . Pitch * MAX_SNES_HEIGHT ) ;
2012-01-02 00:48:51 +00:00
S9xGraphicsInit ( ) ;
S9xInitInputDevices ( ) ;
for ( int i = 0 ; i < 2 ; i + + )
{
S9xSetController ( i , CTL_JOYPAD , i , 0 , 0 , 0 ) ;
2012-04-10 21:06:17 +00:00
snes_devices [ i ] = RETRO_DEVICE_JOYPAD ;
2012-01-02 00:48:51 +00:00
}
S9xUnmapAllControls ( ) ;
map_buttons ( ) ;
2016-10-08 15:52:38 +00:00
check_system_specs ( ) ;
2012-01-02 00:48:51 +00:00
}
# define MAP_BUTTON(id, name) S9xMapButton((id), S9xGetCommandT((name)), false)
# define MAKE_BUTTON(pad, btn) (((pad)<<4)|(btn))
# define PAD_1 1
# define PAD_2 2
# define PAD_3 3
# define PAD_4 4
# define PAD_5 5
2012-04-10 21:06:17 +00:00
# define BTN_B RETRO_DEVICE_ID_JOYPAD_B
# define BTN_Y RETRO_DEVICE_ID_JOYPAD_Y
# define BTN_SELECT RETRO_DEVICE_ID_JOYPAD_SELECT
# define BTN_START RETRO_DEVICE_ID_JOYPAD_START
# define BTN_UP RETRO_DEVICE_ID_JOYPAD_UP
# define BTN_DOWN RETRO_DEVICE_ID_JOYPAD_DOWN
# define BTN_LEFT RETRO_DEVICE_ID_JOYPAD_LEFT
# define BTN_RIGHT RETRO_DEVICE_ID_JOYPAD_RIGHT
# define BTN_A RETRO_DEVICE_ID_JOYPAD_A
# define BTN_X RETRO_DEVICE_ID_JOYPAD_X
# define BTN_L RETRO_DEVICE_ID_JOYPAD_L
# define BTN_R RETRO_DEVICE_ID_JOYPAD_R
2012-01-02 00:48:51 +00:00
# define BTN_FIRST BTN_B
# define BTN_LAST BTN_R
2012-04-10 21:06:17 +00:00
# define MOUSE_X RETRO_DEVICE_ID_MOUSE_X
# define MOUSE_Y RETRO_DEVICE_ID_MOUSE_Y
# define MOUSE_LEFT RETRO_DEVICE_ID_MOUSE_LEFT
# define MOUSE_RIGHT RETRO_DEVICE_ID_MOUSE_RIGHT
2012-01-02 00:48:51 +00:00
# define MOUSE_FIRST MOUSE_X
# define MOUSE_LAST MOUSE_RIGHT
2012-04-10 21:06:17 +00:00
# define SCOPE_X RETRO_DEVICE_ID_SUPER_SCOPE_X
# define SCOPE_Y RETRO_DEVICE_ID_SUPER_SCOPE_Y
# define SCOPE_TRIGGER RETRO_DEVICE_ID_LIGHTGUN_TRIGGER
# define SCOPE_CURSOR RETRO_DEVICE_ID_LIGHTGUN_CURSOR
# define SCOPE_TURBO RETRO_DEVICE_ID_LIGHTGUN_TURBO
# define SCOPE_PAUSE RETRO_DEVICE_ID_LIGHTGUN_PAUSE
2012-01-02 00:48:51 +00:00
# define SCOPE_FIRST SCOPE_X
# define SCOPE_LAST SCOPE_PAUSE
2012-04-10 21:06:17 +00:00
# define JUSTIFIER_X RETRO_DEVICE_ID_JUSTIFIER_X
# define JUSTIFIER_Y RETRO_DEVICE_ID_JUSTIFIER_Y
# define JUSTIFIER_TRIGGER RETRO_DEVICE_ID_LIGHTGUN_TRIGGER
2016-10-08 15:52:38 +00:00
# define JUSTIFIER_OFFSCREEN RETRO_DEVICE_ID_LIGHTGUN_TURBO
2012-04-10 21:06:17 +00:00
# define JUSTIFIER_START RETRO_DEVICE_ID_LIGHTGUN_PAUSE
2012-01-02 00:48:51 +00:00
# define JUSTIFIER_FIRST JUSTIFIER_X
# define JUSTIFIER_LAST JUSTIFIER_START
# define BTN_POINTER (BTN_LAST + 1)
# define BTN_POINTER2 (BTN_POINTER + 1)
2018-05-25 21:56:02 +00:00
2012-01-02 00:48:51 +00:00
static void map_buttons ( )
{
MAP_BUTTON ( MAKE_BUTTON ( PAD_1 , BTN_A ) , " Joypad1 A " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_1 , BTN_B ) , " Joypad1 B " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_1 , BTN_X ) , " Joypad1 X " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_1 , BTN_Y ) , " Joypad1 Y " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_1 , BTN_SELECT ) , " {Joypad1 Select,Mouse1 L} " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_1 , BTN_START ) , " {Joypad1 Start,Mouse1 R} " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_1 , BTN_L ) , " Joypad1 L " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_1 , BTN_R ) , " Joypad1 R " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_1 , BTN_LEFT ) , " Joypad1 Left " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_1 , BTN_RIGHT ) , " Joypad1 Right " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_1 , BTN_UP ) , " Joypad1 Up " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_1 , BTN_DOWN ) , " Joypad1 Down " ) ;
S9xMapPointer ( ( BTN_POINTER ) , S9xGetCommandT ( " Pointer Mouse1+Superscope+Justifier1 " ) , false ) ;
S9xMapPointer ( ( BTN_POINTER2 ) , S9xGetCommandT ( " Pointer Mouse2 " ) , false ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_2 , BTN_A ) , " Joypad2 A " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_2 , BTN_B ) , " Joypad2 B " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_2 , BTN_X ) , " Joypad2 X " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_2 , BTN_Y ) , " Joypad2 Y " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_2 , BTN_SELECT ) , " {Joypad2 Select,Mouse2 L,Superscope Fire,Justifier1 Trigger} " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_2 , BTN_START ) , " {Joypad2 Start,Mouse2 R,Superscope Cursor,Justifier1 Start} " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_2 , BTN_L ) , " Joypad2 L " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_2 , BTN_R ) , " Joypad2 R " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_2 , BTN_LEFT ) , " Joypad2 Left " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_2 , BTN_RIGHT ) , " Joypad2 Right " ) ;
2016-10-08 15:52:38 +00:00
MAP_BUTTON ( MAKE_BUTTON ( PAD_2 , BTN_UP ) , " {Joypad2 Up,Superscope ToggleTurbo,Justifier1 AimOffscreen} " ) ;
2012-01-02 00:48:51 +00:00
MAP_BUTTON ( MAKE_BUTTON ( PAD_2 , BTN_DOWN ) , " {Joypad2 Down,Superscope Pause} " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_3 , BTN_A ) , " Joypad3 A " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_3 , BTN_B ) , " Joypad3 B " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_3 , BTN_X ) , " Joypad3 X " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_3 , BTN_Y ) , " Joypad3 Y " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_3 , BTN_SELECT ) , " Joypad3 Select " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_3 , BTN_START ) , " Joypad3 Start " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_3 , BTN_L ) , " Joypad3 L " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_3 , BTN_R ) , " Joypad3 R " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_3 , BTN_LEFT ) , " Joypad3 Left " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_3 , BTN_RIGHT ) , " Joypad3 Right " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_3 , BTN_UP ) , " Joypad3 Up " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_3 , BTN_DOWN ) , " Joypad3 Down " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_4 , BTN_A ) , " Joypad4 A " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_4 , BTN_B ) , " Joypad4 B " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_4 , BTN_X ) , " Joypad4 X " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_4 , BTN_Y ) , " Joypad4 Y " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_4 , BTN_SELECT ) , " Joypad4 Select " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_4 , BTN_START ) , " Joypad4 Start " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_4 , BTN_L ) , " Joypad4 L " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_4 , BTN_R ) , " Joypad4 R " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_4 , BTN_LEFT ) , " Joypad4 Left " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_4 , BTN_RIGHT ) , " Joypad4 Right " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_4 , BTN_UP ) , " Joypad4 Up " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_4 , BTN_DOWN ) , " Joypad4 Down " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_5 , BTN_A ) , " Joypad5 A " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_5 , BTN_B ) , " Joypad5 B " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_5 , BTN_X ) , " Joypad5 X " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_5 , BTN_Y ) , " Joypad5 Y " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_5 , BTN_SELECT ) , " Joypad5 Select " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_5 , BTN_START ) , " Joypad5 Start " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_5 , BTN_L ) , " Joypad5 L " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_5 , BTN_R ) , " Joypad5 R " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_5 , BTN_LEFT ) , " Joypad5 Left " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_5 , BTN_RIGHT ) , " Joypad5 Right " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_5 , BTN_UP ) , " Joypad5 Up " ) ;
MAP_BUTTON ( MAKE_BUTTON ( PAD_5 , BTN_DOWN ) , " Joypad5 Down " ) ;
}
2016-12-10 16:52:05 +00:00
// libretro uses relative values for analogue devices.
2012-01-02 00:48:51 +00:00
// S9x seems to use absolute values, but do convert these into relative values in the core. (Why?!)
// Hack around it. :)
static int16_t snes_mouse_state [ 2 ] [ 2 ] = { { 0 } , { 0 } } ;
static int16_t snes_scope_state [ 2 ] = { 0 } ;
static int16_t snes_justifier_state [ 2 ] [ 2 ] = { { 0 } , { 0 } } ;
static void report_buttons ( )
{
int _x , _y ;
2014-06-02 20:20:19 +00:00
int offset = snes_devices [ 0 ] = = RETRO_DEVICE_JOYPAD_MULTITAP ? 4 : 1 ;
2012-04-10 21:06:17 +00:00
for ( int port = 0 ; port < = 1 ; port + + )
2012-01-02 00:48:51 +00:00
{
switch ( snes_devices [ port ] )
{
2012-04-10 21:06:17 +00:00
case RETRO_DEVICE_JOYPAD :
2012-01-02 00:48:51 +00:00
for ( int i = BTN_FIRST ; i < = BTN_LAST ; i + + )
2016-10-08 15:52:38 +00:00
S9xReportButton ( MAKE_BUTTON ( port * offset + 1 , i ) , input_state_cb ( port * offset , RETRO_DEVICE_JOYPAD , 0 , i ) ) ;
2012-01-02 00:48:51 +00:00
break ;
2012-04-10 21:06:17 +00:00
case RETRO_DEVICE_JOYPAD_MULTITAP :
2012-01-02 00:48:51 +00:00
for ( int j = 0 ; j < 4 ; j + + )
for ( int i = BTN_FIRST ; i < = BTN_LAST ; i + + )
2016-10-08 15:52:38 +00:00
S9xReportButton ( MAKE_BUTTON ( port * offset + j + 1 , i ) , input_state_cb ( port * offset + j , RETRO_DEVICE_JOYPAD , 0 , i ) ) ;
2012-01-02 00:48:51 +00:00
break ;
2012-04-10 21:06:17 +00:00
case RETRO_DEVICE_MOUSE :
2016-10-08 15:52:38 +00:00
_x = input_state_cb ( port , RETRO_DEVICE_MOUSE , 0 , RETRO_DEVICE_ID_MOUSE_X ) ;
_y = input_state_cb ( port , RETRO_DEVICE_MOUSE , 0 , RETRO_DEVICE_ID_MOUSE_Y ) ;
2012-01-02 00:48:51 +00:00
snes_mouse_state [ port ] [ 0 ] + = _x ;
snes_mouse_state [ port ] [ 1 ] + = _y ;
S9xReportPointer ( BTN_POINTER + port , snes_mouse_state [ port ] [ 0 ] , snes_mouse_state [ port ] [ 1 ] ) ;
for ( int i = MOUSE_LEFT ; i < = MOUSE_LAST ; i + + )
2016-10-08 15:52:38 +00:00
S9xReportButton ( MAKE_BUTTON ( port + 1 , i ) , input_state_cb ( port , RETRO_DEVICE_MOUSE , 0 , i ) ) ;
2012-01-02 00:48:51 +00:00
break ;
2012-04-10 21:06:17 +00:00
case RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE :
2016-10-08 15:52:38 +00:00
snes_scope_state [ 0 ] + = input_state_cb ( port , RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE , 0 , RETRO_DEVICE_ID_LIGHTGUN_X ) ;
snes_scope_state [ 1 ] + = input_state_cb ( port , RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE , 0 , RETRO_DEVICE_ID_LIGHTGUN_Y ) ;
if ( snes_scope_state [ 0 ] < 0 ) snes_scope_state [ 0 ] = 0 ;
else if ( snes_scope_state [ 0 ] > ( SNES_WIDTH - 1 ) ) snes_scope_state [ 0 ] = SNES_WIDTH - 1 ;
if ( snes_scope_state [ 1 ] < 0 ) snes_scope_state [ 1 ] = 0 ;
else if ( snes_scope_state [ 1 ] > ( SNES_HEIGHT - 1 ) ) snes_scope_state [ 1 ] = SNES_HEIGHT - 1 ;
2012-01-02 00:48:51 +00:00
S9xReportPointer ( BTN_POINTER , snes_scope_state [ 0 ] , snes_scope_state [ 1 ] ) ;
for ( int i = SCOPE_TRIGGER ; i < = SCOPE_LAST ; i + + )
2016-10-08 15:52:38 +00:00
S9xReportButton ( MAKE_BUTTON ( 2 , i ) , input_state_cb ( port , RETRO_DEVICE_LIGHTGUN , 0 , i ) ) ;
2012-01-02 00:48:51 +00:00
break ;
2012-04-10 21:06:17 +00:00
case RETRO_DEVICE_LIGHTGUN_JUSTIFIER :
case RETRO_DEVICE_LIGHTGUN_JUSTIFIERS :
2016-10-08 15:52:38 +00:00
snes_justifier_state [ port ] [ 0 ] + = input_state_cb ( port , RETRO_DEVICE_LIGHTGUN_JUSTIFIER , 0 , RETRO_DEVICE_ID_LIGHTGUN_X ) ;
snes_justifier_state [ port ] [ 1 ] + = input_state_cb ( port , RETRO_DEVICE_LIGHTGUN_JUSTIFIER , 0 , RETRO_DEVICE_ID_LIGHTGUN_Y ) ;
if ( snes_justifier_state [ port ] [ 0 ] < 0 ) snes_justifier_state [ port ] [ 0 ] = 0 ;
else if ( snes_justifier_state [ port ] [ 0 ] > ( SNES_WIDTH - 1 ) ) snes_justifier_state [ port ] [ 0 ] = SNES_WIDTH - 1 ;
if ( snes_justifier_state [ port ] [ 1 ] < 0 ) snes_justifier_state [ port ] [ 1 ] = 0 ;
else if ( snes_justifier_state [ port ] [ 1 ] > ( SNES_HEIGHT - 1 ) ) snes_justifier_state [ port ] [ 1 ] = SNES_HEIGHT - 1 ;
S9xReportPointer ( BTN_POINTER , snes_justifier_state [ port ] [ 0 ] , snes_justifier_state [ port ] [ 1 ] ) ;
2012-01-02 00:48:51 +00:00
for ( int i = JUSTIFIER_TRIGGER ; i < = JUSTIFIER_LAST ; i + + )
2016-10-08 15:52:38 +00:00
S9xReportButton ( MAKE_BUTTON ( 2 , i ) , input_state_cb ( port , RETRO_DEVICE_LIGHTGUN , 0 , i ) ) ;
2012-01-02 00:48:51 +00:00
break ;
2016-12-10 16:52:05 +00:00
2012-01-02 00:48:51 +00:00
default :
2013-12-16 14:18:53 +00:00
if ( log_cb )
log_cb ( RETRO_LOG_ERROR , " [libretro]: Unknown device... \n " ) ;
2012-01-02 00:48:51 +00:00
}
}
}
2012-04-10 21:06:17 +00:00
void retro_run ( )
2012-01-02 00:48:51 +00:00
{
2017-07-23 19:11:47 +00:00
static uint16 height = PPU . ScreenHeight ;
2013-07-25 13:26:55 +00:00
bool updated = false ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE , & updated ) & & updated )
update_variables ( ) ;
2017-07-23 19:11:47 +00:00
if ( height ! = PPU . ScreenHeight )
{
update_geometry ( ) ;
height = PPU . ScreenHeight ;
}
2018-05-25 21:56:02 +00:00
int result = - 1 ;
bool okay = environ_cb ( RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE , & result ) ;
if ( okay )
{
bool audioEnabled = 0 ! = ( result & 2 ) ;
bool videoEnabled = 0 ! = ( result & 1 ) ;
IPPU . RenderThisFrame = videoEnabled ;
S9xSetSoundMute ( ! audioEnabled ) ;
}
else
{
IPPU . RenderThisFrame = true ;
S9xSetSoundMute ( false ) ;
}
2016-10-08 15:52:38 +00:00
poll_cb ( ) ;
2012-01-02 00:48:51 +00:00
report_buttons ( ) ;
S9xMainLoop ( ) ;
2018-05-25 21:56:02 +00:00
S9xAudioCallback ( NULL ) ;
2012-01-02 00:48:51 +00:00
}
2012-04-10 21:06:17 +00:00
void retro_deinit ( )
2012-01-02 00:48:51 +00:00
{
S9xDeinitAPU ( ) ;
Memory . Deinit ( ) ;
S9xGraphicsDeinit ( ) ;
S9xUnmapAllControls ( ) ;
2016-12-10 16:52:05 +00:00
2013-11-14 16:22:20 +00:00
free ( GFX . Screen ) ;
2012-01-02 00:48:51 +00:00
}
2012-04-10 21:06:17 +00:00
unsigned retro_get_region ( )
2016-12-10 16:52:05 +00:00
{
return Settings . PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC ;
2012-01-02 00:48:51 +00:00
}
2012-04-10 21:06:17 +00:00
void * retro_get_memory_data ( unsigned type )
2012-01-02 00:48:51 +00:00
{
2012-04-10 21:06:17 +00:00
void * data ;
2012-01-02 00:48:51 +00:00
switch ( type ) {
2012-04-10 21:06:17 +00:00
case RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM :
case RETRO_MEMORY_SAVE_RAM :
2012-01-02 00:48:51 +00:00
data = Memory . SRAM ;
break ;
2012-04-10 21:06:17 +00:00
case RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM :
2012-01-06 19:13:16 +00:00
data = Multi . sramB ;
break ;
2012-04-10 21:06:17 +00:00
case RETRO_MEMORY_RTC :
2012-01-02 00:48:51 +00:00
data = RTCData . reg ;
break ;
2012-04-10 21:06:17 +00:00
case RETRO_MEMORY_SYSTEM_RAM :
2012-01-02 00:48:51 +00:00
data = Memory . RAM ;
2012-04-26 11:16:58 +00:00
break ;
case RETRO_MEMORY_VIDEO_RAM :
data = Memory . VRAM ;
break ;
2018-05-25 21:56:02 +00:00
//case RETRO_MEMORY_ROM:
// data = Memory.ROM;
// break;
2012-01-02 00:48:51 +00:00
default :
data = NULL ;
break ;
}
return data ;
}
2012-04-10 21:06:17 +00:00
size_t retro_get_memory_size ( unsigned type )
2012-01-02 00:48:51 +00:00
{
2012-04-10 21:06:17 +00:00
size_t size ;
2012-01-02 00:48:51 +00:00
switch ( type ) {
2012-04-10 21:06:17 +00:00
case RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM :
case RETRO_MEMORY_SAVE_RAM :
2012-01-02 00:48:51 +00:00
size = ( unsigned ) ( Memory . SRAMSize ? ( 1 < < ( Memory . SRAMSize + 3 ) ) * 128 : 0 ) ;
if ( size > 0x20000 )
size = 0x20000 ;
break ;
2012-04-10 21:06:17 +00:00
case RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM :
2012-01-06 19:13:16 +00:00
size = ( unsigned ) ( Multi . cartType & & Multi . sramSizeB ? ( 1 < < ( Multi . sramSizeB + 3 ) ) * 128 : 0 ) ;
break ;
2012-04-10 21:06:17 +00:00
case RETRO_MEMORY_RTC :
2012-01-02 00:48:51 +00:00
size = ( Settings . SRTC | | Settings . SPC7110RTC ) ? 20 : 0 ;
break ;
2012-04-26 11:16:58 +00:00
case RETRO_MEMORY_SYSTEM_RAM :
size = 128 * 1024 ;
break ;
case RETRO_MEMORY_VIDEO_RAM :
size = 64 * 1024 ;
break ;
2018-05-25 21:56:02 +00:00
//case RETRO_MEMORY_ROM:
// size = Memory.CalculatedSize;
// break;
2012-01-02 00:48:51 +00:00
default :
size = 0 ;
break ;
}
return size ;
}
2012-04-10 21:06:17 +00:00
size_t retro_serialize_size ( )
2012-01-02 00:48:51 +00:00
{
2012-05-07 22:03:20 +00:00
return rom_loaded ? S9xFreezeSize ( ) : 0 ;
2012-01-02 00:48:51 +00:00
}
2012-04-15 19:46:09 +00:00
bool retro_serialize ( void * data , size_t size )
2016-12-10 16:52:05 +00:00
{
2012-04-15 19:46:09 +00:00
if ( S9xFreezeGameMem ( ( uint8_t * ) data , size ) = = FALSE )
2012-01-02 00:48:51 +00:00
return false ;
return true ;
}
2012-04-15 19:46:09 +00:00
bool retro_unserialize ( const void * data , size_t size )
2016-12-10 16:52:05 +00:00
{
2012-04-15 19:46:09 +00:00
if ( S9xUnfreezeGameMem ( ( const uint8_t * ) data , size ) ! = SUCCESS )
2012-01-02 00:48:51 +00:00
return false ;
2018-05-25 21:56:02 +00:00
2012-01-02 00:48:51 +00:00
return true ;
}
bool8 S9xDeinitUpdate ( int width , int height )
{
2018-05-26 13:15:06 +00:00
if ( crop_overscan_mode = = OVERSCAN_CROP_ON )
2012-01-02 00:48:51 +00:00
{
2012-04-10 21:06:17 +00:00
if ( height > = SNES_HEIGHT < < 1 )
2012-01-02 00:48:51 +00:00
{
2012-04-10 21:06:17 +00:00
height = SNES_HEIGHT < < 1 ;
2012-01-02 00:48:51 +00:00
}
else
{
2012-04-10 21:06:17 +00:00
height = SNES_HEIGHT ;
2012-01-02 00:48:51 +00:00
}
}
2018-05-26 13:15:06 +00:00
else if ( crop_overscan_mode = = OVERSCAN_CROP_OFF )
2012-04-15 19:44:25 +00:00
{
if ( height > SNES_HEIGHT_EXTENDED )
{
if ( height < SNES_HEIGHT_EXTENDED < < 1 )
memset ( GFX . Screen + ( GFX . Pitch > > 1 ) * height , 0 , GFX . Pitch * ( ( SNES_HEIGHT_EXTENDED < < 1 ) - height ) ) ;
height = SNES_HEIGHT_EXTENDED < < 1 ;
}
else
{
if ( height < SNES_HEIGHT_EXTENDED )
memset ( GFX . Screen + ( GFX . Pitch > > 1 ) * height , 0 , GFX . Pitch * ( SNES_HEIGHT_EXTENDED - height ) ) ;
height = SNES_HEIGHT_EXTENDED ;
}
}
2012-01-02 00:48:51 +00:00
2016-10-08 15:52:38 +00:00
video_cb ( GFX . Screen , width , height , GFX . Pitch ) ;
2012-01-02 00:48:51 +00:00
return TRUE ;
}
bool8 S9xContinueUpdate ( int width , int height )
{
2018-05-26 13:15:06 +00:00
return true ;
2012-01-02 00:48:51 +00:00
}
// Dummy functions that should probably be implemented correctly later.
void S9xParsePortConfig ( ConfigFile & , int ) { }
void S9xSyncSpeed ( ) { }
const char * S9xStringInput ( const char * in ) { return in ; }
2017-07-23 19:11:47 +00:00
2018-05-25 21:56:02 +00:00
# ifdef _WIN32
# define SLASH '\\'
# else
# define SLASH ' / '
# endif
2017-07-23 19:11:47 +00:00
const char * S9xGetFilename ( const char * in , s9x_getdirtype type )
{
static char newpath [ 2048 ] ;
newpath [ 0 ] = ' \0 ' ;
switch ( type )
{
case ROMFILENAME_DIR :
2018-05-25 21:56:02 +00:00
sprintf ( newpath , " %s%c%s%s " ,
g_rom_dir , SLASH , g_basename , in ) ;
2017-07-23 19:11:47 +00:00
return newpath ;
default :
break ;
}
return in ;
}
const char * S9xGetDirectory ( s9x_getdirtype type )
{
switch ( type )
{
case ROMFILENAME_DIR :
return g_rom_dir ;
default :
break ;
}
return " " ;
}
2012-01-02 00:48:51 +00:00
void S9xInitInputDevices ( ) { }
2012-01-28 00:52:28 +00:00
const char * S9xChooseFilename ( unsigned char ) { return " " ; }
2012-01-02 00:48:51 +00:00
void S9xHandlePortCommand ( s9xcommand_t , short , short ) { }
bool S9xPollButton ( unsigned int , bool * ) { return false ; }
void S9xToggleSoundChannel ( int ) { }
2012-01-28 00:52:28 +00:00
const char * S9xGetFilenameInc ( const char * in , s9x_getdirtype ) { return " " ; }
2012-01-02 00:48:51 +00:00
const char * S9xBasename ( const char * in ) { return in ; }
bool8 S9xInitUpdate ( ) { return TRUE ; }
void S9xExtraUsage ( ) { }
bool8 S9xOpenSoundDevice ( ) { return TRUE ; }
bool S9xPollAxis ( unsigned int , short * ) { return FALSE ; }
void S9xSetPalette ( ) { }
void S9xParseArg ( char * * , int & , int ) { }
void S9xExit ( ) { }
bool S9xPollPointer ( unsigned int , short * , short * ) { return false ; }
2018-05-25 21:56:02 +00:00
2018-05-26 13:15:06 +00:00
const char * S9xChooseMovieFilename ( unsigned char ) { return NULL ; }
2018-05-25 21:56:02 +00:00
void S9xMessage ( int type , int , const char * s )
{
if ( ! log_cb ) return ;
switch ( type )
{
case S9X_DEBUG :
log_cb ( RETRO_LOG_DEBUG , " %s \n " , s ) ;
break ;
case S9X_WARNING :
log_cb ( RETRO_LOG_WARN , " %s \n " , s ) ;
break ;
case S9X_INFO :
log_cb ( RETRO_LOG_INFO , " %s \n " , s ) ;
break ;
case S9X_ERROR :
log_cb ( RETRO_LOG_ERROR , " %s \n " , s ) ;
break ;
default :
log_cb ( RETRO_LOG_DEBUG , " %s \n " , s ) ;
break ;
}
}
2012-01-02 00:48:51 +00:00
2016-12-10 16:52:05 +00:00
bool8 S9xOpenSnapshotFile ( const char * filepath , bool8 read_only , STREAM * file )
{
2012-01-02 00:48:51 +00:00
if ( read_only )
{
if ( ( * file = OPEN_STREAM ( filepath , " rb " ) ) ! = 0 )
{
return ( TRUE ) ;
}
}
else
{
if ( ( * file = OPEN_STREAM ( filepath , " wb " ) ) ! = 0 )
{
return ( TRUE ) ;
}
}
return ( FALSE ) ;
}
2016-12-10 16:52:05 +00:00
void S9xCloseSnapshotFile ( STREAM file )
2012-01-02 00:48:51 +00:00
{
CLOSE_STREAM ( file ) ;
}
2016-12-10 16:52:05 +00:00
void S9xAutoSaveSRAM ( )
2012-01-02 00:48:51 +00:00
{
return ;
}
# ifndef __WIN32__
// S9x weirdness.
void _splitpath ( const char * path , char * drive , char * dir , char * fname , char * ext )
{
* drive = 0 ;
const char * slash = strrchr ( path , SLASH_CHAR ) ,
* dot = strrchr ( path , ' . ' ) ;
if ( dot & & slash & & dot < slash )
dot = NULL ;
if ( ! slash )
{
* dir = 0 ;
strcpy ( fname , path ) ;
if ( dot )
{
fname [ dot - path ] = 0 ;
strcpy ( ext , dot + 1 ) ;
}
else
* ext = 0 ;
}
else
{
strcpy ( dir , path ) ;
dir [ slash - path ] = 0 ;
strcpy ( fname , slash + 1 ) ;
if ( dot )
{
fname [ dot - slash - 1 ] = 0 ;
strcpy ( ext , dot + 1 ) ;
}
else
* ext = 0 ;
}
}
void _makepath ( char * path , const char * , const char * dir , const char * fname , const char * ext )
{
if ( dir & & * dir )
{
strcpy ( path , dir ) ;
strcat ( path , SLASH_STR ) ;
}
else
* path = 0 ;
strcat ( path , fname ) ;
if ( ext & & * ext )
{
strcat ( path , " . " ) ;
strcat ( path , ext ) ;
}
}
# endif // __WIN32__