OpenGothic
Open source reimplementation of Gothic I and II
Loading...
Searching...
No Matches
commandline.cpp
Go to the documentation of this file.
1#include "commandline.h"
2
3#include <Tempest/Log>
4#include <Tempest/TextCodec>
5#include <cstring>
6#include <cassert>
7
8#if defined(__APPLE__)
9#include <filesystem>
10#endif
11
12#include <algorithm>
13
14#include "utils/installdetect.h"
15#include "utils/fileutil.h"
16#include "utils/string_frm.h"
17
18using namespace Tempest;
19using namespace FileUtil;
20
21static CommandLine* instance = nullptr;
22
23static const char16_t* toString(ScriptLang lang) {
24 switch(lang) {
25 case ScriptLang::EN: return u"Scripts_EN";
26 case ScriptLang::DE: return u"Scripts_DE";
27 case ScriptLang::PL: return u"Scripts_PL";
28 case ScriptLang::RU: return u"Scripts_RU";
29 case ScriptLang::FR: return u"Scripts_FR";
30 case ScriptLang::ES: return u"Scripts_ES";
31 case ScriptLang::IT: return u"Scripts_IT";
32 case ScriptLang::CZ: return u"Scripts_CZ";
34 break;
35 }
36 return u"Scripts";
37 }
38
39static bool boolArg(std::string_view v) {
40 return std::string_view(v)!="0" && std::string_view(v)!="false";
41 }
42
43CommandLine::CommandLine(int argc, const char** argv) {
44 instance = this;
45 if(argc<1)
46 return;
47
48 std::string_view mod;
49 for(int i=1;i<argc;++i) {
50 std::string_view arg = argv[i];
51 if(arg.find("-game:")==0) {
52 if(!mod.empty())
53 Log::e("-game specified twice");
54 mod = arg.substr(6);
55 }
56 else if(arg=="-g") {
57 ++i;
58 if(i<argc)
59 gpath.assign(argv[i],argv[i]+std::strlen(argv[i]));
60 }
61 else if(arg=="-devmode") {
62 // http://www.gothic-library.ru/publ/marvin/1-1-0-547
63 devmode = true;
64 }
65 else if(arg=="-save") {
66 ++i;
67 if(i<argc){
68 if(std::strcmp(argv[i],"q")==0) {
69 saveDef = "save_slot_0.sav";
70 } else {
71 saveDef = string_frm("save_slot_",argv[i],".sav");
72 }
73 }
74 }
75 else if(arg=="-w") {
76 ++i;
77 if(i<argc)
78 wrldDef = argv[i];
79 }
80 else if(arg=="-window") {
81 isWindow = true;
82 }
83 else if(arg=="-nomenu") {
84 noMenu = true;
85 }
86 else if(arg=="-benchmark") {
87 isBenchmark = Benchmark::Normal;
88 if(i+1<argc && argv[i+1][0]!='-') {
89 ++i;
90 isBenchmark = std::string_view(argv[i])=="ci" ? Benchmark::CiTooling : isBenchmark;
91 }
92 }
93 else if(arg=="-g1") {
94 forceG1 = true;
95 }
96 else if(arg=="-g2c") {
97 forceG2 = true;
98 }
99 else if(arg=="-g2") {
100 forceG2NR = true;
101 }
102 else if(arg=="-dx12") {
103 graphics = GraphicBackend::DirectX12;
104 }
105 else if(arg=="-validation" || arg=="-v") {
106 isDebug = true;
107 }
108 else if(arg=="-rt") {
109 ++i;
110 if(i<argc)
111 isRQuery = boolArg(argv[i]);
112 }
113 else if(arg=="-aa") {
114 ++i;
115 if(i<argc) {
116 try {
117 aaPresetId = uint32_t(std::stoul(std::string(argv[i])));
118 aaPresetId = std::clamp(aaPresetId, 0u, uint32_t(AaPreset::PRESETS_COUNT)-1u);
119 }
120 catch (const std::exception& e) {
121 Log::i("failed to read cmaa2 preset: \"", std::string(argv[i]), "\"");
122 }
123 }
124 }
125 else if(arg=="-gi") {
126 ++i;
127 if(i<argc)
128 isGi = boolArg(argv[i]);
129 }
130 else if(arg=="-ms") {
131 ++i;
132 if(i<argc)
133 isMeshSh = boolArg(argv[i]);
134 }
135 else if(arg=="-bl") {
136 // not to document - debug only
137 ++i;
138 if(i<argc)
139 isBindlessSh = boolArg(argv[i]);
140 }
141 else if(arg=="-vsm") {
142 // not to document - debug only
143 ++i;
144 if(i<argc)
145 isVsm = boolArg(argv[i]);
146 }
147 else if(arg=="-rtsm") {
148 // not to document - debug only
149 ++i;
150 if(i<argc)
151 isRtSm = boolArg(argv[i]);
152 }
153 else {
154 Log::i("unreacognized commandline option: \"", arg, "\"");
155 }
156 }
157
158 if(gpath.empty()) {
160 gpath = inst.detectG2();
161#if defined(__APPLE__)
162 if(!gpath.empty() && gpath==inst.applicationSupportDirectory()) {
163 std::filesystem::current_path(gpath);
164 }
165#endif
166 }
167
168 for(auto& i:gpath)
169 if(i=='\\')
170 i='/';
171
172 if(gpath.size()>0 && gpath.back()!='/')
173 gpath.push_back('/');
174
175 gscript = nestedPath({u"_work",u"Data",u"Scripts", u"_compiled"},Dir::FT_Dir);
176 gcutscene = nestedPath({u"_work",u"Data",u"Scripts", u"content",u"CUTSCENE"},Dir::FT_Dir);
177
178 gmod = TextCodec::toUtf16(mod);
179 if(!gmod.empty())
180 gmod = nestedPath({u"system",gmod.c_str()},Dir::FT_File);
181
182 if(!validateGothicPath()) {
183 if(gpath.empty()) {
184 Log::e("Gothic path is not provided. Please use command line argument -g <path>");
185 } else {
186 Log::e("Invalid gothic path: \"",TextCodec::toUtf8(gpath),"\"");
187 }
188 throw GothicNotFoundException("gothic not found!"); // TODO: user-friendly message-box
189 }
190 }
191
193 assert(instance!=nullptr);
194 return *instance;
195 }
196
198 return graphics;
199 }
200
201std::u16string_view CommandLine::rootPath() const {
202 return gpath;
203 }
204
205std::u16string CommandLine::scriptPath() const {
206 return gscript;
207 }
208
209std::u16string CommandLine::scriptPath(ScriptLang lang) const {
210 const char16_t* scripts = toString(lang);
211 return nestedPath({u"_work",u"Data",scripts,u"_compiled"},Dir::FT_Dir);
212 }
213
214std::u16string CommandLine::cutscenePath() const {
215 return gcutscene;
216 }
217
218std::u16string CommandLine::cutscenePath(ScriptLang lang) const {
219 const char16_t* scripts = toString(lang);
220 return nestedPath({u"_work",u"Data",scripts},Dir::FT_Dir);
221 }
222
223std::u16string CommandLine::nestedPath(const std::initializer_list<const char16_t*>& name, Tempest::Dir::FileType type) const {
224 return FileUtil::nestedPath(gpath, name, type);
225 }
226
227bool CommandLine::validateGothicPath() const {
228 if(gpath.empty())
229 return false;
230 if(!FileUtil::exists(gscript))
231 return false;
232 if(!FileUtil::exists(nestedPath({u"Data"},Dir::FT_Dir)))
233 return false;
234 if(!FileUtil::exists(nestedPath({u"_work",u"Data"},Dir::FT_Dir)))
235 return false;
236 return true;
237 }
auto graphicsApi() const -> GraphicBackend
std::u16string nestedPath(const std::initializer_list< const char16_t * > &name, Tempest::Dir::FileType type) const
std::u16string scriptPath() const
std::string wrldDef
Definition commandline.h:52
std::u16string cutscenePath() const
static const CommandLine & inst()
std::u16string_view rootPath() const
CommandLine(int argc, const char **argv)
static bool boolArg(std::string_view v)
static CommandLine * instance
static const char16_t * toString(ScriptLang lang)
ScriptLang
Definition constants.h:518
bool exists(const std::u16string &path)
Definition fileutil.cpp:15
std::u16string nestedPath(std::u16string_view gpath, const std::initializer_list< const char16_t * > &name, Tempest::Dir::FileType type)