Пример #1
0
static bool get_info_spectate(netplay_t *handle)
{
   if (!send_nickname(handle, handle->fd))
   {
      RARCH_ERR("Failed to send nickname to host.\n");
      return false;
   }

   if (!get_nickname(handle, handle->fd))
   {
      RARCH_ERR("Failed to receive nickname from host.\n");
      return false;
   }

   char msg[512];
   snprintf(msg, sizeof(msg), "Connected to \"%s\"", handle->other_nick);
   msg_queue_push(g_extern.msg_queue, msg, 1, 180);
   RARCH_LOG("%s\n", msg);

   uint32_t header[4];

   if (!recv_all(handle->fd, header, sizeof(header)))
   {
      RARCH_ERR("Cannot get header from host.\n");
      return false;
   }

   size_t save_state_size = pretro_serialize_size();
   if (!bsv_parse_header(header, implementation_magic_value()))
   {
      RARCH_ERR("Received invalid BSV header from host.\n");
      return false;
   }

   void *buf = malloc(save_state_size);
   if (!buf)
      return false;

   size_t size = save_state_size;

   if (!recv_all(handle->fd, buf, size))
   {
      RARCH_ERR("Failed to receive save state from host.\n");
      free(buf);
      return false;
   }

   bool ret = true;
   if (save_state_size)
      ret = pretro_unserialize(buf, save_state_size);

   free(buf);
   return ret;
}
Пример #2
0
static bool init_playback(bsv_movie_t *handle, const char *path)
{
   handle->playback = true;
   handle->file = fopen(path, "rb");
   if (!handle->file)
   {
      RARCH_ERR("Couldn't open BSV file \"%s\" for playback.\n", path);
      return false;
   }

   uint32_t header[4] = {0};
   if (fread(header, sizeof(uint32_t), 4, handle->file) != 4)
   {
      RARCH_ERR("Couldn't read movie header.\n");
      return false;
   }

   // Compatibility with old implementation that used incorrect documentation.
   if (swap_if_little32(header[MAGIC_INDEX]) != BSV_MAGIC && swap_if_big32(header[MAGIC_INDEX]) != BSV_MAGIC)
   {
      RARCH_ERR("Movie file is not a valid BSV1 file.\n");
      return false;
   }

   if (swap_if_big32(header[CRC_INDEX]) != g_extern.cart_crc)
      RARCH_WARN("CRC32 checksum mismatch between ROM file and saved ROM checksum in replay file header; replay highly likely to desync on playback.\n");

   uint32_t state_size = swap_if_big32(header[STATE_SIZE_INDEX]);

   if (state_size)
   {
      handle->state = (uint8_t*)malloc(state_size);
      handle->state_size = state_size;
      if (!handle->state)
         return false;

      if (fread(handle->state, 1, state_size, handle->file) != state_size)
      {
         RARCH_ERR("Couldn't read state from movie.\n");
         return false;
      }

      if (pretro_serialize_size() == state_size)
         pretro_unserialize(handle->state, state_size);
      else
         RARCH_WARN("Movie format seems to have a different serializer version. Will most likely fail.\n");
   }

   handle->min_file_pos = sizeof(header) + state_size;

   return true;
}
Пример #3
0
static void netplay_post_frame_net(netplay_t *handle)
{
   handle->frame_count++;

   // Nothing to do...
   if (handle->other_frame_count == handle->read_frame_count)
      return;

   // Skip ahead if we predicted correctly. Skip until our simulation failed.
   while (handle->other_frame_count < handle->read_frame_count)
   {
      const struct delta_frame *ptr = &handle->buffer[handle->other_ptr];
      if ((ptr->simulated_input_state != ptr->real_input_state) && !ptr->used_real)
         break;
      handle->other_ptr = NEXT_PTR(handle->other_ptr);
      handle->other_frame_count++;
   }

   if (handle->other_frame_count < handle->read_frame_count)
   {
      // Replay frames
      handle->is_replay = true;
      handle->tmp_ptr = handle->other_ptr;
      handle->tmp_frame_count = handle->other_frame_count;

      pretro_unserialize(handle->buffer[handle->other_ptr].state, handle->state_size);
      bool first = true;
      while (first || (handle->tmp_ptr != handle->self_ptr))
      {
         pretro_serialize(handle->buffer[handle->tmp_ptr].state, handle->state_size);
#if defined(HAVE_THREADS) && !defined(RARCH_CONSOLE)
         lock_autosave();
#endif
         pretro_run();
#if defined(HAVE_THREADS) && !defined(RARCH_CONSOLE)
         unlock_autosave();
#endif
         handle->tmp_ptr = NEXT_PTR(handle->tmp_ptr);
         handle->tmp_frame_count++;
         first = false;
      }

      handle->other_ptr = handle->read_ptr;
      handle->other_frame_count = handle->read_frame_count;
      handle->is_replay = false;
   }
}
Пример #4
0
bool load_state(const char *path)
{
   unsigned i;
   void *buf = NULL;
   ssize_t size = read_file(path, &buf);

   RARCH_LOG("Loading state: \"%s\".\n", path);

   if (size < 0)
   {
      RARCH_ERR("Failed to load state from \"%s\".\n", path);
      return false;
   }

   bool ret = true;
   RARCH_LOG("State size: %u bytes.\n", (unsigned)size);

   struct sram_block *blocks = NULL;
   unsigned num_blocks = 0;

   if (g_settings.block_sram_overwrite && g_extern.savefiles
         && g_extern.savefiles->size)
   {
      RARCH_LOG("Blocking SRAM overwrite.\n");
      blocks = (struct sram_block*)
         calloc(g_extern.savefiles->size, sizeof(*blocks));

      if (blocks)
      {
         num_blocks = g_extern.savefiles->size;
         for (i = 0; i < num_blocks; i++)
            blocks[i].type = g_extern.savefiles->elems[i].attr.i;
      }
   }

   for (i = 0; i < num_blocks; i++)
      blocks[i].size = pretro_get_memory_size(blocks[i].type);

   for (i = 0; i < num_blocks; i++)
      if (blocks[i].size)
         blocks[i].data = malloc(blocks[i].size);

   /* Backup current SRAM which is overwritten by unserialize. */
   for (i = 0; i < num_blocks; i++)
   {
      if (blocks[i].data)
      {
         const void *ptr = pretro_get_memory_data(blocks[i].type);
         if (ptr)
            memcpy(blocks[i].data, ptr, blocks[i].size);
      }
   }

   ret = pretro_unserialize(buf, size);

   /* Flush back. */
   for (i = 0; i < num_blocks; i++)
   {
      if (blocks[i].data)
      {
         void *ptr = pretro_get_memory_data(blocks[i].type);
         if (ptr)
            memcpy(ptr, blocks[i].data, blocks[i].size);
      }
   }

   for (i = 0; i < num_blocks; i++)
      free(blocks[i].data);
   free(blocks);
   return ret;
}
Пример #5
0
bool load_state(const char *path)
{
   unsigned i;
   void *buf = NULL;
   ssize_t size = read_file(path, &buf);

   RARCH_LOG("Loading state: \"%s\".\n", path);

   if (size < 0)
   {
      RARCH_ERR("Failed to load state from \"%s\".\n", path);
      return false;
   }

   bool ret = true;
   RARCH_LOG("State size: %u bytes.\n", (unsigned)size);

   void *block_buf[2] = {NULL, NULL};
   int block_type[2] = {-1, -1};
   size_t block_size[2] = {0};

   if (g_settings.block_sram_overwrite)
   {
      RARCH_LOG("Blocking SRAM overwrite.\n");
      switch (g_extern.game_type)
      {
         case RARCH_CART_NORMAL:
            block_type[0] = RETRO_MEMORY_SAVE_RAM;
            block_type[1] = RETRO_MEMORY_RTC;
            break;

         case RARCH_CART_BSX:
         case RARCH_CART_BSX_SLOTTED:
            block_type[0] = RETRO_MEMORY_SNES_BSX_RAM;
            block_type[1] = RETRO_MEMORY_SNES_BSX_PRAM;
            break;

         case RARCH_CART_SUFAMI:
            block_type[0] = RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM;
            block_type[1] = RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM;
            break;

         case RARCH_CART_SGB:
            block_type[0] = RETRO_MEMORY_SNES_GAME_BOY_RAM;
            block_type[1] = RETRO_MEMORY_SNES_GAME_BOY_RTC;
            break;
      }
   }

   for (i = 0; i < 2; i++)
      if (block_type[i] != -1)
         block_size[i] = pretro_get_memory_size(block_type[i]);

   for (i = 0; i < 2; i++)
      if (block_size[i])
         block_buf[i] = malloc(block_size[i]);

   // Backup current SRAM which is overwritten by unserialize.
   for (i = 0; i < 2; i++)
   {
      if (block_buf[i])
      {
         const void *ptr = pretro_get_memory_data(block_type[i]);
         if (ptr)
            memcpy(block_buf[i], ptr, block_size[i]);
      }
   }

   ret = pretro_unserialize(buf, size);

   // Flush back :D
   for (i = 0; i < 2 && ret; i++)
   {
      if (block_buf[i])
      {
         void *ptr = pretro_get_memory_data(block_type[i]);
         if (ptr)
            memcpy(ptr, block_buf[i], block_size[i]);
      }
   }

   for (i = 0; i < 2; i++)
      if (block_buf[i])
         free(block_buf[i]);

   free(buf);
   return ret;
}
Пример #6
0
/**
 * load_state:
 * @path      : path that state will be loaded from.
 *
 * Load a state from disk to memory.
 *
 * Returns: true if successful, false otherwise.
 **/
