diff --git a/include/emulator.hpp b/include/emulator.hpp index 66aeb27e..de04648e 100644 --- a/include/emulator.hpp +++ b/include/emulator.hpp @@ -87,7 +87,6 @@ class Emulator { bool frameDone = false; Emulator(); - Emulator(const std::filesystem::path& configPath); ~Emulator(); void step(); @@ -130,10 +129,10 @@ class Emulator { Renderer* getRenderer() { return gpu.getRenderer(); } u64 getTicks() { return cpu.getTicks(); } - virtual std::filesystem::path getConfigPath(); - virtual std::filesystem::path getAndroidAppPath(); + std::filesystem::path getConfigPath(); + std::filesystem::path getAndroidAppPath(); // Get the root path for the emulator's app data - virtual std::filesystem::path getAppDataRoot(); + std::filesystem::path getAppDataRoot(); std::span getSMDH(); }; diff --git a/src/emulator.cpp b/src/emulator.cpp index a7d859be..db6c2e1f 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -17,10 +17,7 @@ __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 1; #endif Emulator::Emulator() - : Emulator(getConfigPath()) {} - -Emulator::Emulator(const std::filesystem::path& configPath) - : config(configPath), kernel(cpu, memory, gpu, config), cpu(memory, kernel, *this), gpu(memory, config), memory(cpu.getTicksRef(), config), + : config(getConfigPath()), kernel(cpu, memory, gpu, config), cpu(memory, kernel, *this), gpu(memory, config), memory(cpu.getTicksRef(), config), cheats(memory, kernel.getServiceManager().getHID()), lua(*this), running(false) #ifdef PANDA3DS_ENABLE_HTTP_SERVER , @@ -87,6 +84,7 @@ void Emulator::reset(ReloadOption reload) { } } +#ifndef __LIBRETRO__ std::filesystem::path Emulator::getAndroidAppPath() { // SDL_GetPrefPath fails to get the path due to no JNI environment std::ifstream cmdline("/proc/self/cmdline"); @@ -103,6 +101,7 @@ std::filesystem::path Emulator::getConfigPath() { return std::filesystem::current_path() / "config.toml"; } } +#endif void Emulator::step() {} void Emulator::render() {} @@ -182,6 +181,7 @@ void Emulator::pollScheduler() { } } +#ifndef __LIBRETRO__ // Get path for saving files (AppData on Windows, /home/user/.local/share/ApplicationName on Linux, etc) // Inside that path, we be use a game-specific folder as well. Eg if we were loading a ROM called PenguinDemo.3ds, the savedata would be in // %APPDATA%/Alber/PenguinDemo/SaveData on Windows, and so on. We do this because games save data in their own filesystem on the cart. @@ -205,6 +205,7 @@ std::filesystem::path Emulator::getAppDataRoot() { return appDataPath; } +#endif bool Emulator::loadROM(const std::filesystem::path& path) { // Reset the emulator if we've already loaded a ROM diff --git a/src/libretro_core.cpp b/src/libretro_core.cpp index 10934233..c329b881 100644 --- a/src/libretro_core.cpp +++ b/src/libretro_core.cpp @@ -6,391 +6,361 @@ #include #include -static retro_environment_t environ_cb; -static retro_video_refresh_t video_cb; -static retro_audio_sample_batch_t audio_batch_cb; -static retro_input_poll_t input_poll_cb; -static retro_input_state_t input_state_cb; +static retro_environment_t envCallbacks; +static retro_video_refresh_t videoCallbacks; +static retro_audio_sample_batch_t audioBatchCallback; +static retro_input_poll_t inputPollCallback; +static retro_input_state_t inputStateCallback; -static struct retro_hw_render_callback hw_render; -static std::filesystem::path retro_save_dir; +static retro_hw_render_callback hw_render; +static std::filesystem::path savePath; -class EmulatorCore : public Emulator { - public: - EmulatorCore() : Emulator(getConfigPath()) {} - std::filesystem::path getConfigPath() override; - std::filesystem::path getAppDataRoot() override; -}; - -std::unique_ptr emulator; +std::unique_ptr emulator; RendererGL* renderer; -std::filesystem::path EmulatorCore::getConfigPath() { - return std::filesystem::path(retro_save_dir / "config.toml"); +std::filesystem::path Emulator::getConfigPath() { + return std::filesystem::path(savePath / "config.toml"); } -std::filesystem::path EmulatorCore::getAppDataRoot() { - return std::filesystem::path(retro_save_dir / "Emulator Files"); +std::filesystem::path Emulator::getAppDataRoot() { + return std::filesystem::path(savePath / "Emulator Files"); } -static void* GetRenderProcAddress(const char* name) { - return (void*)hw_render.get_proc_address(name); +static void* GetGLProcAddress(const char* name) { + return (void*)hw_render.get_proc_address(name); } -static void VideoResetContext(void) { +static void VideoResetContext() { #ifdef USING_GLES - if (!gladLoadGLES2Loader(reinterpret_cast(GetRenderProcAddress))) { - Helpers::panic("OpenGL ES init failed"); - } + if (!gladLoadGLES2Loader(reinterpret_cast(GetGLProcAddress))) { + Helpers::panic("OpenGL ES init failed"); + } #else - if (!gladLoadGLLoader(reinterpret_cast(GetRenderProcAddress))) { - Helpers::panic("OpenGL init failed"); - } + if (!gladLoadGLLoader(reinterpret_cast(GetGLProcAddress))) { + Helpers::panic("OpenGL init failed"); + } #endif - emulator->initGraphicsContext(nullptr); + emulator->initGraphicsContext(nullptr); } -static void VideoDestroyContext(void) { +static void VideoDestroyContext() { emulator->deinitGraphicsContext(); } static bool SetHWRender(retro_hw_context_type type) { - hw_render.context_type = type; - hw_render.context_reset = VideoResetContext; - hw_render.context_destroy = VideoDestroyContext; - hw_render.bottom_left_origin = true; + hw_render.context_type = type; + hw_render.context_reset = VideoResetContext; + hw_render.context_destroy = VideoDestroyContext; + hw_render.bottom_left_origin = true; - switch (type) { - case RETRO_HW_CONTEXT_OPENGL_CORE: - hw_render.version_major = 4; - hw_render.version_minor = 1; + switch (type) { + case RETRO_HW_CONTEXT_OPENGL_CORE: + hw_render.version_major = 4; + hw_render.version_minor = 1; - if (environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render)) { - return true; - } - break; - case RETRO_HW_CONTEXT_OPENGLES3: - case RETRO_HW_CONTEXT_OPENGL: - hw_render.version_major = 3; - hw_render.version_minor = 1; + if (envCallbacks(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render)) { + return true; + } + break; + case RETRO_HW_CONTEXT_OPENGLES3: + case RETRO_HW_CONTEXT_OPENGL: + hw_render.version_major = 3; + hw_render.version_minor = 1; - if (environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render)) { - return true; - } - break; - default: - break; - } + if (envCallbacks(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render)) { + return true; + } + break; + default: break; + } - return false; + return false; } -static void VideoInit(void) { - retro_hw_context_type preferred = RETRO_HW_CONTEXT_NONE; - environ_cb(RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER, &preferred); +static void videoInit() { + retro_hw_context_type preferred = RETRO_HW_CONTEXT_NONE; + envCallbacks(RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER, &preferred); - if (preferred && SetHWRender(preferred)) - return; - if (SetHWRender(RETRO_HW_CONTEXT_OPENGL_CORE)) - return; - if (SetHWRender(RETRO_HW_CONTEXT_OPENGL)) - return; - if (SetHWRender(RETRO_HW_CONTEXT_OPENGLES3)) - return; + if (preferred && SetHWRender(preferred)) return; + if (SetHWRender(RETRO_HW_CONTEXT_OPENGL_CORE)) return; + if (SetHWRender(RETRO_HW_CONTEXT_OPENGL)) return; + if (SetHWRender(RETRO_HW_CONTEXT_OPENGLES3)) return; - hw_render.context_type = RETRO_HW_CONTEXT_NONE; + hw_render.context_type = RETRO_HW_CONTEXT_NONE; } -static bool GetButtonState(unsigned id) { - return input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, id); -} +static bool GetButtonState(uint id) { return inputStateCallback(0, RETRO_DEVICE_JOYPAD, 0, id); } +static float GetAxisState(uint index, uint id) { return inputStateCallback(0, RETRO_DEVICE_ANALOG, index, id); } -static float GetAxisState(unsigned index, unsigned id) { - return input_state_cb(0, RETRO_DEVICE_ANALOG, index, id); -} +static void inputInit() { + static const retro_controller_description controllers[] = { + {"Nintendo 3DS", RETRO_DEVICE_JOYPAD}, + {NULL, 0}, + }; -static void InputInit(void) { - static const struct retro_controller_description controllers[] = { - { "Nintendo 3DS", RETRO_DEVICE_JOYPAD }, - { NULL, 0 }, - }; + static const retro_controller_info ports[] = { + {controllers, 1}, + {NULL, 0}, + }; - static const struct retro_controller_info ports[] = { - { controllers, 1 }, - { NULL, 0 }, - }; + envCallbacks(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports); - environ_cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports); + retro_input_descriptor desc[] = { + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "X"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Y"}, + {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Circle Pad X"}, + {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Circle Pad Y"}, + {0}, + }; - struct retro_input_descriptor desc[] = { - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "X" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Y" }, - { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Circle Pad X" }, - { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Circle Pad Y" }, - { 0 }, - }; - - environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, &desc); + envCallbacks(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, &desc); } static std::string FetchVariable(std::string key, std::string def) { - struct retro_variable var = { nullptr }; - var.key = key.c_str(); + retro_variable var = {nullptr}; + var.key = key.c_str(); - if (!environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value == nullptr) { - Helpers::warn("Fetching variable %s failed.", key); - return def; - } + if (!envCallbacks(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value == nullptr) { + Helpers::warn("Fetching variable %s failed.", key); + return def; + } - return std::string(var.value); + return std::string(var.value); } static bool FetchVariableBool(std::string key, bool def) { - return FetchVariable(key, def ? "enabled" : "disabled") == "enabled"; + return FetchVariable(key, def ? "enabled" : "disabled") == "enabled"; } -static void ConfigInit() { - static const retro_variable values[] = { - { "panda3ds_use_shader_jit", "Enable shader JIT; enabled|disabled" }, - { "panda3ds_use_vsync", "Enable VSync; enabled|disabled" }, - { "panda3ds_dsp_emulation", "DSP emulation; Null|HLE|LLE" }, - { "panda3ds_use_audio", "Enable audio; disabled|enabled" }, - { "panda3ds_use_virtual_sd", "Enable virtual SD card; enabled|disabled" }, - { "panda3ds_write_protect_virtual_sd", "Write protect virtual SD card; disabled|enabled" }, - { "panda3ds_battery_level", "Battery percentage; 5|10|20|30|50|70|90|100" }, - { "panda3ds_use_charger", "Charger plugged; enabled|disabled" }, - { nullptr, nullptr } - }; +static void configInit() { + static const retro_variable values[] = { + {"panda3ds_use_shader_jit", "Enable shader JIT; enabled|disabled"}, + {"panda3ds_use_vsync", "Enable VSync; enabled|disabled"}, + {"panda3ds_dsp_emulation", "DSP emulation; Null|HLE|LLE"}, + {"panda3ds_use_audio", "Enable audio; disabled|enabled"}, + {"panda3ds_use_virtual_sd", "Enable virtual SD card; enabled|disabled"}, + {"panda3ds_write_protect_virtual_sd", "Write protect virtual SD card; disabled|enabled"}, + {"panda3ds_battery_level", "Battery percentage; 5|10|20|30|50|70|90|100"}, + {"panda3ds_use_charger", "Charger plugged; enabled|disabled"}, + {nullptr, nullptr} + }; - environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)values); + envCallbacks(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)values); } -static void ConfigUpdate() { - EmulatorConfig& config = emulator->getConfig(); +static void configUpdate() { + EmulatorConfig& config = emulator->getConfig(); - config.rendererType = RendererType::OpenGL; - config.vsyncEnabled = FetchVariableBool("panda3ds_use_vsync", true); - config.shaderJitEnabled = FetchVariableBool("panda3ds_use_shader_jit", true); - config.chargerPlugged = FetchVariableBool("panda3ds_use_charger", true); - config.batteryPercentage = std::clamp(std::stoi(FetchVariable("panda3ds_battery_level", "5")), 0, 100); - config.dspType = Audio::DSPCore::typeFromString(FetchVariable("panda3ds_dsp_emulation", "null")); - config.audioEnabled = FetchVariableBool("panda3ds_use_audio", false); - config.sdCardInserted = FetchVariableBool("panda3ds_use_virtual_sd", true); - config.sdWriteProtected = FetchVariableBool("panda3ds_write_protect_virtual_sd", false); - config.discordRpcEnabled = false; + config.rendererType = RendererType::OpenGL; + config.vsyncEnabled = FetchVariableBool("panda3ds_use_vsync", true); + config.shaderJitEnabled = FetchVariableBool("panda3ds_use_shader_jit", true); + config.chargerPlugged = FetchVariableBool("panda3ds_use_charger", true); + config.batteryPercentage = std::clamp(std::stoi(FetchVariable("panda3ds_battery_level", "5")), 0, 100); + config.dspType = Audio::DSPCore::typeFromString(FetchVariable("panda3ds_dsp_emulation", "null")); + config.audioEnabled = FetchVariableBool("panda3ds_use_audio", false); + config.sdCardInserted = FetchVariableBool("panda3ds_use_virtual_sd", true); + config.sdWriteProtected = FetchVariableBool("panda3ds_write_protect_virtual_sd", false); + config.discordRpcEnabled = false; - config.save(); + config.save(); } static void ConfigCheckVariables() { - bool updated = false; - environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated); + bool updated = false; + envCallbacks(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated); - if (updated) - ConfigUpdate(); + if (updated) { + configUpdate(); + } } void retro_get_system_info(retro_system_info* info) { - info->need_fullpath = true; - info->valid_extensions = "3ds|3dsx|elf|axf|cci|cxi|app"; - info->library_version = "0.8"; - info->library_name = "Panda3DS"; - info->block_extract = true; + info->need_fullpath = true; + info->valid_extensions = "3ds|3dsx|elf|axf|cci|cxi|app"; + info->library_version = "0.8"; + info->library_name = "Panda3DS"; + info->block_extract = true; } void retro_get_system_av_info(retro_system_av_info* info) { - info->geometry.base_width = emulator->width; - info->geometry.base_height = emulator->height; + info->geometry.base_width = emulator->width; + info->geometry.base_height = emulator->height; - info->geometry.max_width = info->geometry.base_width; - info->geometry.max_height = info->geometry.base_height; + info->geometry.max_width = info->geometry.base_width; + info->geometry.max_height = info->geometry.base_height; - info->geometry.aspect_ratio = 5.0 / 6.0; - info->timing.fps = 60.0; - info->timing.sample_rate = 32768; + info->geometry.aspect_ratio = float(5.0 / 6.0); + info->timing.fps = 60.0; + info->timing.sample_rate = 32768; } void retro_set_environment(retro_environment_t cb) { - environ_cb = cb; + envCallbacks = cb; } void retro_set_video_refresh(retro_video_refresh_t cb) { - video_cb = cb; + videoCallbacks = cb; } void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { - audio_batch_cb = cb; + audioBatchCallback = cb; } -void retro_set_audio_sample(retro_audio_sample_t cb) { -} +void retro_set_audio_sample(retro_audio_sample_t cb) {} void retro_set_input_poll(retro_input_poll_t cb) { - input_poll_cb = cb; + inputPollCallback = cb; } void retro_set_input_state(retro_input_state_t cb) { - input_state_cb = cb; + inputStateCallback = cb; } -void retro_init(void) { - enum retro_pixel_format xrgb888 = RETRO_PIXEL_FORMAT_XRGB8888; - environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &xrgb888); +void retro_init() { + enum retro_pixel_format xrgb888 = RETRO_PIXEL_FORMAT_XRGB8888; + envCallbacks(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &xrgb888); - char* save_dir = nullptr; + char* save_dir = nullptr; - if (!environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &save_dir) || save_dir == nullptr) { - Helpers::warn("No save directory provided by LibRetro."); - retro_save_dir = std::filesystem::current_path(); - } else { - retro_save_dir = std::filesystem::path(save_dir); - } + if (!envCallbacks(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &save_dir) || save_dir == nullptr) { + Helpers::warn("No save directory provided by LibRetro."); + savePath = std::filesystem::current_path(); + } else { + savePath = std::filesystem::path(save_dir); + } - emulator = std::make_unique(); + emulator = std::make_unique(); } -void retro_deinit(void) { - emulator = nullptr; +void retro_deinit() { + emulator = nullptr; } -bool retro_load_game(const struct retro_game_info* game) { - ConfigInit(); - ConfigUpdate(); +bool retro_load_game(const retro_game_info* game) { + configInit(); + configUpdate(); - if (emulator->getRendererType() != RendererType::OpenGL) { - throw std::runtime_error("Libretro: Renderer is not OpenGL"); - } + if (emulator->getRendererType() != RendererType::OpenGL) { + Helpers::panic("Libretro: Renderer is not OpenGL"); + } - renderer = static_cast(emulator->getRenderer()); - emulator->setOutputSize(emulator->width, emulator->height); + renderer = static_cast(emulator->getRenderer()); + emulator->setOutputSize(emulator->width, emulator->height); - InputInit(); - VideoInit(); + inputInit(); + videoInit(); - return emulator->loadROM(game->path); + return emulator->loadROM(game->path); } -bool retro_load_game_special(unsigned type, const struct retro_game_info* info, size_t num) { - return false; +bool retro_load_game_special(uint type, const retro_game_info* info, size_t num) { return false; } + +void retro_unload_game() { + renderer->setFBO(0); + renderer = nullptr; } -void retro_unload_game(void) { - renderer->setFBO(0); - renderer = nullptr; +void retro_reset() { + emulator->reset(Emulator::ReloadOption::Reload); } -void retro_reset(void) { - emulator->reset(Emulator::ReloadOption::Reload); +void retro_run() { + ConfigCheckVariables(); + + renderer->setFBO(hw_render.get_current_framebuffer()); + renderer->resetStateManager(); + + inputPollCallback(); + + HIDService& hid = emulator->getServiceManager().getHID(); + + hid.setKey(HID::Keys::A, GetButtonState(RETRO_DEVICE_ID_JOYPAD_A)); + hid.setKey(HID::Keys::B, GetButtonState(RETRO_DEVICE_ID_JOYPAD_B)); + hid.setKey(HID::Keys::X, GetButtonState(RETRO_DEVICE_ID_JOYPAD_X)); + hid.setKey(HID::Keys::Y, GetButtonState(RETRO_DEVICE_ID_JOYPAD_Y)); + hid.setKey(HID::Keys::L, GetButtonState(RETRO_DEVICE_ID_JOYPAD_L)); + hid.setKey(HID::Keys::R, GetButtonState(RETRO_DEVICE_ID_JOYPAD_R)); + hid.setKey(HID::Keys::Start, GetButtonState(RETRO_DEVICE_ID_JOYPAD_START)); + hid.setKey(HID::Keys::Select, GetButtonState(RETRO_DEVICE_ID_JOYPAD_SELECT)); + hid.setKey(HID::Keys::Up, GetButtonState(RETRO_DEVICE_ID_JOYPAD_UP)); + hid.setKey(HID::Keys::Down, GetButtonState(RETRO_DEVICE_ID_JOYPAD_DOWN)); + hid.setKey(HID::Keys::Left, GetButtonState(RETRO_DEVICE_ID_JOYPAD_LEFT)); + hid.setKey(HID::Keys::Right, GetButtonState(RETRO_DEVICE_ID_JOYPAD_RIGHT)); + + // Get analog values for the left analog stick (Right analog stick is N3DS-only and unimplemented) + float xLeft = GetAxisState(RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X); + float yLeft = GetAxisState(RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y); + + hid.setCirclepadX((xLeft / +32767) * 0x9C); + hid.setCirclepadY((yLeft / -32767) * 0x9C); + + bool touch = inputStateCallback(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT); + const int posX = inputStateCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X); + const int posY = inputStateCallback(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y); + + const int newX = static_cast((posX + 0x7fff) / (float)(0x7fff * 2) * emulator->width); + const int newY = static_cast((posY + 0x7fff) / (float)(0x7fff * 2) * emulator->height); + + const int offsetX = 40; + const int offsetY = emulator->height / 2; + + const bool inScreenX = newX >= offsetX && newX < emulator->width - offsetX; + const bool inScreenY = newY >= offsetY && newY <= emulator->height; + + if (touch && inScreenX && inScreenY) { + u16 x = static_cast(newX - offsetX); + u16 y = static_cast(newY - offsetY); + + hid.setTouchScreenPress(x, y); + } else { + hid.releaseTouchScreen(); + } + + hid.updateInputs(emulator->getTicks()); + emulator->runFrame(); + + videoCallbacks(RETRO_HW_FRAME_BUFFER_VALID, emulator->width, emulator->height, 0); } -void retro_run(void) { - ConfigCheckVariables(); +void retro_set_controller_port_device(uint port, uint device) {} - renderer->setFBO(hw_render.get_current_framebuffer()); - renderer->resetStateManager(); - - input_poll_cb(); - - HIDService& hid = emulator->getServiceManager().getHID(); - - hid.setKey(HID::Keys::A, GetButtonState(RETRO_DEVICE_ID_JOYPAD_A)); - hid.setKey(HID::Keys::B, GetButtonState(RETRO_DEVICE_ID_JOYPAD_B)); - hid.setKey(HID::Keys::X, GetButtonState(RETRO_DEVICE_ID_JOYPAD_X)); - hid.setKey(HID::Keys::Y, GetButtonState(RETRO_DEVICE_ID_JOYPAD_Y)); - hid.setKey(HID::Keys::L, GetButtonState(RETRO_DEVICE_ID_JOYPAD_L)); - hid.setKey(HID::Keys::R, GetButtonState(RETRO_DEVICE_ID_JOYPAD_R)); - hid.setKey(HID::Keys::Start, GetButtonState(RETRO_DEVICE_ID_JOYPAD_START)); - hid.setKey(HID::Keys::Select, GetButtonState(RETRO_DEVICE_ID_JOYPAD_SELECT)); - hid.setKey(HID::Keys::Up, GetButtonState(RETRO_DEVICE_ID_JOYPAD_UP)); - hid.setKey(HID::Keys::Down, GetButtonState(RETRO_DEVICE_ID_JOYPAD_DOWN)); - hid.setKey(HID::Keys::Left, GetButtonState(RETRO_DEVICE_ID_JOYPAD_LEFT)); - hid.setKey(HID::Keys::Right, GetButtonState(RETRO_DEVICE_ID_JOYPAD_RIGHT)); - - float x_left = GetAxisState(RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X); - float y_left = GetAxisState(RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y); - - hid.setCirclepadX((x_left / +32767) * 0x9C); - hid.setCirclepadY((y_left / -32767) * 0x9C); - - bool touch = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT); - auto pos_x = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X); - auto pos_y = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y); - - auto new_x = static_cast((pos_x + 0x7fff) / (float)(0x7fff * 2) * emulator->width); - auto new_y = static_cast((pos_y + 0x7fff) / (float)(0x7fff * 2) * emulator->height); - - auto off_x = 40; - auto off_y = emulator->height / 2; - - bool scr_x = new_x >= off_x && new_x < emulator->width - off_x; - bool scr_y = new_y >= off_y && new_y <= emulator->height; - - if (touch && scr_y && scr_x) { - u16 x = static_cast(new_x - off_x); - u16 y = static_cast(new_y - off_y); - - hid.setTouchScreenPress(x, y); - } else { - hid.releaseTouchScreen(); - } - - hid.updateInputs(emulator->getTicks()); - - emulator->runFrame(); - video_cb(RETRO_HW_FRAME_BUFFER_VALID, emulator->width, emulator->height, 0); +size_t retro_serialize_size() { + size_t size = 0; + return size; } -void retro_set_controller_port_device(unsigned port, unsigned device) { +bool retro_serialize(void* data, size_t size) { return false; } +bool retro_unserialize(const void* data, size_t size) { return false; } + +uint retro_get_region() { return RETRO_REGION_NTSC; } +uint retro_api_version() { return RETRO_API_VERSION; } + +size_t retro_get_memory_size(uint id) { + if (id == RETRO_MEMORY_SYSTEM_RAM) { + return 0; + } + + return 0; } -size_t retro_serialize_size(void) { - size_t size = 0; - return size; +void* retro_get_memory_data(uint id) { + if (id == RETRO_MEMORY_SYSTEM_RAM) { + return 0; + } + + return nullptr; } -bool retro_serialize(void* data, size_t size) { - return false; -} - -bool retro_unserialize(const void* data, size_t size) { - return false; -} - -unsigned retro_get_region(void) { - return RETRO_REGION_NTSC; -} - -unsigned retro_api_version() { - return RETRO_API_VERSION; -} - -size_t retro_get_memory_size(unsigned id) { - if (id == RETRO_MEMORY_SYSTEM_RAM) { - return 0; - } - return 0; -} - -void* retro_get_memory_data(unsigned id) { - if (id == RETRO_MEMORY_SYSTEM_RAM) { - return 0; - } - return NULL; -} - -void retro_cheat_set(unsigned index, bool enabled, const char* code) { -} - -void retro_cheat_reset(void) { -} +void retro_cheat_set(uint index, bool enabled, const char* code) {} +void retro_cheat_reset() {}