#include "common/assert.h" #include "common/file_system.h" #include "common/log.h" #include "common/string_util.h" #include "core/system.h" #include #include #include #include #ifdef USE_DRMKMS #include "drm_host_interface.h" #endif #ifdef WITH_SDL2 #include "sdl_host_interface.h" #endif #ifdef _WIN32 #include "common/windows_headers.h" #include "win32_host_interface.h" #include #endif static std::unique_ptr CreateHostInterface(const char* platform) { std::unique_ptr host_interface; #ifdef USE_DRMKMS // TODO: We should detect if we have a display here... if (!host_interface && (!platform || StringUtil::Strcasecmp(platform, "drm") == 0)) host_interface = DRMHostInterface::Create(); #endif #ifdef WITH_SDL2 if (!host_interface && (!platform || StringUtil::Strcasecmp(platform, "sdl") == 0)) host_interface = SDLHostInterface::Create(); #endif #ifdef _WIN32 if (!host_interface && (!platform || StringUtil::Strcasecmp(platform, "win32") == 0)) host_interface = Win32HostInterface::Create(); #endif return host_interface; } static int Run(std::unique_ptr host_interface, std::unique_ptr boot_params) { if (!host_interface->Initialize()) { host_interface->Shutdown(); return EXIT_FAILURE; } if (boot_params) host_interface->BootSystem(*boot_params); int result; if (System::IsValid() || !host_interface->InBatchMode()) { host_interface->Run(); result = EXIT_SUCCESS; } else { host_interface->ReportError("No file specified, and we're in batch mode. Exiting."); result = EXIT_FAILURE; } host_interface->Shutdown(); return result; } #ifdef _WIN32 int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) { std::unique_ptr host_interface = CreateHostInterface(nullptr); std::unique_ptr boot_params; { std::vector argc_strings; argc_strings.reserve(1); // CommandLineToArgvW() only adds the program path if the command line is empty?! argc_strings.push_back(FileSystem::GetProgramPath()); if (std::wcslen(lpCmdLine) > 0) { int argc; LPWSTR* argv_wide = CommandLineToArgvW(lpCmdLine, &argc); if (argv_wide) { for (int i = 0; i < argc; i++) argc_strings.push_back(StringUtil::WideStringToUTF8String(argv_wide[i])); LocalFree(argv_wide); } } std::vector argc_pointers; argc_pointers.reserve(argc_strings.size()); for (std::string& arg : argc_strings) argc_pointers.push_back(arg.data()); if (!host_interface->ParseCommandLineParameters(static_cast(argc_pointers.size()), argc_pointers.data(), &boot_params)) { return EXIT_FAILURE; } } return Run(std::move(host_interface), std::move(boot_params)); } #else int main(int argc, char* argv[]) { std::unique_ptr host_interface = CreateHostInterface(nullptr); std::unique_ptr boot_params; if (!host_interface->ParseCommandLineParameters(argc, argv, &boot_params)) return EXIT_FAILURE; return Run(std::move(host_interface), std::move(boot_params)); } #endif