bool load_state(const char *path)
{
   unsigned i;
   ssize_t size;
   unsigned num_blocks       = 0;
   void *buf                 = NULL;
   struct sram_block *blocks = NULL;
   settings_t *settings      = config_get_ptr();
   global_t *global          = global_get_ptr();
   bool ret                  = read_file(path, &buf, &size);

   RARCH_LOG("%s: \"%s\".\n",
         msg_hash_to_str(MSG_LOADING_STATE),
         path);

   if (!ret || size < 0)
   {
      RARCH_ERR("%s \"%s\".\n",
            msg_hash_to_str(MSG_FAILED_TO_LOAD_STATE),
            path);
      return false;
   }

   RARCH_LOG("%s: %u %s.\n",
         msg_hash_to_str(MSG_STATE_SIZE),
         (unsigned)size,
         msg_hash_to_str(MSG_BYTES));

   if (settings->block_sram_overwrite && global->savefiles
         && global->savefiles->size)
   {
      RARCH_LOG("%s.\n",
            msg_hash_to_str(MSG_BLOCKING_SRAM_OVERWRITE));
      blocks = (struct sram_block*)
         calloc(global->savefiles->size, sizeof(*blocks));

      if (blocks)
      {
         num_blocks = global->savefiles->size;
         for (i = 0; i < num_blocks; i++)
            blocks[i].type = global->savefiles->elems[i].attr.i;
      }
   }

   for (i = 0; i < num_blocks; i++)
      blocks[i].size = pretro_get_memory_size(blocks[i].type);

   for (i = 0; i < num_blocks; i++)
      if (blocks[i].size)
         blocks[i].data = malloc(blocks[i].size);

   /* Backup current SRAM which is overwritten by unserialize. */
   for (i = 0; i < num_blocks; i++)
   {
      if (blocks[i].data)
      {
         const void *ptr = pretro_get_memory_data(blocks[i].type);
         if (ptr)
            memcpy(blocks[i].data, ptr, blocks[i].size);
      }
   }

   ret = pretro_unserialize(buf, size);

   /* Flush back. */
   for (i = 0; i < num_blocks; i++)
   {
      if (blocks[i].data)
      {
         void *ptr = pretro_get_memory_data(blocks[i].type);
         if (ptr)
            memcpy(ptr, blocks[i].data, blocks[i].size);
      }
   }

   for (i = 0; i < num_blocks; i++)
      free(blocks[i].data);
   free(blocks);
   free(buf);
   return ret;
}
Пример #7
0
/**
 * check_rewind:
 * @pressed              : was rewind key pressed or held?
 *
 * Checks if rewind toggle/hold was being pressed and/or held.
 **/
