From 2d73bb01ae9f0e43bf9be42a2afe930ce81f679e Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Fri, 3 Jul 2015 18:11:03 -0400 Subject: [PATCH] Nuke oopsError and out-dated "can't load game" error dialogs --- rsrc/dialogs/load-game-fail.xml | 11 ------- rsrc/dialogs/not-save-game.xml | 11 ------- src/dialogxml/dlogutil.cpp | 15 ---------- src/dialogxml/dlogutil.hpp | 5 ---- src/tools/fileio_party.cpp | 16 +++++----- src/tools/fileio_scen.cpp | 29 +++++++++--------- src/tools/qdpict.cpp | 53 ++++++++++++++++++++++++++------- 7 files changed, 64 insertions(+), 76 deletions(-) delete mode 100644 rsrc/dialogs/load-game-fail.xml delete mode 100644 rsrc/dialogs/not-save-game.xml diff --git a/rsrc/dialogs/load-game-fail.xml b/rsrc/dialogs/load-game-fail.xml deleted file mode 100644 index 676c02d1..00000000 --- a/rsrc/dialogs/load-game-fail.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - Loading Exile III save file failed. - \ No newline at end of file diff --git a/rsrc/dialogs/not-save-game.xml b/rsrc/dialogs/not-save-game.xml deleted file mode 100644 index 3c1a0450..00000000 --- a/rsrc/dialogs/not-save-game.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - This is not an Exile II save file. - \ No newline at end of file diff --git a/src/dialogxml/dlogutil.cpp b/src/dialogxml/dlogutil.cpp index a28f7751..b50614ba 100644 --- a/src/dialogxml/dlogutil.cpp +++ b/src/dialogxml/dlogutil.cpp @@ -542,18 +542,3 @@ void giveError(std::string str1, std::string str2, cDialog* parent){ void giveError(std::string str1, cDialog* parent) { giveError(str1, "", parent); } - -void oopsError(short error, short code, short mode){ - std::ostringstream error_str1, error_str2; - static const char* progname[3] = {"the scenario editor", "Blades of Exile", "the PC editor"}; - static const char* filetname[3] = {"scenario", "game", "game"}; - - error_str1 << "The program encountered an error while loading/saving/creating the " << filetname[mode] - << ". To prevent future problems, the program will now terminate. Trying again may solve the problem."; - // TODO: Update this error message - giving more memory is no longer an option in OSX. - error_str2 << "Giving " << progname[mode] << " more memory might also help. Be sure to back your " << filetname[mode] << " up often. Error number: " << error << "."; - if(code != 0) - error_str2 << " Result code: " << code << "."; - giveError(error_str1.str(),error_str2.str(),NULL); - exit(1); -} diff --git a/src/dialogxml/dlogutil.hpp b/src/dialogxml/dlogutil.hpp index cfca38d3..da62cba8 100644 --- a/src/dialogxml/dlogutil.hpp +++ b/src/dialogxml/dlogutil.hpp @@ -264,8 +264,3 @@ void giveError(std::string str1, std::string str2, cDialog* parent = NULL); /// @param str1 The string in the error dialog. /// @param parent Optionally, a parent dialog. void giveError(std::string str1, cDialog* parent = NULL); -/// Shows a generic error dialog and exits. -/// @param error An arbitrary code intended to be used for locating the error in the source. -/// @param code A code indicating the result of a failed action that triggered the error. -/// @param mode 0 for scenario editor, 1 for game, 2 for pc editor -void oopsError(short error,short code = 0, short mode = 0); diff --git a/src/tools/fileio_party.cpp b/src/tools/fileio_party.cpp index 50ff5d05..6bec2de4 100644 --- a/src/tools/fileio_party.cpp +++ b/src/tools/fileio_party.cpp @@ -54,7 +54,7 @@ bool load_party(fs::path file_to_load, cUniverse& univ){ // the three flags still follow that. FILE* file_id = fopen(file_to_load.string().c_str(), "rb"); if(file_id == NULL) { - cChoiceDlog("load-game-fail").show(); + giveError("Loading Blades of Exile save file failed."); return false; } @@ -63,7 +63,7 @@ bool load_party(fs::path file_to_load, cUniverse& univ){ n = fread(&flags, len, 1, file_id); if(n < 1) { fclose(file_id); - cChoiceDlog("not-save-game").show(); + giveError("This is not a Blades of Exile save file."); return false; } @@ -142,7 +142,7 @@ bool load_party(fs::path file_to_load, cUniverse& univ){ case new_oboe: return load_party_v2(file_to_load, univ, town_restore, in_scen, maps_there); case unknown: - cChoiceDlog("not-save-game").show(); + giveError("This is not a Blades of Exile save file."); return false; } @@ -306,7 +306,7 @@ bool load_party_v2(fs::path file_to_load, cUniverse& univ, bool town_restore, bo { // Load main party data first std::istream& fin = partyIn.getFile("save/party.txt"); if(!fin) { - cChoiceDlog("load-game-fail").show(); + giveError("Loading Blades of Exile save file failed."); return false; } univ.party.readFrom(fin); @@ -315,7 +315,7 @@ bool load_party_v2(fs::path file_to_load, cUniverse& univ, bool town_restore, bo { // Then the "setup" array std::istream& fin = partyIn.getFile("save/setup.dat"); if(!fin) { - cChoiceDlog("load-game-fail").show(); + giveError("Loading Blades of Exile save file failed."); return false; } uint16_t magic; @@ -334,7 +334,7 @@ bool load_party_v2(fs::path file_to_load, cUniverse& univ, bool town_restore, bo fname[7] = i + '1'; std::istream& fin = partyIn.getFile(fname); if(!fin) { - cChoiceDlog("load-game-fail").show(); + giveError("Loading Blades of Exile save file failed."); return false; } univ.party[i].readFrom(fin); @@ -363,7 +363,7 @@ bool load_party_v2(fs::path file_to_load, cUniverse& univ, bool town_restore, bo // Load town data std::istream& fin = partyIn.getFile("save/town.txt"); if(!fin) { - cChoiceDlog("load-game-fail").show(); + giveError("Loading Blades of Exile save file failed."); return false; } univ.town.readFrom(fin); @@ -382,7 +382,7 @@ bool load_party_v2(fs::path file_to_load, cUniverse& univ, bool town_restore, bo // Load outdoors data std::istream& fin = partyIn.getFile("save/out.txt"); if(!fin) { - cChoiceDlog("load-game-fail").show(); + giveError("Loading Blades of Exile save file failed."); return false; } univ.out.readFrom(fin); diff --git a/src/tools/fileio_scen.cpp b/src/tools/fileio_scen.cpp index f9c81d44..d2a1e40f 100644 --- a/src/tools/fileio_scen.cpp +++ b/src/tools/fileio_scen.cpp @@ -99,6 +99,7 @@ template static void port_shop_spec_node(cSpecial& spec, std spec.ex2a = spec.ex2b = -1; } +static const std::string err_prefix = "Error loading Blades of Exile Scenario: "; bool load_scenario_v1(fs::path file_to_load, cScenario& scenario, bool only_header){ short i,n; bool file_ok = false; @@ -109,9 +110,7 @@ bool load_scenario_v1(fs::path file_to_load, cScenario& scenario, bool only_head // TODO: Convert this (and all the others in this file) to use C++ streams FILE* file_id = fopen(file_to_load.string().c_str(),"rb"); if(file_id == NULL) { - // TODO: The third parameter to oopsError is supposed to specify whether we're in the scenario editor or the game, but I don't think this code knows that. - // TODO: Alternatively, nuke oopsError and just use giveError. It's more informative, anyway. - oopsError(10, 0, 0); + giveError(err_prefix + "Could not open file.", boost::lexical_cast(std_fmterr)); return false; } @@ -119,7 +118,7 @@ bool load_scenario_v1(fs::path file_to_load, cScenario& scenario, bool only_head if(fread(&scenario.format, len, 1, file_id) < 1){ fclose(file_id); - oopsError(11, 0, 0); + giveError(err_prefix + "Failed to read scenario header.", boost::lexical_cast(std_fmterr)); return false; } @@ -146,7 +145,7 @@ bool load_scenario_v1(fs::path file_to_load, cScenario& scenario, bool only_head n = fread(temp_scenario, len, 1, file_id); if(n < 1){ fclose(file_id); - oopsError(12, 0, 0); + giveError(err_prefix + "Failed to read scenario data.", boost::lexical_cast(std_fmterr)); return false; } port_scenario(temp_scenario); @@ -154,7 +153,7 @@ bool load_scenario_v1(fs::path file_to_load, cScenario& scenario, bool only_head n = fread(item_data, len, 1, file_id); if(n < 1){ fclose(file_id); - oopsError(13, 0, 0); + giveError(err_prefix + "Failed to read scenario items.", boost::lexical_cast(std_fmterr)); return false; } port_item_list(item_data); @@ -2153,7 +2152,7 @@ bool load_town_v1(fs::path scen_file, short which_town, cTown& the_town, legacy: FILE* file_id = fopen(scen_file.string().c_str(), "rb"); if(file_id == NULL) { - oopsError(14, 0, 0); + giveError(err_prefix + "Could not open file for reading town data.", boost::lexical_cast(std_fmterr)); return false; } @@ -2161,7 +2160,7 @@ bool load_town_v1(fs::path scen_file, short which_town, cTown& the_town, legacy: n = fseek(file_id, len_to_jump, SEEK_SET); if(n != 0) { fclose(file_id); - oopsError(15, 0, 0); + giveError(err_prefix + "Failure seeking to town record.", boost::lexical_cast(std_fmterr)); return false; } @@ -2169,7 +2168,7 @@ bool load_town_v1(fs::path scen_file, short which_town, cTown& the_town, legacy: n = fread(&store_town, len, 1, file_id); if(n < 1) { fclose(file_id); - oopsError(16, 0, 0); + giveError(err_prefix + "Could not read town record.", boost::lexical_cast(std_fmterr)); return false; } port_town(&store_town); @@ -2222,7 +2221,7 @@ bool load_town_v1(fs::path scen_file, short which_town, cTown& the_town, legacy: n = fread(&store_talk, len, 1, file_id); if(n < 1) { fclose(file_id); - oopsError(17, 0, 0); + giveError(err_prefix + "Could not read dialogue record.", boost::lexical_cast(std_fmterr)); return false; } port_talk_nodes(&store_talk); @@ -2257,7 +2256,7 @@ bool load_town_v1(fs::path scen_file, short which_town, cTown& the_town, legacy: n = fclose(file_id); if(n != 0) { - oopsError(18, 0, 0); + giveError(err_prefix + "An error occurred while closing the file.", boost::lexical_cast(std_fmterr)); } return true; @@ -2291,7 +2290,7 @@ bool load_outdoors_v1(fs::path scen_file, location which_out,cOutdoors& the_out, FILE* file_id = fopen(scen_file.string().c_str(), "rb"); if(file_id == NULL) { - oopsError(32, 0, 0); + giveError(err_prefix + "Could not open file for reading outdoor data.", boost::lexical_cast(std_fmterr)); return false; } @@ -2299,7 +2298,7 @@ bool load_outdoors_v1(fs::path scen_file, location which_out,cOutdoors& the_out, n = fseek(file_id, len_to_jump, SEEK_SET); if(n != 0) { fclose(file_id); - oopsError(33, 0, 0); + giveError(err_prefix + "Failure seeking to outdoor record.", boost::lexical_cast(std_fmterr)); return false; } @@ -2307,7 +2306,7 @@ bool load_outdoors_v1(fs::path scen_file, location which_out,cOutdoors& the_out, n = fread(&store_out, len, 1, file_id); if(n < 1) { fclose(file_id); - oopsError(34, 0, 0); + giveError(err_prefix + "Could not read outdoor record.", boost::lexical_cast(std_fmterr)); return false; } @@ -2333,7 +2332,7 @@ bool load_outdoors_v1(fs::path scen_file, location which_out,cOutdoors& the_out, n = fclose(file_id); if(n != 0) { - oopsError(35, 0, 0); + giveError(err_prefix + "Something went wrong when closing the file.", boost::lexical_cast(std_fmterr)); } return true; } diff --git a/src/tools/qdpict.cpp b/src/tools/qdpict.cpp index 2037a317..6fc7d0c1 100644 --- a/src/tools/qdpict.cpp +++ b/src/tools/qdpict.cpp @@ -37,11 +37,17 @@ static typename std::make_unsigned::type to_unsigned(T val) { return *reinterpret_cast::type*>(&val); } +static const std::string err_prefix = "Error reading QuickDraw PICT resource: "; + template class ptr_guard { T* the_ptr; T*const guard; void boundcheck() { - if(the_ptr > guard) oopsError(127, the_ptr - guard); + if(the_ptr > guard) { + std::string overflow = std::to_string(the_ptr - guard); + giveError(err_prefix + "read pointer reached end of buffer", overflow); + throw std::runtime_error(overflow); + } } public: ptr_guard(T* begin, T* end) : the_ptr(begin), guard(end) {} @@ -63,7 +69,11 @@ public: boundcheck(); } T& operator[](size_t i) { - if(the_ptr + i > guard) oopsError(128, i - (guard - the_ptr)); + if(the_ptr + i > guard) { + std::string overflow = std::to_string(i - (guard - the_ptr)); + giveError(err_prefix + "attempt to index beyond buffer", overflow); + throw std::runtime_error(overflow); + } return the_ptr[i]; } template explicit operator T2*() {return (T2*)the_ptr;} @@ -75,7 +85,10 @@ public: static void loadColourTable(ptr_guard& picData, sf::Color(& clut)[256], int numColours) { while(numColours >= 0) { int i = extract_word(picData); - if(i > 256) oopsError(5); + if(i > 256) { + giveError(err_prefix + " Found too many colours in 'clut'", std::to_string(i)); + throw std::runtime_error(std::to_string(i)); + } picData += 2; clut[i].r = to_unsigned(extract_word(picData)) / 256; picData += 2; @@ -150,12 +163,18 @@ static legacy::Rect loadPixMapData(ptr_guard& picData, ptr_guard= 256) oopsError(4); + if(numColours >= 256) { + giveError(err_prefix + "More than 256 colours found."); + throw std::runtime_error(std::to_string(numColours)); + } picData += 2; sf::Color clut[256]; loadColourTable(picData, clut, numColours); @@ -186,11 +205,15 @@ static rectangle loadFromPictResource(Handle resHandle, unsigned char*& pixelSto picFrame.left = extract_word(picData); picData += 2; picFrame.bottom = extract_word(picData); picData += 2; picFrame.right = extract_word(picData); picData += 2; - if(strncmp(picData, "\0\x11\x02\xff", 4) != 0) // QuickDraw version code (version 2) - oopsError(1); + if(strncmp(picData, "\0\x11\x02\xff", 4) != 0) { // QuickDraw version code (version 2) + giveError("Missing QuickDraw 2 version code"); + throw std::runtime_error("QD2 version"); + } picData += 4; // Skip version field - if(strncmp(picData, "\x0c\0", 2) != 0) // Header opcode - oopsError(2); + if(strncmp(picData, "\x0c\0", 2) != 0) { // Header opcode + giveError("Missing QuickDraw 2 header opcode"); + throw std::runtime_error("QD2 header"); + } picData += 2 + 24; // Skip header opcode and payload // Initialize the target data array using the picture's bounding rect size_t picDataSize = picFrame.height() * picFrame.width() * 4; // Four bytes per pixel @@ -461,12 +484,20 @@ bool tryLoadPictFromResourceFile(fs::path& gpath, sf::Image& graphics_store) { } if(resHandle == NULL) { CloseResFile(custRef); - giveError("An old-style .meg graphics file was found, but an error occurred while loading it.",noGraphics); + giveError("An old-style .meg graphics file was found, but an error occurred while fetching the PICT resource of ID 1.",noGraphics); return false; } unsigned char* data = NULL; int error = 0; - rectangle picFrame = loadFromPictResource(resHandle, data, error); + rectangle picFrame; + try { + picFrame = loadFromPictResource(resHandle, data, error); + } catch(std::runtime_error&) { + CloseResFile(custRef); + if(data != NULL) delete[] data; + giveError("An old-style .meg graphics file was found, but an error occurred while loading the PICT resource of ID 1.",noGraphics); + return false; + } CloseResFile(custRef); if(picFrame.width() <= 0 || picFrame.height() <= 0) { if(data != NULL) delete[] data;