1
0
Fork 0
mirror of https://gitlab.com/niansa/llama_nds.git synced 2025-03-06 20:53:28 +01:00
llama_nds/Runtime.hpp
2023-04-03 22:06:29 +02:00

235 lines
5.8 KiB
C++

#ifndef _RUNTIME_HPP
#define _RUNTIME_HPP
#ifdef PLATFORM_3DS
#include <iostream>
#include <string>
#include <string_view>
#include <thread>
#include <chrono>
#include <exception>
#include <stdexcept>
#include <cstring>
#include <malloc.h>
#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 <iostream>
#include <string>
#include <string_view>
#include <thread>
#include <chrono>
#include <exception>
#include <stdexcept>
#include <malloc.h>
#include <nds.h>
#include <dswifi9.h>
class Runtime {
static void kbCallback(int key);
Keyboard *swkbd;
public:
Runtime() {
// 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 = keyboardDemoInit();
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 <iostream>
#include <stdexcept>
#include <mutex>
#include <cstring>
#include <csignal>
#include <cerrno>
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 <iostream>
#include <mutex>
#include <stdexcept>
#include <winsock2.h>
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();
}
};
#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