diff --git a/desktop_version/src/FileSystemUtils.cpp b/desktop_version/src/FileSystemUtils.cpp index e5a3b970..fc6cfa92 100644 --- a/desktop_version/src/FileSystemUtils.cpp +++ b/desktop_version/src/FileSystemUtils.cpp @@ -473,7 +473,9 @@ void FILESYSTEM_loadZip(const char* filename) } } -void FILESYSTEM_mountAssets(const char* path) +void FILESYSTEM_unmountAssets(void); + +bool FILESYSTEM_mountAssets(const char* path) { char filename[MAX_PATH]; char zip_data[MAX_PATH]; @@ -504,10 +506,10 @@ void FILESYSTEM_mountAssets(const char* path) if (!FILESYSTEM_mountAssetsFrom(zip_data)) { - return; + return false; } - graphics.reloadresources(); + MAYBE_FAIL(graphics.reloadresources()); } else if (zip_normal != NULL && endsWith(zip_normal, ".zip")) { @@ -515,10 +517,10 @@ void FILESYSTEM_mountAssets(const char* path) if (!FILESYSTEM_mountAssetsFrom(zip_normal)) { - return; + return false; } - graphics.reloadresources(); + MAYBE_FAIL(graphics.reloadresources()); } else if (FILESYSTEM_exists(dir)) { @@ -526,15 +528,21 @@ void FILESYSTEM_mountAssets(const char* path) if (!FILESYSTEM_mountAssetsFrom(dir)) { - return; + return false; } - graphics.reloadresources(); + MAYBE_FAIL(graphics.reloadresources()); } else { puts("Custom asset directory does not exist"); } + + return true; + +fail: + FILESYSTEM_unmountAssets(); + return false; } void FILESYSTEM_unmountAssets(void) diff --git a/desktop_version/src/FileSystemUtils.h b/desktop_version/src/FileSystemUtils.h index 0074df30..6bb90fb3 100644 --- a/desktop_version/src/FileSystemUtils.h +++ b/desktop_version/src/FileSystemUtils.h @@ -19,7 +19,7 @@ bool FILESYSTEM_isFile(const char* filename); bool FILESYSTEM_isMounted(const char* filename); void FILESYSTEM_loadZip(const char* filename); -void FILESYSTEM_mountAssets(const char *path); +bool FILESYSTEM_mountAssets(const char *path); void FILESYSTEM_unmountAssets(void); bool FILESYSTEM_isAssetMounted(const char* filename); diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 506a3591..645f4d0d 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -6477,6 +6477,9 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ ) option("silence"); menuyoff = 10; break; + case Menu::errorloadinglevel: + option("ok"); + break; } // Automatically center the menu. We must check the width of the menu with the initial horizontal spacing. diff --git a/desktop_version/src/Game.h b/desktop_version/src/Game.h index e1aa4ed2..7f7df630 100644 --- a/desktop_version/src/Game.h +++ b/desktop_version/src/Game.h @@ -35,6 +35,7 @@ namespace Menu youwannaquit, errornostart, errorsavingsettings, + errorloadinglevel, graphicoptions, ed_settings, ed_desc, diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index 63927fe1..5cfc25f9 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -151,6 +151,9 @@ void Graphics::init(void) tiles2_mounted = false; minimap_mounted = false; #endif + + SDL_zeroa(error); + SDL_zeroa(error_title); } void Graphics::destroy(void) @@ -314,24 +317,15 @@ void Graphics::updatetitlecolours(void) else if (grphx.im_##tilesheet->w % tile_square != 0 \ || grphx.im_##tilesheet->h % tile_square != 0) \ { \ - const char* error = "Error: %s.png dimensions not exact multiples of %i!"; \ - char message[128]; \ - const char* error_title = "Error with %s.png"; \ - char message_title[128]; \ + static const char error_fmt[] = "%s.png dimensions not exact multiples of %i!"; \ + static const char error_title_fmt[] = "Error with %s.png"; \ \ - SDL_snprintf(message, sizeof(message), error, #tilesheet, tile_square); \ - SDL_snprintf(message_title, sizeof(message_title), error_title, #tilesheet); \ + SDL_snprintf(error, sizeof(error), error_fmt, #tilesheet, tile_square); \ + SDL_snprintf(error_title, sizeof(error_title), error_title_fmt, #tilesheet); \ \ - puts(message); \ + puts(error); \ \ - SDL_ShowSimpleMessageBox( \ - SDL_MESSAGEBOX_ERROR, \ - message_title, \ - message, \ - NULL \ - ); \ - \ - VVV_exit(1); \ + return false; \ } #define PROCESS_TILESHEET_RENAME(tilesheet, vector, tile_square, extra_code) \ @@ -363,7 +357,7 @@ void Graphics::updatetitlecolours(void) #define PROCESS_TILESHEET(tilesheet, tile_square, extra_code) \ PROCESS_TILESHEET_RENAME(tilesheet, tilesheet, tile_square, extra_code) -void Graphics::Makebfont(void) +bool Graphics::Makebfont(void) { PROCESS_TILESHEET(bfont, 8, { @@ -391,6 +385,8 @@ void Graphics::Makebfont(void) { font_positions.clear(); } + + return true; } int Graphics::bfontlen(uint32_t ch) @@ -405,23 +401,29 @@ int Graphics::bfontlen(uint32_t ch) } } -void Graphics::MakeTileArray(void) +bool Graphics::MakeTileArray(void) { PROCESS_TILESHEET(tiles, 8, {}) PROCESS_TILESHEET(tiles2, 8, {}) PROCESS_TILESHEET(tiles3, 8, {}) PROCESS_TILESHEET(entcolours, 8, {}) + + return true; } -void Graphics::maketelearray(void) +bool Graphics::maketelearray(void) { PROCESS_TILESHEET_RENAME(teleporter, tele, 96, {}) + + return true; } -void Graphics::MakeSpriteArray(void) +bool Graphics::MakeSpriteArray(void) { PROCESS_TILESHEET(sprites, 32, {}) PROCESS_TILESHEET(flipsprites, 32, {}) + + return true; } #undef PROCESS_TILESHEET @@ -3486,17 +3488,17 @@ bool Graphics::onscreen(int t) return (t >= -40 && t <= 280); } -void Graphics::reloadresources(void) +bool Graphics::reloadresources(void) { grphx.destroy(); grphx.init(); destroy(); - MakeTileArray(); - MakeSpriteArray(); - maketelearray(); - Makebfont(); + MAYBE_FAIL(MakeTileArray()); + MAYBE_FAIL(MakeSpriteArray()); + MAYBE_FAIL(maketelearray()); + MAYBE_FAIL(Makebfont()); images.clear(); @@ -3528,6 +3530,11 @@ void Graphics::reloadresources(void) tiles2_mounted = FILESYSTEM_isAssetMounted("graphics/tiles2.png"); minimap_mounted = FILESYSTEM_isAssetMounted("graphics/minimap.png"); #endif + + return true; + +fail: + return false; } Uint32 Graphics::crewcolourreal(int t) diff --git a/desktop_version/src/Graphics.h b/desktop_version/src/Graphics.h index 6e64e5d0..1ec6818d 100644 --- a/desktop_version/src/Graphics.h +++ b/desktop_version/src/Graphics.h @@ -26,7 +26,7 @@ public: int bfontlen(uint32_t ch); int font_idx(uint32_t ch); - void Makebfont(void); + bool Makebfont(void); void drawhuetile(int x, int y, int t); void huetilesetcol(int t); @@ -34,11 +34,11 @@ public: void drawgravityline(int t); - void MakeTileArray(void); + bool MakeTileArray(void); - void MakeSpriteArray(void); + bool MakeSpriteArray(void); - void maketelearray(void); + bool maketelearray(void); void drawcoloredtile(int x, int y, int t, int r, int g, int b); @@ -222,7 +222,7 @@ public: bool onscreen(int t); - void reloadresources(void); + bool reloadresources(void); #ifndef NO_CUSTOM_LEVELS bool tiles1_mounted; bool tiles2_mounted; @@ -357,6 +357,9 @@ public: bool kludgeswnlinewidth; Uint32 crewcolourreal(int t); + + char error[128]; + char error_title[128]; /* for SDL_ShowSimpleMessageBox */ }; #ifndef GRAPHICS_DEFINITION diff --git a/desktop_version/src/Input.cpp b/desktop_version/src/Input.cpp index d61e0fb2..db850484 100644 --- a/desktop_version/src/Input.cpp +++ b/desktop_version/src/Input.cpp @@ -1727,6 +1727,11 @@ static void menuactionpress(void) game.returnmenu(); map.nexttowercolour(); break; + case Menu::errorloadinglevel: + music.playef(11); + game.returnmenu(); + map.nexttowercolour(); + break; default: break; } diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index d94e4c8d..b5267606 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -1387,6 +1387,10 @@ static void menurender(void) case Menu::errorsavingsettings: graphics.Print( -1, 95, "ERROR: Could not save settings file!", tr, tg, tb, true); break; + case Menu::errorloadinglevel: + graphics.bigprint(-1, 45, "ERROR", tr, tg, tb, true); + graphics.PrintWrap(-1, 65, graphics.error, tr, tg, tb, true, 10, 304); + break; default: break; } diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 36c72d18..85419341 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -2634,6 +2634,14 @@ void scriptclass::resetgametomenu(void) game.createmenu(Menu::gameover); } +static void gotoerrorloadinglevel(void) +{ + game.createmenu(Menu::errorloadinglevel); + graphics.fademode = 4; /* start fade in */ + music.currentsong = -1; /* otherwise music.play won't work */ + music.play(6); /* title screen music */ +} + void scriptclass::startgamemode( int t ) { switch(t) @@ -3152,7 +3160,11 @@ void scriptclass::startgamemode( int t ) //Initilise the level //First up, find the start point std::string filename = std::string(ed.ListOfMetaData[game.playcustomlevel].filename); - ed.load(filename); + if (!ed.load(filename)) + { + gotoerrorloadinglevel(); + break; + } ed.findstartpoint(); game.gamestate = GAMEMODE; @@ -3190,7 +3202,11 @@ void scriptclass::startgamemode( int t ) //Initilise the level //First up, find the start point std::string filename = std::string(ed.ListOfMetaData[game.playcustomlevel].filename); - ed.load(filename); + if (!ed.load(filename)) + { + gotoerrorloadinglevel(); + break; + } ed.findstartpoint(); game.gamestate = GAMEMODE; diff --git a/desktop_version/src/UtilityClass.h b/desktop_version/src/UtilityClass.h index 01e8cd3c..b3b6af65 100644 --- a/desktop_version/src/UtilityClass.h +++ b/desktop_version/src/UtilityClass.h @@ -78,6 +78,15 @@ void _VVV_between( # define VVV_fallthrough do { } while (false) /* fallthrough */ #endif +#define MAYBE_FAIL(expr) \ + do \ + { \ + if (!expr) \ + { \ + goto fail; \ + } \ + } \ + while (false) //helperClass class UtilityClass diff --git a/desktop_version/src/editor.cpp b/desktop_version/src/editor.cpp index 03179b82..d26f6357 100644 --- a/desktop_version/src/editor.cpp +++ b/desktop_version/src/editor.cpp @@ -1748,6 +1748,11 @@ void editorclass::switch_enemy(const bool reversed /*= false*/) bool editorclass::load(std::string& _path) { + tinyxml2::XMLDocument doc; + tinyxml2::XMLHandle hDoc(&doc); + tinyxml2::XMLElement* pElem; + tinyxml2::XMLHandle hRoot(NULL); + reset(); static const char *levelDir = "levels/"; @@ -1759,14 +1764,13 @@ bool editorclass::load(std::string& _path) FILESYSTEM_unmountAssets(); if (game.cliplaytest && game.playassets != "") { - FILESYSTEM_mountAssets(game.playassets.c_str()); + MAYBE_FAIL(FILESYSTEM_mountAssets(game.playassets.c_str())); } else { - FILESYSTEM_mountAssets(_path.c_str()); + MAYBE_FAIL(FILESYSTEM_mountAssets(_path.c_str())); } - tinyxml2::XMLDocument doc; if (!FILESYSTEM_loadTiXml2Document(_path.c_str(), doc)) { printf("No level %s to load :(\n", _path.c_str()); @@ -1775,9 +1779,6 @@ bool editorclass::load(std::string& _path) loaded_filepath = _path; - tinyxml2::XMLHandle hDoc(&doc); - tinyxml2::XMLElement* pElem; - tinyxml2::XMLHandle hRoot(NULL); version = 0; { @@ -2040,6 +2041,9 @@ next: version=2; return true; + +fail: + return false; } bool editorclass::save(std::string& _path) diff --git a/desktop_version/src/main.cpp b/desktop_version/src/main.cpp index af7af8c6..a384d534 100644 --- a/desktop_version/src/main.cpp +++ b/desktop_version/src/main.cpp @@ -483,7 +483,19 @@ int main(int argc, char *argv[]) game.init(); // This loads music too... - graphics.reloadresources(); + if (!graphics.reloadresources()) + { + /* Something wrong with the default assets? We can't use them to + * display the error message, and we have to bail. */ + SDL_ShowSimpleMessageBox( + SDL_MESSAGEBOX_ERROR, + graphics.error_title, + graphics.error, + NULL + ); + + VVV_exit(1); + } game.gamestate = PRELOADER;