Nuke oopsError and out-dated "can't load game" error dialogs

This commit is contained in:
2015-07-03 18:11:03 -04:00
parent 558b1b8f62
commit 2d73bb01ae
7 changed files with 64 additions and 76 deletions

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -99,6 +99,7 @@ template<typename Container> 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::string>(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::string>(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::string>(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::string>(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::string>(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::string>(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::string>(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::string>(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::string>(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::string>(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::string>(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::string>(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::string>(std_fmterr));
}
return true;
}

View File

@@ -37,11 +37,17 @@ static typename std::make_unsigned<T>::type to_unsigned(T val) {
return *reinterpret_cast<typename std::make_unsigned<T>::type*>(&val);
}
static const std::string err_prefix = "Error reading QuickDraw PICT resource: ";
template<typename T> 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<typename T2> explicit operator T2*() {return (T2*)the_ptr;}
@@ -75,7 +85,10 @@ public:
static void loadColourTable(ptr_guard<char>& 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<char>& picData, ptr_guard<unsigned
picData += 2 + 2 + 4; // Skip version, packType, and packSize
picData += 4 + 4; // Skip hRes and vRes
picData += 2 + 2; // Skip pixelType and pixelSize
if(picData[-1] != 8) oopsError(3);
if(picData[-1] != 8) {
giveError(err_prefix + "Unsupported pixel type found.");
throw std::runtime_error("pixelType");
}
picData += 2 + 2; // Skip cmpCount and cmpSize
picData += 4 + 4 + 4; // Skip planeBytes, pbTable, pmReserved
picData += 4 + 2; // Skip ctSeed and ctFlags
int numColours = extract_word(picData);
if(numColours >= 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;