static void replace_click(GtkWidget* widget, gpointer data) { GtkTreeIter iter; stateheader* sh; if (_filePath != NULL && gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), NULL, &iter)) { gtk_tree_model_get(GTK_TREE_MODEL(listStore), &iter, 1, &sh, -1); GtkWidget* dialog = gtk_file_chooser_dialog_new("Replace", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); gint res = gtk_dialog_run(GTK_DIALOG(dialog)); if (res != GTK_RESPONSE_ACCEPT) { gtk_widget_destroy(dialog); return; } char* path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); FILE* f = fopen(path, "rb"); gtk_widget_destroy(dialog); fseek(f, 0, SEEK_END); size_t len = ftell(f); if (len > 65536) len = 65536; // prevent using too much memory on opening big file by accident char* gbc_data = (char*)malloc(len); fseek(f, 0, SEEK_SET); size_t total_bytes_read = 0; while (total_bytes_read < len) { size_t bytes_read = fread(gbc_data, 1, len - total_bytes_read, f); total_bytes_read += bytes_read; if (bytes_read <= 0) { error_msg("Could only read %lu bytes from %s", (unsigned long)total_bytes_read, path); free(gbc_data); g_free(path); fclose(f); return; } } g_free(path); fclose(f); // only first X bytes will be used, where X is uncompressed size of current data void* new_data = goomba_new_sav(loaded_file, sh, gbc_data, len); free(gbc_data); if (new_data == NULL) { error_msg("%s", goomba_last_error()); } else { memcpy(loaded_file, new_data, GOOMBA_COLOR_SRAM_SIZE); dirty = true; free(new_data); header_scan(); } } }
bool SaveBatteryOrState(char * filepath, int action, bool silent) { bool result = false; int offset = 0; int datasize = 0; // we need the actual size of the data written int device; if(!FindDevice(filepath, &device)) return 0; if(action == FILE_SNAPSHOT && gameScreenPngSize > 0) { char screenpath[1024]; strncpy(screenpath, filepath, 1024); screenpath[strlen(screenpath)-4] = 0; sprintf(screenpath, "%s.png", screenpath); SaveFile((char *)gameScreenPng, screenpath, gameScreenPngSize, silent); } AllocSaveBuffer(); // put VBA memory into savebuffer, sets datasize to size of memory written if(action == FILE_SRAM) { if(cartridgeType == 1) datasize = MemgbWriteBatteryFile((char *)savebuffer); else datasize = MemCPUWriteBatteryFile((char *)savebuffer); if (cartridgeType == 1) { const char* generic_goomba_error = "Cannot save SRAM in Goomba format (did not load correctly.)"; // check for goomba sram format char* old_sram = (char*)malloc(GOOMBA_COLOR_SRAM_SIZE); size_t br = LoadFile(old_sram, filepath, GOOMBA_COLOR_SRAM_SIZE, true); if (br >= GOOMBA_COLOR_SRAM_SIZE && goomba_is_sram(old_sram)) { void* cleaned = goomba_cleanup(old_sram); if (cleaned == NULL) { ErrorPrompt(generic_goomba_error); datasize = 0; } else { if (cleaned != old_sram) { free(old_sram); old_sram = (char*)cleaned; } stateheader* sh = stateheader_for(old_sram, RomTitle); if (sh == NULL) { // Game probably doesn't use SRAM datasize = 0; } else { void* new_sram = goomba_new_sav(old_sram, sh, savebuffer, datasize); if (new_sram == NULL) { ErrorPrompt(goomba_last_error()); datasize = 0; } else { memcpy(savebuffer, new_sram, GOOMBA_COLOR_SRAM_SIZE); datasize = GOOMBA_COLOR_SRAM_SIZE; free(new_sram); } } } } free(old_sram); } } else { if(emulator.emuWriteMemState((char *)savebuffer, SAVEBUFFERSIZE)) datasize = *((int *)(savebuffer+4)) + 8; } // write savebuffer into file if(datasize > 0) { offset = SaveFile(filepath, datasize, silent); if(offset > 0) { if(!silent) InfoPrompt ("Save successful"); result = true; } } else { if(!silent) InfoPrompt("No data to save!"); } FreeSaveBuffer(); return result; }
bool SaveRAM (char * filepath, bool silent) { bool retval = false; int datasize = 0; int offset = 0; int device; if(!FindDevice(filepath, &device)) return 0; if(GameInfo->type == GIT_FDS) { if(!silent) InfoPrompt("RAM saving is not available for FDS games!"); return false; } AllocSaveBuffer (); // save game save to savebuffer if(GameInfo->type == GIT_CART) datasize = WiiFCEU_GameSave(&iNESCart, 0); else if(GameInfo->type == GIT_VSUNI) datasize = WiiFCEU_GameSave(&UNIFCart, 0); if (datasize) { // Check to see if this is a PocketNES save file FILE* file = fopen(filepath, "rb"); if (file) { uint32 tag; fread(&tag, sizeof(uint32), 1, file); fclose(file); if (goomba_is_sram(&tag)) { void* gba_data = malloc(GOOMBA_COLOR_SRAM_SIZE); file = fopen(filepath, "rb"); fread(gba_data, 1, GOOMBA_COLOR_SRAM_SIZE, file); fclose(file); void* cleaned = goomba_cleanup(gba_data); if (!cleaned) { ErrorPrompt(goomba_last_error()); } else if (cleaned != gba_data) { memcpy(gba_data, cleaned, GOOMBA_COLOR_SRAM_SIZE); free(cleaned); } // Look for just one save file. If there aren't any, or there is more than one, don't read any data. const stateheader* sh1 = NULL; const stateheader* sh2 = NULL; const stateheader* sh = stateheader_first(gba_data); while (sh && stateheader_plausible(sh)) { if (little_endian_conv_16(sh->type) != GOOMBA_SRAMSAVE) {} else if (sh1 == NULL) { sh1 = sh; } else { sh2 = sh; break; } sh = stateheader_advance(sh); } if (sh1 == NULL) { ErrorPrompt("PocketNES save file has no SRAM."); datasize = 0; } else if (sh2 != NULL) { ErrorPrompt("PocketNES save file has more than one SRAM."); datasize = 0; } else { char* newdata = goomba_new_sav(gba_data, sh1, savebuffer, datasize); if (!newdata) { ErrorPrompt(goomba_last_error()); datasize = 0; } else { memcpy(savebuffer, newdata, GOOMBA_COLOR_SRAM_SIZE); datasize = GOOMBA_COLOR_SRAM_SIZE; free(newdata); } } } } } if (datasize) { offset = SaveFile(filepath, datasize, silent); if (offset > 0) { if (!silent) InfoPrompt("Save successful"); retval = true; } } else { if (!silent) InfoPrompt("No data to save!"); } FreeSaveBuffer (); return retval; }