2015-05-24 06:55:12 +02:00
|
|
|
// Copyright 2008 Dolphin Emulator Project
|
2015-05-18 01:08:10 +02:00
|
|
|
// Licensed under GPLv2+
|
2013-04-18 05:43:35 +02:00
|
|
|
// Refer to the license.txt file included.
|
2009-07-13 09:31:43 +02:00
|
|
|
|
2016-01-17 12:13:09 +01:00
|
|
|
#include <OptionParser.h>
|
2014-02-22 23:36:30 +01:00
|
|
|
#include <cstddef>
|
2014-02-17 11:18:15 +01:00
|
|
|
#include <cstdio>
|
2014-02-22 23:36:30 +01:00
|
|
|
#include <cstring>
|
2016-09-24 21:17:34 +02:00
|
|
|
#include <signal.h>
|
2014-03-12 20:33:41 +01:00
|
|
|
#include <string>
|
2016-05-12 03:18:30 +02:00
|
|
|
#include <thread>
|
2015-09-04 08:14:10 +02:00
|
|
|
#include <unistd.h>
|
2008-09-07 22:26:38 +02:00
|
|
|
|
2014-09-08 03:06:58 +02:00
|
|
|
#include "Common/CommonTypes.h"
|
2014-04-14 01:15:23 +02:00
|
|
|
#include "Common/Event.h"
|
2016-09-24 21:17:34 +02:00
|
|
|
#include "Common/Flag.h"
|
2014-06-06 01:29:54 +02:00
|
|
|
#include "Common/Logging/LogManager.h"
|
2016-06-24 10:43:46 +02:00
|
|
|
#include "Common/MsgHandler.h"
|
2009-05-15 10:55:46 +02:00
|
|
|
|
2016-06-18 02:43:59 +02:00
|
|
|
#include "Core/Analytics.h"
|
2017-05-27 15:43:40 +02:00
|
|
|
#include "Core/Boot/Boot.h"
|
2014-02-19 02:56:29 +01:00
|
|
|
#include "Core/BootManager.h"
|
|
|
|
#include "Core/ConfigManager.h"
|
|
|
|
#include "Core/Core.h"
|
|
|
|
#include "Core/HW/Wiimote.h"
|
2016-06-24 10:43:46 +02:00
|
|
|
#include "Core/Host.h"
|
2017-04-29 16:11:22 +02:00
|
|
|
#include "Core/IOS/IOS.h"
|
2017-01-18 13:50:28 +01:00
|
|
|
#include "Core/IOS/STM/STM.h"
|
|
|
|
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
|
|
|
|
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
|
2016-06-24 10:43:46 +02:00
|
|
|
#include "Core/State.h"
|
2014-02-19 02:56:29 +01:00
|
|
|
|
2016-01-17 12:13:09 +01:00
|
|
|
#include "UICommon/CommandLineParse.h"
|
2014-10-04 21:12:15 +02:00
|
|
|
#include "UICommon/UICommon.h"
|
|
|
|
|
2016-11-19 14:03:20 +01:00
|
|
|
#include "VideoCommon/RenderBase.h"
|
2014-02-19 02:56:29 +01:00
|
|
|
#include "VideoCommon/VideoBackendBase.h"
|
|
|
|
|
2014-08-07 03:24:42 +02:00
|
|
|
static bool rendererHasFocus = true;
|
2015-01-04 17:09:56 +01:00
|
|
|
static bool rendererIsFullscreen = false;
|
2016-09-24 21:17:34 +02:00
|
|
|
static Common::Flag s_running{true};
|
2016-10-01 21:35:29 +02:00
|
|
|
static Common::Flag s_shutdown_requested{false};
|
|
|
|
static Common::Flag s_tried_graceful_shutdown{false};
|
2016-09-24 21:17:34 +02:00
|
|
|
|
|
|
|
static void signal_handler(int)
|
|
|
|
{
|
|
|
|
const char message[] = "A signal was received. A second signal will force Dolphin to stop.\n";
|
|
|
|
if (write(STDERR_FILENO, message, sizeof(message)) < 0)
|
|
|
|
{
|
|
|
|
}
|
2016-10-01 21:35:29 +02:00
|
|
|
s_shutdown_requested.Set();
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace ProcessorInterface
|
|
|
|
{
|
|
|
|
void PowerButton_Tap();
|
2016-09-24 21:17:34 +02:00
|
|
|
}
|
2010-05-26 23:23:44 +02:00
|
|
|
|
2014-08-06 06:34:31 +02:00
|
|
|
class Platform
|
|
|
|
{
|
|
|
|
public:
|
2016-06-24 10:43:46 +02:00
|
|
|
virtual void Init() {}
|
|
|
|
virtual void SetTitle(const std::string& title) {}
|
|
|
|
virtual void MainLoop()
|
|
|
|
{
|
2016-09-24 21:17:34 +02:00
|
|
|
while (s_running.IsSet())
|
2016-06-24 10:43:46 +02:00
|
|
|
{
|
|
|
|
Core::HostDispatchJobs();
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
virtual void Shutdown() {}
|
|
|
|
virtual ~Platform() {}
|
2014-08-06 06:34:31 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static Platform* platform;
|
|
|
|
|
2016-06-24 10:43:46 +02:00
|
|
|
void Host_NotifyMapLoaded()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
void Host_RefreshDSPDebuggerWindow()
|
|
|
|
{
|
|
|
|
}
|
2008-09-07 22:26:38 +02:00
|
|
|
|
2014-08-07 03:24:42 +02:00
|
|
|
static Common::Event updateMainFrameEvent;
|
2010-03-16 14:18:52 +01:00
|
|
|
void Host_Message(int Id)
|
|
|
|
{
|
2016-06-24 10:43:46 +02:00
|
|
|
if (Id == WM_USER_STOP)
|
|
|
|
{
|
2016-09-24 21:17:34 +02:00
|
|
|
s_running.Clear();
|
2016-06-24 10:43:46 +02:00
|
|
|
updateMainFrameEvent.Set();
|
|
|
|
}
|
2010-03-16 14:18:52 +01:00
|
|
|
}
|
2008-09-07 22:26:38 +02:00
|
|
|
|
2016-01-26 14:35:17 +01:00
|
|
|
static void* s_window_handle = nullptr;
|
2011-02-12 22:25:49 +01:00
|
|
|
void* Host_GetRenderHandle()
|
|
|
|
{
|
2016-06-24 10:43:46 +02:00
|
|
|
return s_window_handle;
|
2011-02-12 22:25:49 +01:00
|
|
|
}
|
|
|
|
|
2014-08-06 06:44:21 +02:00
|
|
|
void Host_UpdateTitle(const std::string& title)
|
|
|
|
{
|
2016-06-24 10:43:46 +02:00
|
|
|
platform->SetTitle(title);
|
2014-08-06 06:44:21 +02:00
|
|
|
}
|
2010-04-19 05:06:18 +02:00
|
|
|
|
2016-06-24 10:43:46 +02:00
|
|
|
void Host_UpdateDisasmDialog()
|
|
|
|
{
|
|
|
|
}
|
2008-09-07 22:26:38 +02:00
|
|
|
|
2008-09-07 23:06:55 +02:00
|
|
|
void Host_UpdateMainFrame()
|
|
|
|
{
|
2016-06-24 10:43:46 +02:00
|
|
|
updateMainFrameEvent.Set();
|
2008-09-07 23:06:55 +02:00
|
|
|
}
|
2008-09-07 22:26:38 +02:00
|
|
|
|
2016-06-24 10:43:46 +02:00
|
|
|
void Host_RequestRenderWindowSize(int width, int height)
|
|
|
|
{
|
|
|
|
}
|
2014-07-16 15:53:33 +02:00
|
|
|
|
2014-07-16 16:24:40 +02:00
|
|
|
bool Host_UIHasFocus()
|
|
|
|
{
|
2016-06-24 10:43:46 +02:00
|
|
|
return false;
|
2014-07-16 16:24:40 +02:00
|
|
|
}
|
|
|
|
|
2010-04-12 03:33:10 +02:00
|
|
|
bool Host_RendererHasFocus()
|
|
|
|
{
|
2016-06-24 10:43:46 +02:00
|
|
|
return rendererHasFocus;
|
2010-04-12 03:33:10 +02:00
|
|
|
}
|
2008-09-07 22:26:38 +02:00
|
|
|
|
2015-01-04 17:09:56 +01:00
|
|
|
bool Host_RendererIsFullscreen()
|
|
|
|
{
|
2016-06-24 10:43:46 +02:00
|
|
|
return rendererIsFullscreen;
|
2015-01-04 17:09:56 +01:00
|
|
|
}
|
|
|
|
|
2015-06-01 14:47:18 +02:00
|
|
|
void Host_ConnectWiimote(int wm_idx, bool connect)
|
|
|
|
{
|
2017-04-29 16:11:22 +02:00
|
|
|
Core::QueueHostJob([=] {
|
|
|
|
const auto ios = IOS::HLE::GetIOS();
|
|
|
|
if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled)
|
|
|
|
return;
|
|
|
|
bool was_unpaused = Core::PauseAndLock(true);
|
|
|
|
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
|
|
|
|
ios->GetDeviceByName("/dev/usb/oh1/57e/305"));
|
|
|
|
if (bt)
|
|
|
|
bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
|
|
|
|
Host_UpdateMainFrame();
|
|
|
|
Core::PauseAndLock(false, was_unpaused);
|
|
|
|
});
|
2015-06-01 14:47:18 +02:00
|
|
|
}
|
2011-01-08 18:35:34 +01:00
|
|
|
|
2016-06-24 10:43:46 +02:00
|
|
|
void Host_SetWiiMoteConnectionState(int _State)
|
|
|
|
{
|
|
|
|
}
|
2008-10-30 17:36:45 +01:00
|
|
|
|
2016-06-26 08:06:23 +02:00
|
|
|
void Host_ShowVideoConfig(void*, const std::string&)
|
2016-06-24 10:43:46 +02:00
|
|
|
{
|
|
|
|
}
|
2014-08-02 08:21:03 +02:00
|
|
|
|
2016-11-10 17:55:21 +01:00
|
|
|
void Host_YieldToUI()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-01-19 17:11:07 +01:00
|
|
|
#if HAVE_X11
|
2014-08-06 06:34:31 +02:00
|
|
|
#include <X11/keysym.h>
|
2016-05-06 01:43:38 +02:00
|
|
|
#include "UICommon/X11Utils.h"
|
2010-11-25 03:26:46 +01:00
|
|
|
|
2014-08-06 06:34:31 +02:00
|
|
|
class PlatformX11 : public Platform
|
|
|
|
{
|
2016-06-24 10:43:46 +02:00
|
|
|
Display* dpy;
|
|
|
|
Window win;
|
|
|
|
Cursor blankCursor = None;
|
2010-04-22 06:28:34 +02:00
|
|
|
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
2016-06-24 10:43:46 +02:00
|
|
|
X11Utils::XRRConfiguration* XRRConfig;
|
2010-04-22 06:28:34 +02:00
|
|
|
#endif
|
|
|
|
|
2016-06-24 10:43:46 +02:00
|
|
|
void Init() override
|
|
|
|
{
|
|
|
|
XInitThreads();
|
|
|
|
dpy = XOpenDisplay(nullptr);
|
|
|
|
if (!dpy)
|
|
|
|
{
|
|
|
|
PanicAlert("No X11 display found");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), SConfig::GetInstance().iRenderWindowXPos,
|
|
|
|
SConfig::GetInstance().iRenderWindowYPos,
|
|
|
|
SConfig::GetInstance().iRenderWindowWidth,
|
|
|
|
SConfig::GetInstance().iRenderWindowHeight, 0, 0, BlackPixel(dpy, 0));
|
2016-11-19 14:03:20 +01:00
|
|
|
XSelectInput(dpy, win, StructureNotifyMask | KeyPressMask | FocusChangeMask);
|
2016-06-24 10:43:46 +02:00
|
|
|
Atom wmProtocols[1];
|
|
|
|
wmProtocols[0] = XInternAtom(dpy, "WM_DELETE_WINDOW", True);
|
|
|
|
XSetWMProtocols(dpy, win, wmProtocols, 1);
|
|
|
|
XMapRaised(dpy, win);
|
|
|
|
XFlush(dpy);
|
|
|
|
s_window_handle = (void*)win;
|
|
|
|
|
|
|
|
if (SConfig::GetInstance().bDisableScreenSaver)
|
|
|
|
X11Utils::InhibitScreensaver(dpy, win, true);
|
2014-08-06 06:34:31 +02:00
|
|
|
|
2010-04-22 06:28:34 +02:00
|
|
|
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
2016-06-24 10:43:46 +02:00
|
|
|
XRRConfig = new X11Utils::XRRConfiguration(dpy, win);
|
2010-04-22 06:28:34 +02:00
|
|
|
#endif
|
|
|
|
|
2016-06-24 10:43:46 +02:00
|
|
|
if (SConfig::GetInstance().bHideCursor)
|
|
|
|
{
|
|
|
|
// make a blank cursor
|
|
|
|
Pixmap Blank;
|
|
|
|
XColor DummyColor;
|
|
|
|
char ZeroData[1] = {0};
|
|
|
|
Blank = XCreateBitmapFromData(dpy, win, ZeroData, 1, 1);
|
|
|
|
blankCursor = XCreatePixmapCursor(dpy, Blank, Blank, &DummyColor, &DummyColor, 0, 0);
|
|
|
|
XFreePixmap(dpy, Blank);
|
|
|
|
XDefineCursor(dpy, win, blankCursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetTitle(const std::string& string) override { XStoreName(dpy, win, string.c_str()); }
|
|
|
|
void MainLoop() override
|
|
|
|
{
|
|
|
|
bool fullscreen = SConfig::GetInstance().bFullscreen;
|
2016-11-19 14:03:20 +01:00
|
|
|
int last_window_width = SConfig::GetInstance().iRenderWindowWidth;
|
|
|
|
int last_window_height = SConfig::GetInstance().iRenderWindowHeight;
|
2016-06-24 10:43:46 +02:00
|
|
|
|
|
|
|
if (fullscreen)
|
|
|
|
{
|
|
|
|
rendererIsFullscreen = X11Utils::ToggleFullscreen(dpy, win);
|
2014-08-06 06:34:31 +02:00
|
|
|
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
2016-06-24 10:43:46 +02:00
|
|
|
XRRConfig->ToggleDisplayMode(True);
|
2014-08-06 06:34:31 +02:00
|
|
|
#endif
|
2016-06-24 10:43:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// The actual loop
|
2016-09-24 21:17:34 +02:00
|
|
|
while (s_running.IsSet())
|
2016-06-24 10:43:46 +02:00
|
|
|
{
|
2016-10-01 21:35:29 +02:00
|
|
|
if (s_shutdown_requested.TestAndClear())
|
|
|
|
{
|
2017-04-29 16:11:22 +02:00
|
|
|
const auto ios = IOS::HLE::GetIOS();
|
|
|
|
const auto stm = ios ? ios->GetDeviceByName("/dev/stm/eventhook") : nullptr;
|
2016-10-04 22:58:01 +02:00
|
|
|
if (!s_tried_graceful_shutdown.IsSet() && stm &&
|
2017-01-18 20:27:51 +01:00
|
|
|
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->HasHookInstalled())
|
2016-10-01 21:35:29 +02:00
|
|
|
{
|
|
|
|
ProcessorInterface::PowerButton_Tap();
|
|
|
|
s_tried_graceful_shutdown.Set();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s_running.Clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-24 10:43:46 +02:00
|
|
|
XEvent event;
|
|
|
|
KeySym key;
|
|
|
|
for (int num_events = XPending(dpy); num_events > 0; num_events--)
|
|
|
|
{
|
|
|
|
XNextEvent(dpy, &event);
|
|
|
|
switch (event.type)
|
|
|
|
{
|
|
|
|
case KeyPress:
|
|
|
|
key = XLookupKeysym((XKeyEvent*)&event, 0);
|
|
|
|
if (key == XK_Escape)
|
|
|
|
{
|
2017-02-05 13:39:58 +01:00
|
|
|
if (Core::GetState() == Core::State::Running)
|
2016-06-24 10:43:46 +02:00
|
|
|
{
|
|
|
|
if (SConfig::GetInstance().bHideCursor)
|
|
|
|
XUndefineCursor(dpy, win);
|
2017-02-05 13:39:58 +01:00
|
|
|
Core::SetState(Core::State::Paused);
|
2016-06-24 10:43:46 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (SConfig::GetInstance().bHideCursor)
|
|
|
|
XDefineCursor(dpy, win, blankCursor);
|
2017-02-05 13:39:58 +01:00
|
|
|
Core::SetState(Core::State::Running);
|
2016-06-24 10:43:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((key == XK_Return) && (event.xkey.state & Mod1Mask))
|
|
|
|
{
|
|
|
|
fullscreen = !fullscreen;
|
|
|
|
X11Utils::ToggleFullscreen(dpy, win);
|
2010-04-22 06:28:34 +02:00
|
|
|
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
2016-06-24 10:43:46 +02:00
|
|
|
XRRConfig->ToggleDisplayMode(fullscreen);
|
2010-04-22 06:28:34 +02:00
|
|
|
#endif
|
2016-06-24 10:43:46 +02:00
|
|
|
}
|
|
|
|
else if (key >= XK_F1 && key <= XK_F8)
|
|
|
|
{
|
|
|
|
int slot_number = key - XK_F1 + 1;
|
|
|
|
if (event.xkey.state & ShiftMask)
|
|
|
|
State::Save(slot_number);
|
|
|
|
else
|
|
|
|
State::Load(slot_number);
|
|
|
|
}
|
|
|
|
else if (key == XK_F9)
|
|
|
|
Core::SaveScreenShot();
|
|
|
|
else if (key == XK_F11)
|
|
|
|
State::LoadLastSaved();
|
|
|
|
else if (key == XK_F12)
|
|
|
|
{
|
|
|
|
if (event.xkey.state & ShiftMask)
|
|
|
|
State::UndoLoadState();
|
|
|
|
else
|
|
|
|
State::UndoSaveState();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FocusIn:
|
|
|
|
rendererHasFocus = true;
|
2017-02-05 13:39:58 +01:00
|
|
|
if (SConfig::GetInstance().bHideCursor && Core::GetState() != Core::State::Paused)
|
2016-06-24 10:43:46 +02:00
|
|
|
XDefineCursor(dpy, win, blankCursor);
|
|
|
|
break;
|
|
|
|
case FocusOut:
|
|
|
|
rendererHasFocus = false;
|
|
|
|
if (SConfig::GetInstance().bHideCursor)
|
|
|
|
XUndefineCursor(dpy, win);
|
|
|
|
break;
|
|
|
|
case ClientMessage:
|
|
|
|
if ((unsigned long)event.xclient.data.l[0] == XInternAtom(dpy, "WM_DELETE_WINDOW", False))
|
2016-10-01 21:35:29 +02:00
|
|
|
s_shutdown_requested.Set();
|
2016-06-24 10:43:46 +02:00
|
|
|
break;
|
2016-11-19 14:03:20 +01:00
|
|
|
case ConfigureNotify:
|
|
|
|
{
|
|
|
|
if (last_window_width != event.xconfigure.width ||
|
|
|
|
last_window_height != event.xconfigure.height)
|
|
|
|
{
|
|
|
|
last_window_width = event.xconfigure.width;
|
|
|
|
last_window_height = event.xconfigure.height;
|
|
|
|
|
|
|
|
// We call Renderer::ChangeSurface here to indicate the size has changed,
|
|
|
|
// but pass the same window handle. This is needed for the Vulkan backend,
|
|
|
|
// otherwise it cannot tell that the window has been resized on some drivers.
|
|
|
|
if (g_renderer)
|
|
|
|
g_renderer->ChangeSurface(s_window_handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2016-06-24 10:43:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!fullscreen)
|
|
|
|
{
|
|
|
|
Window winDummy;
|
|
|
|
unsigned int borderDummy, depthDummy;
|
|
|
|
XGetGeometry(dpy, win, &winDummy, &SConfig::GetInstance().iRenderWindowXPos,
|
|
|
|
&SConfig::GetInstance().iRenderWindowYPos,
|
|
|
|
(unsigned int*)&SConfig::GetInstance().iRenderWindowWidth,
|
|
|
|
(unsigned int*)&SConfig::GetInstance().iRenderWindowHeight, &borderDummy,
|
|
|
|
&depthDummy);
|
|
|
|
rendererIsFullscreen = false;
|
|
|
|
}
|
|
|
|
Core::HostDispatchJobs();
|
|
|
|
usleep(100000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Shutdown() override
|
|
|
|
{
|
2010-04-22 06:28:34 +02:00
|
|
|
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
2016-06-24 10:43:46 +02:00
|
|
|
delete XRRConfig;
|
2010-04-22 06:28:34 +02:00
|
|
|
#endif
|
2010-11-25 03:26:46 +01:00
|
|
|
|
2016-06-24 10:43:46 +02:00
|
|
|
if (SConfig::GetInstance().bHideCursor)
|
|
|
|
XFreeCursor(dpy, blankCursor);
|
2014-08-06 06:34:31 +02:00
|
|
|
|
2016-06-24 10:43:46 +02:00
|
|
|
XCloseDisplay(dpy);
|
|
|
|
}
|
2014-08-06 06:34:31 +02:00
|
|
|
};
|
2010-04-22 06:28:34 +02:00
|
|
|
#endif
|
2009-01-12 21:52:45 +01:00
|
|
|
|
2014-08-06 06:34:31 +02:00
|
|
|
static Platform* GetPlatform()
|
2010-06-04 06:59:07 +02:00
|
|
|
{
|
2017-04-16 04:23:19 +02:00
|
|
|
#if defined(USE_HEADLESS)
|
2016-06-24 10:43:46 +02:00
|
|
|
return new Platform();
|
2016-01-26 14:35:17 +01:00
|
|
|
#elif HAVE_X11
|
2016-06-24 10:43:46 +02:00
|
|
|
return new PlatformX11();
|
2011-03-09 00:25:37 +01:00
|
|
|
#endif
|
2016-06-24 10:43:46 +02:00
|
|
|
return nullptr;
|
2014-08-06 06:34:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
|
|
{
|
2016-01-17 12:13:09 +01:00
|
|
|
auto parser = CommandLineParse::CreateParser(CommandLineParse::ParserOptions::OmitGUIOptions);
|
|
|
|
optparse::Values& options = CommandLineParse::ParseArguments(parser.get(), argc, argv);
|
|
|
|
std::vector<std::string> args = parser->args();
|
2016-06-24 10:43:46 +02:00
|
|
|
|
2017-02-28 20:36:11 +01:00
|
|
|
std::string boot_filename;
|
2016-01-17 12:13:09 +01:00
|
|
|
if (options.is_set("exec"))
|
2016-06-24 10:43:46 +02:00
|
|
|
{
|
2016-01-17 12:13:09 +01:00
|
|
|
boot_filename = static_cast<const char*>(options.get("exec"));
|
2016-06-24 10:43:46 +02:00
|
|
|
}
|
2016-01-17 12:13:09 +01:00
|
|
|
else if (args.size())
|
2016-06-24 10:43:46 +02:00
|
|
|
{
|
2016-01-17 12:13:09 +01:00
|
|
|
boot_filename = args.front();
|
|
|
|
args.erase(args.begin());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
parser->print_help();
|
|
|
|
return 0;
|
2016-06-24 10:43:46 +02:00
|
|
|
}
|
|
|
|
|
2017-02-28 20:36:11 +01:00
|
|
|
std::string user_directory;
|
|
|
|
if (options.is_set("user"))
|
|
|
|
{
|
|
|
|
user_directory = static_cast<const char*>(options.get("user"));
|
|
|
|
}
|
|
|
|
|
2016-06-24 10:43:46 +02:00
|
|
|
platform = GetPlatform();
|
|
|
|
if (!platform)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "No platform found\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-02-28 20:36:11 +01:00
|
|
|
UICommon::SetUserDirectory(user_directory);
|
2016-06-24 10:43:46 +02:00
|
|
|
UICommon::Init();
|
|
|
|
|
2016-10-01 21:35:29 +02:00
|
|
|
Core::SetOnStoppedCallback([]() { s_running.Clear(); });
|
2016-06-24 10:43:46 +02:00
|
|
|
platform->Init();
|
|
|
|
|
2016-09-24 21:17:34 +02:00
|
|
|
// Shut down cleanly on SIGINT and SIGTERM
|
|
|
|
struct sigaction sa;
|
|
|
|
sa.sa_handler = signal_handler;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
sa.sa_flags = SA_RESETHAND;
|
|
|
|
sigaction(SIGINT, &sa, nullptr);
|
|
|
|
sigaction(SIGTERM, &sa, nullptr);
|
|
|
|
|
2016-06-24 10:43:46 +02:00
|
|
|
DolphinAnalytics::Instance()->ReportDolphinStart("nogui");
|
|
|
|
|
2017-05-27 15:43:40 +02:00
|
|
|
if (!BootManager::BootCore(BootParameters::GenerateFromFile(boot_filename)))
|
2016-06-24 10:43:46 +02:00
|
|
|
{
|
2016-01-17 12:13:09 +01:00
|
|
|
fprintf(stderr, "Could not boot %s\n", boot_filename.c_str());
|
2016-06-24 10:43:46 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-09-24 21:17:34 +02:00
|
|
|
while (!Core::IsRunning() && s_running.IsSet())
|
2016-06-24 10:43:46 +02:00
|
|
|
{
|
|
|
|
Core::HostDispatchJobs();
|
|
|
|
updateMainFrameEvent.Wait();
|
|
|
|
}
|
|
|
|
|
2016-09-24 21:17:34 +02:00
|
|
|
if (s_running.IsSet())
|
2016-06-24 10:43:46 +02:00
|
|
|
platform->MainLoop();
|
|
|
|
Core::Stop();
|
|
|
|
|
|
|
|
Core::Shutdown();
|
|
|
|
platform->Shutdown();
|
|
|
|
UICommon::Shutdown();
|
|
|
|
|
|
|
|
delete platform;
|
|
|
|
|
|
|
|
return 0;
|
2008-09-07 22:26:38 +02:00
|
|
|
}
|