bool ReGBA_SaveSettings(char *cfg_name, bool PerGame) { char fname[MAX_PATH + 1]; if (strlen(main_path) + strlen(cfg_name) + 5 /* / .cfg */ > MAX_PATH) { ReGBA_Trace("E: Somehow you hit the filename size limit :o\n"); return false; } sprintf(fname, "%s/%s.cfg", main_path, cfg_name); FILE_TAG_TYPE fd; ReGBA_ProgressInitialise(PerGame ? FILE_ACTION_SAVE_GAME_SETTINGS : FILE_ACTION_SAVE_GLOBAL_SETTINGS); FILE_OPEN(fd, fname, WRITE); if(FILE_CHECK_VALID(fd)) { Menu_SaveIterateRecurse(fd, PerGame ? MainMenu.AlternateVersion : &MainMenu); ReGBA_ProgressUpdate(1, 1); ReGBA_ProgressFinalise(); } else { ReGBA_Trace("E: Couldn't open file %s for writing.\n", fname); ReGBA_ProgressFinalise(); return false; } FILE_CLOSE(fd); return true; }
s32 save_config_file() { u8 config_path[512]; sprintf(config_path, "%s/%s", main_path, GPSP_CONFIG_FILENAME); FILE_OPEN(config_file, config_path, write); save_game_config_file(); if(FILE_CHECK_VALID(config_file)) { u32 file_options[23]; u32 i; file_options[0] = screen_scale; file_options[1] = screen_filter; file_options[2] = global_enable_audio; file_options[3] = audio_buffer_size_number; file_options[5] = global_enable_analog; file_options[6] = analog_sensitivity_level; for(i = 0; i < 16; i++) { file_options[7 + i] = gamepad_config_map[i]; } FILE_WRITE_ARRAY(config_file, file_options); FILE_CLOSE(config_file); return 0; } return -1; }
s32 save_game_config_file() { u8 game_config_filename[512]; u32 i; change_ext(gamepak_filename, game_config_filename, ".cfg"); FILE_OPEN(game_config_file, game_config_filename, write); if(FILE_CHECK_VALID(game_config_file)) { u32 file_options[14]; file_options[0] = current_frameskip_type; file_options[1] = frameskip_value; file_options[2] = random_skip; file_options[3] = clock_speed; for(i = 0; i < 10; i++) { file_options[4 + i] = cheats[i].cheat_active; } FILE_WRITE_ARRAY(game_config_file, file_options); FILE_CLOSE(game_config_file); return 0; } return -1; }
s32 load_config_file() { u8 config_path[512]; sprintf(config_path, "%s/%s", main_path, GPSP_CONFIG_FILENAME); FILE_OPEN(config_file, config_path, read); if(FILE_CHECK_VALID(config_file)) { u32 file_size = FILE_LENGTH(config_file); // Sanity check: File size must be the right size if(file_size == 92) { u32 file_options[file_size / 4]; u32 i; s32 menu_button = -1; file_read_array(config_file, file_options); screen_scale = file_options[0] % 2; screen_filter = file_options[1] % 2; global_enable_audio = file_options[2] % 2; #ifdef ZAURUS audio_buffer_size_number = file_options[3] % 4; #else audio_buffer_size_number = file_options[3] % 11; #endif global_enable_analog = file_options[5] % 2; analog_sensitivity_level = file_options[6] % 8; // Sanity check: Make sure there's a MENU or FRAMESKIP // key, if not assign to triangle for(i = 0; i < 16; i++) { gamepad_config_map[i] = file_options[7 + i] % (BUTTON_ID_NONE + 1); if(gamepad_config_map[i] == BUTTON_ID_MENU) { menu_button = i; } } if(menu_button == -1) { gamepad_config_map[0] = BUTTON_ID_MENU; } } FILE_CLOSE(config_file); return 0; } return -1; }
void get_savestate_snapshot(u8 *savestate_filename) { /* Unimplemented. Need to figure out a way to show this screenshot on a * 320x240 screen first. - Neb, 2013-08-19 */ #if 0 u16 snapshot_buffer[240 * 160]; u8 savestate_timestamp_string[80]; FILE_OPEN(savestate_file, savestate_filename, read); if(FILE_CHECK_VALID(savestate_file)) { u8 weekday_strings[7][11] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; time_t savestate_time_flat; struct tm *current_time; file_read_array(savestate_file, snapshot_buffer); file_read_variable(savestate_file, savestate_time_flat); file_close(savestate_file); current_time = localtime(&savestate_time_flat); sprintf(savestate_timestamp_string, "%s %02d/%02d/%04d %02d:%02d:%02d ", weekday_strings[current_time->tm_wday], current_time->tm_mon + 1, current_time->tm_mday, current_time->tm_year + 1900, current_time->tm_hour, current_time->tm_min, current_time->tm_sec); savestate_timestamp_string[40] = 0; print_string(savestate_timestamp_string, COLOR_HELP_TEXT, COLOR_BG, 10, 40); } else { memset(snapshot_buffer, 0, 240 * 160 * 2); print_string_ext("No savestate exists for this slot.", 0xFFFF, 0x0000, 15, 75, snapshot_buffer, 240, 0); print_string("---------- --/--/---- --:--:-- ", COLOR_HELP_TEXT, COLOR_BG, 10, 40); } #endif }
// ZIPで圧縮されたRONのロード // 返り値:-2=一時ファイルを作成/-1=エラー/その他=ROMのサイズ // もし、ROMのサイズ>ROMバッファのサイズ の場合は一時ファイルを作成 s32 load_file_zip(char *filename) { struct SZIPFileHeader data; char tmp[MAX_PATH]; s32 retval = -1; u8 *buffer = NULL; u8 *cbuffer; char *ext; FILE_ID fd; FILE_ID tmp_fd; u32 zip_buffer_size; u32 write_tmp_flag = NO; u32 use_vram; use_vram = NO; zip_buffer_size = 16 * 1024 * 1024; cbuffer = malloc(zip_buffer_size); while(cbuffer == NULL) { zip_buffer_size -= (256 * 1024); if(zip_buffer_size == 0) break; cbuffer = malloc(zip_buffer_size); } if(zip_buffer_size == 0) { use_vram = YES; zip_buffer_size = ZIP_BUFFER_SIZE; cbuffer = (u8 *)UNIVERSAL_VRAM_ADDR; // 汎用フレームバッファを使用 } chdir(rom_path); FILE_OPEN(fd, filename, READ); if(!FILE_CHECK_VALID(fd)) return -1; { FILE_READ(fd, &data, sizeof(struct SZIPFileHeader)); // EDIT: Check if this is a zip file without worrying about endian // It checks for the following: 0x50 0x4B 0x03 0x04 (PK..) // Used to be: if(data.Sig != 0x04034b50) break; if( data.Sig[0] != 0x50 || data.Sig[1] != 0x4B || data.Sig[2] != 0x03 || data.Sig[3] != 0x04 ) { goto outcode; } FILE_READ(fd, tmp, data.FilenameLength); tmp[data.FilenameLength] = 0; // end string if(data.ExtraFieldLength) FILE_SEEK(fd, data.ExtraFieldLength, SEEK_CUR); if(data.GeneralBitFlag & 0x0008) { FILE_READ(fd, &data.DataDescriptor, sizeof(struct SZIPFileDataDescriptor)); } ext = strrchr(tmp, '.') + 1; // file is too big if(data.DataDescriptor.UncompressedSize > gamepak_ram_buffer_size) { write_tmp_flag = YES; // テンポラリを使用するフラグをONに FILE_OPEN(tmp_fd, ZIP_TMP, WRITE); } else write_tmp_flag = NO; if(!strncasecmp(ext, "bin", 3) || !strncasecmp(ext, "gba", 3)) { buffer = gamepak_rom; // ok, found switch(data.CompressionMethod) { case 0: //無圧縮 retval = data.DataDescriptor.UncompressedSize; FILE_READ(fd, buffer, retval); goto outcode; case 8: //圧縮 { z_stream stream = {0}; s32 err; /* * z.next_in = 入力ポインタ; * z.avail_in = 入力データの残量; * z.next_out = 出力ポインタ; * z.avail_out = 出力バッファの残量; */ stream.next_in = (Bytef*)cbuffer; stream.avail_in = (u32)zip_buffer_size; stream.next_out = (Bytef*)buffer; if(write_tmp_flag == NO) { stream.avail_out = data.DataDescriptor.UncompressedSize; retval = (u32)data.DataDescriptor.UncompressedSize; } else { stream.avail_out = gamepak_ram_buffer_size; retval = -2; } stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; stream.opaque = (voidpf)0; err = inflateInit2(&stream, -MAX_WBITS); FILE_READ(fd, cbuffer, zip_buffer_size); sceKernelDcacheWritebackAll(); if(err == Z_OK) { while(err != Z_STREAM_END) { err = inflate(&stream, Z_SYNC_FLUSH); if(err == Z_BUF_ERROR) { stream.avail_in = (u32)zip_buffer_size; stream.next_in = (Bytef*)cbuffer; FILE_READ(fd, cbuffer, zip_buffer_size); sceKernelDcacheWritebackAll(); } if((write_tmp_flag == YES) && (stream.avail_out == 0)) /* 出力バッファが尽きれば */ { FILE_WRITE(tmp_fd, buffer, gamepak_ram_buffer_size); stream.next_out = buffer; /* 出力ポインタを元に戻す */ stream.avail_out = gamepak_ram_buffer_size; /* 出力バッファ残量を元に戻す */ } } if((write_tmp_flag == YES) && ((gamepak_ram_buffer_size - stream.avail_out) != 0)) FILE_WRITE(tmp_fd, buffer, gamepak_ram_buffer_size - stream.avail_out); err = Z_OK; inflateEnd(&stream); } goto outcode; } } } } outcode: FILE_CLOSE(fd); if(write_tmp_flag == YES) FILE_CLOSE(tmp_fd); if(use_vram == NO) free(cbuffer); chdir(main_path); return retval; }
void ReGBA_LoadSettings(char *cfg_name, bool PerGame) { char fname[MAX_PATH + 1]; if (strlen(main_path) + strlen(cfg_name) + 5 /* / .cfg */ > MAX_PATH) { ReGBA_Trace("E: Somehow you hit the filename size limit :o\n"); return; } sprintf(fname, "%s/%s.cfg", main_path, cfg_name); FILE_TAG_TYPE fd; ReGBA_ProgressInitialise(PerGame ? FILE_ACTION_LOAD_GAME_SETTINGS : FILE_ACTION_LOAD_GLOBAL_SETTINGS); FILE_OPEN(fd, fname, READ); if(FILE_CHECK_VALID(fd)) { char line[257]; while(fgets(line, 256, fd)) { line[256] = '\0'; char* opt = NULL; char* arg = NULL; char* cur = line; // Find the start of the option name. while (*cur == ' ' || *cur == '\t') cur++; // Now find where it ends. while (*cur && !(*cur == ' ' || *cur == '\t' || *cur == '=')) { if (*cur == '#') continue; else if (opt == NULL) opt = cur; cur++; } if (opt == NULL) continue; bool WasEquals = *cur == '='; *cur++ = '\0'; if (!WasEquals) { // Skip all whitespace before =. while (*cur == ' ' || *cur == '\t') cur++; if (*cur != '=') continue; cur++; } // Find the start of the option argument. while (*cur == ' ' || *cur == '\t') cur++; // Now find where it ends. while (*cur) { if (*cur == '#') { *cur = '\0'; break; } else if (arg == NULL) arg = cur; cur++; } if (arg == NULL) continue; cur--; while (*cur == ' ' || *cur == '\t' || *cur == '\n' || *cur == '\r') { *cur = '\0'; cur--; } struct MenuEntry* entry = Menu_FindByPersistentName(PerGame ? MainMenu.AlternateVersion : &MainMenu, opt); if (entry == NULL) { ReGBA_Trace("W: Option '%s' not found; ignored", opt); } else { MenuPersistenceFunction LoadFunction = entry->LoadFunction; if (LoadFunction == NULL) LoadFunction = &DefaultLoadFunction; (*LoadFunction)(entry, arg); } } ReGBA_ProgressUpdate(1, 1); } else { ReGBA_Trace("W: Couldn't open file %s for loading.\n", fname); } FixUpSettings(); ReGBA_ProgressFinalise(); }