1 /*
2  * This file is part of the Colobot: Gold Edition source code
3  * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
4  * http://epsitec.ch; http://colobot.info; http://github.com/colobot
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see http://gnu.org/licenses
18  */
19 
20 /**
21  * \file app/main.cpp
22  * \brief Entry point of application - main() function
23  */
24 
25 #include "common/config.h"
26 
27 #include "app/app.h"
28 #include "app/signal_handlers.h"
29 
30 #include "common/logger.h"
31 #include "common/make_unique.h"
32 #include "common/profiler.h"
33 #include "common/restext.h"
34 #include "common/version.h"
35 
36 #include "common/resources/resourcemanager.h"
37 
38 #include "common/system/system.h"
39 #if PLATFORM_WINDOWS
40     #include "common/system/system_windows.h"
41 #endif
42 
43 #if PLATFORM_WINDOWS
44     #include <windows.h>
45 #endif
46 
47 #include <memory>
48 #include <vector>
49 #include <boost/filesystem.hpp>
50 
51 /**
52 \mainpage
53 
54 Doxygen documentation of Colobot: Gold Edition project.
55 
56 <b>Colobot</b> <i>(COLOnize with BOTs)</i> is a game combining elements of real time strategy (RTS)
57 and educational game, aiming to teach programming through entertainment. You are playing as an astronaut
58 on a journey with robot helpers to find a planet for colonization. It features a C++ and Java-like,
59 object-oriented language, CBOT, which can be used to program the robots available in the game.
60 
61 The original version of the game was developed by [Epsitec](http://www.epsitec.ch/) and released in 2001.
62 Later, in 2005 another version named Ceebot was released. In March 2012, through attempts
63 by Polish Colobot fans, Epsitec agreeed to release the source code of the game on GPLv3 license.
64 The license was given specifically to our community, <b>TerranovaTeam</b>,
65 part of <b>International Colobot Community (ICC)</b> (previously known as <i>Polish Portal of Colobot (PPC)</i>;
66 Polish: <i>Polski Portal Colobota</i>) with our website at http://colobot.info/.
67 
68 \section Intro Introduction
69 
70 The source code released by Epitec was sparsely documented. This documentation, written from scratch,
71 will aim to describe the various components of the code.
72 
73 Currently, the only documented classes are the ones written from scratch or the old ones rewritten
74 to match the new code.
75 In time, the documentation will be extended to cover every major part of the code.
76 
77 \section Structure Code structure
78 
79 The source code was split from the original all-in-one directory to subdirectories,
80 each containing one major part of the project.
81 The current layout is the following:
82  - src/CBot - separate library with CBot language
83  - src/app - class CApplication and everything concerned with SDL
84  - src/common - shared structs, enums, defines, etc.; should not have any external dependencies
85  - src/common/resources - filesystem management using PHYSFS library
86  - src/common/system - system-dependent code such as displaying a message box, finding files, etc.
87  - src/common/thread - wrapper classes for SDL threads
88  - src/graphics/core - abstract interface of graphics device (abstract CDevice class)
89  - src/graphics/engine - main graphics engine based on abstract graphics device; is composed
90    of CEngine class and associated classes implementing the 3D engine
91  - src/graphics/model - code related to loading/saving model files
92  - src/graphics/opengl - concrete implementation of CDevice class in OpenGL: CGLDevice
93  - src/graphics/d3d - in (far) future - perhaps a newer implementation in DirectX (9? 10?)
94  - src/math - mathematical structures and functions
95  - src/object - non-grphical game object logic, that is robots, buildings, etc.
96  - src/level - main part of non-graphical game engine, that is loading levels etc.
97  - src/level/parser - parser for loading/saving level files from format known as <i>scene files</i>
98  - src/ui - 2D user interface (menu, buttons, check boxes, etc.)
99  - src/sound - sound and music engine written using fmod library
100  - src/physics - physics engine
101  - src/script - link with the CBot library
102 */
103 
104 //! Entry point to the program
105 extern "C"
106 {
107 
main(int argc,char * argv[])108 int main(int argc, char *argv[])
109 {
110     CLogger logger; // single instance of logger
111     logger.AddOutput(stderr);
112 
113     auto systemUtils = CSystemUtils::Create(); // platform-specific utils
114     systemUtils->Init();
115 
116     CProfiler::SetSystemUtils(systemUtils.get());
117 
118     // Add file output to the logger
119     std::string logFileName;
120     #if DEV_BUILD
121         logFileName = "log.txt";
122     #else
123         boost::filesystem::create_directories(systemUtils->GetSaveDir());
124         logFileName = systemUtils->GetSaveDir() + "/log.txt";
125     #endif
126     FILE* logFile = fopen(logFileName.c_str(), "w");
127     if (logFile)
128         logger.AddOutput(logFile);
129     else
130         logger.Error("Failed to create log file, writing log to file disabled\n");
131 
132 
133     // Workaround for character encoding in argv on Windows
134     #if PLATFORM_WINDOWS
135     int wargc = 0;
136     wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &wargc);
137     if (wargv == nullptr)
138     {
139         logger.Error("CommandLineToArgvW failed\n");
140         return 1;
141     }
142 
143     std::vector<std::vector<char>> windowsArgs;
144     for (int i = 0; i < wargc; i++)
145     {
146         std::wstring warg = wargv[i];
147         std::string arg = CSystemUtilsWindows::UTF8_Encode(warg);
148         std::vector<char> argVec(arg.begin(), arg.end());
149         argVec.push_back('\0');
150         windowsArgs.push_back(std::move(argVec));
151     }
152 
153     auto windowsArgvPtrs = MakeUniqueArray<char*>(wargc);
154     for (int i = 0; i < wargc; i++)
155         windowsArgvPtrs[i] = windowsArgs[i].data();
156 
157     argv = windowsArgvPtrs.get();
158 
159     LocalFree(wargv);
160     #endif
161 
162     logger.Info("%s starting\n", COLOBOT_FULLNAME);
163 
164     CSignalHandlers::Init(systemUtils.get());
165 
166     CResourceManager manager(argv[0]);
167 
168     // Initialize static string arrays
169     InitializeRestext();
170     InitializeEventTypeTexts();
171 
172     int code = 0;
173     CApplication app(systemUtils.get()); // single instance of the application
174 
175     app.LoadEnvironmentVariables();
176 
177     ParseArgsStatus status = app.ParseArguments(argc, argv);
178     if (status == PARSE_ARGS_FAIL)
179     {
180         systemUtils->SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", "Invalid commandline arguments!\n");
181         return app.GetExitCode();
182     }
183     else if (status == PARSE_ARGS_HELP)
184     {
185         return app.GetExitCode();
186     }
187 
188     if (! app.Create())
189     {
190         code = app.GetExitCode();
191         if (code != 0 && !app.GetErrorMessage().empty())
192         {
193             systemUtils->SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", app.GetErrorMessage());
194         }
195         logger.Info("Didn't run main loop. Exiting with code %d\n", code);
196         return code;
197     }
198 
199     code = app.Run();
200 
201     logger.Info("Exiting with code %d\n", code);
202 
203     return code;
204 }
205 
206 } // extern "C"
207