static void check_rewind(settings_t *settings,
      global_t *global, runloop_t *runloop, bool pressed)
{
   static bool first = true;

   if (global->rewind.frame_is_reverse)
   {
      audio_driver_frame_is_reverse();
      global->rewind.frame_is_reverse = false;
   }

   if (first)
   {
      first = false;
      return;
   }

   if (!global->rewind.state)
      return;

   if (pressed)
   {
      const void *buf    = NULL;

      if (state_manager_pop(global->rewind.state, &buf))
      {
         global->rewind.frame_is_reverse = true;
         audio_driver_setup_rewind();

         rarch_main_msg_queue_push_new(MSG_REWINDING, 0,
               runloop->is_paused ? 1 : 30, true);
         pretro_unserialize(buf, global->rewind.size);

         if (global->bsv.movie)
            bsv_movie_frame_rewind(global->bsv.movie);
      }
      else
         rarch_main_msg_queue_push_new(MSG_REWIND_REACHED_END,
               0, 30, true);
   }
   else
   {
      static unsigned cnt      = 0;

      cnt = (cnt + 1) % (settings->rewind_granularity ?
            settings->rewind_granularity : 1); /* Avoid possible SIGFPE. */

      if ((cnt == 0) || global->bsv.movie)
      {
         void *state = NULL;
         state_manager_push_where(global->rewind.state, &state);

         RARCH_PERFORMANCE_INIT(rewind_serialize);
         RARCH_PERFORMANCE_START(rewind_serialize);
         pretro_serialize(state, global->rewind.size);
         RARCH_PERFORMANCE_STOP(rewind_serialize);

         state_manager_push_do(global->rewind.state);
      }
   }

   retro_set_rewind_callbacks();
}
Пример #8
0
static void check_rewind(bool pressed)
{
   static bool first = true;

   if (g_extern.frame_is_reverse)
   {
      /* We just rewound. Flush rewind audio buffer. */
      retro_flush_audio(g_extern.audio_data.rewind_buf
            + g_extern.audio_data.rewind_ptr,
            g_extern.audio_data.rewind_size - g_extern.audio_data.rewind_ptr);

      g_extern.frame_is_reverse = false;
   }

   if (first)
   {
      first = false;
      return;
   }

   if (!g_extern.state_manager)
      return;

   if (pressed)
   {
      const void *buf = NULL;

      msg_queue_clear(g_extern.msg_queue);
      if (state_manager_pop(g_extern.state_manager, &buf))
      {
         g_extern.frame_is_reverse = true;
         setup_rewind_audio();

         msg_queue_push(g_extern.msg_queue, RETRO_MSG_REWINDING, 0,
               g_extern.is_paused ? 1 : 30);
         pretro_unserialize(buf, g_extern.state_size);

         if (g_extern.bsv.movie)
            bsv_movie_frame_rewind(g_extern.bsv.movie);
      }
      else
         msg_queue_push(g_extern.msg_queue,
               RETRO_MSG_REWIND_REACHED_END, 0, 30);
   }
   else
   {
      static unsigned cnt = 0;

      cnt = (cnt + 1) % (g_settings.rewind_granularity ?
            g_settings.rewind_granularity : 1); /* Avoid possible SIGFPE. */

      if ((cnt == 0) || g_extern.bsv.movie)
      {
         void *state = NULL;
         state_manager_push_where(g_extern.state_manager, &state);

         RARCH_PERFORMANCE_INIT(rewind_serialize);
         RARCH_PERFORMANCE_START(rewind_serialize);
         pretro_serialize(state, g_extern.state_size);
         RARCH_PERFORMANCE_STOP(rewind_serialize);

         state_manager_push_do(g_extern.state_manager);
      }
   }

   retro_set_rewind_callbacks();
}