2012-06-03 15:48:14 +00:00
# include "mednafen/mednafen.h"
2012-11-29 22:21:44 +00:00
# include "mednafen/mempatcher.h"
2012-06-03 15:48:14 +00:00
# include "mednafen/git.h"
# include "mednafen/general.h"
2020-09-22 04:38:41 +00:00
# include "mednafen/settings.h"
2016-04-08 18:14:31 +00:00
# include <compat/msvc.h>
2016-02-09 22:05:19 +00:00
# include "mednafen/psx/gpu.h"
2012-11-16 14:12:25 +00:00
# ifdef NEED_DEINTERLACER
2016-01-31 03:07:57 +00:00
# include "mednafen/video/Deinterlacer.h"
2012-11-16 14:12:25 +00:00
# endif
2017-12-15 22:20:53 +00:00
# include <libretro.h>
2015-07-29 01:37:42 +00:00
# include <rthreads/rthreads.h>
2017-12-18 13:35:54 +00:00
# include <streams/file_stream.h>
2016-06-09 05:59:14 +00:00
# include <string/stdstring.h>
2017-10-08 12:48:06 +00:00
# include <rhash.h>
2019-07-02 02:15:43 +00:00
# include "ugui_tools.h"
2016-04-08 15:03:52 +00:00
# include "rsx/rsx_intf.h"
2016-05-25 16:14:19 +00:00
# include "libretro_cbs.h"
2019-12-08 17:26:41 +00:00
# include "beetle_psx_globals.h"
2016-12-05 00:14:08 +00:00
# include "libretro_options.h"
2017-11-19 10:45:16 +00:00
# include "input.h"
2014-06-16 20:55:26 +00:00
2020-05-13 22:40:38 +00:00
# include "parallel-psx/custom-textures/dbg_input_callback.h"
retro_input_state_t dbg_input_state_cb = 0 ;
2017-02-18 02:14:24 +00:00
# include "mednafen/mednafen-endian.h"
2020-03-04 09:24:26 +00:00
# include "mednafen/mednafen-types.h"
2018-02-08 11:14:56 +00:00
# include "mednafen/psx/psx.h"
2018-02-21 22:11:20 +00:00
# include "mednafen/error.h"
2017-02-18 02:14:24 +00:00
2020-03-04 09:24:26 +00:00
# include "pgxp/pgxp_main.h"
2016-09-25 10:52:57 +00:00
2022-12-14 18:52:07 +00:00
# if defined(HAVE_ASHMEM) || defined(HAVE_SHM)
2022-12-14 18:16:51 +00:00
# include <errno.h>
# endif
2017-04-06 17:46:37 +00:00
# include <vector>
# define ISHEXDEC ((codeLine[cursor]>='0') && (codeLine[cursor]<='9')) || ((codeLine[cursor]>='a') && (codeLine[cursor]<='f')) || ((codeLine[cursor]>='A') && (codeLine[cursor]<='F'))
2020-01-21 23:26:20 +00:00
# ifdef HAVE_LIGHTREC
# include <sys/mman.h>
# ifdef HAVE_ASHMEM
# include <sys/ioctl.h>
# include <linux/ashmem.h>
2021-05-12 16:18:32 +00:00
# include <dlfcn.h>
2020-01-21 23:26:20 +00:00
# endif
2020-05-17 00:16:57 +00:00
# if defined(HAVE_SHM) || defined(HAVE_ASHMEM)
2020-06-10 13:01:02 +00:00
# include <sys/stat.h>
2020-01-21 23:26:20 +00:00
# include <fcntl.h>
# endif
# ifdef HAVE_WIN_SHM
# include <windows.h>
# endif
2020-05-17 00:16:57 +00:00
# endif /* HAVE_LIGHTREC */
2020-01-21 23:26:20 +00:00
2018-04-24 01:16:53 +00:00
//Fast Save States exclude string labels from variables in the savestate, and are at least 20% faster.
extern bool FastSaveStates ;
const int DEFAULT_STATE_SIZE = 16 * 1024 * 1024 ;
2021-08-16 04:02:21 +00:00
static bool libretro_supports_option_categories = false ;
2019-07-07 07:23:53 +00:00
static bool libretro_supports_bitmasks = false ;
2020-05-29 13:43:50 +00:00
static unsigned libretro_msg_interface_version = 0 ;
2019-07-07 07:23:53 +00:00
2014-06-16 22:31:15 +00:00
struct retro_perf_callback perf_cb ;
retro_get_cpu_features_t perf_get_cpu_features_cb = NULL ;
retro_log_printf_t log_cb ;
static retro_audio_sample_t audio_cb ;
static retro_audio_sample_batch_t audio_batch_cb ;
static retro_input_poll_t input_poll_cb ;
static retro_input_state_t input_state_cb ;
2016-02-07 13:57:39 +00:00
static unsigned frame_count = 0 ;
static unsigned internal_frame_count = 0 ;
static bool display_internal_framerate = false ;
2016-02-07 22:43:26 +00:00
static bool allow_frame_duping = false ;
2016-02-13 19:56:18 +00:00
static bool failed_init = false ;
2016-05-22 14:24:43 +00:00
static unsigned image_offset = 0 ;
2016-05-30 00:59:25 +00:00
static unsigned image_crop = 0 ;
2016-06-09 23:42:57 +00:00
static bool enable_memcard1 = false ;
2016-10-08 22:33:41 +00:00
static bool enable_variable_serialization_size = false ;
2018-06-30 23:32:16 +00:00
static int frame_width = 0 ;
static int frame_height = 0 ;
static bool gui_inited = false ;
static bool gui_show = false ;
2020-05-24 23:08:26 +00:00
static char bios_path [ 4096 ] ;
static bool firmware_found = false ;
2018-06-30 23:32:16 +00:00
2020-05-26 03:02:51 +00:00
// Switchable memory cards
static int memcard_left_index = 0 ;
static int memcard_left_index_old ;
static int memcard_right_index = 1 ;
static int memcard_right_index_old ;
2017-10-08 21:04:32 +00:00
unsigned cd_2x_speedup = 1 ;
2017-10-15 19:48:44 +00:00
bool cd_async = false ;
2017-10-15 21:39:47 +00:00
bool cd_warned_slow = false ;
int64 cd_slow_timeout = 8000 ; // microseconds
2016-02-07 13:57:39 +00:00
2020-03-24 00:16:02 +00:00
// If true, PAL games will run at 60fps
bool fast_pal = false ;
2020-01-21 23:26:20 +00:00
# ifdef HAVE_LIGHTREC
enum DYNAREC psx_dynarec ;
bool psx_dynarec_invalidate ;
2020-05-17 00:16:57 +00:00
uint8 psx_mmap = 0 ;
uint8 * psx_mem = NULL ;
uint8 * psx_bios = NULL ;
uint8 * psx_scratch = NULL ;
# if defined(HAVE_ASHMEM)
2020-01-27 07:21:23 +00:00
int memfd ;
2020-01-21 23:26:20 +00:00
# endif
# endif
2020-01-27 07:21:23 +00:00
uint32 EventCycles = 128 ;
2022-09-01 03:37:29 +00:00
uint8_t spu_samples = 1 ;
2020-01-21 23:26:20 +00:00
2018-02-08 11:14:56 +00:00
// CPU overclock factor (or 0 if disabled)
int32_t psx_overclock_factor = 0 ;
2018-02-09 10:09:28 +00:00
// GPU rasterizer overclock shift
unsigned psx_gpu_overclock_shift = 0 ;
2018-02-08 11:14:56 +00:00
2016-02-07 13:57:39 +00:00
// Sets how often (in number of output frames/retro_run invocations)
// the internal framerace counter should be updated if
// display_internal_framerate is true.
2018-02-09 14:06:18 +00:00
# define INTERNAL_FPS_SAMPLE_PERIOD 64
2014-06-16 22:31:15 +00:00
2015-12-13 02:33:01 +00:00
static int psx_skipbios ;
2021-10-08 21:55:58 +00:00
static int override_bios ;
2015-12-13 02:33:01 +00:00
2018-02-08 18:19:43 +00:00
bool psx_gte_overclock ;
2016-02-08 14:15:26 +00:00
enum dither_mode psx_gpu_dither_mode ;
2016-09-25 10:52:57 +00:00
//iCB: PGXP options
unsigned int psx_pgxp_mode ;
2020-09-18 16:36:36 +00:00
int psx_pgxp_2d_tol ;
2016-09-25 10:52:57 +00:00
unsigned int psx_pgxp_vertex_caching ;
unsigned int psx_pgxp_texture_correction ;
2020-09-22 23:19:18 +00:00
unsigned int psx_pgxp_nclip ;
2016-09-25 10:52:57 +00:00
// \iCB
2018-08-21 16:07:54 +00:00
# define NEGCON_RANGE 0x7FFF
2015-09-30 01:39:52 +00:00
char retro_save_directory [ 4096 ] ;
char retro_base_directory [ 4096 ] ;
2020-05-13 22:40:38 +00:00
char retro_cd_base_directory [ 4096 ] ;
2015-09-30 01:39:52 +00:00
static char retro_cd_path [ 4096 ] ;
char retro_cd_base_name [ 4096 ] ;
# ifdef _WIN32
static char retro_slash = ' \\ ' ;
# else
static char retro_slash = ' / ' ;
# endif
2017-10-05 23:12:24 +00:00
enum
{
REGION_JP = 0 ,
REGION_NA = 1 ,
REGION_EU = 2 ,
} ;
static bool firmware_is_present ( unsigned region )
{
2017-10-08 13:24:16 +00:00
static const size_t list_size = 10 ;
2017-10-08 12:48:06 +00:00
const char * bios_name_list [ list_size ] ;
2018-04-18 22:54:32 +00:00
const char * bios_sha1 = NULL ;
2017-11-19 10:45:16 +00:00
2020-06-17 09:05:20 +00:00
log_cb ( RETRO_LOG_INFO , " Checking if required firmware is present... \n " ) ;
2017-10-08 20:41:50 +00:00
2017-10-08 13:24:16 +00:00
/* SHA1 and alternate BIOS names sourced from
https : //github.com/mamedev/mame/blob/master/src/mame/drivers/psx.cpp */
2021-10-08 21:55:58 +00:00
2021-10-09 00:41:51 +00:00
if ( override_bios )
{
if ( override_bios = = 1 )
{
2021-10-08 21:55:58 +00:00
bios_name_list [ 0 ] = " psxonpsp660.bin " ;
bios_name_list [ 1 ] = " PSXONPSP660.bin " ;
bios_name_list [ 2 ] = NULL ;
bios_sha1 = " 96880D1CA92A016FF054BE5159BB06FE03CB4E14 " ;
2021-10-09 00:41:51 +00:00
}
2021-10-08 21:55:58 +00:00
2021-10-09 00:41:51 +00:00
else if ( override_bios = = 2 )
{
2021-10-08 21:55:58 +00:00
bios_name_list [ 0 ] = " ps1_rom.bin " ;
bios_name_list [ 1 ] = " PS1_ROM.bin " ;
bios_name_list [ 2 ] = NULL ;
bios_sha1 = " C40146361EB8CF670B19FDC9759190257803CAB7 " ;
2021-10-09 00:41:51 +00:00
}
2021-10-08 21:55:58 +00:00
2021-10-09 00:41:51 +00:00
size_t i ;
for ( i = 0 ; i < list_size ; + + i )
{
if ( ! bios_name_list [ i ] )
break ;
int r = snprintf ( bios_path , sizeof ( bios_path ) , " %s%c%s " , retro_base_directory , retro_slash , bios_name_list [ i ] ) ;
if ( r > = 4096 )
{
bios_path [ 4095 ] = ' \0 ' ;
log_cb ( RETRO_LOG_ERROR , " Firmware path longer than 4095: %s \n " , bios_path ) ;
break ;
}
if ( filestream_exists ( bios_path ) )
{
firmware_found = true ;
break ;
}
}
if ( firmware_found )
{
char obtained_sha1 [ 41 ] ;
sha1_calculate ( bios_path , obtained_sha1 ) ;
if ( strcmp ( obtained_sha1 , bios_sha1 ) )
{
log_cb ( RETRO_LOG_WARN , " Override firmware found but has invalid SHA1: %s \n " , bios_path ) ;
log_cb ( RETRO_LOG_WARN , " Expected SHA1: %s \n " , bios_sha1 ) ;
log_cb ( RETRO_LOG_WARN , " Obtained SHA1: %s \n " , obtained_sha1 ) ;
log_cb ( RETRO_LOG_WARN , " Unsupported firmware may cause emulation glitches. \n " ) ;
return true ;
}
log_cb ( RETRO_LOG_INFO , " Override firmware found: %s \n " , bios_path ) ;
log_cb ( RETRO_LOG_INFO , " Override firmware SHA1: %s \n " , obtained_sha1 ) ;
return true ;
}
2021-10-08 21:55:58 +00:00
log_cb ( RETRO_LOG_WARN , " Override firmware is missing: %s \n " , bios_name_list [ 0 ] ) ;
log_cb ( RETRO_LOG_WARN , " Fallback to region specific firmware. \n " ) ;
}
2017-10-05 23:12:24 +00:00
if ( region = = REGION_JP )
{
2017-10-08 12:48:06 +00:00
bios_name_list [ 0 ] = " scph5500.bin " ;
bios_name_list [ 1 ] = " SCPH5500.bin " ;
bios_name_list [ 2 ] = " SCPH-5500.bin " ;
2017-10-08 20:02:22 +00:00
bios_name_list [ 3 ] = NULL ;
2017-10-08 13:24:16 +00:00
bios_sha1 = " B05DEF971D8EC59F346F2D9AC21FB742E3EB6917 " ;
2017-10-08 12:48:06 +00:00
}
2017-11-19 10:45:16 +00:00
else if ( region = = REGION_NA )
2017-10-08 12:48:06 +00:00
{
bios_name_list [ 0 ] = " scph5501.bin " ;
bios_name_list [ 1 ] = " SCPH5501.bin " ;
bios_name_list [ 2 ] = " SCPH-5501.bin " ;
bios_name_list [ 3 ] = " scph5503.bin " ;
bios_name_list [ 4 ] = " SCPH5503.bin " ;
bios_name_list [ 5 ] = " SCPH-5503.bin " ;
bios_name_list [ 6 ] = " scph7003.bin " ;
bios_name_list [ 7 ] = " SCPH7003.bin " ;
bios_name_list [ 8 ] = " SCPH-7003.bin " ;
2017-10-08 20:02:22 +00:00
bios_name_list [ 9 ] = NULL ;
2017-10-08 13:24:16 +00:00
bios_sha1 = " 0555C6FAE8906F3F09BAF5988F00E55F88E9F30B " ;
2017-10-08 12:48:06 +00:00
}
2017-11-19 10:45:16 +00:00
else if ( region = = REGION_EU )
2017-10-08 12:48:06 +00:00
{
bios_name_list [ 0 ] = " scph5502.bin " ;
bios_name_list [ 1 ] = " SCPH5502.bin " ;
bios_name_list [ 2 ] = " SCPH-5502.bin " ;
bios_name_list [ 3 ] = " scph5552.bin " ;
bios_name_list [ 4 ] = " SCPH5552.bin " ;
bios_name_list [ 5 ] = " SCPH-5552.bin " ;
2017-10-08 20:02:22 +00:00
bios_name_list [ 6 ] = NULL ;
2017-10-08 13:24:16 +00:00
bios_sha1 = " F6BC2D1F5EB6593DE7D089C425AC681D6FFFD3F0 " ;
2017-10-08 12:48:06 +00:00
}
size_t i ;
for ( i = 0 ; i < list_size ; + + i )
{
2017-10-08 20:02:22 +00:00
if ( ! bios_name_list [ i ] )
break ;
2017-11-19 10:45:16 +00:00
2020-05-17 22:17:32 +00:00
int r = snprintf ( bios_path , sizeof ( bios_path ) , " %s%c%s " , retro_base_directory , retro_slash , bios_name_list [ i ] ) ;
if ( r > = 4096 )
{
2021-04-22 02:55:06 +00:00
bios_path [ 4095 ] = ' \0 ' ;
2020-05-17 22:17:32 +00:00
log_cb ( RETRO_LOG_ERROR , " Firmware path longer than 4095: %s \n " , bios_path ) ;
break ;
}
2017-12-18 13:35:54 +00:00
if ( filestream_exists ( bios_path ) )
2017-10-08 12:48:06 +00:00
{
2020-05-24 23:08:26 +00:00
firmware_found = true ;
2017-10-08 12:48:06 +00:00
break ;
2017-11-19 10:45:16 +00:00
}
2017-10-08 12:48:06 +00:00
}
2020-05-24 23:08:26 +00:00
if ( ! firmware_found )
2017-10-08 12:48:06 +00:00
{
2018-06-30 23:32:16 +00:00
char s [ 4096 ] ;
2017-10-08 20:41:50 +00:00
log_cb ( RETRO_LOG_ERROR , " Firmware is missing: %s \n " , bios_name_list [ 0 ] ) ;
2018-06-30 23:59:45 +00:00
s [ 4095 ] = ' \0 ' ;
2018-06-30 23:32:16 +00:00
snprintf ( s , sizeof ( s ) , " Firmware is missing: \n \n %s " , bios_name_list [ 0 ] ) ;
gui_set_message ( s ) ;
gui_show = true ;
2019-06-16 20:00:13 +00:00
2018-06-30 23:59:45 +00:00
return false ;
2017-10-05 23:12:24 +00:00
}
2017-10-08 12:48:06 +00:00
char obtained_sha1 [ 41 ] ;
sha1_calculate ( bios_path , obtained_sha1 ) ;
2017-10-08 13:24:16 +00:00
if ( strcmp ( obtained_sha1 , bios_sha1 ) )
2017-10-08 12:48:06 +00:00
{
2017-10-08 20:41:50 +00:00
log_cb ( RETRO_LOG_WARN , " Firmware found but has invalid SHA1: %s \n " , bios_path ) ;
log_cb ( RETRO_LOG_WARN , " Expected SHA1: %s \n " , bios_sha1 ) ;
log_cb ( RETRO_LOG_WARN , " Obtained SHA1: %s \n " , obtained_sha1 ) ;
log_cb ( RETRO_LOG_WARN , " Unsupported firmware may cause emulation glitches. \n " ) ;
return true ;
2017-10-08 12:48:06 +00:00
}
2017-10-08 13:24:16 +00:00
log_cb ( RETRO_LOG_INFO , " Firmware found: %s \n " , bios_path ) ;
2017-10-08 20:41:50 +00:00
log_cb ( RETRO_LOG_INFO , " Firmware SHA1: %s \n " , obtained_sha1 ) ;
2017-11-19 10:45:16 +00:00
2017-10-06 01:32:16 +00:00
return true ;
2017-10-05 23:12:24 +00:00
}
2015-09-30 01:39:52 +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 + + ;
2020-05-17 22:17:32 +00:00
strncpy ( buf , base , size - strlen ( buf ) - 1 ) ;
2015-09-30 01:39:52 +00:00
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 ' ;
}
2014-06-15 17:20:33 +00:00
/* start of Mednafen psx.cpp */
/* Mednafen - Multi-system Emulator
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include "mednafen/psx/psx.h"
# include "mednafen/psx/mdec.h"
# include "mednafen/psx/frontio.h"
# include "mednafen/psx/timer.h"
# include "mednafen/psx/sio.h"
# include "mednafen/psx/cdc.h"
# include "mednafen/psx/spu.h"
# include "mednafen/mempatcher.h"
# include <stdarg.h>
# include <ctype.h>
2014-07-27 19:03:37 +00:00
bool setting_apply_analog_toggle = false ;
bool use_mednafen_memcard0_method = false ;
2014-06-16 20:25:12 +00:00
2014-06-15 17:20:33 +00:00
extern MDFNGI EmulatedPSX ;
# if PSX_DBGPRINT_ENABLE
static unsigned psx_dbg_level = 0 ;
2014-06-16 21:58:16 +00:00
void PSX_DBG ( unsigned level , const char * format , . . . )
2014-06-15 17:20:33 +00:00
{
if ( psx_dbg_level > = level )
2015-07-30 04:54:33 +00:00
{
va_list ap ;
va_start ( ap , format ) ;
2016-06-06 00:20:56 +00:00
vprintf ( format , ap ) ;
2015-07-30 04:54:33 +00:00
va_end ( ap ) ;
}
2014-06-15 17:20:33 +00:00
}
2015-05-06 12:33:31 +00:00
# else
static unsigned const psx_dbg_level = 0 ;
2014-06-15 17:20:33 +00:00
# endif
2015-07-30 05:11:21 +00:00
/* Based off(but not the same as) public-domain "JKISS" PRNG. */
struct MDFN_PseudoRNG
2014-06-15 17:20:33 +00:00
{
uint32_t x , y , z , c ;
uint64_t lcgo ;
} ;
static MDFN_PseudoRNG PSX_PRNG ;
uint32_t PSX_GetRandU32 ( uint32_t mina , uint32_t maxa )
{
2015-07-30 05:11:21 +00:00
uint32_t tmp ;
const uint32_t range_m1 = maxa - mina ;
uint32_t range_mask = range_m1 ;
range_mask | = range_mask > > 1 ;
range_mask | = range_mask > > 2 ;
range_mask | = range_mask > > 4 ;
range_mask | = range_mask > > 8 ;
range_mask | = range_mask > > 16 ;
do
{
uint64_t t = 4294584393ULL * PSX_PRNG . z + PSX_PRNG . c ;
PSX_PRNG . x = 314527869 * PSX_PRNG . x + 1234567 ;
PSX_PRNG . y ^ = PSX_PRNG . y < < 5 ;
PSX_PRNG . y ^ = PSX_PRNG . y > > 7 ;
PSX_PRNG . y ^ = PSX_PRNG . y < < 22 ;
PSX_PRNG . c = t > > 32 ;
PSX_PRNG . z = t ;
PSX_PRNG . lcgo = ( 19073486328125ULL * PSX_PRNG . lcgo ) + 1 ;
tmp = ( ( PSX_PRNG . x + PSX_PRNG . y + PSX_PRNG . z ) ^ ( PSX_PRNG . lcgo > > 16 ) ) & range_mask ;
} while ( tmp > range_m1 ) ;
return ( mina + tmp ) ;
2014-06-15 17:20:33 +00:00
}
2020-02-03 17:17:44 +00:00
static std : : vector < CDIF * > CDInterfaces ; // FIXME: Cleanup on error out.
2014-06-16 02:10:39 +00:00
static std : : vector < CDIF * > * cdifs = NULL ;
static std : : vector < const char * > cdifs_scex_ids ;
2020-02-03 17:17:44 +00:00
static bool eject_state ;
2014-06-16 02:10:39 +00:00
static bool CD_TrayOpen ;
2016-05-10 12:00:53 +00:00
int CD_SelectedDisc ; // -1 for no disc
static bool CD_IsPBP = false ;
extern int PBP_DiscCount ;
2020-04-09 10:38:02 +00:00
/* The global value PBP_DiscCount is set to
* zero when loading single - disk PBP files .
* We therefore have to maintain a separate
* ' physical ' disk count , otherwise the
* frontend disk control interface will fail */
static int PBP_PhysicalDiscCount ;
2014-06-15 17:20:33 +00:00
2020-02-03 17:17:44 +00:00
typedef struct
{
unsigned initial_index ;
std : : string initial_path ;
std : : vector < std : : string > image_paths ;
std : : vector < std : : string > image_labels ;
} disk_control_ext_info_t ;
static disk_control_ext_info_t disk_control_ext_info ;
2014-06-15 17:20:33 +00:00
static uint64_t Memcard_PrevDC [ 8 ] ;
static int64_t Memcard_SaveDelay [ 8 ] ;
2019-07-14 20:05:54 +00:00
PS_CPU * PSX_CPU = NULL ;
PS_SPU * PSX_SPU = NULL ;
PS_CDC * PSX_CDC = NULL ;
FrontIO * PSX_FIO = NULL ;
2014-06-15 17:20:33 +00:00
2020-01-21 23:26:20 +00:00
MultiAccessSizeMem < 512 * 1024 , uint32 , false > * BIOSROM = NULL ;
MultiAccessSizeMem < 65536 , uint32 , false > * PIOMem = NULL ;
2020-04-06 11:53:56 +00:00
MultiAccessSizeMem < 2048 * 1024 , uint32 , false > * MainRAM = NULL ;
2020-01-21 23:26:20 +00:00
MultiAccessSizeMem < 1024 , uint32 , false > * ScratchRAM = NULL ;
# ifdef HAVE_LIGHTREC
/* Size of Expansion 1 (8MB) */
# define PSX_EXPANSION1_SIZE 0x800000U
/* Base address of Expansion 1 */
# define PSX_EXPANSION1_BASE 0x1F000000U
/* Mednafen splits the expansion in two buffers (PIOMem and TextMem). That's not
* super convenient for us so I ' m going to copy both of them in one contiguous
* buffer */
const uint8_t * PSX_LoadExpansion1 ( void ) {
static uint8_t * expansion1 = NULL ;
if ( expansion1 = = NULL ) {
expansion1 = new uint8_t [ PSX_EXPANSION1_SIZE ] ;
}
/* Let's read 32bits at a time to speed things up a bit */
uint32_t * p = reinterpret_cast < uint32_t * > ( expansion1 ) ;
2014-06-15 17:20:33 +00:00
2020-01-21 23:26:20 +00:00
for ( unsigned i = 0 ; i < PSX_EXPANSION1_SIZE / 4 ; i + + ) {
p [ i ] = PSX_MemPeek32 ( PSX_EXPANSION1_BASE + i * 4 ) ;
}
return expansion1 ;
}
# endif
2014-06-15 17:20:33 +00:00
static uint32_t TextMem_Start ;
static std : : vector < uint8 > TextMem ;
static const uint32_t SysControl_Mask [ 9 ] = { 0x00ffffff , 0x00ffffff , 0xffffffff , 0x2f1fffff ,
2017-07-31 02:42:23 +00:00
0xffffffff , 0x2f1fffff , 0x2f1fffff , 0xffffffff ,
0x0003ffff } ;
2014-06-15 17:20:33 +00:00
static const uint32_t SysControl_OR [ 9 ] = { 0x1f000000 , 0x1f000000 , 0x00000000 , 0x00000000 ,
2017-07-31 02:42:23 +00:00
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 ,
0x00000000 } ;
2014-06-15 17:20:33 +00:00
static struct
{
2017-07-31 02:42:23 +00:00
union
{
struct
{
uint32_t PIO_Base ; // 0x1f801000 // BIOS Init: 0x1f000000, Writeable bits: 0x00ffffff(assumed, verify), FixedOR = 0x1f000000
uint32_t Unknown0 ; // 0x1f801004 // BIOS Init: 0x1f802000, Writeable bits: 0x00ffffff, FixedOR = 0x1f000000
uint32_t Unknown1 ; // 0x1f801008 // BIOS Init: 0x0013243f, ????
uint32_t Unknown2 ; // 0x1f80100c // BIOS Init: 0x00003022, Writeable bits: 0x2f1fffff, FixedOR = 0x00000000
uint32_t BIOS_Mapping ; // 0x1f801010 // BIOS Init: 0x0013243f, ????
uint32_t SPU_Delay ; // 0x1f801014 // BIOS Init: 0x200931e1, Writeable bits: 0x2f1fffff, FixedOR = 0x00000000 - Affects bus timing on access to SPU
uint32_t CDC_Delay ; // 0x1f801018 // BIOS Init: 0x00020843, Writeable bits: 0x2f1fffff, FixedOR = 0x00000000
uint32_t Unknown4 ; // 0x1f80101c // BIOS Init: 0x00070777, ????
uint32_t Unknown5 ; // 0x1f801020 // BIOS Init: 0x00031125(but rewritten with other values often), Writeable bits: 0x0003ffff, FixedOR = 0x00000000 -- Possibly CDC related
} ;
uint32_t Regs [ 9 ] ;
} ;
2014-06-15 17:20:33 +00:00
} SysControl ;
2015-05-06 12:33:31 +00:00
static unsigned DMACycleSteal = 0 ; // Doesn't need to be saved in save states, since it's calculated in the ForceEventUpdates() call chain.
void PSX_SetDMACycleSteal ( unsigned stealage )
{
if ( stealage > 200 ) // Due to 8-bit limitations in the CPU core.
stealage = 200 ;
DMACycleSteal = stealage ;
}
2014-06-15 17:20:33 +00:00
//
// Event stuff
//
2017-07-31 02:42:23 +00:00
static int32_t Running ; // Set to -1 when not desiring exit, and 0 when we are.
2014-06-15 17:20:33 +00:00
struct event_list_entry
{
2017-07-31 02:42:23 +00:00
uint32_t which ;
int32_t event_time ;
event_list_entry * prev ;
event_list_entry * next ;
2014-06-15 17:20:33 +00:00
} ;
static event_list_entry events [ PSX_EVENT__COUNT ] ;
static void EventReset ( void )
{
unsigned i ;
for ( i = 0 ; i < PSX_EVENT__COUNT ; i + + )
{
events [ i ] . which = i ;
if ( i = = PSX_EVENT__SYNFIRST )
2017-07-31 02:42:23 +00:00
events [ i ] . event_time = ( int32_t ) 0x80000000 ;
2014-06-15 17:20:33 +00:00
else if ( i = = PSX_EVENT__SYNLAST )
events [ i ] . event_time = 0x7FFFFFFF ;
else
events [ i ] . event_time = PSX_EVENT_MAXTS ;
events [ i ] . prev = ( i > 0 ) ? & events [ i - 1 ] : NULL ;
events [ i ] . next = ( i < ( PSX_EVENT__COUNT - 1 ) ) ? & events [ i + 1 ] : NULL ;
}
}
//static void RemoveEvent(event_list_entry *e)
//{
// e->prev->next = e->next;
// e->next->prev = e->prev;
//}
2015-07-26 13:34:30 +00:00
static void RebaseTS ( const int32_t timestamp )
2014-06-15 17:20:33 +00:00
{
unsigned i ;
for ( i = 0 ; i < PSX_EVENT__COUNT ; i + + )
{
if ( i = = PSX_EVENT__SYNFIRST | | i = = PSX_EVENT__SYNLAST )
continue ;
assert ( events [ i ] . event_time > timestamp ) ;
events [ i ] . event_time - = timestamp ;
}
2019-07-14 20:05:54 +00:00
PSX_CPU - > SetEventNT ( events [ PSX_EVENT__SYNFIRST ] . next - > event_time ) ;
2014-06-15 17:20:33 +00:00
}
2015-07-26 13:34:30 +00:00
void PSX_SetEventNT ( const int type , const int32_t next_timestamp )
2014-06-15 17:20:33 +00:00
{
event_list_entry * e = & events [ type ] ;
if ( next_timestamp < e - > event_time )
{
event_list_entry * fe = e ;
do
{
fe = fe - > prev ;
} while ( next_timestamp < fe - > event_time ) ;
// Remove this event from the list, temporarily of course.
e - > prev - > next = e - > next ;
e - > next - > prev = e - > prev ;
// Insert into the list, just after "fe".
e - > prev = fe ;
e - > next = fe - > next ;
fe - > next - > prev = e ;
fe - > next = e ;
e - > event_time = next_timestamp ;
}
else if ( next_timestamp > e - > event_time )
{
event_list_entry * fe = e ;
do
{
fe = fe - > next ;
} while ( next_timestamp > fe - > event_time ) ;
// Remove this event from the list, temporarily of course
e - > prev - > next = e - > next ;
e - > next - > prev = e - > prev ;
// Insert into the list, just BEFORE "fe".
e - > prev = fe - > prev ;
e - > next = fe ;
fe - > prev - > next = e ;
fe - > prev = e ;
e - > event_time = next_timestamp ;
}
2019-07-14 20:05:54 +00:00
PSX_CPU - > SetEventNT ( events [ PSX_EVENT__SYNFIRST ] . next - > event_time & Running ) ;
2014-06-15 17:20:33 +00:00
}
// Called from debug.cpp too.
2015-07-26 13:34:30 +00:00
void ForceEventUpdates ( const int32_t timestamp )
2014-06-15 17:20:33 +00:00
{
2017-04-22 15:05:39 +00:00
PSX_SetEventNT ( PSX_EVENT_GPU , GPU_Update ( timestamp ) ) ;
2019-07-14 20:05:54 +00:00
PSX_SetEventNT ( PSX_EVENT_CDC , PSX_CDC - > Update ( timestamp ) ) ;
2014-06-15 17:20:33 +00:00
PSX_SetEventNT ( PSX_EVENT_TIMER , TIMER_Update ( timestamp ) ) ;
PSX_SetEventNT ( PSX_EVENT_DMA , DMA_Update ( timestamp ) ) ;
2019-07-14 20:05:54 +00:00
PSX_SetEventNT ( PSX_EVENT_FIO , PSX_FIO - > Update ( timestamp ) ) ;
2014-06-15 17:20:33 +00:00
2019-07-14 20:05:54 +00:00
PSX_CPU - > SetEventNT ( events [ PSX_EVENT__SYNFIRST ] . next - > event_time ) ;
2014-06-15 17:20:33 +00:00
}
2015-07-26 13:34:30 +00:00
bool MDFN_FASTCALL PSX_EventHandler ( const int32_t timestamp )
2014-06-15 17:20:33 +00:00
{
event_list_entry * e = events [ PSX_EVENT__SYNFIRST ] . next ;
2017-07-31 02:42:23 +00:00
while ( timestamp > = e - > event_time ) // If Running = 0, PSX_EventHandler() may be called even if there isn't an event per-se, so while() instead of do { ... } while
2014-06-15 17:20:33 +00:00
{
2015-07-26 13:34:30 +00:00
int32_t nt ;
2014-06-15 17:20:33 +00:00
event_list_entry * prev = e - > prev ;
switch ( e - > which )
{
2014-06-15 17:49:11 +00:00
default :
abort ( ) ;
2014-06-15 17:20:33 +00:00
case PSX_EVENT_GPU :
2017-04-22 15:05:39 +00:00
nt = GPU_Update ( e - > event_time ) ;
2014-06-15 17:49:11 +00:00
break ;
2014-06-15 17:20:33 +00:00
case PSX_EVENT_CDC :
2019-07-14 20:05:54 +00:00
nt = PSX_CDC - > Update ( e - > event_time ) ;
2014-06-15 17:49:11 +00:00
break ;
2014-06-15 17:20:33 +00:00
case PSX_EVENT_TIMER :
2014-06-15 17:49:11 +00:00
nt = TIMER_Update ( e - > event_time ) ;
break ;
2014-06-15 17:20:33 +00:00
case PSX_EVENT_DMA :
2014-06-15 17:49:11 +00:00
nt = DMA_Update ( e - > event_time ) ;
break ;
2014-06-15 17:20:33 +00:00
case PSX_EVENT_FIO :
2019-07-14 20:05:54 +00:00
nt = PSX_FIO - > Update ( e - > event_time ) ;
2014-06-15 17:49:11 +00:00
break ;
2014-06-15 17:20:33 +00:00
}
PSX_SetEventNT ( e - > which , nt ) ;
// Order of events can change due to calling PSX_SetEventNT(), this prev business ensures we don't miss an event due to reordering.
e = prev - > next ;
}
return ( Running ) ;
}
void PSX_RequestMLExit ( void )
{
Running = 0 ;
2019-07-14 20:05:54 +00:00
PSX_CPU - > SetEventNT ( 0 ) ;
2014-06-15 17:20:33 +00:00
}
//
// End event stuff
//
2016-02-02 17:08:43 +00:00
/* Remember to update MemPeek<>() and MemPoke<>() when we change address decoding in MemRW() */
2015-07-26 13:34:30 +00:00
template < typename T , bool IsWrite , bool Access24 > static INLINE void MemRW ( int32_t & timestamp , uint32_t A , uint32_t & V )
2014-06-15 17:20:33 +00:00
{
#if 0
if ( IsWrite )
printf ( " Write%d: %08x(orig=%08x), %08x \n " , ( int ) ( sizeof ( T ) * 8 ) , A & mask [ A > > 29 ] , A , V ) ;
else
printf ( " Read%d: %08x(orig=%08x) \n " , ( int ) ( sizeof ( T ) * 8 ) , A & mask [ A > > 29 ] , A ) ;
# endif
if ( ! IsWrite )
2015-05-06 12:33:31 +00:00
timestamp + = DMACycleSteal ;
2014-06-15 17:20:33 +00:00
//if(A == 0xa0 && IsWrite)
// DBG_Break();
if ( A < 0x00800000 )
{
if ( IsWrite )
{
2017-07-31 02:42:23 +00:00
//timestamp++; // Best-case timing.
2014-06-15 17:20:33 +00:00
}
else
{
2016-01-29 07:05:18 +00:00
// Overclock: get rid of memory access latency
2018-02-08 18:19:43 +00:00
if ( ! psx_gte_overclock )
2016-01-29 07:05:18 +00:00
timestamp + = 3 ;
2014-06-15 17:20:33 +00:00
}
if ( Access24 )
{
if ( IsWrite )
2020-04-06 11:53:56 +00:00
MainRAM - > WriteU24 ( A & 0x1FFFFF , V ) ;
2014-06-15 17:20:33 +00:00
else
2020-04-06 11:53:56 +00:00
V = MainRAM - > ReadU24 ( A & 0x1FFFFF ) ;
2014-06-15 17:20:33 +00:00
}
else
{
if ( IsWrite )
2020-04-06 11:53:56 +00:00
MainRAM - > Write < T > ( A & 0x1FFFFF , V ) ;
2014-06-15 17:20:33 +00:00
else
2020-04-06 11:53:56 +00:00
V = MainRAM - > Read < T > ( A & 0x1FFFFF ) ;
2014-06-15 17:20:33 +00:00
}
return ;
}
if ( A > = 0x1FC00000 & & A < = 0x1FC7FFFF )
{
if ( ! IsWrite )
{
if ( Access24 )
V = BIOSROM - > ReadU24 ( A & 0x7FFFF ) ;
else
V = BIOSROM - > Read < T > ( A & 0x7FFFF ) ;
}
return ;
}
if ( timestamp > = events [ PSX_EVENT__SYNFIRST ] . next - > event_time )
PSX_EventHandler ( timestamp ) ;
if ( A > = 0x1F801000 & & A < = 0x1F802FFF )
{
//if(IsWrite)
// printf("HW Write%d: %08x %08x\n", (unsigned int)(sizeof(T)*8), (unsigned int)A, (unsigned int)V);
//else
// printf("HW Read%d: %08x\n", (unsigned int)(sizeof(T)*8), (unsigned int)A);
if ( A > = 0x1F801C00 & & A < = 0x1F801FFF ) // SPU
{
if ( sizeof ( T ) = = 4 & & ! Access24 )
{
if ( IsWrite )
{
//timestamp += 15;
//if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time)
// PSX_EventHandler(timestamp);
2019-07-14 20:05:54 +00:00
PSX_SPU - > Write ( timestamp , A | 0 , V ) ;
PSX_SPU - > Write ( timestamp , A | 2 , V > > 16 ) ;
2014-06-15 17:20:33 +00:00
}
else
{
timestamp + = 36 ;
if ( timestamp > = events [ PSX_EVENT__SYNFIRST ] . next - > event_time )
PSX_EventHandler ( timestamp ) ;
2019-07-14 20:05:54 +00:00
V = PSX_SPU - > Read ( timestamp , A ) | ( PSX_SPU - > Read ( timestamp , A | 2 ) < < 16 ) ;
2014-06-15 17:20:33 +00:00
}
}
else
{
if ( IsWrite )
{
//timestamp += 8;
//if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time)
// PSX_EventHandler(timestamp);
2019-07-14 20:05:54 +00:00
PSX_SPU - > Write ( timestamp , A & ~ 1 , V ) ;
2014-06-15 17:20:33 +00:00
}
else
{
timestamp + = 16 ; // Just a guess, need to test.
if ( timestamp > = events [ PSX_EVENT__SYNFIRST ] . next - > event_time )
PSX_EventHandler ( timestamp ) ;
2019-07-14 20:05:54 +00:00
V = PSX_SPU - > Read ( timestamp , A & ~ 1 ) ;
2014-06-15 17:20:33 +00:00
}
}
return ;
2017-07-31 02:42:23 +00:00
} // End SPU
2014-06-15 17:20:33 +00:00
// CDC: TODO - 8-bit access.
if ( A > = 0x1f801800 & & A < = 0x1f80180F )
{
2015-10-15 03:12:39 +00:00
if ( ! IsWrite )
2014-06-15 17:20:33 +00:00
{
timestamp + = 6 * sizeof ( T ) ; //24;
}
if ( IsWrite )
2019-07-14 20:05:54 +00:00
PSX_CDC - > Write ( timestamp , A & 0x3 , V ) ;
2014-06-15 17:20:33 +00:00
else
2019-07-14 20:05:54 +00:00
V = PSX_CDC - > Read ( timestamp , A & 0x3 ) ;
2014-06-15 17:20:33 +00:00
return ;
}
if ( A > = 0x1F801810 & & A < = 0x1F801817 )
{
if ( ! IsWrite )
timestamp + + ;
if ( IsWrite )
2017-04-22 15:05:39 +00:00
GPU_Write ( timestamp , A , V ) ;
2014-06-15 17:20:33 +00:00
else
2017-04-22 15:05:39 +00:00
V = GPU_Read ( timestamp , A ) ;
2014-06-15 17:20:33 +00:00
return ;
}
if ( A > = 0x1F801820 & & A < = 0x1F801827 )
{
if ( ! IsWrite )
timestamp + + ;
if ( IsWrite )
MDEC_Write ( timestamp , A , V ) ;
else
V = MDEC_Read ( timestamp , A ) ;
return ;
}
if ( A > = 0x1F801000 & & A < = 0x1F801023 )
{
unsigned index = ( A & 0x1F ) > > 2 ;
if ( ! IsWrite )
timestamp + + ;
//if(A == 0x1F801014 && IsWrite)
// fprintf(stderr, "%08x %08x\n",A,V);
if ( IsWrite )
{
V < < = ( A & 3 ) * 8 ;
SysControl . Regs [ index ] = V & SysControl_Mask [ index ] ;
}
else
{
V = SysControl . Regs [ index ] | SysControl_OR [ index ] ;
V > > = ( A & 3 ) * 8 ;
}
return ;
}
if ( A > = 0x1F801040 & & A < = 0x1F80104F )
{
if ( ! IsWrite )
timestamp + + ;
if ( IsWrite )
2019-07-14 20:05:54 +00:00
PSX_FIO - > Write ( timestamp , A , V ) ;
2014-06-15 17:20:33 +00:00
else
2019-07-14 20:05:54 +00:00
V = PSX_FIO - > Read ( timestamp , A ) ;
2014-06-15 17:20:33 +00:00
return ;
}
if ( A > = 0x1F801050 & & A < = 0x1F80105F )
{
if ( ! IsWrite )
timestamp + + ;
#if 0
if ( IsWrite )
{
PSX_WARNING ( " [SIO] Write: 0x%08x 0x%08x %u " , A , V , ( unsigned ) sizeof ( T ) ) ;
}
else
{
PSX_WARNING ( " [SIO] Read: 0x%08x " , A ) ;
}
# endif
if ( IsWrite )
SIO_Write ( timestamp , A , V ) ;
else
V = SIO_Read ( timestamp , A ) ;
return ;
}
#if 0
if ( A > = 0x1F801060 & & A < = 0x1F801063 )
{
if ( IsWrite )
{
}
else
{
}
return ;
}
# endif
2017-07-31 02:42:23 +00:00
if ( A > = 0x1F801070 & & A < = 0x1F801077 ) // IRQ
2014-06-15 17:20:33 +00:00
{
if ( ! IsWrite )
timestamp + + ;
if ( IsWrite )
2015-07-17 10:51:26 +00:00
: : IRQ_Write ( A , V ) ;
2014-06-15 17:20:33 +00:00
else
2015-07-17 10:51:26 +00:00
V = : : IRQ_Read ( A ) ;
2014-06-15 17:20:33 +00:00
return ;
}
2017-07-31 02:42:23 +00:00
if ( A > = 0x1F801080 & & A < = 0x1F8010FF ) // DMA
2014-06-15 17:20:33 +00:00
{
if ( ! IsWrite )
timestamp + + ;
if ( IsWrite )
DMA_Write ( timestamp , A , V ) ;
else
V = DMA_Read ( timestamp , A ) ;
return ;
}
2017-07-31 02:42:23 +00:00
if ( A > = 0x1F801100 & & A < = 0x1F80113F ) // Root counters
2014-06-15 17:20:33 +00:00
{
if ( ! IsWrite )
timestamp + + ;
if ( IsWrite )
TIMER_Write ( timestamp , A , V ) ;
else
V = TIMER_Read ( timestamp , A ) ;
return ;
}
}
if ( A > = 0x1F000000 & & A < = 0x1F7FFFFF )
{
if ( ! IsWrite )
{
//if((A & 0x7FFFFF) <= 0x84)
//PSX_WARNING("[PIO] Read%d from 0x%08x at time %d", (int)(sizeof(T) * 8), A, timestamp);
2017-07-31 02:42:23 +00:00
V = ~ 0U ; // A game this affects: Tetris with Cardcaptor Sakura
2014-06-15 17:20:33 +00:00
if ( PIOMem )
{
if ( ( A & 0x7FFFFF ) < 65536 )
{
if ( Access24 )
V = PIOMem - > ReadU24 ( A & 0x7FFFFF ) ;
else
V = PIOMem - > Read < T > ( A & 0x7FFFFF ) ;
}
else if ( ( A & 0x7FFFFF ) < ( 65536 + TextMem . size ( ) ) )
{
if ( Access24 )
V = MDFN_de24lsb ( & TextMem [ ( A & 0x7FFFFF ) - 65536 ] ) ;
else switch ( sizeof ( T ) )
{
case 1 : V = TextMem [ ( A & 0x7FFFFF ) - 65536 ] ; break ;
2018-02-21 22:45:09 +00:00
case 2 : V = MDFN_de16lsb < false > ( & TextMem [ ( A & 0x7FFFFF ) - 65536 ] ) ; break ;
case 4 : V = MDFN_de32lsb < false > ( & TextMem [ ( A & 0x7FFFFF ) - 65536 ] ) ; break ;
2014-06-15 17:20:33 +00:00
}
}
}
}
return ;
}
if ( A = = 0xFFFE0130 ) // Per tests on PS1, ignores the access(sort of, on reads the value is forced to 0 if not aligned) if not aligned to 4-bytes.
{
if ( ! IsWrite )
2019-07-14 20:05:54 +00:00
V = PSX_CPU - > GetBIU ( ) ;
2014-06-15 17:20:33 +00:00
else
2019-07-14 20:05:54 +00:00
PSX_CPU - > SetBIU ( V ) ;
2014-06-15 17:20:33 +00:00
return ;
}
if ( IsWrite )
{
PSX_WARNING ( " [MEM] Unknown write%d to %08x at time %d, =%08x(%d) " , ( int ) ( sizeof ( T ) * 8 ) , A , timestamp , V , V ) ;
}
else
{
V = 0 ;
PSX_WARNING ( " [MEM] Unknown read%d from %08x at time %d " , ( int ) ( sizeof ( T ) * 8 ) , A , timestamp ) ;
}
}
2015-07-26 13:34:30 +00:00
void MDFN_FASTCALL PSX_MemWrite8 ( int32_t timestamp , uint32_t A , uint32_t V )
2014-06-15 17:20:33 +00:00
{
MemRW < uint8 , true , false > ( timestamp , A , V ) ;
}
2015-07-26 13:34:30 +00:00
void MDFN_FASTCALL PSX_MemWrite16 ( int32_t timestamp , uint32_t A , uint32_t V )
2014-06-15 17:20:33 +00:00
{
MemRW < uint16 , true , false > ( timestamp , A , V ) ;
}
2015-07-26 13:34:30 +00:00
void MDFN_FASTCALL PSX_MemWrite24 ( int32_t timestamp , uint32_t A , uint32_t V )
2014-06-15 17:20:33 +00:00
{
2017-07-31 02:42:23 +00:00
MemRW < uint32 , true , true > ( timestamp , A , V ) ;
2014-06-15 17:20:33 +00:00
}
2015-07-26 13:34:30 +00:00
void MDFN_FASTCALL PSX_MemWrite32 ( int32_t timestamp , uint32_t A , uint32_t V )
2014-06-15 17:20:33 +00:00
{
2017-07-31 02:42:23 +00:00
MemRW < uint32 , true , false > ( timestamp , A , V ) ;
2014-06-15 17:20:33 +00:00
}
2015-07-26 13:34:30 +00:00
uint8_t MDFN_FASTCALL PSX_MemRead8 ( int32_t & timestamp , uint32_t A )
2014-06-15 17:20:33 +00:00
{
2017-07-31 02:42:23 +00:00
uint32_t V ;
2014-06-15 17:20:33 +00:00
2017-07-31 02:42:23 +00:00
MemRW < uint8 , false , false > ( timestamp , A , V ) ;
2014-06-15 17:20:33 +00:00
2017-07-31 02:42:23 +00:00
return ( V ) ;
2014-06-15 17:20:33 +00:00
}
2015-07-26 13:34:30 +00:00
uint16_t MDFN_FASTCALL PSX_MemRead16 ( int32_t & timestamp , uint32_t A )
2014-06-15 17:20:33 +00:00
{
2017-07-31 02:42:23 +00:00
uint32_t V ;
2014-06-15 17:20:33 +00:00
2017-07-31 02:42:23 +00:00
MemRW < uint16 , false , false > ( timestamp , A , V ) ;
2014-06-15 17:20:33 +00:00
2017-07-31 02:42:23 +00:00
return ( V ) ;
2014-06-15 17:20:33 +00:00
}
2015-07-26 13:34:30 +00:00
uint32_t MDFN_FASTCALL PSX_MemRead24 ( int32_t & timestamp , uint32_t A )
2014-06-15 17:20:33 +00:00
{
2017-07-31 02:42:23 +00:00
uint32_t V ;
2014-06-15 17:20:33 +00:00
2017-07-31 02:42:23 +00:00
MemRW < uint32 , false , true > ( timestamp , A , V ) ;
2014-06-15 17:20:33 +00:00
2017-07-31 02:42:23 +00:00
return ( V ) ;
2014-06-15 17:20:33 +00:00
}
2015-07-26 13:34:30 +00:00
uint32_t MDFN_FASTCALL PSX_MemRead32 ( int32_t & timestamp , uint32_t A )
2014-06-15 17:20:33 +00:00
{
2017-07-31 02:42:23 +00:00
uint32_t V ;
2014-06-15 17:20:33 +00:00
2017-07-31 02:42:23 +00:00
MemRW < uint32 , false , false > ( timestamp , A , V ) ;
2014-06-15 17:20:33 +00:00
2017-07-31 02:42:23 +00:00
return ( V ) ;
2014-06-15 17:20:33 +00:00
}
2015-07-26 13:34:30 +00:00
template < typename T , bool Access24 > static INLINE uint32_t MemPeek ( int32_t timestamp , uint32_t A )
2014-06-15 17:20:33 +00:00
{
if ( A < 0x00800000 )
{
if ( Access24 )
2020-04-06 11:53:56 +00:00
return ( MainRAM - > ReadU24 ( A & 0x1FFFFF ) ) ;
return ( MainRAM - > Read < T > ( A & 0x1FFFFF ) ) ;
2014-06-15 17:20:33 +00:00
}
if ( A > = 0x1FC00000 & & A < = 0x1FC7FFFF )
{
if ( Access24 )
return ( BIOSROM - > ReadU24 ( A & 0x7FFFF ) ) ;
return ( BIOSROM - > Read < T > ( A & 0x7FFFF ) ) ;
}
if ( A > = 0x1F801000 & & A < = 0x1F802FFF )
{
if ( A > = 0x1F801C00 & & A < = 0x1F801FFF ) // SPU
{
// TODO
2017-07-31 02:42:23 +00:00
} // End SPU
2014-06-15 17:20:33 +00:00
// CDC: TODO - 8-bit access.
if ( A > = 0x1f801800 & & A < = 0x1f80180F )
{
// TODO
}
if ( A > = 0x1F801810 & & A < = 0x1F801817 )
{
// TODO
}
if ( A > = 0x1F801820 & & A < = 0x1F801827 )
{
// TODO
}
if ( A > = 0x1F801000 & & A < = 0x1F801023 )
{
unsigned index = ( A & 0x1F ) > > 2 ;
return ( ( SysControl . Regs [ index ] | SysControl_OR [ index ] ) > > ( ( A & 3 ) * 8 ) ) ;
}
if ( A > = 0x1F801040 & & A < = 0x1F80104F )
{
// TODO
}
if ( A > = 0x1F801050 & & A < = 0x1F80105F )
{
// TODO
}
2017-07-31 02:42:23 +00:00
if ( A > = 0x1F801070 & & A < = 0x1F801077 ) // IRQ
2014-06-15 17:20:33 +00:00
{
// TODO
}
2017-07-31 02:42:23 +00:00
if ( A > = 0x1F801080 & & A < = 0x1F8010FF ) // DMA
2014-06-15 17:20:33 +00:00
{
// TODO
}
2017-07-31 02:42:23 +00:00
if ( A > = 0x1F801100 & & A < = 0x1F80113F ) // Root counters
2014-06-15 17:20:33 +00:00
{
// TODO
}
}
if ( A > = 0x1F000000 & & A < = 0x1F7FFFFF )
{
if ( PIOMem )
{
if ( ( A & 0x7FFFFF ) < 65536 )
{
if ( Access24 )
return ( PIOMem - > ReadU24 ( A & 0x7FFFFF ) ) ;
return ( PIOMem - > Read < T > ( A & 0x7FFFFF ) ) ;
}
else if ( ( A & 0x7FFFFF ) < ( 65536 + TextMem . size ( ) ) )
{
if ( Access24 )
return ( MDFN_de24lsb ( & TextMem [ ( A & 0x7FFFFF ) - 65536 ] ) ) ;
else switch ( sizeof ( T ) )
{
case 1 :
return ( TextMem [ ( A & 0x7FFFFF ) - 65536 ] ) ;
case 2 :
2018-02-21 22:45:09 +00:00
return ( MDFN_de16lsb < false > ( & TextMem [ ( A & 0x7FFFFF ) - 65536 ] ) ) ;
2014-06-15 17:20:33 +00:00
case 4 :
2018-02-21 22:45:09 +00:00
return ( MDFN_de32lsb < false > ( & TextMem [ ( A & 0x7FFFFF ) - 65536 ] ) ) ;
2014-06-15 17:20:33 +00:00
}
}
}
return ( ~ 0U ) ;
}
if ( A = = 0xFFFE0130 )
2019-07-14 20:05:54 +00:00
return PSX_CPU - > GetBIU ( ) ;
2014-06-15 17:20:33 +00:00
return ( 0 ) ;
}
uint8_t PSX_MemPeek8 ( uint32_t A )
{
return MemPeek < uint8 , false > ( 0 , A ) ;
}
uint16_t PSX_MemPeek16 ( uint32_t A )
{
return MemPeek < uint16 , false > ( 0 , A ) ;
}
uint32_t PSX_MemPeek32 ( uint32_t A )
{
return MemPeek < uint32 , false > ( 0 , A ) ;
}
// FIXME: Add PSX_Reset() and FrontIO::Reset() so that emulated input devices don't get power-reset on reset-button reset.
static void PSX_Power ( void )
{
unsigned i ;
2015-07-30 05:11:21 +00:00
PSX_PRNG . x = 123456789 ;
PSX_PRNG . y = 987654321 ;
PSX_PRNG . z = 43219876 ;
PSX_PRNG . c = 6543217 ;
PSX_PRNG . lcgo = 0xDEADBEEFCAFEBABEULL ;
2014-06-15 17:20:33 +00:00
2017-10-15 21:39:47 +00:00
cd_warned_slow = false ;
2020-04-06 11:53:56 +00:00
memset ( MainRAM - > data32 , 0 , 2048 * 1024 ) ;
2014-06-15 17:20:33 +00:00
for ( i = 0 ; i < 9 ; i + + )
SysControl . Regs [ i ] = 0 ;
2019-07-14 20:05:54 +00:00
PSX_CPU - > Power ( ) ;
2014-06-15 17:20:33 +00:00
EventReset ( ) ;
TIMER_Power ( ) ;
DMA_Power ( ) ;
2019-07-14 20:05:54 +00:00
PSX_FIO - > Power ( ) ;
2014-06-15 17:20:33 +00:00
SIO_Power ( ) ;
MDEC_Power ( ) ;
2019-07-14 20:05:54 +00:00
PSX_CDC - > Power ( ) ;
2017-04-22 15:05:39 +00:00
GPU_Power ( ) ;
2017-07-31 02:42:23 +00:00
//SPU->Power(); // Called from CDC->Power()
2014-06-15 17:20:33 +00:00
IRQ_Power ( ) ;
ForceEventUpdates ( 0 ) ;
}
2016-02-02 17:08:43 +00:00
template < typename T , bool Access24 > static INLINE void MemPoke ( pscpu_timestamp_t timestamp , uint32 A , T V )
{
if ( A < 0x00800000 )
{
if ( Access24 )
2020-04-06 11:53:56 +00:00
MainRAM - > WriteU24 ( A & 0x1FFFFF , V ) ;
2016-02-02 17:08:43 +00:00
else
2020-04-06 11:53:56 +00:00
MainRAM - > Write < T > ( A & 0x1FFFFF , V ) ;
2016-02-02 17:08:43 +00:00
return ;
}
if ( A > = 0x1FC00000 & & A < = 0x1FC7FFFF )
{
if ( Access24 )
BIOSROM - > WriteU24 ( A & 0x7FFFF , V ) ;
else
BIOSROM - > Write < T > ( A & 0x7FFFF , V ) ;
return ;
}
if ( A > = 0x1F801000 & & A < = 0x1F802FFF )
{
if ( A > = 0x1F801000 & & A < = 0x1F801023 )
{
unsigned index = ( A & 0x1F ) > > 2 ;
SysControl . Regs [ index ] = ( V < < ( ( A & 3 ) * 8 ) ) & SysControl_Mask [ index ] ;
return ;
}
}
if ( A = = 0xFFFE0130 )
{
2019-07-14 20:05:54 +00:00
PSX_CPU - > SetBIU ( V ) ;
2016-02-02 17:08:43 +00:00
return ;
}
}
void PSX_MemPoke8 ( uint32 A , uint8 V )
{
MemPoke < uint8 , false > ( 0 , A , V ) ;
}
void PSX_MemPoke16 ( uint32 A , uint16 V )
{
MemPoke < uint16 , false > ( 0 , A , V ) ;
}
void PSX_MemPoke32 ( uint32 A , uint32 V )
{
MemPoke < uint32 , false > ( 0 , A , V ) ;
}
2014-06-15 17:20:33 +00:00
2019-12-08 21:31:37 +00:00
void PSX_GPULineHook ( const int32_t timestamp , const int32_t line_timestamp , bool vsync , uint32_t * pixels , const MDFN_PixelFormat * const format , const unsigned width , const unsigned pix_clock_offset , const unsigned pix_clock , const unsigned pix_clock_divider , const unsigned surf_pitchinpix , const unsigned upscale_factor )
2014-06-15 17:20:33 +00:00
{
2019-12-08 21:31:37 +00:00
PSX_FIO - > GPULineHook ( timestamp , line_timestamp , vsync , pixels , format , width , pix_clock_offset , pix_clock , pix_clock_divider , surf_pitchinpix , upscale_factor ) ;
2014-06-15 17:20:33 +00:00
}
2017-12-19 02:19:58 +00:00
static bool TestMagic ( const char * name , RFILE * fp , int64_t size )
2014-06-15 17:20:33 +00:00
{
2017-12-19 02:19:58 +00:00
uint8_t header [ 8 ] ;
2014-06-15 17:20:33 +00:00
2017-12-19 02:19:58 +00:00
if ( size < 0x800 )
2014-06-15 17:20:33 +00:00
return ( false ) ;
2017-12-19 02:19:58 +00:00
filestream_read ( fp , header , 8 ) ;
if (
( header [ 0 ] = = ' P ' ) & &
( header [ 1 ] = = ' S ' ) & &
( header [ 2 ] = = ' - ' ) & &
( header [ 3 ] = = ' X ' ) & &
( header [ 4 ] = = ' ' ) & &
( header [ 5 ] = = ' E ' ) & &
( header [ 6 ] = = ' X ' ) & &
( header [ 7 ] = = ' E ' )
)
return ( true ) ;
2014-06-15 17:20:33 +00:00
return ( true ) ;
}
2019-07-14 18:59:05 +00:00
static bool TestMagicCD ( std : : vector < CDIF * > * _CDInterfaces )
2014-06-15 17:20:33 +00:00
{
uint8_t buf [ 2048 ] ;
2015-07-28 20:35:18 +00:00
TOC toc ;
2014-06-15 17:20:33 +00:00
int dt ;
2015-07-28 22:27:57 +00:00
TOC_Clear ( & toc ) ;
2019-07-14 18:59:05 +00:00
( * _CDInterfaces ) [ 0 ] - > ReadTOC ( & toc ) ;
2014-06-15 17:20:33 +00:00
2015-07-28 22:27:57 +00:00
dt = TOC_FindTrackByLBA ( & toc , 4 ) ;
2014-06-15 17:20:33 +00:00
if ( dt > 0 & & ! ( toc . tracks [ dt ] . control & 0x4 ) )
return ( false ) ;
2019-07-14 18:59:05 +00:00
if ( ( * _CDInterfaces ) [ 0 ] - > ReadSector ( buf , 4 , 1 ) ! = 0x2 )
2014-06-15 17:20:33 +00:00
return ( false ) ;
if ( strncmp ( ( char * ) buf + 10 , " Licensed by " , strlen ( " Licensed by " ) ) )
return ( false ) ;
return ( true ) ;
}
2019-07-02 02:18:50 +00:00
static const char * CalcDiscSCEx_BySYSTEMCNF ( CDIF * c , unsigned * rr )
2014-06-15 17:20:33 +00:00
{
2015-07-28 22:27:57 +00:00
uint8_t pvd [ 2048 ] ;
2016-08-14 12:55:16 +00:00
uint32_t rdel , rdel_len ;
const char * ret = NULL ;
Stream * fp = NULL ;
2015-07-28 22:27:57 +00:00
unsigned pvd_search_count = 0 ;
2014-06-15 17:20:33 +00:00
2015-07-28 22:27:57 +00:00
fp = c - > MakeStream ( 0 , ~ 0U ) ;
fp - > seek ( 0x8000 , SEEK_SET ) ;
2014-06-15 17:20:33 +00:00
2019-01-22 01:43:30 +00:00
try // Added this back to fix audio-cd loading issue
{
2015-07-28 22:27:57 +00:00
do
2014-06-15 17:20:33 +00:00
{
2015-07-28 22:27:57 +00:00
if ( ( pvd_search_count + + ) = = 32 )
2016-08-14 12:55:16 +00:00
{
log_cb ( RETRO_LOG_ERROR , " PVD search count limit met. \n " ) ;
ret = NULL ;
goto Breakout ;
}
2014-06-15 17:20:33 +00:00
2015-07-28 22:27:57 +00:00
fp - > read ( pvd , 2048 ) ;
2014-06-15 17:20:33 +00:00
2015-07-28 22:27:57 +00:00
if ( memcmp ( & pvd [ 1 ] , " CD001 " , 5 ) )
2016-08-14 12:55:16 +00:00
{
log_cb ( RETRO_LOG_ERROR , " Not ISO-9660 \n " ) ;
ret = NULL ;
goto Breakout ;
}
2014-06-15 17:20:33 +00:00
2015-07-28 22:27:57 +00:00
if ( pvd [ 0 ] = = 0xFF )
2016-08-14 12:55:16 +00:00
{
log_cb ( RETRO_LOG_ERROR , " Missing Primary Volume Descriptor \n " ) ;
ret = NULL ;
goto Breakout ;
}
2015-07-28 22:27:57 +00:00
} while ( pvd [ 0 ] ! = 0x01 ) ;
2014-06-15 17:20:33 +00:00
2016-08-14 12:55:16 +00:00
/*[156 ... 189], 34 bytes */
2018-02-21 22:45:09 +00:00
rdel = MDFN_de32lsb < false > ( & pvd [ 0x9E ] ) ;
rdel_len = MDFN_de32lsb < false > ( & pvd [ 0xA6 ] ) ;
2016-08-14 12:55:16 +00:00
2017-07-31 02:42:23 +00:00
if ( rdel_len > = ( 1024 * 1024 * 10 ) ) /* Arbitrary sanity check. */
2016-08-14 12:55:16 +00:00
{
log_cb ( RETRO_LOG_ERROR , " Root directory table too large \n " ) ;
ret = NULL ;
goto Breakout ;
}
2014-06-15 17:20:33 +00:00
2015-07-28 22:27:57 +00:00
fp - > seek ( ( int64 ) rdel * 2048 , SEEK_SET ) ;
//printf("%08x, %08x\n", rdel * 2048, rdel_len);
while ( fp - > tell ( ) < ( ( ( int64 ) rdel * 2048 ) + rdel_len ) )
{
uint8_t len_dr = fp - > get_u8 ( ) ;
uint8_t dr [ 256 + 1 ] ;
2014-06-15 17:20:33 +00:00
2015-07-28 22:27:57 +00:00
memset ( dr , 0xFF , sizeof ( dr ) ) ;
2014-06-15 17:20:33 +00:00
2015-07-28 22:27:57 +00:00
if ( ! len_dr )
break ;
2014-06-15 17:20:33 +00:00
2015-07-28 22:27:57 +00:00
memset ( dr , 0 , sizeof ( dr ) ) ;
dr [ 0 ] = len_dr ;
fp - > read ( dr + 1 , len_dr - 1 ) ;
2014-06-15 17:20:33 +00:00
2015-07-28 22:27:57 +00:00
uint8_t len_fi = dr [ 0x20 ] ;
2014-06-15 17:20:33 +00:00
2015-07-28 22:27:57 +00:00
if ( len_fi = = 12 & & ! memcmp ( & dr [ 0x21 ] , " SYSTEM.CNF;1 " , 12 ) )
{
2018-02-21 22:45:09 +00:00
uint32_t file_lba = MDFN_de32lsb < false > ( & dr [ 0x02 ] ) ;
//uint32_t file_len = MDFN_de32lsb<false>(&dr[0x0A]);
2015-07-28 22:27:57 +00:00
uint8_t fb [ 2048 + 1 ] ;
char * bootpos ;
memset ( fb , 0 , sizeof ( fb ) ) ;
fp - > seek ( file_lba * 2048 , SEEK_SET ) ;
fp - > read ( fb , 2048 ) ;
2019-07-02 02:18:50 +00:00
bootpos = strstr ( ( char * ) fb , " BOOT " ) + 4 ;
while ( * bootpos = = ' ' | | * bootpos = = ' \t ' ) bootpos + + ;
if ( * bootpos = = ' = ' )
2014-06-15 17:20:33 +00:00
{
2019-07-02 02:18:50 +00:00
bootpos + + ;
2015-07-28 22:27:57 +00:00
while ( * bootpos = = ' ' | | * bootpos = = ' \t ' ) bootpos + + ;
2019-07-02 02:18:50 +00:00
if ( ! strncasecmp ( bootpos , " cdrom: \\ " , 7 ) )
2015-10-15 03:12:39 +00:00
{
2019-07-02 02:18:50 +00:00
bootpos + = 7 ;
2021-10-10 23:51:03 +00:00
if ( ! strncmp ( bootpos + 7 , " SLUS_007.65 " , 11 ) | | ! strncmp ( bootpos + 7 , " SLES_009.79 " , 11 ) )
{
is_monkey_hero = true ;
log_cb ( RETRO_LOG_INFO , " Monkey Hero FBWrite Tweak Activated \n " ) ;
}
2019-07-02 02:18:50 +00:00
char * tmp ;
2014-06-15 17:20:33 +00:00
2019-07-02 02:18:50 +00:00
if ( ( tmp = strchr ( bootpos , ' _ ' ) ) ) * tmp = 0 ;
if ( ( tmp = strchr ( bootpos , ' . ' ) ) ) * tmp = 0 ;
if ( ( tmp = strchr ( bootpos , ' ; ' ) ) ) * tmp = 0 ;
//puts(bootpos);
2019-05-14 01:37:57 +00:00
2019-07-02 02:18:50 +00:00
if ( strlen ( bootpos ) = = 4 & & bootpos [ 0 ] = = ' S ' & & ( bootpos [ 1 ] = = ' C ' | | bootpos [ 1 ] = = ' L ' | | bootpos [ 1 ] = = ' I ' ) )
{
switch ( bootpos [ 2 ] )
2014-06-15 17:20:33 +00:00
{
2019-07-02 02:18:50 +00:00
case ' E ' : if ( rr )
* rr = REGION_EU ;
ret = " SCEE " ;
goto Breakout ;
case ' U ' : if ( rr )
* rr = REGION_NA ;
ret = " SCEA " ;
goto Breakout ;
case ' K ' : // Korea?
case ' B ' :
case ' P ' : if ( rr )
* rr = REGION_JP ;
ret = " SCEI " ;
goto Breakout ;
2014-06-15 17:20:33 +00:00
}
}
}
}
2019-07-02 02:18:50 +00:00
2015-07-28 22:27:57 +00:00
//puts((char*)fb);
//puts("ASOFKOASDFKO");
}
2014-06-15 17:20:33 +00:00
}
2019-01-22 01:43:30 +00:00
} // try
catch ( std : : exception & e )
{
//
}
catch ( . . . )
{
}
2019-07-02 02:18:50 +00:00
2014-06-15 17:20:33 +00:00
Breakout :
2015-07-28 22:27:57 +00:00
if ( fp )
2014-06-15 17:20:33 +00:00
{
delete fp ;
fp = NULL ;
}
return ( ret ) ;
}
2014-06-16 02:10:39 +00:00
static unsigned CalcDiscSCEx ( void )
2014-06-15 17:20:33 +00:00
{
const char * prev_valid_id = NULL ;
2021-11-18 00:05:31 +00:00
unsigned ret_region = MDFN_GetSettingI ( " psx.region_default " ) ;
2014-06-15 17:20:33 +00:00
cdifs_scex_ids . clear ( ) ;
if ( cdifs )
for ( unsigned i = 0 ; i < cdifs - > size ( ) ; i + + )
{
uint8_t buf [ 2048 ] ;
uint8_t fbuf [ 2048 + 1 ] ;
2015-08-11 20:48:54 +00:00
const char * id = CalcDiscSCEx_BySYSTEMCNF ( ( * cdifs ) [ i ] , ( i = = 0 ) ? & ret_region : NULL ) ;
2014-06-15 17:20:33 +00:00
memset ( fbuf , 0 , sizeof ( fbuf ) ) ;
if ( id = = NULL & & ( * cdifs ) [ i ] - > ReadSector ( buf , 4 , 1 ) = = 0x2 )
{
2015-09-28 22:10:19 +00:00
unsigned ipos , opos ;
2014-06-15 17:20:33 +00:00
for ( ipos = 0 , opos = 0 ; ipos < 0x48 ; ipos + + )
{
if ( buf [ ipos ] > 0x20 & & buf [ ipos ] < 0x80 )
{
fbuf [ opos + + ] = tolower ( buf [ ipos ] ) ;
}
}
fbuf [ opos + + ] = 0 ;
PSX_DBG ( PSX_DBG_SPARSE , " License string: %s " , ( char * ) fbuf ) ;
if ( strstr ( ( char * ) fbuf , " licensedby " ) ! = NULL )
{
if ( strstr ( ( char * ) fbuf , " america " ) ! = NULL )
{
id = " SCEA " ;
if ( ! i )
ret_region = REGION_NA ;
}
else if ( strstr ( ( char * ) fbuf , " europe " ) ! = NULL )
{
id = " SCEE " ;
if ( ! i )
ret_region = REGION_EU ;
}
else if ( strstr ( ( char * ) fbuf , " japan " ) ! = NULL )
{
2017-07-31 02:42:23 +00:00
id = " SCEI " ; // ?
2014-06-15 17:20:33 +00:00
if ( ! i )
ret_region = REGION_JP ;
}
else if ( strstr ( ( char * ) fbuf , " sonycomputerentertainmentinc. " ) ! = NULL )
{
id = " SCEI " ;
if ( ! i )
ret_region = REGION_JP ;
}
2017-07-31 02:42:23 +00:00
else // Failure case
2014-06-15 17:20:33 +00:00
{
if ( prev_valid_id ! = NULL )
id = prev_valid_id ;
else
{
2017-07-31 02:42:23 +00:00
switch ( ret_region ) // Less than correct, but meh, what can we do.
2014-06-15 17:20:33 +00:00
{
case REGION_JP :
id = " SCEI " ;
break ;
case REGION_NA :
id = " SCEA " ;
break ;
case REGION_EU :
id = " SCEE " ;
break ;
}
}
}
}
}
if ( id ! = NULL )
prev_valid_id = id ;
cdifs_scex_ids . push_back ( id ) ;
}
return ret_region ;
}
2018-01-13 10:02:33 +00:00
static void SetDiscWrapper ( const bool CD_TrayOpen ) {
2019-07-02 02:18:50 +00:00
CDIF * cdif = NULL ;
2018-01-13 08:46:38 +00:00
const char * disc_id = NULL ;
if ( CD_SelectedDisc > = 0 & & ! CD_TrayOpen ) {
// only allow one pbp file to be loaded (at index 0)
if ( CD_IsPBP ) {
cdif = ( * cdifs ) [ 0 ] ;
disc_id = cdifs_scex_ids [ 0 ] ;
} else {
cdif = ( * cdifs ) [ CD_SelectedDisc ] ;
disc_id = cdifs_scex_ids [ CD_SelectedDisc ] ;
}
}
2019-07-14 20:05:54 +00:00
PSX_CDC - > SetDisc ( CD_TrayOpen , cdif , disc_id ) ;
2018-01-13 08:46:38 +00:00
}
2020-01-21 23:26:20 +00:00
# ifdef HAVE_LIGHTREC
/* MAP_FIXED_NOREPLACE allows base 0 to work if "sysctl vm.mmap_min_addr = 0"
was used . Base 0 will perform better by directly mapping emulated addresses
to host addresses . If MAP_FIXED_NOREPLACE is not available we should not use
MAP_FIXED , since it can cause strange crashes by unmapping memory mappings . */
# ifndef MAP_FIXED_NOREPLACE
2020-01-22 17:55:48 +00:00
# ifdef USE_FIXED
# define MAP_FIXED_NOREPLACE MAP_FIXED
# else
2020-01-21 23:26:20 +00:00
# define MAP_FIXED_NOREPLACE 0
# endif
2020-01-22 17:55:48 +00:00
# endif
2020-01-21 23:26:20 +00:00
static const uintptr_t supported_io_bases [ ] = {
2020-01-23 17:24:16 +00:00
static_cast < uintptr_t > ( 0x00000000 ) ,
static_cast < uintptr_t > ( 0x10000000 ) ,
static_cast < uintptr_t > ( 0x20000000 ) ,
static_cast < uintptr_t > ( 0x30000000 ) ,
static_cast < uintptr_t > ( 0x40000000 ) ,
static_cast < uintptr_t > ( 0x50000000 ) ,
static_cast < uintptr_t > ( 0x60000000 ) ,
static_cast < uintptr_t > ( 0x70000000 ) ,
static_cast < uintptr_t > ( 0x80000000 ) ,
static_cast < uintptr_t > ( 0x90000000 ) ,
/* Some platforms need higher address base for mmap to work */
# if UINTPTR_MAX == UINT64_MAX
static_cast < uintptr_t > ( 0x100000000 ) ,
static_cast < uintptr_t > ( 0x200000000 ) ,
static_cast < uintptr_t > ( 0x300000000 ) ,
static_cast < uintptr_t > ( 0x400000000 ) ,
static_cast < uintptr_t > ( 0x500000000 ) ,
static_cast < uintptr_t > ( 0x600000000 ) ,
static_cast < uintptr_t > ( 0x700000000 ) ,
static_cast < uintptr_t > ( 0x800000000 ) ,
static_cast < uintptr_t > ( 0x900000000 ) ,
2020-01-23 12:18:49 +00:00
# endif
2020-01-21 23:26:20 +00:00
} ;
2020-05-17 00:16:57 +00:00
# define RAM_SIZE 0x200000
# define BIOS_SIZE 0x80000
# define SCRATCH_SIZE 0x400
2021-05-12 16:18:32 +00:00
# define SHM_SIZE RAM_SIZE+BIOS_SIZE+SCRATCH_SIZE
2020-05-17 00:16:57 +00:00
# ifdef HAVE_WIN_SHM
# define MAP(addr, size, fd, offset) \
MapViewOfFileEx ( fd , FILE_MAP_ALL_ACCESS , 0 , offset , size , addr )
# define UNMAP(addr, size) UnmapViewOfFile(addr)
# define MFAILED NULL
# define NUM_MEM 4
# elif defined(HAVE_SHM) || defined(HAVE_ASHMEM)
# define MAP(addr, size, fd, offset) \
mmap ( addr , size , PROT_READ | PROT_WRITE , \
MAP_SHARED | MAP_FIXED_NOREPLACE , fd , offset )
# define UNMAP(addr, size) munmap(addr, size)
# define MFAILED MAP_FAILED
# define NUM_MEM 4
# else
# define MAP(addr, size, fd, offset) \
mmap ( addr , size , PROT_READ | PROT_WRITE , \
MAP_ANONYMOUS | MAP_PRIVATE , - 1 , 0 )
# define UNMAP(addr, size) munmap(addr, size)
# define MFAILED MAP_FAILED
# define NUM_MEM 1
# endif
2020-01-21 23:26:20 +00:00
int lightrec_init_mmap ( )
{
2020-05-20 21:04:15 +00:00
int r = 0 , i , j ;
2020-01-21 23:26:20 +00:00
uintptr_t base ;
2020-05-17 00:16:57 +00:00
void * bios , * scratch , * map ;
2020-01-21 23:26:20 +00:00
2020-05-17 00:16:57 +00:00
/* open memfd and set size */
2020-01-21 23:26:20 +00:00
# ifdef HAVE_ASHMEM
memfd = open ( " /dev/ashmem " , O_RDWR ) ;
if ( memfd < 0 ) {
2021-05-12 16:18:32 +00:00
/* Android 10+ / API 29+ gives EACCES (permission denied) opening /dev/ashmem
* fallback to ASharedMemory_create available since Android 8 / API 26 */
if ( errno = = EACCES ) {
void * lib ;
int ( * create ) ( const char * , size_t ) ;
int ( * setProt ) ( int , int ) ;
char * error1 , * error2 ;
dlerror ( ) ; /* Clear any existing error */
lib = dlopen ( " libandroid.so " , RTLD_NOW ) ;
if ( lib = = NULL ) {
log_cb ( RETRO_LOG_ERROR , " Failed to dlopen: %s \n " , dlerror ( ) ) ;
return 0 ;
}
* ( void * * ) ( & create ) = dlsym ( lib , " ASharedMemory_create " ) ;
error1 = dlerror ( ) ;
* ( void * * ) ( & setProt ) = dlsym ( lib , " ASharedMemory_setProt " ) ;
error2 = dlerror ( ) ;
if ( error1 = = NULL )
memfd = ( * create ) ( " lightrec_memfd " , SHM_SIZE ) ;
2020-05-17 00:16:57 +00:00
2021-05-12 16:18:32 +00:00
if ( memfd < 0 ) {
log_cb ( RETRO_LOG_ERROR , " Failed to ASharedMemory_create: %s \n " ,
( error1 ! = NULL ) ? error1 : strerror ( errno ) ) ;
dlclose ( lib ) ;
return 0 ;
}
if ( error2 ! = NULL | | ( ( ( * setProt ) ( memfd , PROT_READ | PROT_WRITE ) ) < 0 ) )
log_cb ( RETRO_LOG_ERROR , " Failed to ASharedMemory_setProt: %s \n " ,
( error2 ! = NULL ) ? error2 : strerror ( errno ) ) ;
dlclose ( lib ) ;
} else {
log_cb ( RETRO_LOG_ERROR , " Failed to create ASHMEM: %s \n " , strerror ( errno ) ) ;
return 0 ;
}
} else {
ioctl ( memfd , ASHMEM_SET_NAME , " lightrec_memfd " ) ;
ioctl ( memfd , ASHMEM_SET_SIZE , SHM_SIZE ) ;
}
2020-05-17 00:16:57 +00:00
# endif
# ifdef HAVE_SHM
int memfd ;
2021-08-21 01:29:11 +00:00
const char * shm_name = " /lightrec_memfd_beetle " ;
2020-05-17 00:16:57 +00:00
2021-08-21 01:29:11 +00:00
memfd = shm_open ( shm_name , O_RDWR | O_CREAT | O_EXCL , S_IRUSR | S_IWUSR ) ;
if ( memfd < 0 & & errno = = EEXIST ) {
shm_unlink ( shm_name ) ;
memfd = shm_open ( shm_name , O_RDWR | O_CREAT | O_EXCL , S_IRUSR | S_IWUSR ) ;
}
2020-05-17 00:16:57 +00:00
2020-01-21 23:26:20 +00:00
if ( memfd < 0 ) {
2020-05-20 21:04:15 +00:00
log_cb ( RETRO_LOG_ERROR , " Failed to create SHM: %s \n " , strerror ( errno ) ) ;
2020-05-17 00:16:57 +00:00
return 0 ;
2020-01-21 23:26:20 +00:00
}
2020-05-20 21:04:15 +00:00
/* unlink ASAP to prevent leaving a file in shared memory if we crash */
shm_unlink ( shm_name ) ;
2020-05-17 00:16:57 +00:00
2021-05-12 16:18:32 +00:00
if ( ftruncate ( memfd , SHM_SIZE ) < 0 ) {
2020-05-20 21:04:15 +00:00
log_cb ( RETRO_LOG_ERROR , " Could not truncate SHM size: %s \n " , strerror ( errno ) ) ;
goto close_return ;
2020-05-17 00:16:57 +00:00
}
# endif
# ifdef HAVE_WIN_SHM
HANDLE memfd ;
2021-05-12 16:18:32 +00:00
memfd = CreateFileMapping ( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE , 0 , SHM_SIZE , NULL ) ;
2020-05-17 00:16:57 +00:00
if ( memfd = = NULL ) {
2020-05-20 21:04:15 +00:00
log_cb ( RETRO_LOG_ERROR , " Failed to create WIN_SHM: %s (%d) \n " , strerror ( errno ) , GetLastError ( ) ) ;
2020-05-17 00:16:57 +00:00
return 0 ;
2020-01-21 23:26:20 +00:00
}
# endif
2020-05-17 00:16:57 +00:00
/* Try to map at various base addresses*/
2020-01-21 23:26:20 +00:00
for ( i = 0 ; i < ARRAY_SIZE ( supported_io_bases ) ; i + + ) {
base = supported_io_bases [ i ] ;
bios = ( void * ) ( base + 0x1fc00000 ) ;
scratch = ( void * ) ( base + 0x1f800000 ) ;
2020-05-17 00:16:57 +00:00
for ( j = 0 ; j < NUM_MEM ; j + + ) {
map = MAP ( ( void * ) ( base + j * RAM_SIZE ) , RAM_SIZE , memfd , 0 ) ;
if ( map = = MFAILED )
2020-01-21 23:26:20 +00:00
break ;
2020-05-17 00:16:57 +00:00
else if ( map ! = ( void * ) ( base + j * RAM_SIZE ) )
2020-01-21 23:26:20 +00:00
{
//not at expected address, reject it
2020-05-17 00:16:57 +00:00
UNMAP ( map , RAM_SIZE ) ;
2020-01-21 23:26:20 +00:00
break ;
}
}
/* Impossible to map using this base */
if ( j = = 0 )
continue ;
/* All mirrors mapped - we got a match! */
2020-05-17 00:16:57 +00:00
if ( j = = NUM_MEM )
2020-01-21 23:26:20 +00:00
{
psx_mem = ( uint8 * ) base ;
2020-05-17 00:16:57 +00:00
map = MAP ( bios , BIOS_SIZE , memfd , RAM_SIZE ) ;
if ( map = = MFAILED )
2020-01-21 23:26:20 +00:00
goto err_unmap ;
psx_bios = ( uint8 * ) map ;
if ( map ! = bios )
goto err_unmap_bios ;
2020-05-17 00:16:57 +00:00
map = MAP ( scratch , SCRATCH_SIZE , memfd , RAM_SIZE + BIOS_SIZE ) ;
if ( map = = MFAILED )
2020-01-21 23:26:20 +00:00
goto err_unmap_bios ;
psx_scratch = ( uint8 * ) map ;
if ( map ! = scratch )
goto err_unmap_scratch ;
2020-05-17 00:16:57 +00:00
r = NUM_MEM ;
2020-05-20 21:04:15 +00:00
goto close_return ;
2020-01-21 23:26:20 +00:00
}
err_unmap_scratch :
2020-05-17 00:16:57 +00:00
if ( psx_scratch ) {
UNMAP ( psx_scratch , SCRATCH_SIZE ) ;
psx_scratch = NULL ;
}
2020-01-21 23:26:20 +00:00
err_unmap_bios :
2020-05-17 00:16:57 +00:00
if ( psx_bios ) {
UNMAP ( psx_bios , BIOS_SIZE ) ;
psx_bios = NULL ;
}
2020-01-21 23:26:20 +00:00
err_unmap :
/* Clean up any mapped ram or mirrors and try again */
for ( ; j > 0 ; j - - )
2020-05-17 00:16:57 +00:00
UNMAP ( ( void * ) ( base + ( j - 1 ) * RAM_SIZE ) , RAM_SIZE ) ;
psx_mem = NULL ;
2020-01-21 23:26:20 +00:00
}
if ( i = = ARRAY_SIZE ( supported_io_bases ) ) {
2020-04-29 22:05:48 +00:00
log_cb ( RETRO_LOG_WARN , " Unable to mmap on any base address, dynarec will be slower \n " ) ;
2020-01-21 23:26:20 +00:00
}
2020-05-20 21:04:15 +00:00
close_return :
2020-05-17 00:16:57 +00:00
# ifdef HAVE_SHM
close ( memfd ) ;
2020-01-21 23:26:20 +00:00
# endif
2020-05-17 00:16:57 +00:00
# ifdef HAVE_WIN_SHM
2020-01-21 23:26:20 +00:00
CloseHandle ( memfd ) ;
# endif
2020-05-17 00:16:57 +00:00
return r ;
2020-01-21 23:26:20 +00:00
}
void lightrec_free_mmap ( )
{
2020-05-17 00:16:57 +00:00
for ( int i = 0 ; i < NUM_MEM ; i + + )
UNMAP ( ( void * ) ( ( uintptr_t ) psx_mem + i * RAM_SIZE ) , RAM_SIZE ) ;
2020-01-21 23:26:20 +00:00
2020-05-17 00:16:57 +00:00
UNMAP ( psx_bios , BIOS_SIZE ) ;
UNMAP ( psx_scratch , SCRATCH_SIZE ) ;
2020-01-21 23:26:20 +00:00
2020-05-17 00:16:57 +00:00
# ifdef HAVE_ASHMEM
2021-05-12 16:18:32 +00:00
/* android shared memory is not pinned by mmap, it dies on close */
2020-01-21 23:26:20 +00:00
close ( memfd ) ;
# endif
}
2020-05-17 00:16:57 +00:00
# endif /* HAVE_LIGHTREC */
2020-01-21 23:26:20 +00:00
2022-04-16 14:21:51 +00:00
/* LED interface */
static retro_set_led_state_t led_state_cb = NULL ;
static unsigned int retro_led_state [ 2 ] = { 0 } ;
static void retro_led_interface ( void )
{
/* 0: Power
* 1 : CD */
unsigned int led_state [ 2 ] = { 0 } ;
unsigned int l = 0 ;
led_state [ 0 ] = ( ! Running ) ? 1 : 0 ;
led_state [ 1 ] = ( PSX_CDC - > DriveStatus > 0 ) ? 1 : 0 ;
for ( l = 0 ; l < sizeof ( led_state ) / sizeof ( led_state [ 0 ] ) ; l + + )
{
if ( retro_led_state [ l ] ! = led_state [ l ] )
{
retro_led_state [ l ] = led_state [ l ] ;
led_state_cb ( l , led_state [ l ] ) ;
}
}
}
2020-02-03 17:17:44 +00:00
/* Forward declarations, required for disk control
* ' set initial disk ' functionality */
static unsigned disk_get_num_images ( void ) ;
static void CDInsertEject ( void ) ;
static void CDEject ( void ) ;
2019-07-14 18:59:05 +00:00
static void InitCommon ( std : : vector < CDIF * > * _CDInterfaces , const bool EmulateMemcards = true , const bool WantPIOMem = false )
2014-06-15 17:20:33 +00:00
{
unsigned region , i ;
bool emulate_memcard [ 8 ] ;
bool emulate_multitap [ 2 ] ;
int sls , sle ;
# if PSX_DBGPRINT_ENABLE
psx_dbg_level = MDFN_GetSettingUI ( " psx.dbg_level " ) ;
# endif
for ( i = 0 ; i < 8 ; i + + )
{
char buf [ 64 ] ;
2014-06-19 17:42:42 +00:00
snprintf ( buf , sizeof ( buf ) , " psx.input.port%u.memcard " , i + 1 ) ;
2014-06-15 17:20:33 +00:00
emulate_memcard [ i ] = EmulateMemcards & & MDFN_GetSettingB ( buf ) ;
}
2016-06-09 23:42:57 +00:00
if ( ! enable_memcard1 ) {
emulate_memcard [ 1 ] = false ;
}
2017-03-26 21:44:25 +00:00
emulate_multitap [ 0 ] = setting_psx_multitap_port_1 ;
emulate_multitap [ 1 ] = setting_psx_multitap_port_2 ;
2014-06-15 17:20:33 +00:00
2019-07-14 18:59:05 +00:00
cdifs = _CDInterfaces ;
2014-06-15 17:20:33 +00:00
region = CalcDiscSCEx ( ) ;
if ( ! MDFN_GetSettingB ( " psx.region_autodetect " ) )
region = MDFN_GetSettingI ( " psx.region_default " ) ;
sls = MDFN_GetSettingI ( ( region = = REGION_EU ) ? " psx.slstartp " : " psx.slstart " ) ;
sle = MDFN_GetSettingI ( ( region = = REGION_EU ) ? " psx.slendp " : " psx.slend " ) ;
if ( sls > sle )
{
int tmp = sls ;
sls = sle ;
sle = tmp ;
}
2019-07-14 20:05:54 +00:00
PSX_CPU = new PS_CPU ( ) ;
PSX_SPU = new PS_SPU ( ) ;
2017-04-22 15:05:39 +00:00
GPU_Init ( region = = REGION_EU , sls , sle , psx_gpu_upscale_shift ) ;
2019-07-14 20:05:54 +00:00
PSX_CDC = new PS_CDC ( ) ;
PSX_FIO = new FrontIO ( emulate_memcard , emulate_multitap ) ;
PSX_FIO - > SetAMCT ( MDFN_GetSettingB ( " psx.input.analog_mode_ct " ) ) ;
2021-11-14 12:10:36 +00:00
for ( unsigned i = 0 ; i < 2 ; i + + )
2014-06-15 17:20:33 +00:00
{
char buf [ 64 ] ;
2014-06-19 17:42:42 +00:00
snprintf ( buf , sizeof ( buf ) , " psx.input.port%u.gun_chairs " , i + 1 ) ;
2019-07-14 20:05:54 +00:00
PSX_FIO - > SetCrosshairsColor ( i , MDFN_GetSettingUI ( buf ) ) ;
2014-06-15 17:20:33 +00:00
}
2019-07-14 20:05:54 +00:00
input_set_fio ( PSX_FIO ) ;
2017-11-19 10:45:16 +00:00
2014-06-15 17:20:33 +00:00
DMA_Init ( ) ;
2017-04-22 15:05:39 +00:00
GPU_FillVideoParams ( & EmulatedPSX ) ;
2014-06-15 17:20:33 +00:00
2017-04-22 15:05:39 +00:00
switch ( psx_gpu_dither_mode )
{
case DITHER_NATIVE :
2019-11-24 10:23:52 +00:00
GPU_set_dither_upscale_shift ( psx_gpu_upscale_shift ) ;
2017-04-22 15:05:39 +00:00
break ;
case DITHER_UPSCALED :
2019-10-08 20:52:56 +00:00
GPU_set_dither_upscale_shift ( 0 ) ;
2017-04-22 15:05:39 +00:00
break ;
case DITHER_OFF :
break ;
2016-02-08 14:15:26 +00:00
}
2020-09-27 10:45:58 +00:00
PGXP_SetModes ( psx_pgxp_mode | psx_pgxp_vertex_caching | psx_pgxp_texture_correction | psx_pgxp_nclip ) ;
2016-09-25 10:52:57 +00:00
2015-07-30 05:52:54 +00:00
CD_TrayOpen = true ;
CD_SelectedDisc = - 1 ;
2014-06-15 17:20:33 +00:00
if ( cdifs )
{
2015-07-30 05:52:54 +00:00
CD_TrayOpen = false ;
2014-06-15 17:20:33 +00:00
CD_SelectedDisc = 0 ;
2020-02-03 17:17:44 +00:00
/* Attempt to set initial disk index */
if ( ( disk_control_ext_info . initial_index > 0 ) & &
( disk_control_ext_info . initial_index < disk_get_num_images ( ) ) )
if ( disk_control_ext_info . initial_index <
disk_control_ext_info . image_paths . size ( ) )
if ( string_is_equal (
disk_control_ext_info . image_paths [ disk_control_ext_info . initial_index ] . c_str ( ) ,
disk_control_ext_info . initial_path . c_str ( ) ) )
CD_SelectedDisc = ( int ) disk_control_ext_info . initial_index ;
2014-06-15 17:20:33 +00:00
}
2019-07-14 20:05:54 +00:00
PSX_CDC - > SetDisc ( true , NULL , NULL ) ;
2020-02-03 17:17:44 +00:00
/* Multi-disk PBP files cause additional complication
* here , since the first disk is always loaded by default */
if ( CD_IsPBP & & ( CD_SelectedDisc > 0 ) )
{
CDEject ( ) ;
CDInsertEject ( ) ;
}
else
SetDiscWrapper ( CD_TrayOpen ) ;
2018-11-03 01:11:37 +00:00
2020-01-21 23:26:20 +00:00
# ifdef HAVE_LIGHTREC
2020-05-17 00:16:57 +00:00
psx_mmap = lightrec_init_mmap ( ) ;
2020-04-29 22:05:48 +00:00
2020-05-17 00:16:57 +00:00
if ( psx_mmap > 0 )
2020-01-21 23:26:20 +00:00
{
2020-05-17 00:16:57 +00:00
MainRAM = new ( psx_mem ) MultiAccessSizeMem < RAM_SIZE , uint32 , false > ( ) ;
ScratchRAM = new ( psx_scratch ) MultiAccessSizeMem < SCRATCH_SIZE , uint32 , false > ( ) ;
BIOSROM = new ( psx_bios ) MultiAccessSizeMem < BIOS_SIZE , uint32 , false > ( ) ;
2020-01-21 23:26:20 +00:00
}
else
# endif
{
2020-04-06 11:53:56 +00:00
MainRAM = new MultiAccessSizeMem < 2048 * 1024 , uint32 , false > ( ) ;
2020-01-21 23:26:20 +00:00
ScratchRAM = new MultiAccessSizeMem < 1024 , uint32 , false > ( ) ;
BIOSROM = new MultiAccessSizeMem < 512 * 1024 , uint32 , false > ( ) ;
}
2014-06-15 17:20:33 +00:00
2015-07-30 05:52:54 +00:00
PIOMem = NULL ;
2014-06-15 17:20:33 +00:00
if ( WantPIOMem )
PIOMem = new MultiAccessSizeMem < 65536 , uint32 , false > ( ) ;
2020-04-06 11:53:56 +00:00
for ( uint32_t ma = 0x00000000 ; ma < 0x00800000 ; ma + = 2048 * 1024 )
2014-06-15 17:20:33 +00:00
{
2020-04-06 11:53:56 +00:00
PSX_CPU - > SetFastMap ( MainRAM - > data32 , 0x00000000 + ma , 2048 * 1024 ) ;
PSX_CPU - > SetFastMap ( MainRAM - > data32 , 0x80000000 + ma , 2048 * 1024 ) ;
PSX_CPU - > SetFastMap ( MainRAM - > data32 , 0xA0000000 + ma , 2048 * 1024 ) ;
2014-06-15 17:20:33 +00:00
}
2019-07-14 20:05:54 +00:00
PSX_CPU - > SetFastMap ( BIOSROM - > data32 , 0x1FC00000 , 512 * 1024 ) ;
PSX_CPU - > SetFastMap ( BIOSROM - > data32 , 0x9FC00000 , 512 * 1024 ) ;
PSX_CPU - > SetFastMap ( BIOSROM - > data32 , 0xBFC00000 , 512 * 1024 ) ;
2014-06-15 17:20:33 +00:00
if ( PIOMem )
{
2019-07-14 20:05:54 +00:00
PSX_CPU - > SetFastMap ( PIOMem - > data32 , 0x1F000000 , 65536 ) ;
PSX_CPU - > SetFastMap ( PIOMem - > data32 , 0x9F000000 , 65536 ) ;
PSX_CPU - > SetFastMap ( PIOMem - > data32 , 0xBF000000 , 65536 ) ;
2014-06-15 17:20:33 +00:00
}
MDFNMP_Init ( 1024 , ( ( uint64 ) 1 < < 29 ) / 1024 ) ;
2020-04-06 11:53:56 +00:00
MDFNMP_AddRAM ( 2048 * 1024 , 0x00000000 , MainRAM - > data8 ) ;
2015-07-30 05:52:54 +00:00
#if 0
MDFNMP_AddRAM ( 1024 , 0x1F800000 , ScratchRAM . data8 ) ;
# endif
2014-06-15 17:20:33 +00:00
2020-05-24 23:08:26 +00:00
RFILE * BIOSFile ;
2014-06-15 17:20:33 +00:00
2020-05-24 23:08:26 +00:00
if ( firmware_is_present ( region ) )
{
BIOSFile = filestream_open ( bios_path ,
RETRO_VFS_FILE_ACCESS_READ ,
RETRO_VFS_FILE_ACCESS_HINT_NONE ) ;
}
2014-06-15 17:20:33 +00:00
else
{
2020-05-24 23:08:26 +00:00
const char * biospath_sname ;
if ( region = = REGION_JP )
biospath_sname = " psx.bios_jp " ;
else if ( region = = REGION_EU )
biospath_sname = " psx.bios_eu " ;
else if ( region = = REGION_NA )
biospath_sname = " psx.bios_na " ;
else
abort ( ) ;
2018-11-03 01:11:37 +00:00
const char * biospath = MDFN_MakeFName ( MDFNMKF_FIRMWARE ,
2020-09-14 04:52:05 +00:00
0 , MDFN_GetSettingS ( biospath_sname ) ) ;
2020-05-24 23:08:26 +00:00
BIOSFile = filestream_open ( biospath ,
2017-12-19 00:42:59 +00:00
RETRO_VFS_FILE_ACCESS_READ ,
RETRO_VFS_FILE_ACCESS_HINT_NONE ) ;
2020-05-24 23:08:26 +00:00
}
2017-11-19 10:45:16 +00:00
2017-12-19 00:42:59 +00:00
if ( BIOSFile )
{
filestream_read ( BIOSFile , BIOSROM - > data8 , 512 * 1024 ) ;
filestream_close ( BIOSFile ) ;
}
2014-06-15 17:20:33 +00:00
2014-07-27 19:03:37 +00:00
i = 0 ;
2014-06-16 16:43:58 +00:00
2014-07-27 19:03:37 +00:00
if ( ! use_mednafen_memcard0_method )
{
2019-07-14 20:05:54 +00:00
PSX_FIO - > LoadMemcard ( 0 ) ;
2014-07-27 19:03:37 +00:00
i = 1 ;
}
for ( ; i < 8 ; i + + )
2014-06-15 17:20:33 +00:00
{
char ext [ 64 ] ;
2015-09-30 01:56:50 +00:00
const char * memcard = NULL ;
2020-05-26 03:02:51 +00:00
if ( i = = 0 )
snprintf ( ext , sizeof ( ext ) , " %d.mcr " , memcard_left_index ) ;
else if ( i = = 1 )
snprintf ( ext , sizeof ( ext ) , " %d.mcr " , memcard_right_index ) ;
else
snprintf ( ext , sizeof ( ext ) , " %d.mcr " , i ) ;
2015-09-30 01:56:50 +00:00
memcard = MDFN_MakeFName ( MDFNMKF_SAV , 0 , ext ) ;
2019-07-14 20:05:54 +00:00
PSX_FIO - > LoadMemcard ( i , memcard ) ;
2014-06-15 17:20:33 +00:00
}
for ( i = 0 ; i < 8 ; i + + )
{
2019-07-14 20:05:54 +00:00
Memcard_PrevDC [ i ] = PSX_FIO - > GetMemcardDirtyCount ( i ) ;
2014-06-15 17:20:33 +00:00
Memcard_SaveDelay [ i ] = - 1 ;
}
2017-11-19 10:45:16 +00:00
input_init_calibration ( ) ;
2016-10-07 13:10:07 +00:00
2014-06-15 17:20:33 +00:00
# ifdef WANT_DEBUGGER
DBG_Init ( ) ;
# endif
PSX_Power ( ) ;
}
2016-07-20 07:22:38 +00:00
static bool LoadEXE ( const uint8_t * data , const uint32_t size , bool ignore_pcsp = false )
2014-06-15 17:20:33 +00:00
{
2018-02-21 22:45:09 +00:00
uint32 PC = MDFN_de32lsb < false > ( & data [ 0x10 ] ) ;
uint32 SP = MDFN_de32lsb < false > ( & data [ 0x30 ] ) ;
uint32 TextStart = MDFN_de32lsb < false > ( & data [ 0x18 ] ) ;
uint32 TextSize = MDFN_de32lsb < false > ( & data [ 0x1C ] ) ;
2014-06-15 17:20:33 +00:00
if ( ignore_pcsp )
2020-06-17 09:05:20 +00:00
log_cb ( RETRO_LOG_DEBUG , " TextStart=0x%08x \n TextSize=0x%08x \n " , TextStart , TextSize ) ;
2014-06-15 17:20:33 +00:00
else
2020-06-17 09:05:20 +00:00
log_cb ( RETRO_LOG_DEBUG , " PC=0x%08x \n SP=0x%08x \n TextStart=0x%08x \n TextSize=0x%08x \n " , PC , SP , TextStart , TextSize ) ;
2014-06-15 17:20:33 +00:00
TextStart & = 0x1FFFFF ;
if ( TextSize > 2048 * 1024 )
2016-07-20 07:22:38 +00:00
{
MDFN_Error ( 0 , " Text section too large " ) ;
return false ;
}
2014-06-15 17:20:33 +00:00
if ( TextSize > ( size - 0x800 ) )
2016-07-20 07:22:38 +00:00
{
MDFN_Error ( 0 , " Text section recorded size is larger than data available in file. Header=0x%08x, Available=0x%08x " , TextSize , size - 0x800 ) ;
return false ;
}
2014-06-15 17:20:33 +00:00
if ( TextSize < ( size - 0x800 ) )
2016-07-20 07:22:38 +00:00
{
MDFN_Error ( 0 , " Text section recorded size is smaller than data available in file. Header=0x%08x, Available=0x%08x " , TextSize , size - 0x800 ) ;
return false ;
}
2014-06-15 17:20:33 +00:00
if ( ! TextMem . size ( ) )
{
TextMem_Start = TextStart ;
TextMem . resize ( TextSize ) ;
}
if ( TextStart < TextMem_Start )
{
2014-06-22 15:59:07 +00:00
uint32 old_size = TextMem . size ( ) ;
2014-06-15 17:20:33 +00:00
//printf("RESIZE: 0x%08x\n", TextMem_Start - TextStart);
TextMem . resize ( old_size + TextMem_Start - TextStart ) ;
memmove ( & TextMem [ TextMem_Start - TextStart ] , & TextMem [ 0 ] , old_size ) ;
TextMem_Start = TextStart ;
}
if ( TextMem . size ( ) < ( TextStart - TextMem_Start + TextSize ) )
TextMem . resize ( TextStart - TextMem_Start + TextSize ) ;
memcpy ( & TextMem [ TextStart - TextMem_Start ] , data + 0x800 , TextSize ) ;
// BIOS patch
BIOSROM - > WriteU32 ( 0x6990 , ( 3 < < 26 ) | ( ( 0xBF001000 > > 2 ) & ( ( 1 < < 26 ) - 1 ) ) ) ;
2015-07-30 05:52:54 +00:00
#if 0
BIOSROM - > WriteU32 ( 0x691C , ( 3 < < 26 ) | ( ( 0xBF001000 > > 2 ) & ( ( 1 < < 26 ) - 1 ) ) ) ;
# endif
2014-06-15 17:20:33 +00:00
2014-06-22 15:59:07 +00:00
uint8 * po ;
2014-06-15 17:20:33 +00:00
po = & PIOMem - > data8 [ 0x0800 ] ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0x0 < < 26 ) | ( 31 < < 21 ) | ( 0x8 < < 0 ) ) ; // JR
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , 0 ) ; // NOP(kinda)
2014-06-15 17:20:33 +00:00
po + = 4 ;
po = & PIOMem - > data8 [ 0x1000 ] ;
// Load cacheable-region target PC into r2
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0xF < < 26 ) | ( 0 < < 21 ) | ( 1 < < 16 ) | ( 0x9F001010 > > 16 ) ) ; // LUI
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0xD < < 26 ) | ( 1 < < 21 ) | ( 2 < < 16 ) | ( 0x9F001010 & 0xFFFF ) ) ; // ORI
2014-06-15 17:20:33 +00:00
po + = 4 ;
// Jump to r2
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0x0 < < 26 ) | ( 2 < < 21 ) | ( 0x8 < < 0 ) ) ; // JR
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , 0 ) ; // NOP(kinda)
2014-06-15 17:20:33 +00:00
po + = 4 ;
//
// 0x9F001010:
//
// Load source address into r8
2014-06-22 15:59:07 +00:00
uint32 sa = 0x9F000000 + 65536 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0xF < < 26 ) | ( 0 < < 21 ) | ( 1 < < 16 ) | ( sa > > 16 ) ) ; // LUI
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0xD < < 26 ) | ( 1 < < 21 ) | ( 8 < < 16 ) | ( sa & 0xFFFF ) ) ; // ORI
2014-06-15 17:20:33 +00:00
po + = 4 ;
// Load dest address into r9
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0xF < < 26 ) | ( 0 < < 21 ) | ( 1 < < 16 ) | ( TextMem_Start > > 16 ) ) ; // LUI
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0xD < < 26 ) | ( 1 < < 21 ) | ( 9 < < 16 ) | ( TextMem_Start & 0xFFFF ) ) ; // ORI
2014-06-15 17:20:33 +00:00
po + = 4 ;
// Load size into r10
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0xF < < 26 ) | ( 0 < < 21 ) | ( 1 < < 16 ) | ( TextMem . size ( ) > > 16 ) ) ; // LUI
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0xD < < 26 ) | ( 1 < < 21 ) | ( 10 < < 16 ) | ( TextMem . size ( ) & 0xFFFF ) ) ; // ORI
2014-06-15 17:20:33 +00:00
po + = 4 ;
//
// Loop begin
//
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0x24 < < 26 ) | ( 8 < < 21 ) | ( 1 < < 16 ) ) ; // LBU to r1
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0x08 < < 26 ) | ( 10 < < 21 ) | ( 10 < < 16 ) | 0xFFFF ) ; // Decrement size
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0x28 < < 26 ) | ( 9 < < 21 ) | ( 1 < < 16 ) ) ; // SB from r1
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0x08 < < 26 ) | ( 8 < < 21 ) | ( 8 < < 16 ) | 0x0001 ) ; // Increment source addr
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0x05 < < 26 ) | ( 0 < < 21 ) | ( 10 < < 16 ) | ( - 5 & 0xFFFF ) ) ;
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0x08 < < 26 ) | ( 9 < < 21 ) | ( 9 < < 16 ) | 0x0001 ) ; // Increment dest addr
2014-06-15 17:20:33 +00:00
po + = 4 ;
//
// Loop end
//
// Load SP into r29
if ( ignore_pcsp )
{
po + = 16 ;
}
else
{
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0xF < < 26 ) | ( 0 < < 21 ) | ( 1 < < 16 ) | ( SP > > 16 ) ) ; // LUI
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0xD < < 26 ) | ( 1 < < 21 ) | ( 29 < < 16 ) | ( SP & 0xFFFF ) ) ; // ORI
2014-06-15 17:20:33 +00:00
po + = 4 ;
// Load PC into r2
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0xF < < 26 ) | ( 0 < < 21 ) | ( 1 < < 16 ) | ( ( PC > > 16 ) | 0x8000 ) ) ; // LUI
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0xD < < 26 ) | ( 1 < < 21 ) | ( 2 < < 16 ) | ( PC & 0xFFFF ) ) ; // ORI
2014-06-15 17:20:33 +00:00
po + = 4 ;
}
// Half-assed instruction cache flush. ;)
2014-06-22 15:59:07 +00:00
for ( unsigned i = 0 ; i < 1024 ; i + + )
2014-06-15 17:20:33 +00:00
{
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , 0 ) ;
2014-06-15 17:20:33 +00:00
po + = 4 ;
}
// Jump to r2
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , ( 0x0 < < 26 ) | ( 2 < < 21 ) | ( 0x8 < < 0 ) ) ; // JR
2014-06-15 17:20:33 +00:00
po + = 4 ;
2018-02-21 22:45:09 +00:00
MDFN_en32lsb < false > ( po , 0 ) ; // NOP(kinda)
2014-06-15 17:20:33 +00:00
po + = 4 ;
2016-07-20 07:22:38 +00:00
2020-01-21 23:26:20 +00:00
# ifdef HAVE_LIGHTREC
/* Reload Expansion1 copy */
PSX_LoadExpansion1 ( ) ;
# endif
2016-07-20 07:22:38 +00:00
return true ;
2014-06-15 17:20:33 +00:00
}
2017-12-19 02:19:58 +00:00
static int Load ( const char * name , RFILE * fp )
2014-06-15 17:20:33 +00:00
{
2017-12-19 02:19:58 +00:00
int64_t size = filestream_get_size ( fp ) ;
2015-07-30 05:52:54 +00:00
const bool IsPSF = false ;
2020-02-03 17:17:44 +00:00
char image_label [ 4096 ] ;
image_label [ 0 ] = ' \0 ' ;
2014-06-15 17:20:33 +00:00
2017-12-19 02:19:58 +00:00
if ( ! TestMagic ( name , fp , size ) )
2016-07-20 04:05:30 +00:00
{
2016-08-09 05:24:22 +00:00
MDFN_Error ( 0 , " File format is unknown to module psx.. " ) ;
2016-07-20 04:05:30 +00:00
return - 1 ;
}
2014-06-15 17:20:33 +00:00
2015-07-30 05:52:54 +00:00
InitCommon ( NULL , ! IsPSF , true ) ;
2014-06-15 17:20:33 +00:00
2015-07-30 05:52:54 +00:00
TextMem . resize ( 0 ) ;
2014-06-15 17:20:33 +00:00
2017-12-19 02:19:58 +00:00
if ( size > = 0x800 )
2016-07-20 07:22:38 +00:00
{
2018-04-12 23:09:29 +00:00
int64_t len = size ;
2017-12-19 02:21:52 +00:00
uint8_t * header = ( uint8_t * ) malloc ( len * sizeof ( uint8_t ) ) ;
2017-12-19 02:19:58 +00:00
filestream_read_file ( name , ( void * * ) & header , & len ) ;
if ( ! LoadEXE ( header , len ) )
2016-07-20 07:22:38 +00:00
return - 1 ;
2017-12-19 02:19:58 +00:00
free ( header ) ;
2016-07-20 07:22:38 +00:00
}
2014-06-15 17:20:33 +00:00
2020-02-03 17:17:44 +00:00
disk_control_ext_info . image_paths . push_back ( name ) ;
extract_basename ( image_label , name , sizeof ( image_label ) ) ;
disk_control_ext_info . image_labels . push_back ( image_label ) ;
2015-07-30 05:52:54 +00:00
return ( 1 ) ;
2014-06-15 17:20:33 +00:00
}
2019-07-14 18:59:05 +00:00
static int LoadCD ( std : : vector < CDIF * > * _CDInterfaces )
2014-06-15 17:20:33 +00:00
{
2019-07-14 18:59:05 +00:00
InitCommon ( _CDInterfaces ) ;
2017-04-02 14:17:15 +00:00
2015-12-13 02:33:01 +00:00
if ( psx_skipbios = = 1 )
BIOSROM - > WriteU32 ( 0x6990 , 0 ) ;
2017-04-02 14:17:15 +00:00
2020-10-06 00:48:52 +00:00
EmulatedPSX . GameType = GMT_CDROM ;
2014-06-15 17:20:33 +00:00
return ( 1 ) ;
}
static void Cleanup ( void )
{
TextMem . resize ( 0 ) ;
2019-07-14 20:05:54 +00:00
if ( PSX_CDC )
delete PSX_CDC ;
PSX_CDC = NULL ;
2014-06-15 17:20:33 +00:00
2019-07-14 20:05:54 +00:00
if ( PSX_SPU )
delete PSX_SPU ;
PSX_SPU = NULL ;
2014-06-15 17:20:33 +00:00
2017-04-22 15:05:39 +00:00
GPU_Destroy ( ) ;
2014-06-15 17:20:33 +00:00
2019-07-14 20:05:54 +00:00
if ( PSX_CPU )
delete PSX_CPU ;
PSX_CPU = NULL ;
2014-06-15 17:20:33 +00:00
2019-07-14 20:05:54 +00:00
if ( PSX_FIO )
delete PSX_FIO ;
PSX_FIO = NULL ;
2017-12-18 14:20:17 +00:00
input_set_fio ( NULL ) ;
2014-06-15 17:20:33 +00:00
DMA_Kill ( ) ;
2020-01-21 23:26:20 +00:00
# ifdef HAVE_LIGHTREC
MainRAM = NULL ;
ScratchRAM = NULL ;
BIOSROM = NULL ;
2020-05-17 00:16:57 +00:00
if ( psx_mmap > 0 )
2020-04-29 22:05:48 +00:00
lightrec_free_mmap ( ) ;
2020-01-21 23:26:20 +00:00
# else
if ( MainRAM )
delete MainRAM ;
MainRAM = NULL ;
if ( ScratchRAM )
delete ScratchRAM ;
ScratchRAM = NULL ;
2014-06-15 17:20:33 +00:00
if ( BIOSROM )
delete BIOSROM ;
BIOSROM = NULL ;
2020-01-21 23:26:20 +00:00
# endif
2014-06-15 17:20:33 +00:00
if ( PIOMem )
delete PIOMem ;
PIOMem = NULL ;
cdifs = NULL ;
}
static void CloseGame ( void )
{
int i ;
2016-02-13 19:56:18 +00:00
if ( ! failed_init )
2014-06-15 17:20:33 +00:00
{
2016-02-13 19:56:18 +00:00
for ( i = 0 ; i < 8 ; i + + )
2014-06-16 16:43:58 +00:00
{
2016-02-13 19:56:18 +00:00
if ( i = = 0 & & ! use_mednafen_memcard0_method )
{
2019-07-14 20:05:54 +00:00
PSX_FIO - > SaveMemcard ( i ) ;
2016-02-13 19:56:18 +00:00
continue ;
}
2014-06-16 16:43:58 +00:00
2016-02-13 19:56:18 +00:00
// If there's an error saving one memcard, don't skip trying to save the other, since it might succeed and
// we can reduce potential data loss!
try
{
char ext [ 64 ] ;
const char * memcard = NULL ;
2020-05-26 03:02:51 +00:00
if ( i = = 0 )
snprintf ( ext , sizeof ( ext ) , " %d.mcr " , memcard_left_index ) ;
else if ( i = = 1 )
snprintf ( ext , sizeof ( ext ) , " %d.mcr " , memcard_right_index ) ;
else
snprintf ( ext , sizeof ( ext ) , " %d.mcr " , i ) ;
2016-02-13 19:56:18 +00:00
memcard = MDFN_MakeFName ( MDFNMKF_SAV , 0 , ext ) ;
2019-07-14 20:05:54 +00:00
PSX_FIO - > SaveMemcard ( i , memcard ) ;
2016-02-13 19:56:18 +00:00
}
catch ( std : : exception & e )
{
}
2014-06-15 17:20:33 +00:00
}
}
Cleanup ( ) ;
}
static void CDInsertEject ( void )
{
CD_TrayOpen = ! CD_TrayOpen ;
for ( unsigned disc = 0 ; disc < cdifs - > size ( ) ; disc + + )
{
if ( ! ( * cdifs ) [ disc ] - > Eject ( CD_TrayOpen ) )
{
2020-05-29 13:43:50 +00:00
MDFND_DispMessage ( 3 , RETRO_LOG_ERROR ,
RETRO_MESSAGE_TARGET_ALL , RETRO_MESSAGE_TYPE_NOTIFICATION_ALT ,
" Eject error. " ) ;
2014-06-15 17:20:33 +00:00
CD_TrayOpen = ! CD_TrayOpen ;
}
}
if ( CD_TrayOpen )
2020-05-29 13:43:50 +00:00
MDFND_DispMessage ( 0 , RETRO_LOG_INFO ,
RETRO_MESSAGE_TARGET_OSD , RETRO_MESSAGE_TYPE_NOTIFICATION_ALT ,
" Virtual CD Drive Tray Open " ) ;
2014-06-15 17:20:33 +00:00
else
2020-05-29 13:43:50 +00:00
MDFND_DispMessage ( 0 , RETRO_LOG_INFO ,
RETRO_MESSAGE_TARGET_OSD , RETRO_MESSAGE_TYPE_NOTIFICATION_ALT ,
" Virtual CD Drive Tray Closed " ) ;
2014-06-15 17:20:33 +00:00
2018-01-13 08:46:38 +00:00
SetDiscWrapper ( CD_TrayOpen ) ;
2014-06-15 17:20:33 +00:00
}
static void CDEject ( void )
{
if ( ! CD_TrayOpen )
CDInsertEject ( ) ;
}
static void CDSelect ( void )
{
2020-05-26 17:22:48 +00:00
if ( cdifs & & CD_TrayOpen )
{
int disc_count = ( CD_IsPBP ? PBP_PhysicalDiscCount : ( int ) cdifs - > size ( ) ) ;
2014-06-15 17:20:33 +00:00
2020-05-26 17:22:48 +00:00
CD_SelectedDisc = ( CD_SelectedDisc + 1 ) % ( disc_count + 1 ) ;
2016-05-10 12:00:53 +00:00
2020-05-26 17:22:48 +00:00
if ( CD_SelectedDisc = = disc_count )
CD_SelectedDisc = - 1 ;
2014-06-15 17:20:33 +00:00
2020-05-26 17:22:48 +00:00
if ( CD_SelectedDisc = = - 1 )
2020-05-29 13:43:50 +00:00
MDFND_DispMessage ( 0 , RETRO_LOG_INFO ,
RETRO_MESSAGE_TARGET_OSD , RETRO_MESSAGE_TYPE_NOTIFICATION_ALT ,
" Disc absence selected. " ) ;
2020-05-26 17:22:48 +00:00
else
2020-05-29 13:43:50 +00:00
MDFN_DispMessage ( 0 , RETRO_LOG_INFO ,
RETRO_MESSAGE_TARGET_OSD , RETRO_MESSAGE_TYPE_NOTIFICATION_ALT ,
" Disc %d of %d selected. " , CD_SelectedDisc + 1 , disc_count ) ;
2020-05-26 17:22:48 +00:00
}
2014-06-15 17:20:33 +00:00
}
2020-07-01 16:20:31 +00:00
extern " C " int StateAction ( StateMem * sm , int load , int data_only )
2017-11-21 05:08:11 +00:00
{
SFORMAT StateRegs [ ] =
{
SFVAR ( CD_TrayOpen ) ,
SFVAR ( CD_SelectedDisc ) ,
2020-04-06 11:53:56 +00:00
SFARRAYN ( MainRAM - > data8 , 1024 * 2048 , " MainRAM.data8 " ) ,
2017-11-21 05:08:11 +00:00
SFARRAY32 ( SysControl . Regs , 9 ) ,
SFVAR ( PSX_PRNG . lcgo ) ,
SFVAR ( PSX_PRNG . x ) ,
SFVAR ( PSX_PRNG . y ) ,
SFVAR ( PSX_PRNG . z ) ,
SFVAR ( PSX_PRNG . c ) ,
SFEND
} ;
int ret = MDFNSS_StateAction ( sm , load , data_only , StateRegs , " MAIN " ) ;
// Call SetDisc() BEFORE we load CDC state, since SetDisc() has emulation side effects. We might want to clean this up in the future.
if ( load )
{
if ( CD_IsPBP )
{
2020-04-09 10:38:02 +00:00
if ( ! cdifs | | CD_SelectedDisc > = PBP_PhysicalDiscCount )
2017-11-21 05:08:11 +00:00
CD_SelectedDisc = - 1 ;
CDEject ( ) ;
CDInsertEject ( ) ;
} else {
if ( ! cdifs | | CD_SelectedDisc > = ( int ) cdifs - > size ( ) )
CD_SelectedDisc = - 1 ;
2018-01-13 08:46:38 +00:00
SetDiscWrapper ( CD_TrayOpen ) ;
2017-11-21 05:08:11 +00:00
}
}
// TODO: Remember to increment dirty count in memory card state loading routine.
2019-07-14 20:05:54 +00:00
ret & = PSX_CPU - > StateAction ( sm , load , data_only ) ;
2017-11-21 05:08:11 +00:00
ret & = DMA_StateAction ( sm , load , data_only ) ;
ret & = TIMER_StateAction ( sm , load , data_only ) ;
ret & = SIO_StateAction ( sm , load , data_only ) ;
2019-07-14 20:05:54 +00:00
ret & = PSX_CDC - > StateAction ( sm , load , data_only ) ;
2017-11-21 05:08:11 +00:00
ret & = MDEC_StateAction ( sm , load , data_only ) ;
ret & = GPU_StateAction ( sm , load , data_only ) ;
2019-07-14 20:05:54 +00:00
ret & = PSX_SPU - > StateAction ( sm , load , data_only ) ;
2017-11-21 05:08:11 +00:00
2019-07-14 20:05:54 +00:00
ret & = PSX_FIO - > StateAction ( sm , load , data_only ) ;
2017-11-21 05:08:11 +00:00
ret & = IRQ_StateAction ( sm , load , data_only ) ; // Do it last.
if ( load )
{
ForceEventUpdates ( 0 ) ; // FIXME to work with debugger step mode.
}
return ( ret ) ;
}
2014-06-16 18:41:31 +00:00
static void DoSimpleCommand ( int cmd )
2014-06-15 17:20:33 +00:00
{
switch ( cmd )
{
case MDFN_MSC_RESET :
PSX_Power ( ) ;
break ;
case MDFN_MSC_POWER :
PSX_Power ( ) ;
break ;
case MDFN_MSC_INSERT_DISK :
CDInsertEject ( ) ;
break ;
case MDFN_MSC_SELECT_DISK :
CDSelect ( ) ;
break ;
case MDFN_MSC_EJECT_DISK :
CDEject ( ) ;
break ;
}
}
2014-12-07 16:40:31 +00:00
static void GSCondCode ( MemoryPatch * patch , const char * cc , const unsigned len , const uint32 addr , const uint16 val )
{
2017-07-31 02:42:23 +00:00
char tmp [ 256 ] ;
2014-12-07 16:40:31 +00:00
2017-07-31 02:42:23 +00:00
if ( patch - > conditions . size ( ) > 0 )
patch - > conditions . append ( " , " ) ;
2014-12-07 16:40:31 +00:00
2017-07-31 02:42:23 +00:00
if ( len = = 2 )
snprintf ( tmp , 256 , " %u L 0x%08x %s 0x%04x " , len , addr , cc , val & 0xFFFFU ) ;
else
snprintf ( tmp , 256 , " %u L 0x%08x %s 0x%02x " , len , addr , cc , val & 0xFFU ) ;
2014-12-07 16:40:31 +00:00
2017-07-31 02:42:23 +00:00
patch - > conditions . append ( tmp ) ;
2014-12-07 16:40:31 +00:00
}
static bool DecodeGS ( const std : : string & cheat_string , MemoryPatch * patch )
{
2017-07-31 02:42:23 +00:00
uint64 code = 0 ;
unsigned nybble_count = 0 ;
2014-12-07 16:40:31 +00:00
2017-07-31 02:42:23 +00:00
for ( unsigned i = 0 ; i < cheat_string . size ( ) ; i + + )
{
if ( cheat_string [ i ] = = ' ' | | cheat_string [ i ] = = ' - ' | | cheat_string [ i ] = = ' : ' | | cheat_string [ i ] = = ' + ' )
continue ;
2014-12-07 16:40:31 +00:00
2017-07-31 02:42:23 +00:00
nybble_count + + ;
code < < = 4 ;
2014-12-07 16:40:31 +00:00
2017-07-31 02:42:23 +00:00
if ( cheat_string [ i ] > = ' 0 ' & & cheat_string [ i ] < = ' 9 ' )
code | = cheat_string [ i ] - ' 0 ' ;
else if ( cheat_string [ i ] > = ' a ' & & cheat_string [ i ] < = ' f ' )
code | = cheat_string [ i ] - ' a ' + 0xA ;
else if ( cheat_string [ i ] > = ' A ' & & cheat_string [ i ] < = ' F ' )
code | = cheat_string [ i ] - ' A ' + 0xA ;
else
{
if ( cheat_string [ i ] & 0x80 )
log_cb ( RETRO_LOG_ERROR , " [Mednafen]: Invalid character in GameShark code.. \n " ) ;
else
log_cb ( RETRO_LOG_ERROR , " [Mednafen]: Invalid character in GameShark code: %c. \n " , cheat_string [ i ] ) ;
return false ;
}
}
2014-12-07 16:40:31 +00:00
2017-07-31 02:42:23 +00:00
if ( nybble_count ! = 12 )
{
log_cb ( RETRO_LOG_ERROR , " GameShark code is of an incorrect length. \n " ) ;
return false ;
}
2014-12-07 16:40:31 +00:00
2017-07-31 02:42:23 +00:00
const uint8 code_type = code > > 40 ;
const uint64 cl = code & 0xFFFFFFFFFFULL ;
2014-12-07 16:40:31 +00:00
2017-07-31 02:42:23 +00:00
patch - > bigendian = false ;
patch - > compare = 0 ;
2014-12-07 16:40:31 +00:00
2017-07-31 02:42:23 +00:00
if ( patch - > type = = ' T ' )
{
if ( code_type ! = 0x80 )
log_cb ( RETRO_LOG_ERROR , " Unrecognized GameShark code type for second part to copy bytes code. \n " ) ;
patch - > addr = cl > > 16 ;
return ( false ) ;
}
switch ( code_type )
{
default :
log_cb ( RETRO_LOG_ERROR , " GameShark code type 0x%02X is currently not supported. \n " , code_type ) ;
return ( false ) ;
// TODO:
case 0x10 : // 16-bit increment
patch - > length = 2 ;
patch - > type = ' A ' ;
patch - > addr = cl > > 16 ;
patch - > val = cl & 0xFFFF ;
return ( false ) ;
case 0x11 : // 16-bit decrement
patch - > length = 2 ;
patch - > type = ' A ' ;
patch - > addr = cl > > 16 ;
patch - > val = ( 0 - cl ) & 0xFFFF ;
return ( false ) ;
case 0x20 : // 8-bit increment
patch - > length = 1 ;
patch - > type = ' A ' ;
patch - > addr = cl > > 16 ;
patch - > val = cl & 0xFF ;
return ( false ) ;
case 0x21 : // 8-bit decrement
patch - > length = 1 ;
patch - > type = ' A ' ;
patch - > addr = cl > > 16 ;
patch - > val = ( 0 - cl ) & 0xFF ;
return ( false ) ;
//
//
//
case 0x30 : // 8-bit constant
patch - > length = 1 ;
patch - > type = ' R ' ;
patch - > addr = cl > > 16 ;
patch - > val = cl & 0xFF ;
return ( false ) ;
case 0x80 : // 16-bit constant
patch - > length = 2 ;
patch - > type = ' R ' ;
patch - > addr = cl > > 16 ;
patch - > val = cl & 0xFFFF ;
return ( false ) ;
case 0x50 : // Repeat thingy
{
const uint8 wcount = ( cl > > 24 ) & 0xFF ;
const uint8 addr_inc = ( cl > > 16 ) & 0xFF ;
const uint8 val_inc = ( cl > > 0 ) & 0xFF ;
patch - > mltpl_count = wcount ;
patch - > mltpl_addr_inc = addr_inc ;
patch - > mltpl_val_inc = val_inc ;
}
return ( true ) ;
case 0xC2 : // Copy
{
const uint16 ccount = cl & 0xFFFF ;
patch - > type = ' T ' ;
patch - > val = 0 ;
patch - > length = 1 ;
patch - > copy_src_addr = cl > > 16 ;
patch - > copy_src_addr_inc = 1 ;
patch - > mltpl_count = ccount ;
patch - > mltpl_addr_inc = 1 ;
patch - > mltpl_val_inc = 0 ;
}
return ( true ) ;
case 0xD0 : // 16-bit == condition
GSCondCode ( patch , " == " , 2 , cl > > 16 , cl ) ;
return ( true ) ;
case 0xD1 : // 16-bit != condition
GSCondCode ( patch , " != " , 2 , cl > > 16 , cl ) ;
return ( true ) ;
case 0xD2 : // 16-bit < condition
GSCondCode ( patch , " < " , 2 , cl > > 16 , cl ) ;
return ( true ) ;
case 0xD3 : // 16-bit > condition
GSCondCode ( patch , " > " , 2 , cl > > 16 , cl ) ;
return ( true ) ;
case 0xE0 : // 8-bit == condition
GSCondCode ( patch , " == " , 1 , cl > > 16 , cl ) ;
return ( true ) ;
case 0xE1 : // 8-bit != condition
GSCondCode ( patch , " != " , 1 , cl > > 16 , cl ) ;
return ( true ) ;
case 0xE2 : // 8-bit < condition
GSCondCode ( patch , " < " , 1 , cl > > 16 , cl ) ;
return ( true ) ;
case 0xE3 : // 8-bit > condition
GSCondCode ( patch , " > " , 1 , cl > > 16 , cl ) ;
return ( true ) ;
2014-12-07 16:40:31 +00:00
}
}
static CheatFormatStruct CheatFormats [ ] =
{
2017-07-31 02:42:23 +00:00
{ " GameShark " , " Sharks with lamprey eels for eyes. " , DecodeGS } ,
2014-12-07 16:40:31 +00:00
} ;
static CheatFormatInfoStruct CheatFormatInfo =
{
2017-07-31 02:42:23 +00:00
1 ,
CheatFormats
2014-12-07 16:40:31 +00:00
} ;
2014-06-15 17:20:33 +00:00
// Note for the future: If we ever support PSX emulation with non-8-bit RGB color components, or add a new linear RGB colorspace to MDFN_PixelFormat, we'll need
// to buffer the intermediate 24-bit non-linear RGB calculation into an array and pass that into the GPULineHook stuff, otherwise netplay could break when
// an emulated GunCon is used. This IS assuming, of course, that we ever implement save state support so that netplay actually works at all...
MDFNGI EmulatedPSX =
{
2017-07-31 02:42:23 +00:00
true , // Multires possible?
2014-06-15 17:20:33 +00:00
2017-07-31 02:42:23 +00:00
//
// Note: Following video settings will be overwritten during game load.
//
0 , // lcm_width
0 , // lcm_height
NULL , // Dummy
2014-06-15 17:20:33 +00:00
2017-07-31 02:42:23 +00:00
320 , // Nominal width
240 , // Nominal height
2014-06-15 17:20:33 +00:00
2017-07-31 02:42:23 +00:00
0 , // Framebuffer width
0 , // Framebuffer height
2014-06-15 17:20:33 +00:00
} ;
/* end of Mednafen psx.cpp */
2014-06-15 01:05:14 +00:00
//forward decls
extern void Emulate ( EmulateSpecStruct * espec ) ;
2013-02-25 19:39:39 +00:00
static bool overscan ;
2012-11-16 14:12:25 +00:00
static double last_sound_rate ;
# ifdef NEED_DEINTERLACER
static bool PrevInterlaced ;
static Deinterlacer deint ;
# endif
2016-01-31 01:07:26 +00:00
static MDFN_Surface * surf = NULL ;
2017-04-22 15:05:39 +00:00
static void alloc_surface ( void )
{
MDFN_PixelFormat pix_fmt ( MDFN_COLORSPACE_RGB , 16 , 8 , 0 , 24 ) ;
uint32_t width = MEDNAFEN_CORE_GEOMETRY_MAX_W ;
2020-03-10 00:39:40 +00:00
uint32_t height = content_is_pal ? MEDNAFEN_CORE_GEOMETRY_MAX_H : 480 ;
2016-01-31 01:07:26 +00:00
2017-07-30 17:27:25 +00:00
width < < = GPU_get_upscale_shift ( ) ;
height < < = GPU_get_upscale_shift ( ) ;
2016-01-31 01:07:26 +00:00
2017-04-22 15:05:39 +00:00
if ( surf ! = NULL )
delete surf ;
2016-01-31 01:07:26 +00:00
2017-04-22 15:05:39 +00:00
surf = new MDFN_Surface ( NULL , width , height , width , pix_fmt ) ;
2016-01-31 01:07:26 +00:00
}
2012-10-20 21:32:28 +00:00
static void check_system_specs ( void )
{
// Hints that we need a fairly powerful system to run this.
2014-06-15 00:49:49 +00:00
unsigned level = 15 ;
2012-10-22 12:34:14 +00:00
environ_cb ( RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL , & level ) ;
2012-10-20 21:32:28 +00:00
}
2013-02-21 22:44:41 +00:00
static unsigned disk_get_num_images ( void )
{
2016-05-10 12:00:53 +00:00
if ( cdifs )
2020-04-09 10:38:02 +00:00
return CD_IsPBP ? PBP_PhysicalDiscCount : cdifs - > size ( ) ;
2016-05-20 23:43:43 +00:00
return 0 ;
2013-02-21 22:44:41 +00:00
}
static bool disk_set_eject_state ( bool ejected )
{
2015-07-30 04:15:09 +00:00
log_cb ( RETRO_LOG_INFO , " [Mednafen]: Ejected: %u. \n " , ejected ) ;
2013-02-21 22:44:41 +00:00
if ( ejected = = eject_state )
return false ;
2014-06-15 04:52:49 +00:00
DoSimpleCommand ( ejected ? MDFN_MSC_EJECT_DISK : MDFN_MSC_INSERT_DISK ) ;
2013-02-21 22:44:41 +00:00
eject_state = ejected ;
return true ;
}
static bool disk_get_eject_state ( void )
{
return eject_state ;
}
static unsigned disk_get_image_index ( void )
{
// PSX global. Hacky.
2013-03-09 09:24:29 +00:00
return CD_SelectedDisc ;
2013-02-21 22:44:41 +00:00
}
static bool disk_set_image_index ( unsigned index )
{
CD_SelectedDisc = index ;
if ( CD_SelectedDisc > disk_get_num_images ( ) )
CD_SelectedDisc = disk_get_num_images ( ) ;
// Very hacky. CDSelect command will increment first.
CD_SelectedDisc - - ;
2014-06-15 04:52:49 +00:00
DoSimpleCommand ( MDFN_MSC_SELECT_DISK ) ;
2013-02-21 22:44:41 +00:00
return true ;
}
2013-04-27 14:40:24 +00:00
// Mednafen PSX really doesn't support adding disk images on the fly ...
// Hack around this.
2013-03-09 09:24:29 +00:00
// Untested ...
static bool disk_replace_image_index ( unsigned index , const struct retro_game_info * info )
{
2016-05-10 12:00:53 +00:00
if ( index > = disk_get_num_images ( ) | | ! eject_state | | CD_IsPBP )
2013-03-09 09:24:29 +00:00
return false ;
2013-03-09 09:31:20 +00:00
if ( ! info )
{
delete cdifs - > at ( index ) ;
cdifs - > erase ( cdifs - > begin ( ) + index ) ;
if ( index < CD_SelectedDisc )
CD_SelectedDisc - - ;
2015-10-15 03:12:39 +00:00
2020-02-03 17:17:44 +00:00
disk_control_ext_info . image_paths . erase (
disk_control_ext_info . image_paths . begin ( ) + index ) ;
disk_control_ext_info . image_labels . erase (
disk_control_ext_info . image_labels . begin ( ) + index ) ;
2013-04-27 13:48:36 +00:00
// Poke into psx.cpp
CalcDiscSCEx ( ) ;
2013-03-09 09:31:20 +00:00
return true ;
}
2016-07-20 03:52:35 +00:00
bool success = true ;
2016-08-14 12:17:05 +00:00
2016-07-20 03:52:35 +00:00
CDIF * iface = CDIF_Open ( & success , info - > path , false , false ) ;
2015-09-30 01:39:52 +00:00
2016-07-20 03:52:35 +00:00
if ( ! success )
2013-03-09 09:24:29 +00:00
return false ;
2016-07-20 03:52:35 +00:00
delete cdifs - > at ( index ) ;
cdifs - > at ( index ) = iface ;
CalcDiscSCEx ( ) ;
/* If we replace, we want the "swap disk manually effect". */
extract_basename ( retro_cd_base_name , info - > path , sizeof ( retro_cd_base_name ) ) ;
2020-02-03 17:17:44 +00:00
/* Update disk path/label vectors */
disk_control_ext_info . image_paths [ index ] = info - > path ;
disk_control_ext_info . image_labels [ index ] = retro_cd_base_name ;
2016-07-20 03:52:35 +00:00
return true ;
2013-03-09 09:24:29 +00:00
}
static bool disk_add_image_index ( void )
{
2016-05-10 12:00:53 +00:00
if ( CD_IsPBP )
return false ;
2013-03-09 09:24:29 +00:00
cdifs - > push_back ( NULL ) ;
2020-02-03 17:17:44 +00:00
disk_control_ext_info . image_paths . push_back ( " " ) ;
disk_control_ext_info . image_labels . push_back ( " " ) ;
2013-03-09 09:24:29 +00:00
return true ;
}
2020-02-03 17:17:44 +00:00
static bool disk_set_initial_image ( unsigned index , const char * path )
{
if ( string_is_empty ( path ) )
return false ;
disk_control_ext_info . initial_index = index ;
disk_control_ext_info . initial_path = path ;
return true ;
}
static bool disk_get_image_path ( unsigned index , char * path , size_t len )
{
if ( len < 1 )
return false ;
if ( ( index < disk_get_num_images ( ) ) & &
( index < disk_control_ext_info . image_paths . size ( ) ) )
{
if ( ! string_is_empty ( disk_control_ext_info . image_paths [ index ] . c_str ( ) ) )
{
strlcpy ( path , disk_control_ext_info . image_paths [ index ] . c_str ( ) , len ) ;
return true ;
}
}
return false ;
}
static bool disk_get_image_label ( unsigned index , char * label , size_t len )
{
if ( len < 1 )
return false ;
if ( ( index < disk_get_num_images ( ) ) & &
( index < disk_control_ext_info . image_labels . size ( ) ) )
{
if ( ! string_is_empty ( disk_control_ext_info . image_labels [ index ] . c_str ( ) ) )
{
strlcpy ( label , disk_control_ext_info . image_labels [ index ] . c_str ( ) , len ) ;
return true ;
}
}
return false ;
}
2013-02-21 22:44:41 +00:00
static struct retro_disk_control_callback disk_interface = {
disk_set_eject_state ,
disk_get_eject_state ,
disk_get_image_index ,
disk_set_image_index ,
disk_get_num_images ,
2013-03-09 09:24:29 +00:00
disk_replace_image_index ,
disk_add_image_index ,
2013-02-21 22:44:41 +00:00
} ;
2020-02-03 17:17:44 +00:00
static struct retro_disk_control_ext_callback disk_interface_ext =
{
disk_set_eject_state ,
disk_get_eject_state ,
disk_get_image_index ,
disk_set_image_index ,
disk_get_num_images ,
disk_replace_image_index ,
disk_add_image_index ,
disk_set_initial_image ,
disk_get_image_path ,
disk_get_image_label ,
} ;
2015-07-30 04:15:09 +00:00
static void fallback_log ( enum retro_log_level level , const char * fmt , . . . )
{
}
2015-09-30 01:39:52 +00:00
2014-04-21 22:25:50 +00:00
void retro_init ( void )
2012-06-03 15:48:14 +00:00
{
2014-01-02 01:50:09 +00:00
struct retro_log_callback log ;
2016-10-08 22:33:41 +00:00
uint64_t serialization_quirks = RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE ;
2020-02-03 17:17:44 +00:00
unsigned dci_version = 0 ;
2016-02-09 17:33:17 +00:00
2014-01-02 01:50:09 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_LOG_INTERFACE , & log ) )
log_cb = log . log ;
2015-10-15 03:12:39 +00:00
else
2015-07-30 04:15:09 +00:00
log_cb = fallback_log ;
2014-01-02 01:50:09 +00:00
2020-05-29 13:43:50 +00:00
libretro_msg_interface_version = 0 ;
environ_cb ( RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION , & libretro_msg_interface_version ) ;
2015-07-28 20:35:18 +00:00
CDUtility_Init ( ) ;
2014-06-16 21:58:16 +00:00
2013-02-21 22:44:41 +00:00
eject_state = false ;
2012-06-03 15:48:14 +00:00
2012-06-11 23:03:09 +00:00
const char * dir = NULL ;
2012-06-15 23:00:17 +00:00
2012-06-11 23:03:09 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY , & dir ) & & dir )
{
2015-09-30 01:39:52 +00:00
snprintf ( retro_base_directory , sizeof ( retro_base_directory ) , " %s " , dir ) ;
2012-06-11 23:03:09 +00:00
}
2012-06-15 23:00:17 +00:00
else
2012-06-11 23:03:09 +00:00
{
2013-12-17 01:24:08 +00:00
/* TODO: Add proper fallback */
2015-07-30 04:15:09 +00:00
log_cb ( RETRO_LOG_WARN , " System directory is not defined. Fallback on using same dir as ROM for system directory later ... \n " ) ;
2012-06-15 23:00:17 +00:00
failed_init = true ;
2012-06-11 23:03:09 +00:00
}
2015-07-28 20:35:18 +00:00
2014-02-07 07:07:58 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY , & dir ) & & dir )
{
2015-07-28 20:35:18 +00:00
// If save directory is defined use it, otherwise use system directory
2015-09-30 01:39:52 +00:00
if ( dir )
snprintf ( retro_save_directory , sizeof ( retro_save_directory ) , " %s " , dir ) ;
else
snprintf ( retro_save_directory , sizeof ( retro_save_directory ) , " %s " , retro_base_directory ) ;
2014-02-07 07:07:58 +00:00
}
else
{
/* TODO: Add proper fallback */
2015-07-30 04:15:09 +00:00
log_cb ( RETRO_LOG_WARN , " Save directory is not defined. Fallback on using SYSTEM directory ... \n " ) ;
2015-09-30 01:39:52 +00:00
snprintf ( retro_save_directory , sizeof ( retro_save_directory ) , " %s " , retro_base_directory ) ;
2015-10-15 03:12:39 +00:00
}
2012-06-09 22:46:41 +00:00
2020-02-03 17:17:44 +00:00
/* Initialise disk control interface */
disk_control_ext_info . initial_index = 0 ;
disk_control_ext_info . initial_path . clear ( ) ;
disk_control_ext_info . image_paths . clear ( ) ;
disk_control_ext_info . image_labels . clear ( ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION , & dci_version ) & & ( dci_version > = 1 ) )
environ_cb ( RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE , & disk_interface_ext ) ;
else
environ_cb ( RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE , & disk_interface ) ;
2012-10-22 12:34:14 +00:00
2014-04-21 22:25:50 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_PERF_INTERFACE , & perf_cb ) )
perf_get_cpu_features_cb = perf_cb . get_cpu_features ;
else
perf_get_cpu_features_cb = NULL ;
2016-10-08 22:33:41 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS , & serialization_quirks ) & &
( serialization_quirks & RETRO_SERIALIZATION_QUIRK_FRONT_VARIABLE_SIZE ) )
enable_variable_serialization_size = true ;
2014-06-25 18:53:33 +00:00
setting_initial_scanline = 0 ;
setting_last_scanline = 239 ;
setting_initial_scanline_pal = 0 ;
setting_last_scanline_pal = 287 ;
2019-07-07 07:23:53 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_INPUT_BITMASKS , NULL ) )
libretro_supports_bitmasks = true ;
2012-10-20 21:32:28 +00:00
check_system_specs ( ) ;
2012-06-03 15:48:14 +00:00
}
2014-04-20 14:32:46 +00:00
void retro_reset ( void )
2012-06-03 15:48:14 +00:00
{
2014-06-15 04:52:49 +00:00
DoSimpleCommand ( MDFN_MSC_RESET ) ;
2012-06-03 15:48:14 +00:00
}
bool retro_load_game_special ( unsigned , const struct retro_game_info * , size_t )
{
return false ;
}
2016-10-08 14:35:06 +00:00
# ifdef EMSCRIPTEN
2021-03-17 17:22:14 +00:00
static bool cdimagecache = true ;
2016-10-08 14:35:06 +00:00
# else
2021-03-17 17:22:14 +00:00
static bool cdimagecache = false ;
2016-10-08 14:35:06 +00:00
# endif
2014-06-20 20:36:21 +00:00
2019-11-24 10:23:52 +00:00
static bool boot = true ;
2014-08-17 07:00:48 +00:00
// shared memory cards support
static bool shared_memorycards = false ;
2017-09-03 22:29:52 +00:00
static bool has_new_geometry = false ;
2020-03-01 07:53:26 +00:00
static bool has_new_timing = false ;
2017-09-03 22:29:52 +00:00
2022-08-17 13:46:28 +00:00
uint8_t analog_combo [ 2 ] = { 0 } ;
2023-03-23 21:41:07 +00:00
uint8_t HOLD = { 0 } ;
2022-08-17 13:46:28 +00:00
2021-03-24 13:00:10 +00:00
extern void PSXDitherApply ( bool ) ;
2019-11-24 10:23:52 +00:00
static void check_variables ( bool startup )
2013-04-09 02:05:18 +00:00
{
struct retro_variable var = { 0 } ;
2016-10-08 14:35:06 +00:00
# ifndef EMSCRIPTEN
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( cd_access_method ) ;
2014-06-20 20:51:49 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2014-06-20 20:36:21 +00:00
{
2017-10-15 19:48:44 +00:00
if ( strcmp ( var . value , " sync " ) = = 0 )
{
2021-03-17 17:22:14 +00:00
cdimagecache = false ;
2017-10-15 19:48:44 +00:00
cd_async = false ;
}
else if ( strcmp ( var . value , " async " ) = = 0 )
{
2021-03-17 17:22:14 +00:00
cdimagecache = false ;
2017-10-15 19:48:44 +00:00
cd_async = true ;
}
else if ( strcmp ( var . value , " precache " ) = = 0 )
2014-06-20 20:36:21 +00:00
{
2021-03-17 17:22:14 +00:00
cdimagecache = true ;
2017-10-15 19:48:44 +00:00
cd_async = false ;
2014-06-20 20:36:21 +00:00
}
}
2016-10-08 14:35:06 +00:00
# endif
2016-01-29 07:05:18 +00:00
2020-01-21 23:26:20 +00:00
# ifdef HAVE_LIGHTREC
var . key = BEETLE_OPT ( cpu_dynarec ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " execute " ) = = 0 )
psx_dynarec = DYNAREC_EXECUTE ;
else if ( strcmp ( var . value , " execute_one " ) = = 0 )
psx_dynarec = DYNAREC_EXECUTE_ONE ;
else if ( strcmp ( var . value , " run_interpreter " ) = = 0 )
psx_dynarec = DYNAREC_RUN_INTERPRETER ;
else
psx_dynarec = DYNAREC_DISABLED ;
}
else
2020-01-23 07:12:21 +00:00
psx_dynarec = DYNAREC_DISABLED ;
2020-01-21 23:26:20 +00:00
var . key = BEETLE_OPT ( dynarec_invalidate ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " full " ) = = 0 )
psx_dynarec_invalidate = false ;
else if ( strcmp ( var . value , " dma " ) = = 0 )
psx_dynarec_invalidate = true ;
}
else
psx_dynarec_invalidate = false ;
var . key = BEETLE_OPT ( dynarec_eventcycles ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
EventCycles = atoi ( var . value ) ;
}
else
EventCycles = 128 ;
2022-09-01 03:37:29 +00:00
var . key = BEETLE_OPT ( dynarec_spu_samples ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
spu_samples = atoi ( var . value ) ;
}
else
spu_samples = 1 ;
2020-01-21 23:26:20 +00:00
# endif
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( cpu_freq_scale ) ;
2018-02-08 11:14:56 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
int scale_percent = atoi ( var . value ) ;
2019-11-15 15:07:45 +00:00
if ( scale_percent = = 100 )
2018-02-08 11:14:56 +00:00
psx_overclock_factor = 0 ;
2019-11-15 15:07:45 +00:00
else
2018-02-08 11:14:56 +00:00
psx_overclock_factor = ( ( scale_percent < < OVERCLOCK_SHIFT ) + 50 ) / 100 ;
}
else
psx_overclock_factor = 0 ;
// Need to adjust the CPU<->GPU frequency ratio if the overclocking changes
GPU_RecalcClockRatio ( ) ;
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( gte_overclock ) ;
2016-01-29 07:05:18 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " enabled " ) = = 0 )
2018-02-08 18:19:43 +00:00
psx_gte_overclock = true ;
2016-01-29 07:05:18 +00:00
else if ( strcmp ( var . value , " disabled " ) = = 0 )
2018-02-08 18:19:43 +00:00
psx_gte_overclock = false ;
2016-01-29 07:05:18 +00:00
}
else
2018-02-08 18:19:43 +00:00
psx_gte_overclock = false ;
2017-04-02 14:17:15 +00:00
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( gpu_overclock ) ;
2018-02-09 10:09:28 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2019-11-24 10:23:52 +00:00
{
unsigned val = atoi ( var . value ) ;
2018-02-09 10:09:28 +00:00
2019-11-24 10:23:52 +00:00
// Upscale must be a power of two
assert ( ( val & ( val - 1 ) ) = = 0 ) ;
2018-02-09 10:09:28 +00:00
2019-11-24 10:23:52 +00:00
// Crappy "ffs" implementation since the standard function is not
// widely supported by libc in the wild
uint8_t n ;
for ( n = 0 ; ( val & 1 ) = = 0 ; + + n )
{
val > > = 1 ;
}
psx_gpu_overclock_shift = n ;
2018-02-09 10:09:28 +00:00
}
else
psx_gpu_overclock_shift = 0 ;
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( skip_bios ) ;
2015-12-13 02:33:01 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " enabled " ) = = 0 )
psx_skipbios = 1 ;
else
psx_skipbios = 0 ;
2017-04-02 14:17:15 +00:00
}
2021-10-08 21:55:58 +00:00
var . key = BEETLE_OPT ( override_bios ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( var . value , " disabled " ) )
{
override_bios = 0 ;
}
else if ( ! strcmp ( var . value , " psxonpsp " ) )
{
override_bios = 1 ;
}
else if ( ! strcmp ( var . value , " ps1_rom " ) )
{
override_bios = 2 ;
}
}
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( widescreen_hack ) ;
2015-07-28 18:46:24 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2017-11-19 10:45:16 +00:00
if ( strcmp ( var . value , " enabled " ) = = 0 )
2017-09-03 22:29:52 +00:00
{
2020-02-27 03:05:15 +00:00
if ( widescreen_hack = = false )
has_new_geometry = true ;
2015-07-28 18:46:24 +00:00
widescreen_hack = true ;
2017-09-03 22:29:52 +00:00
}
2015-07-28 18:46:24 +00:00
else if ( strcmp ( var . value , " disabled " ) = = 0 )
2017-09-03 22:29:52 +00:00
{
2020-02-27 03:05:15 +00:00
if ( widescreen_hack = = true )
has_new_geometry = true ;
2015-07-28 18:46:24 +00:00
widescreen_hack = false ;
2017-09-03 22:29:52 +00:00
}
2015-07-28 18:46:24 +00:00
}
else
2020-02-27 03:05:15 +00:00
{
if ( widescreen_hack = = true )
has_new_geometry = true ;
2016-01-31 02:39:46 +00:00
widescreen_hack = false ;
2020-02-27 03:05:15 +00:00
}
2015-07-28 18:46:24 +00:00
2020-12-12 10:18:40 +00:00
var . key = BEETLE_OPT ( widescreen_hack_aspect_ratio ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( var . value , " 16:10 " ) )
{
if ( ! startup & & widescreen_hack_aspect_ratio_setting ! = 0 )
has_new_geometry = true ;
widescreen_hack_aspect_ratio_setting = 0 ;
}
else if ( ! strcmp ( var . value , " 16:9 " ) )
{
if ( ! startup & & widescreen_hack_aspect_ratio_setting ! = 1 )
has_new_geometry = true ;
widescreen_hack_aspect_ratio_setting = 1 ;
}
2021-07-22 10:24:11 +00:00
else if ( ! strcmp ( var . value , " 18:9 " ) )
2020-12-12 10:18:40 +00:00
{
if ( ! startup & & widescreen_hack_aspect_ratio_setting ! = 2 )
has_new_geometry = true ;
widescreen_hack_aspect_ratio_setting = 2 ;
}
2021-07-22 10:24:11 +00:00
else if ( ! strcmp ( var . value , " 19:9 " ) )
2020-12-12 10:18:40 +00:00
{
if ( ! startup & & widescreen_hack_aspect_ratio_setting ! = 3 )
has_new_geometry = true ;
widescreen_hack_aspect_ratio_setting = 3 ;
}
2021-07-22 10:24:11 +00:00
else if ( ! strcmp ( var . value , " 20:9 " ) )
{
if ( ! startup & & widescreen_hack_aspect_ratio_setting ! = 4 )
has_new_geometry = true ;
widescreen_hack_aspect_ratio_setting = 4 ;
}
else if ( ! strcmp ( var . value , " 21:9 " ) ) // 64:27
{
if ( ! startup & & widescreen_hack_aspect_ratio_setting ! = 5 )
has_new_geometry = true ;
widescreen_hack_aspect_ratio_setting = 5 ;
}
else if ( ! strcmp ( var . value , " 32:9 " ) )
{
if ( ! startup & & widescreen_hack_aspect_ratio_setting ! = 6 )
has_new_geometry = true ;
widescreen_hack_aspect_ratio_setting = 6 ;
}
2020-12-12 10:18:40 +00:00
}
2021-04-22 00:06:23 +00:00
else
{
if ( ! startup & & widescreen_hack_aspect_ratio_setting ! = 1 )
has_new_geometry = true ;
widescreen_hack_aspect_ratio_setting = 1 ;
}
2020-12-12 10:18:40 +00:00
2020-03-25 07:46:17 +00:00
var . key = BEETLE_OPT ( pal_video_timing_override ) ;
2020-03-24 00:16:02 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2020-03-25 07:46:17 +00:00
bool want_fast_pal = ( strcmp ( var . value , " enabled " ) = = 0 ) ;
2020-03-24 00:16:02 +00:00
if ( want_fast_pal ! = fast_pal ) {
fast_pal = want_fast_pal ;
has_new_timing = true ;
}
}
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( analog_calibration ) ;
2016-10-07 13:10:07 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " enabled " ) = = 0 )
2019-11-15 15:07:45 +00:00
input_enable_calibration ( true ) ;
2016-10-07 13:10:07 +00:00
else if ( strcmp ( var . value , " disabled " ) = = 0 )
2019-11-15 15:07:45 +00:00
input_enable_calibration ( false ) ;
2016-10-07 13:10:07 +00:00
}
else
2019-11-15 15:07:45 +00:00
input_enable_calibration ( false ) ;
2016-10-07 13:10:07 +00:00
2020-03-01 07:53:26 +00:00
var . key = BEETLE_OPT ( core_timing_fps ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " force_progressive " ) = = 0 )
{
if ( ! startup & & core_timing_fps_mode ! = FORCE_PROGRESSIVE_TIMING )
has_new_timing = true ;
core_timing_fps_mode = FORCE_PROGRESSIVE_TIMING ;
}
else if ( strcmp ( var . value , " force_interlaced " ) = = 0 )
{
if ( ! startup & & core_timing_fps_mode ! = FORCE_INTERLACED_TIMING )
has_new_timing = true ;
core_timing_fps_mode = FORCE_INTERLACED_TIMING ;
}
else // auto toggle setting, timing changes are allowed
{
if ( ! startup & & core_timing_fps_mode ! = AUTO_TOGGLE_TIMING )
has_new_timing = true ;
core_timing_fps_mode = AUTO_TOGGLE_TIMING ;
}
}
2020-02-27 03:05:15 +00:00
var . key = BEETLE_OPT ( aspect_ratio ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( var . value , " corrected " ) )
{
if ( ! startup & & aspect_ratio_setting ! = 0 )
has_new_geometry = true ;
aspect_ratio_setting = 0 ;
}
else if ( ! strcmp ( var . value , " uncorrected " ) )
{
if ( ! startup & & aspect_ratio_setting ! = 1 )
has_new_geometry = true ;
aspect_ratio_setting = 1 ;
}
else if ( ! strcmp ( var . value , " 4:3 " ) )
{
if ( ! startup & & aspect_ratio_setting ! = 2 )
has_new_geometry = true ;
aspect_ratio_setting = 2 ;
}
2020-03-25 07:46:17 +00:00
else if ( ! strcmp ( var . value , " ntsc " ) )
{
if ( ! startup & & aspect_ratio_setting ! = 3 )
has_new_geometry = true ;
aspect_ratio_setting = 3 ;
}
2020-02-27 03:05:15 +00:00
}
2019-11-24 10:23:52 +00:00
if ( startup )
{
var . key = BEETLE_OPT ( renderer ) ;
2019-11-24 10:51:56 +00:00
bool hw_renderer = false ;
2019-11-24 10:23:52 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2020-02-15 05:59:08 +00:00
if ( ! strcmp ( var . value , " hardware " ) | | ! strcmp ( var . value , " hardware_gl " ) | | ! strcmp ( var . value , " hardware_vk " ) )
2019-11-24 10:23:52 +00:00
{
2019-11-24 10:51:56 +00:00
hw_renderer = true ;
}
}
2019-11-24 10:23:52 +00:00
2020-09-27 08:01:20 +00:00
var . key = BEETLE_OPT ( internal_resolution ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2019-11-24 10:51:56 +00:00
{
2020-09-27 08:01:20 +00:00
uint8_t new_upscale_shift ;
uint8_t val = atoi ( var . value ) ;
2019-11-24 10:23:52 +00:00
2020-09-27 08:01:20 +00:00
// Upscale must be a power of two
assert ( ( val & ( val - 1 ) ) = = 0 ) ;
2019-11-24 10:23:52 +00:00
2020-09-27 08:01:20 +00:00
// Crappy "ffs" implementation since the standard function is not
// widely supported by libc in the wild
for ( new_upscale_shift = 0 ; ( val & 1 ) = = 0 ; + + new_upscale_shift )
val > > = 1 ;
psx_gpu_upscale_shift_hw = new_upscale_shift ;
2019-11-24 10:23:52 +00:00
}
2020-09-27 08:01:20 +00:00
else
psx_gpu_upscale_shift_hw = 0 ;
if ( hw_renderer )
psx_gpu_upscale_shift = 0 ;
else
psx_gpu_upscale_shift = psx_gpu_upscale_shift_hw ;
2019-11-24 10:23:52 +00:00
}
else
{
rsx_intf_refresh_variables ( ) ;
2020-09-27 08:01:20 +00:00
var . key = BEETLE_OPT ( internal_resolution ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2019-11-24 10:23:52 +00:00
{
2020-09-27 08:01:20 +00:00
uint8_t new_upscale_shift ;
uint8_t val = atoi ( var . value ) ;
2019-11-24 10:23:52 +00:00
2020-09-27 08:01:20 +00:00
// Upscale must be a power of two
assert ( ( val & ( val - 1 ) ) = = 0 ) ;
2019-11-24 10:23:52 +00:00
2020-09-27 08:01:20 +00:00
// Crappy "ffs" implementation since the standard function is not
// widely supported by libc in the wild
for ( new_upscale_shift = 0 ; ( val & 1 ) = = 0 ; + + new_upscale_shift )
val > > = 1 ;
psx_gpu_upscale_shift_hw = new_upscale_shift ;
}
else
psx_gpu_upscale_shift_hw = 0 ;
2019-11-24 10:23:52 +00:00
2020-09-27 08:01:20 +00:00
switch ( rsx_intf_is_type ( ) )
{
case RSX_SOFTWARE :
psx_gpu_upscale_shift = psx_gpu_upscale_shift_hw ;
2019-11-24 10:23:52 +00:00
break ;
case RSX_OPENGL :
case RSX_VULKAN :
psx_gpu_upscale_shift = 0 ;
break ;
}
}
2016-01-31 01:07:26 +00:00
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( dither_mode ) ;
2016-02-08 14:15:26 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2018-11-03 01:11:37 +00:00
if ( strcmp ( var . value , " 1x(native) " ) = = 0 )
2016-02-08 14:15:26 +00:00
psx_gpu_dither_mode = DITHER_NATIVE ;
2018-11-03 01:11:37 +00:00
else if ( strcmp ( var . value , " internal resolution " ) = = 0 )
2016-02-08 14:15:26 +00:00
psx_gpu_dither_mode = DITHER_UPSCALED ;
2018-11-03 01:11:37 +00:00
else if ( strcmp ( var . value , " disabled " ) = = 0 )
psx_gpu_dither_mode = DITHER_OFF ;
2016-02-08 14:15:26 +00:00
}
else
psx_gpu_dither_mode = DITHER_NATIVE ;
2016-09-25 10:52:57 +00:00
// iCB: PGXP settings
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( pgxp_mode ) ;
2016-09-25 10:52:57 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2017-07-31 02:42:23 +00:00
if ( strcmp ( var . value , " disabled " ) = = 0 )
psx_pgxp_mode = PGXP_MODE_NONE ;
else if ( strcmp ( var . value , " memory only " ) = = 0 )
psx_pgxp_mode = PGXP_MODE_MEMORY | PGXP_MODE_GTE ;
else if ( strcmp ( var . value , " memory + CPU " ) = = 0 )
psx_pgxp_mode = PGXP_MODE_MEMORY | PGXP_MODE_GTE | PGXP_MODE_CPU ;
2016-09-25 10:52:57 +00:00
}
else
2017-07-31 02:42:23 +00:00
psx_pgxp_mode = PGXP_MODE_NONE ;
2016-09-25 10:52:57 +00:00
2020-09-18 16:10:35 +00:00
var . key = BEETLE_OPT ( pgxp_2d_tol ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " disabled " ) = = 0 )
psx_pgxp_2d_tol = - 1 ;
else
psx_pgxp_2d_tol = atoi ( var . value ) ;
}
else
psx_pgxp_2d_tol = - 1 ;
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( pgxp_vertex ) ;
2016-09-25 10:52:57 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2017-07-31 02:42:23 +00:00
if ( strcmp ( var . value , " disabled " ) = = 0 )
psx_pgxp_vertex_caching = PGXP_MODE_NONE ;
else if ( strcmp ( var . value , " enabled " ) = = 0 )
psx_pgxp_vertex_caching = PGXP_VERTEX_CACHE ;
2016-09-25 10:52:57 +00:00
}
else
2017-07-31 02:42:23 +00:00
psx_pgxp_vertex_caching = PGXP_MODE_NONE ;
2016-09-25 10:52:57 +00:00
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( pgxp_texture ) ;
2016-09-25 10:52:57 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2017-07-31 02:42:23 +00:00
if ( strcmp ( var . value , " disabled " ) = = 0 )
psx_pgxp_texture_correction = PGXP_MODE_NONE ;
else if ( strcmp ( var . value , " enabled " ) = = 0 )
psx_pgxp_texture_correction = PGXP_TEXTURE_CORRECTION ;
2016-09-25 10:52:57 +00:00
}
else
2017-07-31 02:42:23 +00:00
psx_pgxp_texture_correction = PGXP_MODE_NONE ;
2016-09-25 10:52:57 +00:00
// \iCB
2018-11-03 01:11:37 +00:00
2020-09-22 23:19:18 +00:00
var . key = BEETLE_OPT ( pgxp_nclip ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " disabled " ) = = 0 )
psx_pgxp_nclip = PGXP_MODE_NONE ;
else if ( strcmp ( var . value , " enabled " ) = = 0 )
psx_pgxp_nclip = PGXP_NCLIP_IMPL ;
}
else
psx_pgxp_nclip = PGXP_MODE_NONE ;
2020-03-14 04:11:29 +00:00
var . key = BEETLE_OPT ( line_render ) ;
2018-08-28 03:19:57 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2019-11-15 15:07:45 +00:00
if ( strcmp ( var . value , " disabled " ) = = 0 )
2019-12-08 17:26:41 +00:00
line_render_mode = 0 ;
2019-11-15 15:07:45 +00:00
else if ( strcmp ( var . value , " default " ) = = 0 )
2019-12-08 17:26:41 +00:00
line_render_mode = 1 ;
2019-11-15 15:07:45 +00:00
else if ( strcmp ( var . value , " aggressive " ) = = 0 )
2019-12-08 17:26:41 +00:00
line_render_mode = 2 ;
2018-08-28 03:19:57 +00:00
}
2018-11-03 01:11:37 +00:00
2018-09-01 22:44:42 +00:00
var . key = BEETLE_OPT ( filter ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
int old_filter_mode = filter_mode ;
2019-11-15 15:07:45 +00:00
if ( strcmp ( var . value , " nearest " ) = = 0 )
2018-09-01 22:44:42 +00:00
filter_mode = 0 ;
2019-11-15 15:07:45 +00:00
else if ( strcmp ( var . value , " xBR " ) = = 0 )
2018-09-01 22:44:42 +00:00
filter_mode = 1 ;
2019-11-15 15:07:45 +00:00
else if ( strcmp ( var . value , " SABR " ) = = 0 )
2018-09-01 22:44:42 +00:00
filter_mode = 2 ;
2019-11-15 15:07:45 +00:00
else if ( strcmp ( var . value , " bilinear " ) = = 0 )
2018-09-01 22:44:42 +00:00
filter_mode = 3 ;
2019-11-15 15:07:45 +00:00
else if ( strcmp ( var . value , " 3-point " ) = = 0 )
2018-09-01 22:44:42 +00:00
filter_mode = 4 ;
2019-11-15 15:07:45 +00:00
else if ( strcmp ( var . value , " JINC2 " ) = = 0 )
2018-09-01 22:44:42 +00:00
filter_mode = 5 ;
2018-11-03 01:11:37 +00:00
2018-09-01 22:44:42 +00:00
if ( filter_mode ! = old_filter_mode )
{
opaque_check = true ;
semitrans_check = true ;
old_filter_mode = filter_mode ;
}
}
2016-09-25 10:52:57 +00:00
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( analog_toggle ) ;
2014-06-20 20:51:49 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2014-04-23 04:37:06 +00:00
{
2014-06-16 20:25:12 +00:00
if ( ( strcmp ( var . value , " enabled " ) = = 0 )
& & setting_psx_analog_toggle ! = 1 )
{
2014-04-23 04:37:06 +00:00
setting_psx_analog_toggle = 1 ;
2014-06-16 20:25:12 +00:00
setting_apply_analog_toggle = true ;
}
else if ( ( strcmp ( var . value , " disabled " ) = = 0 )
& & setting_psx_analog_toggle ! = 0 )
{
2014-04-23 04:37:06 +00:00
setting_psx_analog_toggle = 0 ;
2014-06-16 20:25:12 +00:00
setting_apply_analog_toggle = true ;
}
2015-10-15 03:12:39 +00:00
}
2022-08-17 13:46:28 +00:00
var . key = BEETLE_OPT ( analog_toggle_combo ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " l1+l2+r1+r2+start+select " ) = = 0 )
{
analog_combo [ 0 ] = 0x09 ;
analog_combo [ 1 ] = 0x0f ;
}
else if ( strcmp ( var . value , " l1+r1+select " ) = = 0 )
{
analog_combo [ 0 ] = 0x01 ;
analog_combo [ 1 ] = 0x0c ;
}
else if ( strcmp ( var . value , " l1+r1+start " ) = = 0 )
{
analog_combo [ 0 ] = 0x08 ;
analog_combo [ 1 ] = 0x0c ;
}
else if ( strcmp ( var . value , " l1+r1+l3 " ) = = 0 )
{
analog_combo [ 0 ] = 0x02 ;
analog_combo [ 1 ] = 0x0c ;
}
else if ( strcmp ( var . value , " l1+r1+r3 " ) = = 0 )
{
analog_combo [ 0 ] = 0x04 ;
analog_combo [ 1 ] = 0x0c ;
}
else if ( strcmp ( var . value , " l2+r2+select " ) = = 0 )
{
analog_combo [ 0 ] = 0x01 ;
analog_combo [ 1 ] = 0x03 ;
}
else if ( strcmp ( var . value , " l2+r2+start " ) = = 0 )
{
analog_combo [ 0 ] = 0x08 ;
analog_combo [ 1 ] = 0x03 ;
}
else if ( strcmp ( var . value , " l2+r2+l3 " ) = = 0 )
{
analog_combo [ 0 ] = 0x02 ;
analog_combo [ 1 ] = 0x03 ;
}
else if ( strcmp ( var . value , " l2+r2+r3 " ) = = 0 )
{
analog_combo [ 0 ] = 0x04 ;
analog_combo [ 1 ] = 0x03 ;
}
else if ( strcmp ( var . value , " l3+r3 " ) = = 0 )
{
analog_combo [ 0 ] = 0x06 ;
analog_combo [ 1 ] = 0x00 ;
}
}
2023-03-23 21:41:07 +00:00
var . key = BEETLE_OPT ( analog_toggle_hold ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " 0 " ) = = 0 )
{
HOLD = 0 ;
}
else if ( strcmp ( var . value , " 1 " ) = = 0 )
{
HOLD = 1 ;
}
else if ( strcmp ( var . value , " 2 " ) = = 0 )
{
HOLD = 2 ;
}
else if ( strcmp ( var . value , " 3 " ) = = 0 )
{
HOLD = 3 ;
}
else if ( strcmp ( var . value , " 4 " ) = = 0 )
{
HOLD = 4 ;
}
else if ( strcmp ( var . value , " 5 " ) = = 0 )
{
HOLD = 5 ;
}
}
2021-11-14 12:10:36 +00:00
var . key = BEETLE_OPT ( crosshair_color_p1 ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " red " ) = = 0 )
setting_crosshair_color_p1 = 0xFF0000 ;
else if ( strcmp ( var . value , " blue " ) = = 0 )
setting_crosshair_color_p1 = 0x0080FF ;
else if ( strcmp ( var . value , " green " ) = = 0 )
setting_crosshair_color_p1 = 0x00FF00 ;
else if ( strcmp ( var . value , " orange " ) = = 0 )
setting_crosshair_color_p1 = 0xFF8000 ;
else if ( strcmp ( var . value , " yellow " ) = = 0 )
setting_crosshair_color_p1 = 0xFFFF00 ;
else if ( strcmp ( var . value , " cyan " ) = = 0 )
setting_crosshair_color_p1 = 0x00FFFF ;
else if ( strcmp ( var . value , " pink " ) = = 0 )
setting_crosshair_color_p1 = 0xFF00FF ;
else if ( strcmp ( var . value , " purple " ) = = 0 )
setting_crosshair_color_p1 = 0x8000FF ;
else if ( strcmp ( var . value , " black " ) = = 0 )
setting_crosshair_color_p1 = 0x000000 ;
else if ( strcmp ( var . value , " white " ) = = 0 )
setting_crosshair_color_p1 = 0xFFFFFF ;
}
var . key = BEETLE_OPT ( crosshair_color_p2 ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " red " ) = = 0 )
setting_crosshair_color_p2 = 0xFF0000 ;
else if ( strcmp ( var . value , " blue " ) = = 0 )
setting_crosshair_color_p2 = 0x0080FF ;
else if ( strcmp ( var . value , " green " ) = = 0 )
setting_crosshair_color_p2 = 0x00FF00 ;
else if ( strcmp ( var . value , " orange " ) = = 0 )
setting_crosshair_color_p2 = 0xFF8000 ;
else if ( strcmp ( var . value , " yellow " ) = = 0 )
setting_crosshair_color_p2 = 0xFFFF00 ;
else if ( strcmp ( var . value , " cyan " ) = = 0 )
setting_crosshair_color_p2 = 0x00FFFF ;
else if ( strcmp ( var . value , " pink " ) = = 0 )
setting_crosshair_color_p2 = 0xFF00FF ;
else if ( strcmp ( var . value , " purple " ) = = 0 )
setting_crosshair_color_p2 = 0x8000FF ;
else if ( strcmp ( var . value , " black " ) = = 0 )
setting_crosshair_color_p2 = 0x000000 ;
else if ( strcmp ( var . value , " white " ) = = 0 )
setting_crosshair_color_p2 = 0xFFFFFF ;
}
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( enable_multitap_port1 ) ;
2014-06-20 20:51:49 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2013-05-24 18:39:17 +00:00
{
if ( strcmp ( var . value , " enabled " ) = = 0 )
setting_psx_multitap_port_1 = true ;
else if ( strcmp ( var . value , " disabled " ) = = 0 )
setting_psx_multitap_port_1 = false ;
2015-10-15 03:12:39 +00:00
}
2013-05-24 18:39:17 +00:00
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( enable_multitap_port2 ) ;
2014-06-20 20:51:49 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2013-05-24 18:39:17 +00:00
{
if ( strcmp ( var . value , " enabled " ) = = 0 )
setting_psx_multitap_port_2 = true ;
else if ( strcmp ( var . value , " disabled " ) = = 0 )
setting_psx_multitap_port_2 = false ;
}
2014-06-25 18:53:33 +00:00
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( mouse_sensitivity ) ;
2019-11-15 15:07:45 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
input_set_mouse_sensitivity ( atoi ( var . value ) ) ;
2017-11-23 13:08:26 +00:00
2019-11-15 15:07:45 +00:00
var . key = BEETLE_OPT ( gun_cursor ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " off " ) = = 0 )
input_set_gun_cursor ( FrontIO : : SETTING_GUN_CROSSHAIR_OFF ) ;
else if ( strcmp ( var . value , " cross " ) = = 0 )
input_set_gun_cursor ( FrontIO : : SETTING_GUN_CROSSHAIR_CROSS ) ;
else if ( strcmp ( var . value , " dot " ) = = 0 )
input_set_gun_cursor ( FrontIO : : SETTING_GUN_CROSSHAIR_DOT ) ;
}
2018-11-03 01:11:37 +00:00
2019-07-04 18:33:24 +00:00
var . key = BEETLE_OPT ( gun_input_mode ) ;
2019-11-15 15:07:45 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2019-07-04 18:33:24 +00:00
{
2019-11-15 15:07:45 +00:00
if ( strcmp ( var . value , " lightgun " ) = = 0 )
2019-07-04 18:33:24 +00:00
gun_input_mode = SETTING_GUN_INPUT_LIGHTGUN ;
2019-11-15 15:07:45 +00:00
else if ( strcmp ( var . value , " touchscreen " ) = = 0 )
2019-11-04 06:31:36 +00:00
gun_input_mode = SETTING_GUN_INPUT_POINTER ;
2019-11-15 15:07:45 +00:00
}
else
2019-11-04 06:31:36 +00:00
gun_input_mode = SETTING_GUN_INPUT_LIGHTGUN ;
2019-07-04 18:33:24 +00:00
2019-11-15 15:07:45 +00:00
var . key = BEETLE_OPT ( negcon_deadzone ) ;
input_set_negcon_deadzone ( 0 ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
input_set_negcon_deadzone ( ( int ) ( atoi ( var . value ) * 0.01f * NEGCON_RANGE ) ) ;
}
2017-11-23 13:08:26 +00:00
2019-11-15 15:07:45 +00:00
var . key = BEETLE_OPT ( negcon_response ) ;
input_set_negcon_linearity ( 1 ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " quadratic " ) = = 0 )
input_set_negcon_linearity ( 2 ) ;
else if ( strcmp ( var . value , " cubic " ) = = 0 )
input_set_negcon_linearity ( 3 ) ;
}
2014-06-25 18:53:33 +00:00
2020-02-27 03:05:15 +00:00
// Initial scanline NTSC
2019-11-15 15:07:45 +00:00
var . key = BEETLE_OPT ( initial_scanline ) ;
2014-06-25 18:53:33 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2020-02-27 03:05:15 +00:00
int new_scanline_value = atoi ( var . value ) ;
if ( setting_initial_scanline ! = new_scanline_value )
{
has_new_geometry = true ;
setting_initial_scanline = new_scanline_value ;
}
2014-06-25 18:53:33 +00:00
}
2020-02-27 03:05:15 +00:00
// Last scanline NTSC
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( last_scanline ) ;
2014-06-25 18:53:33 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2020-02-27 03:05:15 +00:00
int new_scanline_value = atoi ( var . value ) ;
if ( setting_last_scanline ! = new_scanline_value )
{
has_new_geometry = true ;
setting_last_scanline = new_scanline_value ;
}
2014-06-25 18:53:33 +00:00
}
2020-02-27 03:05:15 +00:00
// Initial scanline PAL
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( initial_scanline_pal ) ;
2014-06-25 18:53:33 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2020-02-27 03:05:15 +00:00
int new_scanline_value = atoi ( var . value ) ;
if ( setting_initial_scanline_pal ! = new_scanline_value )
{
has_new_geometry = true ;
setting_initial_scanline_pal = new_scanline_value ;
}
2014-06-25 18:53:33 +00:00
}
2020-02-27 03:05:15 +00:00
// Last scanline PAL
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( last_scanline_pal ) ;
2014-06-25 18:53:33 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2020-02-27 03:05:15 +00:00
int new_scanline_value = atoi ( var . value ) ;
if ( setting_last_scanline_pal ! = new_scanline_value )
{
has_new_geometry = true ;
setting_last_scanline_pal = new_scanline_value ;
}
2014-06-25 18:53:33 +00:00
}
2015-10-15 03:12:39 +00:00
2017-03-26 21:44:25 +00:00
if ( setting_psx_multitap_port_1 & & setting_psx_multitap_port_2 )
2019-11-15 15:07:45 +00:00
input_set_player_count ( 8 ) ;
2017-03-26 21:44:25 +00:00
else if ( setting_psx_multitap_port_1 | | setting_psx_multitap_port_2 )
2019-11-15 15:07:45 +00:00
input_set_player_count ( 5 ) ;
2014-08-16 20:32:37 +00:00
else
2019-11-15 15:07:45 +00:00
input_set_player_count ( 2 ) ;
2015-10-15 03:12:39 +00:00
2020-03-10 01:37:34 +00:00
/* Memcards (startup only) */
if ( startup )
2019-11-24 10:23:52 +00:00
{
2020-03-10 01:37:34 +00:00
var . key = BEETLE_OPT ( use_mednafen_memcard0_method ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( var . value , " libretro " ) )
use_mednafen_memcard0_method = false ;
else if ( ! strcmp ( var . value , " mednafen " ) )
use_mednafen_memcard0_method = true ;
}
2019-11-24 10:23:52 +00:00
2020-03-10 01:37:34 +00:00
var . key = BEETLE_OPT ( enable_memcard1 ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( var . value , " enabled " ) )
enable_memcard1 = true ;
else if ( ! strcmp ( var . value , " disabled " ) )
enable_memcard1 = false ;
}
2019-11-24 10:23:52 +00:00
2020-03-10 01:37:34 +00:00
var . key = BEETLE_OPT ( shared_memory_cards ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( var . value , " enabled " ) )
2019-11-24 10:23:52 +00:00
{
2021-01-31 18:05:56 +00:00
// if(use_mednafen_memcard0_method)
2020-03-10 01:37:34 +00:00
shared_memorycards = true ;
2021-01-31 18:05:56 +00:00
// else
// MDFND_DispMessage(3, RETRO_LOG_WARN,
// RETRO_MESSAGE_TARGET_ALL, RETRO_MESSAGE_TYPE_NOTIFICATION,
// "Memory Card 0 Method not set to Mednafen; shared memory cards could not be enabled.");
2019-11-24 10:23:52 +00:00
}
2020-03-10 01:37:34 +00:00
else if ( ! strcmp ( var . value , " disabled " ) )
2019-11-24 10:23:52 +00:00
{
shared_memorycards = false ;
}
2020-03-10 01:37:34 +00:00
}
2019-11-24 10:23:52 +00:00
}
2020-03-10 01:37:34 +00:00
/* End Memcards */
2019-11-24 10:23:52 +00:00
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( frame_duping ) ;
2016-02-07 22:43:26 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
2019-11-15 15:07:45 +00:00
if ( strcmp ( var . value , " enabled " ) = = 0 )
2016-02-07 22:43:26 +00:00
{
bool can_dupe = false ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_CAN_DUPE , & can_dupe ) )
2019-11-04 05:43:34 +00:00
allow_frame_duping = can_dupe ;
2016-02-07 22:43:26 +00:00
}
2019-11-15 15:07:45 +00:00
else if ( strcmp ( var . value , " disabled " ) = = 0 )
2016-02-07 22:43:26 +00:00
allow_frame_duping = false ;
}
else
allow_frame_duping = false ;
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( display_internal_fps ) ;
2016-02-07 13:57:39 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2019-11-15 15:07:45 +00:00
{
if ( strcmp ( var . value , " enabled " ) = = 0 )
2016-02-07 13:57:39 +00:00
display_internal_framerate = true ;
2019-11-15 15:07:45 +00:00
else if ( strcmp ( var . value , " disabled " ) = = 0 )
2016-02-07 13:57:39 +00:00
display_internal_framerate = false ;
2019-11-15 15:07:45 +00:00
}
2016-02-07 13:57:39 +00:00
else
2019-11-15 15:07:45 +00:00
display_internal_framerate = false ;
2016-02-07 13:57:39 +00:00
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( crop_overscan ) ;
2016-05-30 00:59:25 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2019-11-15 15:07:45 +00:00
{
2021-11-01 16:25:49 +00:00
int old_crop_overscan = crop_overscan ;
if ( strcmp ( var . value , " disabled " ) = = 0 )
crop_overscan = 0 ;
else if ( strcmp ( var . value , " static " ) = = 0 )
crop_overscan = 1 ;
else if ( strcmp ( var . value , " smart " ) = = 0 )
crop_overscan = 2 ;
if ( crop_overscan ! = old_crop_overscan )
2020-02-27 03:05:15 +00:00
{
2021-11-01 16:25:49 +00:00
has_new_geometry = true ;
old_crop_overscan = crop_overscan ;
2020-02-27 03:05:15 +00:00
}
2019-11-15 15:07:45 +00:00
}
2016-05-30 00:59:25 +00:00
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( image_offset ) ;
2016-05-22 14:24:43 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " disabled " ) = = 0 )
image_offset = 0 ;
2019-11-04 06:31:36 +00:00
else
image_offset = atoi ( var . value ) ;
2016-05-22 14:24:43 +00:00
}
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( image_crop ) ;
2016-05-30 00:59:25 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( strcmp ( var . value , " disabled " ) = = 0 )
image_crop = 0 ;
2019-11-04 06:31:36 +00:00
else
image_crop = atoi ( var . value ) ;
2016-05-30 00:59:25 +00:00
}
2018-03-13 11:28:29 +00:00
var . key = BEETLE_OPT ( cd_fastload ) ;
2017-10-08 21:04:32 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2019-11-15 15:07:45 +00:00
{
uint8_t val = var . value [ 0 ] - ' 0 ' ;
if ( var . value [ 1 ] ! = ' x ' )
2017-10-08 21:04:32 +00:00
{
2019-11-15 15:07:45 +00:00
val = ( var . value [ 0 ] - ' 0 ' ) * 10 ;
val + = var . value [ 1 ] - ' 0 ' ;
2017-10-08 21:04:32 +00:00
}
2019-11-15 15:07:45 +00:00
// Value is a multiplier from the native 2x, so we divide by two
cd_2x_speedup = val / 2 ;
}
2017-10-08 21:04:32 +00:00
else
cd_2x_speedup = 1 ;
2020-05-26 03:02:51 +00:00
var . key = BEETLE_OPT ( memcard_left_index ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
memcard_left_index_old = memcard_left_index ;
memcard_left_index = atoi ( var . value ) ;
}
var . key = BEETLE_OPT ( memcard_right_index ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
memcard_right_index_old = memcard_right_index ;
memcard_right_index = atoi ( var . value ) ;
}
2013-04-09 02:05:18 +00:00
}
2014-06-16 21:58:16 +00:00
# ifdef NEED_CD
static void ReadM3U ( std : : vector < std : : string > & file_list , std : : string path , unsigned depth = 0 )
{
std : : string dir_path ;
char linebuf [ 2048 ] ;
2021-04-05 16:23:02 +00:00
RFILE * fp = filestream_open ( path . c_str ( ) , RETRO_VFS_FILE_ACCESS_READ ,
RETRO_VFS_FILE_ACCESS_HINT_NONE ) ;
2015-10-01 01:20:54 +00:00
if ( fp = = NULL )
return ;
2014-06-16 21:58:16 +00:00
MDFN_GetFilePathComponents ( path , & dir_path ) ;
2021-04-05 16:23:02 +00:00
while ( filestream_gets ( fp , linebuf , sizeof ( linebuf ) ) ! = NULL )
2014-06-16 21:58:16 +00:00
{
std : : string efp ;
2016-06-09 05:59:14 +00:00
if ( linebuf [ 0 ] = = ' # ' )
continue ;
string_trim_whitespace_right ( linebuf ) ;
if ( linebuf [ 0 ] = = 0 )
continue ;
2014-06-16 21:58:16 +00:00
2020-09-14 07:58:05 +00:00
efp = MDFN_EvalFIP ( dir_path , std : : string ( linebuf ) , false ) ;
2014-06-16 21:58:16 +00:00
if ( efp . size ( ) > = 4 & & efp . substr ( efp . size ( ) - 4 ) = = " .m3u " )
{
if ( efp = = path )
{
2015-07-30 04:15:09 +00:00
log_cb ( RETRO_LOG_ERROR , " M3U at \" %s \" references self. \n " , efp . c_str ( ) ) ;
2015-10-01 01:20:54 +00:00
goto end ;
2014-06-16 21:58:16 +00:00
}
if ( depth = = 99 )
{
2015-07-30 04:15:09 +00:00
log_cb ( RETRO_LOG_ERROR , " M3U load recursion too deep! \n " ) ;
2015-10-01 01:20:54 +00:00
goto end ;
2014-06-16 21:58:16 +00:00
}
ReadM3U ( file_list , efp , depth + + ) ;
}
else
file_list . push_back ( efp ) ;
}
2015-10-01 01:20:54 +00:00
end :
2021-04-05 16:23:02 +00:00
filestream_close ( fp ) ;
2014-06-16 21:58:16 +00:00
}
// TODO: LoadCommon()
2020-09-17 22:14:34 +00:00
static bool MDFNI_LoadCD ( const char * devicename )
2014-06-16 21:58:16 +00:00
{
2016-08-06 04:41:12 +00:00
log_cb ( RETRO_LOG_INFO , " Loading %s... \n " , devicename ) ;
2014-06-16 21:58:16 +00:00
2016-07-20 03:52:35 +00:00
try
{
2022-07-21 14:40:55 +00:00
size_t devicename_len = strlen ( devicename ) ;
if ( devicename & & devicename_len > 4 & & ! strcasecmp ( devicename + devicename_len - 4 , " .m3u " ) )
2016-07-20 03:52:35 +00:00
{
2020-02-03 17:17:44 +00:00
ReadM3U ( disk_control_ext_info . image_paths , devicename ) ;
2014-06-16 21:58:16 +00:00
2020-02-03 17:17:44 +00:00
for ( unsigned i = 0 ; i < disk_control_ext_info . image_paths . size ( ) ; i + + )
2016-07-20 03:52:35 +00:00
{
2020-02-03 17:17:44 +00:00
char image_label [ 4096 ] ;
2016-07-20 03:52:35 +00:00
bool success = true ;
2020-02-03 17:17:44 +00:00
image_label [ 0 ] = ' \0 ' ;
CDIF * image = CDIF_Open (
2021-03-17 17:22:14 +00:00
& success , disk_control_ext_info . image_paths [ i ] . c_str ( ) , false , cdimagecache ) ;
2016-07-20 04:05:30 +00:00
CDInterfaces . push_back ( image ) ;
2020-02-03 17:17:44 +00:00
extract_basename (
image_label , disk_control_ext_info . image_paths [ i ] . c_str ( ) ,
sizeof ( image_label ) ) ;
disk_control_ext_info . image_labels . push_back ( image_label ) ;
2016-07-20 03:52:35 +00:00
}
}
2022-07-21 14:40:55 +00:00
else if ( devicename & & devicename_len > 4 & & ! strcasecmp ( devicename + devicename_len - 4 , " .pbp " ) )
2016-07-20 03:52:35 +00:00
{
bool success = true ;
2021-03-17 17:22:14 +00:00
CDIF * image = CDIF_Open ( & success , devicename , false , cdimagecache ) ;
2016-07-20 04:05:30 +00:00
CD_IsPBP = true ;
CDInterfaces . push_back ( image ) ;
2020-02-03 17:17:44 +00:00
/* CDIF_Open() sets PBP_DiscCount, so we can populate
* image_paths / image_labels here */
2020-04-09 10:38:02 +00:00
PBP_PhysicalDiscCount = ( PBP_DiscCount = = 0 ) ?
1 : PBP_DiscCount ;
for ( unsigned i = 0 ; i < PBP_PhysicalDiscCount ; i + + )
2020-02-03 17:17:44 +00:00
{
2021-04-22 02:55:06 +00:00
/* image_name is at most 4096 - 4 (removing ".pbp")
* gives label room to add index and quiets gcc warnings */
char image_name [ 4092 ] ;
2020-02-03 17:17:44 +00:00
char image_label [ 4096 ] ;
image_name [ 0 ] = ' \0 ' ;
image_label [ 0 ] = ' \0 ' ;
/* All 'disks' have the same path when using
* multi - disk PBP files */
disk_control_ext_info . image_paths . push_back ( devicename ) ;
/* Label is name+index */
extract_basename ( image_name , devicename , sizeof ( image_name ) ) ;
snprintf ( image_label , sizeof ( image_label ) , " %s #%u " , image_name , i + 1 ) ;
disk_control_ext_info . image_labels . push_back ( image_label ) ;
}
2016-07-20 03:52:35 +00:00
}
else
{
2020-02-03 17:17:44 +00:00
char image_label [ 4096 ] ;
2016-07-20 03:52:35 +00:00
bool success = true ;
2020-02-03 17:17:44 +00:00
image_label [ 0 ] = ' \0 ' ;
2021-06-10 00:32:48 +00:00
bool cache = cdimagecache ;
/* don't precache if physical cdrom, will take way too long and be unresponive */
if ( cdimagecache & & devicename & & ! strncasecmp ( devicename , " cdrom: " , 6 ) ) {
cache = false ;
log_cb ( RETRO_LOG_INFO , " Skipping Pre-Cache due to using physical media: %s \n " , devicename ) ;
}
CDIF * image = CDIF_Open ( & success , devicename , false , cache ) ;
2018-10-18 10:06:21 +00:00
if ( ! success )
2020-09-17 22:14:34 +00:00
return false ;
2018-10-18 10:06:21 +00:00
2016-07-20 04:05:30 +00:00
CDInterfaces . push_back ( image ) ;
2020-02-03 17:17:44 +00:00
disk_control_ext_info . image_paths . push_back ( devicename ) ;
extract_basename ( image_label , devicename , sizeof ( image_label ) ) ;
disk_control_ext_info . image_labels . push_back ( image_label ) ;
2016-07-20 03:52:35 +00:00
}
}
catch ( std : : exception & e )
2014-06-16 21:58:16 +00:00
{
2016-07-20 03:52:35 +00:00
log_cb ( RETRO_LOG_ERROR , " Error opening CD. \n " ) ;
2020-09-17 22:14:34 +00:00
return false ;
2014-06-16 21:58:16 +00:00
}
2021-03-24 14:16:32 +00:00
# ifdef DEBUG
2016-07-20 04:05:30 +00:00
// Print out a track list for all discs.
2016-07-20 03:52:35 +00:00
for ( unsigned i = 0 ; i < CDInterfaces . size ( ) ; i + + )
{
TOC toc ;
TOC_Clear ( & toc ) ;
2014-06-16 21:58:16 +00:00
2016-07-20 03:52:35 +00:00
CDInterfaces [ i ] - > ReadTOC ( & toc ) ;
2014-06-16 21:58:16 +00:00
2016-07-20 03:52:35 +00:00
log_cb ( RETRO_LOG_DEBUG , " CD %d Layout: \n " , i + 1 ) ;
2014-06-16 21:58:16 +00:00
2016-07-20 03:52:35 +00:00
for ( int32 track = toc . first_track ; track < = toc . last_track ; track + + )
{
log_cb ( RETRO_LOG_DEBUG , " Track %2d, LBA: %6d %s \n " , track , toc . tracks [ track ] . lba , ( toc . tracks [ track ] . control & 0x4 ) ? " DATA " : " AUDIO " ) ;
}
2014-06-16 21:58:16 +00:00
2016-07-20 03:52:35 +00:00
log_cb ( RETRO_LOG_DEBUG , " Leadout: %6d \n " , toc . tracks [ 100 ] . lba ) ;
}
2021-03-24 14:16:32 +00:00
# endif
2014-06-16 21:58:16 +00:00
2016-08-09 05:24:22 +00:00
if ( ! ( LoadCD ( & CDInterfaces ) ) )
2016-07-20 03:52:35 +00:00
{
for ( unsigned i = 0 ; i < CDInterfaces . size ( ) ; i + + )
delete CDInterfaces [ i ] ;
CDInterfaces . clear ( ) ;
2014-06-16 21:58:16 +00:00
2020-02-03 17:17:44 +00:00
disk_control_ext_info . initial_index = 0 ;
disk_control_ext_info . initial_path . clear ( ) ;
disk_control_ext_info . image_paths . clear ( ) ;
disk_control_ext_info . image_labels . clear ( ) ;
2020-09-17 22:14:34 +00:00
return false ;
2016-07-20 03:52:35 +00:00
}
2014-06-16 21:58:16 +00:00
2016-07-20 03:52:35 +00:00
//MDFNI_SetLayerEnableMask(~0ULL);
2014-06-16 21:58:16 +00:00
2016-07-20 03:52:35 +00:00
MDFN_LoadGameCheats ( NULL ) ;
MDFNMP_InstallReadPatches ( ) ;
2014-06-16 21:58:16 +00:00
2020-09-17 22:14:34 +00:00
return true ;
2014-06-16 21:58:16 +00:00
}
# endif
2020-09-17 22:14:34 +00:00
static bool MDFNI_LoadGame ( const char * name )
2014-06-16 21:58:16 +00:00
{
2017-12-19 02:19:58 +00:00
RFILE * GameFile = NULL ;
2022-07-21 14:40:55 +00:00
size_t name_len = strlen ( name ) ;
if ( name_len > 4 & & (
! strcasecmp ( name + name_len - 4 , " .cue " ) | |
! strcasecmp ( name + name_len - 4 , " .ccd " ) | |
! strcasecmp ( name + name_len - 4 , " .toc " ) | |
! strcasecmp ( name + name_len - 4 , " .m3u " ) | |
! strcasecmp ( name + name_len - 4 , " .chd " ) | |
! strcasecmp ( name + name_len - 4 , " .pbp " )
2017-08-31 17:01:39 +00:00
) )
2017-07-31 02:42:23 +00:00
return MDFNI_LoadCD ( name ) ;
2014-06-16 21:58:16 +00:00
2017-12-19 02:19:58 +00:00
GameFile = filestream_open ( name ,
RETRO_VFS_FILE_ACCESS_READ ,
RETRO_VFS_FILE_ACCESS_HINT_NONE ) ;
2016-05-06 20:23:23 +00:00
if ( ! GameFile )
goto error ;
2016-08-09 05:24:22 +00:00
if ( Load ( name , GameFile ) < = 0 )
2015-07-25 16:06:37 +00:00
goto error ;
2014-06-16 21:58:16 +00:00
2017-12-19 02:19:58 +00:00
filestream_close ( GameFile ) ;
2015-07-25 16:06:37 +00:00
GameFile = NULL ;
2014-06-16 21:58:16 +00:00
2020-09-17 22:14:34 +00:00
return true ;
2015-07-25 16:06:37 +00:00
error :
if ( GameFile )
2017-12-19 02:19:58 +00:00
filestream_close ( GameFile ) ;
2015-07-25 16:06:37 +00:00
GameFile = NULL ;
2020-09-17 22:14:34 +00:00
return false ;
2014-06-16 21:58:16 +00:00
}
2012-06-03 15:48:14 +00:00
bool retro_load_game ( const struct retro_game_info * info )
{
2017-01-24 14:22:56 +00:00
char tocbasepath [ 4096 ] ;
2015-09-30 01:39:52 +00:00
2017-02-04 18:12:00 +00:00
if ( failed_init )
2016-07-20 04:05:30 +00:00
return false ;
2014-02-08 01:41:05 +00:00
2019-11-15 15:07:45 +00:00
input_init_env ( environ_cb ) ;
2015-07-25 16:06:37 +00:00
2016-07-20 04:05:30 +00:00
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888 ;
if ( ! environ_cb ( RETRO_ENVIRONMENT_SET_PIXEL_FORMAT , & fmt ) )
return false ;
2016-01-28 20:10:34 +00:00
2016-07-20 04:05:30 +00:00
extract_basename ( retro_cd_base_name , info - > path , sizeof ( retro_cd_base_name ) ) ;
extract_directory ( retro_cd_base_directory , info - > path , sizeof ( retro_cd_base_directory ) ) ;
2012-10-13 13:31:49 +00:00
2020-05-17 22:17:32 +00:00
int r = snprintf ( tocbasepath , sizeof ( tocbasepath ) , " %s%c%s.toc " , retro_cd_base_directory , retro_slash , retro_cd_base_name ) ;
2012-11-16 14:12:25 +00:00
2020-05-17 22:17:32 +00:00
if ( r > = 0 & & r < 4096 & & filestream_exists ( tocbasepath ) )
2016-07-20 04:05:30 +00:00
snprintf ( retro_cd_path , sizeof ( retro_cd_path ) , " %s " , tocbasepath ) ;
else
snprintf ( retro_cd_path , sizeof ( retro_cd_path ) , " %s " , info - > path ) ;
2015-10-15 03:12:39 +00:00
2019-11-24 10:23:52 +00:00
check_variables ( true ) ;
2016-07-18 02:10:33 +00:00
2016-08-12 09:19:33 +00:00
if ( ! MDFNI_LoadGame ( retro_cd_path ) )
2014-08-01 17:05:09 +00:00
{
2016-07-20 04:05:30 +00:00
failed_init = true ;
return false ;
2016-07-18 02:10:33 +00:00
}
2016-07-20 04:05:30 +00:00
MDFN_LoadGameCheats ( NULL ) ;
MDFNMP_InstallReadPatches ( ) ;
2020-03-10 00:39:40 +00:00
// Determine content_is_pal before calling alloc_surface()
unsigned disc_region = CalcDiscSCEx ( ) ;
content_is_pal = ( disc_region = = REGION_EU ) ;
2016-07-20 04:05:30 +00:00
2019-11-24 10:23:52 +00:00
alloc_surface ( ) ;
# ifdef NEED_DEINTERLACER
PrevInterlaced = false ;
deint . ClearState ( ) ;
# endif
2020-02-15 05:59:08 +00:00
input_init ( ) ;
2016-07-20 04:05:30 +00:00
2019-11-24 10:23:52 +00:00
boot = false ;
2016-07-20 04:05:30 +00:00
frame_count = 0 ;
internal_frame_count = 0 ;
2020-03-10 00:39:40 +00:00
// MDFNI_LoadGame() has been called and surface has been allocated,
// we can now perform firmware check
2019-06-16 20:00:13 +00:00
bool force_software_renderer = false ;
2020-05-24 23:08:26 +00:00
if ( ! firmware_found )
2019-06-16 20:00:13 +00:00
{
log_cb ( RETRO_LOG_ERROR , " Content cannot be loaded \n " ) ;
2016-02-07 13:57:39 +00:00
2019-06-16 20:00:13 +00:00
/* TODO - We're forcing the sw renderer to show the ugui error message. Figure out
how to copy the ugui framebuffer to the hardware renderer side with rsx_intf calls ,
so we don ' t have to force this anymore . */
force_software_renderer = true ;
2020-01-21 23:26:20 +00:00
# ifdef HAVE_LIGHTREC
/* Do not run lightrec if firmware is not found, recompiling garbage is bad*/
psx_dynarec = DYNAREC_DISABLED ;
# endif
}
2019-09-05 16:30:27 +00:00
2020-03-10 00:39:40 +00:00
bool ret = rsx_intf_open ( content_is_pal , force_software_renderer ) ;
2019-09-05 16:30:27 +00:00
/* Hide irrelevant core options */
switch ( rsx_intf_is_type ( ) )
{
case RSX_SOFTWARE :
{
struct retro_core_option_display option_display ;
option_display . visible = false ;
option_display . key = BEETLE_OPT ( renderer_software_fb ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2020-09-27 08:01:20 +00:00
option_display . key = BEETLE_OPT ( scaled_uv_offset ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2020-09-27 07:01:09 +00:00
option_display . key = BEETLE_OPT ( filter_exclude_sprite ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( filter_exclude_2d_polygon ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2019-09-05 16:30:27 +00:00
option_display . key = BEETLE_OPT ( adaptive_smoothing ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( super_sampling ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( msaa ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( mdec_yuv ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2021-04-12 09:14:56 +00:00
option_display . key = BEETLE_OPT ( track_textures ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( dump_textures ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( replace_textures ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2019-09-05 16:30:27 +00:00
option_display . key = BEETLE_OPT ( depth ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( wireframe ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( display_vram ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( filter ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( pgxp_vertex ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( pgxp_texture ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2019-11-19 23:46:38 +00:00
option_display . key = BEETLE_OPT ( image_offset_cycles ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2019-09-05 16:30:27 +00:00
break ;
}
case RSX_OPENGL :
{
struct retro_core_option_display option_display ;
option_display . visible = false ;
2020-09-27 08:01:20 +00:00
option_display . key = BEETLE_OPT ( scaled_uv_offset ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2020-09-27 07:01:09 +00:00
option_display . key = BEETLE_OPT ( filter_exclude_sprite ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( filter_exclude_2d_polygon ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2019-09-05 16:30:27 +00:00
option_display . key = BEETLE_OPT ( adaptive_smoothing ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( super_sampling ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( msaa ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( mdec_yuv ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2021-04-12 09:14:56 +00:00
option_display . key = BEETLE_OPT ( track_textures ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( dump_textures ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( replace_textures ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2019-09-05 16:30:27 +00:00
2019-11-02 14:20:00 +00:00
option_display . key = BEETLE_OPT ( image_offset ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2019-11-04 05:43:34 +00:00
option_display . key = BEETLE_OPT ( frame_duping ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2019-09-05 16:30:27 +00:00
break ;
}
case RSX_VULKAN :
{
struct retro_core_option_display option_display ;
option_display . visible = false ;
option_display . key = BEETLE_OPT ( depth ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( wireframe ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2019-11-02 14:20:00 +00:00
option_display . key = BEETLE_OPT ( image_offset ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2019-09-05 16:30:27 +00:00
break ;
}
}
2020-03-10 09:18:28 +00:00
/* Hide irrelevant scanline core options for current content */
struct retro_core_option_display option_display ;
option_display . visible = false ;
if ( content_is_pal )
{
option_display . key = BEETLE_OPT ( initial_scanline ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( last_scanline ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
}
else
{
option_display . key = BEETLE_OPT ( initial_scanline_pal ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = BEETLE_OPT ( last_scanline_pal ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
}
2019-09-05 16:30:27 +00:00
return ret ;
2012-06-03 15:48:14 +00:00
}
2014-06-15 04:52:49 +00:00
void retro_unload_game ( void )
2012-06-03 15:48:14 +00:00
{
2016-04-08 15:03:52 +00:00
rsx_intf_close ( ) ;
2016-03-24 18:02:55 +00:00
2014-12-24 20:32:23 +00:00
MDFN_FlushGameCheats ( 0 ) ;
2014-06-16 21:58:16 +00:00
2016-08-09 05:24:22 +00:00
CloseGame ( ) ;
2014-06-16 21:58:16 +00:00
MDFNMP_Kill ( ) ;
for ( unsigned i = 0 ; i < CDInterfaces . size ( ) ; i + + )
delete CDInterfaces [ i ] ;
CDInterfaces . clear ( ) ;
2015-09-30 01:39:52 +00:00
2020-02-03 17:17:44 +00:00
disk_control_ext_info . initial_index = 0 ;
disk_control_ext_info . initial_path . clear ( ) ;
disk_control_ext_info . image_paths . clear ( ) ;
disk_control_ext_info . image_labels . clear ( ) ;
2015-09-30 01:39:52 +00:00
retro_cd_base_directory [ 0 ] = ' \0 ' ;
retro_cd_path [ 0 ] = ' \0 ' ;
retro_cd_base_name [ 0 ] = ' \0 ' ;
2014-06-16 21:58:16 +00:00
}
2013-04-09 03:23:42 +00:00
2012-09-20 19:38:19 +00:00
static uint64_t video_frames , audio_frames ;
2014-06-15 03:42:21 +00:00
# define SOUND_CHANNELS 2
2013-04-09 02:05:18 +00:00
2014-06-15 00:49:49 +00:00
void retro_run ( void )
2012-06-03 15:48:14 +00:00
{
2014-06-16 19:11:57 +00:00
bool updated = false ;
2018-04-24 01:16:53 +00:00
//code to implement audio and video disable is not yet implemented
//bool disableVideo = false;
//bool disableAudio = false;
//bool hardDisableAudio = false;
//int flags = 3;
//if (environ_cb(RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE, &flags))
//{
// disableVideo = !(flags & 1);
// disableAudio = !(flags & 2);
// hardDisableAudio = !!(flags & 8);
//}
2016-02-09 17:33:17 +00:00
2018-06-30 23:32:16 +00:00
if ( gui_show & & gui_inited & & frame_width > 0 & & frame_height > 0 )
{
gui_draw ( ) ;
video_cb ( gui_get_framebuffer ( ) , frame_width , frame_height , frame_width * sizeof ( unsigned ) ) ;
}
2016-04-08 15:03:52 +00:00
rsx_intf_prepare_frame ( ) ;
2016-03-24 18:02:55 +00:00
2019-11-24 10:23:52 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE , & updated ) & & updated )
2015-07-28 18:46:24 +00:00
{
2019-11-24 10:23:52 +00:00
check_variables ( false ) ;
struct retro_system_av_info new_av_info ;
2017-09-04 20:57:19 +00:00
2019-11-24 10:23:52 +00:00
/* Max width/height changed, need to call SET_SYSTEM_AV_INFO */
if ( GPU_get_upscale_shift ( ) ! = psx_gpu_upscale_shift )
2015-07-28 18:46:24 +00:00
{
2019-11-24 10:23:52 +00:00
retro_get_system_av_info ( & new_av_info ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO , & new_av_info ) )
{
// We successfully changed the frontend's resolution, we can
// apply the change immediately
GPU_Rescale ( psx_gpu_upscale_shift ) ;
alloc_surface ( ) ;
has_new_geometry = false ;
}
else
{
// Failed, we have to postpone the upscaling change
psx_gpu_upscale_shift = GPU_get_upscale_shift ( ) ;
}
2016-01-31 02:39:46 +00:00
}
2016-02-08 14:15:26 +00:00
2020-03-01 07:53:26 +00:00
/* Core timing option changed, need to call SET_SYSTEM_AV_INFO
*
* Note : May be possible to bundle this dirty flag with the other
* dirty flags such as the one for widescreen hack and do a full
* RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO callback ; should be acceptable
* to have video / audio reinits after changing core options
*/
if ( has_new_timing )
{
retro_get_system_av_info ( & new_av_info ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO , & new_av_info ) )
has_new_timing = false ;
}
2020-02-27 03:05:15 +00:00
/* Widescreen hack, scanlines, overscan cropping, or aspect ratio setting
changed , need to call SET_GEOMETRY to change aspect ratio */
2017-09-04 20:57:19 +00:00
if ( has_new_geometry )
{
retro_get_system_av_info ( & new_av_info ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_SET_GEOMETRY , & new_av_info ) )
{
has_new_geometry = false ;
}
}
2017-04-22 15:05:39 +00:00
switch ( psx_gpu_dither_mode )
{
case DITHER_NATIVE :
2019-11-24 10:23:52 +00:00
GPU_set_dither_upscale_shift ( psx_gpu_upscale_shift ) ;
2017-04-22 15:05:39 +00:00
break ;
case DITHER_UPSCALED :
2019-10-08 20:52:56 +00:00
GPU_set_dither_upscale_shift ( 0 ) ;
2017-04-22 15:05:39 +00:00
break ;
case DITHER_OFF :
break ;
}
2016-02-10 19:27:02 +00:00
2020-02-25 04:32:11 +00:00
GPU_set_visible_scanlines ( MDFN_GetSettingI ( content_is_pal ? " psx.slstartp " : " psx.slstart " ) ,
MDFN_GetSettingI ( content_is_pal ? " psx.slendp " : " psx.slend " ) ) ;
2020-09-22 23:19:18 +00:00
PGXP_SetModes ( psx_pgxp_mode | psx_pgxp_vertex_caching | psx_pgxp_texture_correction | psx_pgxp_nclip ) ;
2020-05-26 03:02:51 +00:00
// Reload memory cards if they were changed
if ( use_mednafen_memcard0_method & &
memcard_left_index_old ! = memcard_left_index )
{
2020-06-29 02:41:34 +00:00
MDFN_DispMessage ( 0 , RETRO_LOG_INFO ,
RETRO_MESSAGE_TARGET_OSD , RETRO_MESSAGE_TYPE_NOTIFICATION_ALT ,
" changing from memory card %d to memory card %d in left slot " ,
memcard_left_index_old , memcard_left_index ) ;
2020-05-26 03:02:51 +00:00
try
{
char ext [ 64 ] ;
const char * memcard = NULL ;
// Save contents of left memory card to previously selected index
snprintf ( ext , sizeof ( ext ) , " %d.mcr " , memcard_left_index_old ) ;
memcard = MDFN_MakeFName ( MDFNMKF_SAV , 0 , ext ) ;
PSX_FIO - > SaveMemcard ( 0 , memcard , true ) ;
// Load contents of currently selected index to left memory card
snprintf ( ext , sizeof ( ext ) , " %d.mcr " , memcard_left_index ) ;
memcard = MDFN_MakeFName ( MDFNMKF_SAV , 0 , ext ) ;
PSX_FIO - > LoadMemcard ( 0 , memcard , true ) ;
}
catch ( std : : exception & e )
{
}
}
if ( memcard_right_index_old ! = memcard_right_index )
{
2020-06-29 02:41:34 +00:00
MDFN_DispMessage ( 0 , RETRO_LOG_INFO ,
RETRO_MESSAGE_TARGET_OSD , RETRO_MESSAGE_TYPE_NOTIFICATION_ALT ,
" changing from memory card %d to memory card %d in right slot " ,
memcard_right_index_old , memcard_right_index ) ;
2020-05-26 03:02:51 +00:00
try
{
char ext [ 64 ] ;
const char * memcard = NULL ;
2020-06-29 02:41:34 +00:00
// Save contents of right memory card to previously selected index
2020-05-26 03:02:51 +00:00
snprintf ( ext , sizeof ( ext ) , " %d.mcr " , memcard_right_index_old ) ;
memcard = MDFN_MakeFName ( MDFNMKF_SAV , 0 , ext ) ;
PSX_FIO - > SaveMemcard ( 1 , memcard , true ) ;
2020-06-29 02:41:34 +00:00
// Load contents of currently selected index to right memory card
2020-05-26 03:02:51 +00:00
snprintf ( ext , sizeof ( ext ) , " %d.mcr " , memcard_right_index ) ;
memcard = MDFN_MakeFName ( MDFNMKF_SAV , 0 , ext ) ;
PSX_FIO - > LoadMemcard ( 1 , memcard , true ) ;
}
catch ( std : : exception & e )
{
}
}
2021-12-18 11:46:01 +00:00
// Update gun crosshair color
PSX_FIO - > SetCrosshairsColor ( 0 , setting_crosshair_color_p1 ) ;
PSX_FIO - > SetCrosshairsColor ( 1 , setting_crosshair_color_p2 ) ;
2015-07-28 18:46:24 +00:00
}
2018-02-09 14:06:18 +00:00
/* We only start counting after the first frame we encounter. This
way the value we display remains consistent if the real
framerate is not a multiple of INTERNAL_FPS_SAMPLE_PERIOD
*/
if ( display_internal_framerate & & internal_frame_count )
2016-04-08 22:43:43 +00:00
{
2017-07-31 02:42:23 +00:00
frame_count + + ;
2016-02-07 13:57:39 +00:00
2017-07-31 02:42:23 +00:00
if ( frame_count % INTERNAL_FPS_SAMPLE_PERIOD = = 0 )
{
char msg_buffer [ 64 ] ;
2020-05-29 13:43:50 +00:00
msg_buffer [ 0 ] = ' \0 ' ;
2020-03-01 07:53:26 +00:00
// Just report the "real-world" refresh rate here regardless of system av info reported to the frontend
2020-03-24 00:16:02 +00:00
float fps = ( content_is_pal & & ! fast_pal ) ?
2020-03-01 07:53:26 +00:00
( currently_interlaced ? FPS_PAL_INTERLACED : FPS_PAL_NONINTERLACED ) :
( currently_interlaced ? FPS_NTSC_INTERLACED : FPS_NTSC_NONINTERLACED ) ;
2017-10-17 05:19:21 +00:00
float internal_fps = ( internal_frame_count * fps ) / INTERNAL_FPS_SAMPLE_PERIOD ;
2016-02-07 13:57:39 +00:00
2020-05-26 17:10:56 +00:00
snprintf ( msg_buffer , sizeof ( msg_buffer ) ,
" Internal FPS: %.2f " , internal_fps ) ;
2016-02-07 17:49:28 +00:00
2020-05-29 13:43:50 +00:00
MDFND_DispMessage ( 1 , RETRO_LOG_INFO ,
RETRO_MESSAGE_TARGET_OSD , RETRO_MESSAGE_TYPE_STATUS ,
msg_buffer ) ;
2016-02-07 13:57:39 +00:00
2017-07-31 02:42:23 +00:00
internal_frame_count = 0 ;
}
2016-04-08 22:43:43 +00:00
}
else
{
2017-07-31 02:42:23 +00:00
// Keep the counters at 0 so that they don't display a bogus
// value if this option is enabled later on
frame_count = 0 ;
internal_frame_count = 0 ;
2016-02-07 13:57:39 +00:00
}
2014-06-16 20:25:12 +00:00
if ( setting_apply_analog_toggle )
{
2019-07-14 20:05:54 +00:00
PSX_FIO - > SetAMCT ( setting_psx_analog_toggle ) ;
2014-06-16 20:25:12 +00:00
setting_apply_analog_toggle = false ;
}
2012-06-03 15:48:14 +00:00
input_poll_cb ( ) ;
2019-07-07 07:23:53 +00:00
input_update ( libretro_supports_bitmasks , input_state_cb ) ;
2012-06-03 16:58:46 +00:00
2014-06-16 19:55:28 +00:00
static int32 rects [ MEDNAFEN_CORE_GEOMETRY_MAX_H ] ;
2014-06-15 19:29:05 +00:00
rects [ 0 ] = ~ 0 ;
2012-06-03 15:48:14 +00:00
2012-07-25 01:17:14 +00:00
EmulateSpecStruct spec = { 0 } ;
2012-06-03 15:48:14 +00:00
spec . surface = surf ;
2020-09-17 23:39:40 +00:00
spec . SoundRate = 44100 ;
2012-06-03 15:48:14 +00:00
spec . LineWidths = rects ;
2012-11-16 14:12:25 +00:00
spec . SoundBufSize = 0 ;
2018-04-24 01:16:53 +00:00
2014-06-15 17:20:33 +00:00
EmulateSpecStruct * espec = ( EmulateSpecStruct * ) & spec ;
/* start of Emulate */
2015-07-26 13:34:30 +00:00
int32_t timestamp = 0 ;
2014-06-15 17:20:33 +00:00
2015-10-15 03:12:39 +00:00
espec - > skip = false ;
2014-06-15 17:20:33 +00:00
MDFNMP_ApplyPeriodicCheats ( ) ;
espec - > SoundBufSize = 0 ;
2019-07-14 20:05:54 +00:00
PSX_FIO - > UpdateInput ( ) ;
2017-04-22 15:05:39 +00:00
GPU_StartFrame ( espec ) ;
2014-06-15 17:20:33 +00:00
Running = - 1 ;
2019-07-14 20:05:54 +00:00
timestamp = PSX_CPU - > Run ( timestamp , false , false ) ;
2014-06-15 17:20:33 +00:00
assert ( timestamp ) ;
ForceEventUpdates ( timestamp ) ;
2017-04-22 15:05:39 +00:00
#if 0
2017-04-22 19:19:16 +00:00
if ( GPU_GetScanlineNum ( ) < 100 )
PSX_DBG ( PSX_DBG_ERROR , " [BUUUUUUUG] Frame timing end glitch; scanline=%u, st=%u \n " , GPU_GetScanlineNum ( ) , timestamp ) ;
2017-04-22 15:05:39 +00:00
# endif
2014-06-15 17:20:33 +00:00
espec - > SoundBufSize = IntermediateBufferPos ;
IntermediateBufferPos = 0 ;
2019-07-14 20:05:54 +00:00
PSX_CDC - > ResetTS ( ) ;
2014-06-15 17:20:33 +00:00
TIMER_ResetTS ( ) ;
DMA_ResetTS ( ) ;
2017-04-22 15:05:39 +00:00
GPU_ResetTS ( ) ;
2019-07-14 20:05:54 +00:00
PSX_FIO - > ResetTS ( ) ;
2014-06-15 17:20:33 +00:00
RebaseTS ( timestamp ) ;
// Save memcards if dirty.
2017-11-19 10:45:16 +00:00
unsigned players = input_get_player_count ( ) ;
2014-08-17 04:54:14 +00:00
for ( int i = 0 ; i < players ; i + + )
2014-06-15 17:20:33 +00:00
{
2019-07-14 20:05:54 +00:00
uint64_t new_dc = PSX_FIO - > GetMemcardDirtyCount ( i ) ;
2014-06-15 17:20:33 +00:00
if ( new_dc > Memcard_PrevDC [ i ] )
{
Memcard_PrevDC [ i ] = new_dc ;
Memcard_SaveDelay [ i ] = 0 ;
}
if ( Memcard_SaveDelay [ i ] > = 0 )
{
Memcard_SaveDelay [ i ] + = timestamp ;
2016-01-31 03:07:57 +00:00
if ( Memcard_SaveDelay [ i ] > = ( 33868800 * 2 ) ) // Wait until about 2 seconds of no new writes.
2014-06-15 17:20:33 +00:00
{
2015-09-30 01:56:50 +00:00
char ext [ 64 ] ;
const char * memcard = NULL ;
2020-06-17 09:05:20 +00:00
# ifndef NDEBUG
2015-07-30 04:15:09 +00:00
log_cb ( RETRO_LOG_INFO , " Saving memcard %d... \n " , i ) ;
2020-06-17 09:05:20 +00:00
# endif
2014-06-15 17:49:11 +00:00
2014-07-27 19:03:37 +00:00
if ( i = = 0 & & ! use_mednafen_memcard0_method )
2014-06-16 16:43:58 +00:00
{
2019-07-14 20:05:54 +00:00
PSX_FIO - > SaveMemcard ( i ) ;
2014-06-16 16:43:58 +00:00
Memcard_SaveDelay [ i ] = - 1 ;
Memcard_PrevDC [ i ] = 0 ;
continue ;
}
2020-06-29 02:41:34 +00:00
int index = i ;
if ( i = = 0 ) index = memcard_left_index ;
else if ( i = = 1 ) index = memcard_right_index ;
snprintf ( ext , sizeof ( ext ) , " %d.mcr " , index ) ;
2015-09-30 01:56:50 +00:00
memcard = MDFN_MakeFName ( MDFNMKF_SAV , 0 , ext ) ;
2019-07-14 20:05:54 +00:00
PSX_FIO - > SaveMemcard ( i , memcard ) ;
2014-06-15 17:49:11 +00:00
Memcard_SaveDelay [ i ] = - 1 ;
Memcard_PrevDC [ i ] = 0 ;
2014-06-15 17:20:33 +00:00
}
}
}
/* end of Emulate */
2012-11-16 14:12:25 +00:00
2020-02-27 03:05:15 +00:00
// Check if aspect ratio needs to be changed due to display mode change on this frame
if ( MDFN_UNLIKELY ( ( aspect_ratio_setting = = 1 ) & & aspect_ratio_dirty ) )
{
struct retro_system_av_info new_av_info ;
retro_get_system_av_info ( & new_av_info ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_SET_GEOMETRY , & new_av_info . geometry ) )
aspect_ratio_dirty = false ;
// If unable to change geometry here, defer to next frame and leave aspect_ratio_dirty flagged
}
2020-03-04 09:24:26 +00:00
// Check if timing needs to be changed due to interlacing change on this frame
// May be possible to track interlacing via espec instead of via RSX?
if ( MDFN_UNLIKELY ( ( core_timing_fps_mode = = AUTO_TOGGLE_TIMING ) & & interlace_setting_dirty ) )
2020-03-01 07:53:26 +00:00
{
// This may cause video and audio reinit on the frontend, so it may be preferable to
// set the core option to force progressive or interlaced timings
struct retro_system_av_info new_av_info ;
retro_get_system_av_info ( & new_av_info ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO , & new_av_info ) )
interlace_setting_dirty = false ;
// If unable to change AV info here, defer to next frame and leave interlace_setting_dirty flagged
}
2016-04-10 01:46:05 +00:00
const void * fb = NULL ;
unsigned width = rects [ 0 ] ;
unsigned height = spec . DisplayRect . h ;
2017-07-30 17:27:25 +00:00
uint8_t upscale_shift = GPU_get_upscale_shift ( ) ;
2016-04-10 01:46:05 +00:00
if ( rsx_intf_is_type ( ) = = RSX_SOFTWARE )
2012-11-16 14:12:25 +00:00
{
2016-04-10 01:46:05 +00:00
# ifdef NEED_DEINTERLACER
if ( spec . InterlaceOn )
{
if ( ! PrevInterlaced )
deint . ClearState ( ) ;
2012-11-16 14:12:25 +00:00
2020-09-17 23:53:54 +00:00
deint . Process ( surf , spec . DisplayRect , rects , spec . InterlaceField ) ;
2012-11-16 14:12:25 +00:00
2016-04-10 01:46:05 +00:00
PrevInterlaced = true ;
2012-11-16 14:12:25 +00:00
2016-04-10 01:46:05 +00:00
spec . InterlaceOn = false ;
spec . InterlaceField = 0 ;
}
else
PrevInterlaced = false ;
2012-11-16 14:12:25 +00:00
# endif
2016-04-10 01:46:05 +00:00
// PSX is rather special, and needs specific handling ...
2012-11-16 14:12:25 +00:00
2016-04-10 01:46:05 +00:00
width = rects [ 0 ] ; // spec.DisplayRect.w is 0. Only rects[0].w seems to return something sane.
height = spec . DisplayRect . h ;
//fprintf(stderr, "(%u x %u)\n", width, height);
2013-02-25 19:39:39 +00:00
2019-10-17 06:07:23 +00:00
// PSX core inserts padding on left and right (overscan). Optionally crop this.
2016-04-10 01:46:05 +00:00
const uint32_t * pix = surf - > pixels ;
2016-05-28 12:47:22 +00:00
unsigned pix_offset = 0 ;
2016-01-28 20:14:41 +00:00
2016-05-30 00:59:25 +00:00
if ( crop_overscan )
2013-02-25 19:39:39 +00:00
{
2019-09-29 16:42:57 +00:00
// Crop total # of pixels output by PSX in active scanline region down to # of pixels in corresponding horizontal display mode
// 280 width -> 256 width.
// 350 width -> 320 width.
2019-10-17 06:07:23 +00:00
// 400 width -> 366 width.
2016-04-10 01:46:05 +00:00
// 560 width -> 512 width.
2019-09-29 16:42:57 +00:00
// 700 width -> 640 width.
2016-04-10 01:46:05 +00:00
switch ( width )
{
case 280 :
2020-02-22 19:41:06 +00:00
pix_offset + = 12 - image_offset + floor ( 0.5 * image_crop ) ;
2016-05-30 00:59:25 +00:00
width = 256 - image_crop ;
2016-04-10 01:46:05 +00:00
break ;
case 350 :
2020-02-22 19:41:06 +00:00
pix_offset + = 15 - image_offset + floor ( 0.5 * image_crop ) ;
2016-05-30 00:59:25 +00:00
width = 320 - image_crop ;
2016-04-10 01:46:05 +00:00
break ;
2019-10-17 06:07:23 +00:00
/* 368px mode. Some games are overcropped at 364 width or undercropped at 368 width, so crop to 366.
Adjust in future if there are issues . */
2016-04-10 01:46:05 +00:00
case 400 :
2020-02-22 19:41:06 +00:00
pix_offset + = 17 - image_offset + floor ( 0.5 * image_crop ) ;
2019-10-17 06:07:23 +00:00
width = 366 - image_crop ;
2016-04-10 01:46:05 +00:00
break ;
case 560 :
2020-02-22 19:41:06 +00:00
pix_offset + = 24 - image_offset + floor ( 0.5 * image_crop ) ;
2016-05-30 00:59:25 +00:00
width = 512 - image_crop ;
2016-04-10 01:46:05 +00:00
break ;
case 700 :
2020-02-22 19:41:06 +00:00
pix_offset + = 30 - image_offset + floor ( 0.5 * image_crop ) ;
2016-05-30 00:59:25 +00:00
width = 640 - image_crop ;
2016-04-10 01:46:05 +00:00
break ;
default :
// This shouldn't happen.
break ;
}
2013-02-25 19:39:39 +00:00
}
2015-08-11 20:48:54 +00:00
2016-01-28 20:10:34 +00:00
2016-04-10 01:46:05 +00:00
width < < = upscale_shift ;
height < < = upscale_shift ;
pix + = pix_offset < < upscale_shift ;
2016-01-30 00:37:04 +00:00
2020-04-01 18:54:50 +00:00
if ( GPU_get_display_possibly_dirty ( ) | | ( GPU_get_display_change_count ( ) ! = 0 ) | | ! allow_frame_duping )
2016-04-10 01:46:05 +00:00
fb = pix ;
}
2016-02-07 22:43:26 +00:00
2016-04-10 01:46:05 +00:00
int16_t * interbuf = ( int16_t * ) & IntermediateBuffer ;
2019-06-16 20:00:13 +00:00
2018-06-30 23:32:16 +00:00
if ( gui_show )
{
if ( ! gui_inited )
{
frame_width = width ;
frame_height = height ;
gui_init ( frame_width , frame_height , sizeof ( unsigned ) ) ;
gui_set_window_title ( " Error " ) ;
gui_inited = true ;
}
if ( width ! = frame_width | | height ! = frame_height )
{
frame_width = width ;
frame_height = height ;
gui_window_resize ( 0 , 0 , frame_width , frame_height ) ;
}
}
else
{
rsx_intf_finalize_frame ( fb , width , height ,
MEDNAFEN_CORE_GEOMETRY_MAX_W < < ( 2 + upscale_shift ) ) ;
}
2012-06-03 15:48:14 +00:00
2022-04-16 14:21:51 +00:00
/* LED interface */
2022-04-16 23:14:17 +00:00
if ( led_state_cb )
retro_led_interface ( ) ;
2022-04-16 14:21:51 +00:00
2012-09-20 19:38:19 +00:00
video_frames + + ;
audio_frames + = spec . SoundBufSize ;
2014-06-15 01:39:44 +00:00
audio_batch_cb ( interbuf , spec . SoundBufSize ) ;
2016-02-07 13:57:39 +00:00
2020-04-01 18:54:50 +00:00
if ( GPU_get_display_possibly_dirty ( ) | | ( GPU_get_display_change_count ( ) ! = 0 ) )
2017-04-22 15:05:39 +00:00
{
internal_frame_count + + ;
GPU_set_display_change_count ( 0 ) ;
2020-04-01 18:54:50 +00:00
GPU_set_display_possibly_dirty ( false ) ;
2016-02-07 13:57:39 +00:00
}
2012-06-03 15:48:14 +00:00
}
void retro_get_system_info ( struct retro_system_info * info )
{
memset ( info , 0 , sizeof ( * info ) ) ;
2012-10-20 21:32:28 +00:00
info - > library_name = MEDNAFEN_CORE_NAME ;
2016-12-05 00:34:02 +00:00
# ifdef GIT_VERSION
info - > library_version = MEDNAFEN_CORE_VERSION GIT_VERSION ;
# else
2012-10-22 12:34:14 +00:00
info - > library_version = MEDNAFEN_CORE_VERSION ;
2016-12-05 00:34:02 +00:00
# endif
2012-06-03 15:48:14 +00:00
info - > need_fullpath = true ;
2012-10-20 21:56:43 +00:00
info - > valid_extensions = MEDNAFEN_CORE_EXTENSIONS ;
2012-10-20 23:47:02 +00:00
info - > block_extract = false ;
2012-06-03 15:48:14 +00:00
}
void retro_get_system_av_info ( struct retro_system_av_info * info )
{
2016-04-08 15:03:52 +00:00
rsx_intf_get_system_av_info ( info ) ;
2012-06-03 15:48:14 +00:00
}
2014-06-16 02:10:39 +00:00
void retro_deinit ( void )
2012-09-20 19:38:19 +00:00
{
delete surf ;
surf = NULL ;
2020-06-17 09:05:20 +00:00
log_cb ( RETRO_LOG_DEBUG , " [%s]: Samples / Frame: %.5f \n " ,
2015-07-30 04:15:09 +00:00
MEDNAFEN_CORE_NAME , ( double ) audio_frames / video_frames ) ;
2020-06-17 09:05:20 +00:00
log_cb ( RETRO_LOG_DEBUG , " [%s]: Estimated FPS: %.5f \n " ,
2015-07-30 04:15:09 +00:00
MEDNAFEN_CORE_NAME , ( double ) video_frames * 44100 / audio_frames ) ;
2019-07-07 07:23:53 +00:00
2021-08-16 04:02:21 +00:00
libretro_supports_option_categories = false ;
2019-07-07 07:23:53 +00:00
libretro_supports_bitmasks = false ;
2012-09-20 19:38:19 +00:00
}
2012-06-03 15:48:14 +00:00
unsigned retro_get_region ( void )
{
2020-03-24 00:16:02 +00:00
// simias: should I override this when fast_pal is set?
//
// I'm not entirely sure what's that used for.
2020-03-10 00:39:40 +00:00
return content_is_pal ? RETRO_REGION_PAL : RETRO_REGION_NTSC ;
2012-06-03 15:48:14 +00:00
}
unsigned retro_api_version ( void )
{
return RETRO_API_VERSION ;
}
2019-08-01 05:48:38 +00:00
# include "libretro_core_options.h"
2012-06-03 15:48:14 +00:00
void retro_set_environment ( retro_environment_t cb )
{
2017-12-15 22:20:53 +00:00
struct retro_vfs_interface_info vfs_iface_info ;
2022-04-16 14:21:51 +00:00
struct retro_led_interface led_interface ;
2012-06-03 15:48:14 +00:00
environ_cb = cb ;
2013-04-09 02:05:18 +00:00
2021-08-16 04:02:21 +00:00
libretro_supports_option_categories = false ;
2022-11-14 20:32:21 +00:00
libretro_set_core_options ( environ_cb , & libretro_supports_option_categories ) ;
2017-11-19 10:45:16 +00:00
2023-01-30 17:42:06 +00:00
vfs_iface_info . required_interface_version = 2 ;
2017-12-15 22:20:53 +00:00
vfs_iface_info . iface = NULL ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VFS_INTERFACE , & vfs_iface_info ) )
2022-11-14 20:32:21 +00:00
filestream_vfs_init ( & vfs_iface_info ) ;
2017-12-15 22:20:53 +00:00
2022-11-14 20:32:21 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_LED_INTERFACE , & led_interface ) )
if ( led_interface . set_led_state & & ! led_state_cb )
led_state_cb = led_interface . set_led_state ;
2022-04-16 14:21:51 +00:00
input_set_env ( cb ) ;
2016-03-24 18:02:55 +00:00
2016-04-08 15:03:52 +00:00
rsx_intf_set_environment ( cb ) ;
2012-06-03 15:48:14 +00:00
}
void retro_set_audio_sample ( retro_audio_sample_t cb )
{
audio_cb = cb ;
}
void retro_set_audio_sample_batch ( retro_audio_sample_batch_t cb )
{
audio_batch_cb = cb ;
}
void retro_set_input_poll ( retro_input_poll_t cb )
{
input_poll_cb = cb ;
}
void retro_set_input_state ( retro_input_state_t cb )
{
input_state_cb = cb ;
2020-05-13 22:40:38 +00:00
dbg_input_state_cb = cb ;
2012-06-03 15:48:14 +00:00
}
void retro_set_video_refresh ( retro_video_refresh_t cb )
{
video_cb = cb ;
2016-03-24 18:02:55 +00:00
2016-04-08 15:03:52 +00:00
rsx_intf_set_video_refresh ( cb ) ;
2012-06-03 15:48:14 +00:00
}
size_t retro_serialize_size ( void )
{
2016-10-08 22:33:41 +00:00
if ( enable_variable_serialization_size )
{
StateMem st ;
2017-12-17 17:36:12 +00:00
st . data = NULL ;
st . loc = 0 ;
st . len = 0 ;
st . malloced = 0 ;
st . initial_malloc = 0 ;
2012-10-21 01:46:12 +00:00
2016-10-08 22:33:41 +00:00
if ( ! MDFNSS_SaveSM ( & st , 0 , 0 , NULL , NULL , NULL ) )
return 0 ;
free ( st . data ) ;
2020-09-14 09:45:24 +00:00
return st . len ;
2016-10-08 22:33:41 +00:00
}
2017-12-17 17:36:12 +00:00
2020-09-14 09:45:24 +00:00
return DEFAULT_STATE_SIZE ; // 16MB
2012-06-03 15:48:14 +00:00
}
2020-05-26 17:40:28 +00:00
bool UsingFastSavestates ( void )
2012-06-03 15:48:14 +00:00
{
2018-04-24 01:16:53 +00:00
int flags ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE , & flags ) )
return flags & 4 ;
return false ;
}
2017-12-17 17:36:12 +00:00
2018-04-24 01:16:53 +00:00
bool retro_serialize ( void * data , size_t size )
{
2020-05-26 17:40:28 +00:00
StateMem st ;
bool ret = false ;
st . len = 0 ;
st . loc = 0 ;
st . malloced = size ;
st . initial_malloc = 0 ;
2018-04-24 01:16:53 +00:00
if ( size = = DEFAULT_STATE_SIZE ) //16MB buffer reserved
{
//actual size is around 3.75MB (3.67MB for fast savestates) rather than 16MB, so 16MB will hold a savestate without worrying about realloc
2017-12-17 17:36:12 +00:00
2018-04-24 01:16:53 +00:00
//save state in place
2020-05-26 17:40:28 +00:00
st . data = ( uint8_t * ) data ;
2017-12-17 17:36:12 +00:00
2018-04-24 01:16:53 +00:00
//fast save states are at least 20% faster
FastSaveStates = UsingFastSavestates ( ) ;
2020-05-26 17:40:28 +00:00
ret = MDFNSS_SaveSM ( & st , 0 , 0 , NULL , NULL , NULL ) ;
2017-03-26 21:44:25 +00:00
}
2018-04-24 01:16:53 +00:00
else
{
/* it seems that mednafen can realloc pointers sent to it?
since we don ' t know the disposition of void * data ( is it safe to realloc ? ) we have to manage a new buffer here */
static bool logged ;
uint8_t * _dat = ( uint8_t * ) malloc ( size ) ;
2017-03-26 21:44:25 +00:00
2018-04-24 01:16:53 +00:00
if ( ! _dat )
return false ;
2015-10-15 03:12:39 +00:00
2018-04-24 01:16:53 +00:00
st . data = _dat ;
/* there are still some errors with the save states,
* the size seems to change on some games for now
* just log when this happens */
if ( ! logged & & st . len ! = size )
{
log_cb ( RETRO_LOG_WARN , " warning, save state size has changed \n " ) ;
logged = true ;
}
2018-04-24 01:20:17 +00:00
FastSaveStates = UsingFastSavestates ( ) ;
2018-04-24 01:16:53 +00:00
ret = MDFNSS_SaveSM ( & st , 0 , 0 , NULL , NULL , NULL ) ;
memcpy ( data , st . data , size ) ;
free ( st . data ) ;
}
2020-05-26 17:40:28 +00:00
FastSaveStates = false ;
return ret ;
2015-10-15 03:12:39 +00:00
}
2017-07-31 02:42:23 +00:00
2012-10-21 01:46:12 +00:00
bool retro_unserialize ( const void * data , size_t size )
2012-06-03 15:48:14 +00:00
{
2012-10-21 01:46:12 +00:00
StateMem st ;
2017-12-17 17:42:32 +00:00
st . data = ( uint8_t * ) data ;
st . loc = 0 ;
st . len = size ;
st . malloced = 0 ;
st . initial_malloc = 0 ;
2015-10-15 03:12:39 +00:00
2018-04-24 01:16:53 +00:00
//fast save states are at least 20% faster
FastSaveStates = UsingFastSavestates ( ) ;
bool okay = MDFNSS_LoadSM ( & st , 0 , 0 ) ;
FastSaveStates = false ;
return okay ;
2012-06-03 15:48:14 +00:00
}
2014-06-16 16:43:58 +00:00
void * retro_get_memory_data ( unsigned type )
2012-06-03 15:48:14 +00:00
{
2014-06-16 16:43:58 +00:00
uint8_t * data ;
switch ( type )
{
2017-10-31 05:09:43 +00:00
case RETRO_MEMORY_SYSTEM_RAM :
2020-01-21 23:26:20 +00:00
return MainRAM - > data8 ;
2014-06-16 16:43:58 +00:00
case RETRO_MEMORY_SAVE_RAM :
2020-09-17 22:14:34 +00:00
if ( ! use_mednafen_memcard0_method )
return PSX_FIO - > GetMemcardDevice ( 0 ) - > GetNVData ( ) ;
break ;
2014-06-16 16:43:58 +00:00
default :
break ;
}
2015-10-15 03:12:39 +00:00
return NULL ;
2012-06-03 15:48:14 +00:00
}
2014-06-16 16:43:58 +00:00
size_t retro_get_memory_size ( unsigned type )
2012-06-03 15:48:14 +00:00
{
2014-06-16 16:43:58 +00:00
switch ( type )
{
2017-11-03 06:31:53 +00:00
case RETRO_MEMORY_SYSTEM_RAM :
return 0x200000 ;
2014-06-16 16:43:58 +00:00
case RETRO_MEMORY_SAVE_RAM :
2020-09-17 22:14:34 +00:00
if ( ! use_mednafen_memcard0_method )
return ( 1 < < 17 ) ;
break ;
2014-06-16 16:43:58 +00:00
default :
break ;
}
2015-07-25 16:34:55 +00:00
return 0 ;
2012-06-03 15:48:14 +00:00
}
void retro_cheat_reset ( void )
2016-12-23 17:27:19 +00:00
{
2017-04-06 17:46:37 +00:00
MDFN_FlushGameCheats ( 1 ) ;
2016-12-23 17:27:19 +00:00
}
2012-06-03 15:48:14 +00:00
2017-04-06 17:46:37 +00:00
void retro_cheat_set ( unsigned index , bool enabled , const char * codeLine )
2016-12-23 17:27:19 +00:00
{
2017-04-06 17:46:37 +00:00
const CheatFormatStruct * cf = CheatFormats ;
2017-04-09 03:05:40 +00:00
char name [ 256 ] ;
2017-04-06 17:46:37 +00:00
std : : vector < std : : string > codeParts ;
int matchLength = 0 ;
int cursor ;
std : : string part ;
2020-05-26 17:40:28 +00:00
if ( codeLine = = NULL )
return ;
2017-04-06 17:46:37 +00:00
//Break the code into Parts
for ( cursor = 0 ; ; cursor + + )
{
2017-04-06 21:27:12 +00:00
if ( ISHEXDEC )
2017-04-06 17:46:37 +00:00
matchLength + + ;
2020-05-26 17:40:28 +00:00
else
{
2017-04-06 21:27:12 +00:00
if ( matchLength )
{
2017-04-06 17:46:37 +00:00
part = codeLine + cursor - matchLength ;
part . erase ( matchLength , std : : string : : npos ) ;
codeParts . push_back ( part ) ;
matchLength = 0 ;
}
}
2017-04-06 21:27:12 +00:00
if ( ! codeLine [ cursor ] )
2017-04-06 17:46:37 +00:00
break ;
}
2017-04-02 14:17:15 +00:00
2017-04-06 21:27:12 +00:00
MemoryPatch patch ;
bool trueML = 0 ;
2017-04-06 17:46:37 +00:00
for ( cursor = 0 ; cursor < codeParts . size ( ) ; cursor + + )
{
part = codeParts [ cursor ] ;
2017-04-06 21:27:12 +00:00
if ( part . length ( ) = = 8 )
2017-04-06 17:46:37 +00:00
part + = codeParts [ + + cursor ] ;
2017-04-06 21:27:12 +00:00
if ( part . length ( ) = = 12 )
{
2017-04-06 17:46:37 +00:00
//Decode the cheat
try
{
2017-04-06 21:27:12 +00:00
if ( ! cf - > DecodeCheat ( std : : string ( part ) , & patch ) )
{
//Generate a name
2023-02-24 00:25:05 +00:00
snprintf ( name , sizeof ( name ) , " cheat_%i_%i " , index , cursor ) ;
2017-04-06 21:27:12 +00:00
//Set parameters
2017-04-09 03:05:40 +00:00
patch . name = ( std : : string ) name ;
2017-04-06 21:27:12 +00:00
patch . status = enabled ;
MDFNI_AddCheat ( patch ) ;
patch = MemoryPatch ( ) ;
}
2017-04-06 17:46:37 +00:00
}
catch ( std : : exception & e )
{
continue ;
}
}
}
2016-12-23 17:27:19 +00:00
}
2014-06-16 20:55:26 +00:00
// Use a simpler approach to make sure that things go right for libretro.
2015-09-30 01:56:50 +00:00
const char * MDFN_MakeFName ( MakeFName_Type type , int id1 , const char * cd1 )
2014-06-16 20:55:26 +00:00
{
2015-09-30 01:56:50 +00:00
static char fullpath [ 4096 ] ;
2020-05-17 22:17:32 +00:00
int r = 0 ;
2015-09-30 01:56:50 +00:00
fullpath [ 0 ] = ' \0 ' ;
2015-09-30 01:39:52 +00:00
2014-06-16 20:55:26 +00:00
switch ( type )
{
case MDFNMKF_SAV :
2020-05-17 22:17:32 +00:00
r = snprintf ( fullpath , sizeof ( fullpath ) , " %s%c%s.%s " ,
2015-09-30 01:39:52 +00:00
retro_save_directory ,
retro_slash ,
2020-03-10 01:37:34 +00:00
shared_memorycards ? " mednafen_psx_libretro_shared " : retro_cd_base_name ,
2015-09-30 01:39:52 +00:00
cd1 ) ;
2014-06-16 20:55:26 +00:00
break ;
case MDFNMKF_FIRMWARE :
2020-05-17 22:17:32 +00:00
r = snprintf ( fullpath , sizeof ( fullpath ) , " %s%c%s " , retro_base_directory , retro_slash , cd1 ) ;
2014-06-16 20:55:26 +00:00
break ;
2015-10-15 03:12:39 +00:00
default :
2014-06-16 20:55:26 +00:00
break ;
}
2020-05-17 22:17:32 +00:00
if ( r > 4095 )
{
fullpath [ 4095 ] = ' \0 ' ;
2021-04-22 02:55:06 +00:00
log_cb ( RETRO_LOG_ERROR , " MakeFName path longer than 4095: %s \n " , fullpath ) ;
2020-05-17 22:17:32 +00:00
}
2015-09-30 01:56:50 +00:00
return fullpath ;
2014-06-16 20:55:26 +00:00
}
2020-05-29 13:43:50 +00:00
void MDFND_DispMessage (
unsigned priority , enum retro_log_level level ,
enum retro_message_target target , enum retro_message_type type ,
const char * str )
2014-06-16 20:55:26 +00:00
{
2020-05-29 13:43:50 +00:00
if ( libretro_msg_interface_version > = 1 )
{
struct retro_message_ext msg = {
str ,
3000 ,
priority ,
level ,
target ,
type ,
- 1
} ;
environ_cb ( RETRO_ENVIRONMENT_SET_MESSAGE_EXT , & msg ) ;
}
else
2014-06-17 03:10:33 +00:00
{
2020-05-29 13:43:50 +00:00
struct retro_message msg =
{
str ,
180
} ;
environ_cb ( RETRO_ENVIRONMENT_SET_MESSAGE , & msg ) ;
}
2014-06-16 20:55:26 +00:00
}
2020-05-29 13:43:50 +00:00
void MDFN_DispMessage (
unsigned priority , enum retro_log_level level ,
enum retro_message_target target , enum retro_message_type type ,
const char * format , . . . )
2014-06-16 22:54:33 +00:00
{
va_list ap ;
2020-05-29 13:43:50 +00:00
char * str = ( char * ) malloc ( 4096 * sizeof ( char ) ) ;
2014-06-16 22:54:33 +00:00
2020-05-29 13:43:50 +00:00
va_start ( ap , format ) ;
2016-06-06 01:07:55 +00:00
vsnprintf ( str , 4096 , format , ap ) ;
2014-06-16 22:54:33 +00:00
va_end ( ap ) ;
2020-05-29 13:43:50 +00:00
MDFND_DispMessage ( priority , level , target , type , str ) ;
2019-07-26 02:42:40 +00:00
free ( str ) ;
2014-06-16 20:55:26 +00:00
}