Nuke oopsError and out-dated "can't load game" error dialogs
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user