Add libretro VFS and use VFS for windows target
[pcsx_rearmed.git] / frontend / libretro.c
index b473436..395bc13 100644 (file)
 #include <libretro.h>
 #include "libretro_core_options.h"
 
+#ifdef USE_LIBRETRO_VFS
+#include <streams/file_stream_transforms.h>
+#endif
+
 #ifdef _3DS
 #include "3ds/3ds_utils.h"
 #endif
@@ -117,6 +121,7 @@ int in_mouse[8][2];
 int multitap1 = 0;
 int multitap2 = 0;
 int in_enable_vibration = 1;
+static int input_changed = 0;
 
 // NegCon adjustment parameters
 // > The NegCon 'twist' action is somewhat awkward when mapped
@@ -516,15 +521,62 @@ void out_register_libretro(struct out_driver *drv)
    drv->feed   = snd_feed;
 }
 
+#define RETRO_DEVICE_PSE_STANDARD   RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD,   0)
+#define RETRO_DEVICE_PSE_ANALOG     RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_ANALOG,   0)
+#define RETRO_DEVICE_PSE_DUALSHOCK  RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_ANALOG,   1)
+#define RETRO_DEVICE_PSE_NEGCON     RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_ANALOG,   2)
+#define RETRO_DEVICE_PSE_GUNCON     RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_LIGHTGUN, 0)
+#define RETRO_DEVICE_PSE_MOUSE      RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE,    0)
+
+static char *get_pse_pad_label[] = {
+   "none", "mouse", "negcon", "konami gun", "standard", "analog", "guncon", "dualshock"
+};
+
+static const struct retro_controller_description pads[7] =
+{
+   { "standard",  RETRO_DEVICE_JOYPAD },
+   { "analog",    RETRO_DEVICE_PSE_ANALOG },
+   { "dualshock", RETRO_DEVICE_PSE_DUALSHOCK },
+   { "negcon",    RETRO_DEVICE_PSE_NEGCON },
+   { "guncon",    RETRO_DEVICE_PSE_GUNCON },
+   { "mouse",     RETRO_DEVICE_PSE_MOUSE },
+   { NULL, 0 },
+};
+
+static const struct retro_controller_info ports[9] =
+{
+   { pads, 7 },
+   { pads, 7 },
+   { pads, 7 },
+   { pads, 7 },
+   { pads, 7 },
+   { pads, 7 },
+   { pads, 7 },
+   { pads, 7 },
+   { NULL, 0 },
+};
+
 /* libretro */
 void retro_set_environment(retro_environment_t cb)
 {
+#ifdef USE_LIBRETRO_VFS
+   struct retro_vfs_interface_info vfs_iface_info;
+#endif
+
    environ_cb = cb;
 
    if (cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &logging))
       log_cb = logging.log;
 
+   environ_cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports);
    libretro_set_core_options(environ_cb);
+
+#ifdef USE_LIBRETRO_VFS
+   vfs_iface_info.required_interface_version = 1;
+   vfs_iface_info.iface                      = NULL;
+   if (environ_cb(RETRO_ENVIRONMENT_GET_VFS_INTERFACE, &vfs_iface_info))
+          filestream_vfs_init(&vfs_iface_info);
+#endif
 }
 
 void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; }
@@ -538,167 +590,76 @@ unsigned retro_api_version(void)
    return RETRO_API_VERSION;
 }
 
-static int controller_port_variable(unsigned port, struct retro_variable *var)
+static void update_multitap(void)
 {
-   if (port >= PORTS_NUMBER)
-      return 0;
-
-   if (!environ_cb)
-      return 0;
+   struct retro_variable var = {};
 
-   var->value = NULL;
-   switch (port)
+   var.value = NULL;
+   var.key = "pcsx_rearmed_multitap";
+   if (environ_cb && (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value))
    {
-   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;
+      if (strcmp(var.value, "port 1 only") == 0)
+      {
+         multitap1 = 1;
+         multitap2 = 0;
+      }
+      else if (strcmp(var.value, "port 2 only") == 0)
+      {
+         multitap1 = 0;
+         multitap2 = 1;
+      }
+      else if (strcmp(var.value, "both") == 0)
+      {
+         multitap1 = 1;
+         multitap2 = 1;
+      }
+      else
+      {
+         multitap1 = 0;
+         multitap2 = 0;
+      }
    }
-
-   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))
+   else
    {
-      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, "guncon") == 0)
-         in_type[port] = PSE_PAD_TYPE_GUNCON;
-      else if (strcmp(var.value, "mouse") == 0)
-         in_type[port] = PSE_PAD_TYPE_MOUSE;
-      else if (strcmp(var.value, "none") == 0)
-         in_type[port] = PSE_PAD_TYPE_NONE;
-      // else 'default' case, do nothing
+      multitap1 = 0;
+      multitap2 = 0;
    }
 }
 
