Exemple #1
0
static uint32_t *bsv_header_generate(size_t *size, uint32_t magic)
{
   uint32_t bsv_header[4] = {0};
   size_t serialize_size = pretro_serialize_size();
   size_t header_size = sizeof(bsv_header) + serialize_size;
   *size = header_size;

   uint32_t *header = (uint32_t*)malloc(header_size);
   if (!header)
      return NULL;

   bsv_header[MAGIC_INDEX] = swap_if_little32(BSV_MAGIC);
   bsv_header[SERIALIZER_INDEX] = swap_if_big32(magic);
   bsv_header[CRC_INDEX] = swap_if_big32(g_extern.cart_crc);
   bsv_header[STATE_SIZE_INDEX] = swap_if_big32(serialize_size);

   if (serialize_size && !pretro_serialize(header + 4, serialize_size))
   {
      free(header);
      return NULL;
   }

   memcpy(header, bsv_header, sizeof(bsv_header));
   return header;
}
Exemple #2
0
bool save_state(const char *path)
{
   RARCH_LOG("Saving state: \"%s\".\n", path);
   size_t size = pretro_serialize_size();
   if (size == 0)
      return false;

   void *data = malloc(size);
   if (!data)
   {
      RARCH_ERR("Failed to allocate memory for save state buffer.\n");
      return false;
   }

   RARCH_LOG("State size: %d bytes.\n", (int)size);
   bool ret = pretro_serialize(data, size);
   if (ret)
      ret = write_file(path, data, size);

   if (!ret)
      RARCH_ERR("Failed to save state to \"%s\".\n", path);

   free(data);
   return ret;
}
Exemple #3
0
static void netplay_pre_frame_net(netplay_t *handle)
{
   pretro_serialize(handle->buffer[handle->self_ptr].state, handle->state_size);
   handle->can_poll = true;

   input_poll_net();
}
Exemple #4
0
void bsv_movie_frame_rewind(bsv_movie_t *handle)
{
   handle->did_rewind = true;

   // If we're at the beginning ... :)
   if ((handle->frame_ptr <= 1) && (handle->frame_pos[0] == handle->min_file_pos))
   {
      handle->frame_ptr = 0;
      fseek(handle->file, handle->min_file_pos, SEEK_SET);
   }
   else
   {
      // First time rewind is performed, the old frame is simply replayed.
      // However, playing back that frame caused us to read data, and push data to the ring buffer.
      // Sucessively rewinding frames, we need to rewind past the read data, plus another.
      handle->frame_ptr = (handle->frame_ptr - (handle->first_rewind ? 1 : 2)) & handle->frame_mask;
      fseek(handle->file, handle->frame_pos[handle->frame_ptr], SEEK_SET);
   }

   // We rewound past the beginning. :O
   if (ftell(handle->file) <= (long)handle->min_file_pos)
   {
      // If recording, we simply reset the starting point. Nice and easy.
      if (!handle->playback)
      {
         fseek(handle->file, 4 * sizeof(uint32_t), SEEK_SET);
         pretro_serialize(handle->state, handle->state_size);
         fwrite(handle->state, 1, handle->state_size, handle->file);
      }
      else
         fseek(handle->file, handle->min_file_pos, SEEK_SET);
   }
}
Exemple #5
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;
   }
}
Exemple #6
0
/**
 * save_state:
 * @path      : path of saved state that shall be written to.
 *
 * Save a state from memory to disk.
 *
 * Returns: true if successful, false otherwise.
 **/
bool save_state(const char *path)
{
   bool ret    = false;
   void *data  = NULL;
   size_t size = pretro_serialize_size();

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

   if (size == 0)
      return false;

   data = malloc(size);

   if (!data)
      return false;

   RARCH_LOG("%s: %d %s.\n", 
         msg_hash_to_str(MSG_STATE_SIZE),
         (int)size,
         msg_hash_to_str(MSG_BYTES));
   ret = pretro_serialize(data, size);

   if (ret)
      ret = retro_write_file(path, data, size);

   if (!ret)
      RARCH_ERR("%s \"%s\".\n", 
            msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO),
            path);

   free(data);

   return ret;
}
Exemple #7
0
static bool init_record(bsv_movie_t *handle, const char *path)
{
   handle->file = fopen(path, "wb");
   if (!handle->file)
   {
      RARCH_ERR("Couldn't open BSV \"%s\" for recording.\n", path);
      return false;
   }

   uint32_t header[4] = {0};

   // This value is supposed to show up as BSV1 in a HEX editor, big-endian.
   header[MAGIC_INDEX] = swap_if_little32(BSV_MAGIC);

   header[CRC_INDEX] = swap_if_big32(g_extern.cart_crc);

   uint32_t state_size = pretro_serialize_size();

   header[STATE_SIZE_INDEX] = swap_if_big32(state_size);
   fwrite(header, 4, sizeof(uint32_t), handle->file);

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

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

      pretro_serialize(handle->state, state_size);
      fwrite(handle->state, 1, state_size, handle->file);
   }

   return true;
}
Exemple #8
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();
}
Exemple #9
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();
}