Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions common/commandline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,21 @@ CommandLine::CommandLine(int argc, const char** argv) {
if(i<argc)
gpath.assign(argv[i],argv[i]+std::strlen(argv[i]));
}
else if(arg=="-saves") {
++i;
if(i<argc) {
savesPath = TextCodec::toUtf16(argv[i]);

for(auto& c : savesPath)
if(c == u'\\') c = u'/';

if(!savesPath.empty() && savesPath.back() != u'/')
savesPath.push_back(u'/');

if(!FileUtil::mkpath(savesPath))
Log::e("unable to create save directory: \"", TextCodec::toUtf8(savesPath), "\"");
}
}
else if(arg=="-devmode") {
// http://www.gothic-library.ru/publ/marvin/1-1-0-547
devmode = true;
Expand Down Expand Up @@ -243,3 +258,17 @@ bool CommandLine::validateGothicPath() const {
return false;
return true;
}

std::u16string CommandLine::saveFilePath(std::string_view fname) const {
std::u16string path16;
if(!savesPath.empty()) {
path16 = savesPath + TextCodec::toUtf16(fname);
} else {
path16 = TextCodec::toUtf16(fname);
}

for(auto& c : path16) {
if(c == u'\\') c = u'/';
}
return path16;
}
2 changes: 2 additions & 0 deletions common/commandline.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class CommandLine {
std::u16string cutscenePath(ScriptLang lang) const;
std::u16string_view modPath() const { return gmod; }
std::u16string nestedPath(const std::initializer_list<const char16_t*> &name, Tempest::Dir::FileType type) const;
std::u16string savesPath;

bool isDevMode() const { return devmode; }
bool isValidationMode() const { return isDebug; }
Expand All @@ -48,6 +49,7 @@ class CommandLine {
bool doForceG2NR() const { return forceG2NR; }
bool aaPreset() const { return aaPresetId; }
std::string_view defaultSave() const { return saveDef; }
std::u16string saveFilePath(std::string_view fname) const;

std::string wrldDef;

Expand Down
3 changes: 3 additions & 0 deletions common/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <Tempest/Layout>
#include <Tempest/Application>
#include <Tempest/Log>
#include <Tempest/TextCodec>

#include "ui/dialogmenu.h"
#include "ui/menuroot.h"
Expand All @@ -23,6 +24,7 @@
#include "utils/gthfont.h"
#include "utils/dbgpainter.h"


#include "commandline.h"
#include "gothic.h"

Expand Down Expand Up @@ -1058,6 +1060,7 @@ void MainWindow::loadGame(std::string_view slot) {
Gothic::inst().setBenchmarkMode(Benchmark::None);
Gothic::inst().startLoad("LOADING.TGA",[slot=std::string(slot)](std::unique_ptr<GameSession>&& game){
game = nullptr; // clear world-memory now

Tempest::RFile file(slot);
Serialize s(file);
std::unique_ptr<GameSession> w(new GameSession(s));
Expand Down
35 changes: 24 additions & 11 deletions common/ui/gamemenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "gothic.h"
#include "resources.h"
#include "build.h"
#include "commandline.h"

using namespace Tempest;

Expand Down Expand Up @@ -919,20 +920,26 @@ void GameMenu::execSaveGame(const GameMenu::Item& item) {
return;

string_frm fname("save_slot_",int(id),".sav");
Gothic::inst().save(fname,item.handle->text[0]);
}
const std::u16string path16 = CommandLine::inst().saveFilePath(fname.c_str());

std::string path8 = Tempest::TextCodec::toUtf8(path16);
Gothic::inst().save(path8, item.handle->text[0]);
}

bool GameMenu::execLoadGame(const GameMenu::Item &item) {
const size_t id = saveSlotId(item);
if(id==size_t(-1))
return false;

string_frm fname("save_slot_",int(id),".sav");
if(!FileUtil::exists(TextCodec::toUtf16(fname.c_str())))
const std::u16string path16 = CommandLine::inst().saveFilePath(fname.c_str());

if(!FileUtil::exists(path16))
return false;
Gothic::inst().load(fname);

Gothic::inst().load(Tempest::TextCodec::toUtf8(path16));
return true;
}
}

void GameMenu::execCommands(std::string str, bool isClick, KeyCodec::Action hint) {
if(str.find("EFFECTS ")==0) {
Expand Down Expand Up @@ -993,15 +1000,19 @@ void GameMenu::updateSavTitle(GameMenu::Item& sel) {
char fname[64]={};
std::snprintf(fname,sizeof(fname)-1,"save_slot_%d.sav",int(id));

if(!FileUtil::exists(TextCodec::toUtf16(fname))) {
const std::u16string path16 = CommandLine::inst().saveFilePath(fname);

if(!FileUtil::exists(path16)) {
sel.handle->text[0] = "---";
return;
}

SaveGameHeader hdr;
try {
RFile fin(fname);
Serialize reader(fin);
std::string path8 = Tempest::TextCodec::toUtf8(path16);
RFile fin(path8);
Serialize reader(fin);

reader.setEntry("header");
reader.read(hdr);
if(id!=0 || sel.handle->text[0].empty())
Expand All @@ -1025,7 +1036,7 @@ void GameMenu::updateSavTitle(GameMenu::Item& sel) {
catch(std::runtime_error&) {
return;
}
}
}

void GameMenu::updateSavThumb(GameMenu::Item &sel) {
if(sel.handle->on_sel_action_s[0]!="SAVEGAME_LOAD" &&
Expand Down Expand Up @@ -1058,7 +1069,9 @@ bool GameMenu::implUpdateSavThumb(GameMenu::Item& sel) {
char fname[64]={};
std::snprintf(fname,sizeof(fname)-1,"save_slot_%d.sav",int(id));

if(!FileUtil::exists(TextCodec::toUtf16(fname)))
const std::u16string path16 = CommandLine::inst().saveFilePath(fname);

if(!FileUtil::exists(path16))
return false;

const SaveGameHeader& hdr = sel.savHdr;
Expand All @@ -1079,7 +1092,7 @@ bool GameMenu::implUpdateSavThumb(GameMenu::Item& sel) {
std::snprintf(form,sizeof(form),"%dh %dmin",int(mins/60),int(mins%60));
set("MENUITEM_LOADSAVE_PLAYTIME_VALUE", form);
return true;
}
}

size_t GameMenu::saveSlotId(const GameMenu::Item &sel) {
const char* prefix[2] = {"MENUITEM_LOAD_SLOT", "MENUITEM_SAVE_SLOT"};
Expand Down
36 changes: 36 additions & 0 deletions common/utils/fileutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <shlwapi.h>
#else
#include <sys/stat.h>
#include <cerrno>
#endif

using namespace Tempest;
Expand All @@ -22,6 +23,41 @@ bool FileUtil::exists(const std::u16string &path) {
#endif
}

static bool mkdirOne(const std::u16string& path) {
#ifdef __WINDOWS__
if(CreateDirectoryW(reinterpret_cast<const WCHAR*>(path.c_str()), nullptr))
return true;
return GetLastError()==ERROR_ALREADY_EXISTS;
#else
std::string p = Tempest::TextCodec::toUtf8(path);
if(::mkdir(p.c_str(), 0755)==0)
return true;
return errno==EEXIST;
#endif
}

bool FileUtil::mkpath(const std::u16string& path) {
std::u16string cur;
for(size_t i=0; i<path.size(); ++i) {
cur.push_back(path[i]);
const bool isSep = (path[i]==u'/');
const bool isLastChr = (i+1==path.size());
if(!isSep && !isLastChr)
continue;

if(cur.size()<=1)
continue;
if(cur.size()==3 && cur[1]==u':' && cur[2]==u'/')
continue;

if(FileUtil::exists(cur))
continue;
if(!mkdirOne(cur))
return false;
}
return true;
}

std::u16string FileUtil::caseInsensitiveSegment(std::u16string_view pathv,const char16_t* segment,Dir::FileType type) {
auto path = std::u16string(pathv);
std::u16string next = path+segment;
Expand Down
2 changes: 2 additions & 0 deletions common/utils/fileutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

namespace FileUtil {
bool exists(const std::u16string& path);
bool mkpath(const std::u16string& path);

std::u16string caseInsensitiveSegment(std::u16string_view path, const char16_t* segment, Tempest::Dir::FileType type);
std::u16string nestedPath(std::u16string_view gpath, const std::initializer_list<const char16_t*> &name, Tempest::Dir::FileType type);
}