-static void update_controller_port_device(unsigned port, unsigned device)
+void retro_set_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:
+   case RETRO_DEVICE_PSE_STANDARD:
       in_type[port] = PSE_PAD_TYPE_STANDARD;
       break;
-   case RETRO_DEVICE_ANALOG:
+   case RETRO_DEVICE_PSE_ANALOG:
+      in_type[port] = PSE_PAD_TYPE_ANALOGJOY;
+      break;
+   case RETRO_DEVICE_PSE_DUALSHOCK:
       in_type[port] = PSE_PAD_TYPE_ANALOGPAD;
       break;
-   case RETRO_DEVICE_MOUSE:
+   case RETRO_DEVICE_PSE_MOUSE:
       in_type[port] = PSE_PAD_TYPE_MOUSE;
       break;
-   case RETRO_DEVICE_LIGHTGUN:
-      in_type[port] = PSE_PAD_TYPE_GUN;
+   case RETRO_DEVICE_PSE_NEGCON:
+      in_type[port] = PSE_PAD_TYPE_NEGCON;
+      break;
+   case RETRO_DEVICE_PSE_GUNCON:
+      in_type[port] = PSE_PAD_TYPE_GUNCON;
       break;
    case RETRO_DEVICE_NONE:
    default:
       in_type[port] = PSE_PAD_TYPE_NONE;
+      break;
    }
-}
-
-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();
+   SysPrintf("port: %u  device: %s\n", port + 1, get_pse_pad_label[in_type[port]]);
+   input_changed = 1;
 }
 
 void retro_get_system_info(struct retro_system_info *info)
@@ -1151,11 +1112,11 @@ static bool read_m3u(const char *file)
 {
    char line[1024];
    char name[PATH_MAX];
-   FILE *f = fopen(file, "r");
-   if (!f)
+   FILE *fp = fopen(file, "r");
+   if (!fp)
       return false;
 
-   while (fgets(line, sizeof(line), f) && disk_count < sizeof(disks) / sizeof(disks[0]))
+   while (fgets(fp, line, sizeof(line)) && disk_count < sizeof(disks) / sizeof(disks[0]))
    {
       if (line[0] == '#')
          continue;
@@ -1181,7 +1142,7 @@ static bool read_m3u(const char *file)
       }
    }
 
-   fclose(f);
+   fclose(fp);
    return (disk_count != 0);
 }
 
@@ -1440,7 +1401,7 @@ bool retro_load_game(const struct retro_game_info *info)
    }
 
    plugin_call_rearmed_cbs();
-   dfinput_activate();
+   /* dfinput_activate(); */
 
    if (CheckCdrom() == -1)
    {
@@ -1459,6 +1420,8 @@ bool retro_load_game(const struct retro_game_info *info)
 
    set_retro_memmap();
 
+   input_changed = 1;
+
    return true;
 }
 
@@ -1525,7 +1488,6 @@ static float GunconAdjustRatioY = 1;
 static void update_variables(bool in_flight)
 {
    struct retro_variable var;
-   int i;
 #ifdef GPU_PEOPS
    int gpu_peops_fix = 0;
 #endif
@@ -1548,8 +1510,8 @@ static void update_variables(bool in_flight)
          Config.PsxType = 1;
    }
 
-   for (i = 0; i < PORTS_NUMBER; i++)
-      update_controller_port_variable(i);
+   /*for (i = 0; i < PORTS_NUMBER; i++)
+      update_controller_port_variable(i);*/
 
    update_multitap();
 
@@ -1782,9 +1744,20 @@ static void update_variables(bool in_flight)
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
    {
       if (strcmp(var.value, "async") == 0)
+      {
          Config.AsyncCD = 1;
-      else
+         Config.CHD_Precache = 0;
+      }
+      else if (strcmp(var.value, "sync") == 0)
+      {
          Config.AsyncCD = 0;
+         Config.CHD_Precache = 0;
+      }
+      else if (strcmp(var.value, "precache") == 0)
+      {
+         Config.AsyncCD = 0;
+         Config.CHD_Precache = 1;
+      }
    }
 #endif
 
@@ -1818,6 +1791,21 @@ static void update_variables(bool in_flight)
          Config.SpuIrq = 1;
    }
 
+#ifdef THREAD_RENDERING
+   var.key = "pcsx_rearmed_gpu_thread_rendering";
+   var.value = NULL;
+
+   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+   {
+      if (strcmp(var.value, "disabled") == 0)
+         pl_rearmed_cbs.thread_rendering = THREAD_RENDERING_OFF;
+      else if (strcmp(var.value, "sync") == 0)
+         pl_rearmed_cbs.thread_rendering = THREAD_RENDERING_SYNC;
+      else if (strcmp(var.value, "async") == 0)
+         pl_rearmed_cbs.thread_rendering = THREAD_RENDERING_ASYNC;
+   }
+#endif
+
 #ifdef GPU_PEOPS
    var.value = NULL;
    var.key = "pcsx_rearmed_gpu_peops_odd_even_bit";
