From b884b7e4e9b63663c170146f4f5df83e9b693fa2 Mon Sep 17 00:00:00 2001 From: Dav999-v Date: Sun, 12 Jan 2020 15:17:39 +0100 Subject: [PATCH] Replace TiXmlDocument load and save functions by PHYSFS The TinyXml functions to load and save files don't properly support unicode file paths on Windows, so in order to support that properly, I saw no other option than to do the actual loading and saving via PHYSFS (or to use the Windows API on Windows and retain doc.LoadFile and doc.SaveFile on other OSes, but that'd be more complicated and unnecessary, we already have PHYSFS, right?). There are two new functions in FileSystemUtils: bool FILESYSTEM_saveTiXmlDocument(const char *name, TiXmlDocument *doc) bool FILESYSTEM_loadTiXmlDocument(const char *name, TiXmlDocument *doc) Any instances of doc.SaveFile() have been replaced by FILESYSTEM_saveTiXmlDocument(, &doc), where included the full path to the saves or levels directory, and only includes the path relative to the VVVVVV directory. When loading a document, a TiXmlDocument used to be created with a full path in its constructor and doc.LoadFile() would then be called, now a TiXmlDocument is constructed with no path name and FILESYSTEM_loadTiXmlDocument(, &doc) is called. --- desktop_version/src/FileSystemUtils.cpp | 32 +++++++++++++++++++++ desktop_version/src/FileSystemUtils.h | 4 +++ desktop_version/src/Game.cpp | 38 ++++++++++++------------- desktop_version/src/Input.cpp | 8 ++++-- desktop_version/src/editor.cpp | 2 +- 5 files changed, 61 insertions(+), 23 deletions(-) diff --git a/desktop_version/src/FileSystemUtils.cpp b/desktop_version/src/FileSystemUtils.cpp index 11590620..0a356eac 100644 --- a/desktop_version/src/FileSystemUtils.cpp +++ b/desktop_version/src/FileSystemUtils.cpp @@ -10,6 +10,8 @@ #include #include +#include "tinyxml.h" + #if defined(_WIN32) #include #include @@ -53,6 +55,7 @@ int FILESYSTEM_init(char *argvZero) /* Mount our base user directory */ PHYSFS_mount(output, NULL, 1); + PHYSFS_setWriteDir(output); printf("Base directory: %s\n", output); /* Create save directory */ @@ -136,6 +139,35 @@ void FILESYSTEM_freeMemory(unsigned char **mem) *mem = NULL; } +bool FILESYSTEM_saveTiXmlDocument(const char *name, TiXmlDocument *doc) +{ + /* TiXmlDocument.SaveFile doesn't account for Unicode paths, PHYSFS does */ + TiXmlPrinter printer; + doc->Accept(&printer); + PHYSFS_File* handle = PHYSFS_openWrite(name); + if (handle == NULL) + { + return false; + } + PHYSFS_writeBytes(handle, printer.CStr(), printer.Size()); + PHYSFS_close(handle); + return true; +} + +bool FILESYSTEM_loadTiXmlDocument(const char *name, TiXmlDocument *doc) +{ + /* TiXmlDocument.SaveFile doesn't account for Unicode paths, PHYSFS does */ + unsigned char *mem = NULL; + FILESYSTEM_loadFileToMemory(name, &mem, NULL); + if (mem == NULL) + { + return false; + } + doc->Parse((const char*)mem); + FILESYSTEM_freeMemory(&mem); + return true; +} + std::vector FILESYSTEM_getLevelDirFileNames() { std::vector list; diff --git a/desktop_version/src/FileSystemUtils.h b/desktop_version/src/FileSystemUtils.h index 26aa7a24..71274daf 100644 --- a/desktop_version/src/FileSystemUtils.h +++ b/desktop_version/src/FileSystemUtils.h @@ -4,6 +4,8 @@ #include #include +#include "tinyxml.h" + int FILESYSTEM_init(char *argvZero); void FILESYSTEM_deinit(); @@ -12,6 +14,8 @@ char *FILESYSTEM_getUserLevelDirectory(); void FILESYSTEM_loadFileToMemory(const char *name, unsigned char **mem, size_t *len); void FILESYSTEM_freeMemory(unsigned char **mem); +bool FILESYSTEM_saveTiXmlDocument(const char *name, TiXmlDocument *doc); +bool FILESYSTEM_loadTiXmlDocument(const char *name, TiXmlDocument *doc); std::vector FILESYSTEM_getLevelDirFileNames(); diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 24ede7ff..cc17ab66 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -293,8 +293,8 @@ Game::Game(void): saveFilePath = FILESYSTEM_getUserSaveDirectory(); - TiXmlDocument doc((saveFilePath + "qsave.vvv").c_str()); - if (!doc.LoadFile()) + TiXmlDocument doc; + if (!FILESYSTEM_loadTiXmlDocument("saves/qsave.vvv", &doc)) { quickcookieexists = false; quicksummary = ""; @@ -470,8 +470,8 @@ void Game::loadcustomlevelstats() //testing if(!customlevelstatsloaded) { - TiXmlDocument doc((saveFilePath+"levelstats.vvv").c_str()); - if (!doc.LoadFile()) + TiXmlDocument doc; + if (!FILESYSTEM_loadTiXmlDocument("saves/levelstats.vvv", &doc)) { //No levelstats file exists; start new numcustomlevelstats=0; @@ -581,7 +581,7 @@ void Game::savecustomlevelstats() msg->LinkEndChild( new TiXmlText( customlevelstatsstr.c_str() )); msgs->LinkEndChild( msg ); - if(doc.SaveFile( (saveFilePath+"levelstats.vvv").c_str() )) + if(FILESYSTEM_saveTiXmlDocument("saves/levelstats.vvv", &doc)) { printf("Level stats saved\n"); } @@ -4105,8 +4105,8 @@ void Game::unlocknum( int t, mapclass& map, Graphics& dwgfx ) void Game::loadstats( mapclass& map, Graphics& dwgfx ) { // TODO loadstats - TiXmlDocument doc((saveFilePath+"unlock.vvv").c_str()); - if (!doc.LoadFile()) + TiXmlDocument doc; + if (!FILESYSTEM_loadTiXmlDocument("saves/unlock.vvv", &doc)) { savestats(map, dwgfx); printf("No Stats found. Assuming a new player\n"); @@ -4564,7 +4564,7 @@ void Game::savestats( mapclass& _map, Graphics& _dwgfx ) msg->LinkEndChild( new TiXmlText( tu.String(controllerSensitivity).c_str())); dataNode->LinkEndChild( msg ); - doc.SaveFile( (saveFilePath+"unlock.vvv").c_str() ); + FILESYSTEM_saveTiXmlDocument("saves/unlock.vvv", &doc); } void Game::customstart( entityclass& obj, musicclass& music ) @@ -4792,8 +4792,8 @@ void Game::starttrial( int t, entityclass& obj, musicclass& music ) void Game::loadquick( mapclass& map, entityclass& obj, musicclass& music ) { - TiXmlDocument doc((saveFilePath+"qsave.vvv").c_str()); - if (!doc.LoadFile()) return; ; + TiXmlDocument doc; + if (!FILESYSTEM_loadTiXmlDocument("saves/qsave.vvv", &doc)) return; TiXmlHandle hDoc(&doc); TiXmlElement* pElem; @@ -5014,8 +5014,8 @@ void Game::loadquick( mapclass& map, entityclass& obj, musicclass& music ) void Game::customloadquick(std::string savfile, mapclass& map, entityclass& obj, musicclass& music ) { std::string levelfile = savfile.substr(7); - TiXmlDocument doc((saveFilePath+levelfile+".vvv").c_str()); - if (!doc.LoadFile()) return; ; + TiXmlDocument doc; + if (!FILESYSTEM_loadTiXmlDocument(("saves/"+levelfile+".vvv").c_str(), &doc)) return; TiXmlHandle hDoc(&doc); TiXmlElement* pElem; @@ -5389,8 +5389,8 @@ void Game::loadsummary( mapclass& map, UtilityClass& help ) tele_currentarea = map.currentarea(map.area(l_saveX, l_saveY)); } - TiXmlDocument doc((saveFilePath+"qsave.vvv").c_str()); - if (!doc.LoadFile()) + TiXmlDocument doc; + if (!FILESYSTEM_loadTiXmlDocument("saves/qsave.vvv", &doc)) { quickcookieexists = false; quicksummary = ""; @@ -5734,7 +5734,7 @@ void Game::savetele( mapclass& map, entityclass& obj, musicclass& music ) //telecookie.flush(); //telecookie.close(); - if(doc.SaveFile( (saveFilePath+"tsave.vvv").c_str() )) + if(FILESYSTEM_saveTiXmlDocument("saves/tsave.vvv", &doc)) { printf("Game saved\n"); } @@ -5978,7 +5978,7 @@ void Game::savequick( mapclass& map, entityclass& obj, musicclass& music ) //telecookie.flush(); //telecookie.close(); - if(doc.SaveFile( (saveFilePath+ "qsave.vvv").c_str() )) + if(FILESYSTEM_saveTiXmlDocument("saves/qsave.vvv", &doc)) { printf("Game saved\n"); } @@ -6239,7 +6239,7 @@ void Game::customsavequick(std::string savfile, mapclass& map, entityclass& obj, //telecookie.close(); std::string levelfile = savfile.substr(7); - if(doc.SaveFile( (saveFilePath+ levelfile+".vvv").c_str() )) + if(FILESYSTEM_saveTiXmlDocument(("saves/"+levelfile+".vvv").c_str(), &doc)) { printf("Game saved\n"); } @@ -6253,8 +6253,8 @@ void Game::customsavequick(std::string savfile, mapclass& map, entityclass& obj, void Game::loadtele( mapclass& map, entityclass& obj, musicclass& music ) { - TiXmlDocument doc((saveFilePath+"tsave.vvv").c_str()); - if (!doc.LoadFile()) return; ; + TiXmlDocument doc; + if (!FILESYSTEM_loadTiXmlDocument("saves/tsave.vvv", &doc)) return; TiXmlHandle hDoc(&doc); TiXmlElement* pElem; diff --git a/desktop_version/src/Input.cpp b/desktop_version/src/Input.cpp index 1042a00c..e1c724a5 100644 --- a/desktop_version/src/Input.cpp +++ b/desktop_version/src/Input.cpp @@ -4,6 +4,8 @@ #include "tinyxml.h" +#include "FileSystemUtils.h" + // Found in titlerender.cpp void updategraphicsmode(Game& game, Graphics& dwgfx); @@ -358,9 +360,9 @@ void titleinput(KeyPoll& key, Graphics& dwgfx, mapclass& map, Game& game, entity game.customleveltitle=ed.ListOfMetaData[game.playcustomlevel].title; game.customlevelfilename=ed.ListOfMetaData[game.playcustomlevel].filename; - std::string name = game.saveFilePath + ed.ListOfMetaData[game.playcustomlevel].filename.substr(7) + ".vvv"; - TiXmlDocument doc(name.c_str()); - if (!doc.LoadFile()){ + std::string name = "saves/" + ed.ListOfMetaData[game.playcustomlevel].filename.substr(7) + ".vvv"; + TiXmlDocument doc; + if (!FILESYSTEM_loadTiXmlDocument(name.c_str(), &doc)){ game.mainmenu = 22; dwgfx.fademode = 2; }else{ diff --git a/desktop_version/src/editor.cpp b/desktop_version/src/editor.cpp index 2b4fd5e4..4db1b7d5 100644 --- a/desktop_version/src/editor.cpp +++ b/desktop_version/src/editor.cpp @@ -2107,7 +2107,7 @@ void editorclass::save(std::string& _path) msg->LinkEndChild( new TiXmlText( scriptString.c_str() )); data->LinkEndChild( msg ); - doc.SaveFile((std::string(FILESYSTEM_getUserLevelDirectory()) + _path).c_str() ); + FILESYSTEM_saveTiXmlDocument(("levels/" + _path).c_str(), &doc); }