int StrUtil::StringToInt(const String &s, int def_val) { if (!s.GetCStr()) return def_val; char *stop_ptr; int val = strtol(s.GetCStr(), &stop_ptr, 0); return (stop_ptr == s.GetCStr() + s.GetLength()) ? val : def_val; }
StrUtil::ConversionError StrUtil::StringToInt(const String &s, int &val, int def_val) { val = def_val; if (!s.GetCStr()) return StrUtil::kFailed; char *stop_ptr; errno = 0; long lval = strtol(s.GetCStr(), &stop_ptr, 0); if (stop_ptr != s.GetCStr() + s.GetLength()) return StrUtil::kFailed; if (lval > INT_MAX || lval < INT_MIN || errno == ERANGE) return StrUtil::kOutOfRange; val = (int)lval; return StrUtil::kNoError; }
void StrUtil::WriteString(const String &s, Stream *out) { size_t len = s.GetLength(); out->WriteInt32(len); if (len > 0) out->Write(s.GetCStr(), len); }
char *INIreaditem(const char *sectn, const char *entry) { Stream *fin = Common::File::OpenFileRead(filetouse); if (fin == NULL) return NULL; TextStreamReader reader(fin); //char templine[200]; char wantsect[100]; sprintf (wantsect, "[%s]", sectn); // NOTE: the string is used as a raw buffer down there; // FIXME that as soon as string class is optimized for common use String line; while (!reader.EOS()) { //fgets (templine, 199, fin); line = reader.ReadLine(); // find the section if (strnicmp (wantsect, line.GetCStr(), strlen(wantsect)) == 0) { while (!reader.EOS()) { // we're in the right section, find the entry //fgets (templine, 199, fin); line = reader.ReadLine(); if (line.IsEmpty()) continue; if (line[0] == '[') break; // Have we found the entry? if (strnicmp (line.GetCStr(), entry, strlen(entry)) == 0) { const char *pptr = &line.GetCStr()[strlen(entry)]; while ((pptr[0] == ' ') || (pptr[0] == '\t')) pptr++; if (pptr[0] == '=') { pptr++; while ((pptr[0] == ' ') || (pptr[0] == '\t')) pptr++; char *toret = (char*)malloc (strlen(pptr) + 5); strcpy (toret, pptr); return toret; } } } } } return NULL; }
bool engine_init_gfx_filters(Size &game_size, Size &screen_size, const int color_depth) { Out::FPrint("Initializing gfx filters"); if (force_gfxfilter[0]) GfxFilterRequest = force_gfxfilter; else GfxFilterRequest = usetup.gfxFilterID; Out::FPrint("Requested gfx filter: %s", GfxFilterRequest.GetCStr()); // Try to initialize gfx filter of requested name if (GfxFilterRequest.CompareNoCase("max") != 0 && initialize_graphics_filter(GfxFilterRequest, color_depth)) { // Filter found, but we must also try if the engine will be able to set // screen resolution if (!try_find_nearest_supported_mode(game_size, filter->GetScalingFactor(), screen_size, color_depth, usetup.windowed, usetup.prefer_sideborders, usetup.prefer_letterbox)) { delete filter; filter = NULL; } } // If the filter was not set for any reason, try to choose standard scaling filter // of maximal possible scaling factor if (!filter) { String filter_name; int scaling_factor; #if defined (WINDOWS_VERSION) || defined (LINUX_VERSION) scaling_factor = try_find_max_supported_uniform_scaling(game_size, screen_size, color_depth, usetup.windowed, usetup.prefer_sideborders, usetup.prefer_letterbox); if (scaling_factor == 0) #endif { screen_size = game_size; scaling_factor = 1; } filter_name.Format(scaling_factor > 1 ? "StdScale%d" : "None", scaling_factor); initialize_graphics_filter(filter_name, color_depth); } // If not suitable filter still found then return with error message if (!filter) { set_allegro_error("Failed to find acceptable graphics filter"); return false; } // On success apply filter and define game frame Out::FPrint("Applying graphics filter: %s", filter->GetFilterID()); gfxDriver->SetGraphicsFilter(filter); game_size.Width = screen_size.Width / filter->GetScalingFactor(); game_size.Height = screen_size.Height / filter->GetScalingFactor(); Out::FPrint("Chosen gfx resolution: %d x %d (%d bit), game frame: %d x %d", screen_size.Width, screen_size.Height, color_depth, game_size.Width, game_size.Height); return true; }
bool pre_create_gfx_driver(const String &gfx_driver_id) { GfxFactory = GetGfxDriverFactory(gfx_driver_id); if (!GfxFactory) { Out::FPrint("Failed to initialize %s graphics factory: %s", gfx_driver_id.GetCStr(), get_allegro_error()); return false; } Out::FPrint("Using graphics factory: %s", gfx_driver_id.GetCStr()); gfxDriver = GfxFactory->GetDriver(); if (!gfxDriver) { Out::FPrint("Failed to create graphics driver. %s", get_allegro_error()); return false; } Out::FPrint("Created graphics driver: %s", gfxDriver->GetDriverName()); return true; }
int engine_init_gfx_filters(Size &game_size, Size &screen_size, const int color_depth) { Out::FPrint("Initializing gfx filters"); if (force_gfxfilter[0]) GfxFilterRequest = force_gfxfilter; else GfxFilterRequest = usetup.gfxFilterID; Out::FPrint("Requested gfx filter: %s", GfxFilterRequest.GetCStr()); String gfxfilter; if (GfxFilterRequest.CompareNoCase("max") != 0) gfxfilter = GfxFilterRequest; const Size base_size = game_size; const bool windowed = usetup.windowed != 0; const bool enable_sideborders = usetup.enable_side_borders != 0; const bool force_letterbox = game.options[OPT_LETTERBOX] != 0; int scaling_factor = 0; if (!gfxfilter.IsEmpty()) { scaling_factor = get_scaling_from_filter_name(gfxfilter); Size found_screen_size; if (try_find_nearest_supported_mode(base_size, scaling_factor, found_screen_size, color_depth, windowed, enable_sideborders, force_letterbox)) screen_size = found_screen_size; } #if defined (WINDOWS_VERSION) || defined (LINUX_VERSION) if (screen_size.IsNull()) { Size found_screen_size; scaling_factor = try_find_max_supported_uniform_scaling(base_size, found_screen_size, color_depth, windowed, enable_sideborders, force_letterbox); if (scaling_factor > 0) { screen_size = found_screen_size; gfxfilter.Format(scaling_factor > 1 ? "StdScale%d" : "None", scaling_factor); } } #endif if (gfxfilter.IsEmpty()) { set_allegro_error("Failed to find acceptable graphics filter"); return EXIT_NORMAL; } game_size.Width = screen_size.Width / scaling_factor; game_size.Height = screen_size.Height / scaling_factor; Out::FPrint("Chosen gfx resolution: %d x %d (%d bit), game frame: %d x %d", screen_size.Width, screen_size.Height, color_depth, game_size.Width, game_size.Height); if (initialize_graphics_filter(gfxfilter, base_size.Width, base_size.Height, color_depth)) { return EXIT_NORMAL; } return RETURN_CONTINUE; }
bool create_gfx_driver(const String &gfx_driver_id) { Out::FPrint("Init gfx driver: %s", gfx_driver_id.GetCStr()); if (!pre_create_gfx_driver(gfx_driver_id)) return false; usetup.gfxDriverID = gfxDriver->GetDriverID(); gfxDriver->SetCallbackOnInit(GfxDriverOnInitCallback); gfxDriver->SetTintMethod(TintReColourise); return true; }
String find_game_data_in_directory(const String &path) { al_ffblk ff; String test_file; String first_nonstd_fn; String pattern = path; pattern.Append("/*"); if (al_findfirst(pattern, &ff, FA_ALL & ~(FA_DIREC)) != 0) return ""; // Select first found data file; files with standart names (*.ags) have // higher priority over files with custom names. do { test_file = ff.name; // Add a bit of sanity and do not parse contents of the 10k-files-large // digital sound libraries. // NOTE: we could certainly benefit from any kind of flag in file lib // that would tell us this is the main lib without extra parsing. if (test_file.CompareRightNoCase(".vox") == 0) continue; // *.ags is a standart cross-platform file pattern for AGS games, // ac2game.dat is a legacy file name for very old games, // *.exe is a MS Win executable; it is included to this case because // users often run AGS ports with Windows versions of games. bool is_std_name = test_file.CompareRightNoCase(".ags") == 0 || test_file.CompareNoCase("ac2game.dat") == 0 || test_file.CompareRightNoCase(".exe") == 0; if (is_std_name || first_nonstd_fn.IsEmpty()) { test_file.Format("%s/%s", path.GetCStr(), ff.name); if (is_main_game_file(test_file)) { if (is_std_name) { al_findclose(&ff); return test_file; } else first_nonstd_fn = test_file; } } } while(al_findnext(&ff) == 0); al_findclose(&ff); return first_nonstd_fn; }
bool initialize_graphics_filter(const String filter_id, const int color_depth) { filter = GfxFactory->SetFilter(filter_id); if (!filter) { Out::FPrint("Unable to create filter: %s", filter_id.GetCStr()); return false; } String filter_error; if (!filter->Initialize(color_depth, filter_error)) { Out::FPrint("Unable to initialize the graphics filter. Error: %s.", filter_error.GetCStr()); return false; } return true; }
// Prepends message text with current room number and running script info, then logs result void debug_script_print(const String &msg, MessageType mt) { String script_ref; ccInstance *curinst = ccInstance::GetCurrentInstance(); if (curinst != NULL) { String scriptname; if (curinst->instanceof == gamescript) scriptname = "G "; else if (curinst->instanceof == thisroom.compiled_script) scriptname = "R "; else if (curinst->instanceof == dialogScriptsScript) scriptname = "D "; else scriptname = "? "; script_ref.Format("[%s%d]", scriptname.GetCStr(), currentline); } Debug::Printf(kDbgGroup_Script, mt, "(room:%d)%s %s", displayed_room, script_ref.GetCStr(), msg.GetCStr()); }
String find_user_global_cfg_file() { String parent_dir = PathOrCurDir(platform->GetUserGlobalConfigDirectory()); return String::FromFormat("%s/%s", parent_dir.GetCStr(), DefaultConfigFileName.GetCStr()); }
String find_user_cfg_file() { String parent_dir = MakeSpecialSubDir(PathOrCurDir(platform->GetUserConfigDirectory())); return String::FromFormat("%s/%s", parent_dir.GetCStr(), DefaultConfigFileName.GetCStr()); }
void MessageBuffer::Send(const String &out_id) { if (_buffer.empty()) return; if (_msgLost > 0) { DebugGroup gr = DbgMgr.GetGroup(kDbgGroup_Main); DbgMgr.SendMessage(out_id, DebugMessage(String::FromFormat("WARNING: output %s lost exceeding buffer: %u debug messages\n", out_id.GetCStr(), (unsigned)_msgLost), gr.UID.ID, gr.OutputName, kDbgMsgSet_All)); } for (std::vector<DebugMessage>::const_iterator it = _buffer.begin(); it != _buffer.end(); ++it) { DbgMgr.SendMessage(out_id, *it); } }
String find_default_cfg_file(const char *alt_cfg_file) { // Try current directory for config first; else try exe dir String filename = String::FromFormat("%s/%s", Directory::GetCurrentDirectory().GetCStr(), DefaultConfigFileName.GetCStr()); if (!Common::File::TestReadFile(filename)) { char conffilebuf[512]; strcpy(conffilebuf, alt_cfg_file); fix_filename_case(conffilebuf); fix_filename_slashes(conffilebuf); INIgetdirec(conffilebuf, DefaultConfigFileName); filename = conffilebuf; } return filename; }
const char* System_GetRuntimeInfo() { String runtimeInfo = GetRuntimeInfo(); return CreateNewScriptString(runtimeInfo.GetCStr()); }
void display_gfx_mode_error(const Size &game_size, const Size &screen_size) { proper_exit=1; platform->FinishedUsingGraphicsMode(); String main_error; if (screen_size.IsNull()) main_error.Format("There was a problem finding appropriate graphics mode for game size %d x %d (%d-bit) and requested filter '%s'.", game_size.Width, game_size.Height, firstDepth, GfxFilterRequest.IsEmpty() ? "Undefined" : GfxFilterRequest.GetCStr()); else main_error.Format("There was a problem initializing graphics mode %d x %d (%d-bit) with game size %d x %d and filter '%s'.", screen_size.Width, screen_size.Height, firstDepth, game_size.Width, game_size.Height, filter ? filter->GetFilterID() : "Undefined"); platform->DisplayAlert("%s\n" "(Problem: '%s')\n" "Try to correct the problem, or seek help from the AGS homepage.\n" "\nPossible causes:\n* your graphics card drivers do not support this resolution. " "Run the game setup program and try the other resolution.\n" "* the graphics driver you have selected does not work. Try switching between Direct3D and DirectDraw.\n" "* the graphics filter you have selected does not work. Try another filter.", main_error.GetCStr(), get_allegro_error()); }
void preparesavegamelist(int ctrllist) { numsaves = 0; toomanygames = 0; al_ffblk ffb; int bufix = 0; char curdir[255]; _getcwd(curdir, 255); char searchPath[260]; sprintf(searchPath, "%s""agssave.*%s", saveGameDirectory, saveGameSuffix); int don = al_findfirst(searchPath, &ffb, -1); while (!don) { bufix = 0; if (numsaves >= MAXSAVEGAMES) { toomanygames = 1; break; } // only list games .000 to .099 (to allow higher slots for other purposes) if (strstr(ffb.name, ".0") == NULL) { don = al_findnext(&ffb); continue; } const char *numberExtension = strstr(ffb.name, ".0") + 1; int sgNumber = atoi(numberExtension); String thisGamePath = get_save_game_path(sgNumber); // get description String description; read_savedgame_description(thisGamePath, description); CSCISendControlMessage(ctrllist, CLB_ADDITEM, 0, (long)description.GetCStr()); // Select the first item CSCISendControlMessage(ctrllist, CLB_SETCURSEL, 0, 0); filenumbers[numsaves] = sgNumber; filedates[numsaves] = (long int)ffb.time; numsaves++; don = al_findnext(&ffb); } al_findclose(&ffb); if (numsaves >= MAXSAVEGAMES) toomanygames = 1; for (int nn = 0; nn < numsaves - 1; nn++) { for (int kk = 0; kk < numsaves - 1; kk++) { // Date order the games if (filedates[kk] < filedates[kk + 1]) { // swap them round CSCISendControlMessage(ctrllist, CLB_GETTEXT, kk, (long)&buff[0]); CSCISendControlMessage(ctrllist, CLB_GETTEXT, kk + 1, (long)&buffer2[0]); CSCISendControlMessage(ctrllist, CLB_SETTEXT, kk + 1, (long)&buff[0]); CSCISendControlMessage(ctrllist, CLB_SETTEXT, kk, (long)&buffer2[0]); int numtem = filenumbers[kk]; filenumbers[kk] = filenumbers[kk + 1]; filenumbers[kk + 1] = numtem; long numted = filedates[kk]; filedates[kk] = filedates[kk + 1]; filedates[kk + 1] = numted; } } } }
String find_game_data_in_directory(const String &path) { String test_file; String found_data_file; // TODO: find a way to make this platform-agnostic way // using find-file interface or something #if defined (LINUX_VERSION) || defined (MAC_VERSION) DIR* fd = NULL; struct dirent* entry = NULL; version_info_t version_info; if ((fd = opendir(path))) { while ((entry = readdir(fd))) { // Filename must be >= 4 chars long int length = strlen(entry->d_name); if (length < 4) { continue; } // Exclude the setup program if (stricmp(entry->d_name, "winsetup.exe") == 0) { continue; } if (stricmp(&(entry->d_name[length - 4]), ".exe") == 0) { if (!getVersionInformation(entry->d_name, &version_info)) continue; if (strcmp(version_info.internal_name, "acwin") == 0) { test_file.Format("%s/%s", path.GetCStr(), entry->d_name); if (AGS::Common::AssetManager::IsDataFile(test_file)) { found_data_file = test_file; break; } } } else if (stricmp(&(entry->d_name[length - 4]), ".ags") == 0 || stricmp(entry->d_name, "ac2game.dat") == 0) { test_file.Format("%s/%s", path.GetCStr(), entry->d_name); if (AGS::Common::AssetManager::IsDataFile(test_file)) { found_data_file = test_file; break; } } } closedir(fd); } #elif defined (WINDOWS_VERSION) String path_mask = path; path_mask.Append("/*"); WIN32_FIND_DATAA file_data; HANDLE find_handle = FindFirstFileA(path_mask, &file_data); if (find_handle != INVALID_HANDLE_VALUE) { do { // Filename must be >= 4 chars long int length = strlen(file_data.cFileName); if (length < 4) { continue; } // Exclude the setup program if (strcmp(file_data.cFileName, "winsetup.exe") == 0) { continue; } if (strcmp(&(file_data.cFileName[length - 4]), ".exe") == 0 || strcmp(&(file_data.cFileName[length - 4]), ".ags") == 0 || strcmp(file_data.cFileName, "ac2game.dat") == 0) { test_file.Format("%s/%s", path.GetCStr(), file_data.cFileName); if (AGS::Common::AssetManager::IsDataFile(test_file)) { found_data_file = test_file; break; } } } while (FindNextFileA(find_handle, &file_data) != FALSE); FindClose(find_handle); } #else // TODO ??? (PSP, ANDROID) #endif return found_data_file; }
void display_gfx_mode_error(const Size &game_size, const Size &screen_size) { proper_exit=1; platform->FinishedUsingGraphicsMode(); String main_error; if (screen_size.IsNull()) main_error.Format("There was a problem finding appropriate graphics mode for game size %d x %d (%d-bit) and requested filter '%s'.", game_size.Width, game_size.Height, firstDepth, GfxFilterRequest.IsEmpty() ? "Undefined" : GfxFilterRequest.GetCStr()); else main_error.Format("There was a problem initializing graphics mode %d x %d (%d-bit) with game size %d x %d and filter '%s'.", screen_size.Width, screen_size.Height, firstDepth, game_size.Width, game_size.Height, filter ? filter->GetFilterID() : "Undefined"); platform->DisplayAlert("%s\n" "(Problem: '%s')\n" "Try to correct the problem, or seek help from the AGS homepage." "%s", main_error.GetCStr(), get_allegro_error(), platform->GetGraphicsTroubleshootingText()); }
HSaveError OpenSavegameBase(const String &filename, SavegameSource *src, SavegameDescription *desc, SavegameDescElem elems) { UStream in(File::OpenFileRead(filename)); if (!in.get()) return new SavegameError(kSvgErr_FileOpenFailed, String::FromFormat("Requested filename: %s.", filename.GetCStr())); // Skip MS Windows Vista rich media header RICH_GAME_MEDIA_HEADER rich_media_header; rich_media_header.ReadFromFile(in.get()); // Check saved game signature bool is_new_save = false; size_t pre_sig_pos = in->GetPosition(); String svg_sig = String::FromStreamCount(in.get(), SavegameSource::Signature.GetLength()); if (svg_sig.Compare(SavegameSource::Signature) == 0) { is_new_save = true; } else { in->Seek(pre_sig_pos, kSeekBegin); svg_sig = String::FromStreamCount(in.get(), SavegameSource::LegacySignature.GetLength()); if (svg_sig.Compare(SavegameSource::LegacySignature) != 0) return new SavegameError(kSvgErr_SignatureFailed); } SavegameVersion svg_ver; SavegameDescription temp_desc; HSaveError err; if (is_new_save) err = ReadDescription(in.get(), svg_ver, temp_desc, desc ? elems : kSvgDesc_None); else err = ReadDescription_v321(in.get(), svg_ver, temp_desc, desc ? elems : kSvgDesc_None); if (!err) return err; if (src) { src->Filename = filename; src->Version = svg_ver; src->InputStream.reset(in.release()); // give the stream away to the caller } if (desc) { if (elems & kSvgDesc_EnvInfo) { desc->EngineName = temp_desc.EngineName; desc->EngineVersion = temp_desc.EngineVersion; desc->GameGuid = temp_desc.GameGuid; desc->GameTitle = temp_desc.GameTitle; desc->MainDataFilename = temp_desc.MainDataFilename; desc->MainDataVersion = temp_desc.MainDataVersion; desc->ColorDepth = temp_desc.ColorDepth; } if (elems & kSvgDesc_UserText) desc->UserText = temp_desc.UserText; if (elems & kSvgDesc_UserImage) desc->UserImage.reset(temp_desc.UserImage.release()); } return err; }
String GetPathInASCII(const String &path) { char ascii_buffer[MAX_PATH]; if (GetShortPathNameA(path, ascii_buffer, MAX_PATH) == 0) { Debug::Printf(kDbgMsg_Error, "Unable to determine path: GetShortPathNameA failed.\nArg: %s", path.GetCStr()); return ""; } return Path::MakeAbsolutePath(ascii_buffer); }
bool graphics_mode_init(const ScreenSetup &setup, const ColorDepthOption &color_depths) { // Log out display information Size device_size; if (get_desktop_resolution(&device_size.Width, &device_size.Height) == 0) Out::FPrint("Device display resolution: %d x %d", device_size.Width, device_size.Height); else Out::FPrint("Unable to obtain device resolution"); const char *screen_sz_def_options[kNumScreenDef] = { "explicit", "scaling", "max" }; const bool ignore_device_ratio = setup.Windowed || setup.SizeDef == kScreenDef_Explicit; const String scale_option = make_scaling_option(setup.GameFrame.ScaleDef, convert_fp_to_scaling(setup.GameFrame.ScaleFactor)); Out::FPrint("Game settings: windowed = %s, screen def: %s, screen size: %d x %d, match device ratio: %s, game scale: %s", setup.Windowed ? "yes" : "no", screen_sz_def_options[setup.SizeDef], setup.Size.Width, setup.Size.Height, ignore_device_ratio ? "ignore" : (setup.MatchDeviceRatio ? "yes" : "no"), scale_option.GetCStr()); // Game size is used when defining resolution base and proper scaling; // Box size specifies minimal wanted screen size for the game (unscaled), // it is supposed to be be equal or greater than game_size GameSizeDef game_size; game_size.Game = game.size; game_size.Box = game.size; // Prepare the list of available gfx factories, having the one requested by user at first place StringV ids; GetGfxDriverFactoryNames(ids); StringV::iterator it = std::find(ids.begin(), ids.end(), setup.DriverID); if (it != ids.end()) std::rotate(ids.begin(), it, ids.end()); else Out::FPrint("Requested graphics driver '%s' not found, will try existing drivers instead", setup.DriverID.GetCStr()); // Try to create renderer and init gfx mode, choosing one factory at a time bool result = false; for (StringV::const_iterator it = ids.begin(); it != ids.end(); ++it) { result = create_gfx_driver_and_init_mode(*it, game_size, setup, color_depths, setup.Windowed); if (result) break; graphics_mode_shutdown(); } // If all possibilities failed, display error message and quit if (!result) { display_gfx_mode_error(game_size.Box, setup.Filter, color_depths.Prime); return false; } // On success: log out new mode params and continue initialization DisplayMode dm = gfxDriver->GetDisplayMode(); ScreenResolution = dm; Rect dst_rect = gfxDriver->GetRenderDestination(); Rect filter_rect = filter->GetDestination(); Out::FPrint("Succeeded. Using gfx mode %d x %d (%d-bit) %s\n\t" "filter dest (%d, %d, %d, %d : %d x %d), render dest (%d, %d, %d, %d : %d x %d)", dm.Width, dm.Height, dm.ColorDepth, dm.Windowed ? "windowed" : "fullscreen", filter_rect.Left, filter_rect.Top, filter_rect.Right, filter_rect.Bottom, filter_rect.GetWidth(), filter_rect.GetHeight(), dst_rect.Left, dst_rect.Top, dst_rect.Right, dst_rect.Bottom, dst_rect.GetWidth(), dst_rect.GetHeight()); return true; }
void StrUtil::WriteCStr(const String &s, Stream *out) { out->Write(s.GetCStr(), s.GetLength() + 1); }