@@ -2031,7 +2019,7 @@ static void update_variables(bool in_flight)
             "pcsx_rearmed_gpu_unai_fast_lighting",
             "pcsx_rearmed_gpu_unai_ilace_force",
             "pcsx_rearmed_gpu_unai_pixel_skip",
-            "pcsx_rearmed_gpu_unai_scale_hires"
+            "pcsx_rearmed_gpu_unai_scale_hires",
          };
 
          option_display.visible = show_advanced_gpu_unai_settings;
@@ -2144,14 +2132,6 @@ static void update_variables(bool in_flight)
          unsigned i;
          struct retro_core_option_display option_display;
          char gpu_peops_option[][50] = {
-            "pcsx_rearmed_multitap1",
-            "pcsx_rearmed_multitap2",
-            "pcsx_rearmed_pad3type",
-            "pcsx_rearmed_pad4type",
-            "pcsx_rearmed_pad5type",
-            "pcsx_rearmed_pad6type",
-            "pcsx_rearmed_pad7type",
-            "pcsx_rearmed_pad8type",
             "pcsx_rearmed_negcon_deadzone",
             "pcsx_rearmed_negcon_response",
             "pcsx_rearmed_analog_axis_modifier",
@@ -2183,7 +2163,7 @@ static void update_variables(bool in_flight)
          GPU_open(&gpuDisp, "PCSX", NULL);
       }
 
-      dfinput_activate();
+      /* dfinput_activate(); */
    }
    else
    {
@@ -2540,6 +2520,19 @@ static void print_internal_fps(void)
 
 void retro_run(void)
 {
+   /* update multitap when inputs have changed */
+   /* this is only applied on core restart */
+   if (input_changed)
+   {
+      int i;
+      input_changed = 0;
+      update_multitap();
+      for (i = 0; i < 8; i++)
+         SysDLog("Player %d: %s\n", i + 1, get_pse_pad_label[in_type[i]]);
+      SysDLog("Multiplayer 1: %s\n", multitap1 ? "enabled" : "disabled");
+      SysDLog("Multiplayer 2: %s\n", multitap2 ? "enabled" : "disabled");
+   }
+
    //SysReset must be run while core is running,Not in menu (Locks up Retroarch)
    if (rebootemu != 0)
    {
@@ -2550,6 +2543,7 @@ void retro_run(void)
          // skip BIOS logos
          psxRegs.pc = psxRegs.GPR.n.ra;
       }
+      return;
    }
 
    print_internal_fps();
@@ -2574,17 +2568,15 @@ void retro_run(void)
 
 static bool try_use_bios(const char *path)
 {
-   FILE *f;
    long size;
    const char *name;
-
-   f = fopen(path, "rb");
-   if (f == NULL)
+   FILE *fp = fopen(path, "rb");
+   if (fp == NULL)
       return false;
 
-   fseek(f, 0, SEEK_END);
-   size = ftell(f);
-   fclose(f);
+   fseek(fp, 0, SEEK_END);
+   size = ftell(fp);
+   fclose(fp);
 
    if (size != 512 * 1024)
       return false;
@@ -2686,6 +2678,7 @@ static void loadPSXBios(void)
    unsigned useHLE = 0;
 
    const char *bios[] = {
+      "PS1_ROM", "ps1_rom",
       "PSXONPSP660", "psxonpsp660",
       "SCPH101", "scph101",
       "SCPH5501", "scph5501",
@@ -2730,11 +2723,19 @@ static void loadPSXBios(void)
       }
    }
 
-   if (useHLE || !found_bios)
+   if (!found_bios)
    {
-      const char *msg_str = "No PlayStation BIOS file found - add for better compatibility";
-
-      SysPrintf("no BIOS files found.\n");
+      const char *msg_str;
+      if (useHLE)
+      {
+         msg_str = "BIOS set to \'hle\' in core options - real BIOS will be ignored";
+         SysPrintf("Using HLE BIOS.\n");
+      }
+      else
+      {
+         msg_str = "No PlayStation BIOS file found - add for better compatibility";
+         SysPrintf("No BIOS files found.\n");
+      }
 
       if (msg_interface_version >= 1)
       {
@@ -2769,7 +2770,7 @@ void retro_init(void)
    msg_interface_version = 0;
    environ_cb(RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION, &msg_interface_version);
 
-#ifdef __MACH__
+#if defined(__MACH__) && !defined(TVOS)
    // magic sauce to make the dynarec work on iOS
    syscall(SYS_ptrace, 0 /*PTRACE_TRACEME*/, 0, 0, 0);
 #endif
@@ -2828,7 +2829,7 @@ void retro_init(void)
     * we have to do this because cache misses and some IO penalties
     * are not emulated. Warning: changing this may break compatibility. */
    cycle_multiplier = 175;
-#ifdef HAVE_PRE_ARMV7
+#if defined(HAVE_PRE_ARMV7) && !defined(_3DS)
    cycle_multiplier = 200;
 #endif
    pl_rearmed_cbs.gpu_peops.iUseDither = 1;