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; }
uint32_t *np_bsv_header_generate(size_t *size, uint32_t magic) { uint32_t *header, bsv_header[4] = {0}; size_t serialize_size = core.retro_serialize_size(); size_t header_size = sizeof(bsv_header) + serialize_size; global_t *global = global_get_ptr(); *size = header_size; 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(global->content_crc); bsv_header[STATE_SIZE_INDEX] = swap_if_big32(serialize_size); if (serialize_size && !core.retro_serialize(header + 4, serialize_size)) { free(header); return NULL; } memcpy(header, bsv_header, sizeof(bsv_header)); return header; }
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; }
static bool init_playback(bsv_movie_t *handle, const char *path) { uint32_t state_size; uint32_t header[4] = {0}; global_t *global = global_get_ptr(); 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; } 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]) != global->content_crc) RARCH_WARN("CRC32 checksum mismatch between content file and saved content checksum in replay file header; replay highly likely to desync on playback.\n"); 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 (core.retro_serialize_size() == state_size) core.retro_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; }
static int task_database_iterate_crc_lookup( database_state_handle_t *db_state, database_info_handle_t *db, const char *zip_entry) { if (!db_state->list || (unsigned)db_state->list_index == (unsigned)db_state->list->size) return database_info_list_iterate_end_no_match(db_state); if (db_state->entry_index == 0) { char query[50] = {0}; snprintf(query, sizeof(query), "{crc:or(b\"%08X\",b\"%08X\")}", swap_if_big32(db_state->crc), swap_if_big32(db_state->zip_crc)); database_info_list_iterate_new(db_state, query); } if (db_state->info) { database_info_t *db_info_entry = &db_state->info->list[db_state->entry_index]; if (db_info_entry && db_info_entry->crc32) { #if 0 RARCH_LOG("CRC32: 0x%08X , entry CRC32: 0x%08X (%s).\n", db_state->crc, db_info_entry->crc32, db_info_entry->name); #endif if (db_state->zip_crc == db_info_entry->crc32) return database_info_list_iterate_found_match( db_state, db, NULL); if (db_state->crc == db_info_entry->crc32) return database_info_list_iterate_found_match( db_state, db, zip_entry); } } db_state->entry_index++; if (db_state->info) { if (db_state->entry_index >= db_state->info->count) return database_info_list_iterate_next(db_state); } /* If we haven't reached the end of the database list yet, * continue iterating. */ if (db_state->list_index < db_state->list->size) return 1; database_info_list_free(db_state->info); return 0; }
static bool init_record(bsv_movie_t *handle, const char *path) { retro_ctx_size_info_t info; uint32_t state_size; uint32_t header[4] = {0}; uint32_t *content_crc_ptr = NULL; handle->file = fopen(path, "wb"); if (!handle->file) { RARCH_ERR("Couldn't open BSV \"%s\" for recording.\n", path); return false; } content_ctl(CONTENT_CTL_GET_CRC, &content_crc_ptr); /* 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(*content_crc_ptr); core_ctl(CORE_CTL_RETRO_SERIALIZE_SIZE, &info); state_size = info.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) { retro_ctx_serialize_info_t serial_info; handle->state = (uint8_t*)malloc(state_size); if (!handle->state) return false; serial_info.data = handle->state; serial_info.size = state_size; core_ctl(CORE_CTL_RETRO_SERIALIZE, &serial_info); fwrite(handle->state, 1, state_size, handle->file); } return true; }
bool np_bsv_parse_header(const uint32_t *header, uint32_t magic) { retro_ctx_size_info_t info; uint32_t *content_crc_ptr; uint32_t in_crc, in_magic, in_state_size; 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; } 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; } in_crc = swap_if_big32(header[CRC_INDEX]); content_ctl(CONTENT_CTL_GET_CRC, &content_crc_ptr); if (in_crc != *content_crc_ptr) { RARCH_ERR("CRC32 mismatch, got 0x%x, expected 0x%x.\n", in_crc, *content_crc_ptr); return false; } core_ctl(CORE_CTL_RETRO_SERIALIZE_SIZE, &info); in_state_size = swap_if_big32(header[STATE_SIZE_INDEX]); if (in_state_size != info.size) { RARCH_ERR("Serialization size mismatch, got 0x%x, expected 0x%x.\n", (unsigned)in_state_size, (unsigned)info.size); return false; } return true; }
bool np_bsv_parse_header(const uint32_t *header, uint32_t magic) { uint32_t in_crc, in_magic, in_state_size; uint32_t in_bsv = swap_if_little32(header[MAGIC_INDEX]); global_t *global = global_get_ptr(); if (in_bsv != BSV_MAGIC) { RARCH_ERR("BSV magic mismatch, got 0x%x, expected 0x%x.\n", in_bsv, BSV_MAGIC); return false; } 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; } in_crc = swap_if_big32(header[CRC_INDEX]); if (in_crc != global->content_crc) { RARCH_ERR("CRC32 mismatch, got 0x%x, expected 0x%x.\n", in_crc, global->content_crc); return false; } in_state_size = swap_if_big32(header[STATE_SIZE_INDEX]); if (in_state_size != core.retro_serialize_size()) { RARCH_ERR("Serialization size mismatch, got 0x%x, expected 0x%x.\n", (unsigned)in_state_size, (unsigned)core.retro_serialize_size()); return false; } return true; }
uint32_t *np_bsv_header_generate(size_t *size, uint32_t magic) { retro_ctx_serialize_info_t serial_info; retro_ctx_size_info_t info; uint32_t *content_crc_ptr; size_t serialize_size, header_size; uint32_t *header, bsv_header[4] = {0}; core_ctl(CORE_CTL_RETRO_SERIALIZE_SIZE, &info); serialize_size = info.size; header_size = sizeof(bsv_header) + serialize_size; *size = header_size; header = (uint32_t*)malloc(header_size); if (!header) goto error; content_ctl(CONTENT_CTL_GET_CRC, &content_crc_ptr); bsv_header[MAGIC_INDEX] = swap_if_little32(BSV_MAGIC); bsv_header[SERIALIZER_INDEX] = swap_if_big32(magic); bsv_header[CRC_INDEX] = swap_if_big32(*content_crc_ptr); bsv_header[STATE_SIZE_INDEX] = swap_if_big32(serialize_size); serial_info.data = header + 4; serial_info.size = serialize_size; if (serialize_size && !core_ctl(CORE_CTL_RETRO_SERIALIZE, &serial_info)) goto error; memcpy(header, bsv_header, sizeof(bsv_header)); return header; error: if (header) free(header); return NULL; }
static bool init_record(bsv_movie_t *handle, const char *path) { uint32_t state_size; uint32_t header[4] = {0}; global_t *global = global_get_ptr(); handle->file = fopen(path, "wb"); if (!handle->file) { RARCH_ERR("Couldn't open BSV \"%s\" for recording.\n", path); return false; } /* 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(global->content_crc); state_size = core.retro_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; core.retro_serialize(handle->state, state_size); fwrite(handle->state, 1, state_size, handle->file); } return true; }
static int task_database_iterate_crc_lookup( database_state_handle_t *db_state, database_info_handle_t *db, const char *name, const char *archive_entry) { if (!db_state->list || (unsigned)db_state->list_index == (unsigned)db_state->list->size) return database_info_list_iterate_end_no_match(db_state); if (db_state->entry_index == 0) { bool db_supports_content; bool unsupported_content; char query[50]; query[0] = '\0'; db_supports_content = core_info_database_supports_content_path(db_state->list->elems[db_state->list_index].data, name); unsupported_content = core_info_unsupported_content_path(name); /* don't scan files that can't be in this database */ if(!db_supports_content && !unsupported_content) return database_info_list_iterate_next(db_state); snprintf(query, sizeof(query), "{crc:or(b\"%08X\",b\"%08X\")}", swap_if_big32(db_state->crc), swap_if_big32(db_state->archive_crc)); database_info_list_iterate_new(db_state, query); } if (db_state->info) { database_info_t *db_info_entry = &db_state->info->list[db_state->entry_index]; if (db_info_entry && db_info_entry->crc32) { #if 0 RARCH_LOG("CRC32: 0x%08X , entry CRC32: 0x%08X (%s).\n", db_state->crc, db_info_entry->crc32, db_info_entry->name); #endif if (db_state->archive_crc == db_info_entry->crc32) return database_info_list_iterate_found_match( db_state, db, NULL); if (db_state->crc == db_info_entry->crc32) return database_info_list_iterate_found_match( db_state, db, archive_entry); } } db_state->entry_index++; if (db_state->info) { if (db_state->entry_index >= db_state->info->count) return database_info_list_iterate_next(db_state); } /* If we haven't reached the end of the database list yet, * continue iterating. */ if (db_state->list_index < db_state->list->size) return 1; database_info_list_free(db_state->info); if (db_state->info) free(db_state->info); return 0; }
static bool init_playback(bsv_movie_t *handle, const char *path) { uint32_t state_size; uint32_t *content_crc_ptr = NULL; uint32_t header[4] = {0}; 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; } 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; } content_ctl(CONTENT_CTL_GET_CRC, &content_crc_ptr); if (swap_if_big32(header[CRC_INDEX]) != *content_crc_ptr) RARCH_WARN("CRC32 checksum mismatch between content file and saved content checksum in replay file header; replay highly likely to desync on playback.\n"); state_size = swap_if_big32(header[STATE_SIZE_INDEX]); if (state_size) { retro_ctx_serialize_info_t serial_info; retro_ctx_size_info_t info; 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; } core_ctl(CORE_CTL_RETRO_SERIALIZE_SIZE, &info); if (info.size == state_size) { serial_info.data_const = handle->state; serial_info.size = state_size; core_ctl(CORE_CTL_RETRO_UNSERIALIZE, &serial_info); } 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; }