#ifndef _RUNTIME_HPP #define _RUNTIME_HPP #ifdef PLATFORM_3DS #include #include #include #include #include #include #include #include #include #include <3ds.h> class Runtime { u32 *SOC_buffer = NULL; constexpr static auto SOC_ALIGN = 0x1000, SOC_BUFFERSIZE = 0x100000; [[noreturn]] static void customTerminate() noexcept; public: Runtime() { std::set_terminate(customTerminate); gfxInitDefault(); consoleInit(GFX_TOP, NULL); aptInit(); SOC_buffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE); auto ret = socInit(SOC_buffer, SOC_BUFFERSIZE); if (ret != 0) { throw std::runtime_error("socInit() = "+std::to_string((unsigned int)ret)); } } Runtime(Runtime&) = delete; Runtime(const Runtime&) = delete; Runtime(Runtime&&) = delete; ~Runtime() { aptSetHomeAllowed(false); std::cout << std::flush; std::cerr << std::flush; std::clog << std::endl << "Runtime destroyed." << std::endl; std::clog << "Press START to exit" << std::flush; for (u32 kDown; !(hidKeysDown() & KEY_START) && cooperate(); hidScanInput()) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } aptExit(); socExit(); gfxExit(); } static inline bool cooperate() noexcept { return aptMainLoop(); } static const char *readInput(const char *hint) { static SwkbdState swkbd; static char swkbd_buf[2048]; // Read input memset(swkbd_buf, 0, sizeof(swkbd_buf)); swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 3, sizeof(swkbd_buf)); swkbdSetHintText(&swkbd, hint); swkbdInputText(&swkbd, swkbd_buf, sizeof(swkbd_buf)); // Return input as string return swkbd_buf; } static void clearScreen() { consoleClear(); } }; #elif PLATFORM_DS #include #include #include #include #include #include #include #include #include #include class Runtime { static void kbCallback(int key); Keyboard *swkbd; public: Runtime() { // Configure video videoSetMode(MODE_0_2D); lcdMainOnBottom(); // Initialize console consoleDemoInit(); // Initialize WiFi std::cout << "Connecting via WFC data" << std::endl; if (!Wifi_InitDefault(WFC_CONNECT)) { throw std::runtime_error("Failed to enable WiFi"); } // Initialize keyboard swkbd = keyboardGetDefault(); swkbd = keyboardInit(swkbd, 3, BgType_Text4bpp, BgSize_T_256x512, swkbd->mapBase, swkbd->tileBase, true, true); swkbd->OnKeyPressed = kbCallback; } Runtime(Runtime&) = delete; Runtime(const Runtime&) = delete; Runtime(Runtime&&) = delete; ~Runtime() {} static inline bool cooperate() noexcept { // The Nintendo DS does not support multitasking return true; } static const char *readInput(const char *hint) { std::cout << hint << ": " << std::flush; static std::string outstr; std::getline(std::cin, outstr); return outstr.c_str(); } static void clearScreen() { consoleClear(); } }; #elif PLATFORM_LINUX #include #include #include #include #include #include class Runtime { static inline bool stopping = false; static inline void handler(int signo, siginfo_t *info, void *context) { stopping = true; } public: Runtime() { struct sigaction act = { 0 }; act.sa_flags = SA_SIGINFO; act.sa_sigaction = handler; for (int sig : {SIGTERM, SIGINT, SIGQUIT, SIGHUP}) { if (sigaction(sig, &act, nullptr) < 0) { throw std::runtime_error("sigaction() = "+std::string(strerror(errno))); } } } Runtime(Runtime&) = delete; Runtime(const Runtime&) = delete; Runtime(Runtime&&) = delete; ~Runtime() { std::cout << std::flush; std::cerr << std::flush; std::clog << std::endl << "Runtime destroyed." << std::endl; } static inline bool cooperate() noexcept { // Linux runs threads preemptively, no need to actually cooperate return !stopping; } static const char *readInput(const char *hint) { static std::string content; std::cout << hint << ": "; std::getline(std::cin, content); return content.c_str(); } static void clearScreen() { std::cout << "\033[H\033[2J\033[3J"; } }; #elif PLATFORM_WINDOWS #include #include #include #include class Runtime { public: Runtime() { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { throw std::runtime_error("Failed to initialize WinSock"); } } Runtime(Runtime&) = delete; Runtime(const Runtime&) = delete; Runtime(Runtime&&) = delete; ~Runtime() { std::cout << std::flush; std::cerr << std::flush; std::clog << std::endl << "Runtime destroyed." << std::endl; WSACleanup(); } static constexpr bool cooperate() noexcept { // Windows runs threads preemptively, no need to cooperate. // No signals to handle either, Windows doesn't support them. return true; } static const char *readInput(const char *hint) { static std::string content; std::cout << hint << ": "; std::getline(std::cin, content); return content.c_str(); } static void clearScreen() { system("cls"); } }; #endif #endif #if !(defined(PLATFORM_WINDOWS) || defined(PLATFORM_DS)) # define MSG_FLAGS_OR_ZERO(...) __VA_ARGS__ #else # define MSG_FLAGS_OR_ZERO(...) 0 #endif #ifdef PLATFORM_DS # define IPPROTO_TCP 0 #endif #ifndef PLATFORM_DS # define HAS_ADDRINFO #endif