OXYGENHUB
◆ main openmsx / src / main.cc
3.7 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
/*
2
 *  openmsx - the MSX emulator that aims for perfection
3
 *
4
 */
5
6
#include "CliServer.hh"
7
#include "CommandLineParser.hh"
8
#include "Display.hh"
9
#include "EnumSetting.hh"
10
#include "EventDistributor.hh"
11
#include "MSXException.hh"
12
#include "Reactor.hh"
13
#include "RenderSettings.hh"
14
#include "Thread.hh"
15
16
#include "one_of.hh"
17
#include "random.hh"
18
#include "setenv.hh" // setenv() for windows
19
20
#include <SDL.h>
21
22
#include <cstdio>
23
#include <cstdlib>
24
#include <ctime>
25
#include <exception>
26
#include <iostream>
27
#ifdef _WIN32
28
#include "win32-arggen.hh"
29
#endif
30
31
namespace openmsx {
32
33
#ifdef _WIN32
34
// enable console output on Windows
35
static void EnableConsoleOutput()
36
{
37
    if (AttachConsole(ATTACH_PARENT_PROCESS)) {
38
        freopen("CONOUT$", "w", stdout);
39
        freopen("CONOUT$", "w", stderr);
40
    }
41
}
42
#endif
43
44
static void initializeSDL()
45
{
46
	int flags = 0;
47
	flags |= SDL_INIT_JOYSTICK;
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
	// for now: instruct FreeType to use the v35 TTF engine
56
	// this is the rendering we had before FreeType implemented and
57
	// switched over to the v40 engine. To keep this the same for now, we
58
	// select the old engine explicitly, until we decide how to continue
59
	// (e.g. just use v40 or use a font that renders better on v40
60
	setenv("FREETYPE_PROPERTIES", "truetype:interpreter-version=35", 0);
61
}
62
63
static int main(int argc, char **argv)
64
{
65
#ifdef _WIN32
66
    EnableConsoleOutput();
67
#endif
68
69
	try {
70
		randomize(); // seed global random generator
71
		initializeSDL();
72
73
		Thread::setMainThread();
74
		Reactor reactor;
75
#ifdef _WIN32
76
		(void)argc; (void)argv;
77
		ArgumentGenerator argGen;
78
		auto args = argGen.getArgs();
79
#else
80
		std::span<char*> args{argv, size_t(argc)};
81
#endif
82
		CommandLineParser parser(reactor);
83
		parser.parse(args);
84
		auto parseStatus = parser.getParseStatus();
85
86
		if (parseStatus != one_of(CommandLineParser::Status::EXIT, CommandLineParser::Status::TEST)) {
87
			reactor.runStartupScripts(parser);
88
89
			auto& display = reactor.getDisplay();
90
			auto& render = display.getRenderSettings().getRendererSetting();
91
			if ((render.getEnum() == RenderSettings::RendererID::UNINITIALIZED) &&
92
			    (parseStatus != CommandLineParser::Status::CONTROL)) {
93
				render.setValue(render.getDefaultValue());
94
				// Switching renderer requires events, handle
95
				// these events before continuing with the rest
96
				// of initialization. This fixes a bug where
97
				// you have a '-script bla.tcl' command line
98
				// argument where bla.tcl contains a line like
99
				// 'ext gfx9000'.
100
				reactor.getEventDistributor().deliverEvents();
101
			}
102
103
			CliServer cliServer(reactor.getCommandController(),
104
			                    reactor.getEventDistributor(),
105
			                    reactor.getGlobalCliComm());
106
107
			if (parser.getParseStatus() == CommandLineParser::Status::RUN) {
108
				reactor.powerOn();
109
			}
110
			display.repaint();
111
			reactor.run();
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
}