1 /*
2  * This file is part of EasyRPG Player.
3  *
4  * EasyRPG Player is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * EasyRPG Player is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "game_config.h"
19 #include "cmdline_parser.h"
20 #include "filefinder.h"
21 #include "output.h"
22 #include <lcf/inireader.h>
23 #include <cstring>
24 
Create(CmdlineParser & cp)25 Game_Config Game_Config::Create(CmdlineParser& cp) {
26 	Game_Config cfg;
27 	auto default_path = GetDefaultConfigPath();
28 	cp.Rewind();
29 	auto arg_path = GetConfigPath(cp);
30 	const auto& path = (arg_path.empty()) ? default_path : arg_path;
31 
32 	if (!path.empty()) {
33 		cfg.LoadFromConfig(path);
34 	}
35 
36 	cp.Rewind();
37 	cfg.LoadFromArgs(cp);
38 
39 	return cfg;
40 }
41 
GetDefaultConfigPath()42 std::string Game_Config::GetDefaultConfigPath() {
43 	// FIXME: Platform specific add this.
44 	// FIXME: Game specific configs?
45 
46 	return "";
47 }
48 
GetConfigPath(CmdlineParser & cp)49 std::string Game_Config::GetConfigPath(CmdlineParser& cp) {
50 	std::string path;
51 
52 	while (!cp.Done()) {
53 		CmdlineArg arg;
54 		if (cp.ParseNext(arg, 1, "--config", 'c')) {
55 			if (arg.NumValues() > 0) {
56 				path = arg.Value(0);
57 			}
58 			continue;
59 		}
60 
61 		cp.SkipNext();
62 	}
63 
64 	return path;
65 }
66 
LoadFromArgs(CmdlineParser & cp)67 void Game_Config::LoadFromArgs(CmdlineParser& cp) {
68 	while (!cp.Done()) {
69 		CmdlineArg arg;
70 		long li_value = 0;
71 		if (cp.ParseNext(arg, 0, "--vsync")) {
72 			video.vsync.Set(true);
73 			continue;
74 		}
75 		if (cp.ParseNext(arg, 0, "--no-vsync")) {
76 			video.vsync.Set(false);
77 			continue;
78 		}
79 		if (cp.ParseNext(arg, 1, "--fps-limit")) {
80 			if (arg.ParseValue(0, li_value)) {
81 				video.fps_limit.Set(li_value);
82 			}
83 			continue;
84 		}
85 		if (cp.ParseNext(arg, 0, "--no-fps-limit")) {
86 			video.fps_limit.Set(0);
87 			continue;
88 		}
89 		if (cp.ParseNext(arg, 0, "--show-fps")) {
90 			video.show_fps.Set(true);
91 			continue;
92 		}
93 		if (cp.ParseNext(arg, 0, "--no-show-fps")) {
94 			video.show_fps.Set(false);
95 			continue;
96 		}
97 		if (cp.ParseNext(arg, 0, "--fps-render-window")) {
98 			video.fps_render_window.Set(true);
99 			continue;
100 		}
101 		if (cp.ParseNext(arg, 0, "--no-fps-render-window")) {
102 			video.fps_render_window.Set(false);
103 			continue;
104 		}
105 		if (cp.ParseNext(arg, 0, "--window")) {
106 			video.fullscreen.Set(false);
107 			continue;
108 		}
109 		if (cp.ParseNext(arg, 0, "--fullscreen")) {
110 			video.fullscreen.Set(true);
111 			continue;
112 		}
113 		if (cp.ParseNext(arg, 1, "--window-zoom")) {
114 			if (arg.ParseValue(0, li_value)) {
115 				video.window_zoom.Set(li_value);
116 			}
117 			continue;
118 		}
119 		if (cp.ParseNext(arg, 1, "--autobattle-algo")) {
120 			std::string svalue;
121 			if (arg.ParseValue(0, svalue)) {
122 				player.autobattle_algo.Set(std::move(svalue));
123 			}
124 			continue;
125 		}
126 		if (cp.ParseNext(arg, 1, "--enemyai-algo")) {
127 			std::string svalue;
128 			if (arg.ParseValue(0, svalue)) {
129 				player.enemyai_algo.Set(std::move(svalue));
130 			}
131 			continue;
132 		}
133 
134 		cp.SkipNext();
135 	}
136 }
137 
LoadFromConfig(const std::string & path)138 void Game_Config::LoadFromConfig(const std::string& path) {
139 	this->config_path = path;
140 
141 	auto is = FileFinder::Root().OpenInputStream(path);
142 	if (!is) {
143 		Output::Debug("Ini config file {} not found", path);
144 		return;
145 	}
146 
147 	lcf::INIReader ini(is);
148 
149 	if (ini.ParseError()) {
150 		Output::Debug("Failed to parse ini config file {}", path);
151 		return;
152 	}
153 
154 	/** PLAYER SECTION */
155 
156 	if (ini.HasValue("player", "autobattle-algo")) {
157 		player.autobattle_algo.Set(ini.GetString("player", "autobattle-algo", "RPG_RT"));
158 	}
159 	if (ini.HasValue("player", "enemyai-algo")) {
160 		player.enemyai_algo.Set(ini.GetString("player", "enemyai-algo", "RPG_RT"));
161 	}
162 
163 	/** VIDEO SECTION */
164 
165 	if (ini.HasValue("video", "vsync")) {
166 		video.vsync.Set(ini.GetBoolean("video", "vsync", false));
167 	}
168 	if (ini.HasValue("video", "fullscreen")) {
169 		video.fullscreen.Set(ini.GetBoolean("video", "fullscreen", false));
170 	}
171 	if (ini.HasValue("video", "show-fps")) {
172 		video.show_fps.Set(ini.GetBoolean("video", "show-fps", false));
173 	}
174 	if (ini.HasValue("video", "fps-render-window")) {
175 		video.fps_render_window.Set(ini.GetBoolean("video", "fps-render-window", false));
176 	}
177 	if (ini.HasValue("video", "fps-limit")) {
178 		video.fps_limit.Set(ini.GetInteger("video", "fps-limit", 0));
179 	}
180 	if (ini.HasValue("video", "window-zoom")) {
181 		video.window_zoom.Set(ini.GetInteger("video", "window-zoom", 0));
182 	}
183 
184 	/** AUDIO SECTION */
185 
186 	/** INPUT SECTION */
187 }
188 
WriteToConfig(const std::string & path) const189 void Game_Config::WriteToConfig(const std::string& path) const {
190 	auto of = FileFinder::Root().OpenOutputStream(path);
191 
192 	if (!of) {
193 		Output::Debug("Failed to open {} for writing: {}", path, strerror(errno));
194 		return;
195 	}
196 
197 	/** PLAYER SECTION */
198 	of << "[player]\n";
199 	of << "autobattle-algo=" << player.autobattle_algo.Get() << "\n";
200 	of << "enemyai-algo=" << player.enemyai_algo.Get() << "\n";
201 	of << "\n";
202 
203 	/** VIDEO SECTION */
204 
205 	of << "[video]\n";
206 	if (video.vsync.Enabled()) {
207 		of << "vsync=" << int(video.vsync.Get()) << "\n";
208 	}
209 	if (video.fullscreen.Enabled()) {
210 		of << "fullscreen=" << int(video.fullscreen.Get()) << "\n";
211 	}
212 	if (video.show_fps.Enabled()) {
213 		of << "show-fps=" << int(video.show_fps.Get()) << "\n";
214 	}
215 	if (video.fps_render_window.Enabled()) {
216 		of << "fps-render-window=" << int(video.fps_render_window.Get()) << "\n";
217 	}
218 	if (video.fps_limit.Enabled()) {
219 		of << "fps-limit=" << video.fps_limit.Get() << "\n";
220 	}
221 	if (video.window_zoom.Enabled()) {
222 		of << "window-zoom=" << video.window_zoom.Get() << "\n";
223 	}
224 	of << "\n";
225 
226 	/** AUDIO SECTION */
227 
228 	/** INPUT SECTION */
229 }
230 
231