Пример #1
0
static bool bsv_parse_header(const uint32_t *header, uint32_t magic)
{
   uint32_t in_bsv = swap_if_little32(header[MAGIC_INDEX]);
   if (in_bsv != BSV_MAGIC)
   {
      RARCH_ERR("BSV magic mismatch, got 0x%x, expected 0x%x.\n",
            in_bsv, BSV_MAGIC);
      return false;
   }

   uint32_t in_magic = swap_if_big32(header[SERIALIZER_INDEX]);
   if (in_magic != magic)
   {
      RARCH_ERR("Magic mismatch, got 0x%x, expected 0x%x.\n", in_magic, magic);
      return false;
   }

   uint32_t in_crc = swap_if_big32(header[CRC_INDEX]);
   if (in_crc != g_extern.cart_crc)
   {
      RARCH_ERR("CRC32 mismatch, got 0x%x, expected 0x%x.\n", in_crc, g_extern.cart_crc);
      return false;
   }

   uint32_t in_state_size = swap_if_big32(header[STATE_SIZE_INDEX]);
   if (in_state_size != pretro_serialize_size())
   {
      RARCH_ERR("Serialization size mismatch, got 0x%x, expected 0x%x.\n",
            (unsigned)in_state_size, (unsigned)pretro_serialize_size());
      return false;
   }

   return true;
}
Пример #2
0
static void event_main_state(unsigned cmd)
{
   char path[PATH_MAX_LENGTH] = {0};
   char msg[PATH_MAX_LENGTH]  = {0};
   global_t *global           = global_get_ptr();
   settings_t *settings       = config_get_ptr();

   if (settings->state_slot > 0)
      snprintf(path, sizeof(path), "%s%d",
            global->savestate_name, settings->state_slot);
   else if (settings->state_slot < 0)
      fill_pathname_join_delim(path, global->savestate_name, "auto", '.', sizeof(path));
   else
      strlcpy(path, global->savestate_name, sizeof(path));

   if (pretro_serialize_size())
   {
      if (cmd == EVENT_CMD_SAVE_STATE)
         event_save_state(path, msg, sizeof(msg));
      else if (cmd == EVENT_CMD_LOAD_STATE)
         event_load_state(path, msg, sizeof(msg));
   }
   else
      strlcpy(msg, "Core does not support save states.", sizeof(msg));

   rarch_main_msg_queue_push(msg, 2, 180, true);
   RARCH_LOG("%s\n", msg);
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
0
static void event_main_state(unsigned cmd)
{
   char path[PATH_MAX_LENGTH] = {0};
   char msg[PATH_MAX_LENGTH]  = {0};
   global_t *global           = global_get_ptr();
   settings_t *settings       = config_get_ptr();

   if (settings->state_slot > 0)
      snprintf(path, sizeof(path), "%s%d",
            global->name.savestate, settings->state_slot);
   else if (settings->state_slot < 0)
      fill_pathname_join_delim(path,
            global->name.savestate, "auto", '.', sizeof(path));
   else
      strlcpy(path, global->name.savestate, sizeof(path));

   if (pretro_serialize_size())
   {
      switch (cmd)
      {
         case EVENT_CMD_SAVE_STATE:
            event_save_state(path, msg, sizeof(msg));
            break;
         case EVENT_CMD_LOAD_STATE:
            event_load_state(path, msg, sizeof(msg));
            break;
      }
   }
   else
      strlcpy(msg, msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_SAVESTATES), sizeof(msg));

   rarch_main_msg_queue_push(msg, 2, 180, true);
   RARCH_LOG("%s\n", msg);
}
Пример #6
0
static void init_buffers(netplay_t *handle)
{
   handle->buffer = (struct delta_frame*)calloc(handle->buffer_size, sizeof(*handle->buffer));
   handle->state_size = pretro_serialize_size();
   for (unsigned i = 0; i < handle->buffer_size; i++)
   {
      handle->buffer[i].state = malloc(handle->state_size);
      handle->buffer[i].is_simulated = true;
   }
}
Пример #7
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;
}
Пример #8
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;
}
Пример #9
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;
}
Пример #10
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;
}