openMSX
main.cc
Go to the documentation of this file.
1 /*
2  * openmsx - the MSX emulator that aims for perfection
3  *
4  */
5 
6 #include "openmsx.hh"
7 #include "Date.hh"
8 #include "Reactor.hh"
9 #include "CommandLineParser.hh"
10 #include "CliServer.hh"
11 #include "Display.hh"
12 #include "EventDistributor.hh"
13 #include "RenderSettings.hh"
14 #include "EnumSetting.hh"
15 #include "MSXException.hh"
16 #include "Thread.hh"
17 #include "build-info.hh"
18 #include "random.hh"
19 #include <iostream>
20 #include <exception>
21 #include <ctime>
22 #include <cstdio>
23 #include <cstdlib>
24 #include <SDL.h>
25 #ifdef _WIN32
26 #include "win32-arggen.hh"
27 #endif
28 
29 // Set LOG_TO_FILE to 1 for any platform on which stdout and stderr must
30 // be redirected to a file
31 // Also, specify the appropriate file names, depending on the platform conventions
32 #if PLATFORM_ANDROID
33 #define LOG_TO_FILE 1
34 #define STDOUT_LOG_FILE_NAME "openmsx_system/openmsx.stdout"
35 #define STDERR_LOG_FILE_NAME "openmsx_system/openmsx.stderr"
36 #else
37 #define LOG_TO_FILE 0
38 #endif
39 
40 namespace openmsx {
41 
42 static void initializeSDL()
43 {
44  int flags = 0;
45 #ifndef SDL_JOYSTICK_DISABLED
46  flags |= SDL_INIT_JOYSTICK;
47 #endif
48 #ifndef NDEBUG
49  flags |= SDL_INIT_NOPARACHUTE;
50 #endif
51  if (SDL_Init(flags) < 0) {
52  throw FatalError("Couldn't init SDL: ", SDL_GetError());
53  }
54 }
55 
56 static int main(int argc, char **argv)
57 {
58 #if LOG_TO_FILE
59  ad_printf("Redirecting stdout to %s and stderr to %s\n",
60  STDOUT_LOG_FILE_NAME, STDERR_LOG_FILE_NAME);
61 
62  if (!freopen(STDOUT_LOG_FILE_NAME, "a", stdout)) {
63  ad_printf("Couldn't redirect stdout to logfile, aborting\n");
64  std::cerr << "Couldn't redirect stdout to "
65  STDOUT_LOG_FILE_NAME "\n";
66  return 1;
67  }
68  if (!freopen(STDERR_LOG_FILE_NAME, "a", stderr)) {
69  ad_printf("Couldn't redirect stderr to logfile, aborting\n");
70  std::cout << "Couldn't redirect stderr to "
71  STDERR_LOG_FILE_NAME "\n";
72  return 1;
73  }
74 
75  std::string msg = Date::toString(time(nullptr)) + ": starting openMSX";
76  std::cout << msg << '\n';
77  std::cerr << msg << '\n';
78 #endif
79 
80  try {
81  randomize(); // seed global random generator
82  initializeSDL();
83 
85  Reactor reactor;
86 #ifdef _WIN32
87  ArgumentGenerator arggen;
88  argv = arggen.GetArguments(argc);
89 #endif
90  CommandLineParser parser(reactor);
91  parser.parse(argc, argv);
92  CommandLineParser::ParseStatus parseStatus = parser.getParseStatus();
93 
94  if (parseStatus != CommandLineParser::EXIT) {
95  if (!parser.isHiddenStartup()) {
96  auto& render = reactor.getDisplay().getRenderSettings().getRendererSetting();
97  render.setValue(render.getRestoreValue());
98  // Switching renderer requires events, handle
99  // these events before continuing with the rest
100  // of initialization. This fixes a bug where
101  // you have a '-script bla.tcl' command line
102  // argument where bla.tcl contains a line like
103  // 'ext gfx9000'.
104  reactor.getEventDistributor().deliverEvents();
105  }
106  if (parseStatus != CommandLineParser::TEST) {
107  CliServer cliServer(reactor.getCommandController(),
108  reactor.getEventDistributor(),
109  reactor.getGlobalCliComm());
110  reactor.run(parser);
111  }
112  }
113  } catch (FatalError& e) {
114  std::cerr << "Fatal error: " << e.getMessage() << '\n';
115  exitCode = 1;
116  } catch (MSXException& e) {
117  std::cerr << "Uncaught exception: " << e.getMessage() << '\n';
118  exitCode = 1;
119  } catch (std::exception& e) {
120  std::cerr << "Uncaught std::exception: " << e.what() << '\n';
121  exitCode = 1;
122  } catch (...) {
123  std::cerr << "Uncaught exception of unexpected type." << '\n';
124  exitCode = 1;
125  }
126  // Clean up.
127  if (SDL_WasInit(SDL_INIT_EVERYTHING)) {
128  SDL_Quit();
129  }
130 
131  return exitCode;
132 }
133 
134 } // namespace openmsx
135 
136 // Enter the openMSX namespace.
137 int main(int argc, char **argv)
138 {
139  // TODO with SDL1 we had the comment:
140  // need exit() iso return on win32/SDL
141  // Is that still the case with SDL2? Because for Android we need to
142  // return from main instead of exit().
143  return openmsx::main(argc, argv);
144 }
win32-arggen.hh
openmsx.hh
Display.hh
Date.hh
random.hh
CommandLineParser.hh
openmsx::Thread::setMainThread
void setMainThread()
Store ID of the main thread, should be called exactly once from the main thread.
Definition: Thread.cc:9
MSXException.hh
randomize
void randomize()
Seed the (shared) random number generator.
Definition: random.hh:16
Reactor.hh
openmsx::CommandLineParser::TEST
Definition: CommandLineParser.hh:35
EventDistributor.hh
build-info.hh
main
int main(int argc, char **argv)
Definition: main.cc:137
EnumSetting.hh
RenderSettings.hh
openmsx::Date::toString
std::string toString(time_t time)
Definition: Date.cc:150
CliServer.hh
openmsx::CommandLineParser::ParseStatus
ParseStatus
Definition: CommandLineParser.hh:35
ad_printf
#define ad_printf(...)
Definition: openmsx.hh:11
openmsx::CommandLineParser::EXIT
Definition: CommandLineParser.hh:35
Thread.hh
openmsx
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
openmsx::exitCode
int exitCode
Definition: Reactor.cc:61