diff options
Diffstat (limited to 'frontend/libretro.c')
| -rw-r--r-- | frontend/libretro.c | 1036 | 
1 files changed, 908 insertions, 128 deletions
| diff --git a/frontend/libretro.c b/frontend/libretro.c index 940ff05..a5ec2c2 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -22,6 +22,7 @@  #include "../libpcsxcore/cdrom.h"  #include "../libpcsxcore/cdriso.h"  #include "../libpcsxcore/cheat.h" +#include "../libpcsxcore/r3000a.h"  #include "../plugins/dfsound/out.h"  #include "../plugins/dfsound/spu_config.h"  #include "../plugins/dfinput/externals.h" @@ -33,36 +34,94 @@  #include "revision.h"  #include "libretro.h" +#ifdef _3DS +#include "3ds/3ds_utils.h" +#endif + +#define PORTS_NUMBER 8 + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#define ISHEXDEC ((buf[cursor]>='0') && (buf[cursor]<='9')) || ((buf[cursor]>='a') && (buf[cursor]<='f')) || ((buf[cursor]>='A') && (buf[cursor]<='F')) + +//hack to prevent retroarch freezing when reseting in the menu but not while running with the hot key +static int rebootemu = 0; +  static retro_video_refresh_t video_cb;  static retro_input_poll_t input_poll_cb;  static retro_input_state_t input_state_cb;  static retro_environment_t environ_cb;  static retro_audio_sample_batch_t audio_batch_cb; -static struct retro_rumble_interface rumble; +static retro_set_rumble_state_t rumble_cb; +static struct retro_log_callback logging; +static retro_log_printf_t log_cb;  static void *vout_buf; +static void * vout_buf_ptr;  static int vout_width, vout_height;  static int vout_doffs_old, vout_fb_dirty;  static bool vout_can_dupe;  static bool duping_enable; +static bool found_bios;  static int plugins_opened;  static int is_pal_mode;  /* memory card data */  extern char Mcd1Data[MCD_SIZE]; +extern char Mcd2Data[MCD_SIZE];  extern char McdDisable[2];  /* PCSX ReARMed core calls and stuff */ -int in_type1, in_type2; -int in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 }; -int in_keystate; +int in_type[8] =  { PSE_PAD_TYPE_NONE, PSE_PAD_TYPE_NONE, +                  PSE_PAD_TYPE_NONE, PSE_PAD_TYPE_NONE, +                  PSE_PAD_TYPE_NONE, PSE_PAD_TYPE_NONE, +                  PSE_PAD_TYPE_NONE, PSE_PAD_TYPE_NONE }; +int in_analog_left[8][2] = {{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 }}; +int in_analog_right[8][2] = {{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 }}; +unsigned short in_keystate[PORTS_NUMBER]; +int multitap1 = 0; +int multitap2 = 0;  int in_enable_vibration = 1; +// NegCon adjustment parameters +// > The NegCon 'twist' action is somewhat awkward when mapped +//   to a standard analog stick -> user should be able to tweak +//   response/deadzone for comfort +// > When response is linear, 'additional' deadzone (set here) +//   may be left at zero, since this is normally handled via in-game +//   options menus +// > When response is non-linear, deadzone should be set to match the +//   controller being used (otherwise precision may be lost) +// > negcon_linearity: +//   - 1: Response is linear - recommended when using racing wheel +//        peripherals, not recommended for standard gamepads +//   - 2: Response is quadratic - optimal setting for gamepads +//   - 3: Response is cubic - enables precise fine control, but +//        difficult to use... +#define NEGCON_RANGE 0x7FFF +static int negcon_deadzone = 0; +static int negcon_linearity = 1; +  /* PSX max resolution is 640x512, but with enhancement it's 1024x512 */  #define VOUT_MAX_WIDTH 1024  #define VOUT_MAX_HEIGHT 512 +//Dummy functions +bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info){return false;} +void retro_unload_game(void){} +static int vout_open(void){return 0;} +static void vout_close(void){} +static int snd_init(void){return 0;} +static void snd_finish(void){} +static int snd_busy(void){return 0;} +  static void init_memcard(char *mcd_data)  {  	unsigned off = 0; @@ -96,15 +155,26 @@ static void init_memcard(char *mcd_data)  	}  } -static int vout_open(void) +static void set_vout_fb()  { -	return 0; +  struct retro_framebuffer fb = {0}; + +  fb.width           = vout_width; +  fb.height          = vout_height; +  fb.access_flags    = RETRO_MEMORY_ACCESS_WRITE; + +  if (environ_cb(RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER, &fb) && fb.format == RETRO_PIXEL_FORMAT_RGB565) +     vout_buf_ptr = (uint16_t*)fb.data; +  else +     vout_buf_ptr = vout_buf;  }  static void vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp)  { -	vout_width = w; -	vout_height = h; +  vout_width = w; +  vout_height = h; + +  set_vout_fb();  }  #ifndef FRONTEND_SUPPORTS_RGB565 @@ -121,14 +191,14 @@ static void convert(void *buf, size_t bytes)  static void vout_flip(const void *vram, int stride, int bgr24, int w, int h)  { -	unsigned short *dest = vout_buf; +	unsigned short *dest = vout_buf_ptr;  	const unsigned short *src = vram;  	int dstride = vout_width, h1 = h;  	int doffs;  	if (vram == NULL) {  		// blanking -		memset(vout_buf, 0, dstride * h * 2); +		memset(vout_buf_ptr, 0, dstride * h * 2);  		goto out;  	} @@ -136,7 +206,7 @@ static void vout_flip(const void *vram, int stride, int bgr24, int w, int h)  	doffs += (dstride - w) / 2 & ~1;  	if (doffs != vout_doffs_old) {  		// clear borders -		memset(vout_buf, 0, dstride * h * 2); +		memset(vout_buf_ptr, 0, dstride * h * 2);  		vout_doffs_old = doffs;  	}  	dest += doffs; @@ -159,16 +229,173 @@ static void vout_flip(const void *vram, int stride, int bgr24, int w, int h)  out:  #ifndef FRONTEND_SUPPORTS_RGB565 -	convert(vout_buf, vout_width * vout_height * 2); +	convert(vout_buf_ptr, vout_width * vout_height * 2);  #endif  	vout_fb_dirty = 1;  	pl_rearmed_cbs.flip_cnt++;  } -static void vout_close(void) +#ifdef _3DS +typedef struct  { +   void* buffer; +   uint32_t target_map; +   size_t size; +   enum psxMapTag tag; +}psx_map_t; + +psx_map_t custom_psx_maps[] = { +   {NULL, 0x13000000, 0x210000, MAP_TAG_RAM},   // 0x80000000 +   {NULL, 0x12800000, 0x010000, MAP_TAG_OTHER}, // 0x1f800000 +   {NULL, 0x12c00000, 0x080000, MAP_TAG_OTHER}, // 0x1fc00000 +   {NULL, 0x11000000, 0x800000, MAP_TAG_LUTS},  // 0x08000000 +   {NULL, 0x12000000, 0x200000, MAP_TAG_VRAM},  // 0x00000000 +}; + +void* pl_3ds_mmap(unsigned long addr, size_t size, int is_fixed, +	enum psxMapTag tag) +{ +   (void)is_fixed; +   (void)addr; + +   if (__ctr_svchax) +   { +      psx_map_t* custom_map = custom_psx_maps; + +      for (; custom_map->size; custom_map++) +      { +         if ((custom_map->size == size) && (custom_map->tag == tag)) +         { +            uint32_t ptr_aligned, tmp; + +            custom_map->buffer = malloc(size + 0x1000); +            ptr_aligned = (((u32)custom_map->buffer) + 0xFFF) & ~0xFFF; + +            if(svcControlMemory(&tmp, (void*)custom_map->target_map, (void*)ptr_aligned, size, MEMOP_MAP, 0x3) < 0) +            { +               SysPrintf("could not map memory @0x%08X\n", custom_map->target_map); +               exit(1); +            } + +            return (void*)custom_map->target_map; +         } +      } +   } + +   return malloc(size);  } +void pl_3ds_munmap(void *ptr, size_t size, enum psxMapTag tag) +{ +   (void)tag; + +   if (__ctr_svchax) +   { +      psx_map_t* custom_map = custom_psx_maps; + +      for (; custom_map->size; custom_map++) +      { +         if ((custom_map->target_map == (uint32_t)ptr)) +         { +            uint32_t ptr_aligned, tmp; + +            ptr_aligned = (((u32)custom_map->buffer) + 0xFFF) & ~0xFFF; + +            svcControlMemory(&tmp, (void*)custom_map->target_map, (void*)ptr_aligned, size, MEMOP_UNMAP, 0x3); + +            free(custom_map->buffer); +            custom_map->buffer = NULL; +            return; +         } +      } +   } + +   free(ptr); +} +#endif + +#ifdef VITA +typedef struct +{ +   void* buffer; +   uint32_t target_map; +   size_t size; +   enum psxMapTag tag; +}psx_map_t; + +void* addr = NULL; + +psx_map_t custom_psx_maps[] = { +   {NULL, NULL, 0x210000, MAP_TAG_RAM},   // 0x80000000 +   {NULL, NULL, 0x010000, MAP_TAG_OTHER}, // 0x1f800000 +   {NULL, NULL, 0x080000, MAP_TAG_OTHER}, // 0x1fc00000 +   {NULL, NULL, 0x800000, MAP_TAG_LUTS},  // 0x08000000 +   {NULL, NULL, 0x200000, MAP_TAG_VRAM},  // 0x00000000 +}; + +int init_vita_mmap(){ +  int n; +  void * tmpaddr; +  addr = malloc(64*1024*1024); +  if(addr==NULL) +    return -1; +  tmpaddr = ((u32)(addr+0xFFFFFF))&~0xFFFFFF; +  custom_psx_maps[0].buffer=tmpaddr+0x2000000; +  custom_psx_maps[1].buffer=tmpaddr+0x1800000; +  custom_psx_maps[2].buffer=tmpaddr+0x1c00000; +  custom_psx_maps[3].buffer=tmpaddr+0x0000000; +  custom_psx_maps[4].buffer=tmpaddr+0x1000000; +#if 0 +  for(n = 0; n < 5; n++){ +    sceClibPrintf("addr reserved %x\n",custom_psx_maps[n].buffer); +  } +#endif +  return 0; +} + +void deinit_vita_mmap(){ +  free(addr); +} + +void* pl_vita_mmap(unsigned long addr, size_t size, int is_fixed, +	enum psxMapTag tag) +{ +   (void)is_fixed; +   (void)addr; + + +    psx_map_t* custom_map = custom_psx_maps; + +    for (; custom_map->size; custom_map++) +    { +       if ((custom_map->size == size) && (custom_map->tag == tag)) +       { +          return custom_map->buffer; +       } +    } + + +   return malloc(size); +} + +void pl_vita_munmap(void *ptr, size_t size, enum psxMapTag tag) +{ +   (void)tag; + +   psx_map_t* custom_map = custom_psx_maps; + +  for (; custom_map->size; custom_map++) +  { +     if ((custom_map->buffer == ptr)) +     { +        return; +     } +  } + +   free(ptr); +} +#endif +  static void *pl_mmap(unsigned int size)  {  	return psxMap(0, size, 0, MAP_TAG_VRAM); @@ -204,8 +431,14 @@ void pl_timing_prepare(int is_pal)  void plat_trigger_vibrate(int pad, int low, int high)  { -    rumble.set_rumble_state(pad, RETRO_RUMBLE_STRONG, high << 8); -    rumble.set_rumble_state(pad, RETRO_RUMBLE_WEAK, low ? 0xffff : 0x0); +	if (!rumble_cb) +		return; + +	if (in_enable_vibration) +	{ +		rumble_cb(pad, RETRO_RUMBLE_STRONG, high << 8); +		rumble_cb(pad, RETRO_RUMBLE_WEAK, low ? 0xffff : 0x0); +    }  }  void pl_update_gun(int *xn, int *yn, int *xres, int *yres, int *in) @@ -213,20 +446,6 @@ void pl_update_gun(int *xn, int *yn, int *xres, int *yres, int *in)  }  /* sound calls */ -static int snd_init(void) -{ -	return 0; -} - -static void snd_finish(void) -{ -} - -static int snd_busy(void) -{ -	return 0; -} -  static void snd_feed(void *buf, int bytes)  {  	if (audio_batch_cb != NULL) @@ -247,23 +466,48 @@ void retro_set_environment(retro_environment_t cb)  {     static const struct retro_variable vars[] = {        { "pcsx_rearmed_frameskip", "Frameskip; 0|1|2|3" }, -      { "pcsx_rearmed_region", "Region; Auto|NTSC|PAL" }, -      { "pcsx_rearmed_pad1type", "Pad 1 Type; standard|analog" }, -      { "pcsx_rearmed_pad2type", "Pad 2 Type; standard|analog" }, +      { "pcsx_rearmed_bios", "Use BIOS; auto|HLE" }, +      { "pcsx_rearmed_region", "Region; auto|NTSC|PAL" }, +      { "pcsx_rearmed_memcard2", "Enable second memory card; disabled|enabled" }, +      { "pcsx_rearmed_pad1type", "Pad 1 Type; standard|analog|dualshock|negcon|none" }, +      { "pcsx_rearmed_pad2type", "Pad 2 Type; standard|analog|dualshock|negcon|none" }, +      { "pcsx_rearmed_pad3type", "Pad 3 Type; none|standard|analog|dualshock|negcon" }, +      { "pcsx_rearmed_pad4type", "Pad 4 Type; none|standard|analog|dualshock|negcon" }, +      { "pcsx_rearmed_pad5type", "Pad 5 Type; none|standard|analog|dualshock|negcon" }, +      { "pcsx_rearmed_pad6type", "Pad 6 Type; none|standard|analog|dualshock|negcon" }, +      { "pcsx_rearmed_pad7type", "Pad 7 Type; none|standard|analog|dualshock|negcon" }, +      { "pcsx_rearmed_pad8type", "Pad 8 Type; none|standard|analog|dualshock|negcon" }, +      { "pcsx_rearmed_multitap1", "Multitap 1; auto|disabled|enabled" }, +      { "pcsx_rearmed_multitap2", "Multitap 2; auto|disabled|enabled" }, +      { "pcsx_rearmed_negcon_deadzone", "NegCon Twist Deadzone (percent); 0|5|10|15|20|25|30" }, +      { "pcsx_rearmed_negcon_response", "NegCon Twist Response; linear|quadratic|cubic" }, +      { "pcsx_rearmed_vibration", "Enable Vibration; enabled|disabled" }, +      { "pcsx_rearmed_dithering", "Enable Dithering; enabled|disabled" },  #ifndef DRC_DISABLE        { "pcsx_rearmed_drc", "Dynamic recompiler; enabled|disabled" }, +#ifdef HAVE_PRE_ARMV7 +      { "pcsx_rearmed_psxclock", "PSX cpu clock (default 50); 50|51|52|53|54|55|5657|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49" }, +#else +      { "pcsx_rearmed_psxclock", "PSX cpu clock (default 57); 57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56" }, +#endif  #endif  #ifdef __ARM_NEON__        { "pcsx_rearmed_neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" },        { "pcsx_rearmed_neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" },        { "pcsx_rearmed_neon_enhancement_no_main", "Enhanced resolution speed hack; disabled|enabled" },  #endif -      { "pcsx_rearmed_duping_enable", "Frame duping; on|off" }, -      { "pcsx_rearmed_spu_reverb", "Sound: Reverb; on|off" }, +      { "pcsx_rearmed_duping_enable", "Frame duping; enabled|disabled" }, +      { "pcsx_rearmed_show_bios_bootlogo", "Show Bios Bootlogo(Breaks some games); disabled|enabled" }, +      { "pcsx_rearmed_spu_reverb", "Sound: Reverb; enabled|disabled" },        { "pcsx_rearmed_spu_interpolation", "Sound: Interpolation; simple|gaussian|cubic|off" }, +      { "pcsx_rearmed_pe2_fix", "Parasite Eve 2/Vandal Hearts 1/2 Fix; disabled|enabled" }, +      { "pcsx_rearmed_inuyasha_fix", "InuYasha Sengoku Battle Fix; disabled|enabled" },        { NULL, NULL },     }; +    if (cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &logging)) +        log_cb = logging.log; +     environ_cb = cb;     cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars); @@ -280,15 +524,172 @@ unsigned retro_api_version(void)  	return RETRO_API_VERSION;  } +static int controller_port_variable(unsigned port, struct retro_variable *var) +{ +	if (port >= PORTS_NUMBER) +		return 0; + +	if (!environ_cb) +		return 0; + +	var->value = NULL; +	switch (port) { +	case 0: +		var->key = "pcsx_rearmed_pad1type"; +		break; +	case 1: +		var->key = "pcsx_rearmed_pad2type"; +		break; +	case 2: +		var->key = "pcsx_rearmed_pad3type"; +		break; +	case 3: +		var->key = "pcsx_rearmed_pad4type"; +		break; +	case 4: +		var->key = "pcsx_rearmed_pad5type"; +		break; +	case 5: +		var->key = "pcsx_rearmed_pad6type"; +		break; +	case 6: +		var->key = "pcsx_rearmed_pad7type"; +		break; +	case 7: +		var->key = "pcsx_rearmed_pad8type"; +		break; +	} + +	return environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, var) || var->value; +} + +static void update_controller_port_variable(unsigned port) +{ +	if (port >= PORTS_NUMBER) +		return; + +	struct retro_variable var; + +	if (controller_port_variable(port, &var)) +	{ +		if (strcmp(var.value, "standard") == 0) +			in_type[port] = PSE_PAD_TYPE_STANDARD; +		else if (strcmp(var.value, "analog") == 0) +			in_type[port] = PSE_PAD_TYPE_ANALOGJOY; +		else if (strcmp(var.value, "dualshock") == 0) +			in_type[port] = PSE_PAD_TYPE_ANALOGPAD; +		else if (strcmp(var.value, "negcon") == 0) +			in_type[port] = PSE_PAD_TYPE_NEGCON; +		else if (strcmp(var.value, "none") == 0) +			in_type[port] = PSE_PAD_TYPE_NONE; +		// else 'default' case, do nothing +	} +} + +static void update_controller_port_device(unsigned port, unsigned device) +{ +	if (port >= PORTS_NUMBER) +		return; + +	struct retro_variable var; + +	if (!controller_port_variable(port, &var)) +		return; + +	if (strcmp(var.value, "default") != 0) +		return; + +	switch (device) +	{ +	case RETRO_DEVICE_JOYPAD: +		in_type[port] = PSE_PAD_TYPE_STANDARD; +		break; +	case RETRO_DEVICE_ANALOG: +		in_type[port] = PSE_PAD_TYPE_ANALOGPAD; +		break; +	case RETRO_DEVICE_MOUSE: +		in_type[port] = PSE_PAD_TYPE_MOUSE; +		break; +	case RETRO_DEVICE_LIGHTGUN: +		in_type[port] = PSE_PAD_TYPE_GUN; +		break; +	case RETRO_DEVICE_NONE: +	default: +		in_type[port] = PSE_PAD_TYPE_NONE; +	} +} + +static void update_multitap() +{ +	struct retro_variable var; +	int auto_case, port; + +	var.value = NULL; +	var.key = "pcsx_rearmed_multitap1"; +	auto_case = 0; +	if (environ_cb && (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)) +	{ +		if (strcmp(var.value, "enabled") == 0) +			multitap1 = 1; +		else if (strcmp(var.value, "disabled") == 0) +			multitap1 = 0; +		else // 'auto' case +			auto_case = 1; +	} +	else +		auto_case = 1; + +	if (auto_case) +	{ +		// If a gamepad is plugged after port 2, we need a first multitap. +		multitap1 = 0; +		for (port = 2; port < PORTS_NUMBER; port++) +			multitap1 |= in_type[port] != PSE_PAD_TYPE_NONE; +	} + +	var.value = NULL; +	var.key = "pcsx_rearmed_multitap2"; +	auto_case = 0; +	if (environ_cb && (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)) +	{ +		if (strcmp(var.value, "enabled") == 0) +			multitap2 = 1; +		else if (strcmp(var.value, "disabled") == 0) +			multitap2 = 0; +		else // 'auto' case +			auto_case = 1; +	} +	else +		auto_case = 1; + +	if (auto_case) +	{ +		// If a gamepad is plugged after port 4, we need a second multitap. +		multitap2 = 0; +		for (port = 4; port < PORTS_NUMBER; port++) +			multitap2 |= in_type[port] != PSE_PAD_TYPE_NONE; +	} +} +  void retro_set_controller_port_device(unsigned port, unsigned device)  { +	SysPrintf("port %u  device %u",port,device); + +	if (port >= PORTS_NUMBER) +		return; + +	update_controller_port_device(port, device); +	update_multitap();  }  void retro_get_system_info(struct retro_system_info *info)  {  	memset(info, 0, sizeof(*info));  	info->library_name = "PCSX-ReARMed"; -	info->library_version = "r22"; +#ifndef GIT_VERSION +#define GIT_VERSION "" +#endif +	info->library_version = "r22" GIT_VERSION;  	info->valid_extensions = "bin|cue|img|mdf|pbp|toc|cbn|m3u";  	info->need_fullpath = true;  } @@ -306,8 +707,8 @@ void retro_get_system_av_info(struct retro_system_av_info *info)  }  /* savestates */ -size_t retro_serialize_size(void)  -{  +size_t retro_serialize_size(void) +{  	// it's currently 4380651-4397047 bytes,  	// but have some reserved for future  	return 0x440000; @@ -393,7 +794,7 @@ static void save_close(void *file)  }  bool retro_serialize(void *data, size_t size) -{  +{  	int ret = SaveState(data);  	return ret == 0 ? true : false;  } @@ -419,6 +820,21 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code)  	strncpy(buf, code, sizeof(buf));  	buf[sizeof(buf) - 1] = 0; +	//Prepare buffered cheat for PCSX's AddCheat fucntion. +	int cursor=0; +	int nonhexdec=0; +	while (buf[cursor]){ +		if (!(ISHEXDEC)){ +			if (++nonhexdec%2){ +				buf[cursor]=' '; +			} else { +				buf[cursor]='\n'; +			} +		} +		cursor++; +	} + +  	if (index < NumCheats)  		ret = EditCheat(index, "", buf);  	else @@ -557,6 +973,10 @@ static struct retro_disk_control_callback disk_control = {  #define SLASH '/'  #endif +#ifndef PATH_MAX +#define PATH_MAX  4096 +#endif +  static char base_dir[PATH_MAX];  static bool read_m3u(const char *file) @@ -761,7 +1181,7 @@ bool retro_load_game(const struct retro_game_info *info)        { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2,    "R2" },        { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3,    "R3" },        { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT,    "Select" }, -      { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START,    "Start" },  +      { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START,    "Start" },        { 5, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" },        { 5, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" },        { 5, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, @@ -782,7 +1202,7 @@ bool retro_load_game(const struct retro_game_info *info)        { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2,    "R2" },        { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3,    "R3" },        { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT,    "Select" }, -      { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START,    "Start" },  +      { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START,    "Start" },        { 6, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" },        { 6, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" },        { 6, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, @@ -803,7 +1223,7 @@ bool retro_load_game(const struct retro_game_info *info)        { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2,    "R2" },        { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3,    "R3" },        { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT,    "Select" }, -      { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START,    "Start" },  +      { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START,    "Start" },        { 7, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" },        { 7, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" },        { 7, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, @@ -844,7 +1264,7 @@ bool retro_load_game(const struct retro_game_info *info)  	if (is_m3u) {  		if (!read_m3u(info->path)) { -			SysPrintf("failed to read m3u file\n"); +			log_cb(RETRO_LOG_INFO, "failed to read m3u file\n");  			return false;  		}  	} else { @@ -856,7 +1276,7 @@ bool retro_load_game(const struct retro_game_info *info)  	/* have to reload after set_cd_image for correct cdr plugin */  	if (LoadPlugins() == -1) { -		SysPrintf("failed to load plugins\n"); +		log_cb(RETRO_LOG_INFO, "failed to load plugins\n");  		return false;  	} @@ -864,23 +1284,25 @@ bool retro_load_game(const struct retro_game_info *info)  	NetOpened = 0;  	if (OpenPlugins() == -1) { -		SysPrintf("failed to open plugins\n"); +		log_cb(RETRO_LOG_INFO, "failed to open plugins\n");  		return false;  	}  	plugin_call_rearmed_cbs();  	dfinput_activate(); -	Config.PsxAuto = 1;  	if (CheckCdrom() == -1) { -		SysPrintf("unsupported/invalid CD image: %s\n", info->path); +        log_cb(RETRO_LOG_INFO, "unsupported/invalid CD image: %s\n", info->path);  		return false;  	} -	SysReset(); +	/* TODO: Calling SysReset() outside retro_run for some system +	 * causes RetroArch to freeze, e.g Ludo */ +	//SysReset(); +	rebootemu = 1;  	if (LoadCdrom() == -1) { -		SysPrintf("could not load CD-ROM!\n"); +		log_cb(RETRO_LOG_INFO, "could not load CD\n");  		return false;  	}  	emu_on_new_cd(0); @@ -897,15 +1319,6 @@ bool retro_load_game(const struct retro_game_info *info)  	return true;  } -bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info) -{ -	return false; -} - -void retro_unload_game(void)  -{ -} -  unsigned retro_get_region(void)  {  	return is_pal_mode ? RETRO_REGION_PAL : RETRO_REGION_NTSC; @@ -929,7 +1342,9 @@ size_t retro_get_memory_size(unsigned id)  void retro_reset(void)  { -	SysReset(); +   //hack to prevent retroarch freezing when reseting in the menu but not while running with the hot key +   rebootemu = 1; +	//SysReset();  }  static const unsigned short retro_psx_map[] = { @@ -955,20 +1370,19 @@ static const unsigned short retro_psx_map[] = {  static void update_variables(bool in_flight)  {     struct retro_variable var; -    +   int i; +     var.value = NULL;     var.key = "pcsx_rearmed_frameskip"; -     if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)        pl_rearmed_cbs.frameskip = atoi(var.value);     var.value = NULL;     var.key = "pcsx_rearmed_region"; -     if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)     {        Config.PsxAuto = 0; -      if (strcmp(var.value, "Automatic") == 0) +      if (strcmp(var.value, "auto") == 0)           Config.PsxAuto = 1;        else if (strcmp(var.value, "NTSC") == 0)           Config.PsxType = 0; @@ -976,24 +1390,61 @@ static void update_variables(bool in_flight)           Config.PsxType = 1;     } +   for (i = 0; i < PORTS_NUMBER; i++) +      update_controller_port_variable(i); + +   update_multitap(); +     var.value = NULL; -   var.key = "pcsx_rearmed_pad1type"; +   var.key = "pcsx_rearmed_negcon_deadzone"; +   negcon_deadzone = 0; +   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) +   { +      negcon_deadzone = (int)(atoi(var.value) * 0.01f * NEGCON_RANGE); +   } +   var.value = NULL; +   var.key = "pcsx_rearmed_negcon_response"; +   negcon_linearity = 1;     if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)     { -      in_type1 = PSE_PAD_TYPE_STANDARD; -      if (strcmp(var.value, "analog") == 0) -         in_type1 = PSE_PAD_TYPE_ANALOGPAD; +      if (strcmp(var.value, "quadratic") == 0){ +         negcon_linearity = 2; +      } else if (strcmp(var.value, "cubic") == 0){ +         negcon_linearity = 3; +      }     }     var.value = NULL; -   var.key = "pcsx_rearmed_pad2type"; +   var.key = "pcsx_rearmed_vibration";     if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)     { -      in_type2 = PSE_PAD_TYPE_STANDARD; -      if (strcmp(var.value, "analog") == 0) -         in_type2 = PSE_PAD_TYPE_ANALOGPAD; +      if (strcmp(var.value, "disabled") == 0) +         in_enable_vibration = 0; +      else if (strcmp(var.value, "enabled") == 0) +         in_enable_vibration = 1; +   } + +   var.value = NULL; +   var.key = "pcsx_rearmed_dithering"; + +   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) +   { +      if (strcmp(var.value, "disabled") == 0) { +         pl_rearmed_cbs.gpu_peops.iUseDither = 0; +         pl_rearmed_cbs.gpu_peopsgl.bDrawDither = 0; +#ifdef __ARM_NEON__ +         pl_rearmed_cbs.gpu_neon.allow_dithering = 0; +#endif +      } +      else if (strcmp(var.value, "enabled") == 0) { +         pl_rearmed_cbs.gpu_peops.iUseDither = 1; +         pl_rearmed_cbs.gpu_peopsgl.bDrawDither = 1; +#ifdef __ARM_NEON__ +         pl_rearmed_cbs.gpu_neon.allow_dithering = 1; +#endif +      }     }  #ifdef __ARM_NEON__ @@ -1036,9 +1487,9 @@ static void update_variables(bool in_flight)     if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)     { -      if (strcmp(var.value, "off") == 0) +      if (strcmp(var.value, "disabled") == 0)           duping_enable = false; -      else if (strcmp(var.value, "on") == 0) +      else if (strcmp(var.value, "enabled") == 0)           duping_enable = true;     } @@ -1050,6 +1501,11 @@ static void update_variables(bool in_flight)     {        R3000Acpu *prev_cpu = psxCpu; +#ifdef _3DS +      if(!__ctr_svchax) +         Config.Cpu = CPU_INTERPRETER; +      else +#endif        if (strcmp(var.value, "disabled") == 0)           Config.Cpu = CPU_INTERPRETER;        else if (strcmp(var.value, "enabled") == 0) @@ -1069,9 +1525,9 @@ static void update_variables(bool in_flight)     if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)     { -      if (strcmp(var.value, "off") == 0) +      if (strcmp(var.value, "disabled") == 0)           spu_config.iUseReverb = false; -      else if (strcmp(var.value, "on") == 0) +      else if (strcmp(var.value, "enabled") == 0)           spu_config.iUseReverb = true;     } @@ -1090,6 +1546,28 @@ static void update_variables(bool in_flight)           spu_config.iUseInterpolation = 0;     } +   var.value = "NULL"; +   var.key = "pcsx_rearmed_pe2_fix"; + +   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) +   { +      if (strcmp(var.value, "disabled") == 0) +         Config.RCntFix = 0; +      else if (strcmp(var.value, "enabled") == 0) +         Config.RCntFix = 1; +   } + +   var.value = "NULL"; +   var.key = "pcsx_rearmed_inuyasha_fix"; + +   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) +   { +      if (strcmp(var.value, "disabled") == 0) +         Config.VSyncWA = 0; +      else if (strcmp(var.value, "enabled") == 0) +         Config.VSyncWA = 1; +   } +     if (in_flight) {        // inform core things about possible config changes        plugin_call_rearmed_cbs(); @@ -1101,11 +1579,77 @@ static void update_variables(bool in_flight)        dfinput_activate();     } +   else{ +      //not yet running + +      //bootlogo display hack +      if (found_bios) { +         var.value = "NULL"; +         var.key = "pcsx_rearmed_show_bios_bootlogo"; +         if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) +         { +            if (strcmp(var.value, "enabled") == 0) +               Config.SlowBoot = 1; +            else +               Config.SlowBoot = 0; +         } +      } +#ifndef DRC_DISABLE +      var.value = "NULL"; +      var.key = "pcsx_rearmed_psxclock"; +      if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) +      { +         int psxclock = atoi(var.value); +         cycle_multiplier = 10000 / psxclock; +      } +#endif +   }  } -void retro_run(void)  +// Taken from beetle-psx-libretro +static uint16_t get_analog_button(retro_input_state_t input_state_cb, int player_index, int id) +{ +	uint16_t button; + +	// NOTE: Analog buttons were added Nov 2017. Not all front-ends support this +	// feature (or pre-date it) so we need to handle this in a graceful way. + +	// First, try and get an analog value using the new libretro API constant +	button = input_state_cb(player_index, +									RETRO_DEVICE_ANALOG, +									RETRO_DEVICE_INDEX_ANALOG_BUTTON, +									id); +	button = MIN(button / 128, 255); + +	if (button == 0) +	{ +		// If we got exactly zero, we're either not pressing the button, or the front-end +		// is not reporting analog values. We need to do a second check using the classic +		// digital API method, to at least get some response - better than nothing. + +		// NOTE: If we're really just not holding the button, we're still going to get zero. + +		button = input_state_cb(player_index, +										RETRO_DEVICE_JOYPAD, +										0, +										id) ? 255 : 0; +	} + +	return button; +} + +void retro_run(void)  {  	int i; +	//SysReset must be run while core is running,Not in menu (Locks up Retroarch) +	if (rebootemu != 0) { +		rebootemu = 0; +		SysReset(); +		if (!Config.HLE && !Config.SlowBoot) { +			// skip BIOS logos +			psxRegs.pc = psxRegs.GPR.n.ra; +		} +	}  	input_poll_cb(); @@ -1113,29 +1657,161 @@ void retro_run(void)  	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)  		update_variables(true); -	in_keystate = 0; -	for (i = 0; i < RETRO_PSX_MAP_LEN; i++) -		if (input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, i)) -			in_keystate |= retro_psx_map[i]; -	in_keystate <<= 16; -	for (i = 0; i < RETRO_PSX_MAP_LEN; i++) -		if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i)) -			in_keystate |= retro_psx_map[i]; +	// reset all keystate, query libretro for keystate +	int j; +	int lsx; +	int rsy; +	float negcon_twist_amplitude; +	int negcon_i_rs; +	int negcon_ii_rs; +	for(i = 0; i < PORTS_NUMBER; i++) { +		in_keystate[i] = 0; + +		if (in_type[i] == PSE_PAD_TYPE_NONE) +			continue; -	if (in_type1 == PSE_PAD_TYPE_ANALOGPAD) -	{ -		in_a1[0] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) / 256) + 128; -		in_a1[1] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / 256) + 128; -		in_a2[0] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) / 256) + 128; -		in_a2[1] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y) / 256) + 128; +		if (in_type[i] == PSE_PAD_TYPE_NEGCON) +		{ +			// Query digital inputs +			// +			// > Pad-Up +			if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP)){ +				in_keystate[i] |= (1 << DKEY_UP); +			} +			// > Pad-Right +			if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)){ +				in_keystate[i] |= (1 << DKEY_RIGHT); +			} +			// > Pad-Down +			if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN)){ +				in_keystate[i] |= (1 << DKEY_DOWN); +			} +			// > Pad-Left +			if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)){ +				in_keystate[i] |= (1 << DKEY_LEFT); +			} +			// > Start +			if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START)){ +				in_keystate[i] |= (1 << DKEY_START); +			} +			// > neGcon A +			if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A)){ +				in_keystate[i] |= (1 << DKEY_CIRCLE); +			} +			// > neGcon B +			if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X)){ +				in_keystate[i] |= (1 << DKEY_TRIANGLE); +			} +			// > neGcon R shoulder (digital) +			if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R)){ +				in_keystate[i] |= (1 << DKEY_R1); +			} +			// Query analog inputs +			// +			// From studying 'libpcsxcore/plugins.c' and 'frontend/plugin.c': +			// >> pad->leftJoyX  == in_analog_left[i][0]  == NeGcon II +			// >> pad->leftJoyY  == in_analog_left[i][1]  == NeGcon L +			// >> pad->rightJoyX == in_analog_right[i][0] == NeGcon twist +			// >> pad->rightJoyY == in_analog_right[i][1] == NeGcon I +			// So we just have to map in_analog_left/right to more +			// appropriate inputs... +			// +			// > NeGcon twist +			// >> Get raw analog stick value and account for deadzone +			lsx = input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X); +			if (lsx > negcon_deadzone){ +				lsx = lsx - negcon_deadzone; +			} else if (lsx < -negcon_deadzone){ +				lsx = lsx + negcon_deadzone; +			} else { +				lsx = 0; +			} +			// >> Convert to an 'amplitude' [-1.0,1.0] and adjust response +			negcon_twist_amplitude = (float)lsx / (float)(NEGCON_RANGE - negcon_deadzone); +			if (negcon_linearity == 2){ +				if (negcon_twist_amplitude < 0.0){ +					negcon_twist_amplitude = -(negcon_twist_amplitude * negcon_twist_amplitude); +				} else { +					negcon_twist_amplitude = negcon_twist_amplitude * negcon_twist_amplitude; +				} +			} else if (negcon_linearity == 3){ +				negcon_twist_amplitude = negcon_twist_amplitude * negcon_twist_amplitude * negcon_twist_amplitude; +			} +			// >> Convert to final 'in_analog' integer value [0,255] +			in_analog_right[i][0] = MAX(MIN((int)(negcon_twist_amplitude * 128.0f) + 128, 255), 0); +			// > NeGcon I + II +			// >> Handle right analog stick vertical axis mapping... +			//    - Up (-Y) == accelerate == neGcon I +			//    - Down (+Y) == brake == neGcon II +			negcon_i_rs = 0; +			negcon_ii_rs = 0; +			rsy = input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y); +			if (rsy >= 0){ +				// Account for deadzone +				// (Note: have never encountered a gamepad with significant differences +				// in deadzone between left/right analog sticks, so use the regular 'twist' +				// deadzone here) +				if (rsy > negcon_deadzone){ +					rsy = rsy - negcon_deadzone; +				} else { +					rsy = 0; +				} +				// Convert to 'in_analog' integer value [0,255] +				negcon_ii_rs = MIN((int)(((float)rsy / (float)(NEGCON_RANGE - negcon_deadzone)) * 255.0f), 255); +			} else { +				if (rsy < -negcon_deadzone){ +					rsy = -1 * (rsy + negcon_deadzone); +				} else { +					rsy = 0; +				} +				negcon_i_rs = MIN((int)(((float)rsy / (float)(NEGCON_RANGE - negcon_deadzone)) * 255.0f), 255); +			} +			// >> NeGcon I +			in_analog_right[i][1] = MAX( +				MAX( +					get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_R2), +					get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_B) +				), +				negcon_i_rs +			); +			// >> NeGcon II +			in_analog_left[i][0] = MAX( +				MAX( +					get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_L2), +					get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_Y) +				), +				negcon_ii_rs +			); +			// > NeGcon L +			in_analog_left[i][1] = get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_L); +		} +		else +		{ +			// Query digital inputs +			for (j = 0; j < RETRO_PSX_MAP_LEN; j++){ +				if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, j)){ +					in_keystate[i] |= retro_psx_map[j]; +				} +			} +			// Query analog inputs +			if (in_type[i] == PSE_PAD_TYPE_ANALOGJOY || in_type[i] == PSE_PAD_TYPE_ANALOGPAD) +			{ +				in_analog_left[i][0] = MIN((input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) / 255) + 128, 255); +				in_analog_left[i][1] = MIN((input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / 255) + 128, 255); +				in_analog_right[i][0] = MIN((input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) / 255) + 128, 255); +				in_analog_right[i][1] = MIN((input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y) / 255) + 128, 255); +			} +		}  	}  	stop = 0;  	psxCpu->Execute(); -	video_cb((vout_fb_dirty || !vout_can_dupe || !duping_enable) ? vout_buf : NULL, +	video_cb((vout_fb_dirty || !vout_can_dupe || !duping_enable) ? vout_buf_ptr : NULL,  		vout_width, vout_height, vout_width * 2);  	vout_fb_dirty = 0; + +    set_vout_fb();  }  static bool try_use_bios(const char *path) @@ -1162,7 +1838,7 @@ static bool try_use_bios(const char *path)  	return true;  } -#if 1 +#ifndef VITA  #include <sys/types.h>  #include <dirent.h> @@ -1180,7 +1856,7 @@ static bool find_any_bios(const char *dirpath, char *path, size_t path_size)  		if (strncasecmp(ent->d_name, "scph", 4) != 0)  			continue; -		snprintf(path, path_size, "%s/%s", dirpath, ent->d_name); +		snprintf(path, path_size, "%s%c%s", dirpath, SLASH, ent->d_name);  		ret = try_use_bios(path);  		if (ret)  			break; @@ -1198,63 +1874,155 @@ static void check_system_specs(void)     environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level);  } -void retro_init(void) +static int init_memcards(void) +{ +	int ret = 0; +	const char *dir; +	struct retro_variable var = { .key="pcsx_rearmed_memcard2", .value=NULL }; +	static const char CARD2_FILE[] = "pcsx-card2.mcd"; + +	// Memcard2 will be handled and is re-enabled if needed using core +	// operations. +	// Memcard1 is handled by libretro, doing this will set core to +	// skip file io operations for memcard1 like SaveMcd +	snprintf(Config.Mcd1, sizeof(Config.Mcd1), "none"); +	snprintf(Config.Mcd2, sizeof(Config.Mcd2), "none"); +	init_memcard(Mcd1Data); +	// Memcard 2 is managed by the emulator on the filesystem, +	// There is no need to initialize Mcd2Data like Mcd1Data. + +	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { +		SysPrintf("Memcard 2: %s\n", var.value); +		if (memcmp(var.value, "enabled", 7) == 0) { +			if (environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &dir) && dir) { +				if (strlen(dir) + strlen(CARD2_FILE) + 2 > sizeof(Config.Mcd2)) { +					SysPrintf("Path '%s' is too long. Cannot use memcard 2. Use a shorter path.\n", dir); +					ret = -1; +				} else { +					McdDisable[1] = 0; +					snprintf(Config.Mcd2, sizeof(Config.Mcd2), "%s/%s", dir, CARD2_FILE); +					SysPrintf("Use memcard 2: %s\n", Config.Mcd2); +				} +			} else { +				SysPrintf("Could not get save directory! Could not create memcard 2."); +				ret = -1; +			} +		} +	} +	return ret; +} + +static void loadPSXBios(void)  { -	const char *bios[] = { "scph1001", "scph5501", "scph7001" };  	const char *dir;  	char path[256]; -	int i, ret; -	bool found_bios = false; +	unsigned useHLE = 0; + +	const char *bios[] = { +		"SCPH101", "scph101", +		"SCPH5501", "scph5501", +		"SCPH7001", "scph7001", +		"SCPH1001", "scph1001" +	}; + +	struct retro_variable var = { +		.key = "pcsx_rearmed_bios", +		.value = NULL +	}; + +	found_bios = 0; + +	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { +		if (!strcmp(var.value, "HLE")) +			useHLE = 1; +	} + +	if (!useHLE) +	{ +		if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir) +		{ +			unsigned i; +			snprintf(Config.BiosDir, sizeof(Config.BiosDir), "%s", dir); + +			for (i = 0; i < sizeof(bios) / sizeof(bios[0]); i++) { +				snprintf(path, sizeof(path), "%s%c%s.bin", dir, SLASH, bios[i]); +				found_bios = try_use_bios(path); +				if (found_bios) +					break; +			} + +			if (!found_bios) +				found_bios = find_any_bios(dir, path, sizeof(path)); +		} +		if (found_bios) { +			SysPrintf("found BIOS file: %s\n", Config.Bios); +		} +	} + +	if (useHLE || !found_bios) +	{ +		SysPrintf("no BIOS files found.\n"); +		struct retro_message msg = +		{ +			"No PlayStation BIOS file found - add for better compatibility", +			180 +		}; +		environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, (void*)&msg); +	} +} + +void retro_init(void) +{ +	struct retro_rumble_interface rumble; +	int ret;  #ifdef __MACH__  	// magic sauce to make the dynarec work on iOS  	syscall(SYS_ptrace, 0 /*PTRACE_TRACEME*/, 0, 0, 0);  #endif +#ifdef _3DS +   psxMapHook = pl_3ds_mmap; +   psxUnmapHook = pl_3ds_munmap; +#endif +#ifdef VITA +   if(init_vita_mmap()<0) +      abort(); +   psxMapHook = pl_vita_mmap; +   psxUnmapHook = pl_vita_munmap; +#endif  	ret = emu_core_preinit(); +#ifdef _3DS +   /* emu_core_preinit sets the cpu to dynarec */ +   if(!__ctr_svchax) +      Config.Cpu = CPU_INTERPRETER; +#endif +	ret |= init_memcards(); +  	ret |= emu_core_init();  	if (ret != 0) {  		SysPrintf("PCSX init failed.\n");  		exit(1);  	} -#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) +#ifdef _3DS +   vout_buf = linearMemAlign(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2, 0x80); +#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) && !defined(VITA)  	posix_memalign(&vout_buf, 16, VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2);  #else  	vout_buf = malloc(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2);  #endif -	if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir) -	{ -		snprintf(Config.BiosDir, sizeof(Config.BiosDir), "%s/", dir); - -		for (i = 0; i < sizeof(bios) / sizeof(bios[0]); i++) { -			snprintf(path, sizeof(path), "%s/%s.bin", dir, bios[i]); -			found_bios = try_use_bios(path); -			if (found_bios) -				break; -		} +	vout_buf_ptr = vout_buf; -		if (!found_bios) -			found_bios = find_any_bios(dir, path, sizeof(path)); -	} -	if (found_bios) { -		SysPrintf("found BIOS file: %s\n", Config.Bios); -	} -	else -	{ -		SysPrintf("no BIOS files found.\n"); -		struct retro_message msg =  -		{ -			"no BIOS found, expect bugs!", -			180 -		}; -		environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, (void*)&msg); -	} +	loadPSXBios();  	environ_cb(RETRO_ENVIRONMENT_GET_CAN_DUPE, &vout_can_dupe);  	environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_control); -	environ_cb(RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE, &rumble); + +	rumble_cb = NULL; +	if (environ_cb(RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE, &rumble)) +		rumble_cb = rumble.set_rumble_state;  	/* Set how much slower PSX CPU runs * 100 (so that 200 is 2 times)  	 * we have to do this because cache misses and some IO penalties @@ -1266,10 +2034,6 @@ void retro_init(void)  	pl_rearmed_cbs.gpu_peops.iUseDither = 1;  	spu_config.iUseFixedUpdates = 1; -	McdDisable[0] = 0; -	McdDisable[1] = 1; -	init_memcard(Mcd1Data); -  	SaveFuncs.open = save_open;  	SaveFuncs.read = save_read;  	SaveFuncs.write = save_write; @@ -1283,6 +2047,22 @@ void retro_init(void)  void retro_deinit(void)  {  	SysClose(); +#ifdef _3DS +   linearFree(vout_buf); +#else  	free(vout_buf); +#endif  	vout_buf = NULL; + +#ifdef VITA +  deinit_vita_mmap(); +#endif  } + +#ifdef VITA +#include <psp2/kernel/threadmgr.h> +int usleep (unsigned long us) +{ +   sceKernelDelayThread(us); +} +#endif | 
