1 /***************************************************************************
2 * Copyright (C) 2009 by Andrey Afletdinov <fheroes2@gmail.com> *
3 * *
4 * Part of the Free Heroes2 Engine: *
5 * http://sourceforge.net/projects/fheroes2 *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22
23 #include <cstdlib>
24 #include <iostream>
25 #include <string>
26
27 #include "agg.h"
28 #include "audio.h"
29 #include "bin_info.h"
30 #include "core.h"
31 #include "cursor.h"
32 #include "embedded_image.h"
33 #include "game.h"
34 #include "game_logo.h"
35 #include "game_video.h"
36 #include "image_palette.h"
37 #include "localevent.h"
38 #include "logging.h"
39 #include "screen.h"
40 #include "settings.h"
41 #include "system.h"
42 #ifdef WITH_DEBUG
43 #include "tools.h"
44 #endif
45 #include "ui_tool.h"
46 #include "zzlib.h"
47
48 namespace
49 {
GetCaption()50 std::string GetCaption()
51 {
52 return std::string( "Free Heroes of Might and Magic II, version: " + Settings::GetVersion() );
53 }
54
PrintHelp(const char * basename)55 int PrintHelp( const char * basename )
56 {
57 COUT( "Usage: " << basename << " [OPTIONS]" );
58 #ifdef WITH_DEBUG
59 COUT( " -d <level>\tprint debug messages, see src/engine/logging.h for possible values of <level> argument" );
60 #endif
61 COUT( " -h\t\tprint this help message and exit" );
62
63 return EXIT_SUCCESS;
64 }
65
ReadConfigs()66 void ReadConfigs()
67 {
68 const std::string configurationFileName( "fheroes2.cfg" );
69 const std::string confFile = Settings::GetLastFile( "", configurationFileName );
70
71 Settings & conf = Settings::Get();
72 if ( System::IsFile( confFile ) && conf.Read( confFile ) ) {
73 LocalEvent::Get().SetControllerPointerSpeed( conf.controllerPointerSpeed() );
74 }
75 else {
76 conf.Save( configurationFileName );
77 }
78 }
79
InitConfigDir()80 void InitConfigDir()
81 {
82 const std::string configDir = System::GetConfigDirectory( "fheroes2" );
83
84 if ( !configDir.empty() && !System::IsDirectory( configDir ) ) {
85 System::MakeDirectory( configDir );
86 }
87 }
88
InitDataDir()89 void InitDataDir()
90 {
91 const std::string dataDir = System::GetDataDirectory( "fheroes2" );
92
93 if ( dataDir.empty() )
94 return;
95
96 const std::string dataFiles = System::ConcatePath( dataDir, "files" );
97 const std::string dataFilesSave = System::ConcatePath( dataFiles, "save" );
98
99 if ( !System::IsDirectory( dataDir ) )
100 System::MakeDirectory( dataDir );
101
102 if ( System::IsDirectory( dataDir, true ) && !System::IsDirectory( dataFiles ) )
103 System::MakeDirectory( dataFiles );
104
105 if ( System::IsDirectory( dataFiles, true ) && !System::IsDirectory( dataFilesSave ) )
106 System::MakeDirectory( dataFilesSave );
107 }
108
109 class DisplayInitializer
110 {
111 public:
DisplayInitializer()112 DisplayInitializer()
113 {
114 const Settings & conf = Settings::Get();
115
116 fheroes2::engine().setVSync( conf.isVSyncEnabled() );
117
118 fheroes2::Display & display = fheroes2::Display::instance();
119 if ( conf.FullScreen() != fheroes2::engine().isFullScreen() )
120 fheroes2::engine().toggleFullScreen();
121
122 display.resize( conf.VideoMode().width, conf.VideoMode().height );
123 display.fill( 0 ); // start from a black screen
124
125 fheroes2::engine().setTitle( GetCaption() );
126
127 SDL_ShowCursor( SDL_DISABLE ); // hide system cursor
128
129 // Initialize local event processing.
130 LocalEvent::Get().RegisterCycling( fheroes2::PreRenderSystemInfo, fheroes2::PostRenderSystemInfo );
131
132 // Update mouse cursor when switching between software emulation and OS mouse modes.
133 fheroes2::cursor().registerUpdater( Cursor::Refresh );
134
135 const fheroes2::Image & appIcon = CreateImageFromZlib( 32, 32, iconImage, sizeof( iconImage ), true );
136 fheroes2::engine().setIcon( appIcon );
137 }
138
139 DisplayInitializer( const DisplayInitializer & ) = delete;
140 DisplayInitializer & operator=( const DisplayInitializer & ) = delete;
141
~DisplayInitializer()142 ~DisplayInitializer()
143 {
144 fheroes2::Display::instance().release();
145 }
146 };
147 }
148
149 #if defined( _MSC_VER )
150 #undef main
151 #endif
152
main(int argc,char ** argv)153 int main( int argc, char ** argv )
154 {
155 try {
156 const fheroes2::HardwareInitializer hardwareInitializer;
157 Logging::InitLog();
158
159 DEBUG_LOG( DBG_ALL, DBG_INFO, GetCaption() );
160
161 Settings & conf = Settings::Get();
162 conf.SetProgramPath( argv[0] );
163
164 InitConfigDir();
165 InitDataDir();
166 ReadConfigs();
167
168 // getopt
169 {
170 int opt;
171 while ( ( opt = System::GetCommandOptions( argc, argv, "hd:" ) ) != -1 )
172 switch ( opt ) {
173 #ifdef WITH_DEBUG
174 case 'd':
175 conf.SetDebug( System::GetOptionsArgument() ? GetInt( System::GetOptionsArgument() ) : 0 );
176 break;
177 #endif
178 case '?':
179 case 'h':
180 return PrintHelp( argv[0] );
181
182 default:
183 break;
184 }
185 }
186
187 std::set<fheroes2::SystemInitializationComponent> coreComponents{ fheroes2::SystemInitializationComponent::Audio,
188 fheroes2::SystemInitializationComponent::Video };
189
190 #if defined( FHEROES2_VITA ) || defined( __SWITCH__ )
191 coreComponents.emplace( fheroes2::SystemInitializationComponent::GameController );
192 #endif
193
194 const fheroes2::CoreInitializer coreInitializer( coreComponents );
195
196 if ( Audio::isValid() ) {
197 Mixer::SetChannels( 16 );
198 Mixer::Volume( -1, Mixer::MaxVolume() * conf.SoundVolume() / 10 );
199
200 Music::Volume( Mixer::MaxVolume() * conf.MusicVolume() / 10 );
201 Music::SetFadeIn( 900 );
202 }
203
204 DEBUG_LOG( DBG_GAME, DBG_INFO, conf.String() );
205
206 const DisplayInitializer displayInitializer;
207
208 const AGG::AGGInitializer aggInitializer;
209
210 // Load palette.
211 fheroes2::setGamePalette( AGG::ReadChunk( "KB.PAL" ) );
212
213 // load BIN data
214 Bin_Info::InitBinInfo();
215
216 // init game data
217 Game::Init();
218
219 conf.setGameLanguage( conf.getGameLanguage() );
220
221 if ( conf.isShowIntro() ) {
222 fheroes2::showTeamInfo();
223
224 Video::ShowVideo( "H2XINTRO.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END );
225 }
226
227 // init cursor
228 const CursorRestorer cursorRestorer( true, Cursor::POINTER );
229
230 Game::mainGameLoop( conf.isFirstGameRun() );
231 }
232 catch ( const std::exception & ex ) {
233 ERROR_LOG( "Exception '" << ex.what() << "' occured during application runtime." );
234 return EXIT_FAILURE;
235 }
236
237 return EXIT_SUCCESS;
238 }
239