diff options
Diffstat (limited to 'src')
200 files changed, 2 insertions, 22393 deletions
diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 45c28ad09..432bf2ced 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -134,21 +134,6 @@ void Config::ReadValues() { Settings::values.region_value = sdl2_config->GetInteger("System", "region_value", Settings::REGION_VALUE_AUTO_SELECT); - // Camera - using namespace Service::CAM; - Settings::values.camera_name[OuterRightCamera] = - sdl2_config->Get("Camera", "camera_outer_right_name", "blank"); - Settings::values.camera_config[OuterRightCamera] = - sdl2_config->Get("Camera", "camera_outer_right_config", ""); - Settings::values.camera_name[InnerCamera] = - sdl2_config->Get("Camera", "camera_inner_name", "blank"); - Settings::values.camera_config[InnerCamera] = - sdl2_config->Get("Camera", "camera_inner_config", ""); - Settings::values.camera_name[OuterLeftCamera] = - sdl2_config->Get("Camera", "camera_outer_left_name", "blank"); - Settings::values.camera_config[OuterLeftCamera] = - sdl2_config->Get("Camera", "camera_outer_left_config", ""); - // Miscellaneous Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info"); diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index 59faf773f..783c4a835 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -153,22 +153,6 @@ is_new_3ds = # -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan region_value = -[Camera] -# Which camera engine to use for the right outer camera -# blank (default): a dummy camera that always returns black image -camera_outer_right_name = - -# A config string for the right outer camera. Its meaning is defined by the camera engine -camera_outer_right_config = - -# ... for the left outer camera -camera_outer_left_name = -camera_outer_left_config = - -# ... for the inner camera -camera_inner_name = -camera_inner_config = - [Miscellaneous] # A filter which removes logs below a certain logging level. # Examples: *:Debug Kernel.SVC:Trace Service.*:Critical diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index 5261f4c4c..c268e0068 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -105,22 +105,6 @@ void Config::ReadValues() { qt_config->value("output_device", "auto").toString().toStdString(); qt_config->endGroup(); - using namespace Service::CAM; - qt_config->beginGroup("Camera"); - Settings::values.camera_name[OuterRightCamera] = - qt_config->value("camera_outer_right_name", "blank").toString().toStdString(); - Settings::values.camera_config[OuterRightCamera] = - qt_config->value("camera_outer_right_config", "").toString().toStdString(); - Settings::values.camera_name[InnerCamera] = - qt_config->value("camera_inner_name", "blank").toString().toStdString(); - Settings::values.camera_config[InnerCamera] = - qt_config->value("camera_inner_config", "").toString().toStdString(); - Settings::values.camera_name[OuterLeftCamera] = - qt_config->value("camera_outer_left_name", "blank").toString().toStdString(); - Settings::values.camera_config[OuterLeftCamera] = - qt_config->value("camera_outer_left_config", "").toString().toStdString(); - qt_config->endGroup(); - qt_config->beginGroup("Data Storage"); Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool(); qt_config->endGroup(); @@ -259,22 +243,6 @@ void Config::SaveValues() { qt_config->setValue("output_device", QString::fromStdString(Settings::values.audio_device_id)); qt_config->endGroup(); - using namespace Service::CAM; - qt_config->beginGroup("Camera"); - qt_config->setValue("camera_outer_right_name", - QString::fromStdString(Settings::values.camera_name[OuterRightCamera])); - qt_config->setValue("camera_outer_right_config", - QString::fromStdString(Settings::values.camera_config[OuterRightCamera])); - qt_config->setValue("camera_inner_name", - QString::fromStdString(Settings::values.camera_name[InnerCamera])); - qt_config->setValue("camera_inner_config", - QString::fromStdString(Settings::values.camera_config[InnerCamera])); - qt_config->setValue("camera_outer_left_name", - QString::fromStdString(Settings::values.camera_name[OuterLeftCamera])); - qt_config->setValue("camera_outer_left_config", - QString::fromStdString(Settings::values.camera_config[OuterLeftCamera])); - qt_config->endGroup(); - qt_config->beginGroup("Data Storage"); qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd); qt_config->endGroup(); diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 4b83eeb28..1361ccfba 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -33,32 +33,11 @@ namespace Log { SUB(Kernel, SVC) \ CLS(Service) \ SUB(Service, SRV) \ - SUB(Service, FRD) \ SUB(Service, FS) \ - SUB(Service, ERR) \ - SUB(Service, APT) \ - SUB(Service, BOSS) \ SUB(Service, GSP) \ - SUB(Service, AC) \ - SUB(Service, AM) \ - SUB(Service, PTM) \ - SUB(Service, LDR) \ - SUB(Service, MIC) \ - SUB(Service, NDM) \ - SUB(Service, NFC) \ - SUB(Service, NIM) \ - SUB(Service, NWM) \ - SUB(Service, CAM) \ - SUB(Service, CECD) \ SUB(Service, CFG) \ - SUB(Service, CSND) \ SUB(Service, DSP) \ - SUB(Service, DLP) \ SUB(Service, HID) \ - SUB(Service, HTTP) \ - SUB(Service, SOC) \ - SUB(Service, IR) \ - SUB(Service, Y2R) \ CLS(HW) \ SUB(HW, Memory) \ SUB(HW, LCD) \ diff --git a/src/common/logging/log.h b/src/common/logging/log.h index fe4dfed69..2ebd8911c 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -50,32 +50,11 @@ enum class Class : ClassType { Service, ///< HLE implementation of system services. Each major service /// should have its own subclass. Service_SRV, ///< The SRV (Service Directory) implementation - Service_FRD, ///< The FRD (Friends) service Service_FS, ///< The FS (Filesystem) service implementation - Service_ERR, ///< The ERR (Error) port implementation - Service_APT, ///< The APT (Applets) service - Service_BOSS, ///< The BOSS (SpotPass) service Service_GSP, ///< The GSP (GPU control) service - Service_AC, ///< The AC (WiFi status) service - Service_AM, ///< The AM (Application manager) service - Service_PTM, ///< The PTM (Power status & misc.) service - Service_LDR, ///< The LDR (3ds dll loader) service - Service_MIC, ///< The MIC (Microphone) service - Service_NDM, ///< The NDM (Network daemon manager) service - Service_NFC, ///< The NFC service - Service_NIM, ///< The NIM (Network interface manager) service - Service_NWM, ///< The NWM (Network wlan manager) service - Service_CAM, ///< The CAM (Camera) service - Service_CECD, ///< The CECD (StreetPass) service Service_CFG, ///< The CFG (Configuration) service - Service_CSND, ///< The CSND (CWAV format process) service Service_DSP, ///< The DSP (DSP control) service - Service_DLP, ///< The DLP (Download Play) service Service_HID, ///< The HID (Human interface device) service - Service_HTTP, ///< The HTTP service - Service_SOC, ///< The SOC (Socket) service - Service_IR, ///< The IR service - Service_Y2R, ///< The Y2R (YUV to RGB conversion) service HW, ///< Low-level hardware emulation HW_Memory, ///< Memory-map and address translation HW_LCD, ///< LCD register emulation diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8b25eaf0a..fa0379946 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -32,18 +32,10 @@ set(SRCS file_sys/path_parser.cpp file_sys/savedata_archive.cpp file_sys/title_metadata.cpp - frontend/camera/blank_camera.cpp - frontend/camera/factory.cpp - frontend/camera/interface.cpp frontend/emu_window.cpp frontend/framebuffer_layout.cpp gdbstub/gdbstub.cpp hle/config_mem.cpp - hle/applets/applet.cpp - hle/applets/erreula.cpp - hle/applets/mii_selector.cpp - hle/applets/mint.cpp - hle/applets/swkbd.cpp hle/kernel/address_arbiter.cpp hle/kernel/client_port.cpp hle/kernel/client_session.cpp @@ -65,49 +57,12 @@ set(SRCS hle/kernel/wait_object.cpp hle/lock.cpp hle/romfs.cpp - hle/service/ac/ac.cpp - hle/service/ac/ac_i.cpp - hle/service/ac/ac_u.cpp - hle/service/act/act.cpp - hle/service/act/act_a.cpp - hle/service/act/act_u.cpp - hle/service/am/am.cpp - hle/service/am/am_app.cpp - hle/service/am/am_net.cpp - hle/service/am/am_sys.cpp - hle/service/am/am_u.cpp - hle/service/apt/apt.cpp - hle/service/apt/apt_a.cpp - hle/service/apt/apt_s.cpp - hle/service/apt/apt_u.cpp - hle/service/apt/bcfnt/bcfnt.cpp - hle/service/boss/boss.cpp - hle/service/boss/boss_p.cpp - hle/service/boss/boss_u.cpp - hle/service/cam/cam.cpp - hle/service/cam/cam_c.cpp - hle/service/cam/cam_q.cpp - hle/service/cam/cam_s.cpp - hle/service/cam/cam_u.cpp - hle/service/cecd/cecd.cpp - hle/service/cecd/cecd_ndm.cpp - hle/service/cecd/cecd_s.cpp - hle/service/cecd/cecd_u.cpp hle/service/cfg/cfg.cpp hle/service/cfg/cfg_i.cpp hle/service/cfg/cfg_nor.cpp hle/service/cfg/cfg_s.cpp hle/service/cfg/cfg_u.cpp - hle/service/csnd_snd.cpp - hle/service/dlp/dlp.cpp - hle/service/dlp/dlp_clnt.cpp - hle/service/dlp/dlp_fkcl.cpp - hle/service/dlp/dlp_srvr.cpp hle/service/dsp_dsp.cpp - hle/service/err_f.cpp - hle/service/frd/frd.cpp - hle/service/frd/frd_a.cpp - hle/service/frd/frd_u.cpp hle/service/fs/archive.cpp hle/service/fs/fs_user.cpp hle/service/gsp_gpu.cpp @@ -115,60 +70,11 @@ set(SRCS hle/service/hid/hid.cpp hle/service/hid/hid_spvr.cpp hle/service/hid/hid_user.cpp - hle/service/http_c.cpp - hle/service/ir/extra_hid.cpp - hle/service/ir/ir.cpp - hle/service/ir/ir_rst.cpp - hle/service/ir/ir_u.cpp - hle/service/ir/ir_user.cpp - hle/service/ldr_ro/cro_helper.cpp - hle/service/ldr_ro/ldr_ro.cpp - hle/service/ldr_ro/memory_synchronizer.cpp - hle/service/mic_u.cpp - hle/service/mvd/mvd.cpp - hle/service/mvd/mvd_std.cpp - hle/service/ndm/ndm.cpp - hle/service/ndm/ndm_u.cpp - hle/service/nfc/nfc.cpp - hle/service/nfc/nfc_m.cpp - hle/service/nfc/nfc_u.cpp - hle/service/news/news.cpp - hle/service/news/news_s.cpp - hle/service/news/news_u.cpp - hle/service/nim/nim.cpp - hle/service/nim/nim_aoc.cpp - hle/service/nim/nim_s.cpp - hle/service/nim/nim_u.cpp hle/service/ns/ns.cpp hle/service/ns/ns_s.cpp - hle/service/nwm/nwm.cpp - hle/service/nwm/nwm_cec.cpp - hle/service/nwm/nwm_ext.cpp - hle/service/nwm/nwm_inf.cpp - hle/service/nwm/nwm_sap.cpp - hle/service/nwm/nwm_soc.cpp - hle/service/nwm/nwm_tst.cpp - hle/service/nwm/nwm_uds.cpp - hle/service/nwm/uds_beacon.cpp - hle/service/nwm/uds_connection.cpp - hle/service/nwm/uds_data.cpp - hle/service/pm_app.cpp - hle/service/ptm/ptm.cpp - hle/service/ptm/ptm_gets.cpp - hle/service/ptm/ptm_play.cpp - hle/service/ptm/ptm_sets.cpp - hle/service/ptm/ptm_sysm.cpp - hle/service/ptm/ptm_u.cpp - hle/service/qtm/qtm.cpp - hle/service/qtm/qtm_s.cpp - hle/service/qtm/qtm_sp.cpp - hle/service/qtm/qtm_u.cpp hle/service/service.cpp hle/service/sm/sm.cpp hle/service/sm/srv.cpp - hle/service/soc_u.cpp - hle/service/ssl_c.cpp - hle/service/y2r_u.cpp hle/shared_page.cpp hle/svc.cpp hw/aes/arithmetic128.cpp @@ -177,7 +83,6 @@ set(SRCS hw/gpu.cpp hw/hw.cpp hw/lcd.cpp - hw/y2r.cpp loader/3dsx.cpp loader/elf.cpp loader/linker.cpp @@ -231,9 +136,6 @@ set(HEADERS file_sys/ivfc_archive.h file_sys/path_parser.h file_sys/savedata_archive.h - frontend/camera/blank_camera.h - frontend/camera/factory.h - frontend/camera/interface.h frontend/emu_window.h frontend/framebuffer_layout.h frontend/input.h @@ -242,11 +144,6 @@ set(HEADERS hle/function_wrappers.h hle/ipc.h hle/ipc_helpers.h - hle/applets/applet.h - hle/applets/erreula.h - hle/applets/mii_selector.h - hle/applets/mint.h - hle/applets/swkbd.h hle/kernel/address_arbiter.h hle/kernel/client_port.h hle/kernel/client_session.h @@ -271,49 +168,12 @@ set(HEADERS hle/lock.h hle/result.h hle/romfs.h - hle/service/ac/ac.h - hle/service/ac/ac_i.h - hle/service/ac/ac_u.h - hle/service/act/act.h - hle/service/act/act_a.h - hle/service/act/act_u.h - hle/service/am/am.h - hle/service/am/am_app.h - hle/service/am/am_net.h - hle/service/am/am_sys.h - hle/service/am/am_u.h - hle/service/apt/apt.h - hle/service/apt/apt_a.h - hle/service/apt/apt_s.h - hle/service/apt/apt_u.h - hle/service/apt/bcfnt/bcfnt.h - hle/service/boss/boss.h - hle/service/boss/boss_p.h - hle/service/boss/boss_u.h - hle/service/cam/cam.h - hle/service/cam/cam_c.h - hle/service/cam/cam_q.h - hle/service/cam/cam_s.h - hle/service/cam/cam_u.h - hle/service/cecd/cecd.h - hle/service/cecd/cecd_ndm.h - hle/service/cecd/cecd_s.h - hle/service/cecd/cecd_u.h hle/service/cfg/cfg.h hle/service/cfg/cfg_i.h hle/service/cfg/cfg_nor.h hle/service/cfg/cfg_s.h hle/service/cfg/cfg_u.h - hle/service/csnd_snd.h - hle/service/dlp/dlp.h - hle/service/dlp/dlp_clnt.h - hle/service/dlp/dlp_fkcl.h - hle/service/dlp/dlp_srvr.h hle/service/dsp_dsp.h - hle/service/err_f.h - hle/service/frd/frd.h - hle/service/frd/frd_a.h - hle/service/frd/frd_u.h hle/service/fs/archive.h hle/service/fs/fs_user.h hle/service/gsp_gpu.h @@ -321,60 +181,11 @@ set(HEADERS hle/service/hid/hid.h hle/service/hid/hid_spvr.h hle/service/hid/hid_user.h - hle/service/http_c.h - hle/service/ir/extra_hid.h - hle/service/ir/ir.h - hle/service/ir/ir_rst.h - hle/service/ir/ir_u.h - hle/service/ir/ir_user.h - hle/service/ldr_ro/cro_helper.h - hle/service/ldr_ro/ldr_ro.h - hle/service/ldr_ro/memory_synchronizer.h - hle/service/mic_u.h - hle/service/mvd/mvd.h - hle/service/mvd/mvd_std.h - hle/service/ndm/ndm.h - hle/service/ndm/ndm_u.h - hle/service/nfc/nfc.h - hle/service/nfc/nfc_m.h - hle/service/nfc/nfc_u.h - hle/service/news/news.h - hle/service/news/news_s.h - hle/service/news/news_u.h - hle/service/nim/nim.h - hle/service/nim/nim_aoc.h - hle/service/nim/nim_s.h - hle/service/nim/nim_u.h hle/service/ns/ns.h hle/service/ns/ns_s.h - hle/service/nwm/nwm.h - hle/service/nwm/nwm_cec.h - hle/service/nwm/nwm_ext.h - hle/service/nwm/nwm_inf.h - hle/service/nwm/nwm_sap.h - hle/service/nwm/nwm_soc.h - hle/service/nwm/nwm_tst.h - hle/service/nwm/nwm_uds.h - hle/service/nwm/uds_beacon.h - hle/service/nwm/uds_connection.h - hle/service/nwm/uds_data.h - hle/service/pm_app.h - hle/service/ptm/ptm.h - hle/service/ptm/ptm_gets.h - hle/service/ptm/ptm_play.h - hle/service/ptm/ptm_sets.h - hle/service/ptm/ptm_sysm.h - hle/service/ptm/ptm_u.h - hle/service/qtm/qtm.h - hle/service/qtm/qtm_s.h - hle/service/qtm/qtm_sp.h - hle/service/qtm/qtm_u.h hle/service/service.h hle/service/sm/sm.h hle/service/sm/srv.h - hle/service/soc_u.h - hle/service/ssl_c.h - hle/service/y2r_u.h hle/shared_page.h hle/svc.h hw/aes/arithmetic128.h @@ -383,7 +194,6 @@ set(HEADERS hw/gpu.h hw/hw.h hw/lcd.h - hw/y2r.h loader/3dsx.h loader/elf.h loader/linker.h diff --git a/src/core/frontend/camera/blank_camera.cpp b/src/core/frontend/camera/blank_camera.cpp deleted file mode 100644 index 7995abcbd..000000000 --- a/src/core/frontend/camera/blank_camera.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/frontend/camera/blank_camera.h" - -namespace Camera { - -void BlankCamera::StartCapture() {} - -void BlankCamera::StopCapture() {} - -void BlankCamera::SetFormat(Service::CAM::OutputFormat output_format) { - output_rgb = output_format == Service::CAM::OutputFormat::RGB565; -} - -void BlankCamera::SetResolution(const Service::CAM::Resolution& resolution) { - width = resolution.width; - height = resolution.height; -}; - -void BlankCamera::SetFlip(Service::CAM::Flip) {} - -void BlankCamera::SetEffect(Service::CAM::Effect) {} - -std::vector<u16> BlankCamera::ReceiveFrame() const { - // Note: 0x80008000 stands for two black pixels in YUV422 - return std::vector<u16>(width * height, output_rgb ? 0 : 0x8000); -} - -} // namespace Camera diff --git a/src/core/frontend/camera/blank_camera.h b/src/core/frontend/camera/blank_camera.h deleted file mode 100644 index c6619bd88..000000000 --- a/src/core/frontend/camera/blank_camera.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/frontend/camera/factory.h" -#include "core/frontend/camera/interface.h" - -namespace Camera { - -class BlankCamera final : public CameraInterface { -public: - void StartCapture() override; - void StopCapture() override; - void SetResolution(const Service::CAM::Resolution&) override; - void SetFlip(Service::CAM::Flip) override; - void SetEffect(Service::CAM::Effect) override; - void SetFormat(Service::CAM::OutputFormat) override; - std::vector<u16> ReceiveFrame() const override; - -private: - int width = 0; - int height = 0; - bool output_rgb = false; -}; - -} // namespace Camera diff --git a/src/core/frontend/camera/factory.cpp b/src/core/frontend/camera/factory.cpp deleted file mode 100644 index 4b4da50dd..000000000 --- a/src/core/frontend/camera/factory.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <unordered_map> -#include "common/logging/log.h" -#include "core/frontend/camera/blank_camera.h" -#include "core/frontend/camera/factory.h" - -namespace Camera { - -static std::unordered_map<std::string, std::unique_ptr<CameraFactory>> factories; - -CameraFactory::~CameraFactory() = default; - -void RegisterFactory(const std::string& name, std::unique_ptr<CameraFactory> factory) { - factories[name] = std::move(factory); -} - -std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std::string& config) { - auto pair = factories.find(name); - if (pair != factories.end()) { - return pair->second->Create(config); - } - - if (name != "blank") { - LOG_ERROR(Service_CAM, "Unknown camera \"%s\"", name.c_str()); - } - return std::make_unique<BlankCamera>(); -} - -} // namespace Camera diff --git a/src/core/frontend/camera/factory.h b/src/core/frontend/camera/factory.h deleted file mode 100644 index f46413fa7..000000000 --- a/src/core/frontend/camera/factory.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <memory> -#include <string> -#include "core/frontend/camera/interface.h" - -namespace Camera { - -class CameraFactory { -public: - virtual ~CameraFactory(); - - /** - * Creates a camera object based on the configuration string. - * @param config Configuration string to create the camera. The implementation can decide the - * meaning of this string. - * @returns a unique_ptr to the created camera object. - */ - virtual std::unique_ptr<CameraInterface> Create(const std::string& config) const = 0; -}; - -/** - * Registers an external camera factory. - * @param name Identifier of the camera factory. - * @param factory Camera factory to register. - */ -void RegisterFactory(const std::string& name, std::unique_ptr<CameraFactory> factory); - -/** - * Creates a camera from the factory. - * @param name Identifier of the camera factory. - * @param config Configuration string to create the camera. The meaning of this string is - * defined by the factory. - */ -std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std::string& config); - -} // namespace Camera diff --git a/src/core/frontend/camera/interface.cpp b/src/core/frontend/camera/interface.cpp deleted file mode 100644 index 9aec9e7f1..000000000 --- a/src/core/frontend/camera/interface.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/frontend/camera/interface.h" - -namespace Camera { - -CameraInterface::~CameraInterface() = default; - -} // namespace Camera diff --git a/src/core/frontend/camera/interface.h b/src/core/frontend/camera/interface.h deleted file mode 100644 index a55a495c9..000000000 --- a/src/core/frontend/camera/interface.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <vector> -#include "common/common_types.h" -#include "core/hle/service/cam/cam.h" - -namespace Camera { - -/// An abstract class standing for a camera. All camera implementations should inherit from this. -class CameraInterface { -public: - virtual ~CameraInterface(); - - /// Starts the camera for video capturing. - virtual void StartCapture() = 0; - - /// Stops the camera for video capturing. - virtual void StopCapture() = 0; - - /** - * Sets the video resolution from raw CAM service parameters. - * For the meaning of the parameters, please refer to Service::CAM::Resolution. Note that the - * actual camera implementation doesn't need to respect all the parameters. However, the width - * and the height parameters must be respected and be used to determine the size of output - * frames. - * @param resolution The resolution parameters to set - */ - virtual void SetResolution(const Service::CAM::Resolution& resolution) = 0; - - /** - * Configures how received frames should be flipped by the camera. - * @param flip Flip applying to the frame - */ - virtual void SetFlip(Service::CAM::Flip flip) = 0; - - /** - * Configures what effect should be applied to received frames by the camera. - * @param effect Effect applying to the frame - */ - virtual void SetEffect(Service::CAM::Effect effect) = 0; - - /** - * Sets the output format of the all frames received after this function is called. - * @param format Output format of the frame - */ - virtual void SetFormat(Service::CAM::OutputFormat format) = 0; - - /** - * Receives a frame from the camera. - * This function should be only called between a StartCapture call and a StopCapture call. - * @returns A std::vector<u16> containing pixels. The total size of the vector is width * height - * where width and height are set by a call to SetResolution. - */ - virtual std::vector<u16> ReceiveFrame() const = 0; -}; - -} // namespace Camera diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp deleted file mode 100644 index 9c43ed2fd..000000000 --- a/src/core/hle/applets/applet.cpp +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <cstddef> -#include <memory> -#include <type_traits> -#include <unordered_map> -#include "common/assert.h" -#include "common/common_types.h" -#include "core/core_timing.h" -#include "core/hle/applets/applet.h" -#include "core/hle/applets/erreula.h" -#include "core/hle/applets/mii_selector.h" -#include "core/hle/applets/mint.h" -#include "core/hle/applets/swkbd.h" -#include "core/hle/result.h" -#include "core/hle/service/apt/apt.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -// Specializes std::hash for AppletId, so that we can use it in std::unordered_map. -// Workaround for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970 -namespace std { -template <> -struct hash<Service::APT::AppletId> { - typedef Service::APT::AppletId argument_type; - typedef std::size_t result_type; - - result_type operator()(const argument_type& id_code) const { - typedef std::underlying_type<argument_type>::type Type; - return std::hash<Type>()(static_cast<Type>(id_code)); - } -}; -} - -namespace HLE { -namespace Applets { - -static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets; -static u32 applet_update_event = - -1; ///< The CoreTiming event identifier for the Applet update callback. -/// The interval at which the Applet update callback will be called, 16.6ms -static const u64 applet_update_interval_us = 16666; - -ResultCode Applet::Create(Service::APT::AppletId id) { - switch (id) { - case Service::APT::AppletId::SoftwareKeyboard1: - case Service::APT::AppletId::SoftwareKeyboard2: - applets[id] = std::make_shared<SoftwareKeyboard>(id); - break; - case Service::APT::AppletId::Ed1: - case Service::APT::AppletId::Ed2: - applets[id] = std::make_shared<MiiSelector>(id); - break; - case Service::APT::AppletId::Error: - case Service::APT::AppletId::Error2: - applets[id] = std::make_shared<ErrEula>(id); - break; - case Service::APT::AppletId::Mint: - case Service::APT::AppletId::Mint2: - applets[id] = std::make_shared<Mint>(id); - break; - default: - LOG_ERROR(Service_APT, "Could not create applet %u", id); - // TODO(Subv): Find the right error code - return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, - ErrorSummary::NotSupported, ErrorLevel::Permanent); - } - - return RESULT_SUCCESS; -} - -std::shared_ptr<Applet> Applet::Get(Service::APT::AppletId id) { - auto itr = applets.find(id); - if (itr != applets.end()) - return itr->second; - return nullptr; -} - -/// Handles updating the current Applet every time it's called. -static void AppletUpdateEvent(u64 applet_id, int cycles_late) { - Service::APT::AppletId id = static_cast<Service::APT::AppletId>(applet_id); - std::shared_ptr<Applet> applet = Applet::Get(id); - ASSERT_MSG(applet != nullptr, "Applet doesn't exist! applet_id=%08X", id); - - applet->Update(); - - // If the applet is still running after the last update, reschedule the event - if (applet->IsRunning()) { - CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us) - cycles_late, - applet_update_event, applet_id); - } else { - // Otherwise the applet has terminated, in which case we should clean it up - applets[id] = nullptr; - } -} - -ResultCode Applet::Start(const Service::APT::AppletStartupParameter& parameter) { - ResultCode result = StartImpl(parameter); - if (result.IsError()) - return result; - // Schedule the update event - CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us), applet_update_event, - static_cast<u64>(id)); - return result; -} - -bool Applet::IsRunning() const { - return is_running; -} - -bool IsLibraryAppletRunning() { - // Check the applets map for instances of any applet - for (auto itr = applets.begin(); itr != applets.end(); ++itr) - if (itr->second != nullptr) - return true; - return false; -} - -void Init() { - // Register the applet update callback - applet_update_event = CoreTiming::RegisterEvent("HLE Applet Update Event", AppletUpdateEvent); -} - -void Shutdown() { - CoreTiming::RemoveEvent(applet_update_event); -} -} -} // namespace diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h deleted file mode 100644 index ebeed9813..000000000 --- a/src/core/hle/applets/applet.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <memory> -#include "core/hle/result.h" -#include "core/hle/service/apt/apt.h" - -namespace HLE { -namespace Applets { - -class Applet { -public: - virtual ~Applet() = default; - - /** - * Creates an instance of the Applet subclass identified by the parameter. - * and stores it in a global map. - * @param id Id of the applet to create. - * @returns ResultCode Whether the operation was successful or not. - */ - static ResultCode Create(Service::APT::AppletId id); - - /** - * Retrieves the Applet instance identified by the specified id. - * @param id Id of the Applet to retrieve. - * @returns Requested Applet or nullptr if not found. - */ - static std::shared_ptr<Applet> Get(Service::APT::AppletId id); - - /** - * Handles a parameter from the application. - * @param parameter Parameter data to handle. - * @returns ResultCode Whether the operation was successful or not. - */ - virtual ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) = 0; - - /** - * Handles the Applet start event, triggered from the application. - * @param parameter Parameter data to handle. - * @returns ResultCode Whether the operation was successful or not. - */ - ResultCode Start(const Service::APT::AppletStartupParameter& parameter); - - /** - * Whether the applet is currently executing instead of the host application or not. - */ - bool IsRunning() const; - - /** - * Handles an update tick for the Applet, lets it update the screen, send commands, etc. - */ - virtual void Update() = 0; - -protected: - explicit Applet(Service::APT::AppletId id) : id(id) {} - - /** - * Handles the Applet start event, triggered from the application. - * @param parameter Parameter data to handle. - * @returns ResultCode Whether the operation was successful or not. - */ - virtual ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) = 0; - - Service::APT::AppletId id; ///< Id of this Applet - std::shared_ptr<std::vector<u8>> heap_memory; ///< Heap memory for this Applet - - /// Whether this applet is currently running instead of the host application or not. - bool is_running = false; -}; - -/// Returns whether a library applet is currently running -bool IsLibraryAppletRunning(); - -/// Initializes the HLE applets -void Init(); - -/// Shuts down the HLE applets -void Shutdown(); -} -} // namespace diff --git a/src/core/hle/applets/erreula.cpp b/src/core/hle/applets/erreula.cpp deleted file mode 100644 index 518f371f5..000000000 --- a/src/core/hle/applets/erreula.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/string_util.h" -#include "core/hle/applets/erreula.h" -#include "core/hle/service/apt/apt.h" - -namespace HLE { -namespace Applets { - -ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& parameter) { - if (parameter.signal != static_cast<u32>(Service::APT::SignalType::Request)) { - LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal); - UNIMPLEMENTED(); - // TODO(Subv): Find the right error code - return ResultCode(-1); - } - - // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared - // memory. - // Create the SharedMemory that will hold the framebuffer data - Service::APT::CaptureBufferInfo capture_info; - ASSERT(sizeof(capture_info) == parameter.buffer.size()); - - memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); - - // TODO: allocated memory never released - using Kernel::MemoryPermission; - // Allocate a heap block of the required size for this applet. - heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); - // Create a SharedMemory that directly points to this heap block. - framebuffer_memory = Kernel::SharedMemory::CreateForApplet( - heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, - "ErrEula Memory"); - - // Send the response message with the newly created SharedMemory - Service::APT::MessageParameter result; - result.signal = static_cast<u32>(Service::APT::SignalType::Response); - result.buffer.clear(); - result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); - result.sender_id = static_cast<u32>(id); - result.object = framebuffer_memory; - - Service::APT::SendParameter(result); - return RESULT_SUCCESS; -} - -ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) { - is_running = true; - - // TODO(Subv): Set the expected fields in the response buffer before resending it to the - // application. - // TODO(Subv): Reverse the parameter format for the ErrEula applet - - // Let the application know that we're closing - Service::APT::MessageParameter message; - message.buffer.resize(parameter.buffer.size()); - std::fill(message.buffer.begin(), message.buffer.end(), 0); - message.signal = static_cast<u32>(Service::APT::SignalType::WakeupByExit); - message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); - message.sender_id = static_cast<u32>(id); - Service::APT::SendParameter(message); - - is_running = false; - return RESULT_SUCCESS; -} - -void ErrEula::Update() {} - -} // namespace Applets -} // namespace HLE diff --git a/src/core/hle/applets/erreula.h b/src/core/hle/applets/erreula.h deleted file mode 100644 index 681bbea0c..000000000 --- a/src/core/hle/applets/erreula.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/applets/applet.h" -#include "core/hle/kernel/shared_memory.h" - -namespace HLE { -namespace Applets { - -class ErrEula final : public Applet { -public: - explicit ErrEula(Service::APT::AppletId id) : Applet(id) {} - - ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; - ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; - void Update() override; - -private: - /// This SharedMemory will be created when we receive the LibAppJustStarted message. - /// It holds the framebuffer info retrieved by the application with - /// GSPGPU::ImportDisplayCaptureInfo - Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; -}; - -} // namespace Applets -} // namespace HLE diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp deleted file mode 100644 index f225c23a5..000000000 --- a/src/core/hle/applets/mii_selector.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <cstring> -#include <string> -#include "common/assert.h" -#include "common/logging/log.h" -#include "common/string_util.h" -#include "core/hle/applets/mii_selector.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/shared_memory.h" -#include "core/hle/result.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -namespace HLE { -namespace Applets { - -ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& parameter) { - if (parameter.signal != static_cast<u32>(Service::APT::SignalType::Request)) { - LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal); - UNIMPLEMENTED(); - // TODO(Subv): Find the right error code - return ResultCode(-1); - } - - // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared - // memory. - // Create the SharedMemory that will hold the framebuffer data - Service::APT::CaptureBufferInfo capture_info; - ASSERT(sizeof(capture_info) == parameter.buffer.size()); - - memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); - - using Kernel::MemoryPermission; - // Allocate a heap block of the required size for this applet. - heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); - // Create a SharedMemory that directly points to this heap block. - framebuffer_memory = Kernel::SharedMemory::CreateForApplet( - heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, - "MiiSelector Memory"); - - // Send the response message with the newly created SharedMemory - Service::APT::MessageParameter result; - result.signal = static_cast<u32>(Service::APT::SignalType::Response); - result.buffer.clear(); - result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); - result.sender_id = static_cast<u32>(id); - result.object = framebuffer_memory; - - Service::APT::SendParameter(result); - return RESULT_SUCCESS; -} - -ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) { - is_running = true; - - // TODO(Subv): Set the expected fields in the response buffer before resending it to the - // application. - // TODO(Subv): Reverse the parameter format for the Mii Selector - - memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); - - // TODO(Subv): Find more about this structure, result code 0 is enough to let most games - // continue. - MiiResult result; - memset(&result, 0, sizeof(result)); - result.return_code = 0; - - // Let the application know that we're closing - Service::APT::MessageParameter message; - message.buffer.resize(sizeof(MiiResult)); - std::memcpy(message.buffer.data(), &result, message.buffer.size()); - message.signal = static_cast<u32>(Service::APT::SignalType::WakeupByExit); - message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); - message.sender_id = static_cast<u32>(id); - Service::APT::SendParameter(message); - - is_running = false; - return RESULT_SUCCESS; -} - -void MiiSelector::Update() {} -} // namespace Applets -} // namespace HLE diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h deleted file mode 100644 index 136ce8948..000000000 --- a/src/core/hle/applets/mii_selector.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "core/hle/applets/applet.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/shared_memory.h" -#include "core/hle/result.h" -#include "core/hle/service/apt/apt.h" - -namespace HLE { -namespace Applets { - -struct MiiConfig { - u8 enable_cancel_button; - u8 enable_guest_mii; - u8 show_on_top_screen; - INSERT_PADDING_BYTES(5); - u16 title[0x40]; - INSERT_PADDING_BYTES(4); - u8 show_guest_miis; - INSERT_PADDING_BYTES(3); - u32 initially_selected_mii_index; - u8 guest_mii_whitelist[6]; - u8 user_mii_whitelist[0x64]; - INSERT_PADDING_BYTES(2); - u32 magic_value; -}; -static_assert(sizeof(MiiConfig) == 0x104, "MiiConfig structure has incorrect size"); -#define ASSERT_REG_POSITION(field_name, position) \ - static_assert(offsetof(MiiConfig, field_name) == position, \ - "Field " #field_name " has invalid position") -ASSERT_REG_POSITION(title, 0x08); -ASSERT_REG_POSITION(show_guest_miis, 0x8C); -ASSERT_REG_POSITION(initially_selected_mii_index, 0x90); -ASSERT_REG_POSITION(guest_mii_whitelist, 0x94); -#undef ASSERT_REG_POSITION - -struct MiiResult { - u32 return_code; - u32 is_guest_mii_selected; - u32 selected_guest_mii_index; - // TODO(mailwl): expand to Mii Format structure: https://www.3dbrew.org/wiki/Mii - u8 selected_mii_data[0x5C]; - INSERT_PADDING_BYTES(2); - u16 mii_data_checksum; - u16 guest_mii_name[0xC]; -}; -static_assert(sizeof(MiiResult) == 0x84, "MiiResult structure has incorrect size"); -#define ASSERT_REG_POSITION(field_name, position) \ - static_assert(offsetof(MiiResult, field_name) == position, \ - "Field " #field_name " has invalid position") -ASSERT_REG_POSITION(selected_mii_data, 0x0C); -ASSERT_REG_POSITION(guest_mii_name, 0x6C); -#undef ASSERT_REG_POSITION - -class MiiSelector final : public Applet { -public: - MiiSelector(Service::APT::AppletId id) : Applet(id) {} - - ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; - ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; - void Update() override; - -private: - /// This SharedMemory will be created when we receive the LibAppJustStarted message. - /// It holds the framebuffer info retrieved by the application with - /// GSPGPU::ImportDisplayCaptureInfo - Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; - - MiiConfig config; -}; -} // namespace Applets -} // namespace HLE diff --git a/src/core/hle/applets/mint.cpp b/src/core/hle/applets/mint.cpp deleted file mode 100644 index 50d79190b..000000000 --- a/src/core/hle/applets/mint.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/string_util.h" -#include "core/hle/applets/mint.h" -#include "core/hle/service/apt/apt.h" - -namespace HLE { -namespace Applets { - -ResultCode Mint::ReceiveParameter(const Service::APT::MessageParameter& parameter) { - if (parameter.signal != static_cast<u32>(Service::APT::SignalType::Request)) { - LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal); - UNIMPLEMENTED(); - // TODO(Subv): Find the right error code - return ResultCode(-1); - } - - // The Request message contains a buffer with the size of the framebuffer shared - // memory. - // Create the SharedMemory that will hold the framebuffer data - Service::APT::CaptureBufferInfo capture_info; - ASSERT(sizeof(capture_info) == parameter.buffer.size()); - - memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); - - // TODO: allocated memory never released - using Kernel::MemoryPermission; - // Allocate a heap block of the required size for this applet. - heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); - // Create a SharedMemory that directly points to this heap block. - framebuffer_memory = Kernel::SharedMemory::CreateForApplet( - heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, - "Mint Memory"); - - // Send the response message with the newly created SharedMemory - Service::APT::MessageParameter result; - result.signal = static_cast<u32>(Service::APT::SignalType::Response); - result.buffer.clear(); - result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); - result.sender_id = static_cast<u32>(id); - result.object = framebuffer_memory; - - Service::APT::SendParameter(result); - return RESULT_SUCCESS; -} - -ResultCode Mint::StartImpl(const Service::APT::AppletStartupParameter& parameter) { - is_running = true; - - // TODO(Subv): Set the expected fields in the response buffer before resending it to the - // application. - // TODO(Subv): Reverse the parameter format for the Mint applet - - // Let the application know that we're closing - Service::APT::MessageParameter message; - message.buffer.resize(parameter.buffer.size()); - std::fill(message.buffer.begin(), message.buffer.end(), 0); - message.signal = static_cast<u32>(Service::APT::SignalType::WakeupByExit); - message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); - message.sender_id = static_cast<u32>(id); - Service::APT::SendParameter(message); - - is_running = false; - return RESULT_SUCCESS; -} - -void Mint::Update() {} - -} // namespace Applets -} // namespace HLE diff --git a/src/core/hle/applets/mint.h b/src/core/hle/applets/mint.h deleted file mode 100644 index d23dc40f9..000000000 --- a/src/core/hle/applets/mint.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/applets/applet.h" -#include "core/hle/kernel/shared_memory.h" - -namespace HLE { -namespace Applets { - -class Mint final : public Applet { -public: - explicit Mint(Service::APT::AppletId id) : Applet(id) {} - - ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; - ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; - void Update() override; - -private: - /// This SharedMemory will be created when we receive the Request message. - /// It holds the framebuffer info retrieved by the application with - /// GSPGPU::ImportDisplayCaptureInfo - Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; -}; - -} // namespace Applets -} // namespace HLE diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp deleted file mode 100644 index 0bc471a3a..000000000 --- a/src/core/hle/applets/swkbd.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <cstring> -#include <string> -#include "common/assert.h" -#include "common/logging/log.h" -#include "common/string_util.h" -#include "core/hle/applets/swkbd.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/shared_memory.h" -#include "core/hle/result.h" -#include "core/hle/service/gsp_gpu.h" -#include "core/hle/service/hid/hid.h" -#include "core/memory.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -namespace HLE { -namespace Applets { - -ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter const& parameter) { - if (parameter.signal != static_cast<u32>(Service::APT::SignalType::Request)) { - LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal); - UNIMPLEMENTED(); - // TODO(Subv): Find the right error code - return ResultCode(-1); - } - - // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared - // memory. - // Create the SharedMemory that will hold the framebuffer data - Service::APT::CaptureBufferInfo capture_info; - ASSERT(sizeof(capture_info) == parameter.buffer.size()); - - memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); - - using Kernel::MemoryPermission; - // Allocate a heap block of the required size for this applet. - heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); - // Create a SharedMemory that directly points to this heap block. - framebuffer_memory = Kernel::SharedMemory::CreateForApplet( - heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, - "SoftwareKeyboard Memory"); - - // Send the response message with the newly created SharedMemory - Service::APT::MessageParameter result; - result.signal = static_cast<u32>(Service::APT::SignalType::Response); - result.buffer.clear(); - result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); - result.sender_id = static_cast<u32>(id); - result.object = framebuffer_memory; - - Service::APT::SendParameter(result); - return RESULT_SUCCESS; -} - -ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { - ASSERT_MSG(parameter.buffer.size() == sizeof(config), - "The size of the parameter (SoftwareKeyboardConfig) is wrong"); - - memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); - text_memory = - boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); - - // TODO(Subv): Verify if this is the correct behavior - memset(text_memory->GetPointer(), 0, text_memory->size); - - DrawScreenKeyboard(); - - is_running = true; - return RESULT_SUCCESS; -} - -void SoftwareKeyboard::Update() { - // TODO(Subv): Handle input using the touch events from the HID module - - // TODO(Subv): Remove this hardcoded text - std::u16string text = Common::UTF8ToUTF16("Citra"); - memcpy(text_memory->GetPointer(), text.c_str(), text.length() * sizeof(char16_t)); - - // TODO(Subv): Ask for input and write it to the shared memory - // TODO(Subv): Find out what are the possible values for the return code, - // some games seem to check for a hardcoded 2 - config.return_code = 2; - config.text_length = 6; - config.text_offset = 0; - - // TODO(Subv): We're finalizing the applet immediately after it's started, - // but we should defer this call until after all the input has been collected. - Finalize(); -} - -void SoftwareKeyboard::DrawScreenKeyboard() { - auto bottom_screen = Service::GSP::GetFrameBufferInfo(0, 1); - auto info = bottom_screen->framebuffer_info[bottom_screen->index]; - - // TODO(Subv): Draw the HLE keyboard, for now just zero-fill the framebuffer - Memory::ZeroBlock(info.address_left, info.stride * 320); - - Service::GSP::SetBufferSwap(1, info); -} - -void SoftwareKeyboard::Finalize() { - // Let the application know that we're closing - Service::APT::MessageParameter message; - message.buffer.resize(sizeof(SoftwareKeyboardConfig)); - std::memcpy(message.buffer.data(), &config, message.buffer.size()); - message.signal = static_cast<u32>(Service::APT::SignalType::WakeupByExit); - message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); - message.sender_id = static_cast<u32>(id); - Service::APT::SendParameter(message); - - is_running = false; -} -} -} // namespace diff --git a/src/core/hle/applets/swkbd.h b/src/core/hle/applets/swkbd.h deleted file mode 100644 index cc92a8f19..000000000 --- a/src/core/hle/applets/swkbd.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "core/hle/applets/applet.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/shared_memory.h" -#include "core/hle/result.h" -#include "core/hle/service/apt/apt.h" - -namespace HLE { -namespace Applets { - -struct SoftwareKeyboardConfig { - INSERT_PADDING_WORDS(0x8); - - u16 max_text_length; ///< Maximum length of the input text - - INSERT_PADDING_BYTES(0x6E); - - char16_t display_text[65]; ///< Text to display when asking the user for input - - INSERT_PADDING_BYTES(0xE); - - u32 default_text_offset; ///< Offset of the default text in the output SharedMemory - - INSERT_PADDING_WORDS(0x3); - - u32 shared_memory_size; ///< Size of the SharedMemory - - INSERT_PADDING_WORDS(0x1); - - u32 return_code; ///< Return code of the SoftwareKeyboard, usually 2, other values are unknown - - INSERT_PADDING_WORDS(0x2); - - u32 text_offset; ///< Offset in the SharedMemory where the output text starts - u16 text_length; ///< Length in characters of the output text - - INSERT_PADDING_BYTES(0x2B6); -}; - -/** - * The size of this structure (0x400) has been verified via reverse engineering of multiple games - * that use the software keyboard. - */ -static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config size is wrong"); - -class SoftwareKeyboard final : public Applet { -public: - SoftwareKeyboard(Service::APT::AppletId id) : Applet(id) {} - - ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; - ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; - void Update() override; - - /** - * Draws a keyboard to the current bottom screen framebuffer. - */ - void DrawScreenKeyboard(); - - /** - * Sends the LibAppletClosing signal to the application, - * along with the relevant data buffers. - */ - void Finalize(); - -private: - /// This SharedMemory will be created when we receive the LibAppJustStarted message. - /// It holds the framebuffer info retrieved by the application with - /// GSPGPU::ImportDisplayCaptureInfo - Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; - - /// SharedMemory where the output text will be stored - Kernel::SharedPtr<Kernel::SharedMemory> text_memory; - - /// Configuration of this instance of the SoftwareKeyboard, as received from the application - SoftwareKeyboardConfig config; -}; -} -} // namespace diff --git a/src/core/hle/service/ac/ac.cpp b/src/core/hle/service/ac/ac.cpp deleted file mode 100644 index e3dd23949..000000000 --- a/src/core/hle/service/ac/ac.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <array> - -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/hle/ipc.h" -#include "core/hle/kernel/event.h" -#include "core/hle/kernel/handle_table.h" -#include "core/hle/result.h" -#include "core/hle/service/ac/ac.h" -#include "core/hle/service/ac/ac_i.h" -#include "core/hle/service/ac/ac_u.h" -#include "core/memory.h" - -namespace Service { -namespace AC { - -struct ACConfig { - std::array<u8, 0x200> data; -}; - -static ACConfig default_config{}; - -static bool ac_connected = false; - -static Kernel::SharedPtr<Kernel::Event> close_event; -static Kernel::SharedPtr<Kernel::Event> connect_event; -static Kernel::SharedPtr<Kernel::Event> disconnect_event; - -void CreateDefaultConfig(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 ac_config_addr = cmd_buff[65]; - - ASSERT_MSG(cmd_buff[64] == (sizeof(ACConfig) << 14 | 2), - "Output buffer size not equal ACConfig size"); - - Memory::WriteBlock(ac_config_addr, &default_config, sizeof(ACConfig)); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - - LOG_WARNING(Service_AC, "(STUBBED) called"); -} - -void ConnectAsync(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - connect_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]); - if (connect_event) { - connect_event->name = "AC:connect_event"; - connect_event->Signal(); - ac_connected = true; - } - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - - LOG_WARNING(Service_AC, "(STUBBED) called"); -} - -void GetConnectResult(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - - LOG_WARNING(Service_AC, "(STUBBED) called"); -} - -void CloseAsync(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - if (ac_connected && disconnect_event) { - disconnect_event->Signal(); - } - - close_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]); - if (close_event) { - close_event->name = "AC:close_event"; - close_event->Signal(); - } - - ac_connected = false; - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_AC, "(STUBBED) called"); -} - -void GetCloseResult(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - - LOG_WARNING(Service_AC, "(STUBBED) called"); -} - -void GetWifiStatus(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - // TODO(purpasmart96): This function is only a stub, - // it returns a valid result without implementing full functionality. - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = 0; // Connection type set to none - - LOG_WARNING(Service_AC, "(STUBBED) called"); -} - -void GetInfraPriority(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = 0; // Infra Priority, default 0 - - LOG_WARNING(Service_AC, "(STUBBED) called"); -} - -void SetRequestEulaVersion(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 major = cmd_buff[1] & 0xFF; - u32 minor = cmd_buff[2] & 0xFF; - - ASSERT_MSG(cmd_buff[3] == (sizeof(ACConfig) << 14 | 2), - "Input buffer size not equal ACConfig size"); - ASSERT_MSG(cmd_buff[64] == (sizeof(ACConfig) << 14 | 2), - "Output buffer size not equal ACConfig size"); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = 0; // Infra Priority - - LOG_WARNING(Service_AC, "(STUBBED) called, major=%u, minor=%u", major, minor); -} - -void RegisterDisconnectEvent(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - disconnect_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]); - if (disconnect_event) { - disconnect_event->name = "AC:disconnect_event"; - } - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - - LOG_WARNING(Service_AC, "(STUBBED) called"); -} - -void IsConnected(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = ac_connected; - - LOG_WARNING(Service_AC, "(STUBBED) called"); -} - -void SetClientVersion(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - const u32 version = cmd_buff[1]; - self->SetVersion(version); - - LOG_WARNING(Service_AC, "(STUBBED) called, version: 0x%08X", version); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error -} - -void Init() { - AddService(new AC_I); - AddService(new AC_U); - - ac_connected = false; - - close_event = nullptr; - connect_event = nullptr; - disconnect_event = nullptr; -} - -void Shutdown() { - ac_connected = false; - - close_event = nullptr; - connect_event = nullptr; - disconnect_event = nullptr; -} - -} // namespace AC -} // namespace Service diff --git a/src/core/hle/service/ac/ac.h b/src/core/hle/service/ac/ac.h deleted file mode 100644 index 6185faf9b..000000000 --- a/src/core/hle/service/ac/ac.h +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service { - -class Interface; - -namespace AC { - -/** - * AC::CreateDefaultConfig service function - * Inputs: - * 64 : ACConfig size << 14 | 2 - * 65 : pointer to ACConfig struct - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void CreateDefaultConfig(Interface* self); - -/** - * AC::ConnectAsync service function - * Inputs: - * 1 : ProcessId Header - * 3 : Copy Handle Header - * 4 : Connection Event handle - * 5 : ACConfig size << 14 | 2 - * 6 : pointer to ACConfig struct - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void ConnectAsync(Interface* self); - -/** - * AC::GetConnectResult service function - * Inputs: - * 1 : ProcessId Header - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void GetConnectResult(Interface* self); - -/** - * AC::CloseAsync service function - * Inputs: - * 1 : ProcessId Header - * 3 : Copy Handle Header - * 4 : Event handle, should be signaled when AC connection is closed - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void CloseAsync(Interface* self); - -/** - * AC::GetCloseResult service function - * Inputs: - * 1 : ProcessId Header - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void GetCloseResult(Interface* self); - -/** - * AC::GetWifiStatus service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Output connection type, 0 = none, 1 = Old3DS Internet, 2 = New3DS Internet. - */ -void GetWifiStatus(Interface* self); - -/** - * AC::GetInfraPriority service function - * Inputs: - * 1 : ACConfig size << 14 | 2 - * 2 : pointer to ACConfig struct - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Infra Priority - */ -void GetInfraPriority(Interface* self); - -/** - * AC::SetRequestEulaVersion service function - * Inputs: - * 1 : Eula Version major - * 2 : Eula Version minor - * 3 : ACConfig size << 14 | 2 - * 4 : Input pointer to ACConfig struct - * 64 : ACConfig size << 14 | 2 - * 65 : Output pointer to ACConfig struct - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Infra Priority - */ -void SetRequestEulaVersion(Interface* self); - -/** - * AC::RegisterDisconnectEvent service function - * Inputs: - * 1 : ProcessId Header - * 3 : Copy Handle Header - * 4 : Event handle, should be signaled when AC connection is closed - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void RegisterDisconnectEvent(Interface* self); - -/** - * AC::IsConnected service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : bool, is connected - */ -void IsConnected(Interface* self); - -/** - * AC::SetClientVersion service function - * Inputs: - * 1 : Used SDK Version - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void SetClientVersion(Interface* self); - -/// Initialize AC service -void Init(); - -/// Shutdown AC service -void Shutdown(); - -} // namespace AC -} // namespace Service diff --git a/src/core/hle/service/ac/ac_i.cpp b/src/core/hle/service/ac/ac_i.cpp deleted file mode 100644 index b22fe3698..000000000 --- a/src/core/hle/service/ac/ac_i.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/ac/ac.h" -#include "core/hle/service/ac/ac_i.h" - -namespace Service { -namespace AC { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010000, CreateDefaultConfig, "CreateDefaultConfig"}, - {0x00040006, ConnectAsync, "ConnectAsync"}, - {0x00050002, GetConnectResult, "GetConnectResult"}, - {0x00070002, nullptr, "CancelConnectAsync"}, - {0x00080004, CloseAsync, "CloseAsync"}, - {0x00090002, GetCloseResult, "GetCloseResult"}, - {0x000A0000, nullptr, "GetLastErrorCode"}, - {0x000C0000, nullptr, "GetStatus"}, - {0x000D0000, GetWifiStatus, "GetWifiStatus"}, - {0x000E0042, nullptr, "GetCurrentAPInfo"}, - {0x00100042, nullptr, "GetCurrentNZoneInfo"}, - {0x00110042, nullptr, "GetNZoneApNumService"}, - {0x001D0042, nullptr, "ScanAPs"}, - {0x00240042, nullptr, "AddDenyApType"}, - {0x00270002, GetInfraPriority, "GetInfraPriority"}, - {0x002D0082, SetRequestEulaVersion, "SetRequestEulaVersion"}, - {0x00300004, RegisterDisconnectEvent, "RegisterDisconnectEvent"}, - {0x003C0042, nullptr, "GetAPSSIDList"}, - {0x003E0042, IsConnected, "IsConnected"}, - {0x00400042, SetClientVersion, "SetClientVersion"}, -}; - -AC_I::AC_I() { - Register(FunctionTable); -} - -} // namespace AC -} // namespace Service diff --git a/src/core/hle/service/ac/ac_i.h b/src/core/hle/service/ac/ac_i.h deleted file mode 100644 index 465bba59c..000000000 --- a/src/core/hle/service/ac/ac_i.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace AC { - -class AC_I final : public Interface { -public: - AC_I(); - - std::string GetPortName() const override { - return "ac:i"; - } -}; - -} // namespace AC -} // namespace Service diff --git a/src/core/hle/service/ac/ac_u.cpp b/src/core/hle/service/ac/ac_u.cpp deleted file mode 100644 index 346671b4a..000000000 --- a/src/core/hle/service/ac/ac_u.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/ac/ac.h" -#include "core/hle/service/ac/ac_u.h" - -namespace Service { -namespace AC { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010000, CreateDefaultConfig, "CreateDefaultConfig"}, - {0x00040006, ConnectAsync, "ConnectAsync"}, - {0x00050002, GetConnectResult, "GetConnectResult"}, - {0x00070002, nullptr, "CancelConnectAsync"}, - {0x00080004, CloseAsync, "CloseAsync"}, - {0x00090002, GetCloseResult, "GetCloseResult"}, - {0x000A0000, nullptr, "GetLastErrorCode"}, - {0x000C0000, nullptr, "GetStatus"}, - {0x000D0000, GetWifiStatus, "GetWifiStatus"}, - {0x000E0042, nullptr, "GetCurrentAPInfo"}, - {0x00100042, nullptr, "GetCurrentNZoneInfo"}, - {0x00110042, nullptr, "GetNZoneApNumService"}, - {0x001D0042, nullptr, "ScanAPs"}, - {0x00240042, nullptr, "AddDenyApType"}, - {0x00270002, GetInfraPriority, "GetInfraPriority"}, - {0x002D0082, SetRequestEulaVersion, "SetRequestEulaVersion"}, - {0x00300004, RegisterDisconnectEvent, "RegisterDisconnectEvent"}, - {0x003C0042, nullptr, "GetAPSSIDList"}, - {0x003E0042, IsConnected, "IsConnected"}, - {0x00400042, SetClientVersion, "SetClientVersion"}, -}; - -AC_U::AC_U() { - Register(FunctionTable); -} - -} // namespace AC -} // namespace Service diff --git a/src/core/hle/service/ac/ac_u.h b/src/core/hle/service/ac/ac_u.h deleted file mode 100644 index f9d21e112..000000000 --- a/src/core/hle/service/ac/ac_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace AC { - -class AC_U final : public Interface { -public: - AC_U(); - - std::string GetPortName() const override { - return "ac:u"; - } -}; - -} // namespace AC -} // namespace Service diff --git a/src/core/hle/service/act/act.cpp b/src/core/hle/service/act/act.cpp deleted file mode 100644 index 9600036c0..000000000 --- a/src/core/hle/service/act/act.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/act/act.h" -#include "core/hle/service/act/act_a.h" -#include "core/hle/service/act/act_u.h" - -namespace Service { -namespace ACT { - -void Init() { - AddService(new ACT_A); - AddService(new ACT_U); -} - -} // namespace ACT -} // namespace Service diff --git a/src/core/hle/service/act/act.h b/src/core/hle/service/act/act.h deleted file mode 100644 index 1425291aa..000000000 --- a/src/core/hle/service/act/act.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service { -namespace ACT { - -/// Initializes all ACT services -void Init(); - -} // namespace ACT -} // namespace Service diff --git a/src/core/hle/service/act/act_a.cpp b/src/core/hle/service/act/act_a.cpp deleted file mode 100644 index 5c523368f..000000000 --- a/src/core/hle/service/act/act_a.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/act/act.h" -#include "core/hle/service/act/act_a.h" - -namespace Service { -namespace ACT { - -const Interface::FunctionInfo FunctionTable[] = { - // act:u shared commands - {0x00010084, nullptr, "Initialize"}, - {0x00020040, nullptr, "GetErrorCode"}, - {0x000600C2, nullptr, "GetAccountDataBlock"}, - {0x000B0042, nullptr, "AcquireEulaList"}, - {0x000D0040, nullptr, "GenerateUuid"}, - // act:a - {0x041300C2, nullptr, "UpdateMiiImage"}, - {0x041B0142, nullptr, "AgreeEula"}, - {0x04210042, nullptr, "UploadMii"}, - {0x04230082, nullptr, "ValidateMailAddress"}, -}; - -ACT_A::ACT_A() { - Register(FunctionTable); -} - -} // namespace ACT -} // namespace Service diff --git a/src/core/hle/service/act/act_a.h b/src/core/hle/service/act/act_a.h deleted file mode 100644 index e3adb03e5..000000000 --- a/src/core/hle/service/act/act_a.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace ACT { - -class ACT_A final : public Service::Interface { -public: - ACT_A(); - - std::string GetPortName() const override { - return "act:a"; - } -}; - -} // namespace ACT -} // namespace Service diff --git a/src/core/hle/service/act/act_u.cpp b/src/core/hle/service/act/act_u.cpp deleted file mode 100644 index cf98aa1d6..000000000 --- a/src/core/hle/service/act/act_u.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/act/act.h" -#include "core/hle/service/act/act_u.h" - -namespace Service { -namespace ACT { - -const Interface::FunctionInfo FunctionTable[] = { - // clang-format off - {0x00010084, nullptr, "Initialize"}, - {0x00020040, nullptr, "GetErrorCode"}, - {0x000600C2, nullptr, "GetAccountDataBlock"}, - {0x000B0042, nullptr, "AcquireEulaList"}, - {0x000D0040, nullptr, "GenerateUuid"}, - // clang-format on -}; - -ACT_U::ACT_U() { - Register(FunctionTable); -} - -} // namespace ACT -} // namespace Service diff --git a/src/core/hle/service/act/act_u.h b/src/core/hle/service/act/act_u.h deleted file mode 100644 index 9d8538fbf..000000000 --- a/src/core/hle/service/act/act_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace ACT { - -class ACT_U final : public Interface { -public: - ACT_U(); - - std::string GetPortName() const override { - return "act:u"; - } -}; - -} // namespace ACT -} // namespace Service diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp deleted file mode 100644 index 961305e9f..000000000 --- a/src/core/hle/service/am/am.cpp +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <array> -#include <cinttypes> -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/hle/ipc.h" -#include "core/hle/result.h" -#include "core/hle/service/am/am.h" -#include "core/hle/service/am/am_app.h" -#include "core/hle/service/am/am_net.h" -#include "core/hle/service/am/am_sys.h" -#include "core/hle/service/am/am_u.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace AM { - -static std::array<u32, 3> am_content_count = {0, 0, 0}; -static std::array<u32, 3> am_titles_count = {0, 0, 0}; -static std::array<u32, 3> am_titles_list_count = {0, 0, 0}; -static u32 am_ticket_count = 0; -static u32 am_ticket_list_count = 0; - -void GetNumPrograms(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 media_type = cmd_buff[1] & 0xFF; - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = am_titles_count[media_type]; - LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_count=0x%08x", media_type, - am_titles_count[media_type]); -} - -void FindContentInfos(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 media_type = cmd_buff[1] & 0xFF; - u64 title_id = (static_cast<u64>(cmd_buff[3]) << 32) | cmd_buff[2]; - u32 content_ids_pointer = cmd_buff[6]; - u32 content_info_pointer = cmd_buff[8]; - - am_content_count[media_type] = cmd_buff[4]; - - cmd_buff[1] = RESULT_SUCCESS.raw; - LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016llx, content_cound=%u, " - "content_ids_pointer=0x%08x, content_info_pointer=0x%08x", - media_type, title_id, am_content_count[media_type], content_ids_pointer, - content_info_pointer); -} - -void ListContentInfos(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 media_type = cmd_buff[2] & 0xFF; - u64 title_id = (static_cast<u64>(cmd_buff[4]) << 32) | cmd_buff[3]; - u32 start_index = cmd_buff[5]; - u32 content_info_pointer = cmd_buff[7]; - - am_content_count[media_type] = cmd_buff[1]; - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = am_content_count[media_type]; - LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, content_count=%u, title_id=0x%016" PRIx64 - ", start_index=0x%08x, content_info_pointer=0x%08X", - media_type, am_content_count[media_type], title_id, start_index, - content_info_pointer); -} - -void DeleteContents(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 media_type = cmd_buff[1] & 0xFF; - u64 title_id = (static_cast<u64>(cmd_buff[3]) << 32) | cmd_buff[2]; - u32 content_ids_pointer = cmd_buff[6]; - - am_content_count[media_type] = cmd_buff[4]; - - cmd_buff[1] = RESULT_SUCCESS.raw; - LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016" PRIx64 - ", content_count=%u, content_ids_pointer=0x%08x", - media_type, title_id, am_content_count[media_type], content_ids_pointer); -} - -void GetProgramList(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 media_type = cmd_buff[2] & 0xFF; - u32 title_ids_output_pointer = cmd_buff[4]; - - am_titles_list_count[media_type] = cmd_buff[1]; - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = am_titles_list_count[media_type]; - LOG_WARNING( - Service_AM, - "(STUBBED) media_type=%u, titles_list_count=0x%08X, title_ids_output_pointer=0x%08X", - media_type, am_titles_list_count[media_type], title_ids_output_pointer); -} - -void GetProgramInfos(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 media_type = cmd_buff[1] & 0xFF; - u32 title_id_list_pointer = cmd_buff[4]; - u32 title_list_pointer = cmd_buff[6]; - - am_titles_count[media_type] = cmd_buff[2]; - - cmd_buff[1] = RESULT_SUCCESS.raw; - LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, total_titles=0x%08X, " - "title_id_list_pointer=0x%08X, title_list_pointer=0x%08X", - media_type, am_titles_count[media_type], title_id_list_pointer, title_list_pointer); -} - -void GetDataTitleInfos(Service::Interface* self) { - GetProgramInfos(self); - - LOG_WARNING(Service_AM, "(STUBBED) called"); -} - -void ListDataTitleTicketInfos(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u64 title_id = (static_cast<u64>(cmd_buff[3]) << 32) | cmd_buff[2]; - u32 start_index = cmd_buff[4]; - u32 ticket_info_pointer = cmd_buff[6]; - - am_ticket_count = cmd_buff[1]; - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = am_ticket_count; - LOG_WARNING(Service_AM, "(STUBBED) ticket_count=0x%08X, title_id=0x%016" PRIx64 - ", start_index=0x%08X, ticket_info_pointer=0x%08X", - am_ticket_count, title_id, start_index, ticket_info_pointer); -} - -void GetNumContentInfos(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 1; // Number of content infos plus one - LOG_WARNING(Service_AM, "(STUBBED) called"); -} - -void DeleteTicket(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u64 title_id = (static_cast<u64>(cmd_buff[2]) << 32) | cmd_buff[1]; - - cmd_buff[1] = RESULT_SUCCESS.raw; - LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "", title_id); -} - -void GetNumTickets(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = am_ticket_count; - LOG_WARNING(Service_AM, "(STUBBED) called ticket_count=0x%08x", am_ticket_count); -} - -void GetTicketList(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 num_of_skip = cmd_buff[2]; - u32 ticket_list_pointer = cmd_buff[4]; - - am_ticket_list_count = cmd_buff[1]; - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = am_ticket_list_count; - LOG_WARNING( - Service_AM, - "(STUBBED) ticket_list_count=0x%08x, num_of_skip=0x%08x, ticket_list_pointer=0x%08x", - am_ticket_list_count, num_of_skip, ticket_list_pointer); -} - -void Init() { - AddService(new AM_APP_Interface); - AddService(new AM_NET_Interface); - AddService(new AM_SYS_Interface); - AddService(new AM_U_Interface); -} - -void Shutdown() {} - -} // namespace AM - -} // namespace Service diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h deleted file mode 100644 index 9bc2ca305..000000000 --- a/src/core/hle/service/am/am.h +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service { - -class Interface; - -namespace AM { - -/** - * AM::GetNumPrograms service function - * Gets the number of installed titles in the requested media type - * Inputs: - * 0 : Command header (0x00010040) - * 1 : Media type to load the titles from - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : The number of titles in the requested media type - */ -void GetNumPrograms(Service::Interface* self); - -/** - * AM::FindContentInfos service function - * Inputs: - * 1 : MediaType - * 2-3 : u64, Title ID - * 4 : Content count - * 6 : Content IDs pointer - * 8 : Content Infos pointer - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void FindContentInfos(Service::Interface* self); - -/** - * AM::ListContentInfos service function - * Inputs: - * 1 : Content count - * 2 : MediaType - * 3-4 : u64, Title ID - * 5 : Start Index - * 7 : Content Infos pointer - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Number of content infos returned - */ -void ListContentInfos(Service::Interface* self); - -/** - * AM::DeleteContents service function - * Inputs: - * 1 : MediaType - * 2-3 : u64, Title ID - * 4 : Content count - * 6 : Content IDs pointer - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void DeleteContents(Service::Interface* self); - -/** - * AM::GetProgramList service function - * Loads information about the desired number of titles from the desired media type into an array - * Inputs: - * 1 : Title count - * 2 : Media type to load the titles from - * 4 : Title IDs output pointer - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : The number of titles loaded from the requested media type - */ -void GetProgramList(Service::Interface* self); - -/** - * AM::GetProgramInfos service function - * Inputs: - * 1 : u8 Mediatype - * 2 : Total titles - * 4 : TitleIDList pointer - * 6 : TitleList pointer - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void GetProgramInfos(Service::Interface* self); - -/** - * AM::GetDataTitleInfos service function - * Wrapper for AM::GetProgramInfos - * Inputs: - * 1 : u8 Mediatype - * 2 : Total titles - * 4 : TitleIDList pointer - * 6 : TitleList pointer - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void GetDataTitleInfos(Service::Interface* self); - -/** - * AM::ListDataTitleTicketInfos service function - * Inputs: - * 1 : Ticket count - * 2-3 : u64, Title ID - * 4 : Start Index? - * 5 : (TicketCount * 24) << 8 | 0x4 - * 6 : Ticket Infos pointer - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Number of ticket infos returned - */ -void ListDataTitleTicketInfos(Service::Interface* self); - -/** - * AM::GetNumContentInfos service function - * Inputs: - * 0 : Command header (0x100100C0) - * 1 : MediaType - * 2-3 : u64, Title ID - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Number of content infos plus one - */ -void GetNumContentInfos(Service::Interface* self); - -/** - * AM::DeleteTicket service function - * Inputs: - * 1-2 : u64, Title ID - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void DeleteTicket(Service::Interface* self); - -/** - * AM::GetNumTickets service function - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Number of tickets - */ -void GetNumTickets(Service::Interface* self); - -/** - * AM::GetTicketList service function - * Inputs: - * 1 : Number of TicketList - * 2 : Number to skip - * 4 : TicketList pointer - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Total TicketList - */ -void GetTicketList(Service::Interface* self); - -/// Initialize AM service -void Init(); - -/// Shutdown AM service -void Shutdown(); - -} // namespace AM -} // namespace Service diff --git a/src/core/hle/service/am/am_app.cpp b/src/core/hle/service/am/am_app.cpp deleted file mode 100644 index 218375c8f..000000000 --- a/src/core/hle/service/am/am_app.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/am/am.h" -#include "core/hle/service/am/am_app.h" - -namespace Service { -namespace AM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x100100C0, GetNumContentInfos, "GetNumContentInfos"}, - {0x10020104, FindContentInfos, "FindContentInfos"}, - {0x10030142, ListContentInfos, "ListContentInfos"}, - {0x10040102, DeleteContents, "DeleteContents"}, - {0x10050084, GetDataTitleInfos, "GetDataTitleInfos"}, - {0x10060080, nullptr, "GetNumDataTitleTickets"}, - {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"}, - {0x100801C2, nullptr, "GetItemRights"}, - {0x100900C0, nullptr, "IsDataTitleInUse"}, - {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"}, - {0x100B00C0, nullptr, "GetNumExistingContentInfos"}, - {0x100C0142, nullptr, "ListExistingContentInfos"}, - {0x100D0084, nullptr, "GetPatchTitleInfos"}, -}; - -AM_APP_Interface::AM_APP_Interface() { - Register(FunctionTable); -} - -} // namespace AM -} // namespace Service diff --git a/src/core/hle/service/am/am_app.h b/src/core/hle/service/am/am_app.h deleted file mode 100644 index fd6017d14..000000000 --- a/src/core/hle/service/am/am_app.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace AM { - -class AM_APP_Interface : public Service::Interface { -public: - AM_APP_Interface(); - - std::string GetPortName() const override { - return "am:app"; - } -}; - -} // namespace AM -} // namespace Service diff --git a/src/core/hle/service/am/am_net.cpp b/src/core/hle/service/am/am_net.cpp deleted file mode 100644 index f3cd1d23f..000000000 --- a/src/core/hle/service/am/am_net.cpp +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/am/am.h" -#include "core/hle/service/am/am_net.h" - -namespace Service { -namespace AM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetNumPrograms, "GetNumPrograms"}, - {0x00020082, GetProgramList, "GetProgramList"}, - {0x00030084, GetProgramInfos, "GetProgramInfos"}, - {0x000400C0, nullptr, "DeleteUserProgram"}, - {0x000500C0, nullptr, "GetProductCode"}, - {0x000600C0, nullptr, "GetStorageId"}, - {0x00070080, DeleteTicket, "DeleteTicket"}, - {0x00080000, GetNumTickets, "GetNumTickets"}, - {0x00090082, GetTicketList, "GetTicketList"}, - {0x000A0000, nullptr, "GetDeviceID"}, - {0x000B0040, nullptr, "GetNumImportTitleContexts"}, - {0x000C0082, nullptr, "GetImportTitleContextList"}, - {0x000D0084, nullptr, "GetImportTitleContexts"}, - {0x000E00C0, nullptr, "DeleteImportTitleContext"}, - {0x000F00C0, nullptr, "GetNumImportContentContexts"}, - {0x00100102, nullptr, "GetImportContentContextList"}, - {0x00110104, nullptr, "GetImportContentContexts"}, - {0x00120102, nullptr, "DeleteImportContentContexts"}, - {0x00130040, nullptr, "NeedsCleanup"}, - {0x00140040, nullptr, "DoCleanup"}, - {0x00150040, nullptr, "DeleteAllImportContexts"}, - {0x00160000, nullptr, "DeleteAllTemporaryPrograms"}, - {0x00170044, nullptr, "ImportTwlBackupLegacy"}, - {0x00180080, nullptr, "InitializeTitleDatabase"}, - {0x00190040, nullptr, "QueryAvailableTitleDatabase"}, - {0x001A00C0, nullptr, "CalcTwlBackupSize"}, - {0x001B0144, nullptr, "ExportTwlBackup"}, - {0x001C0084, nullptr, "ImportTwlBackup"}, - {0x001D0000, nullptr, "DeleteAllTwlUserPrograms"}, - {0x001E00C8, nullptr, "ReadTwlBackupInfo"}, - {0x001F0040, nullptr, "DeleteAllExpiredUserPrograms"}, - {0x00200000, nullptr, "GetTwlArchiveResourceInfo"}, - {0x00210042, nullptr, "GetPersonalizedTicketInfoList"}, - {0x00220080, nullptr, "DeleteAllImportContextsFiltered"}, - {0x00230080, nullptr, "GetNumImportTitleContextsFiltered"}, - {0x002400C2, nullptr, "GetImportTitleContextListFiltered"}, - {0x002500C0, nullptr, "CheckContentRights"}, - {0x00260044, nullptr, "GetTicketLimitInfos"}, - {0x00270044, nullptr, "GetDemoLaunchInfos"}, - {0x00280108, nullptr, "ReadTwlBackupInfoEx"}, - {0x00290082, nullptr, "DeleteUserProgramsAtomically"}, - {0x002A00C0, nullptr, "GetNumExistingContentInfosSystem"}, - {0x002B0142, nullptr, "ListExistingContentInfosSystem"}, - {0x002C0084, nullptr, "GetProgramInfosIgnorePlatform"}, - {0x002D00C0, nullptr, "CheckContentRightsIgnorePlatform"}, - {0x04010080, nullptr, "UpdateFirmwareTo"}, - {0x04020040, nullptr, "BeginImportProgram"}, - {0x04030000, nullptr, "BeginImportProgramTemporarily"}, - {0x04040002, nullptr, "CancelImportProgram"}, - {0x04050002, nullptr, "EndImportProgram"}, - {0x04060002, nullptr, "EndImportProgramWithoutCommit"}, - {0x040700C2, nullptr, "CommitImportPrograms"}, - {0x04080042, nullptr, "GetProgramInfoFromCia"}, - {0x04090004, nullptr, "GetSystemMenuDataFromCia"}, - {0x040A0002, nullptr, "GetDependencyListFromCia"}, - {0x040B0002, nullptr, "GetTransferSizeFromCia"}, - {0x040C0002, nullptr, "GetCoreVersionFromCia"}, - {0x040D0042, nullptr, "GetRequiredSizeFromCia"}, - {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, - {0x040F0000, nullptr, "UpdateFirmwareAuto"}, - {0x041000C0, nullptr, "DeleteProgram"}, - {0x04110044, nullptr, "GetTwlProgramListForReboot"}, - {0x04120000, nullptr, "GetSystemUpdaterMutex"}, - {0x04130002, nullptr, "GetMetaSizeFromCia"}, - {0x04140044, nullptr, "GetMetaDataFromCia"}, - {0x04150080, nullptr, "CheckDemoLaunchRights"}, - {0x041600C0, nullptr, "GetInternalTitleLocationInfo"}, - {0x041700C0, nullptr, "PerpetuateAgbSaveData"}, - {0x04180040, nullptr, "BeginImportProgramForOverWrite"}, - {0x04190000, nullptr, "BeginImportSystemProgram"}, - {0x08010000, nullptr, "BeginImportTicket"}, - {0x08020002, nullptr, "CancelImportTicket"}, - {0x08030002, nullptr, "EndImportTicket"}, - {0x08040100, nullptr, "BeginImportTitle"}, - {0x08050000, nullptr, "StopImportTitle"}, - {0x080600C0, nullptr, "ResumeImportTitle"}, - {0x08070000, nullptr, "CancelImportTitle"}, - {0x08080000, nullptr, "EndImportTitle"}, - {0x080900C2, nullptr, "CommitImportTitles"}, - {0x080A0000, nullptr, "BeginImportTmd"}, - {0x080B0002, nullptr, "CancelImportTmd"}, - {0x080C0042, nullptr, "EndImportTmd"}, - {0x080D0042, nullptr, "CreateImportContentContexts"}, - {0x080E0040, nullptr, "BeginImportContent"}, - {0x080F0002, nullptr, "StopImportContent"}, - {0x08100040, nullptr, "ResumeImportContent"}, - {0x08110002, nullptr, "CancelImportContent"}, - {0x08120002, nullptr, "EndImportContent"}, - {0x08130000, nullptr, "GetNumCurrentImportContentContexts"}, - {0x08140042, nullptr, "GetCurrentImportContentContextList"}, - {0x08150044, nullptr, "GetCurrentImportContentContexts"}, - {0x08160146, nullptr, "Sign"}, - {0x08170146, nullptr, "Verify"}, - {0x08180042, nullptr, "GetDeviceCert"}, - {0x08190108, nullptr, "ImportCertificates"}, - {0x081A0042, nullptr, "ImportCertificate"}, - {0x081B00C2, nullptr, "CommitImportTitlesAndUpdateFirmwareAuto"}, - {0x081C0100, nullptr, "DeleteTicketId"}, - {0x081D0080, nullptr, "GetNumTicketIds"}, - {0x081E0102, nullptr, "GetTicketIdList"}, - {0x081F0080, nullptr, "GetNumTicketsOfProgram"}, - {0x08200102, nullptr, "ListTicketInfos"}, - {0x08210142, nullptr, "GetRightsOnlyTicketData"}, - {0x08220000, nullptr, "GetNumCurrentContentInfos"}, - {0x08230044, nullptr, "FindCurrentContentInfos"}, - {0x08240082, nullptr, "ListCurrentContentInfos"}, - {0x08250102, nullptr, "CalculateContextRequiredSize"}, - {0x08260042, nullptr, "UpdateImportContentContexts"}, - {0x08270000, nullptr, "DeleteAllDemoLaunchInfos"}, - {0x082800C0, nullptr, "BeginImportTitleForOverWrite"}, -}; - -AM_NET_Interface::AM_NET_Interface() { - Register(FunctionTable); -} - -} // namespace AM -} // namespace Service diff --git a/src/core/hle/service/am/am_net.h b/src/core/hle/service/am/am_net.h deleted file mode 100644 index 25d2c3f23..000000000 --- a/src/core/hle/service/am/am_net.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace AM { - -class AM_NET_Interface : public Service::Interface { -public: - AM_NET_Interface(); - - std::string GetPortName() const override { - return "am:net"; - } -}; - -} // namespace AM -} // namespace Service diff --git a/src/core/hle/service/am/am_sys.cpp b/src/core/hle/service/am/am_sys.cpp deleted file mode 100644 index 949b3591d..000000000 --- a/src/core/hle/service/am/am_sys.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/am/am.h" -#include "core/hle/service/am/am_sys.h" - -namespace Service { -namespace AM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetNumPrograms, "GetNumPrograms"}, - {0x00020082, GetProgramList, "GetProgramList"}, - {0x00030084, GetProgramInfos, "GetProgramInfos"}, - {0x000400C0, nullptr, "DeleteUserProgram"}, - {0x000500C0, nullptr, "GetProductCode"}, - {0x000600C0, nullptr, "GetStorageId"}, - {0x00070080, DeleteTicket, "DeleteTicket"}, - {0x00080000, GetNumTickets, "GetNumTickets"}, - {0x00090082, GetTicketList, "GetTicketList"}, - {0x000A0000, nullptr, "GetDeviceID"}, - {0x000B0040, nullptr, "GetNumImportTitleContexts"}, - {0x000C0082, nullptr, "GetImportTitleContextList"}, - {0x000D0084, nullptr, "GetImportTitleContexts"}, - {0x000E00C0, nullptr, "DeleteImportTitleContext"}, - {0x000F00C0, nullptr, "GetNumImportContentContexts"}, - {0x00100102, nullptr, "GetImportContentContextList"}, - {0x00110104, nullptr, "GetImportContentContexts"}, - {0x00120102, nullptr, "DeleteImportContentContexts"}, - {0x00130040, nullptr, "NeedsCleanup"}, - {0x00140040, nullptr, "DoCleanup"}, - {0x00150040, nullptr, "DeleteAllImportContexts"}, - {0x00160000, nullptr, "DeleteAllTemporaryPrograms"}, - {0x00170044, nullptr, "ImportTwlBackupLegacy"}, - {0x00180080, nullptr, "InitializeTitleDatabase"}, - {0x00190040, nullptr, "QueryAvailableTitleDatabase"}, - {0x001A00C0, nullptr, "CalcTwlBackupSize"}, - {0x001B0144, nullptr, "ExportTwlBackup"}, - {0x001C0084, nullptr, "ImportTwlBackup"}, - {0x001D0000, nullptr, "DeleteAllTwlUserPrograms"}, - {0x001E00C8, nullptr, "ReadTwlBackupInfo"}, - {0x001F0040, nullptr, "DeleteAllExpiredUserPrograms"}, - {0x00200000, nullptr, "GetTwlArchiveResourceInfo"}, - {0x00210042, nullptr, "GetPersonalizedTicketInfoList"}, - {0x00220080, nullptr, "DeleteAllImportContextsFiltered"}, - {0x00230080, nullptr, "GetNumImportTitleContextsFiltered"}, - {0x002400C2, nullptr, "GetImportTitleContextListFiltered"}, - {0x002500C0, nullptr, "CheckContentRights"}, - {0x00260044, nullptr, "GetTicketLimitInfos"}, - {0x00270044, nullptr, "GetDemoLaunchInfos"}, - {0x00280108, nullptr, "ReadTwlBackupInfoEx"}, - {0x00290082, nullptr, "DeleteUserProgramsAtomically"}, - {0x002A00C0, nullptr, "GetNumExistingContentInfosSystem"}, - {0x002B0142, nullptr, "ListExistingContentInfosSystem"}, - {0x002C0084, nullptr, "GetProgramInfosIgnorePlatform"}, - {0x002D00C0, nullptr, "CheckContentRightsIgnorePlatform"}, - {0x100100C0, GetNumContentInfos, "GetNumContentInfos"}, - {0x10020104, FindContentInfos, "FindContentInfos"}, - {0x10030142, ListContentInfos, "ListContentInfos"}, - {0x10040102, DeleteContents, "DeleteContents"}, - {0x10050084, GetDataTitleInfos, "GetDataTitleInfos"}, - {0x10060080, nullptr, "GetNumDataTitleTickets"}, - {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"}, - {0x100801C2, nullptr, "GetItemRights"}, - {0x100900C0, nullptr, "IsDataTitleInUse"}, - {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"}, - {0x100B00C0, nullptr, "GetNumExistingContentInfos"}, - {0x100C0142, nullptr, "ListExistingContentInfos"}, - {0x100D0084, nullptr, "GetPatchTitleInfos"}, -}; - -AM_SYS_Interface::AM_SYS_Interface() { - Register(FunctionTable); -} - -} // namespace AM -} // namespace Service diff --git a/src/core/hle/service/am/am_sys.h b/src/core/hle/service/am/am_sys.h deleted file mode 100644 index b114f1d35..000000000 --- a/src/core/hle/service/am/am_sys.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace AM { - -class AM_SYS_Interface : public Service::Interface { -public: - AM_SYS_Interface(); - - std::string GetPortName() const override { - return "am:sys"; - } -}; - -} // namespace AM -} // namespace Service diff --git a/src/core/hle/service/am/am_u.cpp b/src/core/hle/service/am/am_u.cpp deleted file mode 100644 index 354d51610..000000000 --- a/src/core/hle/service/am/am_u.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/am/am.h" -#include "core/hle/service/am/am_u.h" - -namespace Service { -namespace AM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetNumPrograms, "GetNumPrograms"}, - {0x00020082, GetProgramList, "GetProgramList"}, - {0x00030084, GetProgramInfos, "GetProgramInfos"}, - {0x000400C0, nullptr, "DeleteUserProgram"}, - {0x000500C0, nullptr, "GetProductCode"}, - {0x000600C0, nullptr, "GetStorageId"}, - {0x00070080, DeleteTicket, "DeleteTicket"}, - {0x00080000, GetNumTickets, "GetNumTickets"}, - {0x00090082, GetTicketList, "GetTicketList"}, - {0x000A0000, nullptr, "GetDeviceID"}, - {0x000B0040, nullptr, "GetNumImportTitleContexts"}, - {0x000C0082, nullptr, "GetImportTitleContextList"}, - {0x000D0084, nullptr, "GetImportTitleContexts"}, - {0x000E00C0, nullptr, "DeleteImportTitleContext"}, - {0x000F00C0, nullptr, "GetNumImportContentContexts"}, - {0x00100102, nullptr, "GetImportContentContextList"}, - {0x00110104, nullptr, "GetImportContentContexts"}, - {0x00120102, nullptr, "DeleteImportContentContexts"}, - {0x00130040, nullptr, "NeedsCleanup"}, - {0x00140040, nullptr, "DoCleanup"}, - {0x00150040, nullptr, "DeleteAllImportContexts"}, - {0x00160000, nullptr, "DeleteAllTemporaryPrograms"}, - {0x00170044, nullptr, "ImportTwlBackupLegacy"}, - {0x00180080, nullptr, "InitializeTitleDatabase"}, - {0x00190040, nullptr, "QueryAvailableTitleDatabase"}, - {0x001A00C0, nullptr, "CalcTwlBackupSize"}, - {0x001B0144, nullptr, "ExportTwlBackup"}, - {0x001C0084, nullptr, "ImportTwlBackup"}, - {0x001D0000, nullptr, "DeleteAllTwlUserPrograms"}, - {0x001E00C8, nullptr, "ReadTwlBackupInfo"}, - {0x001F0040, nullptr, "DeleteAllExpiredUserPrograms"}, - {0x00200000, nullptr, "GetTwlArchiveResourceInfo"}, - {0x00210042, nullptr, "GetPersonalizedTicketInfoList"}, - {0x00220080, nullptr, "DeleteAllImportContextsFiltered"}, - {0x00230080, nullptr, "GetNumImportTitleContextsFiltered"}, - {0x002400C2, nullptr, "GetImportTitleContextListFiltered"}, - {0x002500C0, nullptr, "CheckContentRights"}, - {0x00260044, nullptr, "GetTicketLimitInfos"}, - {0x00270044, nullptr, "GetDemoLaunchInfos"}, - {0x00280108, nullptr, "ReadTwlBackupInfoEx"}, - {0x00290082, nullptr, "DeleteUserProgramsAtomically"}, - {0x002A00C0, nullptr, "GetNumExistingContentInfosSystem"}, - {0x002B0142, nullptr, "ListExistingContentInfosSystem"}, - {0x002C0084, nullptr, "GetProgramInfosIgnorePlatform"}, - {0x002D00C0, nullptr, "CheckContentRightsIgnorePlatform"}, - {0x04010080, nullptr, "UpdateFirmwareTo"}, - {0x04020040, nullptr, "BeginImportProgram"}, - {0x04030000, nullptr, "BeginImportProgramTemporarily"}, - {0x04040002, nullptr, "CancelImportProgram"}, - {0x04050002, nullptr, "EndImportProgram"}, - {0x04060002, nullptr, "EndImportProgramWithoutCommit"}, - {0x040700C2, nullptr, "CommitImportPrograms"}, - {0x04080042, nullptr, "GetProgramInfoFromCia"}, - {0x04090004, nullptr, "GetSystemMenuDataFromCia"}, - {0x040A0002, nullptr, "GetDependencyListFromCia"}, - {0x040B0002, nullptr, "GetTransferSizeFromCia"}, - {0x040C0002, nullptr, "GetCoreVersionFromCia"}, - {0x040D0042, nullptr, "GetRequiredSizeFromCia"}, - {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, - {0x040F0000, nullptr, "UpdateFirmwareAuto"}, - {0x041000C0, nullptr, "DeleteProgram"}, - {0x04110044, nullptr, "GetTwlProgramListForReboot"}, - {0x04120000, nullptr, "GetSystemUpdaterMutex"}, - {0x04130002, nullptr, "GetMetaSizeFromCia"}, - {0x04140044, nullptr, "GetMetaDataFromCia"}, - {0x04150080, nullptr, "CheckDemoLaunchRights"}, - {0x041600C0, nullptr, "GetInternalTitleLocationInfo"}, - {0x041700C0, nullptr, "PerpetuateAgbSaveData"}, - {0x04180040, nullptr, "BeginImportProgramForOverWrite"}, - {0x04190000, nullptr, "BeginImportSystemProgram"}, -}; - -AM_U_Interface::AM_U_Interface() { - Register(FunctionTable); -} - -} // namespace AM -} // namespace Service diff --git a/src/core/hle/service/am/am_u.h b/src/core/hle/service/am/am_u.h deleted file mode 100644 index 3b2454b6c..000000000 --- a/src/core/hle/service/am/am_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace AM { - -class AM_U_Interface : public Service::Interface { -public: - AM_U_Interface(); - - std::string GetPortName() const override { - return "am:u"; - } -}; - -} // namespace AM -} // namespace Service diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp deleted file mode 100644 index 912ab550d..000000000 --- a/src/core/hle/service/apt/apt.cpp +++ /dev/null @@ -1,1124 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <boost/optional.hpp> -#include "common/common_paths.h" -#include "common/file_util.h" -#include "common/logging/log.h" -#include "core/core.h" -#include "core/file_sys/file_backend.h" -#include "core/hle/applets/applet.h" -#include "core/hle/kernel/event.h" -#include "core/hle/kernel/mutex.h" -#include "core/hle/kernel/process.h" -#include "core/hle/kernel/shared_memory.h" -#include "core/hle/romfs.h" -#include "core/hle/service/apt/apt.h" -#include "core/hle/service/apt/apt_a.h" -#include "core/hle/service/apt/apt_s.h" -#include "core/hle/service/apt/apt_u.h" -#include "core/hle/service/apt/bcfnt/bcfnt.h" -#include "core/hle/service/cfg/cfg.h" -#include "core/hle/service/fs/archive.h" -#include "core/hle/service/ptm/ptm.h" -#include "core/hle/service/service.h" -#include "core/hw/aes/ccm.h" -#include "core/hw/aes/key.h" - -namespace Service { -namespace APT { - -/// Handle to shared memory region designated to for shared system font -static Kernel::SharedPtr<Kernel::SharedMemory> shared_font_mem; -static bool shared_font_loaded = false; -static bool shared_font_relocated = false; - -static Kernel::SharedPtr<Kernel::Mutex> lock; - -static u32 cpu_percent; ///< CPU time available to the running application - -// APT::CheckNew3DSApp will check this unknown_ns_state_field to determine processing mode -static u8 unknown_ns_state_field; - -static ScreencapPostPermission screen_capture_post_permission; - -/// Parameter data to be returned in the next call to Glance/ReceiveParameter. -/// TODO(Subv): Use std::optional once we migrate to C++17. -static boost::optional<MessageParameter> next_parameter; - -enum class AppletPos { Application = 0, Library = 1, System = 2, SysLibrary = 3, Resident = 4 }; - -static constexpr size_t NumAppletSlot = 4; - -enum class AppletSlot : u8 { - Application, - SystemApplet, - HomeMenu, - LibraryApplet, - - // An invalid tag - Error, -}; - -union AppletAttributes { - u32 raw; - - BitField<0, 3, u32> applet_pos; - BitField<29, 1, u32> is_home_menu; - - AppletAttributes() : raw(0) {} - AppletAttributes(u32 attributes) : raw(attributes) {} -}; - -struct AppletSlotData { - AppletId applet_id; - AppletSlot slot; - bool registered; - AppletAttributes attributes; - Kernel::SharedPtr<Kernel::Event> notification_event; - Kernel::SharedPtr<Kernel::Event> parameter_event; -}; - -// Holds data about the concurrently running applets in the system. -static std::array<AppletSlotData, NumAppletSlot> applet_slots = {}; - -// This overload returns nullptr if no applet with the specified id has been started. -static AppletSlotData* GetAppletSlotData(AppletId id) { - auto GetSlot = [](AppletSlot slot) -> AppletSlotData* { - return &applet_slots[static_cast<size_t>(slot)]; - }; - - if (id == AppletId::Application) { - auto* slot = GetSlot(AppletSlot::Application); - if (slot->applet_id != AppletId::None) - return slot; - - return nullptr; - } - - if (id == AppletId::AnySystemApplet) { - auto* system_slot = GetSlot(AppletSlot::SystemApplet); - if (system_slot->applet_id != AppletId::None) - return system_slot; - - // The Home Menu is also a system applet, but it lives in its own slot to be able to run - // concurrently with other system applets. - auto* home_slot = GetSlot(AppletSlot::HomeMenu); - if (home_slot->applet_id != AppletId::None) - return home_slot; - - return nullptr; - } - - if (id == AppletId::AnyLibraryApplet || id == AppletId::AnySysLibraryApplet) { - auto* slot = GetSlot(AppletSlot::LibraryApplet); - if (slot->applet_id == AppletId::None) - return nullptr; - - u32 applet_pos = slot->attributes.applet_pos; - - if (id == AppletId::AnyLibraryApplet && applet_pos == static_cast<u32>(AppletPos::Library)) - return slot; - - if (id == AppletId::AnySysLibraryApplet && - applet_pos == static_cast<u32>(AppletPos::SysLibrary)) - return slot; - - return nullptr; - } - - if (id == AppletId::HomeMenu || id == AppletId::AlternateMenu) { - auto* slot = GetSlot(AppletSlot::HomeMenu); - if (slot->applet_id != AppletId::None) - return slot; - - return nullptr; - } - - for (auto& slot : applet_slots) { - if (slot.applet_id == id) - return &slot; - } - - return nullptr; -} - -static AppletSlotData* GetAppletSlotData(AppletAttributes attributes) { - // Mapping from AppletPos to AppletSlot - static constexpr std::array<AppletSlot, 6> applet_position_slots = { - AppletSlot::Application, AppletSlot::LibraryApplet, AppletSlot::SystemApplet, - AppletSlot::LibraryApplet, AppletSlot::Error, AppletSlot::LibraryApplet}; - - u32 applet_pos = attributes.applet_pos; - if (applet_pos >= applet_position_slots.size()) - return nullptr; - - AppletSlot slot = applet_position_slots[applet_pos]; - - if (slot == AppletSlot::Error) - return nullptr; - - // The Home Menu is a system applet, however, it has its own applet slot so that it can run - // concurrently with other system applets. - if (slot == AppletSlot::SystemApplet && attributes.is_home_menu) - return &applet_slots[static_cast<size_t>(AppletSlot::HomeMenu)]; - - return &applet_slots[static_cast<size_t>(slot)]; -} - -void SendParameter(const MessageParameter& parameter) { - next_parameter = parameter; - // Signal the event to let the receiver know that a new parameter is ready to be read - auto* const slot_data = GetAppletSlotData(static_cast<AppletId>(parameter.destination_id)); - if (slot_data == nullptr) { - LOG_DEBUG(Service_APT, "No applet was registered with the id %03X", - parameter.destination_id); - return; - } - - slot_data->parameter_event->Signal(); -} - -void Initialize(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x2, 2, 0); // 0x20080 - u32 app_id = rp.Pop<u32>(); - u32 attributes = rp.Pop<u32>(); - - LOG_DEBUG(Service_APT, "called app_id=0x%08X, attributes=0x%08X", app_id, attributes); - - auto* const slot_data = GetAppletSlotData(attributes); - - // Note: The real NS service does not check if the attributes value is valid before accessing - // the data in the array - ASSERT_MSG(slot_data, "Invalid application attributes"); - - if (slot_data->registered) { - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(ResultCode(ErrorDescription::AlreadyExists, ErrorModule::Applet, - ErrorSummary::InvalidState, ErrorLevel::Status)); - return; - } - - slot_data->applet_id = static_cast<AppletId>(app_id); - slot_data->attributes.raw = attributes; - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 3); - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles(Kernel::g_handle_table.Create(slot_data->notification_event).Unwrap(), - Kernel::g_handle_table.Create(slot_data->parameter_event).Unwrap()); - - if (slot_data->applet_id == AppletId::Application || - slot_data->applet_id == AppletId::HomeMenu) { - // Initialize the APT parameter to wake up the application. - next_parameter.emplace(); - next_parameter->signal = static_cast<u32>(SignalType::Wakeup); - next_parameter->sender_id = static_cast<u32>(AppletId::None); - next_parameter->destination_id = app_id; - // Not signaling the parameter event will cause the application (or Home Menu) to hang - // during startup. In the real console, it is usually the Kernel and Home Menu who cause NS - // to signal the HomeMenu and Application parameter events, respectively. - slot_data->parameter_event->Signal(); - } -} - -static u32 DecompressLZ11(const u8* in, u8* out) { - u32_le decompressed_size; - memcpy(&decompressed_size, in, sizeof(u32)); - in += 4; - - u8 type = decompressed_size & 0xFF; - ASSERT(type == 0x11); - decompressed_size >>= 8; - - u32 current_out_size = 0; - u8 flags = 0, mask = 1; - while (current_out_size < decompressed_size) { - if (mask == 1) { - flags = *(in++); - mask = 0x80; - } else { - mask >>= 1; - } - - if (flags & mask) { - u8 byte1 = *(in++); - u32 length = byte1 >> 4; - u32 offset; - if (length == 0) { - u8 byte2 = *(in++); - u8 byte3 = *(in++); - length = (((byte1 & 0x0F) << 4) | (byte2 >> 4)) + 0x11; - offset = (((byte2 & 0x0F) << 8) | byte3) + 0x1; - } else if (length == 1) { - u8 byte2 = *(in++); - u8 byte3 = *(in++); - u8 byte4 = *(in++); - length = (((byte1 & 0x0F) << 12) | (byte2 << 4) | (byte3 >> 4)) + 0x111; - offset = (((byte3 & 0x0F) << 8) | byte4) + 0x1; - } else { - u8 byte2 = *(in++); - length = (byte1 >> 4) + 0x1; - offset = (((byte1 & 0x0F) << 8) | byte2) + 0x1; - } - - for (u32 i = 0; i < length; i++) { - *out = *(out - offset); - ++out; - } - - current_out_size += length; - } else { - *(out++) = *(in++); - current_out_size++; - } - } - return decompressed_size; -} - -static bool LoadSharedFont() { - u8 font_region_code; - switch (CFG::GetRegionValue()) { - case 4: // CHN - font_region_code = 2; - break; - case 5: // KOR - font_region_code = 3; - break; - case 6: // TWN - font_region_code = 4; - break; - default: // JPN/EUR/USA - font_region_code = 1; - break; - } - - const u64_le shared_font_archive_id_low = 0x0004009b00014002 | ((font_region_code - 1) << 8); - const u64_le shared_font_archive_id_high = 0x00000001ffffff00; - std::vector<u8> shared_font_archive_id(16); - std::memcpy(&shared_font_archive_id[0], &shared_font_archive_id_low, sizeof(u64)); - std::memcpy(&shared_font_archive_id[8], &shared_font_archive_id_high, sizeof(u64)); - FileSys::Path archive_path(shared_font_archive_id); - auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::NCCH, archive_path); - if (archive_result.Failed()) - return false; - - std::vector<u8> romfs_path(20, 0); // 20-byte all zero path for opening RomFS - FileSys::Path file_path(romfs_path); - FileSys::Mode open_mode = {}; - open_mode.read_flag.Assign(1); - auto file_result = Service::FS::OpenFileFromArchive(*archive_result, file_path, open_mode); - if (file_result.Failed()) - return false; - - auto romfs = std::move(file_result).Unwrap(); - std::vector<u8> romfs_buffer(romfs->backend->GetSize()); - romfs->backend->Read(0, romfs_buffer.size(), romfs_buffer.data()); - romfs->backend->Close(); - - const char16_t* file_name[4] = {u"cbf_std.bcfnt.lz", u"cbf_zh-Hans-CN.bcfnt.lz", - u"cbf_ko-Hang-KR.bcfnt.lz", u"cbf_zh-Hant-TW.bcfnt.lz"}; - const u8* font_file = - RomFS::GetFilePointer(romfs_buffer.data(), {file_name[font_region_code - 1]}); - if (font_file == nullptr) - return false; - - struct { - u32_le status; - u32_le region; - u32_le decompressed_size; - INSERT_PADDING_WORDS(0x1D); - } shared_font_header{}; - static_assert(sizeof(shared_font_header) == 0x80, "shared_font_header has incorrect size"); - - shared_font_header.status = 2; // successfully loaded - shared_font_header.region = font_region_code; - shared_font_header.decompressed_size = - DecompressLZ11(font_file, shared_font_mem->GetPointer(0x80)); - std::memcpy(shared_font_mem->GetPointer(), &shared_font_header, sizeof(shared_font_header)); - *shared_font_mem->GetPointer(0x83) = 'U'; // Change the magic from "CFNT" to "CFNU" - - return true; -} - -static bool LoadLegacySharedFont() { - // This is the legacy method to load shared font. - // The expected format is a decrypted, uncompressed BCFNT file with the 0x80 byte header - // generated by the APT:U service. The best way to get is by dumping it from RAM. We've provided - // a homebrew app to do this: https://github.com/citra-emu/3dsutils. Put the resulting file - // "shared_font.bin" in the Citra "sysdata" directory. - std::string filepath = FileUtil::GetUserPath(D_SYSDATA_IDX) + SHARED_FONT; - - FileUtil::CreateFullPath(filepath); // Create path if not already created - FileUtil::IOFile file(filepath, "rb"); - if (file.IsOpen()) { - file.ReadBytes(shared_font_mem->GetPointer(), file.GetSize()); - return true; - } - - return false; -} - -void GetSharedFont(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x44, 0, 0); // 0x00440000 - IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); - - // Log in telemetry if the game uses the shared font - Core::Telemetry().AddField(Telemetry::FieldType::Session, "RequiresSharedFont", true); - - if (!shared_font_loaded) { - // On real 3DS, font loading happens on booting. However, we load it on demand to coordinate - // with CFG region auto configuration, which happens later than APT initialization. - if (LoadSharedFont()) { - shared_font_loaded = true; - } else if (LoadLegacySharedFont()) { - LOG_WARNING(Service_APT, "Loaded shared font by legacy method"); - shared_font_loaded = true; - } else { - LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds"); - rb.Push<u32>(-1); // TODO: Find the right error code - rb.Skip(1 + 2, true); - Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSharedFont); - return; - } - } - - // The shared font has to be relocated to the new address before being passed to the - // application. - VAddr target_address = - Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address).value(); - if (!shared_font_relocated) { - BCFNT::RelocateSharedFont(shared_font_mem, target_address); - shared_font_relocated = true; - } - - rb.Push(RESULT_SUCCESS); // No error - // Since the SharedMemory interface doesn't provide the address at which the memory was - // allocated, the real APT service calculates this address by scanning the entire address space - // (using svcQueryMemory) and searches for an allocation of the same size as the Shared Font. - rb.Push(target_address); - rb.PushCopyHandles(Kernel::g_handle_table.Create(shared_font_mem).Unwrap()); -} - -void NotifyToWait(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x43, 1, 0); // 0x430040 - u32 app_id = rp.Pop<u32>(); - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); // No error - LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id); -} - -void GetLockHandle(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1, 1, 0); // 0x10040 - - // Bits [0:2] are the applet type (System, Library, etc) - // Bit 5 tells the application that there's a pending APT parameter, - // this will cause the app to wait until parameter_event is signaled. - u32 applet_attributes = rp.Pop<u32>(); - IPC::RequestBuilder rb = rp.MakeBuilder(3, 2); - rb.Push(RESULT_SUCCESS); // No error - - // TODO(Subv): The output attributes should have an AppletPos of either Library or System | - // Library (depending on the type of the last launched applet) if the input attributes' - // AppletPos has the Library bit set. - - rb.Push(applet_attributes); // Applet Attributes, this value is passed to Enable. - rb.Push<u32>(0); // Least significant bit = power button state - Kernel::Handle handle_copy = Kernel::g_handle_table.Create(lock).Unwrap(); - rb.PushCopyHandles(handle_copy); - - LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", handle_copy, - applet_attributes); -} - -void Enable(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x3, 1, 0); // 0x30040 - u32 attributes = rp.Pop<u32>(); - - LOG_DEBUG(Service_APT, "called attributes=0x%08X", attributes); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - auto* const slot_data = GetAppletSlotData(attributes); - - if (!slot_data) { - rb.Push(ResultCode(ErrCodes::InvalidAppletSlot, ErrorModule::Applet, - ErrorSummary::InvalidState, ErrorLevel::Status)); - return; - } - - slot_data->registered = true; - - rb.Push(RESULT_SUCCESS); -} - -void GetAppletManInfo(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x5, 1, 0); // 0x50040 - u32 unk = rp.Pop<u32>(); - IPC::RequestBuilder rb = rp.MakeBuilder(5, 0); - rb.Push(RESULT_SUCCESS); // No error - rb.Push<u32>(0); - rb.Push<u32>(0); - rb.Push(static_cast<u32>(AppletId::HomeMenu)); // Home menu AppID - rb.Push(static_cast<u32>(AppletId::Application)); // TODO(purpasmart96): Do this correctly - - LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); -} - -void IsRegistered(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x9, 1, 0); // 0x90040 - AppletId app_id = static_cast<AppletId>(rp.Pop<u32>()); - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); // No error - - auto* const slot_data = GetAppletSlotData(app_id); - - // Check if an LLE applet was registered first, then fallback to HLE applets - bool is_registered = slot_data && slot_data->registered; - - if (!is_registered) { - if (app_id == AppletId::AnyLibraryApplet) { - is_registered = HLE::Applets::IsLibraryAppletRunning(); - } else if (auto applet = HLE::Applets::Applet::Get(app_id)) { - // The applet exists, set it as registered. - is_registered = true; - } - } - - rb.Push(is_registered); - - LOG_DEBUG(Service_APT, "called app_id=0x%08X", static_cast<u32>(app_id)); -} - -void InquireNotification(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xB, 1, 0); // 0xB0040 - u32 app_id = rp.Pop<u32>(); - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); // No error - rb.Push(static_cast<u32>(SignalType::None)); // Signal type - LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); -} - -void SendParameter(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xC, 4, 4); // 0xC0104 - u32 src_app_id = rp.Pop<u32>(); - u32 dst_app_id = rp.Pop<u32>(); - u32 signal_type = rp.Pop<u32>(); - u32 buffer_size = rp.Pop<u32>(); - Kernel::Handle handle = rp.PopHandle(); - size_t size; - VAddr buffer = rp.PopStaticBuffer(&size); - - LOG_DEBUG(Service_APT, - "called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," - "buffer_size=0x%08X, handle=0x%08X, size=0x%08zX, in_param_buffer_ptr=0x%08X", - src_app_id, dst_app_id, signal_type, buffer_size, handle, size, buffer); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - // A new parameter can not be sent if the previous one hasn't been consumed yet - if (next_parameter) { - rb.Push(ResultCode(ErrCodes::ParameterPresent, ErrorModule::Applet, - ErrorSummary::InvalidState, ErrorLevel::Status)); - return; - } - - MessageParameter param; - param.destination_id = dst_app_id; - param.sender_id = src_app_id; - param.object = Kernel::g_handle_table.GetGeneric(handle); - param.signal = signal_type; - param.buffer.resize(buffer_size); - Memory::ReadBlock(buffer, param.buffer.data(), param.buffer.size()); - - SendParameter(param); - - // If the applet is running in HLE mode, use the HLE interface to communicate with it. - if (auto dest_applet = HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id))) { - rb.Push(dest_applet->ReceiveParameter(param)); - } else { - rb.Push(RESULT_SUCCESS); - } -} - -void ReceiveParameter(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xD, 2, 0); // 0xD0080 - u32 app_id = rp.Pop<u32>(); - u32 buffer_size = rp.Pop<u32>(); - - size_t static_buff_size; - VAddr buffer = rp.PeekStaticBuffer(0, &static_buff_size); - if (buffer_size > static_buff_size) - LOG_WARNING( - Service_APT, - "buffer_size is bigger than the size in the buffer descriptor (0x%08X > 0x%08zX)", - buffer_size, static_buff_size); - - LOG_DEBUG(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); - - if (!next_parameter) { - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(ResultCode(ErrorDescription::NoData, ErrorModule::Applet, - ErrorSummary::InvalidState, ErrorLevel::Status)); - return; - } - - if (next_parameter->destination_id != app_id) { - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotFound, - ErrorLevel::Status)); - return; - } - - IPC::RequestBuilder rb = rp.MakeBuilder(4, 4); - - rb.Push(RESULT_SUCCESS); // No error - rb.Push(next_parameter->sender_id); - rb.Push(next_parameter->signal); // Signal type - ASSERT_MSG(next_parameter->buffer.size() <= buffer_size, "Input static buffer is too small !"); - rb.Push(static_cast<u32>(next_parameter->buffer.size())); // Parameter buffer size - - rb.PushMoveHandles((next_parameter->object != nullptr) - ? Kernel::g_handle_table.Create(next_parameter->object).Unwrap() - : 0); - - rb.PushStaticBuffer(buffer, next_parameter->buffer.size(), 0); - - Memory::WriteBlock(buffer, next_parameter->buffer.data(), next_parameter->buffer.size()); - - // Clear the parameter - next_parameter = boost::none; -} - -void GlanceParameter(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xE, 2, 0); // 0xE0080 - u32 app_id = rp.Pop<u32>(); - u32 buffer_size = rp.Pop<u32>(); - - size_t static_buff_size; - VAddr buffer = rp.PeekStaticBuffer(0, &static_buff_size); - if (buffer_size > static_buff_size) - LOG_WARNING( - Service_APT, - "buffer_size is bigger than the size in the buffer descriptor (0x%08X > 0x%08zX)", - buffer_size, static_buff_size); - - LOG_DEBUG(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); - - if (!next_parameter) { - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(ResultCode(ErrorDescription::NoData, ErrorModule::Applet, - ErrorSummary::InvalidState, ErrorLevel::Status)); - return; - } - - if (next_parameter->destination_id != app_id) { - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotFound, - ErrorLevel::Status)); - return; - } - - IPC::RequestBuilder rb = rp.MakeBuilder(4, 4); - rb.Push(RESULT_SUCCESS); // No error - rb.Push(next_parameter->sender_id); - rb.Push(next_parameter->signal); // Signal type - ASSERT_MSG(next_parameter->buffer.size() <= buffer_size, "Input static buffer is too small !"); - rb.Push(static_cast<u32>(next_parameter->buffer.size())); // Parameter buffer size - - rb.PushMoveHandles((next_parameter->object != nullptr) - ? Kernel::g_handle_table.Create(next_parameter->object).Unwrap() - : 0); - - rb.PushStaticBuffer(buffer, next_parameter->buffer.size(), 0); - - Memory::WriteBlock(buffer, next_parameter->buffer.data(), next_parameter->buffer.size()); - - // Note: The NS module always clears the DSPSleep and DSPWakeup signals even in GlanceParameter. - if (next_parameter->signal == static_cast<u32>(SignalType::DspSleep) || - next_parameter->signal == static_cast<u32>(SignalType::DspWakeup)) - next_parameter = boost::none; -} - -void CancelParameter(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xF, 4, 0); // 0xF0100 - - bool check_sender = rp.Pop<bool>(); - u32 sender_appid = rp.Pop<u32>(); - bool check_receiver = rp.Pop<bool>(); - u32 receiver_appid = rp.Pop<u32>(); - - bool cancellation_success = true; - - if (!next_parameter) { - cancellation_success = false; - } else { - if (check_sender && next_parameter->sender_id != sender_appid) - cancellation_success = false; - - if (check_receiver && next_parameter->destination_id != receiver_appid) - cancellation_success = false; - } - - if (cancellation_success) - next_parameter = boost::none; - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - - rb.Push(RESULT_SUCCESS); // No error - rb.Push(cancellation_success); - - LOG_DEBUG(Service_APT, "called check_sender=%u, sender_appid=0x%08X, " - "check_receiver=%u, receiver_appid=0x%08X", - check_sender, sender_appid, check_receiver, receiver_appid); -} - -void PrepareToStartApplication(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x15, 5, 0); // 0x00150140 - u32 title_info1 = rp.Pop<u32>(); - u32 title_info2 = rp.Pop<u32>(); - u32 title_info3 = rp.Pop<u32>(); - u32 title_info4 = rp.Pop<u32>(); - u32 flags = rp.Pop<u32>(); - - if (flags & 0x00000100) { - unknown_ns_state_field = 1; - } - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); // No error - - LOG_WARNING(Service_APT, - "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X," - "title_info4=0x%08X, flags=0x%08X", - title_info1, title_info2, title_info3, title_info4, flags); -} - -void StartApplication(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1B, 3, 4); // 0x001B00C4 - u32 buffer1_size = rp.Pop<u32>(); - u32 buffer2_size = rp.Pop<u32>(); - u32 flag = rp.Pop<u32>(); - size_t size1; - VAddr buffer1_ptr = rp.PopStaticBuffer(&size1); - size_t size2; - VAddr buffer2_ptr = rp.PopStaticBuffer(&size2); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); // No error - - LOG_WARNING(Service_APT, - "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X," - "size1=0x%08zX, buffer1_ptr=0x%08X, size2=0x%08zX, buffer2_ptr=0x%08X", - buffer1_size, buffer2_size, flag, size1, buffer1_ptr, size2, buffer2_ptr); -} - -void AppletUtility(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x4B, 3, 2); // 0x004B00C2 - - // These are from 3dbrew - I'm not really sure what they're used for. - u32 utility_command = rp.Pop<u32>(); - u32 input_size = rp.Pop<u32>(); - u32 output_size = rp.Pop<u32>(); - VAddr input_addr = rp.PopStaticBuffer(); - - VAddr output_addr = rp.PeekStaticBuffer(0); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); // No error - - LOG_WARNING(Service_APT, - "(STUBBED) called command=0x%08X, input_size=0x%08X, output_size=0x%08X, " - "input_addr=0x%08X, output_addr=0x%08X", - utility_command, input_size, output_size, input_addr, output_addr); -} - -void SetAppCpuTimeLimit(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x4F, 2, 0); // 0x4F0080 - u32 value = rp.Pop<u32>(); - cpu_percent = rp.Pop<u32>(); - - if (value != 1) { - LOG_ERROR(Service_APT, "This value should be one, but is actually %u!", value); - } - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); // No error - - LOG_WARNING(Service_APT, "(STUBBED) called cpu_percent=%u, value=%u", cpu_percent, value); -} - -void GetAppCpuTimeLimit(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x50, 1, 0); // 0x500040 - u32 value = rp.Pop<u32>(); - - if (value != 1) { - LOG_ERROR(Service_APT, "This value should be one, but is actually %u!", value); - } - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); // No error - rb.Push(cpu_percent); - - LOG_WARNING(Service_APT, "(STUBBED) called value=%u", value); -} - -void PrepareToStartLibraryApplet(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x18, 1, 0); // 0x180040 - AppletId applet_id = static_cast<AppletId>(rp.Pop<u32>()); - - LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - // TODO(Subv): Launch the requested applet application. - - auto applet = HLE::Applets::Applet::Get(applet_id); - if (applet) { - LOG_WARNING(Service_APT, "applet has already been started id=%08X", applet_id); - rb.Push(RESULT_SUCCESS); - } else { - rb.Push(HLE::Applets::Applet::Create(applet_id)); - } -} - -void PrepareToStartNewestHomeMenu(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1A, 0, 0); // 0x1A0000 - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - // TODO(Subv): This command can only be called by a System Applet (return 0xC8A0CC04 otherwise). - - // This command must return an error when called, otherwise the Home Menu will try to reboot the - // system. - rb.Push(ResultCode(ErrorDescription::AlreadyExists, ErrorModule::Applet, - ErrorSummary::InvalidState, ErrorLevel::Status)); - - LOG_DEBUG(Service_APT, "called"); -} - -void PreloadLibraryApplet(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x16, 1, 0); // 0x160040 - AppletId applet_id = static_cast<AppletId>(rp.Pop<u32>()); - - LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - // TODO(Subv): Launch the requested applet application. - - auto applet = HLE::Applets::Applet::Get(applet_id); - if (applet) { - LOG_WARNING(Service_APT, "applet has already been started id=%08X", applet_id); - rb.Push(RESULT_SUCCESS); - } else { - rb.Push(HLE::Applets::Applet::Create(applet_id)); - } -} - -void StartLibraryApplet(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1E, 2, 4); // 0x1E0084 - AppletId applet_id = static_cast<AppletId>(rp.Pop<u32>()); - - size_t buffer_size = rp.Pop<u32>(); - Kernel::Handle handle = rp.PopHandle(); - VAddr buffer_addr = rp.PopStaticBuffer(); - - LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - // Send the Wakeup signal to the applet - MessageParameter param; - param.destination_id = static_cast<u32>(applet_id); - param.sender_id = static_cast<u32>(AppletId::Application); - param.object = Kernel::g_handle_table.GetGeneric(handle); - param.signal = static_cast<u32>(SignalType::Wakeup); - param.buffer.resize(buffer_size); - Memory::ReadBlock(buffer_addr, param.buffer.data(), param.buffer.size()); - SendParameter(param); - - // In case the applet is being HLEd, attempt to communicate with it. - if (auto applet = HLE::Applets::Applet::Get(applet_id)) { - AppletStartupParameter parameter; - parameter.object = Kernel::g_handle_table.GetGeneric(handle); - parameter.buffer.resize(buffer_size); - Memory::ReadBlock(buffer_addr, parameter.buffer.data(), parameter.buffer.size()); - rb.Push(applet->Start(parameter)); - } else { - rb.Push(RESULT_SUCCESS); - } -} - -void CancelLibraryApplet(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x3B, 1, 0); // 0x003B0040 - bool exiting = rp.Pop<bool>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push<u32>(1); // TODO: Find the return code meaning - - LOG_WARNING(Service_APT, "(STUBBED) called exiting=%d", exiting); -} - -void SetScreenCapPostPermission(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x55, 1, 0); // 0x00550040 - - screen_capture_post_permission = static_cast<ScreencapPostPermission>(rp.Pop<u32>() & 0xF); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); // No error - LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", - screen_capture_post_permission); -} - -void GetScreenCapPostPermission(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x56, 0, 0); // 0x00560000 - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); // No error - rb.Push(static_cast<u32>(screen_capture_post_permission)); - LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", - screen_capture_post_permission); -} - -void GetAppletInfo(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x6, 1, 0); // 0x60040 - auto app_id = static_cast<AppletId>(rp.Pop<u32>()); - - if (auto applet = HLE::Applets::Applet::Get(app_id)) { - // TODO(Subv): Get the title id for the current applet and write it in the response[2-3] - IPC::RequestBuilder rb = rp.MakeBuilder(7, 0); - rb.Push(RESULT_SUCCESS); - u64 title_id = 0; - rb.Push(title_id); - rb.Push(static_cast<u32>(Service::FS::MediaType::NAND)); - rb.Push(true); // Registered - rb.Push(true); // Loaded - rb.Push<u32>(0); // Applet Attributes - } else { - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotFound, - ErrorLevel::Status)); - } - LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id); -} - -void GetStartupArgument(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x51, 2, 0); // 0x00510080 - u32 parameter_size = rp.Pop<u32>(); - StartupArgumentType startup_argument_type = static_cast<StartupArgumentType>(rp.Pop<u8>()); - - if (parameter_size >= 0x300) { - LOG_ERROR( - Service_APT, - "Parameter size is outside the valid range (capped to 0x300): parameter_size=0x%08x", - parameter_size); - return; - } - - size_t static_buff_size; - VAddr addr = rp.PeekStaticBuffer(0, &static_buff_size); - if (parameter_size > static_buff_size) - LOG_WARNING( - Service_APT, - "parameter_size is bigger than the size in the buffer descriptor (0x%08X > 0x%08zX)", - parameter_size, static_buff_size); - - if (addr && parameter_size) { - Memory::ZeroBlock(addr, parameter_size); - } - - LOG_WARNING(Service_APT, "(stubbed) called startup_argument_type=%u , parameter_size=0x%08x", - startup_argument_type, parameter_size); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); - rb.Push(RESULT_SUCCESS); - rb.Push<u32>(0); - rb.PushStaticBuffer(addr, parameter_size, 0); -} - -void Wrap(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x46, 4, 4); - const u32 output_size = rp.Pop<u32>(); - const u32 input_size = rp.Pop<u32>(); - const u32 nonce_offset = rp.Pop<u32>(); - u32 nonce_size = rp.Pop<u32>(); - size_t desc_size; - IPC::MappedBufferPermissions desc_permission; - const VAddr input = rp.PopMappedBuffer(&desc_size, &desc_permission); - ASSERT(desc_size == input_size && desc_permission == IPC::MappedBufferPermissions::R); - const VAddr output = rp.PopMappedBuffer(&desc_size, &desc_permission); - ASSERT(desc_size == output_size && desc_permission == IPC::MappedBufferPermissions::W); - - // Note: real 3DS still returns SUCCESS when the sizes don't match. It seems that it doesn't - // check the buffer size and writes data with potential overflow. - ASSERT_MSG(output_size == input_size + HW::AES::CCM_MAC_SIZE, - "input_size (%d) doesn't match to output_size (%d)", input_size, output_size); - - LOG_DEBUG(Service_APT, "called, output_size=%u, input_size=%u, nonce_offset=%u, nonce_size=%u", - output_size, input_size, nonce_offset, nonce_size); - - // Note: This weird nonce size modification is verified against real 3DS - nonce_size = std::min<u32>(nonce_size & ~3, HW::AES::CCM_NONCE_SIZE); - - // Reads nonce and concatenates the rest of the input as plaintext - HW::AES::CCMNonce nonce{}; - Memory::ReadBlock(input + nonce_offset, nonce.data(), nonce_size); - u32 pdata_size = input_size - nonce_size; - std::vector<u8> pdata(pdata_size); - Memory::ReadBlock(input, pdata.data(), nonce_offset); - Memory::ReadBlock(input + nonce_offset + nonce_size, pdata.data() + nonce_offset, - pdata_size - nonce_offset); - - // Encrypts the plaintext using AES-CCM - auto cipher = HW::AES::EncryptSignCCM(pdata, nonce, HW::AES::KeySlotID::APTWrap); - - // Puts the nonce to the beginning of the output, with ciphertext followed - Memory::WriteBlock(output, nonce.data(), nonce_size); - Memory::WriteBlock(output + nonce_size, cipher.data(), cipher.size()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); - rb.Push(RESULT_SUCCESS); - - // Unmap buffer - rb.PushMappedBuffer(input, input_size, IPC::MappedBufferPermissions::R); - rb.PushMappedBuffer(output, output_size, IPC::MappedBufferPermissions::W); -} - -void Unwrap(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x47, 4, 4); - const u32 output_size = rp.Pop<u32>(); - const u32 input_size = rp.Pop<u32>(); - const u32 nonce_offset = rp.Pop<u32>(); - u32 nonce_size = rp.Pop<u32>(); - size_t desc_size; - IPC::MappedBufferPermissions desc_permission; - const VAddr input = rp.PopMappedBuffer(&desc_size, &desc_permission); - ASSERT(desc_size == input_size && desc_permission == IPC::MappedBufferPermissions::R); - const VAddr output = rp.PopMappedBuffer(&desc_size, &desc_permission); - ASSERT(desc_size == output_size && desc_permission == IPC::MappedBufferPermissions::W); - - // Note: real 3DS still returns SUCCESS when the sizes don't match. It seems that it doesn't - // check the buffer size and writes data with potential overflow. - ASSERT_MSG(output_size == input_size - HW::AES::CCM_MAC_SIZE, - "input_size (%d) doesn't match to output_size (%d)", input_size, output_size); - - LOG_DEBUG(Service_APT, "called, output_size=%u, input_size=%u, nonce_offset=%u, nonce_size=%u", - output_size, input_size, nonce_offset, nonce_size); - - // Note: This weird nonce size modification is verified against real 3DS - nonce_size = std::min<u32>(nonce_size & ~3, HW::AES::CCM_NONCE_SIZE); - - // Reads nonce and cipher text - HW::AES::CCMNonce nonce{}; - Memory::ReadBlock(input, nonce.data(), nonce_size); - u32 cipher_size = input_size - nonce_size; - std::vector<u8> cipher(cipher_size); - Memory::ReadBlock(input + nonce_size, cipher.data(), cipher_size); - - // Decrypts the ciphertext using AES-CCM - auto pdata = HW::AES::DecryptVerifyCCM(cipher, nonce, HW::AES::KeySlotID::APTWrap); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); - if (!pdata.empty()) { - // Splits the plaintext and put the nonce in between - Memory::WriteBlock(output, pdata.data(), nonce_offset); - Memory::WriteBlock(output + nonce_offset, nonce.data(), nonce_size); - Memory::WriteBlock(output + nonce_offset + nonce_size, pdata.data() + nonce_offset, - pdata.size() - nonce_offset); - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_APT, "Failed to decrypt data"); - rb.Push(ResultCode(static_cast<ErrorDescription>(1), ErrorModule::PS, - ErrorSummary::WrongArgument, ErrorLevel::Status)); - } - - // Unmap buffer - rb.PushMappedBuffer(input, input_size, IPC::MappedBufferPermissions::R); - rb.PushMappedBuffer(output, output_size, IPC::MappedBufferPermissions::W); -} - -void CheckNew3DSApp(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x101, 0, 0); // 0x01010000 - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - if (unknown_ns_state_field) { - rb.Push(RESULT_SUCCESS); - rb.Push<u32>(0); - } else { - PTM::CheckNew3DS(rb); - } - - LOG_WARNING(Service_APT, "(STUBBED) called"); -} - -void CheckNew3DS(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x102, 0, 0); // 0x01020000 - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - - PTM::CheckNew3DS(rb); - - LOG_WARNING(Service_APT, "(STUBBED) called"); -} - -void Init() { - AddService(new APT_A_Interface); - AddService(new APT_S_Interface); - AddService(new APT_U_Interface); - - HLE::Applets::Init(); - - using Kernel::MemoryPermission; - shared_font_mem = - Kernel::SharedMemory::Create(nullptr, 0x332000, // 3272 KB - MemoryPermission::ReadWrite, MemoryPermission::Read, 0, - Kernel::MemoryRegion::SYSTEM, "APT:SharedFont"); - - if (LoadSharedFont()) { - shared_font_loaded = true; - } else if (LoadLegacySharedFont()) { - LOG_WARNING(Service_APT, "Loaded shared font by legacy method"); - shared_font_loaded = true; - } else { - LOG_WARNING(Service_APT, "Unable to load shared font"); - shared_font_loaded = false; - } - - lock = Kernel::Mutex::Create(false, 0, "APT_U:Lock"); - - cpu_percent = 0; - unknown_ns_state_field = 0; - screen_capture_post_permission = - ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value - - for (size_t slot = 0; slot < applet_slots.size(); ++slot) { - auto& slot_data = applet_slots[slot]; - slot_data.slot = static_cast<AppletSlot>(slot); - slot_data.applet_id = AppletId::None; - slot_data.attributes.raw = 0; - slot_data.registered = false; - slot_data.notification_event = - Kernel::Event::Create(Kernel::ResetType::OneShot, "APT:Notification"); - slot_data.parameter_event = - Kernel::Event::Create(Kernel::ResetType::OneShot, "APT:Parameter"); - } -} - -void Shutdown() { - shared_font_mem = nullptr; - shared_font_loaded = false; - shared_font_relocated = false; - lock = nullptr; - - for (auto& slot : applet_slots) { - slot.registered = false; - slot.notification_event = nullptr; - slot.parameter_event = nullptr; - } - - next_parameter = boost::none; - - HLE::Applets::Shutdown(); -} - -} // namespace APT -} // namespace Service diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h deleted file mode 100644 index 7b79e1f3e..000000000 --- a/src/core/hle/service/apt/apt.h +++ /dev/null @@ -1,533 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <vector> -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "common/swap.h" -#include "core/hle/kernel/kernel.h" - -namespace Service { - -class Interface; - -namespace APT { - -/// Each APT service can only have up to 2 sessions connected at the same time. -static const u32 MaxAPTSessions = 2; - -/// Holds information about the parameters used in Send/Glance/ReceiveParameter -struct MessageParameter { - u32 sender_id = 0; - u32 destination_id = 0; - u32 signal = 0; - Kernel::SharedPtr<Kernel::Object> object = nullptr; - std::vector<u8> buffer; -}; - -/// Holds information about the parameters used in StartLibraryApplet -struct AppletStartupParameter { - Kernel::SharedPtr<Kernel::Object> object = nullptr; - std::vector<u8> buffer; -}; - -/// Used by the application to pass information about the current framebuffer to applets. -struct CaptureBufferInfo { - u32_le size; - u8 is_3d; - INSERT_PADDING_BYTES(0x3); // Padding for alignment - u32_le top_screen_left_offset; - u32_le top_screen_right_offset; - u32_le top_screen_format; - u32_le bottom_screen_left_offset; - u32_le bottom_screen_right_offset; - u32_le bottom_screen_format; -}; -static_assert(sizeof(CaptureBufferInfo) == 0x20, "CaptureBufferInfo struct has incorrect size"); - -/// Signals used by APT functions -enum class SignalType : u32 { - None = 0x0, - Wakeup = 0x1, - Request = 0x2, - Response = 0x3, - Exit = 0x4, - Message = 0x5, - HomeButtonSingle = 0x6, - HomeButtonDouble = 0x7, - DspSleep = 0x8, - DspWakeup = 0x9, - WakeupByExit = 0xA, - WakeupByPause = 0xB, - WakeupByCancel = 0xC, - WakeupByCancelAll = 0xD, - WakeupByPowerButtonClick = 0xE, - WakeupToJumpHome = 0xF, - RequestForSysApplet = 0x10, - WakeupToLaunchApplication = 0x11, -}; - -/// App Id's used by APT functions -enum class AppletId : u32 { - None = 0, - AnySystemApplet = 0x100, - HomeMenu = 0x101, - AlternateMenu = 0x103, - Camera = 0x110, - FriendsList = 0x112, - GameNotes = 0x113, - InternetBrowser = 0x114, - InstructionManual = 0x115, - Notifications = 0x116, - Miiverse = 0x117, - MiiversePost = 0x118, - AmiiboSettings = 0x119, - AnySysLibraryApplet = 0x200, - SoftwareKeyboard1 = 0x201, - Ed1 = 0x202, - PnoteApp = 0x204, - SnoteApp = 0x205, - Error = 0x206, - Mint = 0x207, - Extrapad = 0x208, - Memolib = 0x209, - Application = 0x300, - AnyLibraryApplet = 0x400, - SoftwareKeyboard2 = 0x401, - Ed2 = 0x402, - PnoteApp2 = 0x404, - SnoteApp2 = 0x405, - Error2 = 0x406, - Mint2 = 0x407, - Extrapad2 = 0x408, - Memolib2 = 0x409, -}; - -enum class StartupArgumentType : u32 { - OtherApp = 0, - Restart = 1, - OtherMedia = 2, -}; - -enum class ScreencapPostPermission : u32 { - CleanThePermission = 0, // TODO(JamePeng): verify what "zero" means - NoExplicitSetting = 1, - EnableScreenshotPostingToMiiverse = 2, - DisableScreenshotPostingToMiiverse = 3 -}; - -namespace ErrCodes { -enum { - ParameterPresent = 2, - InvalidAppletSlot = 4, -}; -} // namespace ErrCodes - -/// Send a parameter to the currently-running application, which will read it via ReceiveParameter -void SendParameter(const MessageParameter& parameter); - -/** - * APT::Initialize service function - * Service function that initializes the APT process for the running application - * Outputs: - * 1 : Result of the function, 0 on success, otherwise error code - * 3 : Handle to the notification event - * 4 : Handle to the pause event - */ -void Initialize(Service::Interface* self); - -/** - * APT::GetSharedFont service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Virtual address of where shared font will be loaded in memory - * 4 : Handle to shared font memory - */ -void GetSharedFont(Service::Interface* self); - -/** - * APT::Wrap service function - * Inputs: - * 1 : Output buffer size - * 2 : Input buffer size - * 3 : Nonce offset to the input buffer - * 4 : Nonce size - * 5 : Buffer mapping descriptor ((input_buffer_size << 4) | 0xA) - * 6 : Input buffer address - * 7 : Buffer mapping descriptor ((input_buffer_size << 4) | 0xC) - * 8 : Output buffer address - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Buffer unmapping descriptor ((input_buffer_size << 4) | 0xA) - * 3 : Input buffer address - * 4 : Buffer unmapping descriptor ((input_buffer_size << 4) | 0xC) - * 5 : Output buffer address - */ -void Wrap(Service::Interface* self); - -/** - * APT::Unwrap service function - * Inputs: - * 1 : Output buffer size - * 2 : Input buffer size - * 3 : Nonce offset to the output buffer - * 4 : Nonce size - * 5 : Buffer mapping descriptor ((input_buffer_size << 4) | 0xA) - * 6 : Input buffer address - * 7 : Buffer mapping descriptor ((input_buffer_size << 4) | 0xC) - * 8 : Output buffer address - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Buffer unmapping descriptor ((input_buffer_size << 4) | 0xA) - * 3 : Input buffer address - * 4 : Buffer unmapping descriptor ((input_buffer_size << 4) | 0xC) - * 5 : Output buffer address - */ -void Unwrap(Service::Interface* self); - -/** - * APT::NotifyToWait service function - * Inputs: - * 1 : AppID - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void NotifyToWait(Service::Interface* self); - -/** - * APT::GetLockHandle service function - * Inputs: - * 1 : Applet attributes - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Applet attributes - * 3 : Power button state - * 4 : IPC handle descriptor - * 5 : APT mutex handle - */ -void GetLockHandle(Service::Interface* self); - -/** - * APT::Enable service function - * Inputs: - * 1 : Applet attributes - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void Enable(Service::Interface* self); - -/** - * APT::GetAppletManInfo service function. - * Inputs: - * 1 : Unknown - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Unknown u32 value - * 3 : Unknown u8 value - * 4 : Home Menu AppId - * 5 : AppID of currently active app - */ -void GetAppletManInfo(Service::Interface* self); - -/** - * APT::GetAppletInfo service function. - * Inputs: - * 1 : AppId - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2-3 : Title ID - * 4 : Media Type - * 5 : Registered - * 6 : Loaded - * 7 : Attributes - */ -void GetAppletInfo(Service::Interface* self); - -/** - * APT::IsRegistered service function. This returns whether the specified AppID is registered with - * NS yet. An AppID is "registered" once the process associated with the AppID uses APT:Enable. Home - * Menu uses this command to determine when the launched process is running and to determine when to - * stop using GSP, etc., while displaying the "Nintendo 3DS" loading screen. - * - * Inputs: - * 1 : AppID - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Output, 0 = not registered, 1 = registered. - */ -void IsRegistered(Service::Interface* self); - -void InquireNotification(Service::Interface* self); - -/** - * APT::SendParameter service function. This sets the parameter data state. - * Inputs: - * 1 : Source AppID - * 2 : Destination AppID - * 3 : Signal type - * 4 : Parameter buffer size, max size is 0x1000 (this can be zero) - * 5 : Value - * 6 : Handle to the destination process, likely used for shared memory (this can be zero) - * 7 : (Size<<14) | 2 - * 8 : Input parameter buffer ptr - * Outputs: - * 0 : Return Header - * 1 : Result of function, 0 on success, otherwise error code -*/ -void SendParameter(Service::Interface* self); - -/** - * APT::ReceiveParameter service function. This returns the current parameter data from NS state, - * from the source process which set the parameters. Once finished, NS will clear a flag in the NS - * state so that this command will return an error if this command is used again if parameters were - * not set again. This is called when the second Initialize event is triggered. It returns a signal - * type indicating why it was triggered. - * Inputs: - * 1 : AppID - * 2 : Parameter buffer size, max size is 0x1000 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : AppID of the process which sent these parameters - * 3 : Signal type - * 4 : Actual parameter buffer size, this is <= to the the input size - * 5 : Value - * 6 : Handle from the source process which set the parameters, likely used for shared memory - * 7 : Size - * 8 : Output parameter buffer ptr - */ -void ReceiveParameter(Service::Interface* self); - -/** - * APT::GlanceParameter service function. This is exactly the same as APT_U::ReceiveParameter - * (except for the word value prior to the output handle), except this will not clear the flag - * (except when responseword[3]==8 || responseword[3]==9) in NS state. - * Inputs: - * 1 : AppID - * 2 : Parameter buffer size, max size is 0x1000 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Unknown, for now assume AppID of the process which sent these parameters - * 3 : Unknown, for now assume Signal type - * 4 : Actual parameter buffer size, this is <= to the the input size - * 5 : Value - * 6 : Handle from the source process which set the parameters, likely used for shared memory - * 7 : Size - * 8 : Output parameter buffer ptr - */ -void GlanceParameter(Service::Interface* self); - -/** - * APT::CancelParameter service function. When the parameter data is available, and when the above - * specified fields match the ones in NS state(for the ones where the checks are enabled), this - * clears the flag which indicates that parameter data is available - * (same flag cleared by APT:ReceiveParameter). - * Inputs: - * 1 : Flag, when non-zero NS will compare the word after this one with a field in the NS - * state. - * 2 : Unknown, this is the same as the first unknown field returned by APT:ReceiveParameter. - * 3 : Flag, when non-zero NS will compare the word after this one with a field in the NS - * state. - * 4 : AppID - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Status flag, 0 = failure due to no parameter data being available, or the above enabled - * fields don't match the fields in NS state. 1 = success. - */ -void CancelParameter(Service::Interface* self); - -/** - * APT::PrepareToStartApplication service function. When the input title-info programID is zero, - * NS will load the actual program ID via AMNet:GetTitleIDList. After doing some checks with the - * programID, NS will then set a NS state flag to value 1, then set the programID for AppID - * 0x300(application) to the input program ID(or the one from GetTitleIDList). A media-type field - * in the NS state is also set to the input media-type value - * (other state fields are set at this point as well). With 8.0.0-18, NS will set an u8 NS state - * field to value 1 when input flags bit8 is set - * Inputs: - * 1-4 : 0x10-byte title-info struct - * 4 : Flags - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -void PrepareToStartApplication(Service::Interface* self); - -/** - * APT::StartApplication service function. Buf0 is copied to NS FIRMparams+0x0, then Buf1 is copied - * to the NS FIRMparams+0x480. Then the application is launched. - * Inputs: - * 1 : Buffer 0 size, max size is 0x300 - * 2 : Buffer 1 size, max size is 0x20 (this can be zero) - * 3 : u8 flag - * 4 : (Size0<<14) | 2 - * 5 : Buffer 0 pointer - * 6 : (Size1<<14) | 0x802 - * 7 : Buffer 1 pointer - * Outputs: - * 0 : Return Header - * 1 : Result of function, 0 on success, otherwise error code -*/ -void StartApplication(Service::Interface* self); - -/** - * APT::AppletUtility service function - * Inputs: - * 1 : Unknown, but clearly used for something - * 2 : Buffer 1 size (purpose is unknown) - * 3 : Buffer 2 size (purpose is unknown) - * 5 : Buffer 1 address (purpose is unknown) - * 65 : Buffer 2 address (purpose is unknown) - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void AppletUtility(Service::Interface* self); - -/** - * APT::SetAppCpuTimeLimit service function - * Inputs: - * 1 : Value, must be one - * 2 : Percentage of CPU time from 5 to 80 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void SetAppCpuTimeLimit(Service::Interface* self); - -/** - * APT::GetAppCpuTimeLimit service function - * Inputs: - * 1 : Value, must be one - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - * 2 : System core CPU time percentage - */ -void GetAppCpuTimeLimit(Service::Interface* self); - -/** - * APT::PrepareToStartLibraryApplet service function - * Inputs: - * 0 : Command header [0x00180040] - * 1 : Id of the applet to start - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -void PrepareToStartLibraryApplet(Service::Interface* self); - -/** - * APT::PrepareToStartNewestHomeMenu service function - * Inputs: - * 0 : Command header [0x001A0000] - * Outputs: - * 0 : Return header - * 1 : Result of function - */ -void PrepareToStartNewestHomeMenu(Service::Interface* self); - -/** - * APT::PreloadLibraryApplet service function - * Inputs: - * 0 : Command header [0x00160040] - * 1 : Id of the applet to start - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -void PreloadLibraryApplet(Service::Interface* self); - -/** - * APT::StartLibraryApplet service function - * Inputs: - * 0 : Command header [0x001E0084] - * 1 : Id of the applet to start - * 2 : Buffer size - * 3 : Always 0? - * 4 : Handle passed to the applet - * 5 : (Size << 14) | 2 - * 6 : Input buffer virtual address - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -void StartLibraryApplet(Service::Interface* self); - -/** - * APT::CancelLibraryApplet service function - * Inputs: - * 0 : Command header [0x003B0040] - * 1 : u8, Application exiting (0 = not exiting, 1 = exiting) - * Outputs: - * 0 : Header code - * 1 : Result code - */ -void CancelLibraryApplet(Service::Interface* self); - -/** - * APT::GetStartupArgument service function - * Inputs: - * 1 : Parameter Size (capped to 0x300) - * 2 : StartupArgumentType - * 65 : Output buffer for startup argument - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8, Exists (0 = does not exist, 1 = exists) - */ -void GetStartupArgument(Service::Interface* self); - -/** - * APT::SetScreenCapPostPermission service function - * Inputs: - * 0 : Header Code[0x00550040] - * 1 : u8 The screenshot posting permission - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void SetScreenCapPostPermission(Service::Interface* self); - -/** - * APT::GetScreenCapPostPermission service function - * Inputs: - * 0 : Header Code[0x00560000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8 The screenshot posting permission - */ -void GetScreenCapPostPermission(Service::Interface* self); - -/** - * APT::CheckNew3DSApp service function - * Outputs: - * 1: Result code, 0 on success, otherwise error code - * 2: u8 output: 0 = Old3DS, 1 = New3DS. - * Note: - * This uses PTMSYSM:CheckNew3DS. - * When a certain NS state field is non-zero, the output value is zero, - * Otherwise the output is from PTMSYSM:CheckNew3DS. - * Normally this NS state field is zero, however this state field is set to 1 - * when APT:PrepareToStartApplication is used with flags bit8 is set. - */ -void CheckNew3DSApp(Service::Interface* self); - -/** - * Wrapper for PTMSYSM:CheckNew3DS - * APT::CheckNew3DS service function - * Outputs: - * 1: Result code, 0 on success, otherwise error code - * 2: u8 output: 0 = Old3DS, 1 = New3DS. - */ -void CheckNew3DS(Service::Interface* self); - -/// Initialize the APT service -void Init(); - -/// Shutdown the APT service -void Shutdown(); - -} // namespace APT -} // namespace Service diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp deleted file mode 100644 index c496cba8d..000000000 --- a/src/core/hle/service/apt/apt_a.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/apt/apt.h" -#include "core/hle/service/apt/apt_a.h" - -namespace Service { -namespace APT { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetLockHandle, "GetLockHandle"}, - {0x00020080, Initialize, "Initialize"}, - {0x00030040, Enable, "Enable"}, - {0x00040040, nullptr, "Finalize"}, - {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, - {0x00060040, GetAppletInfo, "GetAppletInfo"}, - {0x00070000, nullptr, "GetLastSignaledAppletId"}, - {0x00080000, nullptr, "CountRegisteredApplet"}, - {0x00090040, IsRegistered, "IsRegistered"}, - {0x000A0040, nullptr, "GetAttribute"}, - {0x000B0040, InquireNotification, "InquireNotification"}, - {0x000C0104, SendParameter, "SendParameter"}, - {0x000D0080, ReceiveParameter, "ReceiveParameter"}, - {0x000E0080, GlanceParameter, "GlanceParameter"}, - {0x000F0100, CancelParameter, "CancelParameter"}, - {0x001000C2, nullptr, "DebugFunc"}, - {0x001100C0, nullptr, "MapProgramIdForDebug"}, - {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, - {0x00130000, nullptr, "GetPreparationState"}, - {0x00140040, nullptr, "SetPreparationState"}, - {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, - {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, - {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, - {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, - {0x00190040, nullptr, "PrepareToStartSystemApplet"}, - {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, - {0x001B00C4, nullptr, "StartApplication"}, - {0x001C0000, nullptr, "WakeupApplication"}, - {0x001D0000, nullptr, "CancelApplication"}, - {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, - {0x001F0084, nullptr, "StartSystemApplet"}, - {0x00200044, nullptr, "StartNewestHomeMenu"}, - {0x00210000, nullptr, "OrderToCloseApplication"}, - {0x00220040, nullptr, "PrepareToCloseApplication"}, - {0x00230040, nullptr, "PrepareToJumpToApplication"}, - {0x00240044, nullptr, "JumpToApplication"}, - {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, - {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, - {0x00270044, nullptr, "CloseApplication"}, - {0x00280044, nullptr, "CloseLibraryApplet"}, - {0x00290044, nullptr, "CloseSystemApplet"}, - {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, - {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, - {0x002C0044, nullptr, "JumpToHomeMenu"}, - {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, - {0x002E0044, nullptr, "LeaveHomeMenu"}, - {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, - {0x00300044, nullptr, "LeaveResidentApplet"}, - {0x00310100, nullptr, "PrepareToDoApplicationJump"}, - {0x00320084, nullptr, "DoApplicationJump"}, - {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, - {0x00340084, nullptr, "SendDeliverArg"}, - {0x00350080, nullptr, "ReceiveDeliverArg"}, - {0x00360040, nullptr, "LoadSysMenuArg"}, - {0x00370042, nullptr, "StoreSysMenuArg"}, - {0x00380040, nullptr, "PreloadResidentApplet"}, - {0x00390040, nullptr, "PrepareToStartResidentApplet"}, - {0x003A0044, nullptr, "StartResidentApplet"}, - {0x003B0040, CancelLibraryApplet, "CancelLibraryApplet"}, - {0x003C0042, nullptr, "SendDspSleep"}, - {0x003D0042, nullptr, "SendDspWakeUp"}, - {0x003E0080, nullptr, "ReplySleepQuery"}, - {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, - {0x00400042, nullptr, "SendCaptureBufferInfo"}, - {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, - {0x00420080, nullptr, "SleepSystem"}, - {0x00430040, NotifyToWait, "NotifyToWait"}, - {0x00440000, GetSharedFont, "GetSharedFont"}, - {0x00450040, nullptr, "GetWirelessRebootInfo"}, - {0x00460104, Wrap, "Wrap"}, - {0x00470104, Unwrap, "Unwrap"}, - {0x00480100, nullptr, "GetProgramInfo"}, - {0x00490180, nullptr, "Reboot"}, - {0x004A0040, nullptr, "GetCaptureInfo"}, - {0x004B00C2, AppletUtility, "AppletUtility"}, - {0x004C0000, nullptr, "SetFatalErrDispMode"}, - {0x004D0080, nullptr, "GetAppletProgramInfo"}, - {0x004E0000, nullptr, "HardwareResetAsync"}, - {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, - {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, - {0x00510080, GetStartupArgument, "GetStartupArgument"}, - {0x00520104, nullptr, "Wrap1"}, - {0x00530104, nullptr, "Unwrap1"}, - {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, - {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, - {0x00570044, nullptr, "WakeupApplication2"}, - {0x00580002, nullptr, "GetProgramID"}, - {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, - {0x01020000, CheckNew3DS, "CheckNew3DS"}, - {0x01040000, nullptr, "IsStandardMemoryLayout"}, - {0x01050100, nullptr, "IsTitleAllowed"}, -}; - -APT_A_Interface::APT_A_Interface() : Interface(MaxAPTSessions) { - Register(FunctionTable); -} - -} // namespace APT -} // namespace Service diff --git a/src/core/hle/service/apt/apt_a.h b/src/core/hle/service/apt/apt_a.h deleted file mode 100644 index 331fb5586..000000000 --- a/src/core/hle/service/apt/apt_a.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace APT { - -class APT_A_Interface : public Service::Interface { -public: - APT_A_Interface(); - - std::string GetPortName() const override { - return "APT:A"; - } -}; - -} // namespace APT -} // namespace Service
\ No newline at end of file diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp deleted file mode 100644 index bb78ee7d7..000000000 --- a/src/core/hle/service/apt/apt_s.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/apt/apt.h" -#include "core/hle/service/apt/apt_s.h" - -namespace Service { -namespace APT { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetLockHandle, "GetLockHandle"}, - {0x00020080, Initialize, "Initialize"}, - {0x00030040, Enable, "Enable"}, - {0x00040040, nullptr, "Finalize"}, - {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, - {0x00060040, GetAppletInfo, "GetAppletInfo"}, - {0x00070000, nullptr, "GetLastSignaledAppletId"}, - {0x00080000, nullptr, "CountRegisteredApplet"}, - {0x00090040, IsRegistered, "IsRegistered"}, - {0x000A0040, nullptr, "GetAttribute"}, - {0x000B0040, InquireNotification, "InquireNotification"}, - {0x000C0104, SendParameter, "SendParameter"}, - {0x000D0080, ReceiveParameter, "ReceiveParameter"}, - {0x000E0080, GlanceParameter, "GlanceParameter"}, - {0x000F0100, nullptr, "CancelParameter"}, - {0x001000C2, nullptr, "DebugFunc"}, - {0x001100C0, nullptr, "MapProgramIdForDebug"}, - {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, - {0x00130000, nullptr, "GetPreparationState"}, - {0x00140040, nullptr, "SetPreparationState"}, - {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, - {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, - {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, - {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, - {0x00190040, nullptr, "PrepareToStartSystemApplet"}, - {0x001A0000, PrepareToStartNewestHomeMenu, "PrepareToStartNewestHomeMenu"}, - {0x001B00C4, nullptr, "StartApplication"}, - {0x001C0000, nullptr, "WakeupApplication"}, - {0x001D0000, nullptr, "CancelApplication"}, - {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, - {0x001F0084, nullptr, "StartSystemApplet"}, - {0x00200044, nullptr, "StartNewestHomeMenu"}, - {0x00210000, nullptr, "OrderToCloseApplication"}, - {0x00220040, nullptr, "PrepareToCloseApplication"}, - {0x00230040, nullptr, "PrepareToJumpToApplication"}, - {0x00240044, nullptr, "JumpToApplication"}, - {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, - {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, - {0x00270044, nullptr, "CloseApplication"}, - {0x00280044, nullptr, "CloseLibraryApplet"}, - {0x00290044, nullptr, "CloseSystemApplet"}, - {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, - {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, - {0x002C0044, nullptr, "JumpToHomeMenu"}, - {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, - {0x002E0044, nullptr, "LeaveHomeMenu"}, - {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, - {0x00300044, nullptr, "LeaveResidentApplet"}, - {0x00310100, nullptr, "PrepareToDoApplicationJump"}, - {0x00320084, nullptr, "DoApplicationJump"}, - {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, - {0x00340084, nullptr, "SendDeliverArg"}, - {0x00350080, nullptr, "ReceiveDeliverArg"}, - {0x00360040, nullptr, "LoadSysMenuArg"}, - {0x00370042, nullptr, "StoreSysMenuArg"}, - {0x00380040, nullptr, "PreloadResidentApplet"}, - {0x00390040, nullptr, "PrepareToStartResidentApplet"}, - {0x003A0044, nullptr, "StartResidentApplet"}, - {0x003B0040, nullptr, "CancelLibraryApplet"}, - {0x003C0042, nullptr, "SendDspSleep"}, - {0x003D0042, nullptr, "SendDspWakeUp"}, - {0x003E0080, nullptr, "ReplySleepQuery"}, - {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, - {0x00400042, nullptr, "SendCaptureBufferInfo"}, - {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, - {0x00420080, nullptr, "SleepSystem"}, - {0x00430040, NotifyToWait, "NotifyToWait"}, - {0x00440000, GetSharedFont, "GetSharedFont"}, - {0x00450040, nullptr, "GetWirelessRebootInfo"}, - {0x00460104, Wrap, "Wrap"}, - {0x00470104, Unwrap, "Unwrap"}, - {0x00480100, nullptr, "GetProgramInfo"}, - {0x00490180, nullptr, "Reboot"}, - {0x004A0040, nullptr, "GetCaptureInfo"}, - {0x004B00C2, AppletUtility, "AppletUtility"}, - {0x004C0000, nullptr, "SetFatalErrDispMode"}, - {0x004D0080, nullptr, "GetAppletProgramInfo"}, - {0x004E0000, nullptr, "HardwareResetAsync"}, - {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, - {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, - {0x00510080, GetStartupArgument, "GetStartupArgument"}, - {0x00520104, nullptr, "Wrap1"}, - {0x00530104, nullptr, "Unwrap1"}, - {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, - {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, - {0x00570044, nullptr, "WakeupApplication2"}, - {0x00580002, nullptr, "GetProgramID"}, - {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, - {0x01020000, CheckNew3DS, "CheckNew3DS"}, - {0x01040000, nullptr, "IsStandardMemoryLayout"}, - {0x01050100, nullptr, "IsTitleAllowed"}, -}; - -APT_S_Interface::APT_S_Interface() : Interface(MaxAPTSessions) { - Register(FunctionTable); -} - -} // namespace APT -} // namespace Service diff --git a/src/core/hle/service/apt/apt_s.h b/src/core/hle/service/apt/apt_s.h deleted file mode 100644 index 8e87b69af..000000000 --- a/src/core/hle/service/apt/apt_s.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace APT { - -// Application and title launching service. These services handle signaling for home/power button as -// well. Only one session for either APT service can be open at a time, normally processes close the -// service handle immediately once finished using the service. The commands for APT:U and APT:S are -// exactly the same, however certain commands are only accessible with APT:S(NS module will call -// svcBreak when the command isn't accessible). See http://3dbrew.org/wiki/NS#APT_Services. - -/// Interface to "APT:S" service -class APT_S_Interface : public Service::Interface { -public: - APT_S_Interface(); - - std::string GetPortName() const override { - return "APT:S"; - } -}; - -} // namespace APT -} // namespace Service
\ No newline at end of file diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp deleted file mode 100644 index 9dd002590..000000000 --- a/src/core/hle/service/apt/apt_u.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/apt/apt.h" -#include "core/hle/service/apt/apt_u.h" - -namespace Service { -namespace APT { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetLockHandle, "GetLockHandle"}, - {0x00020080, Initialize, "Initialize"}, - {0x00030040, Enable, "Enable"}, - {0x00040040, nullptr, "Finalize"}, - {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, - {0x00060040, GetAppletInfo, "GetAppletInfo"}, - {0x00070000, nullptr, "GetLastSignaledAppletId"}, - {0x00080000, nullptr, "CountRegisteredApplet"}, - {0x00090040, IsRegistered, "IsRegistered"}, - {0x000A0040, nullptr, "GetAttribute"}, - {0x000B0040, InquireNotification, "InquireNotification"}, - {0x000C0104, SendParameter, "SendParameter"}, - {0x000D0080, ReceiveParameter, "ReceiveParameter"}, - {0x000E0080, GlanceParameter, "GlanceParameter"}, - {0x000F0100, CancelParameter, "CancelParameter"}, - {0x001000C2, nullptr, "DebugFunc"}, - {0x001100C0, nullptr, "MapProgramIdForDebug"}, - {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, - {0x00130000, nullptr, "GetPreparationState"}, - {0x00140040, nullptr, "SetPreparationState"}, - {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, - {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, - {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, - {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, - {0x00190040, nullptr, "PrepareToStartSystemApplet"}, - {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, - {0x001B00C4, nullptr, "StartApplication"}, - {0x001C0000, nullptr, "WakeupApplication"}, - {0x001D0000, nullptr, "CancelApplication"}, - {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, - {0x001F0084, nullptr, "StartSystemApplet"}, - {0x00200044, nullptr, "StartNewestHomeMenu"}, - {0x00210000, nullptr, "OrderToCloseApplication"}, - {0x00220040, nullptr, "PrepareToCloseApplication"}, - {0x00230040, nullptr, "PrepareToJumpToApplication"}, - {0x00240044, nullptr, "JumpToApplication"}, - {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, - {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, - {0x00270044, nullptr, "CloseApplication"}, - {0x00280044, nullptr, "CloseLibraryApplet"}, - {0x00290044, nullptr, "CloseSystemApplet"}, - {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, - {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, - {0x002C0044, nullptr, "JumpToHomeMenu"}, - {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, - {0x002E0044, nullptr, "LeaveHomeMenu"}, - {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, - {0x00300044, nullptr, "LeaveResidentApplet"}, - {0x00310100, nullptr, "PrepareToDoApplicationJump"}, - {0x00320084, nullptr, "DoApplicationJump"}, - {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, - {0x00340084, nullptr, "SendDeliverArg"}, - {0x00350080, nullptr, "ReceiveDeliverArg"}, - {0x00360040, nullptr, "LoadSysMenuArg"}, - {0x00370042, nullptr, "StoreSysMenuArg"}, - {0x00380040, nullptr, "PreloadResidentApplet"}, - {0x00390040, nullptr, "PrepareToStartResidentApplet"}, - {0x003A0044, nullptr, "StartResidentApplet"}, - {0x003B0040, CancelLibraryApplet, "CancelLibraryApplet"}, - {0x003C0042, nullptr, "SendDspSleep"}, - {0x003D0042, nullptr, "SendDspWakeUp"}, - {0x003E0080, nullptr, "ReplySleepQuery"}, - {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, - {0x00400042, nullptr, "SendCaptureBufferInfo"}, - {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, - {0x00420080, nullptr, "SleepSystem"}, - {0x00430040, NotifyToWait, "NotifyToWait"}, - {0x00440000, GetSharedFont, "GetSharedFont"}, - {0x00450040, nullptr, "GetWirelessRebootInfo"}, - {0x00460104, Wrap, "Wrap"}, - {0x00470104, Unwrap, "Unwrap"}, - {0x00480100, nullptr, "GetProgramInfo"}, - {0x00490180, nullptr, "Reboot"}, - {0x004A0040, nullptr, "GetCaptureInfo"}, - {0x004B00C2, AppletUtility, "AppletUtility"}, - {0x004C0000, nullptr, "SetFatalErrDispMode"}, - {0x004D0080, nullptr, "GetAppletProgramInfo"}, - {0x004E0000, nullptr, "HardwareResetAsync"}, - {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, - {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, - {0x00510080, GetStartupArgument, "GetStartupArgument"}, - {0x00520104, nullptr, "Wrap1"}, - {0x00530104, nullptr, "Unwrap1"}, - {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, - {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, - {0x00580002, nullptr, "GetProgramID"}, - {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, - {0x01020000, CheckNew3DS, "CheckNew3DS"}, -}; - -APT_U_Interface::APT_U_Interface() : Interface(MaxAPTSessions) { - Register(FunctionTable); -} - -} // namespace APT -} // namespace Service diff --git a/src/core/hle/service/apt/apt_u.h b/src/core/hle/service/apt/apt_u.h deleted file mode 100644 index 8c7fe0ccb..000000000 --- a/src/core/hle/service/apt/apt_u.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace APT { - -// Application and title launching service. These services handle signaling for home/power button as -// well. Only one session for either APT service can be open at a time, normally processes close the -// service handle immediately once finished using the service. The commands for APT:U and APT:S are -// exactly the same, however certain commands are only accessible with APT:S(NS module will call -// svcBreak when the command isn't accessible). See http://3dbrew.org/wiki/NS#APT_Services. - -/// Interface to "APT:U" service -class APT_U_Interface : public Service::Interface { -public: - APT_U_Interface(); - - std::string GetPortName() const override { - return "APT:U"; - } -}; - -} // namespace APT -} // namespace Service
\ No newline at end of file diff --git a/src/core/hle/service/apt/bcfnt/bcfnt.cpp b/src/core/hle/service/apt/bcfnt/bcfnt.cpp deleted file mode 100644 index 6d2474702..000000000 --- a/src/core/hle/service/apt/bcfnt/bcfnt.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/apt/bcfnt/bcfnt.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace APT { -namespace BCFNT { - -void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr new_address) { - static const u32 SharedFontStartOffset = 0x80; - const u8* cfnt_ptr = shared_font->GetPointer(SharedFontStartOffset); - - CFNT cfnt; - memcpy(&cfnt, cfnt_ptr, sizeof(cfnt)); - - u32 assumed_cmap_offset = 0; - u32 assumed_cwdh_offset = 0; - u32 assumed_tglp_offset = 0; - u32 first_cmap_offset = 0; - u32 first_cwdh_offset = 0; - u32 first_tglp_offset = 0; - - // First discover the location of sections so that the rebase offset can be auto-detected - u32 current_offset = SharedFontStartOffset + cfnt.header_size; - for (unsigned block = 0; block < cfnt.num_blocks; ++block) { - const u8* data = shared_font->GetPointer(current_offset); - - SectionHeader section_header; - memcpy(§ion_header, data, sizeof(section_header)); - - if (first_cmap_offset == 0 && memcmp(section_header.magic, "CMAP", 4) == 0) { - first_cmap_offset = current_offset; - } else if (first_cwdh_offset == 0 && memcmp(section_header.magic, "CWDH", 4) == 0) { - first_cwdh_offset = current_offset; - } else if (first_tglp_offset == 0 && memcmp(section_header.magic, "TGLP", 4) == 0) { - first_tglp_offset = current_offset; - } else if (memcmp(section_header.magic, "FINF", 4) == 0) { - BCFNT::FINF finf; - memcpy(&finf, data, sizeof(finf)); - - assumed_cmap_offset = finf.cmap_offset - sizeof(SectionHeader); - assumed_cwdh_offset = finf.cwdh_offset - sizeof(SectionHeader); - assumed_tglp_offset = finf.tglp_offset - sizeof(SectionHeader); - } - - current_offset += section_header.section_size; - } - - u32 previous_base = assumed_cmap_offset - first_cmap_offset; - ASSERT(previous_base == assumed_cwdh_offset - first_cwdh_offset); - ASSERT(previous_base == assumed_tglp_offset - first_tglp_offset); - - u32 offset = new_address - previous_base; - - // Reset pointer back to start of sections and do the actual rebase - current_offset = SharedFontStartOffset + cfnt.header_size; - for (unsigned block = 0; block < cfnt.num_blocks; ++block) { - u8* data = shared_font->GetPointer(current_offset); - - SectionHeader section_header; - memcpy(§ion_header, data, sizeof(section_header)); - - if (memcmp(section_header.magic, "FINF", 4) == 0) { - BCFNT::FINF finf; - memcpy(&finf, data, sizeof(finf)); - - // Relocate the offsets in the FINF section - finf.cmap_offset += offset; - finf.cwdh_offset += offset; - finf.tglp_offset += offset; - - memcpy(data, &finf, sizeof(finf)); - } else if (memcmp(section_header.magic, "CMAP", 4) == 0) { - BCFNT::CMAP cmap; - memcpy(&cmap, data, sizeof(cmap)); - - // Relocate the offsets in the CMAP section - if (cmap.next_cmap_offset != 0) - cmap.next_cmap_offset += offset; - - memcpy(data, &cmap, sizeof(cmap)); - } else if (memcmp(section_header.magic, "CWDH", 4) == 0) { - BCFNT::CWDH cwdh; - memcpy(&cwdh, data, sizeof(cwdh)); - - // Relocate the offsets in the CWDH section - if (cwdh.next_cwdh_offset != 0) - cwdh.next_cwdh_offset += offset; - - memcpy(data, &cwdh, sizeof(cwdh)); - } else if (memcmp(section_header.magic, "TGLP", 4) == 0) { - BCFNT::TGLP tglp; - memcpy(&tglp, data, sizeof(tglp)); - - // Relocate the offsets in the TGLP section - tglp.sheet_data_offset += offset; - - memcpy(data, &tglp, sizeof(tglp)); - } - - current_offset += section_header.section_size; - } -} - -} // namespace BCFNT -} // namespace APT -} // namespace Service
\ No newline at end of file diff --git a/src/core/hle/service/apt/bcfnt/bcfnt.h b/src/core/hle/service/apt/bcfnt/bcfnt.h deleted file mode 100644 index 453bf7606..000000000 --- a/src/core/hle/service/apt/bcfnt/bcfnt.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/swap.h" -#include "core/hle/kernel/shared_memory.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace APT { -namespace BCFNT { ///< BCFNT Shared Font file structures - -struct CFNT { - u8 magic[4]; - u16_le endianness; - u16_le header_size; - u32_le version; - u32_le file_size; - u32_le num_blocks; -}; - -struct SectionHeader { - u8 magic[4]; - u32_le section_size; -}; - -struct FINF { - u8 magic[4]; - u32_le section_size; - u8 font_type; - u8 line_feed; - u16_le alter_char_index; - u8 default_width[3]; - u8 encoding; - u32_le tglp_offset; - u32_le cwdh_offset; - u32_le cmap_offset; - u8 height; - u8 width; - u8 ascent; - u8 reserved; -}; - -struct TGLP { - u8 magic[4]; - u32_le section_size; - u8 cell_width; - u8 cell_height; - u8 baseline_position; - u8 max_character_width; - u32_le sheet_size; - u16_le num_sheets; - u16_le sheet_image_format; - u16_le num_columns; - u16_le num_rows; - u16_le sheet_width; - u16_le sheet_height; - u32_le sheet_data_offset; -}; - -struct CMAP { - u8 magic[4]; - u32_le section_size; - u16_le code_begin; - u16_le code_end; - u16_le mapping_method; - u16_le reserved; - u32_le next_cmap_offset; -}; - -struct CWDH { - u8 magic[4]; - u32_le section_size; - u16_le start_index; - u16_le end_index; - u32_le next_cwdh_offset; -}; - -/** - * Relocates the internal addresses of the BCFNT Shared Font to the new base. The current base will - * be auto-detected based on the file headers. - * - * @param shared_font SharedMemory object that contains the Shared Font - * @param new_address New base for the offsets in the structure. - */ -void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr new_address); - -} // namespace BCFNT -} // namespace APT -} // namespace Service diff --git a/src/core/hle/service/boss/boss.cpp b/src/core/hle/service/boss/boss.cpp deleted file mode 100644 index 2bba3aff6..000000000 --- a/src/core/hle/service/boss/boss.cpp +++ /dev/null @@ -1,994 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <cinttypes> -#include "common/logging/log.h" -#include "core/hle/ipc.h" -#include "core/hle/result.h" -#include "core/hle/service/boss/boss.h" -#include "core/hle/service/boss/boss_p.h" -#include "core/hle/service/boss/boss_u.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace BOSS { - -static u32 new_arrival_flag; -static u32 ns_data_new_flag; -static u32 output_flag; - -void InitializeSession(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u64 unk_param = ((u64)cmd_buff[1] | ((u64)cmd_buff[2] << 32)); - u32 translation = cmd_buff[3]; - u32 unk_param4 = cmd_buff[4]; - - if (translation != IPC::CallingPidDesc()) { - cmd_buff[0] = IPC::MakeHeader(0, 0x1, 0); // 0x40 - cmd_buff[1] = IPC::ERR_INVALID_BUFFER_DESCRIPTOR.raw; - LOG_ERROR(Service_BOSS, "The translation was invalid, translation=0x%08X", translation); - return; - } - - cmd_buff[0] = IPC::MakeHeader(0x1, 0x1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_BOSS, - "(STUBBED) unk_param=0x%016" PRIX64 ", translation=0x%08X, unk_param4=0x%08X", - unk_param, translation, unk_param4); -} - -void RegisterStorage(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - u32 unk_param3 = cmd_buff[3]; - u32 unk_flag = cmd_buff[4] & 0xFF; - - cmd_buff[0] = IPC::MakeHeader(0x2, 0x1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING( - Service_BOSS, - "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, unk_param3=0x%08X, unk_flag=0x%08X", - unk_param1, unk_param2, unk_param3, unk_flag); -} - -void UnregisterStorage(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x3, 0x1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_BOSS, "(STUBBED) called"); -} - -void GetStorageInfo(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x4, 0x2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 - - LOG_WARNING(Service_BOSS, "(STUBBED) called"); -} - -void RegisterPrivateRootCa(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 translation = cmd_buff[2]; - u32 buff_addr = cmd_buff[3]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x5, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) translation=0x%08X, buff_addr=0x%08X, buff_size=0x%08X", - translation, buff_addr, buff_size); -} - -void RegisterPrivateClientCert(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - u32 translation1 = cmd_buff[3]; - u32 buff1_addr = cmd_buff[4]; - u32 buff1_size = (translation1 >> 4); - u32 translation2 = cmd_buff[5]; - u32 buff2_addr = cmd_buff[6]; - u32 buff2_size = (translation2 >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x6, 0x1, 0x4); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff1_size << 4 | 0xA); - cmd_buff[3] = buff1_addr; - cmd_buff[2] = (buff2_size << 4 | 0xA); - cmd_buff[3] = buff2_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, " - "translation1=0x%08X, buff1_addr=0x%08X, buff1_size=0x%08X, " - "translation2=0x%08X, buff2_addr=0x%08X, buff2_size=0x%08X", - unk_param1, unk_param2, translation1, buff1_addr, buff1_size, translation2, - buff2_addr, buff2_size); -} - -void GetNewArrivalFlag(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x7, 0x2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = new_arrival_flag; - - LOG_WARNING(Service_BOSS, "(STUBBED) new_arrival_flag=%u", new_arrival_flag); -} - -void RegisterNewArrivalEvent(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - - cmd_buff[0] = IPC::MakeHeader(0x8, 0x1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X", unk_param1, - unk_param2); -} - -void SetOptoutFlag(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - output_flag = cmd_buff[1] & 0xFF; - - cmd_buff[0] = IPC::MakeHeader(0x9, 0x1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_BOSS, "output_flag=%u", output_flag); -} - -void GetOptoutFlag(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0xA, 0x2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = output_flag; - - LOG_WARNING(Service_BOSS, "output_flag=%u", output_flag); -} - -void RegisterTask(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2] & 0xFF; - u32 unk_param3 = cmd_buff[3] & 0xFF; - u32 translation = cmd_buff[4]; - u32 buff_addr = cmd_buff[5]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0xB, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, unk_param3=0x%08X, " - "translation=0x%08X, buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, unk_param3, translation, buff_addr, buff_size); -} - -void UnregisterTask(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2] & 0xFF; - u32 translation = cmd_buff[3]; - u32 buff_addr = cmd_buff[4]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0xC, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, translation, buff_addr, buff_size); -} - -void ReconfigureTask(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2] & 0xFF; - u32 translation = cmd_buff[3]; - u32 buff_addr = cmd_buff[4]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0xD, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, translation, buff_addr, buff_size); -} - -void GetTaskIdList(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0xE, 0x1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_BOSS, "(STUBBED) called"); -} - -void GetStepIdList(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 translation = cmd_buff[2]; - u32 buff_addr = cmd_buff[3]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0xF, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) translation=0x%08X, buff_addr=0x%08X, buff_size=0x%08X", - translation, buff_addr, buff_size); -} - -void GetNsDataIdList(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - u32 unk_param3 = cmd_buff[3]; - u32 unk_param4 = cmd_buff[4]; - u32 translation = cmd_buff[5]; - u32 buff_addr = cmd_buff[6]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x10, 0x3, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (16 bit value) - cmd_buff[3] = 0; // stub 0 (16 bit value) - cmd_buff[4] = (buff_size << 4 | 0xC); - cmd_buff[5] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, unk_param3=0x%08X, " - "unk_param4=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, unk_param3, unk_param4, translation, buff_addr, buff_size); -} - -void GetOwnNsDataIdList(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - u32 unk_param3 = cmd_buff[3]; - u32 unk_param4 = cmd_buff[4]; - u32 translation = cmd_buff[5]; - u32 buff_addr = cmd_buff[6]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x11, 0x3, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (16 bit value) - cmd_buff[3] = 0; // stub 0 (16 bit value) - cmd_buff[4] = (buff_size << 4 | 0xC); - cmd_buff[5] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, unk_param3=0x%08X, " - "unk_param4=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, unk_param3, unk_param4, translation, buff_addr, buff_size); -} - -void GetNewDataNsDataIdList(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - u32 unk_param3 = cmd_buff[3]; - u32 unk_param4 = cmd_buff[4]; - u32 translation = cmd_buff[5]; - u32 buff_addr = cmd_buff[6]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x12, 0x3, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (16 bit value) - cmd_buff[3] = 0; // stub 0 (16 bit value) - cmd_buff[4] = (buff_size << 4 | 0xC); - cmd_buff[5] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, unk_param3=0x%08X, " - "unk_param4=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, unk_param3, unk_param4, translation, buff_addr, buff_size); -} - -void GetOwnNewDataNsDataIdList(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - u32 unk_param3 = cmd_buff[3]; - u32 unk_param4 = cmd_buff[4]; - u32 translation = cmd_buff[5]; - u32 buff_addr = cmd_buff[6]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x13, 0x3, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (16 bit value) - cmd_buff[3] = 0; // stub 0 (16 bit value) - cmd_buff[4] = (buff_size << 4 | 0xC); - cmd_buff[5] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, unk_param3=0x%08X, " - "unk_param4=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, unk_param3, unk_param4, translation, buff_addr, buff_size); -} - -void SendProperty(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - u32 translation = cmd_buff[3]; - u32 buff_addr = cmd_buff[4]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x14, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, translation, buff_addr, buff_size); -} - -void SendPropertyHandle(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[2] & 0xFF; - u32 translation = cmd_buff[3]; - u32 buff_addr = cmd_buff[4]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x15, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, translation, buff_addr, buff_size); -} - -void ReceiveProperty(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 buff_size = cmd_buff[2]; - u32 translation = cmd_buff[3]; - u32 buff_addr = cmd_buff[4]; - - cmd_buff[0] = IPC::MakeHeader(0x16, 0x2, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (32 bit value) - cmd_buff[2] = (buff_size << 4 | 0xC); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, buff_size=0x%08X, " - "translation=0x%08X, buff_addr=0x%08X", - unk_param1, buff_size, translation, buff_addr); -} - -void UpdateTaskInterval(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2] & 0xFF; - u32 translation = cmd_buff[3]; - u32 buff_addr = cmd_buff[4]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x17, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, " - "translation=0x%08X, buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, translation, buff_addr, buff_size); -} - -void UpdateTaskCount(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 buff_size = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; // TODO(JamePeng): Figure out the meaning of these parameters - u32 translation = cmd_buff[3]; - u32 buff_addr = cmd_buff[4]; - - cmd_buff[0] = IPC::MakeHeader(0x18, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) buff_size=0x%08X, unk_param2=0x%08X, " - "translation=0x%08X, buff_addr=0x%08X", - buff_size, unk_param2, translation, buff_addr); -} - -void GetTaskInterval(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 unk_param1 = cmd_buff[1]; // TODO(JamePeng): Figure out the meaning of these parameters - u32 translation = cmd_buff[2]; - u32 buff_addr = cmd_buff[3]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x19, 0x2, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 ( 32bit value) - cmd_buff[3] = (buff_size << 4 | 0xA); - cmd_buff[4] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, translation, buff_addr, buff_size); -} - -void GetTaskCount(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 unk_param1 = cmd_buff[1]; // TODO(JamePeng): Figure out the meaning of these parameters - u32 translation = cmd_buff[2]; - u32 buff_addr = cmd_buff[3]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x1A, 0x2, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 ( 32bit value) - cmd_buff[3] = (buff_size << 4 | 0xA); - cmd_buff[4] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, translation, buff_addr, buff_size); -} - -void GetTaskServiceStatus(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 unk_param1 = cmd_buff[1]; // TODO(JamePeng): Figure out the meaning of these parameters - u32 translation = cmd_buff[2]; - u32 buff_addr = cmd_buff[3]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x1B, 0x2, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 ( 8bit value) - cmd_buff[3] = (buff_size << 4 | 0xA); - cmd_buff[4] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, translation, buff_addr, buff_size); -} - -void StartTask(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 unk_param1 = cmd_buff[1]; // TODO(JamePeng): Figure out the meaning of these parameters - u32 translation = cmd_buff[2]; - u32 buff_addr = cmd_buff[3]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x1C, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, translation, buff_addr, buff_size); -} - -void StartTaskImmediate(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 unk_param1 = cmd_buff[1]; // TODO(JamePeng): Figure out the meaning of these parameters - u32 translation = cmd_buff[2]; - u32 buff_addr = cmd_buff[3]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x1D, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, translation, buff_addr, buff_size); -} - -void CancelTask(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 translation = cmd_buff[2]; - u32 buff_addr = cmd_buff[3]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x1E, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, translation, buff_addr, buff_size); -} - -void GetTaskFinishHandle(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x1F, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; - cmd_buff[3] = 0; // stub 0(This should be a handle of task_finish ?) - - LOG_WARNING(Service_BOSS, "(STUBBED) called"); -} - -void GetTaskState(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 buff_size = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2] & 0xFF; - u32 translation = cmd_buff[3]; - u32 buff_addr = cmd_buff[4]; - - cmd_buff[0] = IPC::MakeHeader(0x20, 0x4, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (8 bit value) - cmd_buff[3] = 0; // stub 0 (32 bit value) - cmd_buff[4] = 0; // stub 0 (8 bit value) - cmd_buff[5] = (buff_size << 4 | 0xA); - cmd_buff[6] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) buff_size=0x%08X, unk_param2=0x%08X, " - "translation=0x%08X, buff_addr=0x%08X", - buff_size, unk_param2, translation, buff_addr); -} - -void GetTaskResult(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 translation = cmd_buff[2]; - u32 buff_addr = cmd_buff[3]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x21, 0x4, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (8 bit value) - cmd_buff[3] = 0; // stub 0 (32 bit value) - cmd_buff[4] = 0; // stub 0 (8 bit value) - cmd_buff[5] = (buff_size << 4 | 0xA); - cmd_buff[6] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, translation, buff_addr, buff_size); -} - -void GetTaskCommErrorCode(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 translation = cmd_buff[2]; - u32 buff_addr = cmd_buff[3]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x22, 0x4, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (32 bit value) - cmd_buff[3] = 0; // stub 0 (32 bit value) - cmd_buff[4] = 0; // stub 0 (8 bit value) - cmd_buff[5] = (buff_size << 4 | 0xA); - cmd_buff[6] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, translation, buff_addr, buff_size); -} - -void GetTaskStatus(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2] & 0xFF; - u32 unk_param3 = cmd_buff[3] & 0xFF; - u32 translation = cmd_buff[4]; - u32 buff_addr = cmd_buff[5]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x23, 0x2, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (8 bit value) - cmd_buff[3] = (buff_size << 4 | 0xA); - cmd_buff[4] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, unk_param3=0x%08X, " - "translation=0x%08X, buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, unk_param3, translation, buff_addr, buff_size); -} - -void GetTaskError(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2] & 0xFF; - u32 translation = cmd_buff[4]; - u32 buff_addr = cmd_buff[5]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x24, 0x2, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (8 bit value) - cmd_buff[3] = (buff_size << 4 | 0xA); - cmd_buff[4] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, translation, buff_addr, buff_size); -} - -void GetTaskInfo(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2] & 0xFF; - u32 translation = cmd_buff[4]; - u32 buff_addr = cmd_buff[5]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x25, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, translation, buff_addr, buff_size); -} - -void DeleteNsData(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - - cmd_buff[0] = IPC::MakeHeader(0x26, 0x1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X", unk_param1); -} - -void GetNsDataHeaderInfo(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2] & 0xFF; - u32 unk_param3 = cmd_buff[3]; - u32 translation = cmd_buff[4]; - u32 buff_addr = cmd_buff[5]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x27, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xC); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, unk_param3=0x%08X, " - "translation=0x%08X, buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, unk_param3, translation, buff_addr, buff_size); -} - -void ReadNsData(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - u32 unk_param3 = cmd_buff[3]; - u32 unk_param4 = cmd_buff[4]; - u32 translation = cmd_buff[5]; - u32 buff_addr = cmd_buff[6]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x28, 0x3, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (32bit value) - cmd_buff[3] = 0; // stub 0 (32bit value) - cmd_buff[4] = (buff_size << 4 | 0xC); - cmd_buff[5] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, unk_param3=0x%08X, " - "unk_param4=0x%08X, translation=0x%08X, " - "buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, unk_param3, unk_param4, translation, buff_addr, buff_size); -} - -void SetNsDataAdditionalInfo(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - - cmd_buff[0] = IPC::MakeHeader(0x29, 0x1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X", unk_param1, - unk_param2); -} - -void GetNsDataAdditionalInfo(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - - cmd_buff[0] = IPC::MakeHeader(0x2A, 0x2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (32bit value) - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X", unk_param1); -} - -void SetNsDataNewFlag(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - ns_data_new_flag = cmd_buff[2] & 0xFF; - - cmd_buff[0] = IPC::MakeHeader(0x2B, 0x1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, ns_data_new_flag=0x%08X", unk_param1, - ns_data_new_flag); -} - -void GetNsDataNewFlag(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - - cmd_buff[0] = IPC::MakeHeader(0x2C, 0x2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = ns_data_new_flag; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, ns_data_new_flag=0x%08X", unk_param1, - ns_data_new_flag); -} - -void GetNsDataLastUpdate(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - - cmd_buff[0] = IPC::MakeHeader(0x2D, 0x3, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (32bit value) - cmd_buff[3] = 0; // stub 0 (32bit value) - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X", unk_param1); -} - -void GetErrorCode(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - - cmd_buff[0] = IPC::MakeHeader(0x2E, 0x2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (32bit value) - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X", unk_param1); -} - -void RegisterStorageEntry(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - u32 unk_param3 = cmd_buff[3]; - u32 unk_param4 = cmd_buff[4]; - u32 unk_param5 = cmd_buff[5] & 0xFF; - - cmd_buff[0] = IPC::MakeHeader(0x2F, 0x1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, unk_param3=0x%08X, " - "unk_param4=0x%08X, unk_param5=0x%08X", - unk_param1, unk_param2, unk_param3, unk_param4, unk_param5); -} - -void GetStorageEntryInfo(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x30, 0x3, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (32bit value) - cmd_buff[3] = 0; // stub 0 (16bit value) - - LOG_WARNING(Service_BOSS, "(STUBBED) called"); -} - -void SetStorageOption(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1] & 0xFF; - u32 unk_param2 = cmd_buff[2]; - u32 unk_param3 = cmd_buff[3]; - u32 unk_param4 = cmd_buff[4]; - - cmd_buff[0] = IPC::MakeHeader(0x31, 0x1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, " - "unk_param3=0x%08X, unk_param4=0x%08X", - unk_param1, unk_param2, unk_param3, unk_param4); -} - -void GetStorageOption(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x32, 0x5, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (32bit value) - cmd_buff[3] = 0; // stub 0 (8bit value) - cmd_buff[4] = 0; // stub 0 (16bit value) - cmd_buff[5] = 0; // stub 0 (16bit value) - - LOG_WARNING(Service_BOSS, "(STUBBED) called"); -} - -void StartBgImmediate(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 unk_param1 = cmd_buff[1]; // TODO(JamePeng): Figure out the meaning of these parameters - u32 translation = cmd_buff[2]; - u32 buff_addr = cmd_buff[3]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x33, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff_size << 4 | 0xA); - cmd_buff[3] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) buff_size=0x%08X, unk_param2=0x%08X, " - "translation=0x%08X, buff_addr=0x%08X", - unk_param1, translation, buff_addr, buff_size); -} - -void GetTaskActivePriority(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 unk_param1 = cmd_buff[1]; // TODO(JamePeng): Figure out the meaning of these parameters - u32 translation = cmd_buff[2]; - u32 buff_addr = cmd_buff[3]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x34, 0x2, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // stub 0 (8bit value) - cmd_buff[3] = (buff_size << 4 | 0xA); - cmd_buff[4] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) buff_size=0x%08X, unk_param2=0x%08X, " - "translation=0x%08X, buff_addr=0x%08X", - unk_param1, translation, buff_addr, buff_size); -} - -void RegisterImmediateTask(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2] & 0xFF; - u32 unk_param3 = cmd_buff[3] & 0xFF; - u32 translation = cmd_buff[4]; - u32 buff_addr = cmd_buff[5]; - u32 buff_size = (translation >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x35, 0x1, 0x2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[3] = (buff_size << 4 | 0xA); - cmd_buff[4] = buff_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, unk_param3=0x%08X, " - "translation=0x%08X, buff_addr=0x%08X, buff_size=0x%08X", - unk_param1, unk_param2, unk_param3, translation, buff_addr, buff_size); -} - -void SetTaskQuery(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - u32 translation1 = cmd_buff[3]; - u32 buff1_addr = cmd_buff[4]; - u32 buff1_size = (translation1 >> 4); - u32 translation2 = cmd_buff[5]; - u32 buff2_addr = cmd_buff[6]; - u32 buff2_size = (translation2 >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x36, 0x1, 0x4); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff1_size << 4 | 0xA); - cmd_buff[3] = buff1_addr; - cmd_buff[2] = (buff2_size << 4 | 0xA); - cmd_buff[3] = buff2_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, " - "translation1=0x%08X, buff1_addr=0x%08X, buff1_size=0x%08X, " - "translation2=0x%08X, buff2_addr=0x%08X, buff2_size=0x%08X", - unk_param1, unk_param2, translation1, buff1_addr, buff1_size, translation2, - buff2_addr, buff2_size); -} - -void GetTaskQuery(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - // TODO(JamePeng): Figure out the meaning of these parameters - u32 unk_param1 = cmd_buff[1]; - u32 unk_param2 = cmd_buff[2]; - u32 translation1 = cmd_buff[3]; - u32 buff1_addr = cmd_buff[4]; - u32 buff1_size = (translation1 >> 4); - u32 translation2 = cmd_buff[5]; - u32 buff2_addr = cmd_buff[6]; - u32 buff2_size = (translation2 >> 4); - - cmd_buff[0] = IPC::MakeHeader(0x37, 0x1, 0x4); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = (buff1_size << 4 | 0xA); - cmd_buff[3] = buff1_addr; - cmd_buff[2] = (buff2_size << 4 | 0xC); - cmd_buff[3] = buff2_addr; - - LOG_WARNING(Service_BOSS, "(STUBBED) unk_param1=0x%08X, unk_param2=0x%08X, " - "translation1=0x%08X, buff1_addr=0x%08X, buff1_size=0x%08X, " - "translation2=0x%08X, buff2_addr=0x%08X, buff2_size=0x%08X", - unk_param1, unk_param2, translation1, buff1_addr, buff1_size, translation2, - buff2_addr, buff2_size); -} - -void Init() { - using namespace Kernel; - - AddService(new BOSS_P_Interface); - AddService(new BOSS_U_Interface); - - new_arrival_flag = 0; - ns_data_new_flag = 0; - output_flag = 0; -} - -void Shutdown() {} - -} // namespace BOSS - -} // namespace Service diff --git a/src/core/hle/service/boss/boss.h b/src/core/hle/service/boss/boss.h deleted file mode 100644 index 8cdc663c8..000000000 --- a/src/core/hle/service/boss/boss.h +++ /dev/null @@ -1,802 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace BOSS { - -/** - * BOSS::InitializeSession service function - * Inputs: - * 0 : Header Code[0x00010082] - * 1 : u32 lower 64bit value - * 2 : u32 higher 64bit value - * 3 : 0x20 - * 4 : u32 unknown value - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void InitializeSession(Service::Interface* self); - -/** - * BOSS::RegisterStorage service function - * Inputs: - * 0 : Header Code[0x00020010] - * 1 : u32 unknown1 - * 2 : u32 unknown2 - * 3 : u32 unknown3 - * 4 : u8 unknown_flag - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void RegisterStorage(Service::Interface* self); - -/** - * BOSS::UnregisterStorage service function - * Inputs: - * 0 : Header Code[0x00030000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void UnregisterStorage(Service::Interface* self); - -/** - * BOSS::GetStorageInfo service function - * Inputs: - * 0 : Header Code[0x00040000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u32 unknown value - */ -void GetStorageInfo(Service::Interface* self); - -/** - * BOSS::RegisterPrivateRootCa service function - * Inputs: - * 0 : Header Code[0x00050042] - * 1 : u32 unknown value - * 2 : MappedBufferDesc(permission = R) - * 3 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void RegisterPrivateRootCa(Service::Interface* self); - -/** - * BOSS::RegisterPrivateClientCert service function - * Inputs: - * 0 : Header Code[0x00060084] - * 1 : u32 unknown value - * 2 : u32 unknown value - * 3 : MappedBufferDesc1(permission = R) - * 4 : u32 buff_addr1 - * 5 : MappedBufferDesc2(permission = R) - * 6 : u32 buff_addr2 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff1_size << 4 | 0xA - * 3 : u32 buff_addr1 - * 4 : buff2_size << 4 | 0xA - * 5 : u32 buff_addr2 - */ -void RegisterPrivateClientCert(Service::Interface* self); - -/** - * BOSS::GetNewArrivalFlag service function - * Inputs: - * 0 : Header Code[0x00070000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8 flag - */ -void GetNewArrivalFlag(Service::Interface* self); - -/** - * BOSS::RegisterNewArrivalEvent service function - * Inputs: - * 0 : Header Code[0x00080002] - * 1 : u32 unknown1 - * 2 : u32 unknown2 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void RegisterNewArrivalEvent(Service::Interface* self); - -/** - * BOSS::SetOptoutFlag service function - * Inputs: - * 0 : Header Code[0x00090040] - * 1 : u8 output_flag - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void SetOptoutFlag(Service::Interface* self); - -/** - * BOSS::GetOptoutFlag service function - * Inputs: - * 0 : Header Code[0x000A0000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8 output_flag - */ -void GetOptoutFlag(Service::Interface* self); - -/** - * BOSS::RegisterTask service function - * Inputs: - * 0 : Header Code[0x000B00C2] - * 1 : u32 unknown value - * 2 : u8 unknown value - * 3 : u8 unknown value - * 4 : MappedBufferDesc1(permission = R) - * 5 : buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void RegisterTask(Service::Interface* self); - -/** - * BOSS::UnregisterTask service function - * Inputs: - * 0 : Header Code[0x000C0082] - * 1 : u32 unknown value - * 2 : u8 unknown value - * 3 : MappedBufferDesc1(permission = R) - * 4 : buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void UnregisterTask(Service::Interface* self); - -/** - * BOSS::ReconfigureTask service function - * Inputs: - * 0 : Header Code[0x000D0082] - * 1 : u32 unknown value - * 2 : u8 unknown value - * 3 : MappedBufferDesc1(permission = R) - * 4 : buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void ReconfigureTask(Service::Interface* self); - -/** - * BOSS::GetTaskIdList service function - * Inputs: - * 0 : Header Code[0x000E0000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void GetTaskIdList(Service::Interface* self); - -/** - * BOSS::GetStepIdList service function - * Inputs: - * 0 : Header Code[0x000F0042] - * 2 : MappedBufferDesc(permission = R) - * 3 : u32 buff_addr - * - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void GetStepIdList(Service::Interface* self); - -/** - * BOSS::GetNsDataIdList service function - * Inputs: - * 0 : Header Code[0x00100102] - * 1 : u32 unknown1 - * 2 : u32 unknown2 - * 3 : u32 unknown3 - * 4 : u32 unknown4 - * 5 : MappedBufferDesc(permission = W) - * 6 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u16 unknown value - * 3 : u16 unknown value - * 4 : buff_size << 4 | 0xC - * 5 : u32 buff_addr - */ -void GetNsDataIdList(Service::Interface* self); - -/** - * BOSS::GetOwnNsDataIdList service function - * Inputs: - * 0 : Header Code[0x00110102] - * 1 : u32 unknown1 - * 2 : u32 unknown2 - * 3 : u32 unknown3 - * 4 : u32 unknown4 - * 5 : MappedBufferDesc(permission = W) - * 6 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u16 unknown value - * 3 : u16 unknown value - * 4 : buff_size << 4 | 0xC - * 5 : u32 buff_addr - */ -void GetOwnNsDataIdList(Service::Interface* self); - -/** - * BOSS::GetNewDataNsDataIdList service function - * Inputs: - * 0 : Header Code[0x00120102] - * 1 : u32 unknown1 - * 2 : u32 unknown2 - * 3 : u32 unknown3 - * 4 : u32 unknown4 - * 5 : MappedBufferDesc(permission = W) - * 6 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u16 unknown value - * 3 : u16 unknown value - * 4 : buff_size << 4 | 0xC - * 5 : u32 buff_addr - */ -void GetNewDataNsDataIdList(Service::Interface* self); - -/** - * BOSS::GetOwnNewDataNsDataIdList service function - * Inputs: - * 0 : Header Code[0x00130102] - * 1 : u32 unknown1 - * 2 : u32 unknown2 - * 3 : u32 unknown3 - * 4 : u32 unknown4 - * 5 : MappedBufferDesc(permission = W) - * 6 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u16 unknown value - * 3 : u16 unknown value - - */ -void GetOwnNewDataNsDataIdList(Service::Interface* self); - -/** - * BOSS::SendProperty service function - * Inputs: - * 0 : Header Code[0x00140082] - * 1 : u16 unknown value - * 2 : u32 unknown value - * 3 : MappedBufferDesc(permission = R) - * 4 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void SendProperty(Service::Interface* self); - -/** - * BOSS::SendPropertyHandle service function - * Inputs: - * 0 : Header Code[0x00150042] - * 2 : u8 unknown value - * 3 : MappedBufferDesc(permission = R) - * 4 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void SendPropertyHandle(Service::Interface* self); - -/** - * BOSS::ReceiveProperty service function - * Inputs: - * 0 : Header Code[0x00160082] - * 1 : u16 unknown1 - * 2 : u32 buff_size - * 3 : MappedBufferDesc(permission = W) - * 4 : u32 buff addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u32 unknown value - * 3 : u16 unknown value - * 4 : buff_size << 4 | 0xC - * 5 : u32 buff_addr - */ -void ReceiveProperty(Service::Interface* self); - -/** - * BOSS::UpdateTaskInterval service function - * Inputs: - * 0 : Header Code[0x00170082] - * 1 : u32 unknown value - * 2 : u8 unknown value - * 3 : MappedBufferDesc1(permission = R) - * 4 : buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void UpdateTaskInterval(Service::Interface* self); - -/** - * BOSS::UpdateTaskCount service function - * Inputs: - * 0 : Header Code[0x00180082] - * 1 : u32 buff_size - * 2 : u32 unknown2 - * 3 : MappedBufferDesc(permission = R) - * 4 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void UpdateTaskCount(Service::Interface* self); - -/** - * BOSS::GetTaskInterval service function - * Inputs: - * 0 : Header Code[0x00190042] - * 1 : u32 unknown value - * 2 : MappedBufferDesc(permission = R) - * 3 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u32 unknown value - * 3 : buff_size << 4 | 0xA - * 4 : u32 buff_addr - */ -void GetTaskInterval(Service::Interface* self); - -/** - * BOSS::GetTaskCount service function - * Inputs: - * 0 : Header Code[0x001A0042] - * 1 : u32 unknown value - * 2 : MappedBufferDesc(permission = R) - * 3 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u32 unknown value - * 3 : buff_size << 4 | 0xA - * 4 : u32 buff_addr - */ -void GetTaskCount(Service::Interface* self); - -/** - * BOSS::GetTaskServiceStatus service function - * Inputs: - * 0 : Header Code[0x001B0042] - * 1 : u32 unknown value - * 2 : MappedBufferDesc(permission = R) - * 3 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8 unknown value - * 3 : buff_size << 4 | 0xA - * 4 : u32 buff_addr - */ -void GetTaskServiceStatus(Service::Interface* self); - -/** - * BOSS::StartTask service function - * Inputs: - * 0 : Header Code[0x001C0042] - * 1 : u32 unknown value - * 2 : MappedBufferDesc(permission = R) - * 3 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void StartTask(Service::Interface* self); - -/** - * BOSS::StartTaskImmediate service function - * Inputs: - * 0 : Header Code[0x001D0042] - * 1 : u32 unknown value - * 2 : MappedBufferDesc(permission = R) - * 3 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void StartTaskImmediate(Service::Interface* self); - -/** - * BOSS::CancelTask service function - * Inputs: - * 0 : Header Code[0x001E0042] - * 1 : u32 unknown value - * 2 : MappedBufferDesc(permission = R) - * 3 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void CancelTask(Service::Interface* self); - -/** - * BOSS::GetTaskFinishHandle service function - * Inputs: - * 0 : Header Code[0x001F0000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : 0 - * 3 : Task Finish Handle - */ -void GetTaskFinishHandle(Service::Interface* self); - -/** - * BOSS::GetTaskState service function - * Inputs: - * 0 : Header Code[0x00200082] - * 1 : u32 buff_size - * 2 : u8 unknown value - * 3 : MappedBufferDesc(permission = R) - * 4 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8 unknown value - * 3 : u32 unknown value - * 4 : u8 unknown value - * 5 : buff_size << 4 | 0xA - * 6 : u32 buff_addr - */ -void GetTaskState(Service::Interface* self); - -/** - * BOSS::GetTaskResult service function - * Inputs: - * 0 : Header Code[0x00210042] - * 1 : u32 unknown value - * 2 : MappedBufferDesc(permission = R) - * 3 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8 unknown value - * 3 : u32 unknown value - * 4 : u8 unknown value - * 5 : buff_size << 4 | 0xA - * 6 : u32 buff_addr - */ -void GetTaskResult(Service::Interface* self); - -/** - * BOSS::GetTaskCommErrorCode service function - * Inputs: - * 0 : Header Code[0x00220042] - * 1 : u32 unknown value - * 2 : MappedBufferDesc(permission = R) - * 3 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u32 unknown value - * 3 : u32 unknown value - * 4 : u8 unknown value - * 5 : buff_size << 4 | 0xA - * 6 : u32 buff_addr - */ -void GetTaskCommErrorCode(Service::Interface* self); - -/** - * BOSS::GetTaskStatus service function - * Inputs: - * 0 : Header Code[0x002300C2] - * 1 : u32 unknown value - * 2 : u8 unknown value - * 3 : u8 unknown value - * 4 : MappedBufferDesc(permission = R) - * 5 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8 unknown value - * 3 : buff_size << 4 | 0xA - * 4 : u32 buff_addr - */ -void GetTaskStatus(Service::Interface* self); - -/** - * BOSS::GetTaskError service function - * Inputs: - * 0 : Header Code[0x00240082] - * 1 : u32 unknown value - * 2 : u8 unknown value - * 3 : MappedBufferDesc(permission = R) - * 4 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8 unknown value - * 3 : buff_size << 4 | 0xA - * 4 : u32 buff_addr - */ -void GetTaskError(Service::Interface* self); - -/** - * BOSS::GetTaskInfo service function - * Inputs: - * 0 : Header Code[0x00250082] - * 1 : u32 unknown value - * 2 : u8 unknown value - * 3 : MappedBufferDesc(permission = R) - * 4 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void GetTaskInfo(Service::Interface* self); - -/** - * BOSS::DeleteNsData service function - * Inputs: - * 0 : Header Code[0x00260040] - * 1 : u32 unknown value - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void DeleteNsData(Service::Interface* self); - -/** - * BOSS::GetNsDataHeaderInfo service function - * Inputs: - * 0 : Header Code[0x002700C2] - * 1 : u32 unknown value - * 2 : u8 unknown value - * 3 : u32 unknown value - * 4 : MappedBufferDesc(permission = W) - * 5 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xC - * 3 : u32 buff_addr - */ -void GetNsDataHeaderInfo(Service::Interface* self); - -/** - * BOSS::ReadNsData service function - * Inputs: - * 0 : Header Code[0x00280102] - * 1 : u32 unknown value - * 2 : u32 unknown value - * 3 : u32 unknown value - * 4 : u32 unknown value - * 5 : MappedBufferDesc(permission = W) - * 6 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u32 unknown value - * 3 : u32 unknown value - * 4 : buff_size << 4 | 0xC - * 5 : u32 buff_addr - */ -void ReadNsData(Service::Interface* self); - -/** - * BOSS::SetNsDataAdditionalInfo service function - * Inputs: - * 0 : Header Code[0x00290080] - * 1 : u32 unknown value - * 2 : u32 unknown value - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void SetNsDataAdditionalInfo(Service::Interface* self); - -/** - * BOSS::GetNsDataAdditionalInfo service function - * Inputs: - * 0 : Header Code[0x002A0040] - * 1 : u32 unknown value - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u32 unknown value - */ -void GetNsDataAdditionalInfo(Service::Interface* self); - -/** - * BOSS::SetNsDataNewFlag service function - * Inputs: - * 0 : Header Code[0x002B0080] - * 1 : u32 unknown value - * 2 : u8 flag - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void SetNsDataNewFlag(Service::Interface* self); - -/** - * BOSS::GetNsDataNewFlag service function - * Inputs: - * 0 : Header Code[0x002C0040] - * 1 : u32 unknown value - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8 flag - */ -void GetNsDataNewFlag(Service::Interface* self); - -/** - * BOSS::GetNsDataLastUpdate service function - * Inputs: - * 0 : Header Code[0x002D0040] - * 1 : u32 unknown value - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u32 unknown value - * 3 : u32 unknown value - */ -void GetNsDataLastUpdate(Service::Interface* self); - -/** - * BOSS::GetErrorCode service function - * Inputs: - * 0 : Header Code[0x002E0040] - * 1 : u8 unknown value - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u32 unknown value - */ -void GetErrorCode(Service::Interface* self); - -/** - * BOSS::RegisterStorageEntry service function - * Inputs: - * 0 : Header Code[0x002F0140] - * 1 : u32 unknown value - * 2 : u32 unknown value - * 3 : u32 unknown value - * 4 : u16 unknown value - * 5 : u8 unknown value - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void RegisterStorageEntry(Service::Interface* self); - -/** - * BOSS::GetStorageEntryInfo service function - * Inputs: - * 0 : Header Code[0x00300000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u32 unknown value - * 3 : u16 unknown value - */ -void GetStorageEntryInfo(Service::Interface* self); - -/** - * BOSS::SetStorageOption service function - * Inputs: - * 0 : Header Code[0x00310100] - * 1 : u8 unknown value - * 2 : u32 unknown value - * 3 : u16 unknown value - * 4 : u16 unknown value - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void SetStorageOption(Service::Interface* self); - -/** - * BOSS::GetStorageOption service function - * Inputs: - * 0 : Header Code[0x00320000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8 unknown value - * 3 : u32 unknown value - * 4 : u16 unknown value - * 5 : u16 unknown value - */ -void GetStorageOption(Service::Interface* self); - -/** - * BOSS::StartBgImmediate service function - * Inputs: - * 0 : Header Code[0x00330042] - * 1 : u32 unknown value - * 2 : MappedBufferDesc(permission = R) - * 3 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void StartBgImmediate(Service::Interface* self); - -/** - * BOSS::GetTaskActivePriority service function - * Inputs: - * 0 : Header Code[0x00340042] - * 1 : u32 unknown value - * 2 : MappedBufferDesc(permission = R) - * 3 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8 unknown value - * 3 : buff_size << 4 | 0xA - * 4 : u32 buff_addr - */ -void GetTaskActivePriority(Service::Interface* self); - -/** - * BOSS::RegisterImmediateTask service function - * Inputs: - * 0 : Header Code[0x003500C2] - * 1 : u32 unknown value - * 2 : u8 unknown value - * 3 : u8 unknown value - * 4 : MappedBufferDesc(permission = R) - * 5 : u32 buff_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff_size << 4 | 0xA - * 3 : u32 buff_addr - */ -void RegisterImmediateTask(Service::Interface* self); - -/** - * BOSS::SetTaskQuery service function - * Inputs: - * 0 : Header Code[0x00360084] - * 1 : u32 unknown value - * 2 : u32 unknown value - * 3 : MappedBufferDesc1(permission = R) - * 4 : u32 buff1_addr - * 5 : MappedBufferDesc2(permission = R) - * 6 : u32 buff2_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff1_size << 4 | 0xA - * 3 : u32 buff1_addr - * 4 : buff2_size << 4 | 0xA - * 5 : u32 buff2_addr - */ -void SetTaskQuery(Service::Interface* self); - -/** - * BOSS::GetTaskQuery service function - * Inputs: - * 0 : Header Code[0x00370084] - * 1 : u32 unknown value - * 2 : u32 unknown value - * 3 : MappedBufferDesc1(permission = R) - * 4 : u32 buff1_addr - * 5 : MappedBufferDesc2(permission = W) - * 6 : u32 buff2_addr - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : buff1_size << 4 | 0xA - * 3 : u32 buff1_addr - * 4 : buff2_size << 4 | 0xC - * 5 : u32 buff2_addr - */ -void GetTaskQuery(Service::Interface* self); - -/// Initialize BOSS service(s) -void Init(); - -/// Shutdown BOSS service(s) -void Shutdown(); - -} // namespace BOSS -} // namespace Service diff --git a/src/core/hle/service/boss/boss_p.cpp b/src/core/hle/service/boss/boss_p.cpp deleted file mode 100644 index 3990d0d6e..000000000 --- a/src/core/hle/service/boss/boss_p.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/boss/boss.h" -#include "core/hle/service/boss/boss_p.h" - -namespace Service { -namespace BOSS { - -const Interface::FunctionInfo FunctionTable[] = { - // boss:u shared commands - {0x00010082, InitializeSession, "InitializeSession"}, - {0x00020100, RegisterStorage, "RegisterStorage"}, - {0x00030000, UnregisterStorage, "UnregisterStorage"}, - {0x00040000, GetStorageInfo, "GetStorageInfo"}, - {0x00050042, RegisterPrivateRootCa, "RegisterPrivateRootCa"}, - {0x00060084, RegisterPrivateClientCert, "RegisterPrivateClientCert"}, - {0x00070000, GetNewArrivalFlag, "GetNewArrivalFlag"}, - {0x00080002, RegisterNewArrivalEvent, "RegisterNewArrivalEvent"}, - {0x00090040, SetOptoutFlag, "SetOptoutFlag"}, - {0x000A0000, GetOptoutFlag, "GetOptoutFlag"}, - {0x000B00C2, RegisterTask, "RegisterTask"}, - {0x000C0082, UnregisterTask, "UnregisterTask"}, - {0x000D0082, ReconfigureTask, "ReconfigureTask"}, - {0x000E0000, GetTaskIdList, "GetTaskIdList"}, - {0x000F0042, GetStepIdList, "GetStepIdList"}, - {0x00100102, GetNsDataIdList, "GetNsDataIdList"}, - {0x00110102, GetOwnNsDataIdList, "GetOwnNsDataIdList"}, - {0x00120102, GetNewDataNsDataIdList, "GetNewDataNsDataIdList"}, - {0x00130102, GetOwnNewDataNsDataIdList, "GetOwnNewDataNsDataIdList"}, - {0x00140082, SendProperty, "SendProperty"}, - {0x00150042, SendPropertyHandle, "SendPropertyHandle"}, - {0x00160082, ReceiveProperty, "ReceiveProperty"}, - {0x00170082, UpdateTaskInterval, "UpdateTaskInterval"}, - {0x00180082, UpdateTaskCount, "UpdateTaskCount"}, - {0x00190042, GetTaskInterval, "GetTaskInterval"}, - {0x001A0042, GetTaskCount, "GetTaskCount"}, - {0x001B0042, GetTaskServiceStatus, "GetTaskServiceStatus"}, - {0x001C0042, StartTask, "StartTask"}, - {0x001D0042, StartTaskImmediate, "StartTaskImmediate"}, - {0x001E0042, CancelTask, "CancelTask"}, - {0x001F0000, GetTaskFinishHandle, "GetTaskFinishHandle"}, - {0x00200082, GetTaskState, "GetTaskState"}, - {0x00210042, GetTaskResult, "GetTaskResult"}, - {0x00220042, GetTaskCommErrorCode, "GetTaskCommErrorCode"}, - {0x002300C2, GetTaskStatus, "GetTaskStatus"}, - {0x00240082, GetTaskError, "GetTaskError"}, - {0x00250082, GetTaskInfo, "GetTaskInfo"}, - {0x00260040, DeleteNsData, "DeleteNsData"}, - {0x002700C2, GetNsDataHeaderInfo, "GetNsDataHeaderInfo"}, - {0x00280102, ReadNsData, "ReadNsData"}, - {0x00290080, SetNsDataAdditionalInfo, "SetNsDataAdditionalInfo"}, - {0x002A0040, GetNsDataAdditionalInfo, "GetNsDataAdditionalInfo"}, - {0x002B0080, SetNsDataNewFlag, "SetNsDataNewFlag"}, - {0x002C0040, GetNsDataNewFlag, "GetNsDataNewFlag"}, - {0x002D0040, GetNsDataLastUpdate, "GetNsDataLastUpdate"}, - {0x002E0040, GetErrorCode, "GetErrorCode"}, - {0x002F0140, RegisterStorageEntry, "RegisterStorageEntry"}, - {0x00300000, GetStorageEntryInfo, "GetStorageEntryInfo"}, - {0x00310100, SetStorageOption, "SetStorageOption"}, - {0x00320000, GetStorageOption, "GetStorageOption"}, - {0x00330042, StartBgImmediate, "StartBgImmediate"}, - {0x00340042, GetTaskActivePriority, "GetTaskActivePriority"}, - {0x003500C2, RegisterImmediateTask, "RegisterImmediateTask"}, - {0x00360084, SetTaskQuery, "SetTaskQuery"}, - {0x00370084, GetTaskQuery, "GetTaskQuery"}, - // boss:p - {0x04010082, nullptr, "InitializeSessionPrivileged"}, - {0x04040080, nullptr, "GetAppNewFlag"}, - {0x040D0182, nullptr, "GetNsDataIdListPrivileged"}, - {0x040E0182, nullptr, "GetNsDataIdListPrivileged1"}, - {0x04130082, nullptr, "SendPropertyPrivileged"}, - {0x041500C0, nullptr, "DeleteNsDataPrivileged"}, - {0x04160142, nullptr, "GetNsDataHeaderInfoPrivileged"}, - {0x04170182, nullptr, "ReadNsDataPrivileged"}, - {0x041A0100, nullptr, "SetNsDataNewFlagPrivileged"}, - {0x041B00C0, nullptr, "GetNsDataNewFlagPrivileged"}, -}; - -BOSS_P_Interface::BOSS_P_Interface() { - Register(FunctionTable); -} - -} // namespace BOSS -} // namespace Service diff --git a/src/core/hle/service/boss/boss_p.h b/src/core/hle/service/boss/boss_p.h deleted file mode 100644 index 32112c251..000000000 --- a/src/core/hle/service/boss/boss_p.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace BOSS { - -class BOSS_P_Interface : public Service::Interface { -public: - BOSS_P_Interface(); - - std::string GetPortName() const override { - return "boss:P"; - } -}; - -} // namespace BOSS -} // namespace Service diff --git a/src/core/hle/service/boss/boss_u.cpp b/src/core/hle/service/boss/boss_u.cpp deleted file mode 100644 index 371d702e0..000000000 --- a/src/core/hle/service/boss/boss_u.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/boss/boss.h" -#include "core/hle/service/boss/boss_u.h" - -namespace Service { -namespace BOSS { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010082, InitializeSession, "InitializeSession"}, - {0x00020100, RegisterStorage, "RegisterStorage"}, - {0x00030000, UnregisterStorage, "UnregisterStorage"}, - {0x00040000, GetStorageInfo, "GetStorageInfo"}, - {0x00050042, RegisterPrivateRootCa, "RegisterPrivateRootCa"}, - {0x00060084, RegisterPrivateClientCert, "RegisterPrivateClientCert"}, - {0x00070000, GetNewArrivalFlag, "GetNewArrivalFlag"}, - {0x00080002, RegisterNewArrivalEvent, "RegisterNewArrivalEvent"}, - {0x00090040, SetOptoutFlag, "SetOptoutFlag"}, - {0x000A0000, GetOptoutFlag, "GetOptoutFlag"}, - {0x000B00C2, RegisterTask, "RegisterTask"}, - {0x000C0082, UnregisterTask, "UnregisterTask"}, - {0x000D0082, ReconfigureTask, "ReconfigureTask"}, - {0x000E0000, GetTaskIdList, "GetTaskIdList"}, - {0x000F0042, GetStepIdList, "GetStepIdList"}, - {0x00100102, GetNsDataIdList, "GetNsDataIdList"}, - {0x00110102, GetOwnNsDataIdList, "GetOwnNsDataIdList"}, - {0x00120102, GetNewDataNsDataIdList, "GetNewDataNsDataIdList"}, - {0x00130102, GetOwnNewDataNsDataIdList, "GetOwnNewDataNsDataIdList"}, - {0x00140082, SendProperty, "SendProperty"}, - {0x00150042, SendPropertyHandle, "SendPropertyHandle"}, - {0x00160082, ReceiveProperty, "ReceiveProperty"}, - {0x00170082, UpdateTaskInterval, "UpdateTaskInterval"}, - {0x00180082, UpdateTaskCount, "UpdateTaskCount"}, - {0x00190042, GetTaskInterval, "GetTaskInterval"}, - {0x001A0042, GetTaskCount, "GetTaskCount"}, - {0x001B0042, GetTaskServiceStatus, "GetTaskServiceStatus"}, - {0x001C0042, StartTask, "StartTask"}, - {0x001D0042, StartTaskImmediate, "StartTaskImmediate"}, - {0x001E0042, CancelTask, "CancelTask"}, - {0x001F0000, GetTaskFinishHandle, "GetTaskFinishHandle"}, - {0x00200082, GetTaskState, "GetTaskState"}, - {0x00210042, GetTaskResult, "GetTaskResult"}, - {0x00220042, GetTaskCommErrorCode, "GetTaskCommErrorCode"}, - {0x002300C2, GetTaskStatus, "GetTaskStatus"}, - {0x00240082, GetTaskError, "GetTaskError"}, - {0x00250082, GetTaskInfo, "GetTaskInfo"}, - {0x00260040, DeleteNsData, "DeleteNsData"}, - {0x002700C2, GetNsDataHeaderInfo, "GetNsDataHeaderInfo"}, - {0x00280102, ReadNsData, "ReadNsData"}, - {0x00290080, SetNsDataAdditionalInfo, "SetNsDataAdditionalInfo"}, - {0x002A0040, GetNsDataAdditionalInfo, "GetNsDataAdditionalInfo"}, - {0x002B0080, SetNsDataNewFlag, "SetNsDataNewFlag"}, - {0x002C0040, GetNsDataNewFlag, "GetNsDataNewFlag"}, - {0x002D0040, GetNsDataLastUpdate, "GetNsDataLastUpdate"}, - {0x002E0040, GetErrorCode, "GetErrorCode"}, - {0x002F0140, RegisterStorageEntry, "RegisterStorageEntry"}, - {0x00300000, GetStorageEntryInfo, "GetStorageEntryInfo"}, - {0x00310100, SetStorageOption, "SetStorageOption"}, - {0x00320000, GetStorageOption, "GetStorageOption"}, - {0x00330042, StartBgImmediate, "StartBgImmediate"}, - {0x00340042, GetTaskActivePriority, "GetTaskActivePriority"}, - {0x003500C2, RegisterImmediateTask, "RegisterImmediateTask"}, - {0x00360084, SetTaskQuery, "SetTaskQuery"}, - {0x00370084, GetTaskQuery, "GetTaskQuery"}, -}; - -BOSS_U_Interface::BOSS_U_Interface() { - Register(FunctionTable); -} - -} // namespace BOSS -} // namespace Service diff --git a/src/core/hle/service/boss/boss_u.h b/src/core/hle/service/boss/boss_u.h deleted file mode 100644 index d047d8cf2..000000000 --- a/src/core/hle/service/boss/boss_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace BOSS { - -class BOSS_U_Interface : public Service::Interface { -public: - BOSS_U_Interface(); - - std::string GetPortName() const override { - return "boss:U"; - } -}; - -} // namespace BOSS -} // namespace Service diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp deleted file mode 100644 index 8172edae8..000000000 --- a/src/core/hle/service/cam/cam.cpp +++ /dev/null @@ -1,1106 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> -#include <array> -#include <future> -#include <memory> -#include <vector> -#include "common/bit_set.h" -#include "common/logging/log.h" -#include "core/core_timing.h" -#include "core/frontend/camera/factory.h" -#include "core/hle/ipc.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/event.h" -#include "core/hle/result.h" -#include "core/hle/service/cam/cam.h" -#include "core/hle/service/cam/cam_c.h" -#include "core/hle/service/cam/cam_q.h" -#include "core/hle/service/cam/cam_s.h" -#include "core/hle/service/cam/cam_u.h" -#include "core/hle/service/service.h" -#include "core/memory.h" -#include "core/settings.h" - -namespace Service { -namespace CAM { - -namespace { - -struct ContextConfig { - Flip flip; - Effect effect; - OutputFormat format; - Resolution resolution; -}; - -struct CameraConfig { - std::unique_ptr<Camera::CameraInterface> impl; - std::array<ContextConfig, 2> contexts; - int current_context; - FrameRate frame_rate; -}; - -struct PortConfig { - int camera_id; - - bool is_active; // set when the port is activated by an Activate call. - bool is_pending_receiving; // set if SetReceiving is called when is_busy = false. When - // StartCapture is called then, this will trigger a receiving - // process and reset itself. - bool is_busy; // set when StartCapture is called and reset when StopCapture is called. - bool is_receiving; // set when there is an ongoing receiving process. - - bool is_trimming; - u16 x0; // x-coordinate of starting position for trimming - u16 y0; // y-coordinate of starting position for trimming - u16 x1; // x-coordinate of ending position for trimming - u16 y1; // y-coordinate of ending position for trimming - - u16 transfer_bytes; - - Kernel::SharedPtr<Kernel::Event> completion_event; - Kernel::SharedPtr<Kernel::Event> buffer_error_interrupt_event; - Kernel::SharedPtr<Kernel::Event> vsync_interrupt_event; - - std::future<std::vector<u16>> capture_result; // will hold the received frame. - VAddr dest; // the destination address of a receiving process - u32 dest_size; // the destination size of a receiving process - - void Clear() { - completion_event->Clear(); - buffer_error_interrupt_event->Clear(); - vsync_interrupt_event->Clear(); - is_receiving = false; - is_active = false; - is_pending_receiving = false; - is_busy = false; - is_trimming = false; - x0 = 0; - y0 = 0; - x1 = 0; - y1 = 0; - transfer_bytes = 256; - } -}; - -// built-in resolution parameters -constexpr std::array<Resolution, 8> PRESET_RESOLUTION{{ - {640, 480, 0, 0, 639, 479}, // VGA - {320, 240, 0, 0, 639, 479}, // QVGA - {160, 120, 0, 0, 639, 479}, // QQVGA - {352, 288, 26, 0, 613, 479}, // CIF - {176, 144, 26, 0, 613, 479}, // QCIF - {256, 192, 0, 0, 639, 479}, // DS_LCD - {512, 384, 0, 0, 639, 479}, // DS_LCDx4 - {400, 240, 0, 48, 639, 431}, // CTR_TOP_LCD -}}; - -// latency in ms for each frame rate option -constexpr std::array<int, 13> LATENCY_BY_FRAME_RATE{{ - 67, // Rate_15 - 67, // Rate_15_To_5 - 67, // Rate_15_To_2 - 100, // Rate_10 - 118, // Rate_8_5 - 200, // Rate_5 - 50, // Rate_20 - 50, // Rate_20_To_5 - 33, // Rate_30 - 33, // Rate_30_To_5 - 67, // Rate_15_To_10 - 50, // Rate_20_To_10 - 33, // Rate_30_To_10 -}}; - -std::array<CameraConfig, NumCameras> cameras; -std::array<PortConfig, 2> ports; -int completion_event_callback; - -const ResultCode ERROR_INVALID_ENUM_VALUE(ErrorDescription::InvalidEnumValue, ErrorModule::CAM, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); -const ResultCode ERROR_OUT_OF_RANGE(ErrorDescription::OutOfRange, ErrorModule::CAM, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); - -void CompletionEventCallBack(u64 port_id, int) { - PortConfig& port = ports[port_id]; - const CameraConfig& camera = cameras[port.camera_id]; - const auto buffer = port.capture_result.get(); - - if (port.is_trimming) { - u32 trim_width; - u32 trim_height; - const int original_width = camera.contexts[camera.current_context].resolution.width; - const int original_height = camera.contexts[camera.current_context].resolution.height; - if (port.x1 <= port.x0 || port.y1 <= port.y0 || port.x1 > original_width || - port.y1 > original_height) { - LOG_ERROR(Service_CAM, "Invalid trimming coordinates x0=%u, y0=%u, x1=%u, y1=%u", - port.x0, port.y0, port.x1, port.y1); - trim_width = 0; - trim_height = 0; - } else { - trim_width = port.x1 - port.x0; - trim_height = port.y1 - port.y0; - } - - u32 trim_size = (port.x1 - port.x0) * (port.y1 - port.y0) * 2; - if (port.dest_size != trim_size) { - LOG_ERROR(Service_CAM, "The destination size (%u) doesn't match the source (%u)!", - port.dest_size, trim_size); - } - - const u32 src_offset = port.y0 * original_width + port.x0; - const u16* src_ptr = buffer.data() + src_offset; - // Note: src_size_left is int because it can be negative if the buffer size doesn't match. - int src_size_left = static_cast<int>((buffer.size() - src_offset) * sizeof(u16)); - VAddr dest_ptr = port.dest; - // Note: dest_size_left and line_bytes are int to match the type of src_size_left. - int dest_size_left = static_cast<int>(port.dest_size); - const int line_bytes = static_cast<int>(trim_width * sizeof(u16)); - - for (u32 y = 0; y < trim_height; ++y) { - int copy_length = std::min({line_bytes, dest_size_left, src_size_left}); - if (copy_length <= 0) { - break; - } - Memory::WriteBlock(dest_ptr, src_ptr, copy_length); - dest_ptr += copy_length; - dest_size_left -= copy_length; - src_ptr += original_width; - src_size_left -= original_width * sizeof(u16); - } - } else { - std::size_t buffer_size = buffer.size() * sizeof(u16); - if (port.dest_size != buffer_size) { - LOG_ERROR(Service_CAM, "The destination size (%u) doesn't match the source (%zu)!", - port.dest_size, buffer_size); - } - Memory::WriteBlock(port.dest, buffer.data(), std::min<size_t>(port.dest_size, buffer_size)); - } - - port.is_receiving = false; - port.completion_event->Signal(); -} - -// Starts a receiving process on the specified port. This can only be called when is_busy = true and -// is_receiving = false. -void StartReceiving(int port_id) { - PortConfig& port = ports[port_id]; - port.is_receiving = true; - - // launches a capture task asynchronously - const CameraConfig& camera = cameras[port.camera_id]; - port.capture_result = - std::async(std::launch::async, &Camera::CameraInterface::ReceiveFrame, camera.impl.get()); - - // schedules a completion event according to the frame rate. The event will block on the - // capture task if it is not finished within the expected time - CoreTiming::ScheduleEvent( - msToCycles(LATENCY_BY_FRAME_RATE[static_cast<int>(camera.frame_rate)]), - completion_event_callback, port_id); -} - -// Cancels any ongoing receiving processes at the specified port. This is used by functions that -// stop capturing. -// TODO: what is the exact behaviour on real 3DS when stopping capture during an ongoing process? -// Will the completion event still be signaled? -void CancelReceiving(int port_id) { - if (!ports[port_id].is_receiving) - return; - LOG_WARNING(Service_CAM, "tries to cancel an ongoing receiving process."); - CoreTiming::UnscheduleEvent(completion_event_callback, port_id); - ports[port_id].capture_result.wait(); - ports[port_id].is_receiving = false; -} - -// Activates the specified port with the specfied camera. -static void ActivatePort(int port_id, int camera_id) { - if (ports[port_id].is_busy && ports[port_id].camera_id != camera_id) { - CancelReceiving(port_id); - cameras[ports[port_id].camera_id].impl->StopCapture(); - ports[port_id].is_busy = false; - } - ports[port_id].is_active = true; - ports[port_id].camera_id = camera_id; -} - -template <int max_index> -class CommandParamBitSet : public BitSet8 { -public: - explicit CommandParamBitSet(u8 command_param) : BitSet8(command_param) {} - - bool IsValid() const { - return m_val < (1 << max_index); - } - - bool IsSingle() const { - return IsValid() && Count() == 1; - } -}; - -using PortSet = CommandParamBitSet<2>; -using ContextSet = CommandParamBitSet<2>; -using CameraSet = CommandParamBitSet<3>; - -} // namespace - -void StartCapture(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x01, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - if (port_select.IsValid()) { - for (int i : port_select) { - if (!ports[i].is_busy) { - if (!ports[i].is_active) { - // This doesn't return an error, but seems to put the camera in an undefined - // state - LOG_ERROR(Service_CAM, "port %u hasn't been activated", i); - } else { - cameras[ports[i].camera_id].impl->StartCapture(); - ports[i].is_busy = true; - if (ports[i].is_pending_receiving) { - ports[i].is_pending_receiving = false; - StartReceiving(i); - } - } - } else { - LOG_WARNING(Service_CAM, "port %u already started", i); - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); -} - -void StopCapture(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x02, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - if (port_select.IsValid()) { - for (int i : port_select) { - if (ports[i].is_busy) { - CancelReceiving(i); - cameras[ports[i].camera_id].impl->StopCapture(); - ports[i].is_busy = false; - } else { - LOG_WARNING(Service_CAM, "port %u already stopped", i); - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); -} - -void IsBusy(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x03, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - - if (port_select.IsValid()) { - bool is_busy = true; - // Note: the behaviour on no or both ports selected are verified against real 3DS. - for (int i : port_select) { - is_busy &= ports[i].is_busy; - } - rb.Push(RESULT_SUCCESS); - rb.Push(is_busy); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.Skip(1, false); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); -} - -void ClearBuffer(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x04, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u", port_select.m_val); -} - -void GetVsyncInterruptEvent(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x05, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - if (port_select.IsSingle()) { - int port = *port_select.begin(); - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles( - Kernel::g_handle_table.Create(ports[port].vsync_interrupt_event).Unwrap()); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.PushCopyHandles(0); - } - - LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u", port_select.m_val); -} - -void GetBufferErrorInterruptEvent(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x06, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - if (port_select.IsSingle()) { - int port = *port_select.begin(); - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles( - Kernel::g_handle_table.Create(ports[port].buffer_error_interrupt_event).Unwrap()); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.PushCopyHandles(0); - } - - LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u", port_select.m_val); -} - -void SetReceiving(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x07, 4, 2); - const VAddr dest = rp.Pop<u32>(); - const PortSet port_select(rp.Pop<u8>()); - const u32 image_size = rp.Pop<u32>(); - const u16 trans_unit = rp.Pop<u16>(); - rp.PopHandle(); // Handle to destination process. not used - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - if (port_select.IsSingle()) { - int port_id = *port_select.begin(); - PortConfig& port = ports[port_id]; - CancelReceiving(port_id); - port.completion_event->Clear(); - port.dest = dest; - port.dest_size = image_size; - - if (port.is_busy) { - StartReceiving(port_id); - } else { - port.is_pending_receiving = true; - } - - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles(Kernel::g_handle_table.Create(port.completion_event).Unwrap()); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.PushCopyHandles(0); - } - - LOG_DEBUG(Service_CAM, "called, addr=0x%X, port_select=%u, image_size=%u, trans_unit=%u", dest, - port_select.m_val, image_size, trans_unit); -} - -void IsFinishedReceiving(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x08, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - if (port_select.IsSingle()) { - int port = *port_select.begin(); - bool is_busy = ports[port].is_receiving || ports[port].is_pending_receiving; - rb.Push(RESULT_SUCCESS); - rb.Push(!is_busy); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.Skip(1, false); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); -} - -void SetTransferLines(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x09, 4, 0); - const PortSet port_select(rp.Pop<u8>()); - const u16 transfer_lines = rp.Pop<u16>(); - const u16 width = rp.Pop<u16>(); - const u16 height = rp.Pop<u16>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (port_select.IsValid()) { - for (int i : port_select) { - ports[i].transfer_bytes = transfer_lines * width * 2; - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u, lines=%u, width=%u, height=%u", - port_select.m_val, transfer_lines, width, height); -} - -void GetMaxLines(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0A, 2, 0); - const u16 width = rp.Pop<u16>(); - const u16 height = rp.Pop<u16>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - - // Note: the result of the algorithm below are hwtested with width < 640 and with height < 480 - constexpr u32 MIN_TRANSFER_UNIT = 256; - constexpr u32 MAX_BUFFER_SIZE = 2560; - if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { - rb.Push(ERROR_OUT_OF_RANGE); - rb.Skip(1, false); - } else { - u32 lines = MAX_BUFFER_SIZE / width; - if (lines > height) { - lines = height; - } - ResultCode result = RESULT_SUCCESS; - while (height % lines != 0 || (lines * width * 2 % MIN_TRANSFER_UNIT != 0)) { - --lines; - if (lines == 0) { - result = ERROR_OUT_OF_RANGE; - break; - } - } - rb.Push(result); - rb.Push(lines); - } - - LOG_DEBUG(Service_CAM, "called, width=%u, height=%u", width, height); -} - -void SetTransferBytes(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0B, 4, 0); - const PortSet port_select(rp.Pop<u8>()); - const u16 transfer_bytes = rp.Pop<u16>(); - const u16 width = rp.Pop<u16>(); - const u16 height = rp.Pop<u16>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (port_select.IsValid()) { - for (int i : port_select) { - ports[i].transfer_bytes = transfer_bytes; - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_WARNING(Service_CAM, "(STUBBED)called, port_select=%u, bytes=%u, width=%u, height=%u", - port_select.m_val, transfer_bytes, width, height); -} - -void GetTransferBytes(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0C, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - if (port_select.IsSingle()) { - int port = *port_select.begin(); - rb.Push(RESULT_SUCCESS); - rb.Push(ports[port].transfer_bytes); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.Skip(1, false); - } - - LOG_WARNING(Service_CAM, "(STUBBED)called, port_select=%u", port_select.m_val); -} - -void GetMaxBytes(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0D, 2, 0); - const u16 width = rp.Pop<u16>(); - const u16 height = rp.Pop<u16>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - - // Note: the result of the algorithm below are hwtested with width < 640 and with height < 480 - constexpr u32 MIN_TRANSFER_UNIT = 256; - constexpr u32 MAX_BUFFER_SIZE = 2560; - if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { - rb.Push(ERROR_OUT_OF_RANGE); - rb.Skip(1, false); - } else { - u32 bytes = MAX_BUFFER_SIZE; - - while (width * height * 2 % bytes != 0) { - bytes -= MIN_TRANSFER_UNIT; - } - - rb.Push(RESULT_SUCCESS); - rb.Push(bytes); - } - - LOG_DEBUG(Service_CAM, "called, width=%u, height=%u", width, height); -} - -void SetTrimming(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0E, 2, 0); - const PortSet port_select(rp.Pop<u8>()); - const bool trim = rp.Pop<bool>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (port_select.IsValid()) { - for (int i : port_select) { - ports[i].is_trimming = trim; - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u, trim=%d", port_select.m_val, trim); -} - -void IsTrimming(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0F, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - if (port_select.IsSingle()) { - int port = *port_select.begin(); - rb.Push(RESULT_SUCCESS); - rb.Push(ports[port].is_trimming); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.Skip(1, false); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); -} - -void SetTrimmingParams(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x10, 5, 0); - const PortSet port_select(rp.Pop<u8>()); - const u16 x0 = rp.Pop<u16>(); - const u16 y0 = rp.Pop<u16>(); - const u16 x1 = rp.Pop<u16>(); - const u16 y1 = rp.Pop<u16>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (port_select.IsValid()) { - for (int i : port_select) { - ports[i].x0 = x0; - ports[i].y0 = y0; - ports[i].x1 = x1; - ports[i].y1 = y1; - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u, x0=%u, y0=%u, x1=%u, y1=%u", port_select.m_val, - x0, y0, x1, y1); -} - -void GetTrimmingParams(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x11, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(5, 0); - if (port_select.IsSingle()) { - int port = *port_select.begin(); - rb.Push(RESULT_SUCCESS); - rb.Push(ports[port].x0); - rb.Push(ports[port].y0); - rb.Push(ports[port].x1); - rb.Push(ports[port].y1); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.Skip(4, false); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); -} - -void SetTrimmingParamsCenter(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x12, 5, 0); - const PortSet port_select(rp.Pop<u8>()); - const u16 trim_w = rp.Pop<u16>(); - const u16 trim_h = rp.Pop<u16>(); - const u16 cam_w = rp.Pop<u16>(); - const u16 cam_h = rp.Pop<u16>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (port_select.IsValid()) { - for (int i : port_select) { - ports[i].x0 = (cam_w - trim_w) / 2; - ports[i].y0 = (cam_h - trim_h) / 2; - ports[i].x1 = ports[i].x0 + trim_w; - ports[i].y1 = ports[i].y0 + trim_h; - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u, trim_w=%u, trim_h=%u, cam_w=%u, cam_h=%u", - port_select.m_val, trim_w, trim_h, cam_w, cam_h); -} - -void Activate(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x13, 1, 0); - const CameraSet camera_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid()) { - if (camera_select.m_val == 0) { // deactive all - for (int i = 0; i < 2; ++i) { - if (ports[i].is_busy) { - CancelReceiving(i); - cameras[ports[i].camera_id].impl->StopCapture(); - ports[i].is_busy = false; - } - ports[i].is_active = false; - } - rb.Push(RESULT_SUCCESS); - } else if (camera_select[0] && camera_select[1]) { - LOG_ERROR(Service_CAM, "camera 0 and 1 can't be both activated"); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } else { - if (camera_select[0]) { - ActivatePort(0, 0); - } else if (camera_select[1]) { - ActivatePort(0, 1); - } - - if (camera_select[2]) { - ActivatePort(1, 2); - } - rb.Push(RESULT_SUCCESS); - } - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u", camera_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u", camera_select.m_val); -} - -void SwitchContext(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x14, 2, 0); - const CameraSet camera_select(rp.Pop<u8>()); - const ContextSet context_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid() && context_select.IsSingle()) { - int context = *context_select.begin(); - for (int camera : camera_select) { - cameras[camera].current_context = context; - const ContextConfig& context_config = cameras[camera].contexts[context]; - cameras[camera].impl->SetFlip(context_config.flip); - cameras[camera].impl->SetEffect(context_config.effect); - cameras[camera].impl->SetFormat(context_config.format); - cameras[camera].impl->SetResolution(context_config.resolution); - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); -} - -void FlipImage(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1D, 3, 0); - const CameraSet camera_select(rp.Pop<u8>()); - const Flip flip = static_cast<Flip>(rp.Pop<u8>()); - const ContextSet context_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid() && context_select.IsValid()) { - for (int camera : camera_select) { - for (int context : context_select) { - cameras[camera].contexts[context].flip = flip; - if (cameras[camera].current_context == context) { - cameras[camera].impl->SetFlip(flip); - } - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u, flip=%d, context_select=%u", - camera_select.m_val, static_cast<int>(flip), context_select.m_val); -} - -void SetDetailSize(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1E, 8, 0); - const CameraSet camera_select(rp.Pop<u8>()); - Resolution resolution; - resolution.width = rp.Pop<u16>(); - resolution.height = rp.Pop<u16>(); - resolution.crop_x0 = rp.Pop<u16>(); - resolution.crop_y0 = rp.Pop<u16>(); - resolution.crop_x1 = rp.Pop<u16>(); - resolution.crop_y1 = rp.Pop<u16>(); - const ContextSet context_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid() && context_select.IsValid()) { - for (int camera : camera_select) { - for (int context : context_select) { - cameras[camera].contexts[context].resolution = resolution; - if (cameras[camera].current_context == context) { - cameras[camera].impl->SetResolution(resolution); - } - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u, width=%u, height=%u, crop_x0=%u, crop_y0=%u, " - "crop_x1=%u, crop_y1=%u, context_select=%u", - camera_select.m_val, resolution.width, resolution.height, resolution.crop_x0, - resolution.crop_y0, resolution.crop_x1, resolution.crop_y1, context_select.m_val); -} - -void SetSize(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1F, 3, 0); - const CameraSet camera_select(rp.Pop<u8>()); - const u8 size = rp.Pop<u8>(); - const ContextSet context_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid() && context_select.IsValid()) { - for (int camera : camera_select) { - for (int context : context_select) { - cameras[camera].contexts[context].resolution = PRESET_RESOLUTION[size]; - if (cameras[camera].current_context == context) { - cameras[camera].impl->SetResolution(PRESET_RESOLUTION[size]); - } - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u, size=%u, context_select=%u", - camera_select.m_val, size, context_select.m_val); -} - -void SetFrameRate(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x20, 2, 0); - const CameraSet camera_select(rp.Pop<u8>()); - const FrameRate frame_rate = static_cast<FrameRate>(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid()) { - for (int camera : camera_select) { - cameras[camera].frame_rate = frame_rate; - // TODO(wwylele): consider hinting the actual camera with the expected frame rate - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u", camera_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_WARNING(Service_CAM, "(STUBBED) called, camera_select=%u, frame_rate=%d", - camera_select.m_val, static_cast<int>(frame_rate)); -} - -void SetEffect(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x22, 3, 0); - const CameraSet camera_select(rp.Pop<u8>()); - const Effect effect = static_cast<Effect>(rp.Pop<u8>()); - const ContextSet context_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid() && context_select.IsValid()) { - for (int camera : camera_select) { - for (int context : context_select) { - cameras[camera].contexts[context].effect = effect; - if (cameras[camera].current_context == context) { - cameras[camera].impl->SetEffect(effect); - } - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u, effect=%d, context_select=%u", - camera_select.m_val, static_cast<int>(effect), context_select.m_val); -} - -void SetOutputFormat(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x25, 3, 0); - const CameraSet camera_select(rp.Pop<u8>()); - const OutputFormat format = static_cast<OutputFormat>(rp.Pop<u8>()); - const ContextSet context_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid() && context_select.IsValid()) { - for (int camera : camera_select) { - for (int context : context_select) { - cameras[camera].contexts[context].format = format; - if (cameras[camera].current_context == context) { - cameras[camera].impl->SetFormat(format); - } - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u, format=%d, context_select=%u", - camera_select.m_val, static_cast<int>(format), context_select.m_val); -} - -void SynchronizeVsyncTiming(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x29, 2, 0); - const u8 camera_select1 = rp.Pop<u8>(); - const u8 camera_select2 = rp.Pop<u8>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_CAM, "(STUBBED) called, camera_select1=%u, camera_select2=%u", - camera_select1, camera_select2); -} - -void GetStereoCameraCalibrationData(Service::Interface* self) { - IPC::RequestBuilder rb = - IPC::RequestParser(Kernel::GetCommandBuffer(), 0x2B, 0, 0).MakeBuilder(17, 0); - - // Default values taken from yuriks' 3DS. Valid data is required here or games using the - // calibration get stuck in an infinite CPU loop. - StereoCameraCalibrationData data = {}; - data.isValidRotationXY = 0; - data.scale = 1.001776f; - data.rotationZ = 0.008322907f; - data.translationX = -87.70484f; - data.translationY = -7.640977f; - data.rotationX = 0.0f; - data.rotationY = 0.0f; - data.angleOfViewRight = 64.66875f; - data.angleOfViewLeft = 64.76067f; - data.distanceToChart = 250.0f; - data.distanceCameras = 35.0f; - data.imageWidth = 640; - data.imageHeight = 480; - - rb.Push(RESULT_SUCCESS); - rb.PushRaw(data); - - LOG_TRACE(Service_CAM, "called"); -} - -void SetPackageParameterWithoutContext(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x33, 11, 0); - - PackageParameterWithoutContext package; - rp.PopRaw(package); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_CAM, "(STUBBED) called"); -} - -template <typename PackageParameterType> -static ResultCode SetPackageParameter(const PackageParameterType& package) { - const CameraSet camera_select(package.camera_select); - const ContextSet context_select(package.context_select); - - if (camera_select.IsValid() && context_select.IsValid()) { - for (int camera_id : camera_select) { - CameraConfig& camera = cameras[camera_id]; - for (int context_id : context_select) { - ContextConfig& context = camera.contexts[context_id]; - context.effect = package.effect; - context.flip = package.flip; - context.resolution = package.GetResolution(); - if (context_id == camera.current_context) { - camera.impl->SetEffect(context.effect); - camera.impl->SetFlip(context.flip); - camera.impl->SetResolution(context.resolution); - } - } - } - return RESULT_SUCCESS; - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", package.camera_select, - package.context_select); - return ERROR_INVALID_ENUM_VALUE; - } -} - -Resolution PackageParameterWithContext::GetResolution() const { - return PRESET_RESOLUTION[static_cast<int>(size)]; -} - -void SetPackageParameterWithContext(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x34, 5, 0); - - PackageParameterWithContext package; - rp.PopRaw(package); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - ResultCode result = SetPackageParameter(package); - rb.Push(result); - - LOG_DEBUG(Service_CAM, "called"); -} - -void SetPackageParameterWithContextDetail(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x35, 7, 0); - - PackageParameterWithContextDetail package; - rp.PopRaw(package); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - ResultCode result = SetPackageParameter(package); - rb.Push(result); - - LOG_DEBUG(Service_CAM, "called"); -} - -void GetSuitableY2rStandardCoefficient(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x36, 0, 0); - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); - rb.Push<u32>(0); - - LOG_WARNING(Service_CAM, "(STUBBED) called"); -} - -void PlayShutterSound(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x38, 1, 0); - u8 sound_id = rp.Pop<u8>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_CAM, "(STUBBED) called, sound_id=%d", sound_id); -} - -void DriverInitialize(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x39, 0, 0); - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - for (int camera_id = 0; camera_id < NumCameras; ++camera_id) { - CameraConfig& camera = cameras[camera_id]; - camera.current_context = 0; - for (int context_id = 0; context_id < 2; ++context_id) { - // Note: the following default values are verified against real 3DS - ContextConfig& context = camera.contexts[context_id]; - context.flip = camera_id == 1 ? Flip::Horizontal : Flip::None; - context.effect = Effect::None; - context.format = OutputFormat::YUV422; - context.resolution = - context_id == 0 ? PRESET_RESOLUTION[5 /*DS_LCD*/] : PRESET_RESOLUTION[0 /*VGA*/]; - } - camera.impl = Camera::CreateCamera(Settings::values.camera_name[camera_id], - Settings::values.camera_config[camera_id]); - camera.impl->SetFlip(camera.contexts[0].flip); - camera.impl->SetEffect(camera.contexts[0].effect); - camera.impl->SetFormat(camera.contexts[0].format); - camera.impl->SetResolution(camera.contexts[0].resolution); - } - - for (PortConfig& port : ports) { - port.Clear(); - } - - rb.Push(RESULT_SUCCESS); - - LOG_DEBUG(Service_CAM, "called"); -} - -void DriverFinalize(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x3A, 0, 0); - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - CancelReceiving(0); - CancelReceiving(1); - - for (CameraConfig& camera : cameras) { - camera.impl = nullptr; - } - - rb.Push(RESULT_SUCCESS); - - LOG_DEBUG(Service_CAM, "called"); -} - -void Init() { - using namespace Kernel; - - AddService(new CAM_C_Interface); - AddService(new CAM_Q_Interface); - AddService(new CAM_S_Interface); - AddService(new CAM_U_Interface); - - for (PortConfig& port : ports) { - port.completion_event = Event::Create(ResetType::Sticky, "CAM_U::completion_event"); - port.buffer_error_interrupt_event = - Event::Create(ResetType::OneShot, "CAM_U::buffer_error_interrupt_event"); - port.vsync_interrupt_event = - Event::Create(ResetType::OneShot, "CAM_U::vsync_interrupt_event"); - } - completion_event_callback = - CoreTiming::RegisterEvent("CAM_U::CompletionEventCallBack", CompletionEventCallBack); -} - -void Shutdown() { - CancelReceiving(0); - CancelReceiving(1); - for (PortConfig& port : ports) { - port.completion_event = nullptr; - port.buffer_error_interrupt_event = nullptr; - port.vsync_interrupt_event = nullptr; - } - for (CameraConfig& camera : cameras) { - camera.impl = nullptr; - } -} - -} // namespace CAM - -} // namespace Service diff --git a/src/core/hle/service/cam/cam.h b/src/core/hle/service/cam/cam.h deleted file mode 100644 index b6da721d8..000000000 --- a/src/core/hle/service/cam/cam.h +++ /dev/null @@ -1,686 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "common/swap.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace CAM { - -enum CameraIndex { - OuterRightCamera = 0, - InnerCamera = 1, - OuterLeftCamera = 2, - - NumCameras = 3, -}; - -enum class Effect : u8 { - None = 0, - Mono = 1, - Sepia = 2, - Negative = 3, - Negafilm = 4, - Sepia01 = 5, -}; - -enum class Flip : u8 { - None = 0, - Horizontal = 1, - Vertical = 2, - Reverse = 3, -}; - -enum class Size : u8 { - VGA = 0, - QVGA = 1, - QQVGA = 2, - CIF = 3, - QCIF = 4, - DS_LCD = 5, - DS_LCDx4 = 6, - CTR_TOP_LCD = 7, - CTR_BOTTOM_LCD = QVGA, -}; - -enum class FrameRate : u8 { - Rate_15 = 0, - Rate_15_To_5 = 1, - Rate_15_To_2 = 2, - Rate_10 = 3, - Rate_8_5 = 4, - Rate_5 = 5, - Rate_20 = 6, - Rate_20_To_5 = 7, - Rate_30 = 8, - Rate_30_To_5 = 9, - Rate_15_To_10 = 10, - Rate_20_To_10 = 11, - Rate_30_To_10 = 12, -}; - -enum class ShutterSoundType : u8 { - Normal = 0, - Movie = 1, - MovieEnd = 2, -}; - -enum class WhiteBalance : u8 { - BalanceAuto = 0, - Balance3200K = 1, - Balance4150K = 2, - Balance5200K = 3, - Balance6000K = 4, - Balance7000K = 5, - BalanceMax = 6, - BalanceNormal = BalanceAuto, - BalanceTungsten = Balance3200K, - BalanceWhiteFluorescentLight = Balance4150K, - BalanceDaylight = Balance5200K, - BalanceCloudy = Balance6000K, - BalanceHorizon = Balance6000K, - BalanceShade = Balance7000K, -}; - -enum class PhotoMode : u8 { - Normal = 0, - Portrait = 1, - Landscape = 2, - Nightview = 3, - Letter0 = 4, -}; - -enum class LensCorrection : u8 { - Off = 0, - On70 = 1, - On90 = 2, - Dark = Off, - Normal = On70, - Bright = On90, -}; - -enum class Contrast : u8 { - Pattern01 = 1, - Pattern02 = 2, - Pattern03 = 3, - Pattern04 = 4, - Pattern05 = 5, - Pattern06 = 6, - Pattern07 = 7, - Pattern08 = 8, - Pattern09 = 9, - Pattern10 = 10, - Pattern11 = 11, - Low = Pattern05, - Normal = Pattern06, - High = Pattern07, -}; - -enum class OutputFormat : u8 { - YUV422 = 0, - RGB565 = 1, -}; - -/// Stereo camera calibration data. -struct StereoCameraCalibrationData { - u8 isValidRotationXY; ///< Bool indicating whether the X and Y rotation data is valid. - INSERT_PADDING_BYTES(3); - float_le scale; ///< Scale to match the left camera image with the right. - float_le rotationZ; ///< Z axis rotation to match the left camera image with the right. - float_le translationX; ///< X axis translation to match the left camera image with the right. - float_le translationY; ///< Y axis translation to match the left camera image with the right. - float_le rotationX; ///< X axis rotation to match the left camera image with the right. - float_le rotationY; ///< Y axis rotation to match the left camera image with the right. - float_le angleOfViewRight; ///< Right camera angle of view. - float_le angleOfViewLeft; ///< Left camera angle of view. - float_le distanceToChart; ///< Distance between cameras and measurement chart. - float_le distanceCameras; ///< Distance between left and right cameras. - s16_le imageWidth; ///< Image width. - s16_le imageHeight; ///< Image height. - INSERT_PADDING_BYTES(16); -}; -static_assert(sizeof(StereoCameraCalibrationData) == 64, - "StereoCameraCalibrationData structure size is wrong"); - -/** - * Resolution parameters for the camera. - * The native resolution of 3DS camera is 640 * 480. The captured image will be cropped in the - * region [crop_x0, crop_x1] * [crop_y0, crop_y1], and then scaled to size width * height as the - * output image. Note that all cropping coordinates are inclusive. - */ -struct Resolution { - u16 width; - u16 height; - u16 crop_x0; - u16 crop_y0; - u16 crop_x1; - u16 crop_y1; -}; - -struct PackageParameterWithoutContext { - u8 camera_select; - s8 exposure; - WhiteBalance white_balance; - s8 sharpness; - bool auto_exposure; - bool auto_white_balance; - FrameRate frame_rate; - PhotoMode photo_mode; - Contrast contrast; - LensCorrection lens_correction; - bool noise_filter; - u8 padding; - s16 auto_exposure_window_x; - s16 auto_exposure_window_y; - s16 auto_exposure_window_width; - s16 auto_exposure_window_height; - s16 auto_white_balance_window_x; - s16 auto_white_balance_window_y; - s16 auto_white_balance_window_width; - s16 auto_white_balance_window_height; - INSERT_PADDING_WORDS(4); -}; - -static_assert(sizeof(PackageParameterWithoutContext) == 44, - "PackageParameterCameraWithoutContext structure size is wrong"); - -struct PackageParameterWithContext { - u8 camera_select; - u8 context_select; - Flip flip; - Effect effect; - Size size; - INSERT_PADDING_BYTES(3); - INSERT_PADDING_WORDS(3); - - Resolution GetResolution() const; -}; - -static_assert(sizeof(PackageParameterWithContext) == 20, - "PackageParameterWithContext structure size is wrong"); - -struct PackageParameterWithContextDetail { - u8 camera_select; - u8 context_select; - Flip flip; - Effect effect; - Resolution resolution; - INSERT_PADDING_WORDS(3); - - Resolution GetResolution() const { - return resolution; - } -}; - -static_assert(sizeof(PackageParameterWithContextDetail) == 28, - "PackageParameterWithContextDetail structure size is wrong"); - -/** - * Starts capturing at the selected port. - * Inputs: - * 0: 0x00010040 - * 1: u8 selected port - * Outputs: - * 0: 0x00010040 - * 1: ResultCode - */ -void StartCapture(Service::Interface* self); - -/** - * Stops capturing from the selected port. - * Inputs: - * 0: 0x00020040 - * 1: u8 selected port - * Outputs: - * 0: 0x00020040 - * 1: ResultCode - */ -void StopCapture(Service::Interface* self); - -/** - * Gets whether the selected port is currently capturing. - * Inputs: - * 0: 0x00030040 - * 1: u8 selected port - * Outputs: - * 0: 0x00030080 - * 1: ResultCode - * 2: 0 if not capturing, 1 if capturing - */ -void IsBusy(Service::Interface* self); - -/** - * Clears the buffer of selected ports. - * Inputs: - * 0: 0x00040040 - * 1: u8 selected port - * Outputs: - * 0: 0x00040040 - * 2: ResultCode - */ -void ClearBuffer(Service::Interface* self); - -/** - * Unknown - * Inputs: - * 0: 0x00050040 - * 1: u8 selected port - * Outputs: - * 0: 0x00050042 - * 1: ResultCode - * 2: Descriptor: Handle - * 3: Event handle - */ -void GetVsyncInterruptEvent(Service::Interface* self); - -/** - * Unknown - * Inputs: - * 0: 0x00060040 - * 1: u8 selected port - * Outputs: - * 0: 0x00060042 - * 1: ResultCode - * 2: Descriptor: Handle - * 3: Event handle - */ -void GetBufferErrorInterruptEvent(Service::Interface* self); - -/** - * Sets the target buffer to receive a frame of image data and starts the transfer. Each camera - * port has its own event to signal the end of the transfer. - * - * Inputs: - * 0: 0x00070102 - * 1: Destination address in calling process - * 2: u8 selected port - * 3: Image size (in bytes) - * 4: u16 Transfer unit size (in bytes) - * 5: Descriptor: Handle - * 6: Handle to destination process - * Outputs: - * 0: 0x00070042 - * 1: ResultCode - * 2: Descriptor: Handle - * 3: Handle to event signalled when transfer finishes - */ -void SetReceiving(Service::Interface* self); - -/** - * Gets whether the selected port finished receiving a frame. - * Inputs: - * 0: 0x00080040 - * 1: u8 selected port - * Outputs: - * 0: 0x00080080 - * 1: ResultCode - * 2: 0 if not finished, 1 if finished - */ -void IsFinishedReceiving(Service::Interface* self); - -/** - * Sets the number of lines the buffer contains. - * Inputs: - * 0: 0x00090100 - * 1: u8 selected port - * 2: u16 Number of lines to transfer - * 3: u16 Width - * 4: u16 Height - * Outputs: - * 0: 0x00090040 - * 1: ResultCode - * @todo figure out how the "buffer" actually works. - */ -void SetTransferLines(Service::Interface* self); - -/** - * Gets the maximum number of lines that fit in the buffer - * Inputs: - * 0: 0x000A0080 - * 1: u16 Width - * 2: u16 Height - * Outputs: - * 0: 0x000A0080 - * 1: ResultCode - * 2: Maximum number of lines that fit in the buffer - * @todo figure out how the "buffer" actually works. - */ -void GetMaxLines(Service::Interface* self); - -/** - * Sets the number of bytes the buffer contains. - * Inputs: - * 0: 0x000B0100 - * 1: u8 selected port - * 2: u16 Number of bytes to transfer - * 3: u16 Width - * 4: u16 Height - * Outputs: - * 0: 0x000B0040 - * 1: ResultCode - * @todo figure out how the "buffer" actually works. - */ -void SetTransferBytes(Service::Interface* self); - -/** - * Gets the number of bytes to the buffer contains. - * Inputs: - * 0: 0x000C0040 - * 1: u8 selected port - * Outputs: - * 0: 0x000C0080 - * 1: ResultCode - * 2: The number of bytes the buffer contains - * @todo figure out how the "buffer" actually works. - */ -void GetTransferBytes(Service::Interface* self); - -/** - * Gets the maximum number of bytes that fit in the buffer. - * Inputs: - * 0: 0x000D0080 - * 1: u16 Width - * 2: u16 Height - * Outputs: - * 0: 0x000D0080 - * 1: ResultCode - * 2: Maximum number of bytes that fit in the buffer - * @todo figure out how the "buffer" actually works. - */ -void GetMaxBytes(Service::Interface* self); - -/** - * Enables or disables trimming. - * Inputs: - * 0: 0x000E0080 - * 1: u8 selected port - * 2: u8 bool Enable trimming if true - * Outputs: - * 0: 0x000E0040 - * 1: ResultCode - */ -void SetTrimming(Service::Interface* self); - -/** - * Gets whether trimming is enabled. - * Inputs: - * 0: 0x000F0040 - * 1: u8 selected port - * Outputs: - * 0: 0x000F0080 - * 1: ResultCode - * 2: u8 bool Enable trimming if true - */ -void IsTrimming(Service::Interface* self); - -/** - * Sets the position to trim. - * Inputs: - * 0: 0x00100140 - * 1: u8 selected port - * 2: x start - * 3: y start - * 4: x end (exclusive) - * 5: y end (exclusive) - * Outputs: - * 0: 0x00100040 - * 1: ResultCode - */ -void SetTrimmingParams(Service::Interface* self); - -/** - * Gets the position to trim. - * Inputs: - * 0: 0x00110040 - * 1: u8 selected port - * - * Outputs: - * 0: 0x00110140 - * 1: ResultCode - * 2: x start - * 3: y start - * 4: x end (exclusive) - * 5: y end (exclusive) - */ -void GetTrimmingParams(Service::Interface* self); - -/** - * Sets the position to trim by giving the width and height. The trimming window is always at the - * center. - * Inputs: - * 0: 0x00120140 - * 1: u8 selected port - * 2: s16 Trim width - * 3: s16 Trim height - * 4: s16 Camera width - * 5: s16 Camera height - * Outputs: - * 0: 0x00120040 - * 1: ResultCode - */ -void SetTrimmingParamsCenter(Service::Interface* self); - -/** - * Selects up to two physical cameras to enable. - * Inputs: - * 0: 0x00130040 - * 1: u8 selected camera - * Outputs: - * 0: 0x00130040 - * 1: ResultCode - */ -void Activate(Service::Interface* self); - -/** - * Switches the context of camera settings. - * Inputs: - * 0: 0x00140080 - * 1: u8 selected camera - * 2: u8 selected context - * Outputs: - * 0: 0x00140040 - * 1: ResultCode - */ -void SwitchContext(Service::Interface* self); - -/** - * Sets flipping of images - * Inputs: - * 0: 0x001D00C0 - * 1: u8 selected camera - * 2: u8 Type of flipping to perform (`Flip` enum) - * 3: u8 selected context - * Outputs: - * 0: 0x001D0040 - * 1: ResultCode - */ -void FlipImage(Service::Interface* self); - -/** - * Sets camera resolution from custom parameters. For more details see the Resolution struct. - * Inputs: - * 0: 0x001E0200 - * 1: u8 selected camera - * 2: width - * 3: height - * 4: crop x0 - * 5: crop y0 - * 6: crop x1 - * 7: crop y1 - * 8: u8 selected context - * Outputs: - * 0: 0x001E0040 - * 1: ResultCode - */ -void SetDetailSize(Service::Interface* self); - -/** - * Sets camera resolution from preset resolution parameters. - * Inputs: - * 0: 0x001F00C0 - * 1: u8 selected camera - * 2: u8 Camera frame resolution (`Size` enum) - * 3: u8 selected context - * Outputs: - * 0: 0x001F0040 - * 1: ResultCode - */ -void SetSize(Service::Interface* self); - -/** - * Sets camera framerate. - * Inputs: - * 0: 0x00200080 - * 1: u8 selected camera - * 2: u8 Camera framerate (`FrameRate` enum) - * Outputs: - * 0: 0x00200040 - * 1: ResultCode - */ -void SetFrameRate(Service::Interface* self); - -/** - * Sets effect on the output image - * Inputs: - * 0: 0x002200C0 - * 1: u8 selected camera - * 2: u8 image effect (`Effect` enum) - * 3: u8 selected context - * Outputs: - * 0: 0x00220040 - * 1: ResultCode - */ -void SetEffect(Service::Interface* self); - -/** - * Sets format of the output image - * Inputs: - * 0: 0x002500C0 - * 1: u8 selected camera - * 2: u8 image format (`OutputFormat` enum) - * 3: u8 selected context - * Outputs: - * 0: 0x00250040 - * 1: ResultCode - */ -void SetOutputFormat(Service::Interface* self); - -/** - * Synchronizes the V-Sync timing of two cameras. - * Inputs: - * 0: 0x00290080 - * 1: u8 selected camera 1 - * 2: u8 selected camera 2 - * Outputs: - * 0: 0x00280040 - * 1: ResultCode - */ -void SynchronizeVsyncTiming(Service::Interface* self); - -/** - * Returns calibration data relating the outside cameras to eachother, for use in AR applications. - * - * Inputs: - * 0: 0x002B0000 - * Outputs: - * 0: 0x002B0440 - * 1: ResultCode - * 2-17: `StereoCameraCalibrationData` structure with calibration values - */ -void GetStereoCameraCalibrationData(Service::Interface* self); - -/** - * Batch-configures context-free settings. - * - * Inputs: - * 0: 0x003302C0 - * 1-7: struct PachageParameterWithoutContext - * 8-11: unused - * Outputs: - * 0: 0x00330040 - * 1: ResultCode - */ -void SetPackageParameterWithoutContext(Service::Interface* self); - -/** - * Batch-configures context-related settings with preset resolution parameters. - * - * Inputs: - * 0: 0x00340140 - * 1-2: struct PackageParameterWithContext - * 3-5: unused - * Outputs: - * 0: 0x00340040 - * 1: ResultCode - */ -void SetPackageParameterWithContext(Service::Interface* self); - -/** - * Batch-configures context-related settings with custom resolution parameters - * - * Inputs: - * 0: 0x003501C0 - * 1-4: struct PackageParameterWithContextDetail - * 5-7: unused - * Outputs: - * 0: 0x00350040 - * 1: ResultCode - */ -void SetPackageParameterWithContextDetail(Service::Interface* self); - -/** - * Unknown - * Inputs: - * 0: 0x00360000 - * Outputs: - * 0: 0x00360080 - * 1: ResultCode - * 2: ? - */ -void GetSuitableY2rStandardCoefficient(Service::Interface* self); - -/** - * Unknown - * Inputs: - * 0: 0x00380040 - * 1: u8 Sound ID - * Outputs: - * 0: 0x00380040 - * 1: ResultCode - */ -void PlayShutterSound(Service::Interface* self); - -/** - * Initializes the camera driver. Must be called before using other functions. - * Inputs: - * 0: 0x00390000 - * Outputs: - * 0: 0x00390040 - * 1: ResultCode - */ -void DriverInitialize(Service::Interface* self); - -/** - * Shuts down the camera driver. - * Inputs: - * 0: 0x003A0000 - * Outputs: - * 0: 0x003A0040 - * 1: ResultCode - */ -void DriverFinalize(Service::Interface* self); - -/// Initialize CAM service(s) -void Init(); - -/// Shutdown CAM service(s) -void Shutdown(); - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_c.cpp b/src/core/hle/service/cam/cam_c.cpp deleted file mode 100644 index 93b047c1a..000000000 --- a/src/core/hle/service/cam/cam_c.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/cam/cam_c.h" - -namespace Service { -namespace CAM { - -// Empty arrays are illegal -- commented out until an entry is added. -// const Interface::FunctionInfo FunctionTable[] = { }; - -CAM_C_Interface::CAM_C_Interface() { - // Register(FunctionTable); -} - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_c.h b/src/core/hle/service/cam/cam_c.h deleted file mode 100644 index 6b296c00d..000000000 --- a/src/core/hle/service/cam/cam_c.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace CAM { - -class CAM_C_Interface : public Service::Interface { -public: - CAM_C_Interface(); - - std::string GetPortName() const override { - return "cam:c"; - } -}; - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_q.cpp b/src/core/hle/service/cam/cam_q.cpp deleted file mode 100644 index 2ba853606..000000000 --- a/src/core/hle/service/cam/cam_q.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/cam/cam_q.h" - -namespace Service { -namespace CAM { - -// Empty arrays are illegal -- commented out until an entry is added. -// const Interface::FunctionInfo FunctionTable[] = { }; - -CAM_Q_Interface::CAM_Q_Interface() { - // Register(FunctionTable); -} - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_q.h b/src/core/hle/service/cam/cam_q.h deleted file mode 100644 index 07cc12534..000000000 --- a/src/core/hle/service/cam/cam_q.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace CAM { - -class CAM_Q_Interface : public Service::Interface { -public: - CAM_Q_Interface(); - - std::string GetPortName() const override { - return "cam:q"; - } -}; - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_s.cpp b/src/core/hle/service/cam/cam_s.cpp deleted file mode 100644 index f1c6da587..000000000 --- a/src/core/hle/service/cam/cam_s.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/cam/cam_s.h" - -namespace Service { -namespace CAM { - -// Empty arrays are illegal -- commented out until an entry is added. -// const Interface::FunctionInfo FunctionTable[] = { }; - -CAM_S_Interface::CAM_S_Interface() { - // Register(FunctionTable); -} - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_s.h b/src/core/hle/service/cam/cam_s.h deleted file mode 100644 index 0a5d6fca2..000000000 --- a/src/core/hle/service/cam/cam_s.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace CAM { - -class CAM_S_Interface : public Service::Interface { -public: - CAM_S_Interface(); - - std::string GetPortName() const override { - return "cam:s"; - } -}; - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_u.cpp b/src/core/hle/service/cam/cam_u.cpp deleted file mode 100644 index 251c1e6d4..000000000 --- a/src/core/hle/service/cam/cam_u.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/cam/cam.h" -#include "core/hle/service/cam/cam_u.h" - -namespace Service { -namespace CAM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, StartCapture, "StartCapture"}, - {0x00020040, StopCapture, "StopCapture"}, - {0x00030040, IsBusy, "IsBusy"}, - {0x00040040, ClearBuffer, "ClearBuffer"}, - {0x00050040, GetVsyncInterruptEvent, "GetVsyncInterruptEvent"}, - {0x00060040, GetBufferErrorInterruptEvent, "GetBufferErrorInterruptEvent"}, - {0x00070102, SetReceiving, "SetReceiving"}, - {0x00080040, IsFinishedReceiving, "IsFinishedReceiving"}, - {0x00090100, SetTransferLines, "SetTransferLines"}, - {0x000A0080, GetMaxLines, "GetMaxLines"}, - {0x000B0100, SetTransferBytes, "SetTransferBytes"}, - {0x000C0040, GetTransferBytes, "GetTransferBytes"}, - {0x000D0080, GetMaxBytes, "GetMaxBytes"}, - {0x000E0080, SetTrimming, "SetTrimming"}, - {0x000F0040, IsTrimming, "IsTrimming"}, - {0x00100140, SetTrimmingParams, "SetTrimmingParams"}, - {0x00110040, GetTrimmingParams, "GetTrimmingParams"}, - {0x00120140, SetTrimmingParamsCenter, "SetTrimmingParamsCenter"}, - {0x00130040, Activate, "Activate"}, - {0x00140080, SwitchContext, "SwitchContext"}, - {0x00150080, nullptr, "SetExposure"}, - {0x00160080, nullptr, "SetWhiteBalance"}, - {0x00170080, nullptr, "SetWhiteBalanceWithoutBaseUp"}, - {0x00180080, nullptr, "SetSharpness"}, - {0x00190080, nullptr, "SetAutoExposure"}, - {0x001A0040, nullptr, "IsAutoExposure"}, - {0x001B0080, nullptr, "SetAutoWhiteBalance"}, - {0x001C0040, nullptr, "IsAutoWhiteBalance"}, - {0x001D00C0, FlipImage, "FlipImage"}, - {0x001E0200, SetDetailSize, "SetDetailSize"}, - {0x001F00C0, SetSize, "SetSize"}, - {0x00200080, SetFrameRate, "SetFrameRate"}, - {0x00210080, nullptr, "SetPhotoMode"}, - {0x002200C0, SetEffect, "SetEffect"}, - {0x00230080, nullptr, "SetContrast"}, - {0x00240080, nullptr, "SetLensCorrection"}, - {0x002500C0, SetOutputFormat, "SetOutputFormat"}, - {0x00260140, nullptr, "SetAutoExposureWindow"}, - {0x00270140, nullptr, "SetAutoWhiteBalanceWindow"}, - {0x00280080, nullptr, "SetNoiseFilter"}, - {0x00290080, SynchronizeVsyncTiming, "SynchronizeVsyncTiming"}, - {0x002A0080, nullptr, "GetLatestVsyncTiming"}, - {0x002B0000, GetStereoCameraCalibrationData, "GetStereoCameraCalibrationData"}, - {0x002C0400, nullptr, "SetStereoCameraCalibrationData"}, - {0x002D00C0, nullptr, "WriteRegisterI2c"}, - {0x002E00C0, nullptr, "WriteMcuVariableI2c"}, - {0x002F0080, nullptr, "ReadRegisterI2cExclusive"}, - {0x00300080, nullptr, "ReadMcuVariableI2cExclusive"}, - {0x00310180, nullptr, "SetImageQualityCalibrationData"}, - {0x00320000, nullptr, "GetImageQualityCalibrationData"}, - {0x003302C0, SetPackageParameterWithoutContext, "SetPackageParameterWithoutContext"}, - {0x00340140, SetPackageParameterWithContext, "SetPackageParameterWithContext"}, - {0x003501C0, SetPackageParameterWithContextDetail, "SetPackageParameterWithContextDetail"}, - {0x00360000, GetSuitableY2rStandardCoefficient, "GetSuitableY2rStandardCoefficient"}, - {0x00370202, nullptr, "PlayShutterSoundWithWave"}, - {0x00380040, PlayShutterSound, "PlayShutterSound"}, - {0x00390000, DriverInitialize, "DriverInitialize"}, - {0x003A0000, DriverFinalize, "DriverFinalize"}, - {0x003B0000, nullptr, "GetActivatedCamera"}, - {0x003C0000, nullptr, "GetSleepCamera"}, - {0x003D0040, nullptr, "SetSleepCamera"}, - {0x003E0040, nullptr, "SetBrightnessSynchronization"}, -}; - -CAM_U_Interface::CAM_U_Interface() { - Register(FunctionTable); -} - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_u.h b/src/core/hle/service/cam/cam_u.h deleted file mode 100644 index 369264037..000000000 --- a/src/core/hle/service/cam/cam_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace CAM { - -class CAM_U_Interface : public Service::Interface { -public: - CAM_U_Interface(); - - std::string GetPortName() const override { - return "cam:u"; - } -}; - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp deleted file mode 100644 index 421006a9e..000000000 --- a/src/core/hle/service/cecd/cecd.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/logging/log.h" -#include "core/hle/ipc.h" -#include "core/hle/kernel/event.h" -#include "core/hle/kernel/handle_table.h" -#include "core/hle/result.h" -#include "core/hle/service/cecd/cecd.h" -#include "core/hle/service/cecd/cecd_ndm.h" -#include "core/hle/service/cecd/cecd_s.h" -#include "core/hle/service/cecd/cecd_u.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace CECD { - -static Kernel::SharedPtr<Kernel::Event> cecinfo_event; -static Kernel::SharedPtr<Kernel::Event> change_state_event; - -void GetCecStateAbbreviated(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = static_cast<u32>(CecStateAbbreviated::CEC_STATE_ABBREV_IDLE); - - LOG_WARNING(Service_CECD, "(STUBBED) called"); -} - -void GetCecInfoEventHandle(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).Unwrap(); // Event handle - - LOG_WARNING(Service_CECD, "(STUBBED) called"); -} - -void GetChangeStateEventHandle(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).Unwrap(); // Event handle - - LOG_WARNING(Service_CECD, "(STUBBED) called"); -} - -void Init() { - AddService(new CECD_NDM); - AddService(new CECD_S); - AddService(new CECD_U); - - cecinfo_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD::cecinfo_event"); - change_state_event = - Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD::change_state_event"); -} - -void Shutdown() { - cecinfo_event = nullptr; - change_state_event = nullptr; -} - -} // namespace CECD - -} // namespace Service diff --git a/src/core/hle/service/cecd/cecd.h b/src/core/hle/service/cecd/cecd.h deleted file mode 100644 index ea97f9266..000000000 --- a/src/core/hle/service/cecd/cecd.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service { - -class Interface; - -namespace CECD { - -enum class CecStateAbbreviated { - CEC_STATE_ABBREV_IDLE = 1, ///< Corresponds to CEC_STATE_IDLE - CEC_STATE_ABBREV_NOT_LOCAL = 2, ///< Corresponds to CEC_STATEs *FINISH*, *POST, and OVER_BOSS - CEC_STATE_ABBREV_SCANNING = 3, ///< Corresponds to CEC_STATE_SCANNING - CEC_STATE_ABBREV_WLREADY = - 4, ///< Corresponds to CEC_STATE_WIRELESS_READY when some unknown bool is true - CEC_STATE_ABBREV_OTHER = 5, ///< Corresponds to CEC_STATEs besides *FINISH*, *POST, and - /// OVER_BOSS and those listed here -}; - -/** - * GetCecStateAbbreviated service function - * Inputs: - * 0: 0x000E0000 - * Outputs: - * 1: ResultCode - * 2: CecStateAbbreviated - */ -void GetCecStateAbbreviated(Service::Interface* self); - -/** - * GetCecInfoEventHandle service function - * Inputs: - * 0: 0x000F0000 - * Outputs: - * 1: ResultCode - * 3: Event Handle - */ -void GetCecInfoEventHandle(Service::Interface* self); - -/** - * GetChangeStateEventHandle service function - * Inputs: - * 0: 0x00100000 - * Outputs: - * 1: ResultCode - * 3: Event Handle - */ -void GetChangeStateEventHandle(Service::Interface* self); - -/// Initialize CECD service(s) -void Init(); - -/// Shutdown CECD service(s) -void Shutdown(); - -} // namespace CECD -} // namespace Service diff --git a/src/core/hle/service/cecd/cecd_ndm.cpp b/src/core/hle/service/cecd/cecd_ndm.cpp deleted file mode 100644 index 7baf93750..000000000 --- a/src/core/hle/service/cecd/cecd_ndm.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/cecd/cecd.h" -#include "core/hle/service/cecd/cecd_ndm.h" - -namespace Service { -namespace CECD { - -static const Interface::FunctionInfo FunctionTable[] = { - {0x00010000, nullptr, "Initialize"}, - {0x00020000, nullptr, "Deinitialize"}, - {0x00030000, nullptr, "ResumeDaemon"}, - {0x00040040, nullptr, "SuspendDaemon"}, -}; - -CECD_NDM::CECD_NDM() { - Register(FunctionTable); -} - -} // namespace CECD -} // namespace Service diff --git a/src/core/hle/service/cecd/cecd_ndm.h b/src/core/hle/service/cecd/cecd_ndm.h deleted file mode 100644 index 2e2e50ada..000000000 --- a/src/core/hle/service/cecd/cecd_ndm.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace CECD { - -class CECD_NDM : public Interface { -public: - CECD_NDM(); - - std::string GetPortName() const override { - return "cecd:ndm"; - } -}; - -} // namespace CECD -} // namespace Service diff --git a/src/core/hle/service/cecd/cecd_s.cpp b/src/core/hle/service/cecd/cecd_s.cpp deleted file mode 100644 index eacda7d41..000000000 --- a/src/core/hle/service/cecd/cecd_s.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/cecd/cecd.h" -#include "core/hle/service/cecd/cecd_s.h" - -namespace Service { -namespace CECD { - -static const Interface::FunctionInfo FunctionTable[] = { - // cecd:u shared commands - {0x000100C2, nullptr, "OpenRawFile"}, - {0x00020042, nullptr, "ReadRawFile"}, - {0x00030104, nullptr, "ReadMessage"}, - {0x00040106, nullptr, "ReadMessageWithHMAC"}, - {0x00050042, nullptr, "WriteRawFile"}, - {0x00060104, nullptr, "WriteMessage"}, - {0x00070106, nullptr, "WriteMessageWithHMAC"}, - {0x00080102, nullptr, "Delete"}, - {0x000A00C4, nullptr, "GetSystemInfo"}, - {0x000B0040, nullptr, "RunCommand"}, - {0x000C0040, nullptr, "RunCommandAlt"}, - {0x000E0000, GetCecStateAbbreviated, "GetCecStateAbbreviated"}, - {0x000F0000, GetCecInfoEventHandle, "GetCecInfoEventHandle"}, - {0x00100000, GetChangeStateEventHandle, "GetChangeStateEventHandle"}, - {0x00110104, nullptr, "OpenAndWrite"}, - {0x00120104, nullptr, "OpenAndRead"}, -}; - -CECD_S::CECD_S() { - Register(FunctionTable); -} - -} // namespace CECD -} // namespace Service diff --git a/src/core/hle/service/cecd/cecd_s.h b/src/core/hle/service/cecd/cecd_s.h deleted file mode 100644 index ab6c6789a..000000000 --- a/src/core/hle/service/cecd/cecd_s.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace CECD { - -class CECD_S : public Interface { -public: - CECD_S(); - - std::string GetPortName() const override { - return "cecd:s"; - } -}; - -} // namespace CECD -} // namespace Service diff --git a/src/core/hle/service/cecd/cecd_u.cpp b/src/core/hle/service/cecd/cecd_u.cpp deleted file mode 100644 index 3ed864f0b..000000000 --- a/src/core/hle/service/cecd/cecd_u.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/cecd/cecd.h" -#include "core/hle/service/cecd/cecd_u.h" - -namespace Service { -namespace CECD { - -static const Interface::FunctionInfo FunctionTable[] = { - // cecd:u shared commands - {0x000100C2, nullptr, "OpenRawFile"}, - {0x00020042, nullptr, "ReadRawFile"}, - {0x00030104, nullptr, "ReadMessage"}, - {0x00040106, nullptr, "ReadMessageWithHMAC"}, - {0x00050042, nullptr, "WriteRawFile"}, - {0x00060104, nullptr, "WriteMessage"}, - {0x00070106, nullptr, "WriteMessageWithHMAC"}, - {0x00080102, nullptr, "Delete"}, - {0x000A00C4, nullptr, "GetSystemInfo"}, - {0x000B0040, nullptr, "RunCommand"}, - {0x000C0040, nullptr, "RunCommandAlt"}, - {0x000E0000, GetCecStateAbbreviated, "GetCecStateAbbreviated"}, - {0x000F0000, GetCecInfoEventHandle, "GetCecInfoEventHandle"}, - {0x00100000, GetChangeStateEventHandle, "GetChangeStateEventHandle"}, - {0x00110104, nullptr, "OpenAndWrite"}, - {0x00120104, nullptr, "OpenAndRead"}, -}; - -CECD_U::CECD_U() { - Register(FunctionTable); -} - -} // namespace CECD -} // namespace Service diff --git a/src/core/hle/service/cecd/cecd_u.h b/src/core/hle/service/cecd/cecd_u.h deleted file mode 100644 index 16e874ff5..000000000 --- a/src/core/hle/service/cecd/cecd_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace CECD { - -class CECD_U : public Interface { -public: - CECD_U(); - - std::string GetPortName() const override { - return "cecd:u"; - } -}; - -} // namespace CECD -} // namespace Service diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp deleted file mode 100644 index aac903ccb..000000000 --- a/src/core/hle/service/csnd_snd.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <cstring> -#include "common/alignment.h" -#include "core/hle/ipc.h" -#include "core/hle/kernel/handle_table.h" -#include "core/hle/kernel/mutex.h" -#include "core/hle/kernel/shared_memory.h" -#include "core/hle/service/csnd_snd.h" -#include "core/memory.h" - -namespace Service { -namespace CSND { - -struct Type0Command { - // command id and next command offset - u32 command_id; - u32 finished; - u32 flags; - u8 parameters[20]; -}; -static_assert(sizeof(Type0Command) == 0x20, "Type0Command structure size is wrong"); - -static Kernel::SharedPtr<Kernel::SharedMemory> shared_memory = nullptr; -static Kernel::SharedPtr<Kernel::Mutex> mutex = nullptr; - -/** - * CSND_SND::Initialize service function - * Inputs: - * 0 : Header Code[0x00010140] - * 1 : Shared memory block size, for mem-block creation - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Handle-list header - * 3 : Mutex handle - * 4 : Shared memory block handle - */ -static void Initialize(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 size = Common::AlignUp(cmd_buff[1], Memory::PAGE_SIZE); - - using Kernel::MemoryPermission; - shared_memory = Kernel::SharedMemory::Create(nullptr, size, MemoryPermission::ReadWrite, - MemoryPermission::ReadWrite, 0, - Kernel::MemoryRegion::BASE, "CSND:SharedMemory"); - - mutex = Kernel::Mutex::Create(false, 0, "CSND:mutex"); - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = IPC::CopyHandleDesc(2); - cmd_buff[3] = Kernel::g_handle_table.Create(mutex).Unwrap(); - cmd_buff[4] = Kernel::g_handle_table.Create(shared_memory).Unwrap(); - - LOG_WARNING(Service_CSND, "(STUBBED) called"); -} - -/** - * CSND_SND::Shutdown service function - * Inputs: - * 0 : Header Code[0x00020000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void Shutdown(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - shared_memory = nullptr; - mutex = nullptr; - - cmd_buff[1] = RESULT_SUCCESS.raw; - LOG_WARNING(Service_CSND, "(STUBBED) called"); -} - -/** - * CSND_SND::ExecuteCommands service function - * Inputs: - * 0 : Header Code[0x00030040] - * 1 : Command offset in shared memory. - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Available channel bit mask - */ -static void ExecuteCommands(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - if (shared_memory == nullptr) { - cmd_buff[1] = 1; - LOG_ERROR(Service_CSND, "called, shared memory not allocated"); - return; - } - - VAddr addr = cmd_buff[1]; - u8* ptr = shared_memory->GetPointer(addr); - - Type0Command command; - std::memcpy(&command, ptr, sizeof(Type0Command)); - command.finished |= 1; - std::memcpy(ptr, &command, sizeof(Type0Command)); - - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_CSND, "(STUBBED) called, addr=0x%08X", addr); -} - -/** - * CSND_SND::AcquireSoundChannels service function - * Inputs: - * 0 : Header Code[0x00050000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Available channel bit mask - */ -static void AcquireSoundChannels(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0xFFFFFF00; - LOG_WARNING(Service_CSND, "(STUBBED) called"); -} - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010140, Initialize, "Initialize"}, - {0x00020000, Shutdown, "Shutdown"}, - {0x00030040, ExecuteCommands, "ExecuteCommands"}, - {0x00040080, nullptr, "ExecuteType1Commands"}, - {0x00050000, AcquireSoundChannels, "AcquireSoundChannels"}, - {0x00060000, nullptr, "ReleaseSoundChannels"}, - {0x00070000, nullptr, "AcquireCaptureDevice"}, - {0x00080040, nullptr, "ReleaseCaptureDevice"}, - {0x00090082, nullptr, "FlushDataCache"}, - {0x000A0082, nullptr, "StoreDataCache"}, - {0x000B0082, nullptr, "InvalidateDataCache"}, - {0x000C0000, nullptr, "Reset"}, -}; - -CSND_SND::CSND_SND() { - Register(FunctionTable); -} - -} // namespace CSND -} // namespace Service diff --git a/src/core/hle/service/csnd_snd.h b/src/core/hle/service/csnd_snd.h deleted file mode 100644 index ca6d4513e..000000000 --- a/src/core/hle/service/csnd_snd.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace CSND { - -class CSND_SND final : public Interface { -public: - CSND_SND(); - - std::string GetPortName() const override { - return "csnd:SND"; - } -}; - -} // namespace CSND -} // namespace Service diff --git a/src/core/hle/service/dlp/dlp.cpp b/src/core/hle/service/dlp/dlp.cpp deleted file mode 100644 index 8f4b67a5d..000000000 --- a/src/core/hle/service/dlp/dlp.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/dlp/dlp.h" -#include "core/hle/service/dlp/dlp_clnt.h" -#include "core/hle/service/dlp/dlp_fkcl.h" -#include "core/hle/service/dlp/dlp_srvr.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace DLP { - -void Init() { - AddService(new DLP_CLNT_Interface); - AddService(new DLP_FKCL_Interface); - AddService(new DLP_SRVR_Interface); -} - -void Shutdown() {} - -} // namespace DLP -} // namespace Service diff --git a/src/core/hle/service/dlp/dlp.h b/src/core/hle/service/dlp/dlp.h deleted file mode 100644 index 3185fe322..000000000 --- a/src/core/hle/service/dlp/dlp.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service { -namespace DLP { - -/// Initializes the DLP services. -void Init(); - -/// Shuts down the DLP services. -void Shutdown(); - -} // namespace DLP -} // namespace Service diff --git a/src/core/hle/service/dlp/dlp_clnt.cpp b/src/core/hle/service/dlp/dlp_clnt.cpp deleted file mode 100644 index 6f2bf2061..000000000 --- a/src/core/hle/service/dlp/dlp_clnt.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/dlp/dlp_clnt.h" - -namespace Service { -namespace DLP { - -const Interface::FunctionInfo FunctionTable[] = { - {0x000100C3, nullptr, "Initialize"}, - {0x00020000, nullptr, "Finalize"}, - {0x00030000, nullptr, "GetEventDesc"}, - {0x00040000, nullptr, "GetChannel"}, - {0x00050180, nullptr, "StartScan"}, - {0x00060000, nullptr, "StopScan"}, - {0x00070080, nullptr, "GetServerInfo"}, - {0x00080100, nullptr, "GetTitleInfo"}, - {0x00090040, nullptr, "GetTitleInfoInOrder"}, - {0x000A0080, nullptr, "DeleteScanInfo"}, - {0x000B0100, nullptr, "PrepareForSystemDownload"}, - {0x000C0000, nullptr, "StartSystemDownload"}, - {0x000D0100, nullptr, "StartTitleDownload"}, - {0x000E0000, nullptr, "GetMyStatus"}, - {0x000F0040, nullptr, "GetConnectingNodes"}, - {0x00100040, nullptr, "GetNodeInfo"}, - {0x00110000, nullptr, "GetWirelessRebootPassphrase"}, - {0x00120000, nullptr, "StopSession"}, - {0x00130100, nullptr, "GetCupVersion"}, - {0x00140100, nullptr, "GetDupAvailability"}, -}; - -DLP_CLNT_Interface::DLP_CLNT_Interface() { - Register(FunctionTable); -} - -} // namespace DLP -} // namespace Service diff --git a/src/core/hle/service/dlp/dlp_clnt.h b/src/core/hle/service/dlp/dlp_clnt.h deleted file mode 100644 index 067f11e37..000000000 --- a/src/core/hle/service/dlp/dlp_clnt.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace DLP { - -class DLP_CLNT_Interface final : public Interface { -public: - DLP_CLNT_Interface(); - - std::string GetPortName() const override { - return "dlp:CLNT"; - } -}; - -} // namespace DLP -} // namespace Service diff --git a/src/core/hle/service/dlp/dlp_fkcl.cpp b/src/core/hle/service/dlp/dlp_fkcl.cpp deleted file mode 100644 index fe6be7d32..000000000 --- a/src/core/hle/service/dlp/dlp_fkcl.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/dlp/dlp_fkcl.h" - -namespace Service { -namespace DLP { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010083, nullptr, "Initialize"}, - {0x00020000, nullptr, "Finalize"}, - {0x00030000, nullptr, "GetEventDesc"}, - {0x00040000, nullptr, "GetChannels"}, - {0x00050180, nullptr, "StartScan"}, - {0x00060000, nullptr, "StopScan"}, - {0x00070080, nullptr, "GetServerInfo"}, - {0x00080100, nullptr, "GetTitleInfo"}, - {0x00090040, nullptr, "GetTitleInfoInOrder"}, - {0x000A0080, nullptr, "DeleteScanInfo"}, - {0x000B0100, nullptr, "StartFakeSession"}, - {0x000C0000, nullptr, "GetMyStatus"}, - {0x000D0040, nullptr, "GetConnectingNodes"}, - {0x000E0040, nullptr, "GetNodeInfo"}, - {0x000F0000, nullptr, "GetWirelessRebootPassphrase"}, - {0x00100000, nullptr, "StopSession"}, - {0x00110203, nullptr, "Initialize2"}, -}; - -DLP_FKCL_Interface::DLP_FKCL_Interface() { - Register(FunctionTable); -} - -} // namespace DLP -} // namespace Service diff --git a/src/core/hle/service/dlp/dlp_fkcl.h b/src/core/hle/service/dlp/dlp_fkcl.h deleted file mode 100644 index e4837a167..000000000 --- a/src/core/hle/service/dlp/dlp_fkcl.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace DLP { - -class DLP_FKCL_Interface final : public Interface { -public: - DLP_FKCL_Interface(); - - std::string GetPortName() const override { - return "dlp:FKCL"; - } -}; - -} // namespace DLP -} // namespace Service diff --git a/src/core/hle/service/dlp/dlp_srvr.cpp b/src/core/hle/service/dlp/dlp_srvr.cpp deleted file mode 100644 index 1bcea43d3..000000000 --- a/src/core/hle/service/dlp/dlp_srvr.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/hle/ipc.h" -#include "core/hle/result.h" -#include "core/hle/service/dlp/dlp_srvr.h" - -namespace Service { -namespace DLP { - -static void IsChild(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; - - LOG_WARNING(Service_DLP, "(STUBBED) called"); -} - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010183, nullptr, "Initialize"}, - {0x00020000, nullptr, "Finalize"}, - {0x00030000, nullptr, "GetServerState"}, - {0x00040000, nullptr, "GetEventDescription"}, - {0x00050080, nullptr, "StartAccepting"}, - {0x00060000, nullptr, "EndAccepting"}, - {0x00070000, nullptr, "StartDistribution"}, - {0x000800C0, nullptr, "SendWirelessRebootPassphrase"}, - {0x00090040, nullptr, "AcceptClient"}, - {0x000A0040, nullptr, "DisconnectClient"}, - {0x000B0042, nullptr, "GetConnectingClients"}, - {0x000C0040, nullptr, "GetClientInfo"}, - {0x000D0040, nullptr, "GetClientState"}, - {0x000E0040, IsChild, "IsChild"}, - {0x000F0303, nullptr, "InitializeWithName"}, - {0x00100000, nullptr, "GetDupNoticeNeed"}, -}; - -DLP_SRVR_Interface::DLP_SRVR_Interface() { - Register(FunctionTable); -} - -} // namespace DLP -} // namespace Service diff --git a/src/core/hle/service/dlp/dlp_srvr.h b/src/core/hle/service/dlp/dlp_srvr.h deleted file mode 100644 index 19fe17840..000000000 --- a/src/core/hle/service/dlp/dlp_srvr.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace DLP { - -class DLP_SRVR_Interface final : public Interface { -public: - DLP_SRVR_Interface(); - - std::string GetPortName() const override { - return "dlp:SRVR"; - } -}; - -} // namespace DLP -} // namespace Service diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp deleted file mode 100644 index 7c8f4339f..000000000 --- a/src/core/hle/service/err_f.cpp +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <array> -#include <chrono> -#include <iomanip> -#include <sstream> -#include "common/bit_field.h" -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/core.h" -#include "core/hle/ipc.h" -#include "core/hle/result.h" -#include "core/hle/service/err_f.h" - -namespace Service { -namespace ERR { - -enum class FatalErrType : u32 { - Generic = 0, - Corrupted = 1, - CardRemoved = 2, - Exception = 3, - ResultFailure = 4, - Logged = 5, -}; - -enum class ExceptionType : u32 { - PrefetchAbort = 0, - DataAbort = 1, - Undefined = 2, - VectorFP = 3, -}; - -struct ExceptionInfo { - u8 exception_type; - INSERT_PADDING_BYTES(3); - u32 sr; - u32 ar; - u32 fpexc; - u32 fpinst; - u32 fpinst2; -}; -static_assert(sizeof(ExceptionInfo) == 0x18, "ExceptionInfo struct has incorrect size"); - -struct ExceptionContext final { - std::array<u32, 16> arm_regs; - u32 cpsr; -}; -static_assert(sizeof(ExceptionContext) == 0x44, "ExceptionContext struct has incorrect size"); - -struct ExceptionData { - ExceptionInfo exception_info; - ExceptionContext exception_context; - INSERT_PADDING_WORDS(1); -}; -static_assert(sizeof(ExceptionData) == 0x60, "ExceptionData struct has incorrect size"); - -// This is used instead of ResultCode from result.h -// because we can't have non-trivial data members in unions. -union RSL { - u32 raw; - - BitField<0, 10, u32> description; - BitField<10, 8, u32> module; - BitField<21, 6, u32> summary; - BitField<27, 5, u32> level; -}; - -struct ErrInfo { - struct ErrInfoCommon { - u8 specifier; // 0x0 - u8 rev_high; // 0x1 - u16 rev_low; // 0x2 - RSL result_code; // 0x4 - u32 pc_address; // 0x8 - u32 pid; // 0xC - u32 title_id_low; // 0x10 - u32 title_id_high; // 0x14 - u32 app_title_id_low; // 0x18 - u32 app_title_id_high; // 0x1C - } errinfo_common; - static_assert(sizeof(ErrInfoCommon) == 0x20, "ErrInfoCommon struct has incorrect size"); - - union { - struct { - char data[0x60]; // 0x20 - } generic; - - struct { - ExceptionData exception_data; // 0x20 - } exception; - - struct { - char message[0x60]; // 0x20 - } result_failure; - }; -}; - -static std::string GetErrType(u8 type_code) { - switch (static_cast<FatalErrType>(type_code)) { - case FatalErrType::Generic: - return "Generic"; - case FatalErrType::Corrupted: - return "Corrupted"; - case FatalErrType::CardRemoved: - return "CardRemoved"; - case FatalErrType::Exception: - return "Exception"; - case FatalErrType::ResultFailure: - return "ResultFailure"; - case FatalErrType::Logged: - return "Logged"; - default: - return "Unknown Error Type"; - } -} - -static std::string GetExceptionType(u8 type_code) { - switch (static_cast<ExceptionType>(type_code)) { - case ExceptionType::PrefetchAbort: - return "Prefetch Abort"; - case ExceptionType::DataAbort: - return "Data Abort"; - case ExceptionType::Undefined: - return "Undefined Exception"; - case ExceptionType::VectorFP: - return "Vector Floating Point Exception"; - default: - return "Unknown Exception Type"; - } -} - -static std::string GetCurrentSystemTime() { - auto now = std::chrono::system_clock::now(); - auto time = std::chrono::system_clock::to_time_t(now); - - std::stringstream time_stream; - time_stream << std::put_time(std::localtime(&time), "%Y/%m/%d %H:%M:%S"); - return time_stream.str(); -} - -static void LogGenericInfo(const ErrInfo::ErrInfoCommon& errinfo_common) { - LOG_CRITICAL(Service_ERR, "PID: 0x%08X", errinfo_common.pid); - LOG_CRITICAL(Service_ERR, "REV: 0x%08X_0x%08X", errinfo_common.rev_high, - errinfo_common.rev_low); - LOG_CRITICAL(Service_ERR, "TID: 0x%08X_0x%08X", errinfo_common.title_id_high, - errinfo_common.title_id_low); - LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errinfo_common.app_title_id_high, - errinfo_common.app_title_id_low); - LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errinfo_common.pc_address); - - LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errinfo_common.result_code.raw); - LOG_CRITICAL(Service_ERR, " Level: %u", errinfo_common.result_code.level.Value()); - LOG_CRITICAL(Service_ERR, " Summary: %u", errinfo_common.result_code.summary.Value()); - LOG_CRITICAL(Service_ERR, " Module: %u", errinfo_common.result_code.module.Value()); - LOG_CRITICAL(Service_ERR, " Desc: %u", errinfo_common.result_code.description.Value()); -} - -/* ThrowFatalError function - * Inputs: - * 0 : Header code [0x00010800] - * 1-32 : FatalErrInfo - * Outputs: - * 0 : Header code - * 1 : Result code - */ -static void ThrowFatalError(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - LOG_CRITICAL(Service_ERR, "Fatal error"); - const ErrInfo* errinfo = reinterpret_cast<ErrInfo*>(&cmd_buff[1]); - LOG_CRITICAL(Service_ERR, "Fatal error type: %s", - GetErrType(errinfo->errinfo_common.specifier).c_str()); - Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorUnknown); - - // Generic Info - LogGenericInfo(errinfo->errinfo_common); - - switch (static_cast<FatalErrType>(errinfo->errinfo_common.specifier)) { - case FatalErrType::Generic: - case FatalErrType::Corrupted: - case FatalErrType::CardRemoved: - case FatalErrType::Logged: { - LOG_CRITICAL(Service_ERR, "Datetime: %s", GetCurrentSystemTime().c_str()); - break; - } - case FatalErrType::Exception: { - const auto& errtype = errinfo->exception; - - // Register Info - LOG_CRITICAL(Service_ERR, "ARM Registers:"); - for (u32 index = 0; index < errtype.exception_data.exception_context.arm_regs.size(); - ++index) { - if (index < 13) { - LOG_DEBUG(Service_ERR, "r%u=0x%08X", index, - errtype.exception_data.exception_context.arm_regs.at(index)); - } else if (index == 13) { - LOG_CRITICAL(Service_ERR, "SP=0x%08X", - errtype.exception_data.exception_context.arm_regs.at(index)); - } else if (index == 14) { - LOG_CRITICAL(Service_ERR, "LR=0x%08X", - errtype.exception_data.exception_context.arm_regs.at(index)); - } else if (index == 15) { - LOG_CRITICAL(Service_ERR, "PC=0x%08X", - errtype.exception_data.exception_context.arm_regs.at(index)); - } - } - LOG_CRITICAL(Service_ERR, "CPSR=0x%08X", errtype.exception_data.exception_context.cpsr); - - // Exception Info - LOG_CRITICAL( - Service_ERR, "EXCEPTION TYPE: %s", - GetExceptionType(errtype.exception_data.exception_info.exception_type).c_str()); - switch (static_cast<ExceptionType>(errtype.exception_data.exception_info.exception_type)) { - case ExceptionType::PrefetchAbort: - LOG_CRITICAL(Service_ERR, "IFSR: 0x%08X", errtype.exception_data.exception_info.sr); - LOG_CRITICAL(Service_ERR, "r15: 0x%08X", errtype.exception_data.exception_info.ar); - case ExceptionType::DataAbort: - LOG_CRITICAL(Service_ERR, "DFSR: 0x%08X", errtype.exception_data.exception_info.sr); - LOG_CRITICAL(Service_ERR, "DFAR: 0x%08X", errtype.exception_data.exception_info.ar); - break; - case ExceptionType::VectorFP: - LOG_CRITICAL(Service_ERR, "FPEXC: 0x%08X", - errtype.exception_data.exception_info.fpinst); - LOG_CRITICAL(Service_ERR, "FINST: 0x%08X", - errtype.exception_data.exception_info.fpinst); - LOG_CRITICAL(Service_ERR, "FINST2: 0x%08X", - errtype.exception_data.exception_info.fpinst2); - break; - case ExceptionType::Undefined: - break; // Not logging exception_info for this case - } - LOG_CRITICAL(Service_ERR, "Datetime: %s", GetCurrentSystemTime().c_str()); - break; - } - - case FatalErrType::ResultFailure: { - const auto& errtype = errinfo->result_failure; - - // Failure Message - LOG_CRITICAL(Service_ERR, "Failure Message: %s", errtype.message); - LOG_CRITICAL(Service_ERR, "Datetime: %s", GetCurrentSystemTime().c_str()); - break; - } - - } // switch FatalErrType - - cmd_buff[0] = IPC::MakeHeader(0x1, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error -} - -const Interface::FunctionInfo FunctionTable[] = { - // clang-format off - {0x00010800, ThrowFatalError, "ThrowFatalError"}, - {0x00020042, nullptr, "SetUserString"}, - // clang-format on -}; - -ERR_F::ERR_F() { - Register(FunctionTable); -} - -} // namespace ERR -} // namespace Service diff --git a/src/core/hle/service/err_f.h b/src/core/hle/service/err_f.h deleted file mode 100644 index 5b27fc871..000000000 --- a/src/core/hle/service/err_f.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace ERR { - -class ERR_F final : public Interface { -public: - ERR_F(); - - std::string GetPortName() const override { - return "err:f"; - } -}; - -} // namespace ERR -} // namespace Service diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp deleted file mode 100644 index 7ad7798da..000000000 --- a/src/core/hle/service/frd/frd.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/assert.h" -#include "common/logging/log.h" -#include "common/string_util.h" -#include "core/hle/ipc.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/result.h" -#include "core/hle/service/frd/frd.h" -#include "core/hle/service/frd/frd_a.h" -#include "core/hle/service/frd/frd_u.h" -#include "core/hle/service/service.h" -#include "core/memory.h" - -namespace Service { -namespace FRD { - -static FriendKey my_friend_key = {0, 0, 0ull}; -static MyPresence my_presence = {}; - -void GetMyPresence(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 shifted_out_size = cmd_buff[64]; - u32 my_presence_addr = cmd_buff[65]; - - ASSERT(shifted_out_size == ((sizeof(MyPresence) << 14) | 2)); - - Memory::WriteBlock(my_presence_addr, &my_presence, sizeof(MyPresence)); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - - LOG_WARNING(Service_FRD, "(STUBBED) called"); -} - -void GetFriendKeyList(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 unknown = cmd_buff[1]; - u32 frd_count = cmd_buff[2]; - u32 frd_key_addr = cmd_buff[65]; - - FriendKey zero_key = {}; - for (u32 i = 0; i < frd_count; ++i) { - Memory::WriteBlock(frd_key_addr + i * sizeof(FriendKey), &zero_key, sizeof(FriendKey)); - } - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = 0; // 0 friends - LOG_WARNING(Service_FRD, "(STUBBED) called, unknown=%d, frd_count=%d, frd_key_addr=0x%08X", - unknown, frd_count, frd_key_addr); -} - -void GetFriendProfile(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 count = cmd_buff[1]; - u32 frd_key_addr = cmd_buff[3]; - u32 profiles_addr = cmd_buff[65]; - - Profile zero_profile = {}; - for (u32 i = 0; i < count; ++i) { - Memory::WriteBlock(profiles_addr + i * sizeof(Profile), &zero_profile, sizeof(Profile)); - } - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_FRD, - "(STUBBED) called, count=%d, frd_key_addr=0x%08X, profiles_addr=0x%08X", count, - frd_key_addr, profiles_addr); -} - -void GetFriendAttributeFlags(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 count = cmd_buff[1]; - u32 frd_key_addr = cmd_buff[3]; - u32 attr_flags_addr = cmd_buff[65]; - - for (u32 i = 0; i < count; ++i) { - // TODO:(mailwl) figure out AttributeFlag size and zero all buffer. Assume 1 byte - Memory::Write8(attr_flags_addr + i, 0); - } - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_FRD, - "(STUBBED) called, count=%d, frd_key_addr=0x%08X, attr_flags_addr=0x%08X", count, - frd_key_addr, attr_flags_addr); -} - -void GetMyFriendKey(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - std::memcpy(&cmd_buff[2], &my_friend_key, sizeof(FriendKey)); - LOG_WARNING(Service_FRD, "(STUBBED) called"); -} - -void GetMyScreenName(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - // TODO: (mailwl) get the name from config - Common::UTF8ToUTF16("Citra").copy(reinterpret_cast<char16_t*>(&cmd_buff[2]), 11); - LOG_WARNING(Service_FRD, "(STUBBED) called"); -} - -void UnscrambleLocalFriendCode(Service::Interface* self) { - const size_t scrambled_friend_code_size = 12; - const size_t friend_code_size = 8; - - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1C, 1, 2); - const u32 friend_code_count = rp.Pop<u32>(); - size_t in_buffer_size; - const VAddr scrambled_friend_codes = rp.PopStaticBuffer(&in_buffer_size, false); - ASSERT_MSG(in_buffer_size == (friend_code_count * scrambled_friend_code_size), - "Wrong input buffer size"); - - size_t out_buffer_size; - VAddr unscrambled_friend_codes = rp.PeekStaticBuffer(0, &out_buffer_size); - ASSERT_MSG(out_buffer_size == (friend_code_count * friend_code_size), - "Wrong output buffer size"); - - for (u32 current = 0; current < friend_code_count; ++current) { - // TODO(B3N30): Unscramble the codes and compare them against the friend list - // Only write 0 if the code isn't in friend list, otherwise write the - // unscrambled one - // - // Code for unscrambling (should be compared to HW): - // std::array<u16, 6> scambled_friend_code; - // Memory::ReadBlock(scrambled_friend_codes+(current*scrambled_friend_code_size), - // scambled_friend_code.data(), scrambled_friend_code_size); std::array<u16, 4> - // unscrambled_friend_code; unscrambled_friend_code[0] = scambled_friend_code[0] ^ - // scambled_friend_code[5]; unscrambled_friend_code[1] = scambled_friend_code[1] ^ - // scambled_friend_code[5]; unscrambled_friend_code[2] = scambled_friend_code[2] ^ - // scambled_friend_code[5]; unscrambled_friend_code[3] = scambled_friend_code[3] ^ - // scambled_friend_code[5]; - - u64 result = 0ull; - Memory::WriteBlock(unscrambled_friend_codes + (current * sizeof(result)), &result, - sizeof(result)); - } - - LOG_WARNING(Service_FRD, "(STUBBED) called"); - IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - rb.Push(RESULT_SUCCESS); - rb.PushStaticBuffer(unscrambled_friend_codes, out_buffer_size, 0); -} - -void SetClientSdkVersion(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - const u32 version = cmd_buff[1]; - - self->SetVersion(version); - - LOG_WARNING(Service_FRD, "(STUBBED) called, version: 0x%08X", version); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error -} - -void Init() { - using namespace Kernel; - - AddService(new FRD_A_Interface); - AddService(new FRD_U_Interface); -} - -void Shutdown() {} - -} // namespace FRD - -} // namespace Service diff --git a/src/core/hle/service/frd/frd.h b/src/core/hle/service/frd/frd.h deleted file mode 100644 index 66a87c8cd..000000000 --- a/src/core/hle/service/frd/frd.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_types.h" - -namespace Service { - -class Interface; - -namespace FRD { - -struct FriendKey { - u32 friend_id; - u32 unknown; - u64 friend_code; -}; - -struct MyPresence { - u8 unknown[0x12C]; -}; - -struct Profile { - u8 region; - u8 country; - u8 area; - u8 language; - u32 unknown; -}; - -/** - * FRD::GetMyPresence service function - * Inputs: - * 64 : sizeof (MyPresence) << 14 | 2 - * 65 : Address of MyPresence structure - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void GetMyPresence(Service::Interface* self); - -/** - * FRD::GetFriendKeyList service function - * Inputs: - * 1 : Unknown - * 2 : Max friends count - * 65 : Address of FriendKey List - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : FriendKey count filled - */ -void GetFriendKeyList(Service::Interface* self); - -/** - * FRD::GetFriendProfile service function - * Inputs: - * 1 : Friends count - * 2 : Friends count << 18 | 2 - * 3 : Address of FriendKey List - * 64 : (count * sizeof (Profile)) << 10 | 2 - * 65 : Address of Profiles List - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void GetFriendProfile(Service::Interface* self); - -/** - * FRD::GetFriendAttributeFlags service function - * Inputs: - * 1 : Friends count - * 2 : Friends count << 18 | 2 - * 3 : Address of FriendKey List - * 65 : Address of AttributeFlags - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void GetFriendAttributeFlags(Service::Interface* self); - -/** - * FRD::GetMyFriendKey service function - * Inputs: - * none - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2-5 : FriendKey - */ -void GetMyFriendKey(Service::Interface* self); - -/** - * FRD::GetMyScreenName service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : UTF16 encoded name (max 11 symbols) - */ -void GetMyScreenName(Service::Interface* self); - -/** - * FRD::UnscrambleLocalFriendCode service function - * Inputs: - * 1 : Friend code count - * 2 : ((count * 12) << 14) | 0x402 - * 3 : Pointer to encoded friend codes. Each is 12 bytes large - * 64 : ((count * 8) << 14) | 2 - * 65 : Pointer to write decoded local friend codes to. Each is 8 bytes large. - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void UnscrambleLocalFriendCode(Service::Interface* self); - -/** - * FRD::SetClientSdkVersion service function - * Inputs: - * 1 : Used SDK Version - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void SetClientSdkVersion(Service::Interface* self); - -/// Initialize FRD service(s) -void Init(); - -/// Shutdown FRD service(s) -void Shutdown(); - -} // namespace FRD -} // namespace Service diff --git a/src/core/hle/service/frd/frd_a.cpp b/src/core/hle/service/frd/frd_a.cpp deleted file mode 100644 index cfc37210b..000000000 --- a/src/core/hle/service/frd/frd_a.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/frd/frd_a.h" - -namespace Service { -namespace FRD { - -// Empty arrays are illegal -- commented out until an entry is added. -// const Interface::FunctionInfo FunctionTable[] = { }; - -FRD_A_Interface::FRD_A_Interface() { - // Register(FunctionTable); -} - -} // namespace FRD -} // namespace Service diff --git a/src/core/hle/service/frd/frd_a.h b/src/core/hle/service/frd/frd_a.h deleted file mode 100644 index 006d1cadd..000000000 --- a/src/core/hle/service/frd/frd_a.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace FRD { - -class FRD_A_Interface : public Service::Interface { -public: - FRD_A_Interface(); - - std::string GetPortName() const override { - return "frd:a"; - } -}; - -} // namespace FRD -} // namespace Service diff --git a/src/core/hle/service/frd/frd_u.cpp b/src/core/hle/service/frd/frd_u.cpp deleted file mode 100644 index 6970ff768..000000000 --- a/src/core/hle/service/frd/frd_u.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/frd/frd.h" -#include "core/hle/service/frd/frd_u.h" - -namespace Service { -namespace FRD { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010000, nullptr, "HasLoggedIn"}, - {0x00020000, nullptr, "IsOnline"}, - {0x00030000, nullptr, "Login"}, - {0x00040000, nullptr, "Logout"}, - {0x00050000, GetMyFriendKey, "GetMyFriendKey"}, - {0x00060000, nullptr, "GetMyPreference"}, - {0x00070000, nullptr, "GetMyProfile"}, - {0x00080000, GetMyPresence, "GetMyPresence"}, - {0x00090000, GetMyScreenName, "GetMyScreenName"}, - {0x000A0000, nullptr, "GetMyMii"}, - {0x000B0000, nullptr, "GetMyLocalAccountId"}, - {0x000C0000, nullptr, "GetMyPlayingGame"}, - {0x000D0000, nullptr, "GetMyFavoriteGame"}, - {0x000E0000, nullptr, "GetMyNcPrincipalId"}, - {0x000F0000, nullptr, "GetMyComment"}, - {0x00100040, nullptr, "GetMyPassword"}, - {0x00110080, GetFriendKeyList, "GetFriendKeyList"}, - {0x00120042, nullptr, "GetFriendPresence"}, - {0x00130142, nullptr, "GetFriendScreenName"}, - {0x00140044, nullptr, "GetFriendMii"}, - {0x00150042, GetFriendProfile, "GetFriendProfile"}, - {0x00160042, nullptr, "GetFriendRelationship"}, - {0x00170042, GetFriendAttributeFlags, "GetFriendAttributeFlags"}, - {0x00180044, nullptr, "GetFriendPlayingGame"}, - {0x00190042, nullptr, "GetFriendFavoriteGame"}, - {0x001A00C4, nullptr, "GetFriendInfo"}, - {0x001B0080, nullptr, "IsIncludedInFriendList"}, - {0x001C0042, UnscrambleLocalFriendCode, "UnscrambleLocalFriendCode"}, - {0x001D0002, nullptr, "UpdateGameModeDescription"}, - {0x001E02C2, nullptr, "UpdateGameMode"}, - {0x001F0042, nullptr, "SendInvitation"}, - {0x00200002, nullptr, "AttachToEventNotification"}, - {0x00210040, nullptr, "SetNotificationMask"}, - {0x00220040, nullptr, "GetEventNotification"}, - {0x00230000, nullptr, "GetLastResponseResult"}, - {0x00240040, nullptr, "PrincipalIdToFriendCode"}, - {0x00250080, nullptr, "FriendCodeToPrincipalId"}, - {0x00260080, nullptr, "IsValidFriendCode"}, - {0x00270040, nullptr, "ResultToErrorCode"}, - {0x00280244, nullptr, "RequestGameAuthentication"}, - {0x00290000, nullptr, "GetGameAuthenticationData"}, - {0x002A0204, nullptr, "RequestServiceLocator"}, - {0x002B0000, nullptr, "GetServiceLocatorData"}, - {0x002C0002, nullptr, "DetectNatProperties"}, - {0x002D0000, nullptr, "GetNatProperties"}, - {0x002E0000, nullptr, "GetServerTimeInterval"}, - {0x002F0040, nullptr, "AllowHalfAwake"}, - {0x00300000, nullptr, "GetServerTypes"}, - {0x00310082, nullptr, "GetFriendComment"}, - {0x00320042, SetClientSdkVersion, "SetClientSdkVersion"}, - {0x00330000, nullptr, "GetMyApproachContext"}, - {0x00340046, nullptr, "AddFriendWithApproach"}, - {0x00350082, nullptr, "DecryptApproachContext"}, -}; - -FRD_U_Interface::FRD_U_Interface() { - Register(FunctionTable); -} - -} // namespace FRD -} // namespace Service diff --git a/src/core/hle/service/frd/frd_u.h b/src/core/hle/service/frd/frd_u.h deleted file mode 100644 index 07e43f155..000000000 --- a/src/core/hle/service/frd/frd_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace FRD { - -class FRD_U_Interface : public Service::Interface { -public: - FRD_U_Interface(); - - std::string GetPortName() const override { - return "frd:u"; - } -}; - -} // namespace FRD -} // namespace Service diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp deleted file mode 100644 index b01d6e031..000000000 --- a/src/core/hle/service/http_c.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/http_c.h" - -namespace Service { -namespace HTTP { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010044, nullptr, "Initialize"}, - {0x00020082, nullptr, "CreateContext"}, - {0x00030040, nullptr, "CloseContext"}, - {0x00040040, nullptr, "CancelConnection"}, - {0x00050040, nullptr, "GetRequestState"}, - {0x00060040, nullptr, "GetDownloadSizeState"}, - {0x00070040, nullptr, "GetRequestError"}, - {0x00080042, nullptr, "InitializeConnectionSession"}, - {0x00090040, nullptr, "BeginRequest"}, - {0x000A0040, nullptr, "BeginRequestAsync"}, - {0x000B0082, nullptr, "ReceiveData"}, - {0x000C0102, nullptr, "ReceiveDataTimeout"}, - {0x000D0146, nullptr, "SetProxy"}, - {0x000E0040, nullptr, "SetProxyDefault"}, - {0x000F00C4, nullptr, "SetBasicAuthorization"}, - {0x00100080, nullptr, "SetSocketBufferSize"}, - {0x001100C4, nullptr, "AddRequestHeader"}, - {0x001200C4, nullptr, "AddPostDataAscii"}, - {0x001300C4, nullptr, "AddPostDataBinary"}, - {0x00140082, nullptr, "AddPostDataRaw"}, - {0x00150080, nullptr, "SetPostDataType"}, - {0x001600C4, nullptr, "SendPostDataAscii"}, - {0x00170144, nullptr, "SendPostDataAsciiTimeout"}, - {0x001800C4, nullptr, "SendPostDataBinary"}, - {0x00190144, nullptr, "SendPostDataBinaryTimeout"}, - {0x001A0082, nullptr, "SendPostDataRaw"}, - {0x001B0102, nullptr, "SendPOSTDataRawTimeout"}, - {0x001C0080, nullptr, "SetPostDataEncoding"}, - {0x001D0040, nullptr, "NotifyFinishSendPostData"}, - {0x001E00C4, nullptr, "GetResponseHeader"}, - {0x001F0144, nullptr, "GetResponseHeaderTimeout"}, - {0x00200082, nullptr, "GetResponseData"}, - {0x00210102, nullptr, "GetResponseDataTimeout"}, - {0x00220040, nullptr, "GetResponseStatusCode"}, - {0x002300C0, nullptr, "GetResponseStatusCodeTimeout"}, - {0x00240082, nullptr, "AddTrustedRootCA"}, - {0x00250080, nullptr, "AddDefaultCert"}, - {0x00260080, nullptr, "SelectRootCertChain"}, - {0x002700C4, nullptr, "SetClientCert"}, - {0x002B0080, nullptr, "SetSSLOpt"}, - {0x002C0080, nullptr, "SetSSLClearOpt"}, - {0x002D0000, nullptr, "CreateRootCertChain"}, - {0x002E0040, nullptr, "DestroyRootCertChain"}, - {0x002F0082, nullptr, "RootCertChainAddCert"}, - {0x00300080, nullptr, "RootCertChainAddDefaultCert"}, - {0x00310080, nullptr, "RootCertChainRemoveCert"}, - {0x00320084, nullptr, "OpenClientCertContext"}, - {0x00330040, nullptr, "OpenDefaultClientCertContext"}, - {0x00340040, nullptr, "CloseClientCertContext"}, - {0x00350186, nullptr, "SetDefaultProxy"}, - {0x00360000, nullptr, "ClearDNSCache"}, - {0x00370080, nullptr, "SetKeepAlive"}, - {0x003800C0, nullptr, "SetPostDataTypeSize"}, - {0x00390000, nullptr, "Finalize"}, -}; - -HTTP_C::HTTP_C() { - Register(FunctionTable); -} - -} // namespace HTTP -} // namespace Service diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h deleted file mode 100644 index cff279c02..000000000 --- a/src/core/hle/service/http_c.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace HTTP { - -class HTTP_C final : public Interface { -public: - HTTP_C(); - - std::string GetPortName() const override { - return "http:C"; - } -}; - -} // namespace HTTP -} // namespace Service diff --git a/src/core/hle/service/ir/extra_hid.cpp b/src/core/hle/service/ir/extra_hid.cpp deleted file mode 100644 index e7acc17a5..000000000 --- a/src/core/hle/service/ir/extra_hid.cpp +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/alignment.h" -#include "common/bit_field.h" -#include "common/string_util.h" -#include "core/core_timing.h" -#include "core/hle/service/ir/extra_hid.h" -#include "core/settings.h" - -namespace Service { -namespace IR { - -enum class RequestID : u8 { - /** - * ConfigureHIDPolling request - * Starts HID input polling, or changes the polling interval if it is already started. - * Inputs: - * byte 0: request ID - * byte 1: polling interval in ms - * byte 2: unknown - */ - ConfigureHIDPolling = 1, - - /** - * ReadCalibrationData request - * Reads the calibration data stored in circle pad pro. - * Inputs: - * byte 0: request ID - * byte 1: expected response time in ms? - * byte 2-3: data offset (aligned to 0x10) - * byte 4-5: data size (aligned to 0x10) - */ - ReadCalibrationData = 2, - - // TODO(wwylele): there are three more request types (id = 3, 4 and 5) -}; - -enum class ResponseID : u8 { - - /** - * PollHID response - * Sends current HID status - * Output: - * byte 0: response ID - * byte 1-3: Right circle pad position. This three bytes are two little-endian 12-bit - * fields. The first one is for x-axis and the second one is for y-axis. - * byte 4: bit[0:4] battery level; bit[5] ZL button; bit[6] ZR button; bit[7] R button - * Note that for the three button fields, the bit is set when the button is NOT pressed. - * byte 5: unknown - */ - PollHID = 0x10, - - /** - * ReadCalibrationData response - * Sends the calibration data reads from circle pad pro. - * Output: - * byte 0: resonse ID - * byte 1-2: data offset (aligned to 0x10) - * byte 3-4: data size (aligned to 0x10) - * byte 5-...: calibration data - */ - ReadCalibrationData = 0x11, -}; - -ExtraHID::ExtraHID(SendFunc send_func) : IRDevice(send_func) { - LoadInputDevices(); - - // The data below was retrieved from a New 3DS - // TODO(wwylele): this data is probably writable (via request 3?) and thus should be saved to - // and loaded from somewhere. - calibration_data = std::array<u8, 0x40>{{ - // 0x00 - 0x00, 0x00, 0x08, 0x80, 0x85, 0xEB, 0x11, 0x3F, - // 0x08 - 0x85, 0xEB, 0x11, 0x3F, 0xFF, 0xFF, 0xFF, 0xF5, - // 0x10 - 0xFF, 0x00, 0x08, 0x80, 0x85, 0xEB, 0x11, 0x3F, - // 0x18 - 0x85, 0xEB, 0x11, 0x3F, 0xFF, 0xFF, 0xFF, 0x65, - // 0x20 - 0xFF, 0x00, 0x08, 0x80, 0x85, 0xEB, 0x11, 0x3F, - // 0x28 - 0x85, 0xEB, 0x11, 0x3F, 0xFF, 0xFF, 0xFF, 0x65, - // 0x30 - 0xFF, 0x00, 0x08, 0x80, 0x85, 0xEB, 0x11, 0x3F, - // 0x38 - 0x85, 0xEB, 0x11, 0x3F, 0xFF, 0xFF, 0xFF, 0x65, - }}; - - hid_polling_callback_id = - CoreTiming::RegisterEvent("ExtraHID::SendHIDStatus", [this](u64, int cycles_late) { - SendHIDStatus(); - CoreTiming::ScheduleEvent(msToCycles(hid_period) - cycles_late, - hid_polling_callback_id); - }); -} - -ExtraHID::~ExtraHID() { - OnDisconnect(); -} - -void ExtraHID::OnConnect() {} - -void ExtraHID::OnDisconnect() { - CoreTiming::UnscheduleEvent(hid_polling_callback_id, 0); -} - -void ExtraHID::HandleConfigureHIDPollingRequest(const std::vector<u8>& request) { - if (request.size() != 3) { - LOG_ERROR(Service_IR, "Wrong request size (%zu): %s", request.size(), - Common::ArrayToString(request.data(), request.size()).c_str()); - return; - } - - // Change HID input polling interval - CoreTiming::UnscheduleEvent(hid_polling_callback_id, 0); - hid_period = request[1]; - CoreTiming::ScheduleEvent(msToCycles(hid_period), hid_polling_callback_id); -} - -void ExtraHID::HandleReadCalibrationDataRequest(const std::vector<u8>& request_buf) { - struct ReadCalibrationDataRequest { - RequestID request_id; - u8 expected_response_time; - u16_le offset; - u16_le size; - }; - static_assert(sizeof(ReadCalibrationDataRequest) == 6, - "ReadCalibrationDataRequest has wrong size"); - - if (request_buf.size() != sizeof(ReadCalibrationDataRequest)) { - LOG_ERROR(Service_IR, "Wrong request size (%zu): %s", request_buf.size(), - Common::ArrayToString(request_buf.data(), request_buf.size()).c_str()); - return; - } - - ReadCalibrationDataRequest request; - std::memcpy(&request, request_buf.data(), sizeof(request)); - - const u16 offset = Common::AlignDown(request.offset, 16); - const u16 size = Common::AlignDown(request.size, 16); - - if (offset + size > calibration_data.size()) { - LOG_ERROR(Service_IR, "Read beyond the end of calibration data! (offset=%u, size=%u)", - offset, size); - return; - } - - std::vector<u8> response(5); - response[0] = static_cast<u8>(ResponseID::ReadCalibrationData); - std::memcpy(&response[1], &request.offset, sizeof(request.offset)); - std::memcpy(&response[3], &request.size, sizeof(request.size)); - response.insert(response.end(), calibration_data.begin() + offset, - calibration_data.begin() + offset + size); - Send(response); -} - -void ExtraHID::OnReceive(const std::vector<u8>& data) { - switch (static_cast<RequestID>(data[0])) { - case RequestID::ConfigureHIDPolling: - HandleConfigureHIDPollingRequest(data); - break; - case RequestID::ReadCalibrationData: - HandleReadCalibrationDataRequest(data); - break; - default: - LOG_ERROR(Service_IR, "Unknown request: %s", - Common::ArrayToString(data.data(), data.size()).c_str()); - break; - } -} - -void ExtraHID::SendHIDStatus() { - if (is_device_reload_pending.exchange(false)) - LoadInputDevices(); - - struct { - union { - BitField<0, 8, u32_le> header; - BitField<8, 12, u32_le> c_stick_x; - BitField<20, 12, u32_le> c_stick_y; - } c_stick; - union { - BitField<0, 5, u8> battery_level; - BitField<5, 1, u8> zl_not_held; - BitField<6, 1, u8> zr_not_held; - BitField<7, 1, u8> r_not_held; - } buttons; - u8 unknown; - } response; - static_assert(sizeof(response) == 6, "HID status response has wrong size!"); - - constexpr int C_STICK_CENTER = 0x800; - // TODO(wwylele): this value is not accurately measured. We currently assume that the axis can - // take values in the whole range of a 12-bit integer. - constexpr int C_STICK_RADIUS = 0x7FF; - - float x, y; - std::tie(x, y) = c_stick->GetStatus(); - - response.c_stick.header.Assign(static_cast<u8>(ResponseID::PollHID)); - response.c_stick.c_stick_x.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * x)); - response.c_stick.c_stick_y.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * y)); - response.buttons.battery_level.Assign(0x1F); - response.buttons.zl_not_held.Assign(!zl->GetStatus()); - response.buttons.zr_not_held.Assign(!zr->GetStatus()); - response.buttons.r_not_held.Assign(1); - response.unknown = 0; - - std::vector<u8> response_buffer(sizeof(response)); - memcpy(response_buffer.data(), &response, sizeof(response)); - Send(response_buffer); -} - -void ExtraHID::RequestInputDevicesReload() { - is_device_reload_pending.store(true); -} - -void ExtraHID::LoadInputDevices() { - zl = Input::CreateDevice<Input::ButtonDevice>( - Settings::values.buttons[Settings::NativeButton::ZL]); - zr = Input::CreateDevice<Input::ButtonDevice>( - Settings::values.buttons[Settings::NativeButton::ZR]); - c_stick = Input::CreateDevice<Input::AnalogDevice>( - Settings::values.analogs[Settings::NativeAnalog::CStick]); -} - -} // namespace IR -} // namespace Service diff --git a/src/core/hle/service/ir/extra_hid.h b/src/core/hle/service/ir/extra_hid.h deleted file mode 100644 index a2459a73a..000000000 --- a/src/core/hle/service/ir/extra_hid.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <array> -#include <atomic> -#include "core/frontend/input.h" -#include "core/hle/service/ir/ir_user.h" - -namespace Service { -namespace IR { - -/** - * An IRDevice emulating Circle Pad Pro or New 3DS additional HID hardware. - * This device sends periodic udates at a rate configured by the 3DS, and sends calibration data if - * requested. - */ -class ExtraHID final : public IRDevice { -public: - explicit ExtraHID(SendFunc send_func); - ~ExtraHID(); - - void OnConnect() override; - void OnDisconnect() override; - void OnReceive(const std::vector<u8>& data) override; - - /// Requests input devices reload from current settings. Called when the input settings change. - void RequestInputDevicesReload(); - -private: - void SendHIDStatus(); - void HandleConfigureHIDPollingRequest(const std::vector<u8>& request); - void HandleReadCalibrationDataRequest(const std::vector<u8>& request); - void LoadInputDevices(); - - u8 hid_period; - int hid_polling_callback_id; - std::array<u8, 0x40> calibration_data; - std::unique_ptr<Input::ButtonDevice> zl; - std::unique_ptr<Input::ButtonDevice> zr; - std::unique_ptr<Input::AnalogDevice> c_stick; - std::atomic<bool> is_device_reload_pending; -}; - -} // namespace IR -} // namespace Service diff --git a/src/core/hle/service/ir/ir.cpp b/src/core/hle/service/ir/ir.cpp deleted file mode 100644 index f06dd552f..000000000 --- a/src/core/hle/service/ir/ir.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/ir/ir.h" -#include "core/hle/service/ir/ir_rst.h" -#include "core/hle/service/ir/ir_u.h" -#include "core/hle/service/ir/ir_user.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace IR { - -void Init() { - AddService(new IR_RST_Interface); - AddService(new IR_U_Interface); - AddService(new IR_User_Interface); - - InitUser(); - InitRST(); -} - -void Shutdown() { - ShutdownUser(); - ShutdownRST(); -} - -void ReloadInputDevices() { - ReloadInputDevicesUser(); - ReloadInputDevicesRST(); -} - -} // namespace IR - -} // namespace Service diff --git a/src/core/hle/service/ir/ir.h b/src/core/hle/service/ir/ir.h deleted file mode 100644 index 6be3e950c..000000000 --- a/src/core/hle/service/ir/ir.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service { - -class Interface; - -namespace IR { - -/// Initialize IR service -void Init(); - -/// Shutdown IR service -void Shutdown(); - -/// Reload input devices. Used when input configuration changed -void ReloadInputDevices(); - -} // namespace IR -} // namespace Service diff --git a/src/core/hle/service/ir/ir_rst.cpp b/src/core/hle/service/ir/ir_rst.cpp deleted file mode 100644 index 0912d5756..000000000 --- a/src/core/hle/service/ir/ir_rst.cpp +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <atomic> -#include "common/bit_field.h" -#include "core/core_timing.h" -#include "core/frontend/input.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/event.h" -#include "core/hle/kernel/shared_memory.h" -#include "core/hle/service/hid/hid.h" -#include "core/hle/service/ir/ir.h" -#include "core/hle/service/ir/ir_rst.h" -#include "core/settings.h" - -namespace Service { -namespace IR { - -union PadState { - u32_le hex{}; - - BitField<14, 1, u32_le> zl; - BitField<15, 1, u32_le> zr; - - BitField<24, 1, u32_le> c_stick_right; - BitField<25, 1, u32_le> c_stick_left; - BitField<26, 1, u32_le> c_stick_up; - BitField<27, 1, u32_le> c_stick_down; -}; - -struct PadDataEntry { - PadState current_state; - PadState delta_additions; - PadState delta_removals; - - s16_le c_stick_x; - s16_le c_stick_y; -}; - -struct SharedMem { - u64_le index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 - u64_le index_reset_ticks_previous; ///< Previous `index_reset_ticks` - u32_le index; - INSERT_PADDING_WORDS(1); - std::array<PadDataEntry, 8> entries; ///< Last 8 pad entries -}; - -static_assert(sizeof(SharedMem) == 0x98, "SharedMem has wrong size!"); - -static Kernel::SharedPtr<Kernel::Event> update_event; -static Kernel::SharedPtr<Kernel::SharedMemory> shared_memory; -static u32 next_pad_index; -static int update_callback_id; -static std::unique_ptr<Input::ButtonDevice> zl_button; -static std::unique_ptr<Input::ButtonDevice> zr_button; -static std::unique_ptr<Input::AnalogDevice> c_stick; -static std::atomic<bool> is_device_reload_pending; -static bool raw_c_stick; -static int update_period; - -static void LoadInputDevices() { - zl_button = Input::CreateDevice<Input::ButtonDevice>( - Settings::values.buttons[Settings::NativeButton::ZL]); - zr_button = Input::CreateDevice<Input::ButtonDevice>( - Settings::values.buttons[Settings::NativeButton::ZR]); - c_stick = Input::CreateDevice<Input::AnalogDevice>( - Settings::values.analogs[Settings::NativeAnalog::CStick]); -} - -static void UnloadInputDevices() { - zl_button = nullptr; - zr_button = nullptr; - c_stick = nullptr; -} - -static void UpdateCallback(u64 userdata, int cycles_late) { - SharedMem* mem = reinterpret_cast<SharedMem*>(shared_memory->GetPointer()); - - if (is_device_reload_pending.exchange(false)) - LoadInputDevices(); - - PadState state; - state.zl.Assign(zl_button->GetStatus()); - state.zr.Assign(zr_button->GetStatus()); - - // Get current c-stick position and update c-stick direction - float c_stick_x_f, c_stick_y_f; - std::tie(c_stick_x_f, c_stick_y_f) = c_stick->GetStatus(); - constexpr int MAX_CSTICK_RADIUS = 0x9C; // Max value for a c-stick radius - const s16 c_stick_x = static_cast<s16>(c_stick_x_f * MAX_CSTICK_RADIUS); - const s16 c_stick_y = static_cast<s16>(c_stick_y_f * MAX_CSTICK_RADIUS); - - if (!raw_c_stick) { - const HID::DirectionState direction = HID::GetStickDirectionState(c_stick_x, c_stick_y); - state.c_stick_up.Assign(direction.up); - state.c_stick_down.Assign(direction.down); - state.c_stick_left.Assign(direction.left); - state.c_stick_right.Assign(direction.right); - } - - // TODO (wwylele): implement raw C-stick data for raw_c_stick = true - - const u32 last_entry_index = mem->index; - mem->index = next_pad_index; - next_pad_index = (next_pad_index + 1) % mem->entries.size(); - - // Get the previous Pad state - PadState old_state{mem->entries[last_entry_index].current_state}; - - // Compute bitmask with 1s for bits different from the old state - PadState changed = {state.hex ^ old_state.hex}; - - // Get the current Pad entry - PadDataEntry& pad_entry = mem->entries[mem->index]; - - // Update entry properties - pad_entry.current_state.hex = state.hex; - pad_entry.delta_additions.hex = changed.hex & state.hex; - pad_entry.delta_removals.hex = changed.hex & old_state.hex; - pad_entry.c_stick_x = c_stick_x; - pad_entry.c_stick_y = c_stick_y; - - // If we just updated index 0, provide a new timestamp - if (mem->index == 0) { - mem->index_reset_ticks_previous = mem->index_reset_ticks; - mem->index_reset_ticks = CoreTiming::GetTicks(); - } - - update_event->Signal(); - - // Reschedule recurrent event - CoreTiming::ScheduleEvent(msToCycles(update_period) - cycles_late, update_callback_id); -} - -/** - * IR::GetHandles service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Translate header, used by the ARM11-kernel - * 3 : Shared memory handle - * 4 : Event handle - */ -static void GetHandles(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x01, 0, 0); - IPC::RequestBuilder rb = rp.MakeBuilder(1, 3); - rb.Push(RESULT_SUCCESS); - rb.PushMoveHandles(Kernel::g_handle_table.Create(Service::IR::shared_memory).Unwrap(), - Kernel::g_handle_table.Create(Service::IR::update_event).Unwrap()); -} - -/** - * IR::Initialize service function - * Inputs: - * 1 : pad state update period in ms - * 2 : bool output raw c-stick data - */ -static void Initialize(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x02, 2, 0); - update_period = static_cast<int>(rp.Pop<u32>()); - raw_c_stick = rp.Pop<bool>(); - - if (raw_c_stick) - LOG_ERROR(Service_IR, "raw C-stick data is not implemented!"); - - next_pad_index = 0; - is_device_reload_pending.store(true); - CoreTiming::ScheduleEvent(msToCycles(update_period), update_callback_id); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_DEBUG(Service_IR, "called. update_period=%d, raw_c_stick=%d", update_period, raw_c_stick); -} - -static void Shutdown(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x03, 1, 0); - - CoreTiming::UnscheduleEvent(update_callback_id, 0); - UnloadInputDevices(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - LOG_DEBUG(Service_IR, "called"); -} - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010000, GetHandles, "GetHandles"}, - {0x00020080, Initialize, "Initialize"}, - {0x00030000, Shutdown, "Shutdown"}, - {0x00090000, nullptr, "WriteToTwoFields"}, -}; - -IR_RST_Interface::IR_RST_Interface() { - Register(FunctionTable); -} - -void InitRST() { - using namespace Kernel; - // Note: these two kernel objects are even available before Initialize service function is - // called. - shared_memory = - SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::Read, - 0, MemoryRegion::BASE, "IRRST:SharedMemory"); - update_event = Event::Create(ResetType::OneShot, "IRRST:UpdateEvent"); - - update_callback_id = CoreTiming::RegisterEvent("IRRST:UpdateCallBack", UpdateCallback); -} - -void ShutdownRST() { - shared_memory = nullptr; - update_event = nullptr; - UnloadInputDevices(); -} - -void ReloadInputDevicesRST() { - is_device_reload_pending.store(true); -} - -} // namespace IR -} // namespace Service diff --git a/src/core/hle/service/ir/ir_rst.h b/src/core/hle/service/ir/ir_rst.h deleted file mode 100644 index d932bb7e5..000000000 --- a/src/core/hle/service/ir/ir_rst.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace IR { - -class IR_RST_Interface : public Service::Interface { -public: - IR_RST_Interface(); - - std::string GetPortName() const override { - return "ir:rst"; - } -}; - -void InitRST(); -void ShutdownRST(); - -/// Reload input devices. Used when input configuration changed -void ReloadInputDevicesRST(); - -} // namespace IR -} // namespace Service diff --git a/src/core/hle/service/ir/ir_u.cpp b/src/core/hle/service/ir/ir_u.cpp deleted file mode 100644 index ce00d5732..000000000 --- a/src/core/hle/service/ir/ir_u.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/ir/ir_u.h" - -namespace Service { -namespace IR { - -const Interface::FunctionInfo FunctionTable[] = { - // clang-format off - {0x00010000, nullptr, "Initialize"}, - {0x00020000, nullptr, "Shutdown"}, - {0x00030042, nullptr, "StartSendTransfer"}, - {0x00040000, nullptr, "WaitSendTransfer"}, - {0x000500C2, nullptr, "StartRecvTransfer"}, - {0x00060000, nullptr, "WaitRecvTransfer"}, - {0x00070080, nullptr, "GetRecvTransferCount"}, - {0x00080000, nullptr, "GetSendState"}, - {0x00090040, nullptr, "SetBitRate"}, - {0x000A0000, nullptr, "GetBitRate"}, - {0x000B0040, nullptr, "SetIRLEDState"}, - {0x000C0000, nullptr, "GetIRLEDRecvState"}, - {0x000D0000, nullptr, "GetSendFinishedEvent"}, - {0x000E0000, nullptr, "GetRecvFinishedEvent"}, - {0x000F0000, nullptr, "GetTransferState"}, - {0x00100000, nullptr, "GetErrorStatus"}, - {0x00110040, nullptr, "SetSleepModeActive"}, - {0x00120040, nullptr, "SetSleepModeState"}, - // clang-format on -}; - -IR_U_Interface::IR_U_Interface() { - Register(FunctionTable); -} - -} // namespace IR -} // namespace Service diff --git a/src/core/hle/service/ir/ir_u.h b/src/core/hle/service/ir/ir_u.h deleted file mode 100644 index 056d2ce1a..000000000 --- a/src/core/hle/service/ir/ir_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace IR { - -class IR_U_Interface : public Service::Interface { -public: - IR_U_Interface(); - - std::string GetPortName() const override { - return "ir:u"; - } -}; - -} // namespace IR -} // namespace Service diff --git a/src/core/hle/service/ir/ir_user.cpp b/src/core/hle/service/ir/ir_user.cpp deleted file mode 100644 index fbdf7a465..000000000 --- a/src/core/hle/service/ir/ir_user.cpp +++ /dev/null @@ -1,558 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <memory> -#include <boost/crc.hpp> -#include <boost/optional.hpp> -#include "common/string_util.h" -#include "common/swap.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/event.h" -#include "core/hle/kernel/shared_memory.h" -#include "core/hle/service/ir/extra_hid.h" -#include "core/hle/service/ir/ir.h" -#include "core/hle/service/ir/ir_user.h" - -namespace Service { -namespace IR { - -// This is a header that will present in the ir:USER shared memory if it is initialized with -// InitializeIrNopShared service function. Otherwise the shared memory doesn't have this header if -// it is initialized with InitializeIrNop service function. -struct SharedMemoryHeader { - u32_le latest_receive_error_result; - u32_le latest_send_error_result; - // TODO(wwylele): for these fields below, make them enum when the meaning of values is known. - u8 connection_status; - u8 trying_to_connect_status; - u8 connection_role; - u8 machine_id; - u8 connected; - u8 network_id; - u8 initialized; - u8 unknown; - - // This is not the end of the shared memory. It is followed by a receive buffer and a send - // buffer. We handle receive buffer in the BufferManager class. For the send buffer, because - // games usually don't access it, we don't emulate it. -}; -static_assert(sizeof(SharedMemoryHeader) == 16, "SharedMemoryHeader has wrong size!"); - -/** - * A manager of the send/receive buffers in the shared memory. Currently it is only used for the - * receive buffer. - * - * A buffer consists of three parts: - * - BufferInfo: stores available count of packets, and their position in the PacketInfo - * circular queue. - * - PacketInfo circular queue: stores the position of each avaiable packets in the Packet data - * buffer. Each entry is a pair of {offset, size}. - * - Packet data circular buffer: stores the actual data of packets. - * - * IR packets can be put into and get from the buffer. - * - * When a new packet is put into the buffer, its data is put into the data circular buffer, - * following the end of previous packet data. A new entry is also added to the PacketInfo circular - * queue pointing to the added packet data. Then BufferInfo is updated. - * - * Packets can be released from the other end of the buffer. When releasing a packet, the front - * entry in thePacketInfo circular queue is removed, and as a result the corresponding memory in the - * data circular buffer is also released. BufferInfo is updated as well. - * - * The client application usually has a similar manager constructed over the same shared memory - * region, performing the same put/get/release operation. This way the client and the service - * communicate via a pair of manager of the same buffer. - * - * TODO(wwylele): implement Get function, which is used by ReceiveIrnop service function. - */ -class BufferManager { -public: - BufferManager(Kernel::SharedPtr<Kernel::SharedMemory> shared_memory_, u32 info_offset_, - u32 buffer_offset_, u32 max_packet_count_, u32 buffer_size) - : shared_memory(shared_memory_), info_offset(info_offset_), buffer_offset(buffer_offset_), - max_packet_count(max_packet_count_), - max_data_size(buffer_size - sizeof(PacketInfo) * max_packet_count_) { - UpdateBufferInfo(); - } - - /** - * Puts a packet to the head of the buffer. - * @params packet The data of the packet to put. - * @returns whether the operation is successful. - */ - bool Put(const std::vector<u8>& packet) { - if (info.packet_count == max_packet_count) - return false; - - u32 write_offset; - - // finds free space offset in data buffer - if (info.packet_count == 0) { - write_offset = 0; - if (packet.size() > max_data_size) - return false; - } else { - const u32 last_index = (info.end_index + max_packet_count - 1) % max_packet_count; - const PacketInfo first = GetPacketInfo(info.begin_index); - const PacketInfo last = GetPacketInfo(last_index); - write_offset = (last.offset + last.size) % max_data_size; - const u32 free_space = (first.offset + max_data_size - write_offset) % max_data_size; - if (packet.size() > free_space) - return false; - } - - // writes packet info - PacketInfo packet_info{write_offset, static_cast<u32>(packet.size())}; - SetPacketInfo(info.end_index, packet_info); - - // writes packet data - for (size_t i = 0; i < packet.size(); ++i) { - *GetDataBufferPointer((write_offset + i) % max_data_size) = packet[i]; - } - - // updates buffer info - info.end_index++; - info.end_index %= max_packet_count; - info.packet_count++; - UpdateBufferInfo(); - return true; - } - - /** - * Release packets from the tail of the buffer - * @params count Numbers of packets to release. - * @returns whether the operation is successful. - */ - bool Release(u32 count) { - if (info.packet_count < count) - return false; - - info.packet_count -= count; - info.begin_index += count; - info.begin_index %= max_packet_count; - UpdateBufferInfo(); - return true; - } - -private: - struct BufferInfo { - u32_le begin_index; - u32_le end_index; - u32_le packet_count; - u32_le unknown; - }; - static_assert(sizeof(BufferInfo) == 16, "BufferInfo has wrong size!"); - - struct PacketInfo { - u32_le offset; - u32_le size; - }; - static_assert(sizeof(PacketInfo) == 8, "PacketInfo has wrong size!"); - - u8* GetPacketInfoPointer(u32 index) { - return shared_memory->GetPointer(buffer_offset + sizeof(PacketInfo) * index); - } - - void SetPacketInfo(u32 index, const PacketInfo& packet_info) { - memcpy(GetPacketInfoPointer(index), &packet_info, sizeof(PacketInfo)); - } - - PacketInfo GetPacketInfo(u32 index) { - PacketInfo packet_info; - memcpy(&packet_info, GetPacketInfoPointer(index), sizeof(PacketInfo)); - return packet_info; - } - - u8* GetDataBufferPointer(u32 offset) { - return shared_memory->GetPointer(buffer_offset + sizeof(PacketInfo) * max_packet_count + - offset); - } - - void UpdateBufferInfo() { - if (info_offset) { - memcpy(shared_memory->GetPointer(info_offset), &info, sizeof(info)); - } - } - - BufferInfo info{0, 0, 0, 0}; - Kernel::SharedPtr<Kernel::SharedMemory> shared_memory; - u32 info_offset; - u32 buffer_offset; - u32 max_packet_count; - u32 max_data_size; -}; - -static Kernel::SharedPtr<Kernel::Event> conn_status_event, send_event, receive_event; -static Kernel::SharedPtr<Kernel::SharedMemory> shared_memory; -static std::unique_ptr<ExtraHID> extra_hid; -static IRDevice* connected_device; -static boost::optional<BufferManager> receive_buffer; - -/// Wraps the payload into packet and puts it to the receive buffer -static void PutToReceive(const std::vector<u8>& payload) { - LOG_TRACE(Service_IR, "called, data=%s", - Common::ArrayToString(payload.data(), payload.size()).c_str()); - size_t size = payload.size(); - - std::vector<u8> packet; - - // Builds packet header. For the format info: - // https://www.3dbrew.org/wiki/IRUSER_Shared_Memory#Packet_structure - - // fixed value - packet.push_back(0xA5); - // destination network ID - u8 network_id = *(shared_memory->GetPointer(offsetof(SharedMemoryHeader, network_id))); - packet.push_back(network_id); - - // puts the size info. - // The highest bit of the first byte is unknown, which is set to zero here. The second highest - // bit is a flag that determines whether the size info is in extended form. If the packet size - // can be represent within 6 bits, the short form (1 byte) of size info is chosen, the size is - // put to the lower bits of this byte, and the flag is clear. If the packet size cannot be - // represent within 6 bits, the extended form (2 bytes) is chosen, the lower 8 bits of the size - // is put to the second byte, the higher bits of the size is put to the lower bits of the first - // byte, and the flag is set. Note that the packet size must be within 14 bits due to this - // format restriction, or it will overlap with the flag bit. - if (size < 0x40) { - packet.push_back(static_cast<u8>(size)); - } else if (size < 0x4000) { - packet.push_back(static_cast<u8>(size >> 8) | 0x40); - packet.push_back(static_cast<u8>(size)); - } else { - ASSERT(false); - } - - // puts the payload - packet.insert(packet.end(), payload.begin(), payload.end()); - - // calculates CRC and puts to the end - packet.push_back(boost::crc<8, 0x07, 0, 0, false, false>(packet.data(), packet.size())); - - if (receive_buffer->Put(packet)) { - receive_event->Signal(); - } else { - LOG_ERROR(Service_IR, "receive buffer is full!"); - } -} - -/** - * IR::InitializeIrNopShared service function - * Initializes ir:USER service with a user provided shared memory. The shared memory is configured - * to shared mode (with SharedMemoryHeader at the beginning of the shared memory). - * Inputs: - * 1 : Size of shared memory - * 2 : Recv buffer size - * 3 : Recv buffer packet count - * 4 : Send buffer size - * 5 : Send buffer packet count - * 6 : BaudRate (u8) - * 7 : 0 (Handle descriptor) - * 8 : Handle of shared memory - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void InitializeIrNopShared(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x18, 6, 2); - const u32 shared_buff_size = rp.Pop<u32>(); - const u32 recv_buff_size = rp.Pop<u32>(); - const u32 recv_buff_packet_count = rp.Pop<u32>(); - const u32 send_buff_size = rp.Pop<u32>(); - const u32 send_buff_packet_count = rp.Pop<u32>(); - const u8 baud_rate = rp.Pop<u8>(); - const Kernel::Handle handle = rp.PopHandle(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle); - if (!shared_memory) { - LOG_CRITICAL(Service_IR, "invalid shared memory handle 0x%08X", handle); - rb.Push(IPC::ERR_INVALID_HANDLE); - return; - } - shared_memory->name = "IR_USER: shared memory"; - - receive_buffer = - BufferManager(shared_memory, 0x10, 0x20, recv_buff_packet_count, recv_buff_size); - SharedMemoryHeader shared_memory_init{}; - shared_memory_init.initialized = 1; - std::memcpy(shared_memory->GetPointer(), &shared_memory_init, sizeof(SharedMemoryHeader)); - - rb.Push(RESULT_SUCCESS); - - LOG_INFO(Service_IR, "called, shared_buff_size=%u, recv_buff_size=%u, " - "recv_buff_packet_count=%u, send_buff_size=%u, " - "send_buff_packet_count=%u, baud_rate=%u, handle=0x%08X", - shared_buff_size, recv_buff_size, recv_buff_packet_count, send_buff_size, - send_buff_packet_count, baud_rate, handle); -} - -/** - * IR::RequireConnection service function - * Searches for an IR device and connects to it. After connecting to the device, applications can - * use SendIrNop function, ReceiveIrNop function (or read from the buffer directly) to communicate - * with the device. - * Inputs: - * 1 : device ID? always 1 for circle pad pro - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void RequireConnection(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x06, 1, 0); - const u8 device_id = rp.Pop<u8>(); - - u8* shared_memory_ptr = shared_memory->GetPointer(); - if (device_id == 1) { - // These values are observed on a New 3DS. The meaning of them is unclear. - // TODO (wwylele): should assign network_id a (random?) number - shared_memory_ptr[offsetof(SharedMemoryHeader, connection_status)] = 2; - shared_memory_ptr[offsetof(SharedMemoryHeader, connection_role)] = 2; - shared_memory_ptr[offsetof(SharedMemoryHeader, connected)] = 1; - - connected_device = extra_hid.get(); - connected_device->OnConnect(); - conn_status_event->Signal(); - } else { - LOG_WARNING(Service_IR, "unknown device id %u. Won't connect.", device_id); - shared_memory_ptr[offsetof(SharedMemoryHeader, connection_status)] = 1; - shared_memory_ptr[offsetof(SharedMemoryHeader, trying_to_connect_status)] = 2; - } - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_INFO(Service_IR, "called, device_id = %u", device_id); -} - -/** - * IR::GetReceiveEvent service function - * Gets an event that is signaled when a packet is received from the IR device. - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : 0 (Handle descriptor) - * 3 : Receive event handle - */ -void GetReceiveEvent(Interface* self) { - IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0A, 1, 2); - - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::receive_event).Unwrap()); - - LOG_INFO(Service_IR, "called"); -} - -/** - * IR::GetSendEvent service function - * Gets an event that is signaled when the sending of a packet is complete - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : 0 (Handle descriptor) - * 3 : Send event handle - */ -void GetSendEvent(Interface* self) { - IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0B, 1, 2); - - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::send_event).Unwrap()); - - LOG_INFO(Service_IR, "called"); -} - -/** - * IR::Disconnect service function - * Disconnects from the current connected IR device. - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void Disconnect(Interface* self) { - if (connected_device) { - connected_device->OnDisconnect(); - connected_device = nullptr; - conn_status_event->Signal(); - } - - u8* shared_memory_ptr = shared_memory->GetPointer(); - shared_memory_ptr[offsetof(SharedMemoryHeader, connection_status)] = 0; - shared_memory_ptr[offsetof(SharedMemoryHeader, connected)] = 0; - - IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x09, 1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_INFO(Service_IR, "called"); -} - -/** - * IR::GetConnectionStatusEvent service function - * Gets an event that is signaled when the connection status is changed - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : 0 (Handle descriptor) - * 3 : Connection Status Event handle - */ -static void GetConnectionStatusEvent(Interface* self) { - IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0C, 1, 2); - - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::conn_status_event).Unwrap()); - - LOG_INFO(Service_IR, "called"); -} - -/** - * IR::FinalizeIrNop service function - * Finalize ir:USER service. - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void FinalizeIrNop(Interface* self) { - if (connected_device) { - connected_device->OnDisconnect(); - connected_device = nullptr; - } - - shared_memory = nullptr; - receive_buffer = boost::none; - - IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x02, 1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_INFO(Service_IR, "called"); -} - -/** - * IR::SendIrNop service function - * Sends a packet to the connected IR device - * Inpus: - * 1 : Size of data to send - * 2 : 2 + (size << 14) (Static buffer descriptor) - * 3 : Data buffer address - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void SendIrNop(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0D, 1, 2); - const u32 size = rp.Pop<u32>(); - const VAddr address = rp.PopStaticBuffer(); - - std::vector<u8> buffer(size); - Memory::ReadBlock(address, buffer.data(), size); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (connected_device) { - connected_device->OnReceive(buffer); - send_event->Signal(); - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_IR, "not connected"); - rb.Push(ResultCode(static_cast<ErrorDescription>(13), ErrorModule::IR, - ErrorSummary::InvalidState, ErrorLevel::Status)); - } - - LOG_TRACE(Service_IR, "called, data=%s", Common::ArrayToString(buffer.data(), size).c_str()); -} - -/** - * IR::ReleaseReceivedData function - * Release a specified amount of packet from the receive buffer. This is called after the - * application reads received packet from the buffer directly, to release the buffer space for - * future packets. - * Inpus: - * 1 : Number of packets to release - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void ReleaseReceivedData(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x19, 1, 0); - u32 count = rp.Pop<u32>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - if (receive_buffer->Release(count)) { - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_IR, "failed to release %u packets", count); - rb.Push(ResultCode(ErrorDescription::NoData, ErrorModule::IR, ErrorSummary::NotFound, - ErrorLevel::Status)); - } - - LOG_TRACE(Service_IR, "called, count=%u", count); -} - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010182, nullptr, "InitializeIrNop"}, - {0x00020000, FinalizeIrNop, "FinalizeIrNop"}, - {0x00030000, nullptr, "ClearReceiveBuffer"}, - {0x00040000, nullptr, "ClearSendBuffer"}, - {0x000500C0, nullptr, "WaitConnection"}, - {0x00060040, RequireConnection, "RequireConnection"}, - {0x000702C0, nullptr, "AutoConnection"}, - {0x00080000, nullptr, "AnyConnection"}, - {0x00090000, Disconnect, "Disconnect"}, - {0x000A0000, GetReceiveEvent, "GetReceiveEvent"}, - {0x000B0000, GetSendEvent, "GetSendEvent"}, - {0x000C0000, GetConnectionStatusEvent, "GetConnectionStatusEvent"}, - {0x000D0042, SendIrNop, "SendIrNop"}, - {0x000E0042, nullptr, "SendIrNopLarge"}, - {0x000F0040, nullptr, "ReceiveIrnop"}, - {0x00100042, nullptr, "ReceiveIrnopLarge"}, - {0x00110040, nullptr, "GetLatestReceiveErrorResult"}, - {0x00120040, nullptr, "GetLatestSendErrorResult"}, - {0x00130000, nullptr, "GetConnectionStatus"}, - {0x00140000, nullptr, "GetTryingToConnectStatus"}, - {0x00150000, nullptr, "GetReceiveSizeFreeAndUsed"}, - {0x00160000, nullptr, "GetSendSizeFreeAndUsed"}, - {0x00170000, nullptr, "GetConnectionRole"}, - {0x00180182, InitializeIrNopShared, "InitializeIrNopShared"}, - {0x00190040, ReleaseReceivedData, "ReleaseReceivedData"}, - {0x001A0040, nullptr, "SetOwnMachineId"}, -}; - -IR_User_Interface::IR_User_Interface() { - Register(FunctionTable); -} - -void InitUser() { - using namespace Kernel; - - shared_memory = nullptr; - - conn_status_event = Event::Create(ResetType::OneShot, "IR:ConnectionStatusEvent"); - send_event = Event::Create(ResetType::OneShot, "IR:SendEvent"); - receive_event = Event::Create(ResetType::OneShot, "IR:ReceiveEvent"); - - receive_buffer = boost::none; - - extra_hid = std::make_unique<ExtraHID>(PutToReceive); - - connected_device = nullptr; -} - -void ShutdownUser() { - if (connected_device) { - connected_device->OnDisconnect(); - connected_device = nullptr; - } - - extra_hid = nullptr; - receive_buffer = boost::none; - shared_memory = nullptr; - conn_status_event = nullptr; - send_event = nullptr; - receive_event = nullptr; -} - -void ReloadInputDevicesUser() { - if (extra_hid) - extra_hid->RequestInputDevicesReload(); -} - -IRDevice::IRDevice(SendFunc send_func_) : send_func(send_func_) {} -IRDevice::~IRDevice() = default; - -void IRDevice::Send(const std::vector<u8>& data) { - send_func(data); -} - -} // namespace IR -} // namespace Service diff --git a/src/core/hle/service/ir/ir_user.h b/src/core/hle/service/ir/ir_user.h deleted file mode 100644 index 930650406..000000000 --- a/src/core/hle/service/ir/ir_user.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <functional> -#include "core/hle/service/service.h" - -namespace Service { -namespace IR { - -/// An interface representing a device that can communicate with 3DS via ir:USER service -class IRDevice { -public: - /** - * A function object that implements the method to send data to the 3DS, which takes a vector of - * data to send. - */ - using SendFunc = std::function<void(const std::vector<u8>& data)>; - - explicit IRDevice(SendFunc send_func); - virtual ~IRDevice(); - - /// Called when connected with 3DS - virtual void OnConnect() = 0; - - /// Called when disconnected from 3DS - virtual void OnDisconnect() = 0; - - /// Called when data is received from the 3DS. This is invoked by the ir:USER send function. - virtual void OnReceive(const std::vector<u8>& data) = 0; - -protected: - /// Sends data to the 3DS. The actual sending method is specified in the constructor - void Send(const std::vector<u8>& data); - -private: - const SendFunc send_func; -}; - -class IR_User_Interface : public Service::Interface { -public: - IR_User_Interface(); - - std::string GetPortName() const override { - return "ir:USER"; - } -}; - -void InitUser(); -void ShutdownUser(); - -/// Reload input devices. Used when input configuration changed -void ReloadInputDevicesUser(); - -} // namespace IR -} // namespace Service diff --git a/src/core/hle/service/ldr_ro/cro_helper.cpp b/src/core/hle/service/ldr_ro/cro_helper.cpp deleted file mode 100644 index 6128f8a6c..000000000 --- a/src/core/hle/service/ldr_ro/cro_helper.cpp +++ /dev/null @@ -1,1495 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/alignment.h" -#include "common/logging/log.h" -#include "common/scope_exit.h" -#include "core/hle/service/ldr_ro/cro_helper.h" - -namespace Service { -namespace LDR { - -static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F - ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, - ErrorLevel::Usage); - -static ResultCode CROFormatError(u32 description) { - return ResultCode(static_cast<ErrorDescription>(description), ErrorModule::RO, - ErrorSummary::WrongArgument, ErrorLevel::Permanent); -} - -const std::array<int, 17> CROHelper::ENTRY_SIZE{{ - 1, // code - 1, // data - 1, // module name - sizeof(SegmentEntry), sizeof(ExportNamedSymbolEntry), sizeof(ExportIndexedSymbolEntry), - 1, // export strings - sizeof(ExportTreeEntry), sizeof(ImportModuleEntry), sizeof(ExternalRelocationEntry), - sizeof(ImportNamedSymbolEntry), sizeof(ImportIndexedSymbolEntry), - sizeof(ImportAnonymousSymbolEntry), - 1, // import strings - sizeof(StaticAnonymousSymbolEntry), sizeof(InternalRelocationEntry), - sizeof(StaticRelocationEntry), -}}; - -const std::array<CROHelper::HeaderField, 4> CROHelper::FIX_BARRIERS{{ - Fix0Barrier, Fix1Barrier, Fix2Barrier, Fix3Barrier, -}}; - -VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const { - u32 segment_num = GetField(SegmentNum); - - if (segment_tag.segment_index >= segment_num) - return 0; - - SegmentEntry entry; - GetEntry(segment_tag.segment_index, entry); - - if (segment_tag.offset_into_segment >= entry.size) - return 0; - - return entry.offset + segment_tag.offset_into_segment; -} - -ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType relocation_type, - u32 addend, u32 symbol_address, u32 target_future_address) { - - switch (relocation_type) { - case RelocationType::Nothing: - break; - case RelocationType::AbsoluteAddress: - case RelocationType::AbsoluteAddress2: - Memory::Write32(target_address, symbol_address + addend); - break; - case RelocationType::RelativeAddress: - Memory::Write32(target_address, symbol_address + addend - target_future_address); - break; - case RelocationType::ThumbBranch: - case RelocationType::ArmBranch: - case RelocationType::ModifyArmBranch: - case RelocationType::AlignedRelativeAddress: - // TODO(wwylele): implement other types - UNIMPLEMENTED(); - break; - default: - return CROFormatError(0x22); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ClearRelocation(VAddr target_address, RelocationType relocation_type) { - switch (relocation_type) { - case RelocationType::Nothing: - break; - case RelocationType::AbsoluteAddress: - case RelocationType::AbsoluteAddress2: - case RelocationType::RelativeAddress: - Memory::Write32(target_address, 0); - break; - case RelocationType::ThumbBranch: - case RelocationType::ArmBranch: - case RelocationType::ModifyArmBranch: - case RelocationType::AlignedRelativeAddress: - // TODO(wwylele): implement other types - UNIMPLEMENTED(); - break; - default: - return CROFormatError(0x22); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset) { - if (symbol_address == 0 && !reset) - return CROFormatError(0x10); - - VAddr relocation_address = batch; - while (true) { - RelocationEntry relocation; - Memory::ReadBlock(relocation_address, &relocation, sizeof(RelocationEntry)); - - VAddr relocation_target = SegmentTagToAddress(relocation.target_position); - if (relocation_target == 0) { - return CROFormatError(0x12); - } - - ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, - symbol_address, relocation_target); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); - return result; - } - - if (relocation.is_batch_end) - break; - - relocation_address += sizeof(RelocationEntry); - } - - RelocationEntry relocation; - Memory::ReadBlock(batch, &relocation, sizeof(RelocationEntry)); - relocation.is_batch_resolved = reset ? 0 : 1; - Memory::WriteBlock(batch, &relocation, sizeof(RelocationEntry)); - return RESULT_SUCCESS; -} - -VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const { - if (!GetField(ExportTreeNum)) - return 0; - - std::size_t len = name.size(); - ExportTreeEntry entry; - GetEntry(0, entry); - ExportTreeEntry::Child next; - next.raw = entry.left.raw; - u32 found_id; - - while (true) { - GetEntry(next.next_index, entry); - - if (next.is_end) { - found_id = entry.export_table_index; - break; - } - - u16 test_byte = entry.test_bit >> 3; - u16 test_bit_in_byte = entry.test_bit & 7; - - if (test_byte >= len) { - next.raw = entry.left.raw; - } else if ((name[test_byte] >> test_bit_in_byte) & 1) { - next.raw = entry.right.raw; - } else { - next.raw = entry.left.raw; - } - } - - u32 export_named_symbol_num = GetField(ExportNamedSymbolNum); - - if (found_id >= export_named_symbol_num) - return 0; - - u32 export_strings_size = GetField(ExportStringsSize); - ExportNamedSymbolEntry symbol_entry; - GetEntry(found_id, symbol_entry); - - if (Memory::ReadCString(symbol_entry.name_offset, export_strings_size) != name) - return 0; - - return SegmentTagToAddress(symbol_entry.symbol_position); -} - -ResultCode CROHelper::RebaseHeader(u32 cro_size) { - ResultCode error = CROFormatError(0x11); - - // verifies magic - if (GetField(Magic) != MAGIC_CRO0) - return error; - - // verifies not registered - if (GetField(NextCRO) != 0 || GetField(PreviousCRO) != 0) - return error; - - // This seems to be a hard limit set by the RO module - if (GetField(FileSize) > 0x10000000 || GetField(BssSize) > 0x10000000) - return error; - - // verifies not fixed - if (GetField(FixedSize) != 0) - return error; - - if (GetField(CodeOffset) < CRO_HEADER_SIZE) - return error; - - // verifies that all offsets are in the correct order - constexpr std::array<HeaderField, 18> OFFSET_ORDER = {{ - CodeOffset, ModuleNameOffset, SegmentTableOffset, ExportNamedSymbolTableOffset, - ExportTreeTableOffset, ExportIndexedSymbolTableOffset, ExportStringsOffset, - ImportModuleTableOffset, ExternalRelocationTableOffset, ImportNamedSymbolTableOffset, - ImportIndexedSymbolTableOffset, ImportAnonymousSymbolTableOffset, ImportStringsOffset, - StaticAnonymousSymbolTableOffset, InternalRelocationTableOffset, - StaticRelocationTableOffset, DataOffset, FileSize, - }}; - - u32 prev_offset = GetField(OFFSET_ORDER[0]); - u32 cur_offset; - for (std::size_t i = 1; i < OFFSET_ORDER.size(); ++i) { - cur_offset = GetField(OFFSET_ORDER[i]); - if (cur_offset < prev_offset) - return error; - prev_offset = cur_offset; - } - - // rebases offsets - u32 offset = GetField(NameOffset); - if (offset != 0) - SetField(NameOffset, offset + module_address); - - for (int field = CodeOffset; field < Fix0Barrier; field += 2) { - HeaderField header_field = static_cast<HeaderField>(field); - offset = GetField(header_field); - if (offset != 0) - SetField(header_field, offset + module_address); - } - - // verifies everything is not beyond the buffer - u32 file_end = module_address + cro_size; - for (int field = CodeOffset, i = 0; field < Fix0Barrier; field += 2, ++i) { - HeaderField offset_field = static_cast<HeaderField>(field); - HeaderField size_field = static_cast<HeaderField>(field + 1); - if (GetField(offset_field) + GetField(size_field) * ENTRY_SIZE[i] > file_end) - return error; - } - - return RESULT_SUCCESS; -} - -ResultVal<VAddr> CROHelper::RebaseSegmentTable(u32 cro_size, VAddr data_segment_address, - u32 data_segment_size, VAddr bss_segment_address, - u32 bss_segment_size) { - - u32 prev_data_segment = 0; - u32 segment_num = GetField(SegmentNum); - for (u32 i = 0; i < segment_num; ++i) { - SegmentEntry segment; - GetEntry(i, segment); - if (segment.type == SegmentType::Data) { - if (segment.size != 0) { - if (segment.size > data_segment_size) - return ERROR_BUFFER_TOO_SMALL; - prev_data_segment = segment.offset; - segment.offset = data_segment_address; - } - } else if (segment.type == SegmentType::BSS) { - if (segment.size != 0) { - if (segment.size > bss_segment_size) - return ERROR_BUFFER_TOO_SMALL; - segment.offset = bss_segment_address; - } - } else if (segment.offset != 0) { - segment.offset += module_address; - if (segment.offset > module_address + cro_size) - return CROFormatError(0x19); - } - SetEntry(i, segment); - } - return MakeResult<VAddr>(prev_data_segment + module_address); -} - -ResultCode CROHelper::RebaseExportNamedSymbolTable() { - VAddr export_strings_offset = GetField(ExportStringsOffset); - VAddr export_strings_end = export_strings_offset + GetField(ExportStringsSize); - - u32 export_named_symbol_num = GetField(ExportNamedSymbolNum); - for (u32 i = 0; i < export_named_symbol_num; ++i) { - ExportNamedSymbolEntry entry; - GetEntry(i, entry); - - if (entry.name_offset != 0) { - entry.name_offset += module_address; - if (entry.name_offset < export_strings_offset || - entry.name_offset >= export_strings_end) { - return CROFormatError(0x11); - } - } - - SetEntry(i, entry); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::VerifyExportTreeTable() const { - u32 tree_num = GetField(ExportTreeNum); - for (u32 i = 0; i < tree_num; ++i) { - ExportTreeEntry entry; - GetEntry(i, entry); - - if (entry.left.next_index >= tree_num || entry.right.next_index >= tree_num) { - return CROFormatError(0x11); - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::RebaseImportModuleTable() { - VAddr import_strings_offset = GetField(ImportStringsOffset); - VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); - VAddr import_indexed_symbol_table_offset = GetField(ImportIndexedSymbolTableOffset); - VAddr index_import_table_end = - import_indexed_symbol_table_offset + - GetField(ImportIndexedSymbolNum) * sizeof(ImportIndexedSymbolEntry); - VAddr import_anonymous_symbol_table_offset = GetField(ImportAnonymousSymbolTableOffset); - VAddr offset_import_table_end = - import_anonymous_symbol_table_offset + - GetField(ImportAnonymousSymbolNum) * sizeof(ImportAnonymousSymbolEntry); - - u32 module_num = GetField(ImportModuleNum); - for (u32 i = 0; i < module_num; ++i) { - ImportModuleEntry entry; - GetEntry(i, entry); - - if (entry.name_offset != 0) { - entry.name_offset += module_address; - if (entry.name_offset < import_strings_offset || - entry.name_offset >= import_strings_end) { - return CROFormatError(0x18); - } - } - - if (entry.import_indexed_symbol_table_offset != 0) { - entry.import_indexed_symbol_table_offset += module_address; - if (entry.import_indexed_symbol_table_offset < import_indexed_symbol_table_offset || - entry.import_indexed_symbol_table_offset > index_import_table_end) { - return CROFormatError(0x18); - } - } - - if (entry.import_anonymous_symbol_table_offset != 0) { - entry.import_anonymous_symbol_table_offset += module_address; - if (entry.import_anonymous_symbol_table_offset < import_anonymous_symbol_table_offset || - entry.import_anonymous_symbol_table_offset > offset_import_table_end) { - return CROFormatError(0x18); - } - } - - SetEntry(i, entry); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::RebaseImportNamedSymbolTable() { - VAddr import_strings_offset = GetField(ImportStringsOffset); - VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); - VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); - VAddr external_relocation_table_end = - external_relocation_table_offset + - GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); - - u32 num = GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < num; ++i) { - ImportNamedSymbolEntry entry; - GetEntry(i, entry); - - if (entry.name_offset != 0) { - entry.name_offset += module_address; - if (entry.name_offset < import_strings_offset || - entry.name_offset >= import_strings_end) { - return CROFormatError(0x1B); - } - } - - if (entry.relocation_batch_offset != 0) { - entry.relocation_batch_offset += module_address; - if (entry.relocation_batch_offset < external_relocation_table_offset || - entry.relocation_batch_offset > external_relocation_table_end) { - return CROFormatError(0x1B); - } - } - - SetEntry(i, entry); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::RebaseImportIndexedSymbolTable() { - VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); - VAddr external_relocation_table_end = - external_relocation_table_offset + - GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); - - u32 num = GetField(ImportIndexedSymbolNum); - for (u32 i = 0; i < num; ++i) { - ImportIndexedSymbolEntry entry; - GetEntry(i, entry); - - if (entry.relocation_batch_offset != 0) { - entry.relocation_batch_offset += module_address; - if (entry.relocation_batch_offset < external_relocation_table_offset || - entry.relocation_batch_offset > external_relocation_table_end) { - return CROFormatError(0x14); - } - } - - SetEntry(i, entry); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::RebaseImportAnonymousSymbolTable() { - VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); - VAddr external_relocation_table_end = - external_relocation_table_offset + - GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); - - u32 num = GetField(ImportAnonymousSymbolNum); - for (u32 i = 0; i < num; ++i) { - ImportAnonymousSymbolEntry entry; - GetEntry(i, entry); - - if (entry.relocation_batch_offset != 0) { - entry.relocation_batch_offset += module_address; - if (entry.relocation_batch_offset < external_relocation_table_offset || - entry.relocation_batch_offset > external_relocation_table_end) { - return CROFormatError(0x17); - } - } - - SetEntry(i, entry); - } - return RESULT_SUCCESS; -} - -VAddr CROHelper::GetOnUnresolvedAddress() { - return SegmentTagToAddress(SegmentTag(GetField(OnUnresolvedSegmentTag))); -} - -ResultCode CROHelper::ResetExternalRelocations() { - u32 unresolved_symbol = GetOnUnresolvedAddress(); - u32 external_relocation_num = GetField(ExternalRelocationNum); - ExternalRelocationEntry relocation; - - // Verifies that the last relocation is the end of a batch - GetEntry(external_relocation_num - 1, relocation); - if (!relocation.is_batch_end) { - return CROFormatError(0x12); - } - - bool batch_begin = true; - for (u32 i = 0; i < external_relocation_num; ++i) { - GetEntry(i, relocation); - VAddr relocation_target = SegmentTagToAddress(relocation.target_position); - - if (relocation_target == 0) { - return CROFormatError(0x12); - } - - ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, - unresolved_symbol, relocation_target); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); - return result; - } - - if (batch_begin) { - // resets to unresolved state - relocation.is_batch_resolved = 0; - SetEntry(i, relocation); - } - - // if current is an end, then the next is a beginning - batch_begin = relocation.is_batch_end != 0; - } - - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ClearExternalRelocations() { - u32 external_relocation_num = GetField(ExternalRelocationNum); - ExternalRelocationEntry relocation; - - bool batch_begin = true; - for (u32 i = 0; i < external_relocation_num; ++i) { - GetEntry(i, relocation); - VAddr relocation_target = SegmentTagToAddress(relocation.target_position); - - if (relocation_target == 0) { - return CROFormatError(0x12); - } - - ResultCode result = ClearRelocation(relocation_target, relocation.type); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error clearing relocation %08X", result.raw); - return result; - } - - if (batch_begin) { - // resets to unresolved state - relocation.is_batch_resolved = 0; - SetEntry(i, relocation); - } - - // if current is an end, then the next is a beginning - batch_begin = relocation.is_batch_end != 0; - } - - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) { - VAddr static_relocation_table_offset = GetField(StaticRelocationTableOffset); - VAddr static_relocation_table_end = - static_relocation_table_offset + - GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry); - - CROHelper crs(crs_address); - u32 offset_export_num = GetField(StaticAnonymousSymbolNum); - LOG_INFO(Service_LDR, "CRO \"%s\" exports %d static anonymous symbols", ModuleName().data(), - offset_export_num); - for (u32 i = 0; i < offset_export_num; ++i) { - StaticAnonymousSymbolEntry entry; - GetEntry(i, entry); - u32 batch_address = entry.relocation_batch_offset + module_address; - - if (batch_address < static_relocation_table_offset || - batch_address > static_relocation_table_end) { - return CROFormatError(0x16); - } - - u32 symbol_address = SegmentTagToAddress(entry.symbol_position); - LOG_TRACE(Service_LDR, "CRO \"%s\" exports 0x%08X to the static module", - ModuleName().data(), symbol_address); - ResultCode result = crs.ApplyRelocationBatch(batch_address, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) { - u32 segment_num = GetField(SegmentNum); - u32 internal_relocation_num = GetField(InternalRelocationNum); - for (u32 i = 0; i < internal_relocation_num; ++i) { - InternalRelocationEntry relocation; - GetEntry(i, relocation); - VAddr target_addressB = SegmentTagToAddress(relocation.target_position); - if (target_addressB == 0) { - return CROFormatError(0x15); - } - - VAddr target_address; - SegmentEntry target_segment; - GetEntry(relocation.target_position.segment_index, target_segment); - - if (target_segment.type == SegmentType::Data) { - // If the relocation is to the .data segment, we need to relocate it in the old buffer - target_address = - old_data_segment_address + relocation.target_position.offset_into_segment; - } else { - target_address = target_addressB; - } - - if (relocation.symbol_segment >= segment_num) { - return CROFormatError(0x15); - } - - SegmentEntry symbol_segment; - GetEntry(relocation.symbol_segment, symbol_segment); - LOG_TRACE(Service_LDR, "Internally relocates 0x%08X with 0x%08X", target_address, - symbol_segment.offset); - ResultCode result = ApplyRelocation(target_address, relocation.type, relocation.addend, - symbol_segment.offset, target_addressB); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); - return result; - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ClearInternalRelocations() { - u32 internal_relocation_num = GetField(InternalRelocationNum); - for (u32 i = 0; i < internal_relocation_num; ++i) { - InternalRelocationEntry relocation; - GetEntry(i, relocation); - VAddr target_address = SegmentTagToAddress(relocation.target_position); - - if (target_address == 0) { - return CROFormatError(0x15); - } - - ResultCode result = ClearRelocation(target_address, relocation.type); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error clearing relocation %08X", result.raw); - return result; - } - } - return RESULT_SUCCESS; -} - -void CROHelper::UnrebaseImportAnonymousSymbolTable() { - u32 num = GetField(ImportAnonymousSymbolNum); - for (u32 i = 0; i < num; ++i) { - ImportAnonymousSymbolEntry entry; - GetEntry(i, entry); - - if (entry.relocation_batch_offset != 0) { - entry.relocation_batch_offset -= module_address; - } - - SetEntry(i, entry); - } -} - -void CROHelper::UnrebaseImportIndexedSymbolTable() { - u32 num = GetField(ImportIndexedSymbolNum); - for (u32 i = 0; i < num; ++i) { - ImportIndexedSymbolEntry entry; - GetEntry(i, entry); - - if (entry.relocation_batch_offset != 0) { - entry.relocation_batch_offset -= module_address; - } - - SetEntry(i, entry); - } -} - -void CROHelper::UnrebaseImportNamedSymbolTable() { - u32 num = GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < num; ++i) { - ImportNamedSymbolEntry entry; - GetEntry(i, entry); - - if (entry.name_offset != 0) { - entry.name_offset -= module_address; - } - - if (entry.relocation_batch_offset) { - entry.relocation_batch_offset -= module_address; - } - - SetEntry(i, entry); - } -} - -void CROHelper::UnrebaseImportModuleTable() { - u32 module_num = GetField(ImportModuleNum); - for (u32 i = 0; i < module_num; ++i) { - ImportModuleEntry entry; - GetEntry(i, entry); - - if (entry.name_offset != 0) { - entry.name_offset -= module_address; - } - - if (entry.import_indexed_symbol_table_offset) { - entry.import_indexed_symbol_table_offset -= module_address; - } - - if (entry.import_anonymous_symbol_table_offset) { - entry.import_anonymous_symbol_table_offset -= module_address; - } - - SetEntry(i, entry); - } -} - -void CROHelper::UnrebaseExportNamedSymbolTable() { - u32 export_named_symbol_num = GetField(ExportNamedSymbolNum); - for (u32 i = 0; i < export_named_symbol_num; ++i) { - ExportNamedSymbolEntry entry; - GetEntry(i, entry); - - if (entry.name_offset != 0) { - entry.name_offset -= module_address; - } - - SetEntry(i, entry); - } -} - -void CROHelper::UnrebaseSegmentTable() { - u32 segment_num = GetField(SegmentNum); - for (u32 i = 0; i < segment_num; ++i) { - SegmentEntry segment; - GetEntry(i, segment); - - if (segment.type == SegmentType::BSS) { - segment.offset = 0; - } else if (segment.offset != 0) { - segment.offset -= module_address; - } - - SetEntry(i, segment); - } -} - -void CROHelper::UnrebaseHeader() { - u32 offset = GetField(NameOffset); - if (offset != 0) - SetField(NameOffset, offset - module_address); - - for (int field = CodeOffset; field < Fix0Barrier; field += 2) { - HeaderField header_field = static_cast<HeaderField>(field); - offset = GetField(header_field); - if (offset != 0) - SetField(header_field, offset - module_address); - } -} - -ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) { - u32 import_strings_size = GetField(ImportStringsSize); - u32 symbol_import_num = GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < symbol_import_num; ++i) { - ImportNamedSymbolEntry entry; - GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - if (!relocation_entry.is_batch_resolved) { - ResultCode result = - ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { - std::string symbol_name = - Memory::ReadCString(entry.name_offset, import_strings_size); - u32 symbol_address = source.FindExportNamedSymbol(symbol_name); - - if (symbol_address != 0) { - LOG_TRACE(Service_LDR, "CRO \"%s\" imports \"%s\" from \"%s\"", - ModuleName().data(), symbol_name.data(), - source.ModuleName().data()); - - ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", - result.raw); - return result; - } - - return MakeResult<bool>(false); - } - - return MakeResult<bool>(true); - }); - if (result.IsError()) { - return result; - } - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ResetImportNamedSymbol() { - u32 unresolved_symbol = GetOnUnresolvedAddress(); - - u32 symbol_import_num = GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < symbol_import_num; ++i) { - ImportNamedSymbolEntry entry; - GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw); - return result; - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ResetImportIndexedSymbol() { - u32 unresolved_symbol = GetOnUnresolvedAddress(); - - u32 import_num = GetField(ImportIndexedSymbolNum); - for (u32 i = 0; i < import_num; ++i) { - ImportIndexedSymbolEntry entry; - GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw); - return result; - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ResetImportAnonymousSymbol() { - u32 unresolved_symbol = GetOnUnresolvedAddress(); - - u32 import_num = GetField(ImportAnonymousSymbolNum); - for (u32 i = 0; i < import_num; ++i) { - ImportAnonymousSymbolEntry entry; - GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw); - return result; - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) { - u32 import_strings_size = GetField(ImportStringsSize); - - u32 import_module_num = GetField(ImportModuleNum); - for (u32 i = 0; i < import_module_num; ++i) { - ImportModuleEntry entry; - GetEntry(i, entry); - std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size); - - ResultCode result = - ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { - if (want_cro_name == source.ModuleName()) { - LOG_INFO(Service_LDR, "CRO \"%s\" imports %d indexed symbols from \"%s\"", - ModuleName().data(), entry.import_indexed_symbol_num, - source.ModuleName().data()); - for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { - ImportIndexedSymbolEntry im; - entry.GetImportIndexedSymbolEntry(j, im); - ExportIndexedSymbolEntry ex; - source.GetEntry(im.index, ex); - u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position); - LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); - ResultCode result = - ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", - result.raw); - return result; - } - } - LOG_INFO(Service_LDR, "CRO \"%s\" imports %d anonymous symbols from \"%s\"", - ModuleName().data(), entry.import_anonymous_symbol_num, - source.ModuleName().data()); - for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { - ImportAnonymousSymbolEntry im; - entry.GetImportAnonymousSymbolEntry(j, im); - u32 symbol_address = source.SegmentTagToAddress(im.symbol_position); - LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); - ResultCode result = - ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", - result.raw); - return result; - } - } - return MakeResult<bool>(false); - } - return MakeResult<bool>(true); - }); - if (result.IsError()) { - return result; - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) { - LOG_DEBUG(Service_LDR, "CRO \"%s\" exports named symbols to \"%s\"", ModuleName().data(), - target.ModuleName().data()); - u32 target_import_strings_size = target.GetField(ImportStringsSize); - u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < target_symbol_import_num; ++i) { - ImportNamedSymbolEntry entry; - target.GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - if (!relocation_entry.is_batch_resolved) { - std::string symbol_name = - Memory::ReadCString(entry.name_offset, target_import_strings_size); - u32 symbol_address = FindExportNamedSymbol(symbol_name); - if (symbol_address != 0) { - LOG_TRACE(Service_LDR, " exports symbol \"%s\"", symbol_name.data()); - ResultCode result = target.ApplyRelocationBatch(relocation_addr, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) { - LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports named symbols to \"%s\"", ModuleName().data(), - target.ModuleName().data()); - u32 unresolved_symbol = target.GetOnUnresolvedAddress(); - u32 target_import_strings_size = target.GetField(ImportStringsSize); - u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < target_symbol_import_num; ++i) { - ImportNamedSymbolEntry entry; - target.GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - if (relocation_entry.is_batch_resolved) { - std::string symbol_name = - Memory::ReadCString(entry.name_offset, target_import_strings_size); - u32 symbol_address = FindExportNamedSymbol(symbol_name); - if (symbol_address != 0) { - LOG_TRACE(Service_LDR, " unexports symbol \"%s\"", symbol_name.data()); - ResultCode result = - target.ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyModuleExport(CROHelper target) { - std::string module_name = ModuleName(); - u32 target_import_string_size = target.GetField(ImportStringsSize); - u32 target_import_module_num = target.GetField(ImportModuleNum); - for (u32 i = 0; i < target_import_module_num; ++i) { - ImportModuleEntry entry; - target.GetEntry(i, entry); - - if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) - continue; - - LOG_INFO(Service_LDR, "CRO \"%s\" exports %d indexed symbols to \"%s\"", module_name.data(), - entry.import_indexed_symbol_num, target.ModuleName().data()); - for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { - ImportIndexedSymbolEntry im; - entry.GetImportIndexedSymbolEntry(j, im); - ExportIndexedSymbolEntry ex; - GetEntry(im.index, ex); - u32 symbol_address = SegmentTagToAddress(ex.symbol_position); - LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); - ResultCode result = - target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - - LOG_INFO(Service_LDR, "CRO \"%s\" exports %d anonymous symbols to \"%s\"", - module_name.data(), entry.import_anonymous_symbol_num, target.ModuleName().data()); - for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { - ImportAnonymousSymbolEntry im; - entry.GetImportAnonymousSymbolEntry(j, im); - u32 symbol_address = SegmentTagToAddress(im.symbol_position); - LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); - ResultCode result = - target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - } - - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ResetModuleExport(CROHelper target) { - u32 unresolved_symbol = target.GetOnUnresolvedAddress(); - - std::string module_name = ModuleName(); - u32 target_import_string_size = target.GetField(ImportStringsSize); - u32 target_import_module_num = target.GetField(ImportModuleNum); - for (u32 i = 0; i < target_import_module_num; ++i) { - ImportModuleEntry entry; - target.GetEntry(i, entry); - - if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) - continue; - - LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports indexed symbols to \"%s\"", module_name.data(), - target.ModuleName().data()); - for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { - ImportIndexedSymbolEntry im; - entry.GetImportIndexedSymbolEntry(j, im); - ResultCode result = - target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - - LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports anonymous symbols to \"%s\"", - module_name.data(), target.ModuleName().data()); - for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { - ImportAnonymousSymbolEntry im; - entry.GetImportAnonymousSymbolEntry(j, im); - ResultCode result = - target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - } - - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) { - u32 import_strings_size = GetField(ImportStringsSize); - u32 symbol_import_num = GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < symbol_import_num; ++i) { - ImportNamedSymbolEntry entry; - GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") { - ResultCode result = - ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { - u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); - - if (symbol_address != 0) { - LOG_DEBUG(Service_LDR, "CRO \"%s\" import exit function from \"%s\"", - ModuleName().data(), source.ModuleName().data()); - - ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", - result.raw); - return result; - } - - return MakeResult<bool>(false); - } - - return MakeResult<bool>(true); - }); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying exit relocation %08X", result.raw); - return result; - } - } - } - return RESULT_SUCCESS; -} - -/** - * Verifies a string or a string table matching a predicted size (i.e. terminated by 0) - * if it is not empty. There can be many other nulls in the string table because - * they are composed by many sub strings. This function is to check whether the - * whole string (table) is terminated properly, despite that it is not actually one string. - * @param address the virtual address of the string (table) - * @param size the size of the string (table), including the terminating 0 - * @returns ResultCode RESULT_SUCCESS if the size matches, otherwise error code. - */ -static ResultCode VerifyStringTableLength(VAddr address, u32 size) { - if (size != 0) { - if (Memory::Read8(address + size - 1) != 0) - return CROFormatError(0x0B); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment_addresss, - u32 data_segment_size, VAddr bss_segment_address, u32 bss_segment_size, - bool is_crs) { - - ResultCode result = RebaseHeader(cro_size); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing header %08X", result.raw); - return result; - } - - result = VerifyStringTableLength(GetField(ModuleNameOffset), GetField(ModuleNameSize)); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error verifying module name %08X", result.raw); - return result; - } - - u32 prev_data_segment_address = 0; - if (!is_crs) { - auto result_val = RebaseSegmentTable(cro_size, data_segment_addresss, data_segment_size, - bss_segment_address, bss_segment_size); - if (result_val.Failed()) { - LOG_ERROR(Service_LDR, "Error rebasing segment table %08X", result_val.Code().raw); - return result_val.Code(); - } - prev_data_segment_address = *result_val; - } - - result = RebaseExportNamedSymbolTable(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing symbol export table %08X", result.raw); - return result; - } - - result = VerifyExportTreeTable(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error verifying export tree %08X", result.raw); - return result; - } - - result = VerifyStringTableLength(GetField(ExportStringsOffset), GetField(ExportStringsSize)); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error verifying export strings %08X", result.raw); - return result; - } - - result = RebaseImportModuleTable(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing object table %08X", result.raw); - return result; - } - - result = ResetExternalRelocations(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error resetting all external relocations %08X", result.raw); - return result; - } - - result = RebaseImportNamedSymbolTable(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing symbol import table %08X", result.raw); - return result; - } - - result = RebaseImportIndexedSymbolTable(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing index import table %08X", result.raw); - return result; - } - - result = RebaseImportAnonymousSymbolTable(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing offset import table %08X", result.raw); - return result; - } - - result = VerifyStringTableLength(GetField(ImportStringsOffset), GetField(ImportStringsSize)); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error verifying import strings %08X", result.raw); - return result; - } - - if (!is_crs) { - result = ApplyStaticAnonymousSymbolToCRS(crs_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying offset export to CRS %08X", result.raw); - return result; - } - } - - result = ApplyInternalRelocations(prev_data_segment_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying internal relocations %08X", result.raw); - return result; - } - - if (!is_crs) { - result = ApplyExitRelocations(crs_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying exit relocations %08X", result.raw); - return result; - } - } - - return RESULT_SUCCESS; -} - -void CROHelper::Unrebase(bool is_crs) { - UnrebaseImportAnonymousSymbolTable(); - UnrebaseImportIndexedSymbolTable(); - UnrebaseImportNamedSymbolTable(); - UnrebaseImportModuleTable(); - UnrebaseExportNamedSymbolTable(); - - if (!is_crs) - UnrebaseSegmentTable(); - - SetNextModule(0); - SetPreviousModule(0); - - SetField(FixedSize, 0); - - UnrebaseHeader(); -} - -ResultCode CROHelper::VerifyHash(u32 cro_size, VAddr crr) const { - // TODO(wwylele): actually verify the hash - return RESULT_SUCCESS; -} - -ResultCode CROHelper::Link(VAddr crs_address, bool link_on_load_bug_fix) { - ResultCode result = RESULT_SUCCESS; - - { - VAddr data_segment_address; - if (link_on_load_bug_fix) { - // this is a bug fix introduced by 7.2.0-17's LoadCRO_New - // The bug itself is: - // If a relocation target is in .data segment, it will relocate to the - // user-specified buffer. But if this is linking during loading, - // the .data segment hasn't been transfer from CRO to the buffer, - // thus the relocation will be overwritten by data transfer. - // To fix this bug, we need temporarily restore the old .data segment - // offset and apply imported symbols. - - // RO service seems assuming segment_index == segment_type, - // so we do the same - if (GetField(SegmentNum) >= 2) { // means we have .data segment - SegmentEntry entry; - GetEntry(2, entry); - ASSERT(entry.type == SegmentType::Data); - data_segment_address = entry.offset; - entry.offset = GetField(DataOffset); - SetEntry(2, entry); - } - } - SCOPE_EXIT({ - // Restore the new .data segment address after importing - if (link_on_load_bug_fix) { - if (GetField(SegmentNum) >= 2) { - SegmentEntry entry; - GetEntry(2, entry); - entry.offset = data_segment_address; - SetEntry(2, entry); - } - } - }); - - // Imports named symbols from other modules - result = ApplyImportNamedSymbol(crs_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying symbol import %08X", result.raw); - return result; - } - - // Imports indexed and anonymous symbols from other modules - result = ApplyModuleImport(crs_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying module import %08X", result.raw); - return result; - } - } - - // Exports symbols to other modules - result = ForEachAutoLinkCRO(crs_address, [this](CROHelper target) -> ResultVal<bool> { - ResultCode result = ApplyExportNamedSymbol(target); - if (result.IsError()) - return result; - - result = ApplyModuleExport(target); - if (result.IsError()) - return result; - - return MakeResult<bool>(true); - }); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying export %08X", result.raw); - return result; - } - - return RESULT_SUCCESS; -} - -ResultCode CROHelper::Unlink(VAddr crs_address) { - - // Resets all imported named symbols - ResultCode result = ResetImportNamedSymbol(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error resetting symbol import %08X", result.raw); - return result; - } - - // Resets all imported indexed symbols - result = ResetImportIndexedSymbol(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error resetting indexed import %08X", result.raw); - return result; - } - - // Resets all imported anonymous symbols - result = ResetImportAnonymousSymbol(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error resetting anonymous import %08X", result.raw); - return result; - } - - // Resets all symbols in other modules imported from this module - // Note: the RO service seems only searching in auto-link modules - result = ForEachAutoLinkCRO(crs_address, [this](CROHelper target) -> ResultVal<bool> { - ResultCode result = ResetExportNamedSymbol(target); - if (result.IsError()) - return result; - - result = ResetModuleExport(target); - if (result.IsError()) - return result; - - return MakeResult<bool>(true); - }); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error resetting export %08X", result.raw); - return result; - } - - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ClearRelocations() { - ResultCode result = ClearExternalRelocations(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error clearing external relocations %08X", result.raw); - return result; - } - - result = ClearInternalRelocations(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error clearing internal relocations %08X", result.raw); - return result; - } - return RESULT_SUCCESS; -} - -void CROHelper::InitCRS() { - SetNextModule(0); - SetPreviousModule(0); -} - -void CROHelper::Register(VAddr crs_address, bool auto_link) { - CROHelper crs(crs_address); - CROHelper head(auto_link ? crs.NextModule() : crs.PreviousModule()); - - if (head.module_address) { - // there are already CROs registered - // register as the new tail - CROHelper tail(head.PreviousModule()); - - // link with the old tail - ASSERT(tail.NextModule() == 0); - SetPreviousModule(tail.module_address); - tail.SetNextModule(module_address); - - // set previous of the head pointing to the new tail - head.SetPreviousModule(module_address); - } else { - // register as the first CRO - // set previous to self as tail - SetPreviousModule(module_address); - - // set self as head - if (auto_link) - crs.SetNextModule(module_address); - else - crs.SetPreviousModule(module_address); - } - - // the new one is the tail - SetNextModule(0); -} - -void CROHelper::Unregister(VAddr crs_address) { - CROHelper crs(crs_address); - CROHelper next_head(crs.NextModule()), previous_head(crs.PreviousModule()); - CROHelper next(NextModule()), previous(PreviousModule()); - - if (module_address == next_head.module_address || - module_address == previous_head.module_address) { - // removing head - if (next.module_address) { - // the next is new head - // let its previous point to the tail - next.SetPreviousModule(previous.module_address); - } - - // set new head - if (module_address == previous_head.module_address) { - crs.SetPreviousModule(next.module_address); - } else { - crs.SetNextModule(next.module_address); - } - } else if (next.module_address) { - // link previous and next - previous.SetNextModule(next.module_address); - next.SetPreviousModule(previous.module_address); - } else { - // removing tail - // set previous as new tail - previous.SetNextModule(0); - - // let head's previous point to the new tail - if (next_head.module_address && next_head.PreviousModule() == module_address) { - next_head.SetPreviousModule(previous.module_address); - } else if (previous_head.module_address && - previous_head.PreviousModule() == module_address) { - previous_head.SetPreviousModule(previous.module_address); - } else { - UNREACHABLE(); - } - } - - // unlink self - SetNextModule(0); - SetPreviousModule(0); -} - -u32 CROHelper::GetFixEnd(u32 fix_level) const { - u32 end = CRO_HEADER_SIZE; - end = std::max<u32>(end, GetField(CodeOffset) + GetField(CodeSize)); - - u32 entry_size_i = 2; - int field = ModuleNameOffset; - while (true) { - end = std::max<u32>(end, GetField(static_cast<HeaderField>(field)) + - GetField(static_cast<HeaderField>(field + 1)) * - ENTRY_SIZE[entry_size_i]); - - ++entry_size_i; - field += 2; - - if (field == FIX_BARRIERS[fix_level]) - return end; - } -} - -u32 CROHelper::Fix(u32 fix_level) { - u32 fix_end = GetFixEnd(fix_level); - - if (fix_level != 0) { - SetField(Magic, MAGIC_FIXD); - - for (int field = FIX_BARRIERS[fix_level]; field < Fix0Barrier; field += 2) { - SetField(static_cast<HeaderField>(field), fix_end); - SetField(static_cast<HeaderField>(field + 1), 0); - } - } - - fix_end = Common::AlignUp(fix_end, Memory::PAGE_SIZE); - - u32 fixed_size = fix_end - module_address; - SetField(FixedSize, fixed_size); - return fixed_size; -} - -bool CROHelper::IsLoaded() const { - u32 magic = GetField(Magic); - if (magic != MAGIC_CRO0 && magic != MAGIC_FIXD) - return false; - - // TODO(wwylele): verify memory state here after memory aliasing is implemented - - return true; -} - -std::tuple<VAddr, u32> CROHelper::GetExecutablePages() const { - u32 segment_num = GetField(SegmentNum); - for (u32 i = 0; i < segment_num; ++i) { - SegmentEntry entry; - GetEntry(i, entry); - if (entry.type == SegmentType::Code && entry.size != 0) { - VAddr begin = Common::AlignDown(entry.offset, Memory::PAGE_SIZE); - VAddr end = Common::AlignUp(entry.offset + entry.size, Memory::PAGE_SIZE); - return std::make_tuple(begin, end - begin); - } - } - return std::make_tuple(0, 0); -} - -} // namespace LDR -} // namespace Service diff --git a/src/core/hle/service/ldr_ro/cro_helper.h b/src/core/hle/service/ldr_ro/cro_helper.h deleted file mode 100644 index 57b4fb6df..000000000 --- a/src/core/hle/service/ldr_ro/cro_helper.h +++ /dev/null @@ -1,714 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <array> -#include <tuple> -#include "common/common_types.h" -#include "common/swap.h" -#include "core/hle/result.h" -#include "core/memory.h" - -namespace Service { -namespace LDR { - -// GCC versions < 5.0 do not implement std::is_trivially_copyable. -// Excluding MSVC because it has weird behaviour for std::is_trivially_copyable. -#if (__GNUC__ >= 5) || defined(__clang__) -#define ASSERT_CRO_STRUCT(name, size) \ - static_assert(std::is_standard_layout<name>::value, \ - "CRO structure " #name " doesn't use standard layout"); \ - static_assert(std::is_trivially_copyable<name>::value, \ - "CRO structure " #name " isn't trivially copyable"); \ - static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name) -#else -#define ASSERT_CRO_STRUCT(name, size) \ - static_assert(std::is_standard_layout<name>::value, \ - "CRO structure " #name " doesn't use standard layout"); \ - static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name) -#endif - -static constexpr u32 CRO_HEADER_SIZE = 0x138; -static constexpr u32 CRO_HASH_SIZE = 0x80; - -/// Represents a loaded module (CRO) with interfaces manipulating it. -class CROHelper final { -public: - explicit CROHelper(VAddr cro_address) : module_address(cro_address) {} - - std::string ModuleName() const { - return Memory::ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize)); - } - - u32 GetFileSize() const { - return GetField(FileSize); - } - - /** - * Rebases the module according to its address. - * @param crs_address the virtual address of the static module - * @param cro_size the size of the CRO file - * @param data_segment_address buffer address for .data segment - * @param data_segment_size the buffer size for .data segment - * @param bss_segment_address the buffer address for .bss segment - * @param bss_segment_size the buffer size for .bss segment - * @param is_crs true if the module itself is the static module - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment_address, - u32 data_segment_size, VAddr bss_segment_address, u32 bss_segment_size, - bool is_crs); - - /** - * Unrebases the module. - * @param is_crs true if the module itself is the static module - */ - void Unrebase(bool is_crs); - - /** - * Verifies module hash by CRR. - * @param cro_size the size of the CRO - * @param crr the virtual address of the CRR - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode VerifyHash(u32 cro_size, VAddr crr) const; - - /** - * Links this module with all registered auto-link module. - * @param crs_address the virtual address of the static module - * @param link_on_load_bug_fix true if links when loading and fixes the bug - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode Link(VAddr crs_address, bool link_on_load_bug_fix); - - /** - * Unlinks this module with other modules. - * @param crs_address the virtual address of the static module - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode Unlink(VAddr crs_address); - - /** - * Clears all relocations to zero. - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ClearRelocations(); - - /// Initialize this module as the static module (CRS) - void InitCRS(); - - /** - * Registers this module and adds it to the module list. - * @param crs_address the virtual address of the static module - * @param auto_link whether to register as an auto link module - */ - void Register(VAddr crs_address, bool auto_link); - - /** - * Unregisters this module and removes from the module list. - * @param crs_address the virtual address of the static module - */ - void Unregister(VAddr crs_address); - - /** - * Gets the end of reserved data according to the fix level. - * @param fix_level fix level from 0 to 3 - * @returns the end of reserved data. - */ - u32 GetFixEnd(u32 fix_level) const; - - /** - * Zeros offsets to cropped data according to the fix level and marks as fixed. - * @param fix_level fix level from 0 to 3 - * @returns page-aligned size of the module after fixing. - */ - u32 Fix(u32 fix_level); - - bool IsFixed() const { - return GetField(Magic) == MAGIC_FIXD; - } - - u32 GetFixedSize() const { - return GetField(FixedSize); - } - - bool IsLoaded() const; - - /** - * Gets the page address and size of the code segment. - * @returns a tuple of (address, size); (0, 0) if the code segment doesn't exist. - */ - std::tuple<VAddr, u32> GetExecutablePages() const; - -private: - const VAddr module_address; ///< the virtual address of this module - - /** - * Each item in this enum represents a u32 field in the header begin from address+0x80, - * successively. We don't directly use a struct here, to avoid GetPointer, reinterpret_cast, or - * Read/WriteBlock repeatedly. - */ - enum HeaderField { - Magic = 0, - NameOffset, - NextCRO, - PreviousCRO, - FileSize, - BssSize, - FixedSize, - UnknownZero, - UnkSegmentTag, - OnLoadSegmentTag, - OnExitSegmentTag, - OnUnresolvedSegmentTag, - - CodeOffset, - CodeSize, - DataOffset, - DataSize, - ModuleNameOffset, - ModuleNameSize, - SegmentTableOffset, - SegmentNum, - - ExportNamedSymbolTableOffset, - ExportNamedSymbolNum, - ExportIndexedSymbolTableOffset, - ExportIndexedSymbolNum, - ExportStringsOffset, - ExportStringsSize, - ExportTreeTableOffset, - ExportTreeNum, - - ImportModuleTableOffset, - ImportModuleNum, - ExternalRelocationTableOffset, - ExternalRelocationNum, - ImportNamedSymbolTableOffset, - ImportNamedSymbolNum, - ImportIndexedSymbolTableOffset, - ImportIndexedSymbolNum, - ImportAnonymousSymbolTableOffset, - ImportAnonymousSymbolNum, - ImportStringsOffset, - ImportStringsSize, - - StaticAnonymousSymbolTableOffset, - StaticAnonymousSymbolNum, - InternalRelocationTableOffset, - InternalRelocationNum, - StaticRelocationTableOffset, - StaticRelocationNum, - Fix0Barrier, - - Fix3Barrier = ExportNamedSymbolTableOffset, - Fix2Barrier = ImportModuleTableOffset, - Fix1Barrier = StaticAnonymousSymbolTableOffset, - }; - static_assert(Fix0Barrier == (CRO_HEADER_SIZE - CRO_HASH_SIZE) / 4, - "CRO Header fields are wrong!"); - - enum class SegmentType : u32 { - Code = 0, - ROData = 1, - Data = 2, - BSS = 3, - }; - - /** - * Identifies a program location inside of a segment. - * Required to refer to program locations because individual segments may be relocated - * independently of each other. - */ - union SegmentTag { - u32_le raw; - BitField<0, 4, u32_le> segment_index; - BitField<4, 28, u32_le> offset_into_segment; - - SegmentTag() = default; - explicit SegmentTag(u32 raw_) : raw(raw_) {} - }; - - /// Information of a segment in this module. - struct SegmentEntry { - u32_le offset; - u32_le size; - SegmentType type; - - static constexpr HeaderField TABLE_OFFSET_FIELD = SegmentTableOffset; - }; - ASSERT_CRO_STRUCT(SegmentEntry, 12); - - /// Identifies a named symbol exported from this module. - struct ExportNamedSymbolEntry { - u32_le name_offset; // pointing to a substring in ExportStrings - SegmentTag symbol_position; // to self's segment - - static constexpr HeaderField TABLE_OFFSET_FIELD = ExportNamedSymbolTableOffset; - }; - ASSERT_CRO_STRUCT(ExportNamedSymbolEntry, 8); - - /// Identifies an indexed symbol exported from this module. - struct ExportIndexedSymbolEntry { - SegmentTag symbol_position; // to self's segment - - static constexpr HeaderField TABLE_OFFSET_FIELD = ExportIndexedSymbolTableOffset; - }; - ASSERT_CRO_STRUCT(ExportIndexedSymbolEntry, 4); - - /// A tree node in the symbol lookup tree. - struct ExportTreeEntry { - u16_le test_bit; // bit address into the name to test - union Child { - u16_le raw; - BitField<0, 15, u16_le> next_index; - BitField<15, 1, u16_le> is_end; - } left, right; - u16_le export_table_index; // index of an ExportNamedSymbolEntry - - static constexpr HeaderField TABLE_OFFSET_FIELD = ExportTreeTableOffset; - }; - ASSERT_CRO_STRUCT(ExportTreeEntry, 8); - - /// Identifies a named symbol imported from another module. - struct ImportNamedSymbolEntry { - u32_le name_offset; // pointing to a substring in ImportStrings - u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable - - static constexpr HeaderField TABLE_OFFSET_FIELD = ImportNamedSymbolTableOffset; - }; - ASSERT_CRO_STRUCT(ImportNamedSymbolEntry, 8); - - /// Identifies an indexed symbol imported from another module. - struct ImportIndexedSymbolEntry { - u32_le index; // index of an ExportIndexedSymbolEntry in the exporting module - u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable - - static constexpr HeaderField TABLE_OFFSET_FIELD = ImportIndexedSymbolTableOffset; - }; - ASSERT_CRO_STRUCT(ImportIndexedSymbolEntry, 8); - - /// Identifies an anonymous symbol imported from another module. - struct ImportAnonymousSymbolEntry { - SegmentTag symbol_position; // in the exporting segment - u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable - - static constexpr HeaderField TABLE_OFFSET_FIELD = ImportAnonymousSymbolTableOffset; - }; - ASSERT_CRO_STRUCT(ImportAnonymousSymbolEntry, 8); - - /// Information of a imported module and symbols imported from it. - struct ImportModuleEntry { - u32_le name_offset; // pointing to a substring in ImportStrings - u32_le import_indexed_symbol_table_offset; // pointing to a subtable in - // ImportIndexedSymbolTable - u32_le import_indexed_symbol_num; - u32_le import_anonymous_symbol_table_offset; // pointing to a subtable in - // ImportAnonymousSymbolTable - u32_le import_anonymous_symbol_num; - - static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset; - - void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) { - Memory::ReadBlock(import_indexed_symbol_table_offset + - index * sizeof(ImportIndexedSymbolEntry), - &entry, sizeof(ImportIndexedSymbolEntry)); - } - - void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) { - Memory::ReadBlock(import_anonymous_symbol_table_offset + - index * sizeof(ImportAnonymousSymbolEntry), - &entry, sizeof(ImportAnonymousSymbolEntry)); - } - }; - ASSERT_CRO_STRUCT(ImportModuleEntry, 20); - - enum class RelocationType : u8 { - Nothing = 0, - AbsoluteAddress = 2, - RelativeAddress = 3, - ThumbBranch = 10, - ArmBranch = 28, - ModifyArmBranch = 29, - AbsoluteAddress2 = 38, - AlignedRelativeAddress = 42, - }; - - struct RelocationEntry { - SegmentTag target_position; // to self's segment as an ExternalRelocationEntry; to static - // module segment as a StaticRelocationEntry - RelocationType type; - u8 is_batch_end; - u8 is_batch_resolved; // set at a batch beginning if the batch is resolved - INSERT_PADDING_BYTES(1); - u32_le addend; - }; - - /// Identifies a normal cross-module relocation. - struct ExternalRelocationEntry : RelocationEntry { - static constexpr HeaderField TABLE_OFFSET_FIELD = ExternalRelocationTableOffset; - }; - ASSERT_CRO_STRUCT(ExternalRelocationEntry, 12); - - /// Identifies a special static relocation (no game is known using this). - struct StaticRelocationEntry : RelocationEntry { - static constexpr HeaderField TABLE_OFFSET_FIELD = StaticRelocationTableOffset; - }; - ASSERT_CRO_STRUCT(StaticRelocationEntry, 12); - - /// Identifies a in-module relocation. - struct InternalRelocationEntry { - SegmentTag target_position; // to self's segment - RelocationType type; - u8 symbol_segment; - INSERT_PADDING_BYTES(2); - u32_le addend; - - static constexpr HeaderField TABLE_OFFSET_FIELD = InternalRelocationTableOffset; - }; - ASSERT_CRO_STRUCT(InternalRelocationEntry, 12); - - /// Identifies a special static anonymous symbol (no game is known using this). - struct StaticAnonymousSymbolEntry { - SegmentTag symbol_position; // to self's segment - u32_le relocation_batch_offset; // pointing to a relocation batch in StaticRelocationTable - - static constexpr HeaderField TABLE_OFFSET_FIELD = StaticAnonymousSymbolTableOffset; - }; - ASSERT_CRO_STRUCT(StaticAnonymousSymbolEntry, 8); - - /** - * Entry size of each table, from Code to StaticRelocationTable. - * Byte string contents (such as Code) are treated with entries of size 1. - * This is used for verifying the size of each table and calculating the fix end. - */ - static const std::array<int, 17> ENTRY_SIZE; - - /// The offset field of the table where to crop for each fix level - static const std::array<HeaderField, 4> FIX_BARRIERS; - - static constexpr u32 MAGIC_CRO0 = 0x304F5243; - static constexpr u32 MAGIC_FIXD = 0x44584946; - - VAddr Field(HeaderField field) const { - return module_address + CRO_HASH_SIZE + field * 4; - } - - u32 GetField(HeaderField field) const { - return Memory::Read32(Field(field)); - } - - void SetField(HeaderField field, u32 value) { - Memory::Write32(Field(field), value); - } - - /** - * Reads an entry in one of module tables. - * @param index index of the entry - * @param data where to put the read entry - * @note the entry type must have the static member TABLE_OFFSET_FIELD - * indicating which table the entry is in. - */ - template <typename T> - void GetEntry(std::size_t index, T& data) const { - Memory::ReadBlock(GetField(T::TABLE_OFFSET_FIELD) + static_cast<u32>(index * sizeof(T)), - &data, sizeof(T)); - } - - /** - * Writes an entry to one of module tables. - * @param index index of the entry - * @param data the entry data to write - * @note the entry type must have the static member TABLE_OFFSET_FIELD - * indicating which table the entry is in. - */ - template <typename T> - void SetEntry(std::size_t index, const T& data) { - Memory::WriteBlock(GetField(T::TABLE_OFFSET_FIELD) + static_cast<u32>(index * sizeof(T)), - &data, sizeof(T)); - } - - /** - * Converts a segment tag to virtual address in this module. - * @param segment_tag the segment tag to convert - * @returns VAddr the virtual address the segment tag points to; 0 if invalid. - */ - VAddr SegmentTagToAddress(SegmentTag segment_tag) const; - - VAddr NextModule() const { - return GetField(NextCRO); - } - - VAddr PreviousModule() const { - return GetField(PreviousCRO); - } - - void SetNextModule(VAddr next) { - SetField(NextCRO, next); - } - - void SetPreviousModule(VAddr previous) { - SetField(PreviousCRO, previous); - } - - /** - * A helper function iterating over all registered auto-link modules, including the static - * module. - * @param crs_address the virtual address of the static module - * @param func a function object to operate on a module. It accepts one parameter - * CROHelper and returns ResultVal<bool>. It should return true to continue the - * iteration, - * false to stop the iteration, or an error code (which will also stop the iteration). - * @returns ResultCode indicating the result of the operation, RESULT_SUCCESS if all iteration - * success, - * otherwise error code of the last iteration. - */ - template <typename FunctionObject> - static ResultCode ForEachAutoLinkCRO(VAddr crs_address, FunctionObject func) { - VAddr current = crs_address; - while (current != 0) { - CROHelper cro(current); - CASCADE_RESULT(bool next, func(cro)); - if (!next) - break; - current = cro.NextModule(); - } - return RESULT_SUCCESS; - } - - /** - * Applies a relocation - * @param target_address where to apply the relocation - * @param relocation_type the type of the relocation - * @param addend address addend applied to the relocated symbol - * @param symbol_address the symbol address to be relocated with - * @param target_future_address the future address of the target. - * Usually equals to target_address, but will be different for a target in .data segment - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ApplyRelocation(VAddr target_address, RelocationType relocation_type, u32 addend, - u32 symbol_address, u32 target_future_address); - - /** - * Clears a relocation to zero - * @param target_address where to apply the relocation - * @param relocation_type the type of the relocation - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ClearRelocation(VAddr target_address, RelocationType relocation_type); - - /** - * Applies or resets a batch of relocations - * @param batch the virtual address of the first relocation in the batch - * @param symbol_address the symbol address to be relocated with - * @param reset false to set the batch to resolved state, true to reset the batch to unresolved - * state - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset = false); - - /** - * Finds an exported named symbol in this module. - * @param name the name of the symbol to find - * @return VAddr the virtual address of the symbol; 0 if not found. - */ - VAddr FindExportNamedSymbol(const std::string& name) const; - - /** - * Rebases offsets in module header according to module address. - * @param cro_size the size of the CRO file - * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error - * code. - */ - ResultCode RebaseHeader(u32 cro_size); - - /** - * Rebases offsets in segment table according to module address. - * @param cro_size the size of the CRO file - * @param data_segment_address the buffer address for .data segment - * @param data_segment_size the buffer size for .data segment - * @param bss_segment_address the buffer address for .bss segment - * @param bss_segment_size the buffer size for .bss segment - * @returns ResultVal<VAddr> with the virtual address of .data segment in CRO. - */ - ResultVal<VAddr> RebaseSegmentTable(u32 cro_size, VAddr data_segment_address, - u32 data_segment_size, VAddr bss_segment_address, - u32 bss_segment_size); - - /** - * Rebases offsets in exported named symbol table according to module address. - * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error - * code. - */ - ResultCode RebaseExportNamedSymbolTable(); - - /** - * Verifies indices in export tree table. - * @returns ResultCode RESULT_SUCCESS if all indices are verified as valid, otherwise error - * code. - */ - ResultCode VerifyExportTreeTable() const; - - /** - * Rebases offsets in exported module table according to module address. - * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error - * code. - */ - ResultCode RebaseImportModuleTable(); - - /** - * Rebases offsets in imported named symbol table according to module address. - * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error - * code. - */ - ResultCode RebaseImportNamedSymbolTable(); - - /** - * Rebases offsets in imported indexed symbol table according to module address. - * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error - * code. - */ - ResultCode RebaseImportIndexedSymbolTable(); - - /** - * Rebases offsets in imported anonymous symbol table according to module address. - * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error - * code. - */ - ResultCode RebaseImportAnonymousSymbolTable(); - - /** - * Gets the address of OnUnresolved function in this module. - * Used as the applied symbol for reset relocation. - * @returns the virtual address of OnUnresolved. 0 if not provided. - */ - VAddr GetOnUnresolvedAddress(); - - /** - * Resets all external relocations to unresolved state. - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ResetExternalRelocations(); - - /** - * Clears all external relocations to zero. - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ClearExternalRelocations(); - - /** - * Applies all static anonymous symbol to the static module. - * @param crs_address the virtual address of the static module - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ApplyStaticAnonymousSymbolToCRS(VAddr crs_address); - - /** - * Applies all internal relocations to the module itself. - * @param old_data_segment_address the virtual address of data segment in CRO buffer - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ApplyInternalRelocations(u32 old_data_segment_address); - - /** - * Clears all internal relocations to zero. - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ClearInternalRelocations(); - - /// Unrebases offsets in imported anonymous symbol table - void UnrebaseImportAnonymousSymbolTable(); - - /// Unrebases offsets in imported indexed symbol table - void UnrebaseImportIndexedSymbolTable(); - - /// Unrebases offsets in imported named symbol table - void UnrebaseImportNamedSymbolTable(); - - /// Unrebases offsets in imported module table - void UnrebaseImportModuleTable(); - - /// Unrebases offsets in exported named symbol table - void UnrebaseExportNamedSymbolTable(); - - /// Unrebases offsets in segment table - void UnrebaseSegmentTable(); - - /// Unrebases offsets in module header - void UnrebaseHeader(); - - /** - * Looks up all imported named symbols of this module in all registered auto-link modules, and - * resolves them if found. - * @param crs_address the virtual address of the static module - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ApplyImportNamedSymbol(VAddr crs_address); - - /** - * Resets all imported named symbols of this module to unresolved state. - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ResetImportNamedSymbol(); - - /** - * Resets all imported indexed symbols of this module to unresolved state. - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ResetImportIndexedSymbol(); - - /** - * Resets all imported anonymous symbols of this module to unresolved state. - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ResetImportAnonymousSymbol(); - - /** - * Finds registered auto-link modules that this module imports, and resolves indexed and - * anonymous symbols exported by them. - * @param crs_address the virtual address of the static module - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ApplyModuleImport(VAddr crs_address); - - /** - * Resolves target module's imported named symbols that exported by this module. - * @param target the module to resolve. - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ApplyExportNamedSymbol(CROHelper target); - - /** - * Resets target's named symbols imported from this module to unresolved state. - * @param target the module to reset. - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ResetExportNamedSymbol(CROHelper target); - - /** - * Resolves imported indexed and anonymous symbols in the target module which imports this - * module. - * @param target the module to resolve. - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ApplyModuleExport(CROHelper target); - - /** - * Resets target's indexed and anonymous symbol imported from this module to unresolved state. - * @param target the module to reset. - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ResetModuleExport(CROHelper target); - - /** - * Resolves the exit function in this module - * @param crs_address the virtual address of the static module. - * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. - */ - ResultCode ApplyExitRelocations(VAddr crs_address); -}; - -} // namespace LDR -} // namespace Service diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp deleted file mode 100644 index 7255ea026..000000000 --- a/src/core/hle/service/ldr_ro/ldr_ro.cpp +++ /dev/null @@ -1,718 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/alignment.h" -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/arm/arm_interface.h" -#include "core/core.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/process.h" -#include "core/hle/kernel/vm_manager.h" -#include "core/hle/service/ldr_ro/cro_helper.h" -#include "core/hle/service/ldr_ro/ldr_ro.h" -#include "core/hle/service/ldr_ro/memory_synchronizer.h" - -namespace Service { -namespace LDR { - -static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9 - ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal, - ErrorLevel::Permanent); -static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8 - ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal, - ErrorLevel::Permanent); -static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F - ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, - ErrorLevel::Usage); -static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1 - ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument, - ErrorLevel::Permanent); -static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2 - ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument, - ErrorLevel::Permanent); -static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F - ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal, - ErrorLevel::Usage); -static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08 - ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState, - ErrorLevel::Permanent); -static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D - ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState, - ErrorLevel::Permanent); - -static MemorySynchronizer memory_synchronizer; - -// TODO(wwylele): this should be in the per-client storage when we implement multi-process -static VAddr loaded_crs; ///< the virtual address of the static module - -static bool VerifyBufferState(VAddr buffer_ptr, u32 size) { - auto vma = Kernel::g_current_process->vm_manager.FindVMA(buffer_ptr); - return vma != Kernel::g_current_process->vm_manager.vma_map.end() && - vma->second.base + vma->second.size >= buffer_ptr + size && - vma->second.permissions == Kernel::VMAPermission::ReadWrite && - vma->second.meminfo_state == Kernel::MemoryState::Private; -} - -/** - * LDR_RO::Initialize service function - * Inputs: - * 0 : 0x000100C2 - * 1 : CRS buffer pointer - * 2 : CRS Size - * 3 : Process memory address where the CRS will be mapped - * 4 : handle translation descriptor (zero) - * 5 : KProcess handle - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void Initialize(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x01, 3, 2); - VAddr crs_buffer_ptr = rp.Pop<u32>(); - u32 crs_size = rp.Pop<u32>(); - VAddr crs_address = rp.Pop<u32>(); - // TODO (wwylele): RO service checks the descriptor here and return error 0xD9001830 for - // incorrect descriptor. This error return should be probably built in IPC::RequestParser. - // All other service functions below have the same issue. - Kernel::Handle process = rp.PopHandle(); - - LOG_DEBUG(Service_LDR, - "called, crs_buffer_ptr=0x%08X, crs_address=0x%08X, crs_size=0x%X, process=0x%08X", - crs_buffer_ptr, crs_address, crs_size, process); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - if (loaded_crs != 0) { - LOG_ERROR(Service_LDR, "Already initialized"); - rb.Push(ERROR_ALREADY_INITIALIZED); - return; - } - - if (crs_size < CRO_HEADER_SIZE) { - LOG_ERROR(Service_LDR, "CRS is too small"); - rb.Push(ERROR_BUFFER_TOO_SMALL); - return; - } - - if (crs_buffer_ptr & Memory::PAGE_MASK) { - LOG_ERROR(Service_LDR, "CRS original address is not aligned"); - rb.Push(ERROR_MISALIGNED_ADDRESS); - return; - } - - if (crs_address & Memory::PAGE_MASK) { - LOG_ERROR(Service_LDR, "CRS mapping address is not aligned"); - rb.Push(ERROR_MISALIGNED_ADDRESS); - return; - } - - if (crs_size & Memory::PAGE_MASK) { - LOG_ERROR(Service_LDR, "CRS size is not aligned"); - rb.Push(ERROR_MISALIGNED_SIZE); - return; - } - - if (!VerifyBufferState(crs_buffer_ptr, crs_size)) { - LOG_ERROR(Service_LDR, "CRS original buffer is in invalid state"); - rb.Push(ERROR_INVALID_MEMORY_STATE); - return; - } - - if (crs_address < Memory::PROCESS_IMAGE_VADDR || - crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) { - LOG_ERROR(Service_LDR, "CRS mapping address is not in the process image region"); - rb.Push(ERROR_ILLEGAL_ADDRESS); - return; - } - - ResultCode result = RESULT_SUCCESS; - - if (crs_buffer_ptr != crs_address) { - // TODO(wwylele): should be memory aliasing - std::shared_ptr<std::vector<u8>> crs_mem = std::make_shared<std::vector<u8>>(crs_size); - Memory::ReadBlock(crs_buffer_ptr, crs_mem->data(), crs_size); - result = Kernel::g_current_process->vm_manager - .MapMemoryBlock(crs_address, crs_mem, 0, crs_size, Kernel::MemoryState::Code) - .Code(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); - rb.Push(result); - return; - } - - result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size, - Kernel::VMAPermission::Read); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); - rb.Push(result); - return; - } - - memory_synchronizer.AddMemoryBlock(crs_address, crs_buffer_ptr, crs_size); - } else { - // Do nothing if buffer_ptr == address - // TODO(wwylele): verify this behaviour. This is only seen in the web browser app, - // and the actual behaviour is unclear. "Do nothing" is probably an incorrect implement. - // There is also a chance that another issue causes the app passing wrong arguments. - LOG_WARNING(Service_LDR, "crs_buffer_ptr == crs_address (0x%08X)", crs_address); - } - - CROHelper crs(crs_address); - crs.InitCRS(); - - result = crs.Rebase(0, crs_size, 0, 0, 0, 0, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing CRS 0x%08X", result.raw); - rb.Push(result); - return; - } - - memory_synchronizer.SynchronizeOriginalMemory(); - - loaded_crs = crs_address; - - rb.Push(RESULT_SUCCESS); -} - -/** - * LDR_RO::LoadCRR service function - * Inputs: - * 0 : 0x00020082 - * 1 : CRR buffer pointer - * 2 : CRR Size - * 3 : handle translation descriptor (zero) - * 4 : KProcess handle - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void LoadCRR(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x02, 2, 2); - VAddr crr_buffer_ptr = rp.Pop<u32>(); - u32 crr_size = rp.Pop<u32>(); - Kernel::Handle process = rp.PopHandle(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_LDR, - "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, process=0x%08X", - crr_buffer_ptr, crr_size, process); -} - -/** - * LDR_RO::UnloadCRR service function - * Inputs: - * 0 : 0x00030042 - * 1 : CRR buffer pointer - * 2 : handle translation descriptor (zero) - * 3 : KProcess handle - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void UnloadCRR(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x03, 1, 2); - u32 crr_buffer_ptr = rp.Pop<u32>(); - Kernel::Handle process = rp.PopHandle(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, process=0x%08X", - crr_buffer_ptr, process); -} - -/** - * LDR_RO::LoadCRO service function - * Inputs: - * 0 : 0x000402C2 (old) / 0x000902C2 (new) - * 1 : CRO buffer pointer - * 2 : memory address where the CRO will be mapped - * 3 : CRO Size - * 4 : .data segment buffer pointer - * 5 : must be zero - * 6 : .data segment buffer size - * 7 : .bss segment buffer pointer - * 8 : .bss segment buffer size - * 9 : (bool) register CRO as auto-link module - * 10 : fix level - * 11 : CRR address (zero if use loaded CRR) - * 12 : handle translation descriptor (zero) - * 13 : KProcess handle - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - * 2 : CRO fixed size - * Note: - * This service function has two versions. The function defined here is a - * unified one of two, with an additional parameter link_on_load_bug_fix. - * There is a dispatcher template below. - */ -static void LoadCRO(Interface* self, bool link_on_load_bug_fix) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), link_on_load_bug_fix ? 0x09 : 0x04, 11, 2); - VAddr cro_buffer_ptr = rp.Pop<u32>(); - VAddr cro_address = rp.Pop<u32>(); - u32 cro_size = rp.Pop<u32>(); - VAddr data_segment_address = rp.Pop<u32>(); - u32 zero = rp.Pop<u32>(); - u32 data_segment_size = rp.Pop<u32>(); - u32 bss_segment_address = rp.Pop<u32>(); - u32 bss_segment_size = rp.Pop<u32>(); - bool auto_link = rp.Pop<bool>(); - u32 fix_level = rp.Pop<u32>(); - VAddr crr_address = rp.Pop<u32>(); - Kernel::Handle process = rp.PopHandle(); - - LOG_DEBUG(Service_LDR, "called (%s), cro_buffer_ptr=0x%08X, cro_address=0x%08X, cro_size=0x%X, " - "data_segment_address=0x%08X, zero=%d, data_segment_size=0x%X, " - "bss_segment_address=0x%08X, bss_segment_size=0x%X, auto_link=%s, " - "fix_level=%d, crr_address=0x%08X, process=0x%08X", - link_on_load_bug_fix ? "new" : "old", cro_buffer_ptr, cro_address, cro_size, - data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size, - auto_link ? "true" : "false", fix_level, crr_address, process); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - - if (loaded_crs == 0) { - LOG_ERROR(Service_LDR, "Not initialized"); - rb.Push(ERROR_NOT_INITIALIZED); - rb.Push<u32>(0); - return; - } - - if (cro_size < CRO_HEADER_SIZE) { - LOG_ERROR(Service_LDR, "CRO too small"); - rb.Push(ERROR_BUFFER_TOO_SMALL); - rb.Push<u32>(0); - return; - } - - if (cro_buffer_ptr & Memory::PAGE_MASK) { - LOG_ERROR(Service_LDR, "CRO original address is not aligned"); - rb.Push(ERROR_MISALIGNED_ADDRESS); - rb.Push<u32>(0); - return; - } - - if (cro_address & Memory::PAGE_MASK) { - LOG_ERROR(Service_LDR, "CRO mapping address is not aligned"); - rb.Push(ERROR_MISALIGNED_ADDRESS); - rb.Push<u32>(0); - return; - } - - if (cro_size & Memory::PAGE_MASK) { - LOG_ERROR(Service_LDR, "CRO size is not aligned"); - rb.Push(ERROR_MISALIGNED_SIZE); - rb.Push<u32>(0); - return; - } - - if (!VerifyBufferState(cro_buffer_ptr, cro_size)) { - LOG_ERROR(Service_LDR, "CRO original buffer is in invalid state"); - rb.Push(ERROR_INVALID_MEMORY_STATE); - rb.Push<u32>(0); - return; - } - - if (cro_address < Memory::PROCESS_IMAGE_VADDR || - cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) { - LOG_ERROR(Service_LDR, "CRO mapping address is not in the process image region"); - rb.Push(ERROR_ILLEGAL_ADDRESS); - rb.Push<u32>(0); - return; - } - - if (zero) { - LOG_ERROR(Service_LDR, "Zero is not zero %d", zero); - rb.Push(ResultCode(static_cast<ErrorDescription>(29), ErrorModule::RO, - ErrorSummary::Internal, ErrorLevel::Usage)); - rb.Push<u32>(0); - return; - } - - ResultCode result = RESULT_SUCCESS; - - if (cro_buffer_ptr != cro_address) { - // TODO(wwylele): should be memory aliasing - std::shared_ptr<std::vector<u8>> cro_mem = std::make_shared<std::vector<u8>>(cro_size); - Memory::ReadBlock(cro_buffer_ptr, cro_mem->data(), cro_size); - result = Kernel::g_current_process->vm_manager - .MapMemoryBlock(cro_address, cro_mem, 0, cro_size, Kernel::MemoryState::Code) - .Code(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); - rb.Push(result); - rb.Push<u32>(0); - return; - } - - result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size, - Kernel::VMAPermission::Read); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); - Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); - rb.Push(result); - rb.Push<u32>(0); - return; - } - - memory_synchronizer.AddMemoryBlock(cro_address, cro_buffer_ptr, cro_size); - } else { - // Do nothing if buffer_ptr == address - // TODO(wwylele): verify this behaviour. - // This is derived from the case of LoadCRS with buffer_ptr==address, - // and is never seen in any game. "Do nothing" is probably an incorrect implement. - // There is also a chance that this case is just prohibited. - LOG_WARNING(Service_LDR, "cro_buffer_ptr == cro_address (0x%08X)", cro_address); - } - - CROHelper cro(cro_address); - - result = cro.VerifyHash(cro_size, crr_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error verifying CRO in CRR %08X", result.raw); - Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); - rb.Push(result); - rb.Push<u32>(0); - return; - } - - result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size, - bss_segment_address, bss_segment_size, false); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw); - Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); - rb.Push(result); - rb.Push<u32>(0); - return; - } - - result = cro.Link(loaded_crs, link_on_load_bug_fix); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error linking CRO %08X", result.raw); - Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); - rb.Push(result); - rb.Push<u32>(0); - return; - } - - cro.Register(loaded_crs, auto_link); - - u32 fix_size = cro.Fix(fix_level); - - memory_synchronizer.SynchronizeOriginalMemory(); - - // TODO(wwylele): verify the behaviour when buffer_ptr == address - if (cro_buffer_ptr != cro_address) { - if (fix_size != cro_size) { - result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size, - cro_size - fix_size); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error unmapping memory block %08X", result.raw); - Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); - rb.Push(result); - rb.Push<u32>(0); - return; - } - } - - // Changes the block size - memory_synchronizer.ResizeMemoryBlock(cro_address, cro_buffer_ptr, fix_size); - } - - VAddr exe_begin; - u32 exe_size; - std::tie(exe_begin, exe_size) = cro.GetExecutablePages(); - if (exe_begin) { - result = Kernel::g_current_process->vm_manager.ReprotectRange( - exe_begin, exe_size, Kernel::VMAPermission::ReadExecute); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); - Kernel::g_current_process->vm_manager.UnmapRange(cro_address, fix_size); - rb.Push(result); - rb.Push<u32>(0); - return; - } - } - - Core::CPU().ClearInstructionCache(); - - LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", cro.ModuleName().data(), - cro_address, cro_address + fix_size); - - rb.Push(RESULT_SUCCESS, fix_size); -} - -template <bool link_on_load_bug_fix> -static void LoadCRO(Interface* self) { - LoadCRO(self, link_on_load_bug_fix); -} - -/** - * LDR_RO::UnloadCRO service function - * Inputs: - * 0 : 0x000500C2 - * 1 : mapped CRO pointer - * 2 : zero? (RO service doesn't care) - * 3 : original CRO pointer - * 4 : handle translation descriptor (zero) - * 5 : KProcess handle - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void UnloadCRO(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x05, 3, 2); - VAddr cro_address = rp.Pop<u32>(); - u32 zero = rp.Pop<u32>(); - VAddr cro_buffer_ptr = rp.Pop<u32>(); - Kernel::Handle process = rp.PopHandle(); - - LOG_DEBUG(Service_LDR, - "called, cro_address=0x%08X, zero=%d, cro_buffer_ptr=0x%08X, process=0x%08X", - cro_address, zero, cro_buffer_ptr, process); - - CROHelper cro(cro_address); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - if (loaded_crs == 0) { - LOG_ERROR(Service_LDR, "Not initialized"); - rb.Push(ERROR_NOT_INITIALIZED); - return; - } - - if (cro_address & Memory::PAGE_MASK) { - LOG_ERROR(Service_LDR, "CRO address is not aligned"); - rb.Push(ERROR_MISALIGNED_ADDRESS); - return; - } - - if (!cro.IsLoaded()) { - LOG_ERROR(Service_LDR, "Invalid or not loaded CRO"); - rb.Push(ERROR_NOT_LOADED); - return; - } - - LOG_INFO(Service_LDR, "Unloading CRO \"%s\"", cro.ModuleName().data()); - - u32 fixed_size = cro.GetFixedSize(); - - cro.Unregister(loaded_crs); - - ResultCode result = cro.Unlink(loaded_crs); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error unlinking CRO %08X", result.raw); - rb.Push(result); - return; - } - - // If the module is not fixed, clears all external/internal relocations - // to restore the state before loading, so that it can be loaded again(?) - if (!cro.IsFixed()) { - result = cro.ClearRelocations(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error clearing relocations %08X", result.raw); - rb.Push(result); - return; - } - } - - cro.Unrebase(false); - - memory_synchronizer.SynchronizeOriginalMemory(); - - // TODO(wwylele): verify the behaviour when buffer_ptr == address - if (cro_address != cro_buffer_ptr) { - result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address, fixed_size); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error unmapping CRO %08X", result.raw); - } - memory_synchronizer.RemoveMemoryBlock(cro_address, cro_buffer_ptr); - } - - Core::CPU().ClearInstructionCache(); - - rb.Push(result); -} - -/** - * LDR_RO::LinkCRO service function - * Inputs: - * 0 : 0x00060042 - * 1 : mapped CRO pointer - * 2 : handle translation descriptor (zero) - * 3 : KProcess handle - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void LinkCRO(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x06, 1, 2); - VAddr cro_address = rp.Pop<u32>(); - Kernel::Handle process = rp.PopHandle(); - - LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, process=0x%08X", cro_address, process); - - CROHelper cro(cro_address); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - if (loaded_crs == 0) { - LOG_ERROR(Service_LDR, "Not initialized"); - rb.Push(ERROR_NOT_INITIALIZED); - return; - } - - if (cro_address & Memory::PAGE_MASK) { - LOG_ERROR(Service_LDR, "CRO address is not aligned"); - rb.Push(ERROR_MISALIGNED_ADDRESS); - return; - } - - if (!cro.IsLoaded()) { - LOG_ERROR(Service_LDR, "Invalid or not loaded CRO"); - rb.Push(ERROR_NOT_LOADED); - return; - } - - LOG_INFO(Service_LDR, "Linking CRO \"%s\"", cro.ModuleName().data()); - - ResultCode result = cro.Link(loaded_crs, false); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error linking CRO %08X", result.raw); - } - - memory_synchronizer.SynchronizeOriginalMemory(); - Core::CPU().ClearInstructionCache(); - - rb.Push(result); -} - -/** - * LDR_RO::UnlinkCRO service function - * Inputs: - * 0 : 0x00070042 - * 1 : mapped CRO pointer - * 2 : handle translation descriptor (zero) - * 3 : KProcess handle - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void UnlinkCRO(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x07, 1, 2); - VAddr cro_address = rp.Pop<u32>(); - Kernel::Handle process = rp.PopHandle(); - - LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, process=0x%08X", cro_address, process); - - CROHelper cro(cro_address); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - if (loaded_crs == 0) { - LOG_ERROR(Service_LDR, "Not initialized"); - rb.Push(ERROR_NOT_INITIALIZED); - return; - } - - if (cro_address & Memory::PAGE_MASK) { - LOG_ERROR(Service_LDR, "CRO address is not aligned"); - rb.Push(ERROR_MISALIGNED_ADDRESS); - return; - } - - if (!cro.IsLoaded()) { - LOG_ERROR(Service_LDR, "Invalid or not loaded CRO"); - rb.Push(ERROR_NOT_LOADED); - return; - } - - LOG_INFO(Service_LDR, "Unlinking CRO \"%s\"", cro.ModuleName().data()); - - ResultCode result = cro.Unlink(loaded_crs); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error unlinking CRO %08X", result.raw); - } - - memory_synchronizer.SynchronizeOriginalMemory(); - Core::CPU().ClearInstructionCache(); - - rb.Push(result); -} - -/** - * LDR_RO::Shutdown service function - * Inputs: - * 0 : 0x00080042 - * 1 : original CRS buffer pointer - * 2 : handle translation descriptor (zero) - * 3 : KProcess handle - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void Shutdown(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x08, 1, 2); - VAddr crs_buffer_ptr = rp.Pop<u32>(); - Kernel::Handle process = rp.PopHandle(); - - LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, process=0x%08X", crs_buffer_ptr, - process); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - if (loaded_crs == 0) { - LOG_ERROR(Service_LDR, "Not initialized"); - rb.Push(ERROR_NOT_INITIALIZED); - return; - } - - CROHelper crs(loaded_crs); - crs.Unrebase(true); - - memory_synchronizer.SynchronizeOriginalMemory(); - - ResultCode result = RESULT_SUCCESS; - - // TODO(wwylele): verify the behaviour when buffer_ptr == address - if (loaded_crs != crs_buffer_ptr) { - result = Kernel::g_current_process->vm_manager.UnmapRange(loaded_crs, crs.GetFileSize()); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error unmapping CRS %08X", result.raw); - } - memory_synchronizer.RemoveMemoryBlock(loaded_crs, crs_buffer_ptr); - } - - loaded_crs = 0; - rb.Push(result); -} - -const Interface::FunctionInfo FunctionTable[] = { - // clang-format off - {0x000100C2, Initialize, "Initialize"}, - {0x00020082, LoadCRR, "LoadCRR"}, - {0x00030042, UnloadCRR, "UnloadCRR"}, - {0x000402C2, LoadCRO<false>, "LoadCRO"}, - {0x000500C2, UnloadCRO, "UnloadCRO"}, - {0x00060042, LinkCRO, "LinkCRO"}, - {0x00070042, UnlinkCRO, "UnlinkCRO"}, - {0x00080042, Shutdown, "Shutdown"}, - {0x000902C2, LoadCRO<true>, "LoadCRO_New"}, - // clang-format on -}; - -LDR_RO::LDR_RO() { - Register(FunctionTable); - - loaded_crs = 0; - memory_synchronizer.Clear(); -} - -} // namespace LDR -} // namespace Service diff --git a/src/core/hle/service/ldr_ro/ldr_ro.h b/src/core/hle/service/ldr_ro/ldr_ro.h deleted file mode 100644 index 0f6fe7b60..000000000 --- a/src/core/hle/service/ldr_ro/ldr_ro.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace LDR { - -class LDR_RO final : public Interface { -public: - LDR_RO(); - - std::string GetPortName() const override { - return "ldr:ro"; - } -}; - -} // namespace LDR -} // namespace Service diff --git a/src/core/hle/service/ldr_ro/memory_synchronizer.cpp b/src/core/hle/service/ldr_ro/memory_synchronizer.cpp deleted file mode 100644 index 0d44bf6bd..000000000 --- a/src/core/hle/service/ldr_ro/memory_synchronizer.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> -#include "common/assert.h" -#include "core/hle/service/ldr_ro/memory_synchronizer.h" - -namespace Service { -namespace LDR { - -auto MemorySynchronizer::FindMemoryBlock(VAddr mapping, VAddr original) { - auto block = std::find_if(memory_blocks.begin(), memory_blocks.end(), - [=](MemoryBlock& b) { return b.original == original; }); - ASSERT(block->mapping == mapping); - return block; -} - -void MemorySynchronizer::Clear() { - memory_blocks.clear(); -} - -void MemorySynchronizer::AddMemoryBlock(VAddr mapping, VAddr original, u32 size) { - memory_blocks.push_back(MemoryBlock{mapping, original, size}); -} - -void MemorySynchronizer::ResizeMemoryBlock(VAddr mapping, VAddr original, u32 size) { - FindMemoryBlock(mapping, original)->size = size; -} - -void MemorySynchronizer::RemoveMemoryBlock(VAddr mapping, VAddr original) { - memory_blocks.erase(FindMemoryBlock(mapping, original)); -} - -void MemorySynchronizer::SynchronizeOriginalMemory() { - for (auto& block : memory_blocks) { - Memory::CopyBlock(block.original, block.mapping, block.size); - } -} - -} // namespace LDR -} // namespace Service diff --git a/src/core/hle/service/ldr_ro/memory_synchronizer.h b/src/core/hle/service/ldr_ro/memory_synchronizer.h deleted file mode 100644 index 438293a58..000000000 --- a/src/core/hle/service/ldr_ro/memory_synchronizer.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <vector> -#include "core/memory.h" - -namespace Service { -namespace LDR { - -/** - * This is a work-around before we implement memory aliasing. - * CRS and CRO are mapped (aliased) to another memory when loading. Games can read - * from both the original buffer and the mapping memory. So we use this to synchronize - * all original buffers with mapping memory after modifying the content. - */ -class MemorySynchronizer { -public: - void Clear(); - - void AddMemoryBlock(VAddr mapping, VAddr original, u32 size); - void ResizeMemoryBlock(VAddr mapping, VAddr original, u32 size); - void RemoveMemoryBlock(VAddr mapping, VAddr original); - - void SynchronizeOriginalMemory(); - -private: - struct MemoryBlock { - VAddr mapping; - VAddr original; - u32 size; - }; - - std::vector<MemoryBlock> memory_blocks; - - auto FindMemoryBlock(VAddr mapping, VAddr original); -}; - -} // namespace LDR -} // namespace Service diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp deleted file mode 100644 index 23e1ff094..000000000 --- a/src/core/hle/service/mic_u.cpp +++ /dev/null @@ -1,346 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/logging/log.h" -#include "core/hle/ipc.h" -#include "core/hle/kernel/event.h" -#include "core/hle/kernel/handle_table.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/shared_memory.h" -#include "core/hle/service/mic_u.h" - -namespace Service { -namespace MIC { - -enum class Encoding : u8 { - PCM8 = 0, - PCM16 = 1, - PCM8Signed = 2, - PCM16Signed = 3, -}; - -enum class SampleRate : u8 { - SampleRate32730 = 0, - SampleRate16360 = 1, - SampleRate10910 = 2, - SampleRate8180 = 3 -}; - -static Kernel::SharedPtr<Kernel::Event> buffer_full_event; -static Kernel::SharedPtr<Kernel::SharedMemory> shared_memory; -static u8 mic_gain = 0; -static bool mic_power = false; -static bool is_sampling = false; -static bool allow_shell_closed; -static bool clamp = false; -static Encoding encoding; -static SampleRate sample_rate; -static s32 audio_buffer_offset; -static u32 audio_buffer_size; -static bool audio_buffer_loop; - -/** - * MIC::MapSharedMem service function - * Inputs: - * 0 : Header Code[0x00010042] - * 1 : Shared-mem size - * 2 : CopyHandleDesc - * 3 : Shared-mem handle - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void MapSharedMem(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 size = cmd_buff[1]; - Kernel::Handle mem_handle = cmd_buff[3]; - shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(mem_handle); - if (shared_memory) { - shared_memory->name = "MIC_U:shared_memory"; - } - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_MIC, "called, size=0x%X, mem_handle=0x%08X", size, mem_handle); -} - -/** - * MIC::UnmapSharedMem service function - * Inputs: - * 0 : Header Code[0x00020000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void UnmapSharedMem(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_MIC, "called"); -} - -/** - * MIC::StartSampling service function - * Inputs: - * 0 : Header Code[0x00030140] - * 1 : Encoding - * 2 : SampleRate - * 3 : Base offset for audio data in sharedmem - * 4 : Size of the audio data in sharedmem - * 5 : Loop at end of buffer - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void StartSampling(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - encoding = static_cast<Encoding>(cmd_buff[1] & 0xFF); - sample_rate = static_cast<SampleRate>(cmd_buff[2] & 0xFF); - audio_buffer_offset = cmd_buff[3]; - audio_buffer_size = cmd_buff[4]; - audio_buffer_loop = (cmd_buff[5] & 0xFF) != 0; - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - is_sampling = true; - LOG_WARNING(Service_MIC, "(STUBBED) called, encoding=%u, sample_rate=%u, " - "audio_buffer_offset=%d, audio_buffer_size=%u, audio_buffer_loop=%u", - static_cast<u32>(encoding), static_cast<u32>(sample_rate), audio_buffer_offset, - audio_buffer_size, audio_buffer_loop); -} - -/** - * MIC::AdjustSampling service function - * Inputs: - * 0 : Header Code[0x00040040] - * 1 : SampleRate - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void AdjustSampling(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - sample_rate = static_cast<SampleRate>(cmd_buff[1] & 0xFF); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_MIC, "(STUBBED) called, sample_rate=%u", static_cast<u32>(sample_rate)); -} - -/** - * MIC::StopSampling service function - * Inputs: - * 0 : Header Code[0x00050000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void StopSampling(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - is_sampling = false; - LOG_WARNING(Service_MIC, "(STUBBED) called"); -} - -/** - * MIC::IsSampling service function - * Inputs: - * 0 : Header Code[0x00060000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : 0 = sampling, non-zero = sampling - */ -static void IsSampling(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = is_sampling; - LOG_WARNING(Service_MIC, "(STUBBED) called"); -} - -/** - * MIC::GetBufferFullEvent service function - * Inputs: - * 0 : Header Code[0x00070000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 3 : Event handle - */ -static void GetBufferFullEvent(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[3] = Kernel::g_handle_table.Create(buffer_full_event).Unwrap(); - LOG_WARNING(Service_MIC, "(STUBBED) called"); -} - -/** - * MIC::SetGain service function - * Inputs: - * 0 : Header Code[0x00080040] - * 1 : Gain - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void SetGain(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - mic_gain = cmd_buff[1] & 0xFF; - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_MIC, "(STUBBED) called, mic_gain=%u", mic_gain); -} - -/** - * MIC::GetGain service function - * Inputs: - * 0 : Header Code[0x00090000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Gain - */ -static void GetGain(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = mic_gain; - LOG_WARNING(Service_MIC, "(STUBBED) called"); -} - -/** - * MIC::SetPower service function - * Inputs: - * 0 : Header Code[0x000A0040] - * 1 : Power (0 = off, 1 = on) - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void SetPower(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - mic_power = (cmd_buff[1] & 0xFF) != 0; - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_MIC, "(STUBBED) called, mic_power=%u", mic_power); -} - -/** - * MIC::GetPower service function - * Inputs: - * 0 : Header Code[0x000B0000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Power - */ -static void GetPower(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = mic_power; - LOG_WARNING(Service_MIC, "(STUBBED) called"); -} - -/** - * MIC::SetIirFilterMic service function - * Inputs: - * 0 : Header Code[0x000C0042] - * 1 : Size - * 2 : (Size << 4) | 0xA - * 3 : Pointer to IIR Filter Data - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void SetIirFilterMic(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 size = cmd_buff[1]; - VAddr buffer = cmd_buff[3]; - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_MIC, "(STUBBED) called, size=0x%X, buffer=0x%08X", size, buffer); -} - -/** - * MIC::SetClamp service function - * Inputs: - * 0 : Header Code[0x000D0040] - * 1 : Clamp (0 = don't clamp, non-zero = clamp) - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void SetClamp(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - clamp = (cmd_buff[1] & 0xFF) != 0; - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_MIC, "(STUBBED) called, clamp=%u", clamp); -} - -/** - * MIC::GetClamp service function - * Inputs: - * 0 : Header Code[0x000E0000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Clamp (0 = don't clamp, non-zero = clamp) - */ -static void GetClamp(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = clamp; - LOG_WARNING(Service_MIC, "(STUBBED) called"); -} - -/** - * MIC::SetAllowShellClosed service function - * Inputs: - * 0 : Header Code[0x000D0040] - * 1 : Sampling allowed while shell closed (0 = disallow, non-zero = allow) - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void SetAllowShellClosed(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - allow_shell_closed = (cmd_buff[1] & 0xFF) != 0; - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_MIC, "(STUBBED) called, allow_shell_closed=%u", allow_shell_closed); -} - -/** - * MIC_U::SetClientVersion service function - * Inputs: - * 1 : Used SDK Version - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void SetClientVersion(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - const u32 version = cmd_buff[1]; - self->SetVersion(version); - - LOG_WARNING(Service_MIC, "(STUBBED) called, version: 0x%08X", version); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error -} - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010042, MapSharedMem, "MapSharedMem"}, - {0x00020000, UnmapSharedMem, "UnmapSharedMem"}, - {0x00030140, StartSampling, "StartSampling"}, - {0x00040040, AdjustSampling, "AdjustSampling"}, - {0x00050000, StopSampling, "StopSampling"}, - {0x00060000, IsSampling, "IsSampling"}, - {0x00070000, GetBufferFullEvent, "GetBufferFullEvent"}, - {0x00080040, SetGain, "SetGain"}, - {0x00090000, GetGain, "GetGain"}, - {0x000A0040, SetPower, "SetPower"}, - {0x000B0000, GetPower, "GetPower"}, - {0x000C0042, SetIirFilterMic, "SetIirFilterMic"}, - {0x000D0040, SetClamp, "SetClamp"}, - {0x000E0000, GetClamp, "GetClamp"}, - {0x000F0040, SetAllowShellClosed, "SetAllowShellClosed"}, - {0x00100040, SetClientVersion, "SetClientVersion"}, -}; - -MIC_U::MIC_U() { - Register(FunctionTable); - shared_memory = nullptr; - buffer_full_event = - Kernel::Event::Create(Kernel::ResetType::OneShot, "MIC_U::buffer_full_event"); - mic_gain = 0; - mic_power = false; - is_sampling = false; - clamp = false; -} - -MIC_U::~MIC_U() { - shared_memory = nullptr; - buffer_full_event = nullptr; -} - -} // namespace MIC -} // namespace Service diff --git a/src/core/hle/service/mic_u.h b/src/core/hle/service/mic_u.h deleted file mode 100644 index ec2b67ab8..000000000 --- a/src/core/hle/service/mic_u.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace MIC { - -class MIC_U final : public Interface { -public: - MIC_U(); - ~MIC_U(); - - std::string GetPortName() const override { - return "mic:u"; - } -}; - -} // namespace MIC -} // namespace Service diff --git a/src/core/hle/service/mvd/mvd.cpp b/src/core/hle/service/mvd/mvd.cpp deleted file mode 100644 index 9416fe5d6..000000000 --- a/src/core/hle/service/mvd/mvd.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/mvd/mvd.h" -#include "core/hle/service/mvd/mvd_std.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace MVD { - -void Init() { - AddService(new MVD_STD()); -} - -} // namespace MVD -} // namespace Service diff --git a/src/core/hle/service/mvd/mvd.h b/src/core/hle/service/mvd/mvd.h deleted file mode 100644 index 7b212e839..000000000 --- a/src/core/hle/service/mvd/mvd.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service { -namespace MVD { - -/// Initializes all MVD services. -void Init(); - -} // namespace MVD -} // namespace Service diff --git a/src/core/hle/service/mvd/mvd_std.cpp b/src/core/hle/service/mvd/mvd_std.cpp deleted file mode 100644 index fd7ca87d3..000000000 --- a/src/core/hle/service/mvd/mvd_std.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/mvd/mvd_std.h" - -namespace Service { -namespace MVD { - -const Interface::FunctionInfo FunctionTable[] = { - // clang-format off - {0x00010082, nullptr, "Initialize"}, - {0x00020000, nullptr, "Shutdown"}, - {0x00030300, nullptr, "CalculateWorkBufSize"}, - {0x000400C0, nullptr, "CalculateImageSize"}, - {0x00080142, nullptr, "ProcessNALUnit"}, - {0x00090042, nullptr, "ControlFrameRendering"}, - {0x000A0000, nullptr, "GetStatus"}, - {0x000B0000, nullptr, "GetStatusOther"}, - {0x001D0042, nullptr, "GetConfig"}, - {0x001E0044, nullptr, "SetConfig"}, - {0x001F0902, nullptr, "SetOutputBuffer"}, - {0x00210100, nullptr, "OverrideOutputBuffers"} - // clang-format on -}; - -MVD_STD::MVD_STD() { - Register(FunctionTable); -} - -} // namespace MVD -} // namespace Service diff --git a/src/core/hle/service/mvd/mvd_std.h b/src/core/hle/service/mvd/mvd_std.h deleted file mode 100644 index 7db9e2e50..000000000 --- a/src/core/hle/service/mvd/mvd_std.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace MVD { - -class MVD_STD final : public Interface { -public: - MVD_STD(); - - std::string GetPortName() const override { - return "mvd:std"; - } -}; - -} // namespace MVD -} // namespace Service diff --git a/src/core/hle/service/ndm/ndm.cpp b/src/core/hle/service/ndm/ndm.cpp deleted file mode 100644 index 096c0cdac..000000000 --- a/src/core/hle/service/ndm/ndm.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <array> -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/hle/ipc.h" -#include "core/hle/service/ndm/ndm.h" -#include "core/hle/service/ndm/ndm_u.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace NDM { - -enum : u32 { - DEFAULT_RETRY_INTERVAL = 10, - DEFAULT_SCAN_INTERVAL = 30, -}; - -static DaemonMask daemon_bit_mask = DaemonMask::Default; -static DaemonMask default_daemon_bit_mask = DaemonMask::Default; -static std::array<DaemonStatus, 4> daemon_status = { - DaemonStatus::Idle, DaemonStatus::Idle, DaemonStatus::Idle, DaemonStatus::Idle, -}; -static ExclusiveState exclusive_state = ExclusiveState::None; -static u32 scan_interval = DEFAULT_SCAN_INTERVAL; -static u32 retry_interval = DEFAULT_RETRY_INTERVAL; -static bool daemon_lock_enabled = false; - -void EnterExclusiveState(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - exclusive_state = static_cast<ExclusiveState>(cmd_buff[1]); - - cmd_buff[0] = IPC::MakeHeader(0x1, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) exclusive_state=0x%08X ", exclusive_state); -} - -void LeaveExclusiveState(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - exclusive_state = ExclusiveState::None; - - cmd_buff[0] = IPC::MakeHeader(0x2, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) exclusive_state=0x%08X ", exclusive_state); -} - -void QueryExclusiveMode(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x3, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = static_cast<u32>(exclusive_state); - LOG_WARNING(Service_NDM, "(STUBBED) exclusive_state=0x%08X ", exclusive_state); -} - -void LockState(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - daemon_lock_enabled = true; - - cmd_buff[0] = IPC::MakeHeader(0x4, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) daemon_lock_enabled=0x%08X ", daemon_lock_enabled); -} - -void UnlockState(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - daemon_lock_enabled = false; - - cmd_buff[0] = IPC::MakeHeader(0x5, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) daemon_lock_enabled=0x%08X ", daemon_lock_enabled); -} - -void SuspendDaemons(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 bit_mask = cmd_buff[1] & 0xF; - daemon_bit_mask = - static_cast<DaemonMask>(static_cast<u32>(default_daemon_bit_mask) & ~bit_mask); - for (size_t index = 0; index < daemon_status.size(); ++index) { - if (bit_mask & (1 << index)) { - daemon_status[index] = DaemonStatus::Suspended; - } - } - - cmd_buff[0] = IPC::MakeHeader(0x6, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) daemon_bit_mask=0x%08X ", daemon_bit_mask); -} - -void ResumeDaemons(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 bit_mask = cmd_buff[1] & 0xF; - daemon_bit_mask = static_cast<DaemonMask>(static_cast<u32>(daemon_bit_mask) | bit_mask); - for (size_t index = 0; index < daemon_status.size(); ++index) { - if (bit_mask & (1 << index)) { - daemon_status[index] = DaemonStatus::Idle; - } - } - - cmd_buff[0] = IPC::MakeHeader(0x7, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) daemon_bit_mask=0x%08X ", daemon_bit_mask); -} - -void SuspendScheduler(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x8, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) called"); -} - -void ResumeScheduler(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) called"); -} - -void QueryStatus(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 daemon = cmd_buff[1] & 0xF; - - cmd_buff[0] = IPC::MakeHeader(0xD, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = static_cast<u32>(daemon_status.at(daemon)); - LOG_WARNING(Service_NDM, "(STUBBED) daemon=0x%08X, daemon_status=0x%08X", daemon, cmd_buff[2]); -} - -void GetDaemonDisableCount(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 daemon = cmd_buff[1] & 0xF; - - cmd_buff[0] = IPC::MakeHeader(0xE, 3, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = 0; - cmd_buff[3] = 0; - LOG_WARNING(Service_NDM, "(STUBBED) daemon=0x%08X", daemon); -} - -void GetSchedulerDisableCount(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0xF, 3, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = 0; - cmd_buff[3] = 0; - LOG_WARNING(Service_NDM, "(STUBBED) called"); -} - -void SetScanInterval(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - scan_interval = cmd_buff[1]; - - cmd_buff[0] = IPC::MakeHeader(0x10, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) scan_interval=0x%08X ", scan_interval); -} - -void GetScanInterval(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x11, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = scan_interval; - LOG_WARNING(Service_NDM, "(STUBBED) scan_interval=0x%08X ", scan_interval); -} - -void SetRetryInterval(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - retry_interval = cmd_buff[1]; - - cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) retry_interval=0x%08X ", retry_interval); -} - -void GetRetryInterval(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x13, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = retry_interval; - LOG_WARNING(Service_NDM, "(STUBBED) retry_interval=0x%08X ", retry_interval); -} - -void OverrideDefaultDaemons(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 bit_mask = cmd_buff[1] & 0xF; - default_daemon_bit_mask = static_cast<DaemonMask>(bit_mask); - daemon_bit_mask = default_daemon_bit_mask; - for (size_t index = 0; index < daemon_status.size(); ++index) { - if (bit_mask & (1 << index)) { - daemon_status[index] = DaemonStatus::Idle; - } - } - - cmd_buff[0] = IPC::MakeHeader(0x14, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) default_daemon_bit_mask=0x%08X ", default_daemon_bit_mask); -} - -void ResetDefaultDaemons(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - default_daemon_bit_mask = DaemonMask::Default; - - cmd_buff[0] = IPC::MakeHeader(0x15, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) default_daemon_bit_mask=0x%08X ", default_daemon_bit_mask); -} - -void GetDefaultDaemons(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x16, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = static_cast<u32>(default_daemon_bit_mask); - LOG_WARNING(Service_NDM, "(STUBBED) default_daemon_bit_mask=0x%08X ", default_daemon_bit_mask); -} - -void ClearHalfAwakeMacFilter(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x17, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) called"); -} - -void Init() { - AddService(new NDM_U_Interface); -} - -void Shutdown() {} - -} // namespace NDM -} // namespace Service diff --git a/src/core/hle/service/ndm/ndm.h b/src/core/hle/service/ndm/ndm.h deleted file mode 100644 index 979e7fcf1..000000000 --- a/src/core/hle/service/ndm/ndm.h +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_types.h" - -namespace Service { - -class Interface; - -namespace NDM { - -enum class Daemon : u32 { - Cec = 0, - Boss = 1, - Nim = 2, - Friend = 3, -}; - -enum class DaemonMask : u32 { - None = 0, - Cec = (1 << static_cast<u32>(Daemon::Cec)), - Boss = (1 << static_cast<u32>(Daemon::Boss)), - Nim = (1 << static_cast<u32>(Daemon::Nim)), - Friend = (1 << static_cast<u32>(Daemon::Friend)), - Default = Cec | Friend, - All = Cec | Boss | Nim | Friend, -}; - -enum class DaemonStatus : u32 { Busy = 0, Idle = 1, Suspending = 2, Suspended = 3 }; - -enum class ExclusiveState : u32 { - None = 0, - Infrastructure = 1, - LocalCommunications = 2, - Streetpass = 3, - StreetpassData = 4, -}; - -/** - * NDM::EnterExclusiveState service function - * Inputs: - * 0 : Header code [0x00010042] - * 1 : Exclusive State - * 2 : 0x20 - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void EnterExclusiveState(Service::Interface* self); - -/** - * NDM::LeaveExclusiveState service function - * Inputs: - * 0 : Header code [0x00020002] - * 1 : 0x20 - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void LeaveExclusiveState(Service::Interface* self); - -/** - * NDM::QueryExclusiveMode service function - * Inputs: - * 0 : Header code [0x00030000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Current Exclusive State - */ -void QueryExclusiveMode(Service::Interface* self); - -/** - * NDM::LockState service function - * Inputs: - * 0 : Header code [0x00040002] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void LockState(Service::Interface* self); - -/** - * NDM::UnlockState service function - * Inputs: - * 0 : Header code [0x00050002] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void UnlockState(Service::Interface* self); - -/** - * NDM::SuspendDaemons service function - * Inputs: - * 0 : Header code [0x00060040] - * 1 : Daemon bit mask - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void SuspendDaemons(Service::Interface* self); - -/** - * NDM::ResumeDaemons service function - * Inputs: - * 0 : Header code [0x00070040] - * 1 : Daemon bit mask - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void ResumeDaemons(Service::Interface* self); - -/** - * NDM::SuspendScheduler service function - * Inputs: - * 0 : Header code [0x00080040] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void SuspendScheduler(Service::Interface* self); - -/** - * NDM::ResumeScheduler service function - * Inputs: - * 0 : Header code [0x00090000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void ResumeScheduler(Service::Interface* self); - -/** - * NDM::QueryStatus service function - * Inputs: - * 0 : Header code [0x000D0040] - * 1 : Daemon - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Daemon status - */ -void QueryStatus(Service::Interface* self); - -/** - * NDM::GetDaemonDisableCount service function - * Inputs: - * 0 : Header code [0x000E0040] - * 1 : Daemon - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Current process disable count - * 3 : Total disable count - */ -void GetDaemonDisableCount(Service::Interface* self); - -/** - * NDM::GetSchedulerDisableCount service function - * Inputs: - * 0 : Header code [0x000F0000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Current process disable count - * 3 : Total disable count - */ -void GetSchedulerDisableCount(Service::Interface* self); - -/** - * NDM::SetScanInterval service function - * Inputs: - * 0 : Header code [0x00100040] - * 1 : Interval (default = 30) - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void SetScanInterval(Service::Interface* self); - -/** - * NDM::GetScanInterval service function - * Inputs: - * 0 : Header code [0x00110000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Interval (default = 30) - */ -void GetScanInterval(Service::Interface* self); - -/** - * NDM::SetRetryInterval service function - * Inputs: - * 0 : Header code [0x00120040] - * 1 : Interval (default = 10) - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void SetRetryInterval(Service::Interface* self); - -/** - * NDM::GetRetryInterval service function - * Inputs: - * 0 : Header code [0x00130000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Interval (default = 10) - */ -void GetRetryInterval(Service::Interface* self); - -/** - * NDM::OverrideDefaultDaemons service function - * Inputs: - * 0 : Header code [0x00140040] - * 1 : Daemon bit mask - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void OverrideDefaultDaemons(Service::Interface* self); - -/** - * NDM::ResetDefaultDaemons service function - * Inputs: - * 0 : Header code [0x00150000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void ResetDefaultDaemons(Service::Interface* self); - -/** - * NDM::GetDefaultDaemons service function - * Inputs: - * 0 : Header code [0x00160000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Daemon bit mask - * Note: - * Gets the current default daemon bit mask. The default value is (DAEMONMASK_CEC | - * DAEMONMASK_FRIENDS) - */ -void GetDefaultDaemons(Service::Interface* self); - -/** - * NDM::ClearHalfAwakeMacFilter service function - * Inputs: - * 0 : Header code [0x00170000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void ClearHalfAwakeMacFilter(Service::Interface* self); - -/// Initialize NDM service -void Init(); - -/// Shutdown NDM service -void Shutdown(); - -} // namespace NDM -} // namespace Service diff --git a/src/core/hle/service/ndm/ndm_u.cpp b/src/core/hle/service/ndm/ndm_u.cpp deleted file mode 100644 index f5c7a341a..000000000 --- a/src/core/hle/service/ndm/ndm_u.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/ndm/ndm.h" -#include "core/hle/service/ndm/ndm_u.h" - -namespace Service { -namespace NDM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010042, EnterExclusiveState, "EnterExclusiveState"}, - {0x00020002, LeaveExclusiveState, "LeaveExclusiveState"}, - {0x00030000, QueryExclusiveMode, "QueryExclusiveMode"}, - {0x00040002, LockState, "LockState"}, - {0x00050002, UnlockState, "UnlockState"}, - {0x00060040, SuspendDaemons, "SuspendDaemons"}, - {0x00070040, ResumeDaemons, "ResumeDaemons"}, - {0x00080040, SuspendScheduler, "SuspendScheduler"}, - {0x00090000, ResumeScheduler, "ResumeScheduler"}, - {0x000A0000, nullptr, "GetCurrentState"}, - {0x000B0000, nullptr, "GetTargetState"}, - {0x000C0000, nullptr, "<Stubbed>"}, - {0x000D0040, QueryStatus, "QueryStatus"}, - {0x000E0040, GetDaemonDisableCount, "GetDaemonDisableCount"}, - {0x000F0000, GetSchedulerDisableCount, "GetSchedulerDisableCount"}, - {0x00100040, SetScanInterval, "SetScanInterval"}, - {0x00110000, GetScanInterval, "GetScanInterval"}, - {0x00120040, SetRetryInterval, "SetRetryInterval"}, - {0x00130000, GetRetryInterval, "GetRetryInterval"}, - {0x00140040, OverrideDefaultDaemons, "OverrideDefaultDaemons"}, - {0x00150000, ResetDefaultDaemons, "ResetDefaultDaemons"}, - {0x00160000, GetDefaultDaemons, "GetDefaultDaemons"}, - {0x00170000, ClearHalfAwakeMacFilter, "ClearHalfAwakeMacFilter"}, -}; - -NDM_U_Interface::NDM_U_Interface() { - Register(FunctionTable); -} - -} // namespace NDM -} // namespace Service diff --git a/src/core/hle/service/ndm/ndm_u.h b/src/core/hle/service/ndm/ndm_u.h deleted file mode 100644 index d567abc84..000000000 --- a/src/core/hle/service/ndm/ndm_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NDM { - -class NDM_U_Interface : public Service::Interface { -public: - NDM_U_Interface(); - - std::string GetPortName() const override { - return "ndm:u"; - } -}; - -} // namespace NDM -} // namespace Service diff --git a/src/core/hle/service/news/news.cpp b/src/core/hle/service/news/news.cpp deleted file mode 100644 index 8b70ec45b..000000000 --- a/src/core/hle/service/news/news.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/logging/log.h" -#include "core/hle/service/news/news.h" -#include "core/hle/service/news/news_s.h" -#include "core/hle/service/news/news_u.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace NEWS { - -void Init() { - using namespace Kernel; - - AddService(new NEWS_S_Interface); - AddService(new NEWS_U_Interface); -} - -void Shutdown() {} - -} // namespace NEWS - -} // namespace Service diff --git a/src/core/hle/service/news/news.h b/src/core/hle/service/news/news.h deleted file mode 100644 index 46a3ffcb5..000000000 --- a/src/core/hle/service/news/news.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service { -namespace NEWS { - -/// Initialize NEWS service(s) -void Init(); - -/// Shutdown NEWS service(s) -void Shutdown(); - -} // namespace NEWS -} // namespace Service diff --git a/src/core/hle/service/news/news_s.cpp b/src/core/hle/service/news/news_s.cpp deleted file mode 100644 index dda3d0f6a..000000000 --- a/src/core/hle/service/news/news_s.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/news/news.h" -#include "core/hle/service/news/news_s.h" - -namespace Service { -namespace NEWS { - -const Interface::FunctionInfo FunctionTable[] = { - {0x000100C6, nullptr, "AddNotification"}, - {0x00050000, nullptr, "GetTotalNotifications"}, - {0x00060042, nullptr, "SetNewsDBHeader"}, - {0x00070082, nullptr, "SetNotificationHeader"}, - {0x00080082, nullptr, "SetNotificationMessage"}, - {0x00090082, nullptr, "SetNotificationImage"}, - {0x000A0042, nullptr, "GetNewsDBHeader"}, - {0x000B0082, nullptr, "GetNotificationHeader"}, - {0x000C0082, nullptr, "GetNotificationMessage"}, - {0x000D0082, nullptr, "GetNotificationImage"}, - {0x000E0040, nullptr, "SetInfoLEDPattern"}, - {0x00120082, nullptr, "GetNotificationHeaderOther"}, - {0x00130000, nullptr, "WriteNewsDBSavedata"}, -}; - -NEWS_S_Interface::NEWS_S_Interface() { - Register(FunctionTable); -} - -} // namespace NEWS -} // namespace Service diff --git a/src/core/hle/service/news/news_s.h b/src/core/hle/service/news/news_s.h deleted file mode 100644 index f58b969a8..000000000 --- a/src/core/hle/service/news/news_s.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NEWS { - -class NEWS_S_Interface : public Service::Interface { -public: - NEWS_S_Interface(); - - std::string GetPortName() const override { - return "news:s"; - } -}; - -} // namespace NEWS -} // namespace Service diff --git a/src/core/hle/service/news/news_u.cpp b/src/core/hle/service/news/news_u.cpp deleted file mode 100644 index a07e466de..000000000 --- a/src/core/hle/service/news/news_u.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/news/news_u.h" - -namespace Service { -namespace NEWS { - -const Interface::FunctionInfo FunctionTable[] = { - {0x000100C6, nullptr, "AddNotification"}, -}; - -NEWS_U_Interface::NEWS_U_Interface() { - Register(FunctionTable); -} - -} // namespace NEWS -} // namespace Service diff --git a/src/core/hle/service/news/news_u.h b/src/core/hle/service/news/news_u.h deleted file mode 100644 index 2720053d0..000000000 --- a/src/core/hle/service/news/news_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NEWS { - -class NEWS_U_Interface : public Service::Interface { -public: - NEWS_U_Interface(); - - std::string GetPortName() const override { - return "news:u"; - } -}; - -} // namespace NEWS -} // namespace Service diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp deleted file mode 100644 index cb09ed0b7..000000000 --- a/src/core/hle/service/nfc/nfc.cpp +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/ipc.h" -#include "core/hle/kernel/event.h" -#include "core/hle/kernel/handle_table.h" -#include "core/hle/service/nfc/nfc.h" -#include "core/hle/service/nfc/nfc_m.h" -#include "core/hle/service/nfc/nfc_u.h" - -namespace Service { -namespace NFC { - -static Kernel::SharedPtr<Kernel::Event> tag_in_range_event; -static Kernel::SharedPtr<Kernel::Event> tag_out_of_range_event; -static TagState nfc_tag_state = TagState::NotInitialized; -static CommunicationStatus nfc_status = CommunicationStatus::NfcInitialized; - -void Initialize(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u8 param = static_cast<u8>(cmd_buff[1] & 0xFF); - - nfc_tag_state = TagState::NotScanning; - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NFC, "(STUBBED) called, param=%u", param); -} - -void Shutdown(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u8 param = static_cast<u8>(cmd_buff[1] & 0xFF); - nfc_tag_state = TagState::NotInitialized; - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NFC, "(STUBBED) called, param=%u", param); -} - -void StartCommunication(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NFC, "(STUBBED) called"); -} - -void StopCommunication(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NFC, "(STUBBED) called"); -} - -void StartTagScanning(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - nfc_tag_state = TagState::TagInRange; - tag_in_range_event->Signal(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NFC, "(STUBBED) called"); -} - -void StopTagScanning(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - nfc_tag_state = TagState::NotScanning; - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NFC, "(STUBBED) called"); -} - -void LoadAmiiboData(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - nfc_tag_state = TagState::TagDataLoaded; - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NFC, "(STUBBED) called"); -} - -void ResetTagScanState(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - nfc_tag_state = TagState::NotScanning; - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NFC, "(STUBBED) called"); -} - -void GetTagInRangeEvent(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0xB, 1, 2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = IPC::CopyHandleDesc(); - cmd_buff[3] = Kernel::g_handle_table.Create(tag_in_range_event).Unwrap(); - LOG_WARNING(Service_NFC, "(STUBBED) called"); -} - -void GetTagOutOfRangeEvent(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0xC, 1, 2); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = IPC::CopyHandleDesc(); - cmd_buff[3] = Kernel::g_handle_table.Create(tag_out_of_range_event).Unwrap(); - LOG_WARNING(Service_NFC, "(STUBBED) called"); -} - -void GetTagState(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = static_cast<u8>(nfc_tag_state); - LOG_DEBUG(Service_NFC, "(STUBBED) called"); -} - -void CommunicationGetStatus(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = static_cast<u8>(nfc_status); - LOG_DEBUG(Service_NFC, "(STUBBED) called"); -} - -void Init() { - AddService(new NFC_M()); - AddService(new NFC_U()); - - tag_in_range_event = - Kernel::Event::Create(Kernel::ResetType::OneShot, "NFC::tag_in_range_event"); - tag_out_of_range_event = - Kernel::Event::Create(Kernel::ResetType::OneShot, "NFC::tag_out_range_event"); - nfc_tag_state = TagState::NotInitialized; -} - -void Shutdown() { - tag_in_range_event = nullptr; - tag_out_of_range_event = nullptr; -} - -} // namespace NFC -} // namespace Service diff --git a/src/core/hle/service/nfc/nfc.h b/src/core/hle/service/nfc/nfc.h deleted file mode 100644 index a013bdae7..000000000 --- a/src/core/hle/service/nfc/nfc.h +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_types.h" - -namespace Service { - -class Interface; - -namespace NFC { - -enum class TagState : u8 { - NotInitialized = 0, - NotScanning = 1, - Scanning = 2, - TagInRange = 3, - TagOutOfRange = 4, - TagDataLoaded = 5, -}; - -enum class CommunicationStatus : u8 { - AttemptInitialize = 1, - NfcInitialized = 2, -}; - -/** - * NFC::Initialize service function - * Inputs: - * 0 : Header code [0x00010040] - * 1 : (u8) unknown parameter. Can be either value 0x1 or 0x2 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void Initialize(Interface* self); - -/** - * NFC::Shutdown service function - * Inputs: - * 0 : Header code [0x00020040] - * 1 : (u8) unknown parameter - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void Shutdown(Interface* self); - -/** - * NFC::StartCommunication service function - * Inputs: - * 0 : Header code [0x00030000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void StartCommunication(Interface* self); - -/** - * NFC::StopCommunication service function - * Inputs: - * 0 : Header code [0x00040000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void StopCommunication(Interface* self); - -/** - * NFC::StartTagScanning service function - * Inputs: - * 0 : Header code [0x00050040] - * 1 : (u16) unknown. This is normally 0x0 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void StartTagScanning(Interface* self); - -/** - * NFC::StopTagScanning service function - * Inputs: - * 0 : Header code [0x00060000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void StopTagScanning(Interface* self); - -/** - * NFC::LoadAmiiboData service function - * Inputs: - * 0 : Header code [0x00070000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void LoadAmiiboData(Interface* self); - -/** - * NFC::ResetTagScanState service function - * Inputs: - * 0 : Header code [0x00080000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void ResetTagScanState(Interface* self); - -/** - * NFC::GetTagInRangeEvent service function - * Inputs: - * 0 : Header code [0x000B0000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Copy handle descriptor - * 3 : Event Handle - */ -void GetTagInRangeEvent(Interface* self); - -/** - * NFC::GetTagOutOfRangeEvent service function - * Inputs: - * 0 : Header code [0x000C0000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Copy handle descriptor - * 3 : Event Handle - */ -void GetTagOutOfRangeEvent(Interface* self); - -/** - * NFC::GetTagState service function - * Inputs: - * 0 : Header code [0x000D0000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : (u8) Tag state - */ -void GetTagState(Interface* self); - -/** - * NFC::CommunicationGetStatus service function - * Inputs: - * 0 : Header code [0x000F0000] - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : (u8) Communication state - */ -void CommunicationGetStatus(Interface* self); - -/// Initialize all NFC services. -void Init(); - -/// Shutdown all NFC services. -void Shutdown(); - -} // namespace NFC -} // namespace Service diff --git a/src/core/hle/service/nfc/nfc_m.cpp b/src/core/hle/service/nfc/nfc_m.cpp deleted file mode 100644 index ebe637650..000000000 --- a/src/core/hle/service/nfc/nfc_m.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nfc/nfc.h" -#include "core/hle/service/nfc/nfc_m.h" - -namespace Service { -namespace NFC { - -const Interface::FunctionInfo FunctionTable[] = { - // clang-format off - // nfc:u shared commands - {0x00010040, Initialize, "Initialize"}, - {0x00020040, Shutdown, "Shutdown"}, - {0x00030000, StartCommunication, "StartCommunication"}, - {0x00040000, StopCommunication, "StopCommunication"}, - {0x00050040, StartTagScanning, "StartTagScanning"}, - {0x00060000, StopTagScanning, "StopTagScanning"}, - {0x00070000, LoadAmiiboData, "LoadAmiiboData"}, - {0x00080000, ResetTagScanState, "ResetTagScanState"}, - {0x00090002, nullptr, "UpdateStoredAmiiboData"}, - {0x000B0000, GetTagInRangeEvent, "GetTagInRangeEvent"}, - {0x000C0000, GetTagOutOfRangeEvent, "GetTagOutOfRangeEvent"}, - {0x000D0000, GetTagState, "GetTagState"}, - {0x000F0000, CommunicationGetStatus, "CommunicationGetStatus"}, - {0x00100000, nullptr, "GetTagInfo2"}, - {0x00110000, nullptr, "GetTagInfo"}, - {0x00120000, nullptr, "CommunicationGetResult"}, - {0x00130040, nullptr, "OpenAppData"}, - {0x00140384, nullptr, "InitializeWriteAppData"}, - {0x00150040, nullptr, "ReadAppData"}, - {0x00160242, nullptr, "WriteAppData"}, - {0x00170000, nullptr, "GetAmiiboSettings"}, - {0x00180000, nullptr, "GetAmiiboConfig"}, - {0x00190000, nullptr, "GetAppDataInitStruct"}, - // nfc:m - {0x04040A40, nullptr, "SetAmiiboSettings"} - // clang-format on -}; - -NFC_M::NFC_M() { - Register(FunctionTable); -} - -} // namespace NFC -} // namespace Service diff --git a/src/core/hle/service/nfc/nfc_m.h b/src/core/hle/service/nfc/nfc_m.h deleted file mode 100644 index fae75535b..000000000 --- a/src/core/hle/service/nfc/nfc_m.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NFC { - -class NFC_M final : public Interface { -public: - NFC_M(); - - std::string GetPortName() const override { - return "nfc:m"; - } -}; - -} // namespace NFC -} // namespace Service diff --git a/src/core/hle/service/nfc/nfc_u.cpp b/src/core/hle/service/nfc/nfc_u.cpp deleted file mode 100644 index 5a40c7874..000000000 --- a/src/core/hle/service/nfc/nfc_u.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nfc/nfc.h" -#include "core/hle/service/nfc/nfc_u.h" - -namespace Service { -namespace NFC { - -const Interface::FunctionInfo FunctionTable[] = { - // clang-format off - {0x00010040, Initialize, "Initialize"}, - {0x00020040, Shutdown, "Shutdown"}, - {0x00030000, StartCommunication, "StartCommunication"}, - {0x00040000, StopCommunication, "StopCommunication"}, - {0x00050040, StartTagScanning, "StartTagScanning"}, - {0x00060000, StopTagScanning, "StopTagScanning"}, - {0x00070000, LoadAmiiboData, "LoadAmiiboData"}, - {0x00080000, ResetTagScanState, "ResetTagScanState"}, - {0x00090002, nullptr, "UpdateStoredAmiiboData"}, - {0x000B0000, GetTagInRangeEvent, "GetTagInRangeEvent"}, - {0x000C0000, GetTagOutOfRangeEvent, "GetTagOutOfRangeEvent"}, - {0x000D0000, GetTagState, "GetTagState"}, - {0x000F0000, CommunicationGetStatus, "CommunicationGetStatus"}, - {0x00100000, nullptr, "GetTagInfo2"}, - {0x00110000, nullptr, "GetTagInfo"}, - {0x00120000, nullptr, "CommunicationGetResult"}, - {0x00130040, nullptr, "OpenAppData"}, - {0x00140384, nullptr, "InitializeWriteAppData"}, - {0x00150040, nullptr, "ReadAppData"}, - {0x00160242, nullptr, "WriteAppData"}, - {0x00170000, nullptr, "GetAmiiboSettings"}, - {0x00180000, nullptr, "GetAmiiboConfig"}, - {0x00190000, nullptr, "GetAppDataInitStruct"}, - // clang-format on -}; - -NFC_U::NFC_U() { - Register(FunctionTable); -} - -} // namespace NFC -} // namespace Service diff --git a/src/core/hle/service/nfc/nfc_u.h b/src/core/hle/service/nfc/nfc_u.h deleted file mode 100644 index eb7507314..000000000 --- a/src/core/hle/service/nfc/nfc_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NFC { - -class NFC_U final : public Interface { -public: - NFC_U(); - - std::string GetPortName() const override { - return "nfc:u"; - } -}; - -} // namespace NFC -} // namespace Service diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp deleted file mode 100644 index b10d5852b..000000000 --- a/src/core/hle/service/nim/nim.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/hle/ipc.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/event.h" -#include "core/hle/service/nim/nim.h" -#include "core/hle/service/nim/nim_aoc.h" -#include "core/hle/service/nim/nim_s.h" -#include "core/hle/service/nim/nim_u.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace NIM { - -static Kernel::SharedPtr<Kernel::Event> nim_system_update_event; - -void CheckForSysUpdateEvent(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x5, 0, 0); // 0x50000 - IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles(Kernel::g_handle_table.Create(nim_system_update_event).Unwrap()); - LOG_TRACE(Service_NIM, "called"); -} - -void CheckSysUpdateAvailable(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // No update available - - LOG_WARNING(Service_NIM, "(STUBBED) called"); -} - -void Init() { - using namespace Kernel; - - AddService(new NIM_AOC_Interface); - AddService(new NIM_S_Interface); - AddService(new NIM_U_Interface); - - nim_system_update_event = Kernel::Event::Create(ResetType::OneShot, "NIM System Update Event"); -} - -void Shutdown() { - nim_system_update_event = nullptr; -} - -} // namespace NIM - -} // namespace Service diff --git a/src/core/hle/service/nim/nim.h b/src/core/hle/service/nim/nim.h deleted file mode 100644 index dbf605e5a..000000000 --- a/src/core/hle/service/nim/nim.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service { - -class Interface; - -namespace NIM { - -/** - * NIM::CheckForSysUpdateEvent service function - * Inputs: - * 1 : None - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Copy handle descriptor - * 3 : System Update event handle - */ -void CheckForSysUpdateEvent(Service::Interface* self); - -/** - * NIM::CheckSysUpdateAvailable service function - * Inputs: - * 1 : None - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : flag, 0 = no system update available, 1 = system update available. - */ -void CheckSysUpdateAvailable(Service::Interface* self); - -/// Initialize NIM service(s) -void Init(); - -/// Shutdown NIM service(s) -void Shutdown(); - -} // namespace NIM -} // namespace Service diff --git a/src/core/hle/service/nim/nim_aoc.cpp b/src/core/hle/service/nim/nim_aoc.cpp deleted file mode 100644 index 2d0fb6fc4..000000000 --- a/src/core/hle/service/nim/nim_aoc.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nim/nim_aoc.h" - -namespace Service { -namespace NIM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00030042, nullptr, "SetApplicationId"}, - {0x00040042, nullptr, "SetTin"}, - {0x000902D0, nullptr, "ListContentSetsEx"}, - {0x00180000, nullptr, "GetBalance"}, - {0x001D0000, nullptr, "GetCustomerSupportCode"}, - {0x00210000, nullptr, "Initialize"}, - {0x00240282, nullptr, "CalculateContentsRequiredSize"}, - {0x00250000, nullptr, "RefreshServerTime"}, -}; - -NIM_AOC_Interface::NIM_AOC_Interface() { - Register(FunctionTable); -} - -} // namespace NIM -} // namespace Service diff --git a/src/core/hle/service/nim/nim_aoc.h b/src/core/hle/service/nim/nim_aoc.h deleted file mode 100644 index aace45b5a..000000000 --- a/src/core/hle/service/nim/nim_aoc.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NIM { - -class NIM_AOC_Interface : public Service::Interface { -public: - NIM_AOC_Interface(); - - std::string GetPortName() const override { - return "nim:aoc"; - } -}; - -} // namespace NIM -} // namespace Service diff --git a/src/core/hle/service/nim/nim_s.cpp b/src/core/hle/service/nim/nim_s.cpp deleted file mode 100644 index 28b87e6f7..000000000 --- a/src/core/hle/service/nim/nim_s.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nim/nim_s.h" - -namespace Service { -namespace NIM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x000A0000, nullptr, "CheckSysupdateAvailableSOAP"}, - {0x0016020A, nullptr, "ListTitles"}, - {0x00290000, nullptr, "AccountCheckBalanceSOAP"}, - {0x002D0042, nullptr, "DownloadTickets"}, - {0x00420240, nullptr, "StartDownload"}, -}; - -NIM_S_Interface::NIM_S_Interface() { - Register(FunctionTable); -} - -} // namespace NIM -} // namespace Service diff --git a/src/core/hle/service/nim/nim_s.h b/src/core/hle/service/nim/nim_s.h deleted file mode 100644 index f4bf73d26..000000000 --- a/src/core/hle/service/nim/nim_s.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NIM { - -class NIM_S_Interface : public Service::Interface { -public: - NIM_S_Interface(); - - std::string GetPortName() const override { - return "nim:s"; - } -}; - -} // namespace NIM -} // namespace Service diff --git a/src/core/hle/service/nim/nim_u.cpp b/src/core/hle/service/nim/nim_u.cpp deleted file mode 100644 index 569660278..000000000 --- a/src/core/hle/service/nim/nim_u.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nim/nim.h" -#include "core/hle/service/nim/nim_u.h" - -namespace Service { -namespace NIM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010000, nullptr, "StartSysUpdate"}, - {0x00020000, nullptr, "GetUpdateDownloadProgress"}, - {0x00040000, nullptr, "FinishTitlesInstall"}, - {0x00050000, CheckForSysUpdateEvent, "CheckForSysUpdateEvent"}, - {0x00090000, CheckSysUpdateAvailable, "CheckSysUpdateAvailable"}, - {0x000A0000, nullptr, "GetState"}, - {0x000B0000, nullptr, "GetSystemTitleHash"}, -}; - -NIM_U_Interface::NIM_U_Interface() { - Register(FunctionTable); -} - -} // namespace NIM -} // namespace Service diff --git a/src/core/hle/service/nim/nim_u.h b/src/core/hle/service/nim/nim_u.h deleted file mode 100644 index c4b74985a..000000000 --- a/src/core/hle/service/nim/nim_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NIM { - -class NIM_U_Interface : public Service::Interface { -public: - NIM_U_Interface(); - - std::string GetPortName() const override { - return "nim:u"; - } -}; - -} // namespace NIM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm.cpp b/src/core/hle/service/nwm/nwm.cpp deleted file mode 100644 index 9f1994dc3..000000000 --- a/src/core/hle/service/nwm/nwm.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nwm/nwm.h" -#include "core/hle/service/nwm/nwm_cec.h" -#include "core/hle/service/nwm/nwm_ext.h" -#include "core/hle/service/nwm/nwm_inf.h" -#include "core/hle/service/nwm/nwm_sap.h" -#include "core/hle/service/nwm/nwm_soc.h" -#include "core/hle/service/nwm/nwm_tst.h" -#include "core/hle/service/nwm/nwm_uds.h" - -namespace Service { -namespace NWM { - -void Init() { - AddService(new NWM_CEC); - AddService(new NWM_EXT); - AddService(new NWM_INF); - AddService(new NWM_SAP); - AddService(new NWM_SOC); - AddService(new NWM_TST); - AddService(new NWM_UDS); -} - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm.h b/src/core/hle/service/nwm/nwm.h deleted file mode 100644 index 6926b29a6..000000000 --- a/src/core/hle/service/nwm/nwm.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service { -namespace NWM { - -/// Initialize all NWM services -void Init(); - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_cec.cpp b/src/core/hle/service/nwm/nwm_cec.cpp deleted file mode 100644 index 7f03987df..000000000 --- a/src/core/hle/service/nwm/nwm_cec.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nwm/nwm_cec.h" - -namespace Service { -namespace NWM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x000D0082, nullptr, "SendProbeRequest"}, -}; - -NWM_CEC::NWM_CEC() { - Register(FunctionTable); -} - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_cec.h b/src/core/hle/service/nwm/nwm_cec.h deleted file mode 100644 index 07b6addb5..000000000 --- a/src/core/hle/service/nwm/nwm_cec.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NWM { - -class NWM_CEC final : public Interface { -public: - NWM_CEC(); - - std::string GetPortName() const override { - return "nwm::CEC"; - } -}; - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_ext.cpp b/src/core/hle/service/nwm/nwm_ext.cpp deleted file mode 100644 index 605640a13..000000000 --- a/src/core/hle/service/nwm/nwm_ext.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nwm/nwm_ext.h" - -namespace Service { -namespace NWM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00080040, nullptr, "ControlWirelessEnabled"}, -}; - -NWM_EXT::NWM_EXT() { - Register(FunctionTable); -} - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_ext.h b/src/core/hle/service/nwm/nwm_ext.h deleted file mode 100644 index 51d39d9ea..000000000 --- a/src/core/hle/service/nwm/nwm_ext.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NWM { - -class NWM_EXT final : public Interface { -public: - NWM_EXT(); - - std::string GetPortName() const override { - return "nwm::EXT"; - } -}; - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_inf.cpp b/src/core/hle/service/nwm/nwm_inf.cpp deleted file mode 100644 index c8470589b..000000000 --- a/src/core/hle/service/nwm/nwm_inf.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nwm/nwm_inf.h" - -namespace Service { -namespace NWM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x000603C4, nullptr, "RecvBeaconBroadcastData"}, - {0x00070742, nullptr, "ConnectToEncryptedAP"}, - {0x00080302, nullptr, "ConnectToAP"}, -}; - -NWM_INF::NWM_INF() { - Register(FunctionTable); -} - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_inf.h b/src/core/hle/service/nwm/nwm_inf.h deleted file mode 100644 index 0043d769c..000000000 --- a/src/core/hle/service/nwm/nwm_inf.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NWM { - -class NWM_INF final : public Interface { -public: - NWM_INF(); - - std::string GetPortName() const override { - return "nwm::INF"; - } -}; - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_sap.cpp b/src/core/hle/service/nwm/nwm_sap.cpp deleted file mode 100644 index fd29ed761..000000000 --- a/src/core/hle/service/nwm/nwm_sap.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nwm/nwm_sap.h" - -namespace Service { -namespace NWM { - -/* -const Interface::FunctionInfo FunctionTable[] = { -}; -*/ - -NWM_SAP::NWM_SAP() { - // Register(FunctionTable); -} - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_sap.h b/src/core/hle/service/nwm/nwm_sap.h deleted file mode 100644 index f692e06d4..000000000 --- a/src/core/hle/service/nwm/nwm_sap.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NWM { - -class NWM_SAP final : public Interface { -public: - NWM_SAP(); - - std::string GetPortName() const override { - return "nwm::SAP"; - } -}; - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_soc.cpp b/src/core/hle/service/nwm/nwm_soc.cpp deleted file mode 100644 index fdffcb925..000000000 --- a/src/core/hle/service/nwm/nwm_soc.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nwm/nwm_soc.h" - -namespace Service { -namespace NWM { - -/* -const Interface::FunctionInfo FunctionTable[] = { -}; -*/ - -NWM_SOC::NWM_SOC() { - // Register(FunctionTable); -} - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_soc.h b/src/core/hle/service/nwm/nwm_soc.h deleted file mode 100644 index 594941d7e..000000000 --- a/src/core/hle/service/nwm/nwm_soc.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NWM { - -class NWM_SOC final : public Interface { -public: - NWM_SOC(); - - std::string GetPortName() const override { - return "nwm::SOC"; - } -}; - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_tst.cpp b/src/core/hle/service/nwm/nwm_tst.cpp deleted file mode 100644 index 5f292e5db..000000000 --- a/src/core/hle/service/nwm/nwm_tst.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nwm/nwm_tst.h" - -namespace Service { -namespace NWM { - -/* -const Interface::FunctionInfo FunctionTable[] = { -}; -*/ - -NWM_TST::NWM_TST() { - // Register(FunctionTable); -} - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_tst.h b/src/core/hle/service/nwm/nwm_tst.h deleted file mode 100644 index 8deca3216..000000000 --- a/src/core/hle/service/nwm/nwm_tst.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace NWM { - -class NWM_TST final : public Interface { -public: - NWM_TST(); - - std::string GetPortName() const override { - return "nwm::TST"; - } -}; - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp deleted file mode 100644 index 87a6b0eca..000000000 --- a/src/core/hle/service/nwm/nwm_uds.cpp +++ /dev/null @@ -1,1035 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> -#include <array> -#include <cstring> -#include <list> -#include <mutex> -#include <unordered_map> -#include <vector> -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/core_timing.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/event.h" -#include "core/hle/kernel/shared_memory.h" -#include "core/hle/lock.h" -#include "core/hle/result.h" -#include "core/hle/service/nwm/nwm_uds.h" -#include "core/hle/service/nwm/uds_beacon.h" -#include "core/hle/service/nwm/uds_connection.h" -#include "core/hle/service/nwm/uds_data.h" -#include "core/memory.h" -#include "network/network.h" - -namespace Service { -namespace NWM { - -// Event that is signaled every time the connection status changes. -static Kernel::SharedPtr<Kernel::Event> connection_status_event; - -// Shared memory provided by the application to store the receive buffer. -// This is not currently used. -static Kernel::SharedPtr<Kernel::SharedMemory> recv_buffer_memory; - -// Connection status of this 3DS. -static ConnectionStatus connection_status{}; - -/* Node information about the current network. - * The amount of elements in this vector is always the maximum number - * of nodes specified in the network configuration. - * The first node is always the host. - */ -static NodeList node_info; - -// Node information about our own system. -static NodeInfo current_node; - -// Mapping of bind node ids to their respective events. -static std::unordered_map<u32, Kernel::SharedPtr<Kernel::Event>> bind_node_events; - -// The WiFi network channel that the network is currently on. -// Since we're not actually interacting with physical radio waves, this is just a dummy value. -static u8 network_channel = DefaultNetworkChannel; - -// Information about the network that we're currently connected to. -static NetworkInfo network_info; - -// Event that will generate and send the 802.11 beacon frames. -static int beacon_broadcast_event; - -// Mutex to synchronize access to the connection status between the emulation thread and the -// network thread. -static std::mutex connection_status_mutex; - -// Mutex to synchronize access to the list of received beacons between the emulation thread and the -// network thread. -static std::mutex beacon_mutex; - -// Number of beacons to store before we start dropping the old ones. -// TODO(Subv): Find a more accurate value for this limit. -constexpr size_t MaxBeaconFrames = 15; - -// List of the last <MaxBeaconFrames> beacons received from the network. -static std::list<Network::WifiPacket> received_beacons; - -/** - * Returns a list of received 802.11 beacon frames from the specified sender since the last call. - */ -std::list<Network::WifiPacket> GetReceivedBeacons(const MacAddress& sender) { - std::lock_guard<std::mutex> lock(beacon_mutex); - if (sender != Network::BroadcastMac) { - std::list<Network::WifiPacket> filtered_list; - const auto beacon = std::find_if(received_beacons.begin(), received_beacons.end(), - [&sender](const Network::WifiPacket& packet) { - return packet.transmitter_address == sender; - }); - if (beacon != received_beacons.end()) { - filtered_list.push_back(*beacon); - // TODO(B3N30): Check if the complete deque is cleared or just the fetched entries - received_beacons.erase(beacon); - } - return filtered_list; - } - return std::move(received_beacons); -} - -/// Sends a WifiPacket to the room we're currently connected to. -void SendPacket(Network::WifiPacket& packet) { - // TODO(Subv): Implement. -} - -/* - * Returns an available index in the nodes array for the - * currently-hosted UDS network. - */ -static u16 GetNextAvailableNodeId() { - for (u16 index = 0; index < connection_status.max_nodes; ++index) { - if ((connection_status.node_bitmask & (1 << index)) == 0) - return index; - } - - // Any connection attempts to an already full network should have been refused. - ASSERT_MSG(false, "No available connection slots in the network"); -} - -// Inserts the received beacon frame in the beacon queue and removes any older beacons if the size -// limit is exceeded. -void HandleBeaconFrame(const Network::WifiPacket& packet) { - std::lock_guard<std::mutex> lock(beacon_mutex); - const auto unique_beacon = - std::find_if(received_beacons.begin(), received_beacons.end(), - [&packet](const Network::WifiPacket& new_packet) { - return new_packet.transmitter_address == packet.transmitter_address; - }); - if (unique_beacon != received_beacons.end()) { - // We already have a beacon from the same mac in the deque, remove the old one; - received_beacons.erase(unique_beacon); - } - - received_beacons.emplace_back(packet); - - // Discard old beacons if the buffer is full. - if (received_beacons.size() > MaxBeaconFrames) - received_beacons.pop_front(); -} - -void HandleAssociationResponseFrame(const Network::WifiPacket& packet) { - auto assoc_result = GetAssociationResult(packet.data); - - ASSERT_MSG(std::get<AssocStatus>(assoc_result) == AssocStatus::Successful, - "Could not join network"); - { - std::lock_guard<std::mutex> lock(connection_status_mutex); - ASSERT(connection_status.status == static_cast<u32>(NetworkStatus::Connecting)); - } - - // Send the EAPoL-Start packet to the server. - using Network::WifiPacket; - WifiPacket eapol_start; - eapol_start.channel = network_channel; - eapol_start.data = GenerateEAPoLStartFrame(std::get<u16>(assoc_result), current_node); - // TODO(B3N30): Encrypt the packet. - eapol_start.destination_address = packet.transmitter_address; - eapol_start.type = WifiPacket::PacketType::Data; - - SendPacket(eapol_start); -} - -static void HandleEAPoLPacket(const Network::WifiPacket& packet) { - std::lock_guard<std::mutex> lock(connection_status_mutex); - - if (GetEAPoLFrameType(packet.data) == EAPoLStartMagic) { - if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) { - LOG_DEBUG(Service_NWM, "Connection sequence aborted, because connection status is %u", - connection_status.status); - return; - } - - auto node = DeserializeNodeInfoFromFrame(packet.data); - - if (connection_status.max_nodes == connection_status.total_nodes) { - // Reject connection attempt - LOG_ERROR(Service_NWM, "Reached maximum nodes, but reject packet wasn't sent."); - // TODO(B3N30): Figure out what packet is sent here - return; - } - - // Get an unused network node id - u16 node_id = GetNextAvailableNodeId(); - node.network_node_id = node_id + 1; - - connection_status.node_bitmask |= 1 << node_id; - connection_status.changed_nodes |= 1 << node_id; - connection_status.nodes[node_id] = node.network_node_id; - connection_status.total_nodes++; - - u8 current_nodes = network_info.total_nodes; - node_info[current_nodes] = node; - - network_info.total_nodes++; - - // Send the EAPoL-Logoff packet. - using Network::WifiPacket; - WifiPacket eapol_logoff; - eapol_logoff.channel = network_channel; - eapol_logoff.data = - GenerateEAPoLLogoffFrame(packet.transmitter_address, node.network_node_id, node_info, - network_info.max_nodes, network_info.total_nodes); - // TODO(Subv): Encrypt the packet. - eapol_logoff.destination_address = packet.transmitter_address; - eapol_logoff.type = WifiPacket::PacketType::Data; - - SendPacket(eapol_logoff); - // TODO(B3N30): Broadcast updated node list - // The 3ds does this presumably to support spectators. - std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); - connection_status_event->Signal(); - } else { - if (connection_status.status != static_cast<u32>(NetworkStatus::NotConnected)) { - LOG_DEBUG(Service_NWM, "Connection sequence aborted, because connection status is %u", - connection_status.status); - return; - } - auto logoff = ParseEAPoLLogoffFrame(packet.data); - - network_info.total_nodes = logoff.connected_nodes; - network_info.max_nodes = logoff.max_nodes; - - connection_status.network_node_id = logoff.assigned_node_id; - connection_status.total_nodes = logoff.connected_nodes; - connection_status.max_nodes = logoff.max_nodes; - - node_info.clear(); - node_info.reserve(network_info.max_nodes); - for (size_t index = 0; index < logoff.connected_nodes; ++index) { - connection_status.node_bitmask |= 1 << index; - connection_status.changed_nodes |= 1 << index; - connection_status.nodes[index] = logoff.nodes[index].network_node_id; - - node_info.emplace_back(DeserializeNodeInfo(logoff.nodes[index])); - } - - // We're now connected, signal the application - connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsClient); - // Some games require ConnectToNetwork to block, for now it doesn't - // If blocking is implemented this lock needs to be changed, - // otherwise it might cause deadlocks - std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); - connection_status_event->Signal(); - } -} - -/* - * Start a connection sequence with an UDS server. The sequence starts by sending an 802.11 - * authentication frame with SEQ1. - */ -void StartConnectionSequence(const MacAddress& server) { - using Network::WifiPacket; - WifiPacket auth_request; - { - std::lock_guard<std::mutex> lock(connection_status_mutex); - ASSERT(connection_status.status == static_cast<u32>(NetworkStatus::NotConnected)); - - // TODO(Subv): Handle timeout. - - // Send an authentication frame with SEQ1 - auth_request.channel = network_channel; - auth_request.data = GenerateAuthenticationFrame(AuthenticationSeq::SEQ1); - auth_request.destination_address = server; - auth_request.type = WifiPacket::PacketType::Authentication; - } - - SendPacket(auth_request); -} - -/// Sends an Association Response frame to the specified mac address -void SendAssociationResponseFrame(const MacAddress& address) { - using Network::WifiPacket; - WifiPacket assoc_response; - - { - std::lock_guard<std::mutex> lock(connection_status_mutex); - if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) { - LOG_ERROR(Service_NWM, "Connection sequence aborted, because connection status is %u", - connection_status.status); - return; - } - - assoc_response.channel = network_channel; - // TODO(Subv): This will cause multiple clients to end up with the same association id, but - // we're not using that for anything. - u16 association_id = 1; - assoc_response.data = GenerateAssocResponseFrame(AssocStatus::Successful, association_id, - network_info.network_id); - assoc_response.destination_address = address; - assoc_response.type = WifiPacket::PacketType::AssociationResponse; - } - - SendPacket(assoc_response); -} - -/* - * Handles the authentication request frame and sends the authentication response and association - * response frames. Once an Authentication frame with SEQ1 is received by the server, it responds - * with an Authentication frame containing SEQ2, and immediately sends an Association response frame - * containing the details of the access point and the assigned association id for the new client. - */ -void HandleAuthenticationFrame(const Network::WifiPacket& packet) { - // Only the SEQ1 auth frame is handled here, the SEQ2 frame doesn't need any special behavior - if (GetAuthenticationSeqNumber(packet.data) == AuthenticationSeq::SEQ1) { - using Network::WifiPacket; - WifiPacket auth_request; - { - std::lock_guard<std::mutex> lock(connection_status_mutex); - if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) { - LOG_ERROR(Service_NWM, - "Connection sequence aborted, because connection status is %u", - connection_status.status); - return; - } - - // Respond with an authentication response frame with SEQ2 - auth_request.channel = network_channel; - auth_request.data = GenerateAuthenticationFrame(AuthenticationSeq::SEQ2); - auth_request.destination_address = packet.transmitter_address; - auth_request.type = WifiPacket::PacketType::Authentication; - } - SendPacket(auth_request); - - SendAssociationResponseFrame(packet.transmitter_address); - } -} - -static void HandleDataFrame(const Network::WifiPacket& packet) { - switch (GetFrameEtherType(packet.data)) { - case EtherType::EAPoL: - HandleEAPoLPacket(packet); - break; - case EtherType::SecureData: - // TODO(B3N30): Handle SecureData packets - break; - } -} - -/// Callback to parse and handle a received wifi packet. -void OnWifiPacketReceived(const Network::WifiPacket& packet) { - switch (packet.type) { - case Network::WifiPacket::PacketType::Beacon: - HandleBeaconFrame(packet); - break; - case Network::WifiPacket::PacketType::Authentication: - HandleAuthenticationFrame(packet); - break; - case Network::WifiPacket::PacketType::AssociationResponse: - HandleAssociationResponseFrame(packet); - break; - case Network::WifiPacket::PacketType::Data: - HandleDataFrame(packet); - break; - } -} - -/** - * NWM_UDS::Shutdown service function - * Inputs: - * 1 : None - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void Shutdown(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - // TODO(purpasmart): Verify return header on HW - - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_NWM, "(STUBBED) called"); -} - -/** - * NWM_UDS::RecvBeaconBroadcastData service function - * Returns the raw beacon data for nearby networks that match the supplied WlanCommId. - * Inputs: - * 1 : Output buffer max size - * 2-3 : Unknown - * 4-5 : Host MAC address. - * 6-14 : Unused - * 15 : WLan Comm Id - * 16 : Id - * 17 : Value 0 - * 18 : Input handle - * 19 : (Size<<4) | 12 - * 20 : Output buffer ptr - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void RecvBeaconBroadcastData(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0F, 16, 4); - - u32 out_buffer_size = rp.Pop<u32>(); - u32 unk1 = rp.Pop<u32>(); - u32 unk2 = rp.Pop<u32>(); - - MacAddress mac_address; - rp.PopRaw(mac_address); - - rp.Skip(9, false); - - u32 wlan_comm_id = rp.Pop<u32>(); - u32 id = rp.Pop<u32>(); - Kernel::Handle input_handle = rp.PopHandle(); - - size_t desc_size; - const VAddr out_buffer_ptr = rp.PopMappedBuffer(&desc_size); - ASSERT(desc_size == out_buffer_size); - - VAddr current_buffer_pos = out_buffer_ptr; - u32 total_size = sizeof(BeaconDataReplyHeader); - - // Retrieve all beacon frames that were received from the desired mac address. - auto beacons = GetReceivedBeacons(mac_address); - - BeaconDataReplyHeader data_reply_header{}; - data_reply_header.total_entries = static_cast<u32>(beacons.size()); - data_reply_header.max_output_size = out_buffer_size; - - Memory::WriteBlock(current_buffer_pos, &data_reply_header, sizeof(BeaconDataReplyHeader)); - current_buffer_pos += sizeof(BeaconDataReplyHeader); - - // Write each of the received beacons into the buffer - for (const auto& beacon : beacons) { - BeaconEntryHeader entry{}; - // TODO(Subv): Figure out what this size is used for. - entry.unk_size = static_cast<u32>(sizeof(BeaconEntryHeader) + beacon.data.size()); - entry.total_size = static_cast<u32>(sizeof(BeaconEntryHeader) + beacon.data.size()); - entry.wifi_channel = beacon.channel; - entry.header_size = sizeof(BeaconEntryHeader); - entry.mac_address = beacon.transmitter_address; - - ASSERT(current_buffer_pos < out_buffer_ptr + out_buffer_size); - - Memory::WriteBlock(current_buffer_pos, &entry, sizeof(BeaconEntryHeader)); - current_buffer_pos += sizeof(BeaconEntryHeader); - - Memory::WriteBlock(current_buffer_pos, beacon.data.data(), beacon.data.size()); - current_buffer_pos += static_cast<VAddr>(beacon.data.size()); - - total_size += static_cast<u32>(sizeof(BeaconEntryHeader) + beacon.data.size()); - } - - // Update the total size in the structure and write it to the buffer again. - data_reply_header.total_size = total_size; - Memory::WriteBlock(out_buffer_ptr, &data_reply_header, sizeof(BeaconDataReplyHeader)); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_DEBUG(Service_NWM, "called out_buffer_size=0x%08X, wlan_comm_id=0x%08X, id=0x%08X," - "input_handle=0x%08X, out_buffer_ptr=0x%08X, unk1=0x%08X, unk2=0x%08X", - out_buffer_size, wlan_comm_id, id, input_handle, out_buffer_ptr, unk1, unk2); -} - -/** - * NWM_UDS::Initialize service function - * Inputs: - * 1 : Shared memory size - * 2-11 : Input NodeInfo Structure - * 12 : 2-byte Version - * 13 : Value 0 - * 14 : Shared memory handle - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Value 0 - * 3 : Output event handle - */ -static void InitializeWithVersion(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1B, 12, 2); - - u32 sharedmem_size = rp.Pop<u32>(); - - // Update the node information with the data the game gave us. - rp.PopRaw(current_node); - - u16 version = rp.Pop<u16>(); - - Kernel::Handle sharedmem_handle = rp.PopHandle(); - - recv_buffer_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(sharedmem_handle); - - ASSERT_MSG(recv_buffer_memory->size == sharedmem_size, "Invalid shared memory size."); - - { - std::lock_guard<std::mutex> lock(connection_status_mutex); - - // Reset the connection status, it contains all zeros after initialization, - // except for the actual status value. - connection_status = {}; - connection_status.status = static_cast<u32>(NetworkStatus::NotConnected); - } - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles(Kernel::g_handle_table.Create(connection_status_event).Unwrap()); - - // TODO(Subv): Connect the OnWifiPacketReceived function to the wifi packet received callback of - // the room we're currently in. - - LOG_DEBUG(Service_NWM, "called sharedmem_size=0x%08X, version=0x%08X, sharedmem_handle=0x%08X", - sharedmem_size, version, sharedmem_handle); -} - -/** - * NWM_UDS::GetConnectionStatus service function. - * Returns the connection status structure for the currently open network connection. - * This structure contains information about the connection, - * like the number of connected nodes, etc. - * Inputs: - * 0 : Command header. - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - * 2-13 : Channel of the current WiFi network connection. - */ -static void GetConnectionStatus(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xB, 0, 0); - IPC::RequestBuilder rb = rp.MakeBuilder(13, 0); - - rb.Push(RESULT_SUCCESS); - { - std::lock_guard<std::mutex> lock(connection_status_mutex); - rb.PushRaw(connection_status); - - // Reset the bitmask of changed nodes after each call to this - // function to prevent falsely informing games of outstanding - // changes in subsequent calls. - // TODO(Subv): Find exactly where the NWM module resets this value. - connection_status.changed_nodes = 0; - } - - LOG_DEBUG(Service_NWM, "called"); -} - -/** - * NWM_UDS::Bind service function. - * Binds a BindNodeId to a data channel and retrieves a data event. - * Inputs: - * 1 : BindNodeId - * 2 : Receive buffer size. - * 3 : u8 Data channel to bind to. - * 4 : Network node id. - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Copy handle descriptor. - * 3 : Data available event handle. - */ -static void Bind(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x12, 4, 0); - - u32 bind_node_id = rp.Pop<u32>(); - u32 recv_buffer_size = rp.Pop<u32>(); - u8 data_channel = rp.Pop<u8>(); - u16 network_node_id = rp.Pop<u16>(); - - // TODO(Subv): Store the data channel and verify it when receiving data frames. - - LOG_DEBUG(Service_NWM, "called"); - - if (data_channel == 0) { - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS, - ErrorSummary::WrongArgument, ErrorLevel::Usage)); - return; - } - - // Create a new event for this bind node. - // TODO(Subv): Signal this event when new data is received on this data channel. - auto event = Kernel::Event::Create(Kernel::ResetType::OneShot, - "NWM::BindNodeEvent" + std::to_string(bind_node_id)); - bind_node_events[bind_node_id] = event; - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles(Kernel::g_handle_table.Create(event).Unwrap()); -} - -/** - * NWM_UDS::BeginHostingNetwork service function. - * Creates a network and starts broadcasting its presence. - * Inputs: - * 1 : Passphrase buffer size. - * 3 : VAddr of the NetworkInfo structure. - * 5 : VAddr of the passphrase. - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void BeginHostingNetwork(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1D, 1, 4); - - const u32 passphrase_size = rp.Pop<u32>(); - - size_t desc_size; - const VAddr network_info_address = rp.PopStaticBuffer(&desc_size, false); - ASSERT(desc_size == sizeof(NetworkInfo)); - const VAddr passphrase_address = rp.PopStaticBuffer(&desc_size, false); - ASSERT(desc_size == passphrase_size); - - // TODO(Subv): Store the passphrase and verify it when attempting a connection. - - LOG_DEBUG(Service_NWM, "called"); - - Memory::ReadBlock(network_info_address, &network_info, sizeof(NetworkInfo)); - - // The real UDS module throws a fatal error if this assert fails. - ASSERT_MSG(network_info.max_nodes > 1, "Trying to host a network of only one member."); - - { - std::lock_guard<std::mutex> lock(connection_status_mutex); - connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsHost); - - // Ensure the application data size is less than the maximum value. - ASSERT_MSG(network_info.application_data_size <= ApplicationDataSize, - "Data size is too big."); - - // Set up basic information for this network. - network_info.oui_value = NintendoOUI; - network_info.oui_type = static_cast<u8>(NintendoTagId::NetworkInfo); - - connection_status.max_nodes = network_info.max_nodes; - - // Resize the nodes list to hold max_nodes. - node_info.resize(network_info.max_nodes); - - // There's currently only one node in the network (the host). - connection_status.total_nodes = 1; - network_info.total_nodes = 1; - // The host is always the first node - connection_status.network_node_id = 1; - current_node.network_node_id = 1; - connection_status.nodes[0] = connection_status.network_node_id; - // Set the bit 0 in the nodes bitmask to indicate that node 1 is already taken. - connection_status.node_bitmask |= 1; - // Notify the application that the first node was set. - connection_status.changed_nodes |= 1; - node_info[0] = current_node; - } - - // If the game has a preferred channel, use that instead. - if (network_info.channel != 0) - network_channel = network_info.channel; - - connection_status_event->Signal(); - - // Start broadcasting the network, send a beacon frame every 102.4ms. - CoreTiming::ScheduleEvent(msToCycles(DefaultBeaconInterval * MillisecondsPerTU), - beacon_broadcast_event, 0); - - LOG_WARNING(Service_NWM, - "An UDS network has been created, but broadcasting it is unimplemented."); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); -} - -/** - * NWM_UDS::DestroyNetwork service function. - * Closes the network that we're currently hosting. - * Inputs: - * 0 : Command header. - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void DestroyNetwork(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x08, 0, 0); - - // TODO(Subv): Find out what happens if this is called while - // no network is being hosted. - - // Unschedule the beacon broadcast event. - CoreTiming::UnscheduleEvent(beacon_broadcast_event, 0); - - { - std::lock_guard<std::mutex> lock(connection_status_mutex); - - // TODO(Subv): Check if connection_status is indeed reset after this call. - connection_status = {}; - connection_status.status = static_cast<u8>(NetworkStatus::NotConnected); - } - connection_status_event->Signal(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_NWM, "called"); -} - -/** - * NWM_UDS::SendTo service function. - * Sends a data frame to the UDS network we're connected to. - * Inputs: - * 0 : Command header. - * 1 : Unknown. - * 2 : u16 Destination network node id. - * 3 : u8 Data channel. - * 4 : Buffer size >> 2 - * 5 : Data size - * 6 : Flags - * 7 : Input buffer descriptor - * 8 : Input buffer address - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void SendTo(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x17, 6, 2); - - rp.Skip(1, false); - u16 dest_node_id = rp.Pop<u16>(); - u8 data_channel = rp.Pop<u8>(); - rp.Skip(1, false); - u32 data_size = rp.Pop<u32>(); - u32 flags = rp.Pop<u32>(); - - size_t desc_size; - const VAddr input_address = rp.PopStaticBuffer(&desc_size, false); - ASSERT(desc_size == data_size); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - u16 network_node_id; - - { - std::lock_guard<std::mutex> lock(connection_status_mutex); - if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsClient) && - connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) { - rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS, - ErrorSummary::InvalidState, ErrorLevel::Status)); - return; - } - - if (dest_node_id == connection_status.network_node_id) { - rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::UDS, - ErrorSummary::WrongArgument, ErrorLevel::Status)); - return; - } - - network_node_id = connection_status.network_node_id; - } - - // TODO(Subv): Do something with the flags. - - constexpr size_t MaxSize = 0x5C6; - if (data_size > MaxSize) { - rb.Push(ResultCode(ErrorDescription::TooLarge, ErrorModule::UDS, - ErrorSummary::WrongArgument, ErrorLevel::Usage)); - return; - } - - std::vector<u8> data(data_size); - Memory::ReadBlock(input_address, data.data(), data.size()); - - // TODO(Subv): Increment the sequence number after each sent packet. - u16 sequence_number = 0; - std::vector<u8> data_payload = - GenerateDataPayload(data, data_channel, dest_node_id, network_node_id, sequence_number); - - // TODO(Subv): Retrieve the MAC address of the dest_node_id and our own to encrypt - // and encapsulate the payload. - - // TODO(Subv): Send the frame. - - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_NWM, "(STUB) called dest_node_id=%u size=%u flags=%u channel=%u", - static_cast<u32>(dest_node_id), data_size, flags, static_cast<u32>(data_channel)); -} - -/** - * NWM_UDS::GetChannel service function. - * Returns the WiFi channel in which the network we're connected to is transmitting. - * Inputs: - * 0 : Command header. - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Channel of the current WiFi network connection. - */ -static void GetChannel(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1A, 0, 0); - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - - std::lock_guard<std::mutex> lock(connection_status_mutex); - bool is_connected = connection_status.status != static_cast<u32>(NetworkStatus::NotConnected); - - u8 channel = is_connected ? network_channel : 0; - - rb.Push(RESULT_SUCCESS); - rb.Push(channel); - - LOG_DEBUG(Service_NWM, "called"); -} - -/** - * NWM_UDS::SetApplicationData service function. - * Updates the application data that is being broadcast in the beacon frames - * for the network that we're hosting. - * Inputs: - * 1 : Data size. - * 3 : VAddr of the data. - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Channel of the current WiFi network connection. - */ -static void SetApplicationData(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1A, 1, 2); - - u32 size = rp.Pop<u32>(); - - size_t desc_size; - const VAddr address = rp.PopStaticBuffer(&desc_size, false); - ASSERT(desc_size == size); - - LOG_DEBUG(Service_NWM, "called"); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - if (size > ApplicationDataSize) { - rb.Push(ResultCode(ErrorDescription::TooLarge, ErrorModule::UDS, - ErrorSummary::WrongArgument, ErrorLevel::Usage)); - return; - } - - network_info.application_data_size = size; - Memory::ReadBlock(address, network_info.application_data.data(), size); - - rb.Push(RESULT_SUCCESS); -} - -/** - * NWM_UDS::DecryptBeaconData service function. - * Decrypts the encrypted data tags contained in the 802.11 beacons. - * Inputs: - * 1 : Input network struct buffer descriptor. - * 2 : Input network struct buffer ptr. - * 3 : Input tag0 encrypted buffer descriptor. - * 4 : Input tag0 encrypted buffer ptr. - * 5 : Input tag1 encrypted buffer descriptor. - * 6 : Input tag1 encrypted buffer ptr. - * 64 : Output buffer descriptor. - * 65 : Output buffer ptr. - * Outputs: - * 0 : Return header - * 1 : Result of function, 0 on success, otherwise error code - */ -static void DecryptBeaconData(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1F, 0, 6); - - size_t desc_size; - const VAddr network_struct_addr = rp.PopStaticBuffer(&desc_size); - ASSERT(desc_size == sizeof(NetworkInfo)); - - size_t data0_size; - const VAddr encrypted_data0_addr = rp.PopStaticBuffer(&data0_size); - - size_t data1_size; - const VAddr encrypted_data1_addr = rp.PopStaticBuffer(&data1_size); - - size_t output_buffer_size; - const VAddr output_buffer_addr = rp.PeekStaticBuffer(0, &output_buffer_size); - - // This size is hardcoded in the 3DS UDS code. - ASSERT(output_buffer_size == sizeof(NodeInfo) * UDSMaxNodes); - - LOG_WARNING(Service_NWM, "called in0=%08X in1=%08X out=%08X", encrypted_data0_addr, - encrypted_data1_addr, output_buffer_addr); - - NetworkInfo net_info; - Memory::ReadBlock(network_struct_addr, &net_info, sizeof(net_info)); - - // Read the encrypted data. - // The first 4 bytes should be the OUI and the OUI Type of the tags. - std::array<u8, 3> oui; - Memory::ReadBlock(encrypted_data0_addr, oui.data(), oui.size()); - ASSERT_MSG(oui == NintendoOUI, "Unexpected OUI"); - Memory::ReadBlock(encrypted_data1_addr, oui.data(), oui.size()); - ASSERT_MSG(oui == NintendoOUI, "Unexpected OUI"); - - ASSERT_MSG(Memory::Read8(encrypted_data0_addr + 3) == - static_cast<u8>(NintendoTagId::EncryptedData0), - "Unexpected tag id"); - ASSERT_MSG(Memory::Read8(encrypted_data1_addr + 3) == - static_cast<u8>(NintendoTagId::EncryptedData1), - "Unexpected tag id"); - - std::vector<u8> beacon_data(data0_size + data1_size); - Memory::ReadBlock(encrypted_data0_addr + 4, beacon_data.data(), data0_size); - Memory::ReadBlock(encrypted_data1_addr + 4, beacon_data.data() + data0_size, data1_size); - - // Decrypt the data - DecryptBeaconData(net_info, beacon_data); - - // The beacon data header contains the MD5 hash of the data. - BeaconData beacon_header; - std::memcpy(&beacon_header, beacon_data.data(), sizeof(beacon_header)); - - // TODO(Subv): Verify the MD5 hash of the data and return 0xE1211005 if invalid. - - u8 num_nodes = net_info.max_nodes; - - std::vector<NodeInfo> nodes; - - for (int i = 0; i < num_nodes; ++i) { - BeaconNodeInfo info; - std::memcpy(&info, beacon_data.data() + sizeof(beacon_header) + i * sizeof(info), - sizeof(info)); - - // Deserialize the node information. - NodeInfo node{}; - node.friend_code_seed = info.friend_code_seed; - node.network_node_id = info.network_node_id; - for (int i = 0; i < info.username.size(); ++i) - node.username[i] = info.username[i]; - - nodes.push_back(node); - } - - Memory::ZeroBlock(output_buffer_addr, sizeof(NodeInfo) * UDSMaxNodes); - Memory::WriteBlock(output_buffer_addr, nodes.data(), sizeof(NodeInfo) * nodes.size()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - rb.PushStaticBuffer(output_buffer_addr, output_buffer_size, 0); - rb.Push(RESULT_SUCCESS); -} - -// Sends a 802.11 beacon frame with information about the current network. -static void BeaconBroadcastCallback(u64 userdata, int cycles_late) { - // Don't do anything if we're not actually hosting a network - if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) - return; - - std::vector<u8> frame = GenerateBeaconFrame(network_info, node_info); - - using Network::WifiPacket; - WifiPacket packet; - packet.type = WifiPacket::PacketType::Beacon; - packet.data = std::move(frame); - packet.destination_address = Network::BroadcastMac; - packet.channel = network_channel; - - SendPacket(packet); - - // Start broadcasting the network, send a beacon frame every 102.4ms. - CoreTiming::ScheduleEvent(msToCycles(DefaultBeaconInterval * MillisecondsPerTU) - cycles_late, - beacon_broadcast_event, 0); -} - -/* - * Called when a client connects to an UDS network we're hosting, - * updates the connection status and signals the update event. - * @param network_node_id Network Node Id of the connecting client. - */ -void OnClientConnected(u16 network_node_id) { - std::lock_guard<std::mutex> lock(connection_status_mutex); - ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost), - "Can not accept clients if we're not hosting a network"); - ASSERT_MSG(connection_status.total_nodes < connection_status.max_nodes, - "Can not accept connections on a full network"); - - u32 node_id = GetNextAvailableNodeId(); - connection_status.node_bitmask |= 1 << node_id; - connection_status.changed_nodes |= 1 << node_id; - connection_status.nodes[node_id] = network_node_id; - connection_status.total_nodes++; - connection_status_event->Signal(); -} - -const Interface::FunctionInfo FunctionTable[] = { - {0x000102C2, nullptr, "Initialize (deprecated)"}, - {0x00020000, nullptr, "Scrap"}, - {0x00030000, Shutdown, "Shutdown"}, - {0x00040402, nullptr, "CreateNetwork (deprecated)"}, - {0x00050040, nullptr, "EjectClient"}, - {0x00060000, nullptr, "EjectSpectator"}, - {0x00070080, nullptr, "UpdateNetworkAttribute"}, - {0x00080000, DestroyNetwork, "DestroyNetwork"}, - {0x00090442, nullptr, "ConnectNetwork (deprecated)"}, - {0x000A0000, nullptr, "DisconnectNetwork"}, - {0x000B0000, GetConnectionStatus, "GetConnectionStatus"}, - {0x000D0040, nullptr, "GetNodeInformation"}, - {0x000E0006, nullptr, "DecryptBeaconData (deprecated)"}, - {0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"}, - {0x00100042, SetApplicationData, "SetApplicationData"}, - {0x00110040, nullptr, "GetApplicationData"}, - {0x00120100, Bind, "Bind"}, - {0x00130040, nullptr, "Unbind"}, - {0x001400C0, nullptr, "PullPacket"}, - {0x00150080, nullptr, "SetMaxSendDelay"}, - {0x00170182, SendTo, "SendTo"}, - {0x001A0000, GetChannel, "GetChannel"}, - {0x001B0302, InitializeWithVersion, "InitializeWithVersion"}, - {0x001D0044, BeginHostingNetwork, "BeginHostingNetwork"}, - {0x001E0084, nullptr, "ConnectToNetwork"}, - {0x001F0006, DecryptBeaconData, "DecryptBeaconData"}, - {0x00200040, nullptr, "Flush"}, - {0x00210080, nullptr, "SetProbeResponseParam"}, - {0x00220402, nullptr, "ScanOnConnection"}, -}; - -NWM_UDS::NWM_UDS() { - connection_status_event = - Kernel::Event::Create(Kernel::ResetType::OneShot, "NWM::connection_status_event"); - - Register(FunctionTable); - - beacon_broadcast_event = - CoreTiming::RegisterEvent("UDS::BeaconBroadcastCallback", BeaconBroadcastCallback); -} - -NWM_UDS::~NWM_UDS() { - network_info = {}; - bind_node_events.clear(); - connection_status_event = nullptr; - recv_buffer_memory = nullptr; - - { - std::lock_guard<std::mutex> lock(connection_status_mutex); - connection_status = {}; - connection_status.status = static_cast<u32>(NetworkStatus::NotConnected); - } - - CoreTiming::UnscheduleEvent(beacon_broadcast_event, 0); -} - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/nwm_uds.h b/src/core/hle/service/nwm/nwm_uds.h deleted file mode 100644 index f1caaf974..000000000 --- a/src/core/hle/service/nwm/nwm_uds.h +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <array> -#include <cstddef> -#include <vector> -#include "common/common_types.h" -#include "common/swap.h" -#include "core/hle/service/service.h" - -// Local-WLAN service - -namespace Service { -namespace NWM { - -const size_t ApplicationDataSize = 0xC8; -const u8 DefaultNetworkChannel = 11; - -// Number of milliseconds in a TU. -const double MillisecondsPerTU = 1.024; -// Interval measured in TU, the default value is 100TU = 102.4ms -const u16 DefaultBeaconInterval = 100; - -/// The maximum number of nodes that can exist in an UDS session. -constexpr u32 UDSMaxNodes = 16; - -struct NodeInfo { - u64_le friend_code_seed; - std::array<u16_le, 10> username; - INSERT_PADDING_BYTES(4); - u16_le network_node_id; - INSERT_PADDING_BYTES(6); -}; - -static_assert(sizeof(NodeInfo) == 40, "NodeInfo has incorrect size."); - -using NodeList = std::vector<NodeInfo>; - -enum class NetworkStatus { - NotConnected = 3, - ConnectedAsHost = 6, - Connecting = 7, - ConnectedAsClient = 9, - ConnectedAsSpectator = 10, -}; - -struct ConnectionStatus { - u32_le status; - INSERT_PADDING_WORDS(1); - u16_le network_node_id; - u16_le changed_nodes; - u16_le nodes[UDSMaxNodes]; - u8 total_nodes; - u8 max_nodes; - u16_le node_bitmask; -}; - -static_assert(sizeof(ConnectionStatus) == 0x30, "ConnectionStatus has incorrect size."); - -struct NetworkInfo { - std::array<u8, 6> host_mac_address; - u8 channel; - INSERT_PADDING_BYTES(1); - u8 initialized; - INSERT_PADDING_BYTES(3); - std::array<u8, 3> oui_value; - u8 oui_type; - // This field is received as BigEndian from the game. - u32_be wlan_comm_id; - u8 id; - INSERT_PADDING_BYTES(1); - u16_be attributes; - u32_be network_id; - u8 total_nodes; - u8 max_nodes; - INSERT_PADDING_BYTES(2); - INSERT_PADDING_BYTES(0x1F); - u8 application_data_size; - std::array<u8, ApplicationDataSize> application_data; -}; - -static_assert(offsetof(NetworkInfo, oui_value) == 0xC, "oui_value is at the wrong offset."); -static_assert(offsetof(NetworkInfo, wlan_comm_id) == 0x10, "wlancommid is at the wrong offset."); -static_assert(sizeof(NetworkInfo) == 0x108, "NetworkInfo has incorrect size."); - -/// Additional block tag ids in the Beacon and Association Response frames -enum class TagId : u8 { - SSID = 0, - SupportedRates = 1, - DSParameterSet = 2, - TrafficIndicationMap = 5, - CountryInformation = 7, - ERPInformation = 42, - VendorSpecific = 221 -}; - -class NWM_UDS final : public Interface { -public: - NWM_UDS(); - ~NWM_UDS() override; - - std::string GetPortName() const override { - return "nwm::UDS"; - } -}; - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/uds_beacon.cpp b/src/core/hle/service/nwm/uds_beacon.cpp deleted file mode 100644 index 73a80d940..000000000 --- a/src/core/hle/service/nwm/uds_beacon.cpp +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <cstring> -#include <cryptopp/aes.h> -#include <cryptopp/md5.h> -#include <cryptopp/modes.h> -#include <cryptopp/sha.h> -#include "common/assert.h" -#include "core/hle/service/nwm/nwm_uds.h" -#include "core/hle/service/nwm/uds_beacon.h" - -namespace Service { -namespace NWM { - -// 802.11 broadcast MAC address -constexpr MacAddress BroadcastMac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - -constexpr u64 DefaultNetworkUptime = 900000000; // 15 minutes in microseconds. - -// Note: These values were taken from a packet capture of an o3DS XL -// broadcasting a Super Smash Bros. 4 lobby. -constexpr u16 DefaultExtraCapabilities = 0x0431; - -// Size of the SSID broadcast by an UDS beacon frame. -constexpr u8 UDSBeaconSSIDSize = 8; - -// The maximum size of the data stored in the EncryptedData0 tag (24). -constexpr u32 EncryptedDataSizeCutoff = 0xFA; - -/** - * NWM Beacon data encryption key, taken from the NWM module code. - * We stub this with an all-zeros key as that is enough for Citra's purpose. - * The real key can be used here to generate beacons that will be accepted by - * a real 3ds. - */ -constexpr std::array<u8, CryptoPP::AES::BLOCKSIZE> nwm_beacon_key = {}; - -/** - * Generates a buffer with the fixed parameters of an 802.11 Beacon frame - * using dummy values. - * @returns A buffer with the fixed parameters of the beacon frame. - */ -std::vector<u8> GenerateFixedParameters() { - std::vector<u8> buffer(sizeof(BeaconFrameHeader)); - - BeaconFrameHeader header{}; - // Use a fixed default time for now. - // TODO(Subv): Perhaps use the difference between now and the time the network was started? - header.timestamp = DefaultNetworkUptime; - header.beacon_interval = DefaultBeaconInterval; - header.capabilities = DefaultExtraCapabilities; - - std::memcpy(buffer.data(), &header, sizeof(header)); - - return buffer; -} - -/** - * Generates an SSID tag of an 802.11 Beacon frame with an 8-byte all-zero SSID value. - * @returns A buffer with the SSID tag. - */ -std::vector<u8> GenerateSSIDTag() { - std::vector<u8> buffer(sizeof(TagHeader) + UDSBeaconSSIDSize); - - TagHeader tag_header{}; - tag_header.tag_id = static_cast<u8>(TagId::SSID); - tag_header.length = UDSBeaconSSIDSize; - - std::memcpy(buffer.data(), &tag_header, sizeof(TagHeader)); - - // The rest of the buffer is already filled with zeros. - - return buffer; -} - -/** - * Generates a buffer with the basic tagged parameters of an 802.11 Beacon frame - * such as SSID, Rate Information, Country Information, etc. - * @returns A buffer with the tagged parameters of the beacon frame. - */ -std::vector<u8> GenerateBasicTaggedParameters() { - // Append the SSID tag - std::vector<u8> buffer = GenerateSSIDTag(); - - // TODO(Subv): Add the SupportedRates tag. - // TODO(Subv): Add the DSParameterSet tag. - // TODO(Subv): Add the TrafficIndicationMap tag. - // TODO(Subv): Add the CountryInformation tag. - // TODO(Subv): Add the ERPInformation tag. - - return buffer; -} - -/** - * Generates a buffer with the Dummy Nintendo tag. - * It is currently unknown what this tag does. - * TODO(Subv): Figure out if this is needed and what it does. - * @returns A buffer with the Nintendo tagged parameters of the beacon frame. - */ -std::vector<u8> GenerateNintendoDummyTag() { - // Note: These values were taken from a packet capture of an o3DS XL - // broadcasting a Super Smash Bros. 4 lobby. - constexpr std::array<u8, 3> dummy_data = {0x0A, 0x00, 0x00}; - - DummyTag tag{}; - tag.header.tag_id = static_cast<u8>(TagId::VendorSpecific); - tag.header.length = sizeof(DummyTag) - sizeof(TagHeader); - tag.oui_type = static_cast<u8>(NintendoTagId::Dummy); - tag.oui = NintendoOUI; - tag.data = dummy_data; - - std::vector<u8> buffer(sizeof(DummyTag)); - std::memcpy(buffer.data(), &tag, sizeof(DummyTag)); - - return buffer; -} - -/** - * Generates a buffer with the Network Info Nintendo tag. - * This tag contains the network information of the network that is being broadcast. - * It also contains the application data provided by the application that opened the network. - * @returns A buffer with the Nintendo network info parameter of the beacon frame. - */ -std::vector<u8> GenerateNintendoNetworkInfoTag(const NetworkInfo& network_info) { - NetworkInfoTag tag{}; - tag.header.tag_id = static_cast<u8>(TagId::VendorSpecific); - tag.header.length = - sizeof(NetworkInfoTag) - sizeof(TagHeader) + network_info.application_data_size; - tag.appdata_size = network_info.application_data_size; - // Set the hash to zero initially, it will be updated once we calculate it. - tag.sha_hash = {}; - - // Ensure the network structure has the correct OUI and OUI type. - ASSERT(network_info.oui_type == static_cast<u8>(NintendoTagId::NetworkInfo)); - ASSERT(network_info.oui_value == NintendoOUI); - - // Ensure the application data size is less than the maximum value. - ASSERT_MSG(network_info.application_data_size <= ApplicationDataSize, "Data size is too big."); - - // This tag contains the network info structure starting at the OUI. - std::memcpy(tag.network_info.data(), &network_info.oui_value, tag.network_info.size()); - - // Copy the tag and the data so we can calculate the SHA1 over it. - std::vector<u8> buffer(sizeof(tag) + network_info.application_data_size); - std::memcpy(buffer.data(), &tag, sizeof(tag)); - std::memcpy(buffer.data() + sizeof(tag), network_info.application_data.data(), - network_info.application_data_size); - - // Calculate the SHA1 of the contents of the tag. - std::array<u8, CryptoPP::SHA1::DIGESTSIZE> hash; - CryptoPP::SHA1().CalculateDigest(hash.data(), - buffer.data() + offsetof(NetworkInfoTag, network_info), - buffer.size() - sizeof(TagHeader)); - - // Copy it directly into the buffer, overwriting the zeros that we had previously placed there. - std::memcpy(buffer.data() + offsetof(NetworkInfoTag, sha_hash), hash.data(), hash.size()); - - return buffer; -} - -/* - * Calculates the CTR used for the AES-CTR encryption of the data stored in the - * EncryptedDataTags. - * @returns The CTR used for beacon crypto. - */ -std::array<u8, CryptoPP::AES::BLOCKSIZE> GetBeaconCryptoCTR(const NetworkInfo& network_info) { - BeaconDataCryptoCTR data{}; - - data.host_mac = network_info.host_mac_address; - data.wlan_comm_id = network_info.wlan_comm_id; - data.id = network_info.id; - data.network_id = network_info.network_id; - - std::array<u8, CryptoPP::AES::BLOCKSIZE> hash; - std::memcpy(hash.data(), &data, sizeof(data)); - - return hash; -} - -/* - * Serializes the node information into the format needed for network transfer, - * and then encrypts it with the NWM key. - * @returns The serialized and encrypted node information. - */ -std::vector<u8> GeneratedEncryptedData(const NetworkInfo& network_info, const NodeList& nodes) { - std::vector<u8> buffer(sizeof(BeaconData)); - - BeaconData data{}; - std::memcpy(buffer.data(), &data, sizeof(BeaconData)); - - for (const NodeInfo& node : nodes) { - // Serialize each node and convert the data from - // host byte-order to Big Endian. - BeaconNodeInfo info{}; - info.friend_code_seed = node.friend_code_seed; - info.network_node_id = node.network_node_id; - for (int i = 0; i < info.username.size(); ++i) - info.username[i] = node.username[i]; - - buffer.insert(buffer.end(), reinterpret_cast<u8*>(&info), - reinterpret_cast<u8*>(&info) + sizeof(info)); - } - - // Calculate the MD5 hash of the data in the buffer, not including the hash field. - std::array<u8, CryptoPP::MD5::DIGESTSIZE> hash; - CryptoPP::MD5().CalculateDigest(hash.data(), buffer.data() + offsetof(BeaconData, bitmask), - buffer.size() - sizeof(data.md5_hash)); - - // Copy the hash into the buffer. - std::memcpy(buffer.data(), hash.data(), hash.size()); - - // Encrypt the data using AES-CTR and the NWM beacon key. - using CryptoPP::AES; - std::array<u8, AES::BLOCKSIZE> counter = GetBeaconCryptoCTR(network_info); - CryptoPP::CTR_Mode<AES>::Encryption aes; - aes.SetKeyWithIV(nwm_beacon_key.data(), AES::BLOCKSIZE, counter.data()); - aes.ProcessData(buffer.data(), buffer.data(), buffer.size()); - - return buffer; -} - -void DecryptBeaconData(const NetworkInfo& network_info, std::vector<u8>& buffer) { - // Decrypt the data using AES-CTR and the NWM beacon key. - using CryptoPP::AES; - std::array<u8, AES::BLOCKSIZE> counter = GetBeaconCryptoCTR(network_info); - CryptoPP::CTR_Mode<AES>::Decryption aes; - aes.SetKeyWithIV(nwm_beacon_key.data(), AES::BLOCKSIZE, counter.data()); - aes.ProcessData(buffer.data(), buffer.data(), buffer.size()); -} - -/** - * Generates a buffer with the Network Info Nintendo tag. - * This tag contains the first portion of the encrypted payload in the 802.11 beacon frame. - * The encrypted payload contains information about the nodes currently connected to the network. - * @returns A buffer with the first Nintendo encrypted data parameters of the beacon frame. - */ -std::vector<u8> GenerateNintendoFirstEncryptedDataTag(const NetworkInfo& network_info, - const NodeList& nodes) { - const size_t payload_size = - std::min<size_t>(EncryptedDataSizeCutoff, nodes.size() * sizeof(NodeInfo)); - - EncryptedDataTag tag{}; - tag.header.tag_id = static_cast<u8>(TagId::VendorSpecific); - tag.header.length = static_cast<u8>(sizeof(tag) - sizeof(TagHeader) + payload_size); - tag.oui_type = static_cast<u8>(NintendoTagId::EncryptedData0); - tag.oui = NintendoOUI; - - std::vector<u8> buffer(sizeof(tag) + payload_size); - std::memcpy(buffer.data(), &tag, sizeof(tag)); - - std::vector<u8> encrypted_data = GeneratedEncryptedData(network_info, nodes); - std::memcpy(buffer.data() + sizeof(tag), encrypted_data.data(), payload_size); - - return buffer; -} - -/** - * Generates a buffer with the Network Info Nintendo tag. - * This tag contains the second portion of the encrypted payload in the 802.11 beacon frame. - * The encrypted payload contains information about the nodes currently connected to the network. - * This tag is only present if the payload size is greater than EncryptedDataSizeCutoff (0xFA) - * bytes. - * @returns A buffer with the second Nintendo encrypted data parameters of the beacon frame. - */ -std::vector<u8> GenerateNintendoSecondEncryptedDataTag(const NetworkInfo& network_info, - const NodeList& nodes) { - // This tag is only present if the payload is larger than EncryptedDataSizeCutoff (0xFA). - if (nodes.size() * sizeof(NodeInfo) <= EncryptedDataSizeCutoff) - return {}; - - const size_t payload_size = nodes.size() * sizeof(NodeInfo) - EncryptedDataSizeCutoff; - - const size_t tag_length = sizeof(EncryptedDataTag) - sizeof(TagHeader) + payload_size; - - // TODO(Subv): What does the 3DS do when a game has too much data to fit into the tag? - ASSERT_MSG(tag_length <= 255, "Data is too big."); - - EncryptedDataTag tag{}; - tag.header.tag_id = static_cast<u8>(TagId::VendorSpecific); - tag.header.length = static_cast<u8>(tag_length); - tag.oui_type = static_cast<u8>(NintendoTagId::EncryptedData1); - tag.oui = NintendoOUI; - - std::vector<u8> buffer(sizeof(tag) + payload_size); - std::memcpy(buffer.data(), &tag, sizeof(tag)); - - std::vector<u8> encrypted_data = GeneratedEncryptedData(network_info, nodes); - std::memcpy(buffer.data() + sizeof(tag), encrypted_data.data() + EncryptedDataSizeCutoff, - payload_size); - - return buffer; -} - -/** - * Generates a buffer with the Nintendo tagged parameters of an 802.11 Beacon frame - * for UDS communication. - * @returns A buffer with the Nintendo tagged parameters of the beacon frame. - */ -std::vector<u8> GenerateNintendoTaggedParameters(const NetworkInfo& network_info, - const NodeList& nodes) { - ASSERT_MSG(network_info.max_nodes == nodes.size(), "Inconsistent network state."); - - std::vector<u8> buffer = GenerateNintendoDummyTag(); - std::vector<u8> network_info_tag = GenerateNintendoNetworkInfoTag(network_info); - std::vector<u8> first_data_tag = GenerateNintendoFirstEncryptedDataTag(network_info, nodes); - std::vector<u8> second_data_tag = GenerateNintendoSecondEncryptedDataTag(network_info, nodes); - - buffer.insert(buffer.end(), network_info_tag.begin(), network_info_tag.end()); - buffer.insert(buffer.end(), first_data_tag.begin(), first_data_tag.end()); - buffer.insert(buffer.end(), second_data_tag.begin(), second_data_tag.end()); - - return buffer; -} - -std::vector<u8> GenerateBeaconFrame(const NetworkInfo& network_info, const NodeList& nodes) { - std::vector<u8> buffer = GenerateFixedParameters(); - std::vector<u8> basic_tags = GenerateBasicTaggedParameters(); - std::vector<u8> nintendo_tags = GenerateNintendoTaggedParameters(network_info, nodes); - - buffer.insert(buffer.end(), basic_tags.begin(), basic_tags.end()); - buffer.insert(buffer.end(), nintendo_tags.begin(), nintendo_tags.end()); - - return buffer; -} - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/uds_beacon.h b/src/core/hle/service/nwm/uds_beacon.h deleted file mode 100644 index 50cc76da2..000000000 --- a/src/core/hle/service/nwm/uds_beacon.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <array> -#include <deque> -#include <vector> -#include "common/common_types.h" -#include "common/swap.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace NWM { - -using MacAddress = std::array<u8, 6>; -constexpr std::array<u8, 3> NintendoOUI = {0x00, 0x1F, 0x32}; - -/** - * Internal vendor-specific tag ids as stored inside - * VendorSpecific blocks in the Beacon frames. - */ -enum class NintendoTagId : u8 { - Dummy = 20, - NetworkInfo = 21, - EncryptedData0 = 24, - EncryptedData1 = 25, -}; - -struct BeaconEntryHeader { - u32_le total_size; - INSERT_PADDING_BYTES(1); - u8 wifi_channel; - INSERT_PADDING_BYTES(2); - MacAddress mac_address; - INSERT_PADDING_BYTES(6); - u32_le unk_size; - u32_le header_size; -}; - -static_assert(sizeof(BeaconEntryHeader) == 0x1C, "BeaconEntryHeader has incorrect size."); - -struct BeaconDataReplyHeader { - u32_le max_output_size; - u32_le total_size; - u32_le total_entries; -}; - -static_assert(sizeof(BeaconDataReplyHeader) == 12, "BeaconDataReplyHeader has incorrect size."); - -#pragma pack(push, 1) -struct BeaconFrameHeader { - // Number of microseconds the AP has been active. - u64_le timestamp; - // Interval between beacon transmissions, expressed in TU. - u16_le beacon_interval; - // Indicates the presence of optional capabilities. - u16_le capabilities; -}; -#pragma pack(pop) - -static_assert(sizeof(BeaconFrameHeader) == 12, "BeaconFrameHeader has incorrect size."); - -struct TagHeader { - u8 tag_id; - u8 length; -}; - -static_assert(sizeof(TagHeader) == 2, "TagHeader has incorrect size."); - -struct DummyTag { - TagHeader header; - std::array<u8, 3> oui; - u8 oui_type; - std::array<u8, 3> data; -}; - -static_assert(sizeof(DummyTag) == 9, "DummyTag has incorrect size."); - -struct NetworkInfoTag { - TagHeader header; - std::array<u8, 0x1F> network_info; - std::array<u8, 0x14> sha_hash; - u8 appdata_size; -}; - -static_assert(sizeof(NetworkInfoTag) == 54, "NetworkInfoTag has incorrect size."); - -struct EncryptedDataTag { - TagHeader header; - std::array<u8, 3> oui; - u8 oui_type; -}; - -static_assert(sizeof(EncryptedDataTag) == 6, "EncryptedDataTag has incorrect size."); - -#pragma pack(push, 1) -// The raw bytes of this structure are the CTR used in the encryption (AES-CTR) -// of the beacon data stored in the EncryptedDataTags. -struct BeaconDataCryptoCTR { - MacAddress host_mac; - u32_le wlan_comm_id; - u8 id; - INSERT_PADDING_BYTES(1); - u32_le network_id; -}; - -static_assert(sizeof(BeaconDataCryptoCTR) == 0x10, "BeaconDataCryptoCTR has incorrect size."); - -struct BeaconNodeInfo { - u64_be friend_code_seed; - std::array<u16_be, 10> username; - u16_be network_node_id; -}; - -static_assert(sizeof(BeaconNodeInfo) == 0x1E, "BeaconNodeInfo has incorrect size."); - -struct BeaconData { - std::array<u8, 0x10> md5_hash; - u16_be bitmask; -}; -#pragma pack(pop) - -static_assert(sizeof(BeaconData) == 0x12, "BeaconData has incorrect size."); - -/** - * Decrypts the beacon data buffer for the network described by `network_info`. - */ -void DecryptBeaconData(const NetworkInfo& network_info, std::vector<u8>& buffer); - -/** - * Generates an 802.11 beacon frame starting at the management frame header. - * This frame contains information about the network and its connected clients. - * @returns The generated frame. - */ -std::vector<u8> GenerateBeaconFrame(const NetworkInfo& network_info, const NodeList& nodes); - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/uds_connection.cpp b/src/core/hle/service/nwm/uds_connection.cpp deleted file mode 100644 index c74f51253..000000000 --- a/src/core/hle/service/nwm/uds_connection.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/nwm/nwm_uds.h" -#include "core/hle/service/nwm/uds_connection.h" -#include "fmt/format.h" - -namespace Service { -namespace NWM { - -// Note: These values were taken from a packet capture of an o3DS XL -// broadcasting a Super Smash Bros. 4 lobby. -constexpr u16 DefaultExtraCapabilities = 0x0431; - -std::vector<u8> GenerateAuthenticationFrame(AuthenticationSeq seq) { - AuthenticationFrame frame{}; - frame.auth_seq = static_cast<u16>(seq); - - std::vector<u8> data(sizeof(frame)); - std::memcpy(data.data(), &frame, sizeof(frame)); - - return data; -} - -AuthenticationSeq GetAuthenticationSeqNumber(const std::vector<u8>& body) { - AuthenticationFrame frame; - std::memcpy(&frame, body.data(), sizeof(frame)); - - return static_cast<AuthenticationSeq>(frame.auth_seq); -} - -/** - * Generates an SSID tag of an 802.11 Beacon frame with an 8-byte character representation of the - * specified network id as the SSID value. - * @param network_id The network id to use. - * @returns A buffer with the SSID tag. - */ -static std::vector<u8> GenerateSSIDTag(u32 network_id) { - constexpr u8 SSIDSize = 8; - - struct { - u8 id = static_cast<u8>(TagId::SSID); - u8 size = SSIDSize; - } tag_header; - - std::vector<u8> buffer(sizeof(tag_header) + SSIDSize); - - std::memcpy(buffer.data(), &tag_header, sizeof(tag_header)); - - std::string network_name = fmt::format("{0:08X}", network_id); - - std::memcpy(buffer.data() + sizeof(tag_header), network_name.c_str(), SSIDSize); - - return buffer; -} - -std::vector<u8> GenerateAssocResponseFrame(AssocStatus status, u16 association_id, u32 network_id) { - AssociationResponseFrame frame{}; - frame.capabilities = DefaultExtraCapabilities; - frame.status_code = static_cast<u16>(status); - // The association id is ORed with this magic value (0xC000) - constexpr u16 AssociationIdMagic = 0xC000; - frame.assoc_id = association_id | AssociationIdMagic; - - std::vector<u8> data(sizeof(frame)); - std::memcpy(data.data(), &frame, sizeof(frame)); - - auto ssid_tag = GenerateSSIDTag(network_id); - data.insert(data.end(), ssid_tag.begin(), ssid_tag.end()); - - // TODO(Subv): Add the SupportedRates tag. - // TODO(Subv): Add the DSParameterSet tag. - // TODO(Subv): Add the ERPInformation tag. - return data; -} - -std::tuple<AssocStatus, u16> GetAssociationResult(const std::vector<u8>& body) { - AssociationResponseFrame frame; - memcpy(&frame, body.data(), sizeof(frame)); - - constexpr u16 AssociationIdMask = 0x3FFF; - return std::make_tuple(static_cast<AssocStatus>(frame.status_code), - frame.assoc_id & AssociationIdMask); -} - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/uds_connection.h b/src/core/hle/service/nwm/uds_connection.h deleted file mode 100644 index a664f8471..000000000 --- a/src/core/hle/service/nwm/uds_connection.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <tuple> -#include <vector> -#include "common/common_types.h" -#include "common/swap.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace NWM { - -/// Sequence number of the 802.11 authentication frames. -enum class AuthenticationSeq : u16 { SEQ1 = 1, SEQ2 = 2 }; - -enum class AuthAlgorithm : u16 { OpenSystem = 0 }; - -enum class AuthStatus : u16 { Successful = 0 }; - -enum class AssocStatus : u16 { Successful = 0 }; - -struct AuthenticationFrame { - u16_le auth_algorithm = static_cast<u16>(AuthAlgorithm::OpenSystem); - u16_le auth_seq; - u16_le status_code = static_cast<u16>(AuthStatus::Successful); -}; - -static_assert(sizeof(AuthenticationFrame) == 6, "AuthenticationFrame has wrong size"); - -struct AssociationResponseFrame { - u16_le capabilities; - u16_le status_code; - u16_le assoc_id; -}; - -static_assert(sizeof(AssociationResponseFrame) == 6, "AssociationResponseFrame has wrong size"); - -/// Generates an 802.11 authentication frame, starting at the frame body. -std::vector<u8> GenerateAuthenticationFrame(AuthenticationSeq seq); - -/// Returns the sequence number from the body of an Authentication frame. -AuthenticationSeq GetAuthenticationSeqNumber(const std::vector<u8>& body); - -/// Generates an 802.11 association response frame with the specified status, association id and -/// network id, starting at the frame body. -std::vector<u8> GenerateAssocResponseFrame(AssocStatus status, u16 association_id, u32 network_id); - -/// Returns a tuple of (association status, association id) from the body of an AssociationResponse -/// frame. -std::tuple<AssocStatus, u16> GetAssociationResult(const std::vector<u8>& body); - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/uds_data.cpp b/src/core/hle/service/nwm/uds_data.cpp deleted file mode 100644 index 4b389710f..000000000 --- a/src/core/hle/service/nwm/uds_data.cpp +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> -#include <cstring> -#include <cryptopp/aes.h> -#include <cryptopp/ccm.h> -#include <cryptopp/filters.h> -#include <cryptopp/md5.h> -#include <cryptopp/modes.h> -#include "core/hle/service/nwm/nwm_uds.h" -#include "core/hle/service/nwm/uds_data.h" -#include "core/hw/aes/key.h" - -namespace Service { -namespace NWM { - -using MacAddress = std::array<u8, 6>; - -/* - * Generates a SNAP-enabled 802.2 LLC header for the specified protocol. - * @returns a buffer with the bytes of the generated header. - */ -static std::vector<u8> GenerateLLCHeader(EtherType protocol) { - LLCHeader header{}; - header.protocol = static_cast<u16>(protocol); - - std::vector<u8> buffer(sizeof(header)); - memcpy(buffer.data(), &header, sizeof(header)); - - return buffer; -} - -/* - * Generates a Nintendo UDS SecureData header with the specified parameters. - * @returns a buffer with the bytes of the generated header. - */ -static std::vector<u8> GenerateSecureDataHeader(u16 data_size, u8 channel, u16 dest_node_id, - u16 src_node_id, u16 sequence_number) { - SecureDataHeader header{}; - header.protocol_size = data_size + sizeof(SecureDataHeader); - // Note: This size includes everything except the first 4 bytes of the structure, - // reinforcing the hypotheses that the first 4 bytes are actually the header of - // another container protocol. - header.securedata_size = data_size + sizeof(SecureDataHeader) - 4; - // Frames sent by the emulated application are never UDS management frames - header.is_management = 0; - header.data_channel = channel; - header.sequence_number = sequence_number; - header.dest_node_id = dest_node_id; - header.src_node_id = src_node_id; - - std::vector<u8> buffer(sizeof(header)); - memcpy(buffer.data(), &header, sizeof(header)); - - return buffer; -} - -/* - * Calculates the CTR used for the AES-CTR process that calculates - * the CCMP crypto key for data frames. - * @returns The CTR used for data frames crypto key generation. - */ -static std::array<u8, CryptoPP::MD5::DIGESTSIZE> GetDataCryptoCTR(const NetworkInfo& network_info) { - DataFrameCryptoCTR data{}; - - data.host_mac = network_info.host_mac_address; - data.wlan_comm_id = network_info.wlan_comm_id; - data.id = network_info.id; - data.network_id = network_info.network_id; - - std::array<u8, CryptoPP::MD5::DIGESTSIZE> hash; - CryptoPP::MD5().CalculateDigest(hash.data(), reinterpret_cast<u8*>(&data), sizeof(data)); - - return hash; -} - -/* - * Generates the key used for encrypting the 802.11 data frames generated by UDS. - * @returns The key used for data frames crypto. - */ -static std::array<u8, CryptoPP::AES::BLOCKSIZE> GenerateDataCCMPKey( - const std::vector<u8>& passphrase, const NetworkInfo& network_info) { - // Calculate the MD5 hash of the input passphrase. - std::array<u8, CryptoPP::MD5::DIGESTSIZE> passphrase_hash; - CryptoPP::MD5().CalculateDigest(passphrase_hash.data(), passphrase.data(), passphrase.size()); - - std::array<u8, CryptoPP::AES::BLOCKSIZE> ccmp_key; - - // The CCMP key is the result of encrypting the MD5 hash of the passphrase with AES-CTR using - // keyslot 0x2D. - using CryptoPP::AES; - std::array<u8, CryptoPP::MD5::DIGESTSIZE> counter = GetDataCryptoCTR(network_info); - std::array<u8, AES::BLOCKSIZE> key = HW::AES::GetNormalKey(HW::AES::KeySlotID::UDSDataKey); - CryptoPP::CTR_Mode<AES>::Encryption aes; - aes.SetKeyWithIV(key.data(), AES::BLOCKSIZE, counter.data()); - aes.ProcessData(ccmp_key.data(), passphrase_hash.data(), passphrase_hash.size()); - - return ccmp_key; -} - -/* - * Generates the Additional Authenticated Data (AAD) for an UDS 802.11 encrypted data frame. - * @returns a buffer with the bytes of the AAD. - */ -static std::vector<u8> GenerateCCMPAAD(const MacAddress& sender, const MacAddress& receiver, - const MacAddress& bssid, u16 frame_control) { - // Reference: IEEE 802.11-2007 - - // 8.3.3.3.2 Construct AAD (22-30 bytes) - // The AAD is constructed from the MPDU header. The AAD does not include the header Duration - // field, because the Duration field value can change due to normal IEEE 802.11 operation (e.g., - // a rate change during retransmission). For similar reasons, several subfields in the Frame - // Control field are masked to 0. - struct { - u16_be FC; // MPDU Frame Control field - MacAddress A1; - MacAddress A2; - MacAddress A3; - u16_be SC; // MPDU Sequence Control field - } aad_struct{}; - - constexpr u16 AADFrameControlMask = 0x8FC7; - aad_struct.FC = frame_control & AADFrameControlMask; - aad_struct.SC = 0; - - bool to_ds = (frame_control & (1 << 0)) != 0; - bool from_ds = (frame_control & (1 << 1)) != 0; - // In the 802.11 standard, ToDS = 1 and FromDS = 1 is a valid configuration, - // however, the 3DS doesn't seem to transmit frames with such combination. - ASSERT_MSG(to_ds != from_ds, "Invalid combination"); - - // The meaning of the address fields depends on the ToDS and FromDS fields. - if (from_ds) { - aad_struct.A1 = receiver; - aad_struct.A2 = bssid; - aad_struct.A3 = sender; - } - - if (to_ds) { - aad_struct.A1 = bssid; - aad_struct.A2 = sender; - aad_struct.A3 = receiver; - } - - std::vector<u8> aad(sizeof(aad_struct)); - std::memcpy(aad.data(), &aad_struct, sizeof(aad_struct)); - - return aad; -} - -/* - * Decrypts the payload of an encrypted 802.11 data frame using the specified key. - * @returns The decrypted payload. - */ -static std::vector<u8> DecryptDataFrame(const std::vector<u8>& encrypted_payload, - const std::array<u8, CryptoPP::AES::BLOCKSIZE>& ccmp_key, - const MacAddress& sender, const MacAddress& receiver, - const MacAddress& bssid, u16 sequence_number, - u16 frame_control) { - - // Reference: IEEE 802.11-2007 - - std::vector<u8> aad = GenerateCCMPAAD(sender, receiver, bssid, frame_control); - - std::vector<u8> packet_number{0, - 0, - 0, - 0, - static_cast<u8>((sequence_number >> 8) & 0xFF), - static_cast<u8>(sequence_number & 0xFF)}; - - // 8.3.3.3.3 Construct CCM nonce (13 bytes) - std::vector<u8> nonce; - nonce.push_back(0); // priority - nonce.insert(nonce.end(), sender.begin(), sender.end()); // Address 2 - nonce.insert(nonce.end(), packet_number.begin(), packet_number.end()); // PN - - try { - CryptoPP::CCM<CryptoPP::AES, 8>::Decryption d; - d.SetKeyWithIV(ccmp_key.data(), ccmp_key.size(), nonce.data(), nonce.size()); - d.SpecifyDataLengths(aad.size(), encrypted_payload.size() - 8, 0); - - CryptoPP::AuthenticatedDecryptionFilter df( - d, nullptr, CryptoPP::AuthenticatedDecryptionFilter::MAC_AT_END | - CryptoPP::AuthenticatedDecryptionFilter::THROW_EXCEPTION); - // put aad - df.ChannelPut(CryptoPP::AAD_CHANNEL, aad.data(), aad.size()); - - // put cipher with mac - df.ChannelPut(CryptoPP::DEFAULT_CHANNEL, encrypted_payload.data(), - encrypted_payload.size() - 8); - df.ChannelPut(CryptoPP::DEFAULT_CHANNEL, - encrypted_payload.data() + encrypted_payload.size() - 8, 8); - - df.ChannelMessageEnd(CryptoPP::AAD_CHANNEL); - df.ChannelMessageEnd(CryptoPP::DEFAULT_CHANNEL); - df.SetRetrievalChannel(CryptoPP::DEFAULT_CHANNEL); - - size_t size = df.MaxRetrievable(); - - std::vector<u8> pdata(size); - df.Get(pdata.data(), size); - return pdata; - } catch (CryptoPP::Exception&) { - LOG_ERROR(Service_NWM, "failed to decrypt"); - } - - return {}; -} - -/* - * Encrypts the payload of an 802.11 data frame using the specified key. - * @returns The encrypted payload. - */ -static std::vector<u8> EncryptDataFrame(const std::vector<u8>& payload, - const std::array<u8, CryptoPP::AES::BLOCKSIZE>& ccmp_key, - const MacAddress& sender, const MacAddress& receiver, - const MacAddress& bssid, u16 sequence_number, - u16 frame_control) { - // Reference: IEEE 802.11-2007 - - std::vector<u8> aad = GenerateCCMPAAD(sender, receiver, bssid, frame_control); - - std::vector<u8> packet_number{0, - 0, - 0, - 0, - static_cast<u8>((sequence_number >> 8) & 0xFF), - static_cast<u8>(sequence_number & 0xFF)}; - - // 8.3.3.3.3 Construct CCM nonce (13 bytes) - std::vector<u8> nonce; - nonce.push_back(0); // priority - nonce.insert(nonce.end(), sender.begin(), sender.end()); // Address 2 - nonce.insert(nonce.end(), packet_number.begin(), packet_number.end()); // PN - - try { - CryptoPP::CCM<CryptoPP::AES, 8>::Encryption d; - d.SetKeyWithIV(ccmp_key.data(), ccmp_key.size(), nonce.data(), nonce.size()); - d.SpecifyDataLengths(aad.size(), payload.size(), 0); - - CryptoPP::AuthenticatedEncryptionFilter df(d); - // put aad - df.ChannelPut(CryptoPP::AAD_CHANNEL, aad.data(), aad.size()); - df.ChannelMessageEnd(CryptoPP::AAD_CHANNEL); - - // put plaintext - df.ChannelPut(CryptoPP::DEFAULT_CHANNEL, payload.data(), payload.size()); - df.ChannelMessageEnd(CryptoPP::DEFAULT_CHANNEL); - - df.SetRetrievalChannel(CryptoPP::DEFAULT_CHANNEL); - - size_t size = df.MaxRetrievable(); - - std::vector<u8> cipher(size); - df.Get(cipher.data(), size); - return cipher; - } catch (CryptoPP::Exception&) { - LOG_ERROR(Service_NWM, "failed to encrypt"); - } - - return {}; -} - -std::vector<u8> GenerateDataPayload(const std::vector<u8>& data, u8 channel, u16 dest_node, - u16 src_node, u16 sequence_number) { - std::vector<u8> buffer = GenerateLLCHeader(EtherType::SecureData); - std::vector<u8> securedata_header = GenerateSecureDataHeader( - static_cast<u16>(data.size()), channel, dest_node, src_node, sequence_number); - - buffer.insert(buffer.end(), securedata_header.begin(), securedata_header.end()); - buffer.insert(buffer.end(), data.begin(), data.end()); - return buffer; -} - -std::vector<u8> GenerateEAPoLStartFrame(u16 association_id, const NodeInfo& node_info) { - EAPoLStartPacket eapol_start{}; - eapol_start.association_id = association_id; - eapol_start.node.friend_code_seed = node_info.friend_code_seed; - - std::copy(node_info.username.begin(), node_info.username.end(), - eapol_start.node.username.begin()); - - // Note: The network_node_id and unknown bytes seem to be uninitialized in the NWM module. - // TODO(B3N30): The last 8 bytes seem to have a fixed value of 07 88 15 00 04 e9 13 00 in - // EAPoL-Start packets from different 3DSs to the same host during a Super Smash Bros. 4 game. - // Find out what that means. - - std::vector<u8> eapol_buffer(sizeof(EAPoLStartPacket)); - std::memcpy(eapol_buffer.data(), &eapol_start, sizeof(eapol_start)); - - std::vector<u8> buffer = GenerateLLCHeader(EtherType::EAPoL); - buffer.insert(buffer.end(), eapol_buffer.begin(), eapol_buffer.end()); - return buffer; -} - -EtherType GetFrameEtherType(const std::vector<u8>& frame) { - LLCHeader header; - std::memcpy(&header, frame.data(), sizeof(header)); - - u16 ethertype = header.protocol; - return static_cast<EtherType>(ethertype); -} - -u16 GetEAPoLFrameType(const std::vector<u8>& frame) { - // Ignore the LLC header - u16_be eapol_type; - std::memcpy(&eapol_type, frame.data() + sizeof(LLCHeader), sizeof(eapol_type)); - return eapol_type; -} - -NodeInfo DeserializeNodeInfoFromFrame(const std::vector<u8>& frame) { - EAPoLStartPacket eapol_start; - - // Skip the LLC header - std::memcpy(&eapol_start, frame.data() + sizeof(LLCHeader), sizeof(eapol_start)); - - NodeInfo node{}; - node.friend_code_seed = eapol_start.node.friend_code_seed; - - std::copy(eapol_start.node.username.begin(), eapol_start.node.username.end(), - node.username.begin()); - - return node; -} - -NodeInfo DeserializeNodeInfo(const EAPoLNodeInfo& node) { - NodeInfo node_info{}; - node_info.friend_code_seed = node.friend_code_seed; - node_info.network_node_id = node.network_node_id; - - std::copy(node.username.begin(), node.username.end(), node_info.username.begin()); - - return node_info; -} - -std::vector<u8> GenerateEAPoLLogoffFrame(const MacAddress& mac_address, u16 network_node_id, - const NodeList& nodes, u8 max_nodes, u8 total_nodes) { - EAPoLLogoffPacket eapol_logoff{}; - eapol_logoff.assigned_node_id = network_node_id; - eapol_logoff.connected_nodes = total_nodes; - eapol_logoff.max_nodes = max_nodes; - - for (size_t index = 0; index < total_nodes; ++index) { - const auto& node_info = nodes[index]; - auto& node = eapol_logoff.nodes[index]; - - node.friend_code_seed = node_info.friend_code_seed; - node.network_node_id = node_info.network_node_id; - - std::copy(node_info.username.begin(), node_info.username.end(), node.username.begin()); - } - - std::vector<u8> eapol_buffer(sizeof(EAPoLLogoffPacket)); - std::memcpy(eapol_buffer.data(), &eapol_logoff, sizeof(eapol_logoff)); - - std::vector<u8> buffer = GenerateLLCHeader(EtherType::EAPoL); - buffer.insert(buffer.end(), eapol_buffer.begin(), eapol_buffer.end()); - return buffer; -} - -EAPoLLogoffPacket ParseEAPoLLogoffFrame(const std::vector<u8>& frame) { - EAPoLLogoffPacket eapol_logoff; - - // Skip the LLC header - std::memcpy(&eapol_logoff, frame.data() + sizeof(LLCHeader), sizeof(eapol_logoff)); - return eapol_logoff; -} - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/nwm/uds_data.h b/src/core/hle/service/nwm/uds_data.h deleted file mode 100644 index 76bccb1bf..000000000 --- a/src/core/hle/service/nwm/uds_data.h +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <array> -#include <vector> -#include "common/common_types.h" -#include "common/swap.h" -#include "core/hle/service/nwm/uds_beacon.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace NWM { - -enum class SAP : u8 { SNAPExtensionUsed = 0xAA }; - -enum class PDUControl : u8 { UnnumberedInformation = 3 }; - -enum class EtherType : u16 { SecureData = 0x876D, EAPoL = 0x888E }; - -/* - * 802.2 header, UDS packets always use SNAP for these headers, - * which means the dsap and ssap are always SNAPExtensionUsed (0xAA) - * and the OUI is always 0. - */ -struct LLCHeader { - u8 dsap = static_cast<u8>(SAP::SNAPExtensionUsed); - u8 ssap = static_cast<u8>(SAP::SNAPExtensionUsed); - u8 control = static_cast<u8>(PDUControl::UnnumberedInformation); - std::array<u8, 3> OUI = {}; - u16_be protocol; -}; - -static_assert(sizeof(LLCHeader) == 8, "LLCHeader has the wrong size"); - -/* - * Nintendo SecureData header, every UDS packet contains one, - * it is used to store metadata about the transmission such as - * the source and destination network node ids. - */ -struct SecureDataHeader { - // TODO(Subv): It is likely that the first 4 bytes of this header are - // actually part of another container protocol. - u16_be protocol_size; - INSERT_PADDING_BYTES(2); - u16_be securedata_size; - u8 is_management; - u8 data_channel; - u16_be sequence_number; - u16_be dest_node_id; - u16_be src_node_id; -}; - -static_assert(sizeof(SecureDataHeader) == 14, "SecureDataHeader has the wrong size"); - -/* - * The raw bytes of this structure are the CTR used in the encryption (AES-CTR) - * process used to generate the CCMP key for data frame encryption. - */ -struct DataFrameCryptoCTR { - u32_le wlan_comm_id; - u32_le network_id; - std::array<u8, 6> host_mac; - u16_le id; -}; - -static_assert(sizeof(DataFrameCryptoCTR) == 16, "DataFrameCryptoCTR has the wrong size"); - -struct EAPoLNodeInfo { - u64_be friend_code_seed; - std::array<u16_be, 10> username; - INSERT_PADDING_BYTES(4); - u16_be network_node_id; - INSERT_PADDING_BYTES(6); -}; - -static_assert(sizeof(EAPoLNodeInfo) == 0x28, "EAPoLNodeInfo has the wrong size"); - -constexpr u16 EAPoLStartMagic = 0x201; - -/* - * Nintendo EAPoLStartPacket, is used to initaliaze a connection between client and host - */ -struct EAPoLStartPacket { - u16_be magic = EAPoLStartMagic; - u16_be association_id; - // This value is hardcoded to 1 in the NWM module. - u16_be unknown = 1; - INSERT_PADDING_BYTES(2); - EAPoLNodeInfo node; -}; - -static_assert(sizeof(EAPoLStartPacket) == 0x30, "EAPoLStartPacket has the wrong size"); - -constexpr u16 EAPoLLogoffMagic = 0x202; - -struct EAPoLLogoffPacket { - u16_be magic = EAPoLLogoffMagic; - INSERT_PADDING_BYTES(2); - u16_be assigned_node_id; - MacAddress client_mac_address; - INSERT_PADDING_BYTES(6); - u8 connected_nodes; - u8 max_nodes; - INSERT_PADDING_BYTES(4); - - std::array<EAPoLNodeInfo, UDSMaxNodes> nodes; -}; - -static_assert(sizeof(EAPoLLogoffPacket) == 0x298, "EAPoLLogoffPacket has the wrong size"); - -/** - * Generates an unencrypted 802.11 data payload. - * @returns The generated frame payload. - */ -std::vector<u8> GenerateDataPayload(const std::vector<u8>& data, u8 channel, u16 dest_node, - u16 src_node, u16 sequence_number); - -/* - * Generates an unencrypted 802.11 data frame body with the EAPoL-Start format for UDS - * communication. - * @returns The generated frame body. - */ -std::vector<u8> GenerateEAPoLStartFrame(u16 association_id, const NodeInfo& node_info); - -/* - * Returns the EtherType of the specified 802.11 frame. - */ -EtherType GetFrameEtherType(const std::vector<u8>& frame); - -/* - * Returns the EAPoL type (Start / Logoff) of the specified 802.11 frame. - * Note: The frame *must* be an EAPoL frame. - */ -u16 GetEAPoLFrameType(const std::vector<u8>& frame); - -/* - * Returns a deserialized NodeInfo structure from the information inside an EAPoL-Start packet - * encapsulated in an 802.11 data frame. - */ -NodeInfo DeserializeNodeInfoFromFrame(const std::vector<u8>& frame); - -/* - * Returns a NodeInfo constructed from the data in the specified EAPoLNodeInfo. - */ -NodeInfo DeserializeNodeInfo(const EAPoLNodeInfo& node); - -/* - * Generates an unencrypted 802.11 data frame body with the EAPoL-Logoff format for UDS - * communication. - * @returns The generated frame body. - */ -std::vector<u8> GenerateEAPoLLogoffFrame(const MacAddress& mac_address, u16 network_node_id, - const NodeList& nodes, u8 max_nodes, u8 total_nodes); - -/* - * Returns a EAPoLLogoffPacket representing the specified 802.11-encapsulated data frame. - */ -EAPoLLogoffPacket ParseEAPoLLogoffFrame(const std::vector<u8>& frame); - -} // namespace NWM -} // namespace Service diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp deleted file mode 100644 index caa16f952..000000000 --- a/src/core/hle/service/pm_app.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/pm_app.h" - -namespace Service { -namespace PM { - -const Interface::FunctionInfo FunctionTable[] = { - // clang-format off - {0x00010140, nullptr, "LaunchTitle"}, - {0x00020082, nullptr, "LaunchFIRM"}, - {0x00030080, nullptr, "TerminateApplication"}, - {0x00040100, nullptr, "TerminateTitle"}, - {0x000500C0, nullptr, "TerminateProcess"}, - {0x00060082, nullptr, "PrepareForReboot"}, - {0x00070042, nullptr, "GetFIRMLaunchParams"}, - {0x00080100, nullptr, "GetTitleExheaderFlags"}, - {0x00090042, nullptr, "SetFIRMLaunchParams"}, - {0x000A0140, nullptr, "SetAppResourceLimit"}, - {0x000B0140, nullptr, "GetAppResourceLimit"}, - {0x000C0080, nullptr, "UnregisterProcess"}, - {0x000D0240, nullptr, "LaunchTitleUpdate"}, - // clang-format on -}; - -PM_APP::PM_APP() { - Register(FunctionTable); -} - -} // namespace PM -} // namespace Service diff --git a/src/core/hle/service/pm_app.h b/src/core/hle/service/pm_app.h deleted file mode 100644 index 151c69f3d..000000000 --- a/src/core/hle/service/pm_app.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace PM { - -class PM_APP final : public Interface { -public: - PM_APP(); - - std::string GetPortName() const override { - return "pm:app"; - } -}; - -} // namespace PM -} // namespace Service diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp deleted file mode 100644 index a0b959797..000000000 --- a/src/core/hle/service/ptm/ptm.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/logging/log.h" -#include "core/file_sys/errors.h" -#include "core/file_sys/file_backend.h" -#include "core/hle/service/fs/archive.h" -#include "core/hle/service/ptm/ptm.h" -#include "core/hle/service/ptm/ptm_gets.h" -#include "core/hle/service/ptm/ptm_play.h" -#include "core/hle/service/ptm/ptm_sets.h" -#include "core/hle/service/ptm/ptm_sysm.h" -#include "core/hle/service/ptm/ptm_u.h" -#include "core/hle/service/service.h" -#include "core/settings.h" - -namespace Service { -namespace PTM { - -/// Values for the default gamecoin.dat file -static const GameCoin default_game_coin = {0x4F00, 42, 0, 0, 0, 2014, 12, 29}; - -/// Id of the SharedExtData archive used by the PTM process -static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0}; - -static bool shell_open; - -static bool battery_is_charging; - -static bool pedometer_is_counting; - -void GetAdapterState(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x5, 0, 0); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); - rb.Push(battery_is_charging); - - LOG_WARNING(Service_PTM, "(STUBBED) called"); -} - -void GetShellState(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x6, 0, 0); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); - rb.Push(shell_open); -} - -void GetBatteryLevel(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x7, 0, 0); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); - rb.Push(static_cast<u32>(ChargeLevels::CompletelyFull)); // Set to a completely full battery - - LOG_WARNING(Service_PTM, "(STUBBED) called"); -} - -void GetBatteryChargeState(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x8, 0, 0); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); - rb.Push(battery_is_charging); - - LOG_WARNING(Service_PTM, "(STUBBED) called"); -} - -void GetPedometerState(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x9, 0, 0); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); - rb.Push(pedometer_is_counting); - - LOG_WARNING(Service_PTM, "(STUBBED) called"); -} - -void GetTotalStepCount(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xC, 0, 0); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); - rb.Push<u32>(0); - - LOG_WARNING(Service_PTM, "(STUBBED) called"); -} - -void GetSoftwareClosedFlag(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x80F, 0, 0); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); - rb.Push(false); - - LOG_WARNING(Service_PTM, "(STUBBED) called"); -} - -void CheckNew3DS(IPC::RequestBuilder& rb) { - const bool is_new_3ds = Settings::values.is_new_3ds; - - if (is_new_3ds) { - LOG_CRITICAL(Service_PTM, "The option 'is_new_3ds' is enabled as part of the 'System' " - "settings. Citra does not fully support New 3DS emulation yet!"); - } - - rb.Push(RESULT_SUCCESS); - rb.Push(is_new_3ds); - - LOG_WARNING(Service_PTM, "(STUBBED) called isNew3DS = 0x%08x", static_cast<u32>(is_new_3ds)); -} - -void CheckNew3DS(Service::Interface* self) { - IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x40A, 0, 0); // 0x040A0000 - CheckNew3DS(rb); -} - -void Init() { - AddService(new PTM_Gets); - AddService(new PTM_Play); - AddService(new PTM_S); - AddService(new PTM_Sets); - AddService(new PTM_Sysm); - AddService(new PTM_U); - - shell_open = true; - battery_is_charging = true; - pedometer_is_counting = false; - - // Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't - // exist - FileSys::Path archive_path(ptm_shared_extdata_id); - auto archive_result = - Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); - // If the archive didn't exist, create the files inside - if (archive_result.Code() == FileSys::ERR_NOT_FORMATTED) { - // Format the archive to create the directories - Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, - FileSys::ArchiveFormatInfo(), archive_path); - // Open it again to get a valid archive now that the folder exists - archive_result = - Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); - ASSERT_MSG(archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!"); - - FileSys::Path gamecoin_path("/gamecoin.dat"); - Service::FS::CreateFileInArchive(*archive_result, gamecoin_path, sizeof(GameCoin)); - FileSys::Mode open_mode = {}; - open_mode.write_flag.Assign(1); - // Open the file and write the default gamecoin information - auto gamecoin_result = - Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode); - if (gamecoin_result.Succeeded()) { - auto gamecoin = std::move(gamecoin_result).Unwrap(); - gamecoin->backend->Write(0, sizeof(GameCoin), true, - reinterpret_cast<const u8*>(&default_game_coin)); - gamecoin->backend->Close(); - } - } -} - -void Shutdown() {} - -} // namespace PTM -} // namespace Service diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h deleted file mode 100644 index e17e59835..000000000 --- a/src/core/hle/service/ptm/ptm.h +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_types.h" -#include "core/hle/ipc_helpers.h" - -namespace Service { - -class Interface; - -namespace PTM { - -/// Charge levels used by PTM functions -enum class ChargeLevels : u32 { - CriticalBattery = 1, - LowBattery = 2, - HalfFull = 3, - MostlyFull = 4, - CompletelyFull = 5, -}; - -/** - * Represents the gamecoin file structure in the SharedExtData archive - * More information in 3dbrew - * (http://www.3dbrew.org/wiki/Extdata#Shared_Extdata_0xf000000b_gamecoin.dat) - */ -struct GameCoin { - u32 magic; ///< Magic number: 0x4F00 - u16 total_coins; ///< Total Play Coins - u16 total_coins_on_date; ///< Total Play Coins obtained on the date stored below. - u32 step_count; ///< Total step count at the time a new Play Coin was obtained. - u32 last_step_count; ///< Step count for the day the last Play Coin was obtained - u16 year; - u8 month; - u8 day; -}; - -/** - * It is unknown if GetAdapterState is the same as GetBatteryChargeState, - * it is likely to just be a duplicate function of GetBatteryChargeState - * that controls another part of the HW. - * PTM::GetAdapterState service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Output of function, 0 = not charging, 1 = charging. - */ -void GetAdapterState(Interface* self); - -/** - * PTM::GetShellState service function. - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Whether the 3DS's physical shell casing is open (1) or closed (0) - */ -void GetShellState(Interface* self); - -/** - * PTM::GetBatteryLevel service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Battery level, 5 = completely full battery, 4 = mostly full battery, - * 3 = half full battery, 2 = low battery, 1 = critical battery. - */ -void GetBatteryLevel(Interface* self); - -/** - * PTM::GetBatteryChargeState service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Output of function, 0 = not charging, 1 = charging. - */ -void GetBatteryChargeState(Interface* self); - -/** - * PTM::GetPedometerState service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Output of function, 0 = not counting steps, 1 = counting steps. - */ -void GetPedometerState(Interface* self); - -/** - * PTM::GetTotalStepCount service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Output of function, * = total step count - */ -void GetTotalStepCount(Interface* self); - -/** - * PTM::GetSoftwareClosedFlag service function - * Outputs: - * 1: Result code, 0 on success, otherwise error code - * 2: Whether or not the "software closed" dialog was requested by the last FIRM - * and should be displayed. - */ -void GetSoftwareClosedFlag(Interface* self); - -/** - * PTM::CheckNew3DS service function - * Outputs: - * 1: Result code, 0 on success, otherwise error code - * 2: u8 output: 0 = Old3DS, 1 = New3DS. - */ -void CheckNew3DS(Interface* self); -void CheckNew3DS(IPC::RequestBuilder& rb); - -/// Initialize the PTM service -void Init(); - -/// Shutdown the PTM service -void Shutdown(); - -} // namespace PTM -} // namespace Service diff --git a/src/core/hle/service/ptm/ptm_gets.cpp b/src/core/hle/service/ptm/ptm_gets.cpp deleted file mode 100644 index b23e508d6..000000000 --- a/src/core/hle/service/ptm/ptm_gets.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/ptm/ptm.h" -#include "core/hle/service/ptm/ptm_gets.h" - -namespace Service { -namespace PTM { - -const Interface::FunctionInfo FunctionTable[] = { - // ptm:u common commands - {0x00010002, nullptr, "RegisterAlarmClient"}, - {0x00020080, nullptr, "SetRtcAlarm"}, - {0x00030000, nullptr, "GetRtcAlarm"}, - {0x00040000, nullptr, "CancelRtcAlarm"}, - {0x00050000, GetAdapterState, "GetAdapterState"}, - {0x00060000, GetShellState, "GetShellState"}, - {0x00070000, GetBatteryLevel, "GetBatteryLevel"}, - {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"}, - {0x00090000, nullptr, "GetPedometerState"}, - {0x000A0042, nullptr, "GetStepHistoryEntry"}, - {0x000B00C2, nullptr, "GetStepHistory"}, - {0x000C0000, GetTotalStepCount, "GetTotalStepCount"}, - {0x000D0040, nullptr, "SetPedometerRecordingMode"}, - {0x000E0000, nullptr, "GetPedometerRecordingMode"}, - {0x000F0084, nullptr, "GetStepHistoryAll"}, - // ptm:gets - {0x04010000, nullptr, "GetSystemTime"}, -}; - -PTM_Gets::PTM_Gets() { - Register(FunctionTable); -} - -} // namespace PTM -} // namespace Service diff --git a/src/core/hle/service/ptm/ptm_gets.h b/src/core/hle/service/ptm/ptm_gets.h deleted file mode 100644 index 5552c9eff..000000000 --- a/src/core/hle/service/ptm/ptm_gets.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace PTM { - -class PTM_Gets final : public Interface { -public: - PTM_Gets(); - - std::string GetPortName() const override { - return "ptm:gets"; - } -}; - -} // namespace PTM -} // namespace Service diff --git a/src/core/hle/service/ptm/ptm_play.cpp b/src/core/hle/service/ptm/ptm_play.cpp deleted file mode 100644 index bcb00e0d4..000000000 --- a/src/core/hle/service/ptm/ptm_play.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/ptm/ptm.h" -#include "core/hle/service/ptm/ptm_play.h" - -namespace Service { -namespace PTM { - -const Interface::FunctionInfo FunctionTable[] = { - // ptm:u common commands - {0x00010002, nullptr, "RegisterAlarmClient"}, - {0x00020080, nullptr, "SetRtcAlarm"}, - {0x00030000, nullptr, "GetRtcAlarm"}, - {0x00040000, nullptr, "CancelRtcAlarm"}, - {0x00050000, GetAdapterState, "GetAdapterState"}, - {0x00060000, GetShellState, "GetShellState"}, - {0x00070000, GetBatteryLevel, "GetBatteryLevel"}, - {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"}, - {0x00090000, nullptr, "GetPedometerState"}, - {0x000A0042, nullptr, "GetStepHistoryEntry"}, - {0x000B00C2, nullptr, "GetStepHistory"}, - {0x000C0000, GetTotalStepCount, "GetTotalStepCount"}, - {0x000D0040, nullptr, "SetPedometerRecordingMode"}, - {0x000E0000, nullptr, "GetPedometerRecordingMode"}, - {0x000F0084, nullptr, "GetStepHistoryAll"}, - // ptm:play - {0x08070082, nullptr, "GetPlayHistory"}, - {0x08080000, nullptr, "GetPlayHistoryStart"}, - {0x08090000, nullptr, "GetPlayHistoryLength"}, - {0x080B0080, nullptr, "CalcPlayHistoryStart"}, -}; - -PTM_Play::PTM_Play() { - Register(FunctionTable); -} - -} // namespace PTM -} // namespace Service
\ No newline at end of file diff --git a/src/core/hle/service/ptm/ptm_play.h b/src/core/hle/service/ptm/ptm_play.h deleted file mode 100644 index 663faabee..000000000 --- a/src/core/hle/service/ptm/ptm_play.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace PTM { - -class PTM_Play final : public Interface { -public: - PTM_Play(); - - std::string GetPortName() const override { - return "ptm:play"; - } -}; - -} // namespace PTM -} // namespace Service diff --git a/src/core/hle/service/ptm/ptm_sets.cpp b/src/core/hle/service/ptm/ptm_sets.cpp deleted file mode 100644 index a8c6cf227..000000000 --- a/src/core/hle/service/ptm/ptm_sets.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/ptm/ptm_sets.h" - -namespace Service { -namespace PTM { - -const Interface::FunctionInfo FunctionTable[] = { - // Note that this service does not have access to ptm:u's common commands - {0x00010080, nullptr, "SetSystemTime"}, -}; - -PTM_Sets::PTM_Sets() { - Register(FunctionTable); -} - -} // namespace PTM -} // namespace Service diff --git a/src/core/hle/service/ptm/ptm_sets.h b/src/core/hle/service/ptm/ptm_sets.h deleted file mode 100644 index d33b047e5..000000000 --- a/src/core/hle/service/ptm/ptm_sets.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace PTM { - -class PTM_Sets final : public Interface { -public: - PTM_Sets(); - - std::string GetPortName() const override { - return "ptm:sets"; - } -}; - -} // namespace PTM -} // namespace Service diff --git a/src/core/hle/service/ptm/ptm_sysm.cpp b/src/core/hle/service/ptm/ptm_sysm.cpp deleted file mode 100644 index f95dfdbb1..000000000 --- a/src/core/hle/service/ptm/ptm_sysm.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/ptm/ptm.h" -#include "core/hle/service/ptm/ptm_sysm.h" - -namespace Service { -namespace PTM { - -const Interface::FunctionInfo FunctionTable[] = { - // ptm:u common commands - {0x00010002, nullptr, "RegisterAlarmClient"}, - {0x00020080, nullptr, "SetRtcAlarm"}, - {0x00030000, nullptr, "GetRtcAlarm"}, - {0x00040000, nullptr, "CancelRtcAlarm"}, - {0x00050000, GetAdapterState, "GetAdapterState"}, - {0x00060000, GetShellState, "GetShellState"}, - {0x00070000, GetBatteryLevel, "GetBatteryLevel"}, - {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"}, - {0x00090000, nullptr, "GetPedometerState"}, - {0x000A0042, nullptr, "GetStepHistoryEntry"}, - {0x000B00C2, nullptr, "GetStepHistory"}, - {0x000C0000, GetTotalStepCount, "GetTotalStepCount"}, - {0x000D0040, nullptr, "SetPedometerRecordingMode"}, - {0x000E0000, nullptr, "GetPedometerRecordingMode"}, - {0x000F0084, nullptr, "GetStepHistoryAll"}, - // ptm:sysm - {0x040100C0, nullptr, "SetRtcAlarmEx"}, - {0x04020042, nullptr, "ReplySleepQuery"}, - {0x04030042, nullptr, "NotifySleepPreparationComplete"}, - {0x04040102, nullptr, "SetWakeupTrigger"}, - {0x04050000, nullptr, "GetAwakeReason"}, - {0x04060000, nullptr, "RequestSleep"}, - {0x040700C0, nullptr, "ShutdownAsync"}, - {0x04080000, nullptr, "Awake"}, - {0x04090080, nullptr, "RebootAsync"}, - {0x040A0000, CheckNew3DS, "CheckNew3DS"}, - {0x08010640, nullptr, "SetInfoLEDPattern"}, - {0x08020040, nullptr, "SetInfoLEDPatternHeader"}, - {0x08030000, nullptr, "GetInfoLEDStatus"}, - {0x08040040, nullptr, "SetBatteryEmptyLEDPattern"}, - {0x08050000, nullptr, "ClearStepHistory"}, - {0x080600C2, nullptr, "SetStepHistory"}, - {0x08070082, nullptr, "GetPlayHistory"}, - {0x08080000, nullptr, "GetPlayHistoryStart"}, - {0x08090000, nullptr, "GetPlayHistoryLength"}, - {0x080A0000, nullptr, "ClearPlayHistory"}, - {0x080B0080, nullptr, "CalcPlayHistoryStart"}, - {0x080C0080, nullptr, "SetUserTime"}, - {0x080D0000, nullptr, "InvalidateSystemTime"}, - {0x080E0140, nullptr, "NotifyPlayEvent"}, - {0x080F0000, GetSoftwareClosedFlag, "GetSoftwareClosedFlag"}, - {0x08100000, nullptr, "ClearSoftwareClosedFlag"}, - {0x08110000, GetShellState, "GetShellState"}, - {0x08120000, nullptr, "IsShutdownByBatteryEmpty"}, - {0x08130000, nullptr, "FormatSavedata"}, - {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"}, - {0x08180040, nullptr, "ConfigureNew3DSCPU"}, -}; - -PTM_S::PTM_S() { - Register(FunctionTable); -} - -PTM_Sysm::PTM_Sysm() { - Register(FunctionTable); -} - -} // namespace PTM -} // namespace Service diff --git a/src/core/hle/service/ptm/ptm_sysm.h b/src/core/hle/service/ptm/ptm_sysm.h deleted file mode 100644 index 8afcebbba..000000000 --- a/src/core/hle/service/ptm/ptm_sysm.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace PTM { - -class PTM_S final : public Interface { -public: - PTM_S(); - - std::string GetPortName() const override { - return "ptm:s"; - } -}; - -class PTM_Sysm final : public Interface { -public: - PTM_Sysm(); - - std::string GetPortName() const override { - return "ptm:sysm"; - } -}; - -} // namespace PTM -} // namespace Service diff --git a/src/core/hle/service/ptm/ptm_u.cpp b/src/core/hle/service/ptm/ptm_u.cpp deleted file mode 100644 index 696a58a36..000000000 --- a/src/core/hle/service/ptm/ptm_u.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/ptm/ptm.h" -#include "core/hle/service/ptm/ptm_u.h" - -namespace Service { -namespace PTM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010002, nullptr, "RegisterAlarmClient"}, - {0x00020080, nullptr, "SetRtcAlarm"}, - {0x00030000, nullptr, "GetRtcAlarm"}, - {0x00040000, nullptr, "CancelRtcAlarm"}, - {0x00050000, GetAdapterState, "GetAdapterState"}, - {0x00060000, GetShellState, "GetShellState"}, - {0x00070000, GetBatteryLevel, "GetBatteryLevel"}, - {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"}, - {0x00090000, GetPedometerState, "GetPedometerState"}, - {0x000A0042, nullptr, "GetStepHistoryEntry"}, - {0x000B00C2, nullptr, "GetStepHistory"}, - {0x000C0000, GetTotalStepCount, "GetTotalStepCount"}, - {0x000D0040, nullptr, "SetPedometerRecordingMode"}, - {0x000E0000, nullptr, "GetPedometerRecordingMode"}, - {0x000F0084, nullptr, "GetStepHistoryAll"}, -}; - -PTM_U::PTM_U() { - Register(FunctionTable); -} - -} // namespace PTM -} // namespace Service diff --git a/src/core/hle/service/ptm/ptm_u.h b/src/core/hle/service/ptm/ptm_u.h deleted file mode 100644 index 7b75d6e49..000000000 --- a/src/core/hle/service/ptm/ptm_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace PTM { - -class PTM_U final : public Interface { -public: - PTM_U(); - - std::string GetPortName() const override { - return "ptm:u"; - } -}; - -} // namespace PTM -} // namespace Service
\ No newline at end of file diff --git a/src/core/hle/service/qtm/qtm.cpp b/src/core/hle/service/qtm/qtm.cpp deleted file mode 100644 index f11542263..000000000 --- a/src/core/hle/service/qtm/qtm.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/qtm/qtm.h" -#include "core/hle/service/qtm/qtm_s.h" -#include "core/hle/service/qtm/qtm_sp.h" -#include "core/hle/service/qtm/qtm_u.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace QTM { - -void Init() { - AddService(new QTM_S()); - AddService(new QTM_SP()); - AddService(new QTM_U()); -} - -} // namespace QTM -} // namespace Service diff --git a/src/core/hle/service/qtm/qtm.h b/src/core/hle/service/qtm/qtm.h deleted file mode 100644 index 33b774c79..000000000 --- a/src/core/hle/service/qtm/qtm.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service { -namespace QTM { - -/// Initializes all QTM services. -void Init(); - -} // namespace QTM -} // namespace Service diff --git a/src/core/hle/service/qtm/qtm_s.cpp b/src/core/hle/service/qtm/qtm_s.cpp deleted file mode 100644 index ad7df24a0..000000000 --- a/src/core/hle/service/qtm/qtm_s.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/qtm/qtm_s.h" - -namespace Service { -namespace QTM { - -const Interface::FunctionInfo FunctionTable[] = { - // clang-format off - // qtm common commands - {0x00010080, nullptr, "GetHeadtrackingInfoRaw"}, - {0x00020080, nullptr, "GetHeadtrackingInfo"}, - // clang-format on -}; - -QTM_S::QTM_S() { - Register(FunctionTable); -} - -} // namespace QTM -} // namespace Service diff --git a/src/core/hle/service/qtm/qtm_s.h b/src/core/hle/service/qtm/qtm_s.h deleted file mode 100644 index e66138ed0..000000000 --- a/src/core/hle/service/qtm/qtm_s.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace QTM { - -class QTM_S final : public Interface { -public: - QTM_S(); - - std::string GetPortName() const override { - return "qtm:s"; - } -}; - -} // namespace QTM -} // namespace Service diff --git a/src/core/hle/service/qtm/qtm_sp.cpp b/src/core/hle/service/qtm/qtm_sp.cpp deleted file mode 100644 index 6e0695d34..000000000 --- a/src/core/hle/service/qtm/qtm_sp.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/qtm/qtm_sp.h" - -namespace Service { -namespace QTM { - -const Interface::FunctionInfo FunctionTable[] = { - // clang-format off - // qtm common commands - {0x00010080, nullptr, "GetHeadtrackingInfoRaw"}, - {0x00020080, nullptr, "GetHeadtrackingInfo"}, - // clang-format on -}; - -QTM_SP::QTM_SP() { - Register(FunctionTable); -} - -} // namespace QTM -} // namespace Service diff --git a/src/core/hle/service/qtm/qtm_sp.h b/src/core/hle/service/qtm/qtm_sp.h deleted file mode 100644 index 0ae0618fc..000000000 --- a/src/core/hle/service/qtm/qtm_sp.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace QTM { - -class QTM_SP final : public Interface { -public: - QTM_SP(); - - std::string GetPortName() const override { - return "qtm:sp"; - } -}; - -} // namespace QTM -} // namespace Service diff --git a/src/core/hle/service/qtm/qtm_u.cpp b/src/core/hle/service/qtm/qtm_u.cpp deleted file mode 100644 index a0f808432..000000000 --- a/src/core/hle/service/qtm/qtm_u.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/qtm/qtm_u.h" - -namespace Service { -namespace QTM { - -const Interface::FunctionInfo FunctionTable[] = { - // clang-format off - // qtm common commands - {0x00010080, nullptr, "GetHeadtrackingInfoRaw"}, - {0x00020080, nullptr, "GetHeadtrackingInfo"}, - // clang-format on -}; - -QTM_U::QTM_U() { - Register(FunctionTable); -} - -} // namespace QTM -} // namespace Service diff --git a/src/core/hle/service/qtm/qtm_u.h b/src/core/hle/service/qtm/qtm_u.h deleted file mode 100644 index 1ed4c0adc..000000000 --- a/src/core/hle/service/qtm/qtm_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace QTM { - -class QTM_U final : public Interface { -public: - QTM_U(); - - std::string GetPortName() const override { - return "qtm:u"; - } -}; - -} // namespace QTM -} // namespace Service diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index f267aad74..afd27d446 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -12,43 +12,17 @@ #include "core/hle/kernel/process.h" #include "core/hle/kernel/server_port.h" #include "core/hle/kernel/server_session.h" -#include "core/hle/service/ac/ac.h" -#include "core/hle/service/act/act.h" -#include "core/hle/service/am/am.h" -#include "core/hle/service/apt/apt.h" -#include "core/hle/service/boss/boss.h" -#include "core/hle/service/cam/cam.h" -#include "core/hle/service/cecd/cecd.h" +#include "core/hle/kernel/handle_table.h" #include "core/hle/service/cfg/cfg.h" -#include "core/hle/service/csnd_snd.h" -#include "core/hle/service/dlp/dlp.h" #include "core/hle/service/dsp_dsp.h" -#include "core/hle/service/err_f.h" -#include "core/hle/service/frd/frd.h" #include "core/hle/service/fs/archive.h" #include "core/hle/service/gsp_gpu.h" #include "core/hle/service/gsp_lcd.h" #include "core/hle/service/hid/hid.h" -#include "core/hle/service/http_c.h" -#include "core/hle/service/ir/ir.h" -#include "core/hle/service/ldr_ro/ldr_ro.h" -#include "core/hle/service/mic_u.h" -#include "core/hle/service/mvd/mvd.h" -#include "core/hle/service/ndm/ndm.h" -#include "core/hle/service/news/news.h" -#include "core/hle/service/nfc/nfc.h" -#include "core/hle/service/nim/nim.h" #include "core/hle/service/ns/ns.h" -#include "core/hle/service/nwm/nwm.h" -#include "core/hle/service/pm_app.h" -#include "core/hle/service/ptm/ptm.h" -#include "core/hle/service/qtm/qtm.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" #include "core/hle/service/sm/srv.h" -#include "core/hle/service/soc_u.h" -#include "core/hle/service/ssl_c.h" -#include "core/hle/service/y2r_u.h" using Kernel::ClientPort; using Kernel::ServerPort; @@ -217,63 +191,21 @@ void Init() { NS::InstallInterfaces(*SM::g_service_manager); - AddNamedPort(new ERR::ERR_F); - FS::ArchiveInit(); - AC::Init(); - ACT::Init(); - AM::Init(); - APT::Init(); - BOSS::Init(); - CAM::Init(); - CECD::Init(); CFG::Init(); - DLP::Init(); - FRD::Init(); HID::Init(); - IR::Init(); - MVD::Init(); - NDM::Init(); - NEWS::Init(); - NFC::Init(); - NIM::Init(); - NWM::Init(); - PTM::Init(); - QTM::Init(); - - AddService(new CSND::CSND_SND); + AddService(new DSP_DSP::Interface); AddService(new GSP::GSP_GPU); AddService(new GSP::GSP_LCD); - AddService(new HTTP::HTTP_C); - AddService(new LDR::LDR_RO); - AddService(new MIC::MIC_U); - AddService(new PM::PM_APP); - AddService(new SOC::SOC_U); - AddService(new SSL::SSL_C); - AddService(new Y2R::Y2R_U); LOG_DEBUG(Service, "initialized OK"); } /// Shutdown ServiceManager void Shutdown() { - PTM::Shutdown(); - NFC::Shutdown(); - NIM::Shutdown(); - NEWS::Shutdown(); - NDM::Shutdown(); - IR::Shutdown(); HID::Shutdown(); - FRD::Shutdown(); - DLP::Shutdown(); CFG::Shutdown(); - CECD::Shutdown(); - CAM::Shutdown(); - BOSS::Shutdown(); - APT::Shutdown(); - AM::Shutdown(); - AC::Shutdown(); FS::ArchiveShutdown(); SM::g_service_manager = nullptr; diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp deleted file mode 100644 index 3d215d42d..000000000 --- a/src/core/hle/service/soc_u.cpp +++ /dev/null @@ -1,919 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> -#include <cstring> -#include <unordered_map> -#include <vector> -#include "common/assert.h" -#include "common/bit_field.h" -#include "common/common_types.h" -#include "common/logging/log.h" -#include "common/scope_exit.h" -#include "core/hle/ipc.h" -#include "core/hle/kernel/server_session.h" -#include "core/hle/result.h" -#include "core/hle/service/soc_u.h" -#include "core/memory.h" - -#ifdef _WIN32 -#include <winsock2.h> -#include <ws2tcpip.h> - -// MinGW does not define several errno constants -#ifndef _MSC_VER -#define EBADMSG 104 -#define ENODATA 120 -#define ENOMSG 122 -#define ENOSR 124 -#define ENOSTR 125 -#define ETIME 137 -#define EIDRM 2001 -#define ENOLINK 2002 -#endif // _MSC_VER -#else -#include <cerrno> -#include <fcntl.h> -#include <netdb.h> -#include <netinet/in.h> -#include <poll.h> -#include <sys/socket.h> -#include <unistd.h> -#endif - -#ifdef _WIN32 -#define WSAEAGAIN WSAEWOULDBLOCK -#define WSAEMULTIHOP -1 // Invalid dummy value -#define ERRNO(x) WSA##x -#define GET_ERRNO WSAGetLastError() -#define poll(x, y, z) WSAPoll(x, y, z); -#else -#define ERRNO(x) x -#define GET_ERRNO errno -#define closesocket(x) close(x) -#endif - -namespace Service { -namespace SOC { - -const s32 SOCKET_ERROR_VALUE = -1; - -/// Holds the translation from system network errors to 3DS network errors -static const std::unordered_map<int, int> error_map = {{ - {E2BIG, 1}, - {ERRNO(EACCES), 2}, - {ERRNO(EADDRINUSE), 3}, - {ERRNO(EADDRNOTAVAIL), 4}, - {ERRNO(EAFNOSUPPORT), 5}, - {ERRNO(EAGAIN), 6}, - {ERRNO(EALREADY), 7}, - {ERRNO(EBADF), 8}, - {EBADMSG, 9}, - {EBUSY, 10}, - {ECANCELED, 11}, - {ECHILD, 12}, - {ERRNO(ECONNABORTED), 13}, - {ERRNO(ECONNREFUSED), 14}, - {ERRNO(ECONNRESET), 15}, - {EDEADLK, 16}, - {ERRNO(EDESTADDRREQ), 17}, - {EDOM, 18}, - {ERRNO(EDQUOT), 19}, - {EEXIST, 20}, - {ERRNO(EFAULT), 21}, - {EFBIG, 22}, - {ERRNO(EHOSTUNREACH), 23}, - {EIDRM, 24}, - {EILSEQ, 25}, - {ERRNO(EINPROGRESS), 26}, - {ERRNO(EINTR), 27}, - {ERRNO(EINVAL), 28}, - {EIO, 29}, - {ERRNO(EISCONN), 30}, - {EISDIR, 31}, - {ERRNO(ELOOP), 32}, - {ERRNO(EMFILE), 33}, - {EMLINK, 34}, - {ERRNO(EMSGSIZE), 35}, - {ERRNO(EMULTIHOP), 36}, - {ERRNO(ENAMETOOLONG), 37}, - {ERRNO(ENETDOWN), 38}, - {ERRNO(ENETRESET), 39}, - {ERRNO(ENETUNREACH), 40}, - {ENFILE, 41}, - {ERRNO(ENOBUFS), 42}, -#ifdef ENODATA - {ENODATA, 43}, -#endif - {ENODEV, 44}, - {ENOENT, 45}, - {ENOEXEC, 46}, - {ENOLCK, 47}, - {ENOLINK, 48}, - {ENOMEM, 49}, - {ENOMSG, 50}, - {ERRNO(ENOPROTOOPT), 51}, - {ENOSPC, 52}, -#ifdef ENOSR - {ENOSR, 53}, -#endif -#ifdef ENOSTR - {ENOSTR, 54}, -#endif - {ENOSYS, 55}, - {ERRNO(ENOTCONN), 56}, - {ENOTDIR, 57}, - {ERRNO(ENOTEMPTY), 58}, - {ERRNO(ENOTSOCK), 59}, - {ENOTSUP, 60}, - {ENOTTY, 61}, - {ENXIO, 62}, - {ERRNO(EOPNOTSUPP), 63}, - {EOVERFLOW, 64}, - {EPERM, 65}, - {EPIPE, 66}, - {EPROTO, 67}, - {ERRNO(EPROTONOSUPPORT), 68}, - {ERRNO(EPROTOTYPE), 69}, - {ERANGE, 70}, - {EROFS, 71}, - {ESPIPE, 72}, - {ESRCH, 73}, - {ERRNO(ESTALE), 74}, -#ifdef ETIME - {ETIME, 75}, -#endif - {ERRNO(ETIMEDOUT), 76}, -}}; - -/// Converts a network error from platform-specific to 3ds-specific -static int TranslateError(int error) { - auto found = error_map.find(error); - if (found != error_map.end()) - return -found->second; - - return error; -} - -/// Holds the translation from system network socket options to 3DS network socket options -/// Note: -1 = No effect/unavailable -static const std::unordered_map<int, int> sockopt_map = {{ - {0x0004, SO_REUSEADDR}, - {0x0080, -1}, - {0x0100, -1}, - {0x1001, SO_SNDBUF}, - {0x1002, SO_RCVBUF}, - {0x1003, -1}, -#ifdef _WIN32 - /// Unsupported in WinSock2 - {0x1004, -1}, -#else - {0x1004, SO_RCVLOWAT}, -#endif - {0x1008, SO_TYPE}, - {0x1009, SO_ERROR}, -}}; - -/// Converts a socket option from 3ds-specific to platform-specific -static int TranslateSockOpt(int console_opt_name) { - auto found = sockopt_map.find(console_opt_name); - if (found != sockopt_map.end()) { - return found->second; - } - return console_opt_name; -} - -/// Holds information about a particular socket -struct SocketHolder { - u32 socket_fd; ///< The socket descriptor - bool blocking; ///< Whether the socket is blocking or not, it is only read on Windows. -}; - -/// Structure to represent the 3ds' pollfd structure, which is different than most implementations -struct CTRPollFD { - u32 fd; ///< Socket handle - - union Events { - u32 hex; ///< The complete value formed by the flags - BitField<0, 1, u32> pollin; - BitField<1, 1, u32> pollpri; - BitField<2, 1, u32> pollhup; - BitField<3, 1, u32> pollerr; - BitField<4, 1, u32> pollout; - BitField<5, 1, u32> pollnval; - - Events& operator=(const Events& other) { - hex = other.hex; - return *this; - } - - /// Translates the resulting events of a Poll operation from platform-specific to 3ds - /// specific - static Events TranslateTo3DS(u32 input_event) { - Events ev = {}; - if (input_event & POLLIN) - ev.pollin.Assign(1); - if (input_event & POLLPRI) - ev.pollpri.Assign(1); - if (input_event & POLLHUP) - ev.pollhup.Assign(1); - if (input_event & POLLERR) - ev.pollerr.Assign(1); - if (input_event & POLLOUT) - ev.pollout.Assign(1); - if (input_event & POLLNVAL) - ev.pollnval.Assign(1); - return ev; - } - - /// Translates the resulting events of a Poll operation from 3ds specific to platform - /// specific - static u32 TranslateToPlatform(Events input_event) { - u32 ret = 0; - if (input_event.pollin) - ret |= POLLIN; - if (input_event.pollpri) - ret |= POLLPRI; - if (input_event.pollhup) - ret |= POLLHUP; - if (input_event.pollerr) - ret |= POLLERR; - if (input_event.pollout) - ret |= POLLOUT; - if (input_event.pollnval) - ret |= POLLNVAL; - return ret; - } - }; - Events events; ///< Events to poll for (input) - Events revents; ///< Events received (output) - - /// Converts a platform-specific pollfd to a 3ds specific structure - static CTRPollFD FromPlatform(pollfd const& fd) { - CTRPollFD result; - result.events.hex = Events::TranslateTo3DS(fd.events).hex; - result.revents.hex = Events::TranslateTo3DS(fd.revents).hex; - result.fd = static_cast<u32>(fd.fd); - return result; - } - - /// Converts a 3ds specific pollfd to a platform-specific structure - static pollfd ToPlatform(CTRPollFD const& fd) { - pollfd result; - result.events = Events::TranslateToPlatform(fd.events); - result.revents = Events::TranslateToPlatform(fd.revents); - result.fd = fd.fd; - return result; - } -}; - -/// Union to represent the 3ds' sockaddr structure -union CTRSockAddr { - /// Structure to represent a raw sockaddr - struct { - u8 len; ///< The length of the entire structure, only the set fields count - u8 sa_family; ///< The address family of the sockaddr - u8 sa_data[0x1A]; ///< The extra data, this varies, depending on the address family - } raw; - - /// Structure to represent the 3ds' sockaddr_in structure - struct CTRSockAddrIn { - u8 len; ///< The length of the entire structure - u8 sin_family; ///< The address family of the sockaddr_in - u16 sin_port; ///< The port associated with this sockaddr_in - u32 sin_addr; ///< The actual address of the sockaddr_in - } in; - - /// Convert a 3DS CTRSockAddr to a platform-specific sockaddr - static sockaddr ToPlatform(CTRSockAddr const& ctr_addr) { - sockaddr result; - result.sa_family = ctr_addr.raw.sa_family; - memset(result.sa_data, 0, sizeof(result.sa_data)); - - // We can not guarantee ABI compatibility between platforms so we copy the fields manually - switch (result.sa_family) { - case AF_INET: { - sockaddr_in* result_in = reinterpret_cast<sockaddr_in*>(&result); - result_in->sin_port = ctr_addr.in.sin_port; - result_in->sin_addr.s_addr = ctr_addr.in.sin_addr; - memset(result_in->sin_zero, 0, sizeof(result_in->sin_zero)); - break; - } - default: - ASSERT_MSG(false, "Unhandled address family (sa_family) in CTRSockAddr::ToPlatform"); - break; - } - return result; - } - - /// Convert a platform-specific sockaddr to a 3DS CTRSockAddr - static CTRSockAddr FromPlatform(sockaddr const& addr) { - CTRSockAddr result; - result.raw.sa_family = static_cast<u8>(addr.sa_family); - // We can not guarantee ABI compatibility between platforms so we copy the fields manually - switch (result.raw.sa_family) { - case AF_INET: { - sockaddr_in const* addr_in = reinterpret_cast<sockaddr_in const*>(&addr); - result.raw.len = sizeof(CTRSockAddrIn); - result.in.sin_port = addr_in->sin_port; - result.in.sin_addr = addr_in->sin_addr.s_addr; - break; - } - default: - ASSERT_MSG(false, "Unhandled address family (sa_family) in CTRSockAddr::ToPlatform"); - break; - } - return result; - } -}; - -/// Holds info about the currently open sockets -static std::unordered_map<u32, SocketHolder> open_sockets; - -/// Close all open sockets -static void CleanupSockets() { - for (auto sock : open_sockets) - closesocket(sock.second.socket_fd); - open_sockets.clear(); -} - -static void Socket(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 domain = cmd_buffer[1]; // Address family - u32 type = cmd_buffer[2]; - u32 protocol = cmd_buffer[3]; - - // Only 0 is allowed according to 3dbrew, using 0 will let the OS decide which protocol to use - if (protocol != 0) { - cmd_buffer[1] = - UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code - return; - } - - if (domain != AF_INET) { - cmd_buffer[1] = - UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code - return; - } - - if (type != SOCK_DGRAM && type != SOCK_STREAM) { - cmd_buffer[1] = - UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code - return; - } - - u32 ret = static_cast<u32>(::socket(domain, type, protocol)); - - if ((s32)ret != SOCKET_ERROR_VALUE) - open_sockets[ret] = {ret, true}; - - int result = 0; - if ((s32)ret == SOCKET_ERROR_VALUE) - ret = TranslateError(GET_ERRNO); - - cmd_buffer[0] = IPC::MakeHeader(2, 2, 0); - cmd_buffer[1] = result; - cmd_buffer[2] = ret; -} - -static void Bind(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - u32 len = cmd_buffer[2]; - - // Virtual address of the sock_addr structure - VAddr sock_addr_addr = cmd_buffer[6]; - if (!Memory::IsValidVirtualAddress(sock_addr_addr)) { - cmd_buffer[1] = -1; // TODO(Subv): Correct code - return; - } - - CTRSockAddr ctr_sock_addr; - Memory::ReadBlock(sock_addr_addr, reinterpret_cast<u8*>(&ctr_sock_addr), sizeof(CTRSockAddr)); - - sockaddr sock_addr = CTRSockAddr::ToPlatform(ctr_sock_addr); - - int ret = ::bind(socket_handle, &sock_addr, std::max<u32>(sizeof(sock_addr), len)); - - int result = 0; - if (ret != 0) - ret = TranslateError(GET_ERRNO); - - cmd_buffer[0] = IPC::MakeHeader(5, 2, 0); - cmd_buffer[1] = result; - cmd_buffer[2] = ret; -} - -static void Fcntl(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - u32 ctr_cmd = cmd_buffer[2]; - u32 ctr_arg = cmd_buffer[3]; - - int result = 0; - u32 posix_ret = 0; // TODO: Check what hardware returns for F_SETFL (unspecified by POSIX) - SCOPE_EXIT({ - cmd_buffer[1] = result; - cmd_buffer[2] = posix_ret; - }); - - if (ctr_cmd == 3) { // F_GETFL -#ifdef _WIN32 - posix_ret = 0; - auto iter = open_sockets.find(socket_handle); - if (iter != open_sockets.end() && iter->second.blocking == false) - posix_ret |= 4; // O_NONBLOCK -#else - int ret = ::fcntl(socket_handle, F_GETFL, 0); - if (ret == SOCKET_ERROR_VALUE) { - posix_ret = TranslateError(GET_ERRNO); - return; - } - posix_ret = 0; - if (ret & O_NONBLOCK) - posix_ret |= 4; // O_NONBLOCK -#endif - } else if (ctr_cmd == 4) { // F_SETFL -#ifdef _WIN32 - unsigned long tmp = (ctr_arg & 4 /* O_NONBLOCK */) ? 1 : 0; - int ret = ioctlsocket(socket_handle, FIONBIO, &tmp); - if (ret == SOCKET_ERROR_VALUE) { - posix_ret = TranslateError(GET_ERRNO); - return; - } - auto iter = open_sockets.find(socket_handle); - if (iter != open_sockets.end()) - iter->second.blocking = (tmp == 0); -#else - int flags = ::fcntl(socket_handle, F_GETFL, 0); - if (flags == SOCKET_ERROR_VALUE) { - posix_ret = TranslateError(GET_ERRNO); - return; - } - - flags &= ~O_NONBLOCK; - if (ctr_arg & 4) // O_NONBLOCK - flags |= O_NONBLOCK; - - int ret = ::fcntl(socket_handle, F_SETFL, flags); - if (ret == SOCKET_ERROR_VALUE) { - posix_ret = TranslateError(GET_ERRNO); - return; - } -#endif - } else { - LOG_ERROR(Service_SOC, "Unsupported command (%d) in fcntl call", ctr_cmd); - posix_ret = TranslateError(EINVAL); // TODO: Find the correct error - return; - } -} - -static void Listen(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - u32 backlog = cmd_buffer[2]; - - int ret = ::listen(socket_handle, backlog); - int result = 0; - if (ret != 0) - ret = TranslateError(GET_ERRNO); - - cmd_buffer[0] = IPC::MakeHeader(3, 2, 0); - cmd_buffer[1] = result; - cmd_buffer[2] = ret; -} - -static void Accept(Interface* self) { - // TODO(Subv): Calling this function on a blocking socket will block the emu thread, - // preventing graceful shutdown when closing the emulator, this can be fixed by always - // performing nonblocking operations and spinlock until the data is available - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - socklen_t max_addr_len = static_cast<socklen_t>(cmd_buffer[2]); - sockaddr addr; - socklen_t addr_len = sizeof(addr); - u32 ret = static_cast<u32>(::accept(socket_handle, &addr, &addr_len)); - - if ((s32)ret != SOCKET_ERROR_VALUE) - open_sockets[ret] = {ret, true}; - - int result = 0; - if ((s32)ret == SOCKET_ERROR_VALUE) { - ret = TranslateError(GET_ERRNO); - } else { - CTRSockAddr ctr_addr = CTRSockAddr::FromPlatform(addr); - Memory::WriteBlock(cmd_buffer[0x104 >> 2], &ctr_addr, sizeof(ctr_addr)); - } - - cmd_buffer[0] = IPC::MakeHeader(4, 2, 2); - cmd_buffer[1] = result; - cmd_buffer[2] = ret; - cmd_buffer[3] = IPC::StaticBufferDesc(static_cast<u32>(max_addr_len), 0); -} - -static void GetHostId(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - - char name[128]; - gethostname(name, sizeof(name)); - addrinfo hints = {}; - addrinfo* res; - - hints.ai_family = AF_INET; - getaddrinfo(name, nullptr, &hints, &res); - sockaddr_in* sock_addr = reinterpret_cast<sockaddr_in*>(res->ai_addr); - in_addr* addr = &sock_addr->sin_addr; - - cmd_buffer[2] = addr->s_addr; - cmd_buffer[1] = 0; - freeaddrinfo(res); -} - -static void Close(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - - int ret = 0; - open_sockets.erase(socket_handle); - - ret = closesocket(socket_handle); - - int result = 0; - if (ret != 0) - ret = TranslateError(GET_ERRNO); - - cmd_buffer[2] = ret; - cmd_buffer[1] = result; -} - -static void SendTo(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - u32 len = cmd_buffer[2]; - u32 flags = cmd_buffer[3]; - u32 addr_len = cmd_buffer[4]; - - VAddr input_buff_address = cmd_buffer[8]; - if (!Memory::IsValidVirtualAddress(input_buff_address)) { - cmd_buffer[1] = -1; // TODO(Subv): Find the right error code - return; - } - - // Memory address of the dest_addr structure - VAddr dest_addr_addr = cmd_buffer[10]; - if (!Memory::IsValidVirtualAddress(dest_addr_addr)) { - cmd_buffer[1] = -1; // TODO(Subv): Find the right error code - return; - } - - std::vector<u8> input_buff(len); - Memory::ReadBlock(input_buff_address, input_buff.data(), input_buff.size()); - - CTRSockAddr ctr_dest_addr; - Memory::ReadBlock(dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); - - int ret = -1; - if (addr_len > 0) { - sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr); - ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, - &dest_addr, sizeof(dest_addr)); - } else { - ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, - nullptr, 0); - } - - int result = 0; - if (ret == SOCKET_ERROR_VALUE) - ret = TranslateError(GET_ERRNO); - - cmd_buffer[2] = ret; - cmd_buffer[1] = result; -} - -static void RecvFrom(Interface* self) { - // TODO(Subv): Calling this function on a blocking socket will block the emu thread, - // preventing graceful shutdown when closing the emulator, this can be fixed by always - // performing nonblocking operations and spinlock until the data is available - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - u32 len = cmd_buffer[2]; - u32 flags = cmd_buffer[3]; - - struct { - u32 output_buffer_descriptor; - u32 output_buffer_addr; - u32 address_buffer_descriptor; - u32 output_src_address_buffer; - } buffer_parameters; - - std::memcpy(&buffer_parameters, &cmd_buffer[64], sizeof(buffer_parameters)); - - if (!Memory::IsValidVirtualAddress(buffer_parameters.output_buffer_addr)) { - cmd_buffer[1] = -1; // TODO(Subv): Find the right error code - return; - } - - if (!Memory::IsValidVirtualAddress(buffer_parameters.output_src_address_buffer)) { - cmd_buffer[1] = -1; // TODO(Subv): Find the right error code - return; - } - - std::vector<u8> output_buff(len); - sockaddr src_addr; - socklen_t src_addr_len = sizeof(src_addr); - int ret = ::recvfrom(socket_handle, reinterpret_cast<char*>(output_buff.data()), len, flags, - &src_addr, &src_addr_len); - - if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { - CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); - Memory::WriteBlock(buffer_parameters.output_src_address_buffer, &ctr_src_addr, - sizeof(ctr_src_addr)); - } - - int result = 0; - int total_received = ret; - if (ret == SOCKET_ERROR_VALUE) { - ret = TranslateError(GET_ERRNO); - total_received = 0; - } else { - // Write only the data we received to avoid overwriting parts of the buffer with zeros - Memory::WriteBlock(buffer_parameters.output_buffer_addr, output_buff.data(), - total_received); - } - - cmd_buffer[1] = result; - cmd_buffer[2] = ret; - cmd_buffer[3] = total_received; -} - -static void Poll(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 nfds = cmd_buffer[1]; - int timeout = cmd_buffer[2]; - - VAddr input_fds_addr = cmd_buffer[6]; - VAddr output_fds_addr = cmd_buffer[0x104 >> 2]; - if (!Memory::IsValidVirtualAddress(input_fds_addr) || - !Memory::IsValidVirtualAddress(output_fds_addr)) { - cmd_buffer[1] = -1; // TODO(Subv): Find correct error code. - return; - } - - std::vector<CTRPollFD> ctr_fds(nfds); - Memory::ReadBlock(input_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); - - // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different - // sizes) - // so we have to copy the data - std::vector<pollfd> platform_pollfd(nfds); - std::transform(ctr_fds.begin(), ctr_fds.end(), platform_pollfd.begin(), CTRPollFD::ToPlatform); - - int ret = ::poll(platform_pollfd.data(), nfds, timeout); - - // Now update the output pollfd structure - std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(), - CTRPollFD::FromPlatform); - - Memory::WriteBlock(output_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); - - int result = 0; - if (ret == SOCKET_ERROR_VALUE) - ret = TranslateError(GET_ERRNO); - - cmd_buffer[1] = result; - cmd_buffer[2] = ret; -} - -static void GetSockName(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - - // Memory address of the ctr_dest_addr structure - VAddr ctr_dest_addr_addr = cmd_buffer[0x104 >> 2]; - - sockaddr dest_addr; - socklen_t dest_addr_len = sizeof(dest_addr); - int ret = ::getsockname(socket_handle, &dest_addr, &dest_addr_len); - - if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { - CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); - Memory::WriteBlock(ctr_dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); - } else { - cmd_buffer[1] = -1; // TODO(Subv): Verify error - return; - } - - int result = 0; - if (ret != 0) - ret = TranslateError(GET_ERRNO); - - cmd_buffer[2] = ret; - cmd_buffer[1] = result; -} - -static void Shutdown(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - int how = cmd_buffer[2]; - - int ret = ::shutdown(socket_handle, how); - int result = 0; - if (ret != 0) - ret = TranslateError(GET_ERRNO); - cmd_buffer[2] = ret; - cmd_buffer[1] = result; -} - -static void GetPeerName(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - - // Memory address of the ctr_dest_addr structure - VAddr ctr_dest_addr_addr = cmd_buffer[0x104 >> 2]; - - sockaddr dest_addr; - socklen_t dest_addr_len = sizeof(dest_addr); - int ret = ::getpeername(socket_handle, &dest_addr, &dest_addr_len); - - if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { - CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); - Memory::WriteBlock(ctr_dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); - } else { - cmd_buffer[1] = -1; - return; - } - - int result = 0; - if (ret != 0) - ret = TranslateError(GET_ERRNO); - - cmd_buffer[2] = ret; - cmd_buffer[1] = result; -} - -static void Connect(Interface* self) { - // TODO(Subv): Calling this function on a blocking socket will block the emu thread, - // preventing graceful shutdown when closing the emulator, this can be fixed by always - // performing nonblocking operations and spinlock until the data is available - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - - // Memory address of the ctr_input_addr structure - VAddr ctr_input_addr_addr = cmd_buffer[6]; - if (!Memory::IsValidVirtualAddress(ctr_input_addr_addr)) { - cmd_buffer[1] = -1; // TODO(Subv): Verify error - return; - } - - CTRSockAddr ctr_input_addr; - Memory::ReadBlock(ctr_input_addr_addr, &ctr_input_addr, sizeof(ctr_input_addr)); - - sockaddr input_addr = CTRSockAddr::ToPlatform(ctr_input_addr); - int ret = ::connect(socket_handle, &input_addr, sizeof(input_addr)); - int result = 0; - if (ret != 0) - ret = TranslateError(GET_ERRNO); - - cmd_buffer[0] = IPC::MakeHeader(6, 2, 0); - cmd_buffer[1] = result; - cmd_buffer[2] = ret; -} - -static void InitializeSockets(Interface* self) { -// TODO(Subv): Implement -#ifdef _WIN32 - WSADATA data; - WSAStartup(MAKEWORD(2, 2), &data); -#endif - - u32* cmd_buffer = Kernel::GetCommandBuffer(); - cmd_buffer[0] = IPC::MakeHeader(1, 1, 0); - cmd_buffer[1] = RESULT_SUCCESS.raw; -} - -static void ShutdownSockets(Interface* self) { - // TODO(Subv): Implement - CleanupSockets(); - -#ifdef _WIN32 - WSACleanup(); -#endif - - u32* cmd_buffer = Kernel::GetCommandBuffer(); - cmd_buffer[1] = 0; -} - -static void GetSockOpt(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - u32 level = cmd_buffer[2]; - int optname = TranslateSockOpt(cmd_buffer[3]); - socklen_t optlen = (socklen_t)cmd_buffer[4]; - - int ret = 0; - int err = 0; - - if (optname < 0) { -#ifdef _WIN32 - err = WSAEINVAL; -#else - err = EINVAL; -#endif - } else { - // 0x100 = static buffer offset (bytes) - // + 0x4 = 2nd pointer (u32) position - // >> 2 = convert to u32 offset instead of byte offset (cmd_buffer = u32*) - char* optval = reinterpret_cast<char*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); - - err = ::getsockopt(socket_handle, level, optname, optval, &optlen); - if (err == SOCKET_ERROR_VALUE) { - err = TranslateError(GET_ERRNO); - } - } - - cmd_buffer[0] = IPC::MakeHeader(0x11, 4, 2); - cmd_buffer[1] = ret; - cmd_buffer[2] = err; - cmd_buffer[3] = optlen; -} - -static void SetSockOpt(Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 socket_handle = cmd_buffer[1]; - u32 level = cmd_buffer[2]; - int optname = TranslateSockOpt(cmd_buffer[3]); - - int ret = 0; - int err = 0; - - if (optname < 0) { -#ifdef _WIN32 - err = WSAEINVAL; -#else - err = EINVAL; -#endif - } else { - socklen_t optlen = static_cast<socklen_t>(cmd_buffer[4]); - const char* optval = reinterpret_cast<const char*>(Memory::GetPointer(cmd_buffer[8])); - - err = static_cast<u32>(::setsockopt(socket_handle, level, optname, optval, optlen)); - if (err == SOCKET_ERROR_VALUE) { - err = TranslateError(GET_ERRNO); - } - } - - cmd_buffer[0] = IPC::MakeHeader(0x12, 4, 4); - cmd_buffer[1] = ret; - cmd_buffer[2] = err; -} - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010044, InitializeSockets, "InitializeSockets"}, - {0x000200C2, Socket, "Socket"}, - {0x00030082, Listen, "Listen"}, - {0x00040082, Accept, "Accept"}, - {0x00050084, Bind, "Bind"}, - {0x00060084, Connect, "Connect"}, - {0x00070104, nullptr, "recvfrom_other"}, - {0x00080102, RecvFrom, "RecvFrom"}, - {0x00090106, nullptr, "sendto_other"}, - {0x000A0106, SendTo, "SendTo"}, - {0x000B0042, Close, "Close"}, - {0x000C0082, Shutdown, "Shutdown"}, - {0x000D0082, nullptr, "GetHostByName"}, - {0x000E00C2, nullptr, "GetHostByAddr"}, - {0x000F0106, nullptr, "GetAddrInfo"}, - {0x00100102, nullptr, "GetNameInfo"}, - {0x00110102, GetSockOpt, "GetSockOpt"}, - {0x00120104, SetSockOpt, "SetSockOpt"}, - {0x001300C2, Fcntl, "Fcntl"}, - {0x00140084, Poll, "Poll"}, - {0x00150042, nullptr, "SockAtMark"}, - {0x00160000, GetHostId, "GetHostId"}, - {0x00170082, GetSockName, "GetSockName"}, - {0x00180082, GetPeerName, "GetPeerName"}, - {0x00190000, ShutdownSockets, "ShutdownSockets"}, - {0x001A00C0, nullptr, "GetNetworkOpt"}, - {0x001B0040, nullptr, "ICMPSocket"}, - {0x001C0104, nullptr, "ICMPPing"}, - {0x001D0040, nullptr, "ICMPCancel"}, - {0x001E0040, nullptr, "ICMPClose"}, - {0x001F0040, nullptr, "GetResolverInfo"}, - {0x00210002, nullptr, "CloseSockets"}, - {0x00230040, nullptr, "AddGlobalSocket"}, -}; - -SOC_U::SOC_U() { - Register(FunctionTable); -} - -SOC_U::~SOC_U() { - CleanupSockets(); -#ifdef _WIN32 - WSACleanup(); -#endif -} - -} // namespace SOC -} // namespace Service diff --git a/src/core/hle/service/soc_u.h b/src/core/hle/service/soc_u.h deleted file mode 100644 index 5f829fc1c..000000000 --- a/src/core/hle/service/soc_u.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <string> -#include "core/hle/service/service.h" - -namespace Service { -namespace SOC { - -class SOC_U final : public Interface { -public: - SOC_U(); - ~SOC_U(); - - std::string GetPortName() const override { - return "soc:U"; - } -}; - -} // namespace SOC -} // namespace Service diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp deleted file mode 100644 index 300acca75..000000000 --- a/src/core/hle/service/ssl_c.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <random> -#include "common/common_types.h" -#include "core/hle/ipc.h" -#include "core/hle/service/ssl_c.h" -#include "core/memory.h" - -namespace Service { -namespace SSL { - -// TODO: Implement a proper CSPRNG in the future when actual security is needed -static std::mt19937 rand_gen; - -static void Initialize(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - // Seed random number generator when the SSL service is initialized - std::random_device rand_device; - rand_gen.seed(rand_device()); - - // Stub, return success - cmd_buff[1] = RESULT_SUCCESS.raw; -} - -static void GenerateRandomData(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 size = cmd_buff[1]; - VAddr address = cmd_buff[3]; - - // Fill the output buffer with random data. - u32 data = 0; - u32 i = 0; - while (i < size) { - if ((i % 4) == 0) { - // The random number generator returns 4 bytes worth of data, so generate new random - // data when i == 0 and when i is divisible by 4 - data = rand_gen(); - } - - if (size > 4) { - // Use up the entire 4 bytes of the random data for as long as possible - Memory::Write32(address + i, data); - i += 4; - } else if (size == 2) { - Memory::Write16(address + i, static_cast<u16>(data & 0xffff)); - i += 2; - } else { - Memory::Write8(address + i, static_cast<u8>(data & 0xff)); - i++; - } - } - - // Stub, return success - cmd_buff[1] = RESULT_SUCCESS.raw; -} - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010002, Initialize, "Initialize"}, - {0x000200C2, nullptr, "CreateContext"}, - {0x00030000, nullptr, "CreateRootCertChain"}, - {0x00040040, nullptr, "DestroyRootCertChain"}, - {0x00050082, nullptr, "AddTrustedRootCA"}, - {0x00060080, nullptr, "RootCertChainAddDefaultCert"}, - {0x00070080, nullptr, "RootCertChainRemoveCert"}, - {0x000D0084, nullptr, "OpenClientCertContext"}, - {0x000E0040, nullptr, "OpenDefaultClientCertContext"}, - {0x000F0040, nullptr, "CloseClientCertContext"}, - {0x00110042, GenerateRandomData, "GenerateRandomData"}, - {0x00120042, nullptr, "InitializeConnectionSession"}, - {0x00130040, nullptr, "StartConnection"}, - {0x00140040, nullptr, "StartConnectionGetOut"}, - {0x00150082, nullptr, "Read"}, - {0x00160082, nullptr, "ReadPeek"}, - {0x00170082, nullptr, "Write"}, - {0x00180080, nullptr, "ContextSetRootCertChain"}, - {0x00190080, nullptr, "ContextSetClientCert"}, - {0x001B0080, nullptr, "ContextClearOpt"}, - {0x001C00C4, nullptr, "ContextGetProtocolCipher"}, - {0x001E0040, nullptr, "DestroyContext"}, - {0x001F0082, nullptr, "ContextInitSharedmem"}, -}; - -SSL_C::SSL_C() { - Register(FunctionTable); -} - -} // namespace SSL_C -} // namespace Service diff --git a/src/core/hle/service/ssl_c.h b/src/core/hle/service/ssl_c.h deleted file mode 100644 index fc50a2eb2..000000000 --- a/src/core/hle/service/ssl_c.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace SSL { - -class SSL_C final : public Interface { -public: - SSL_C(); - - std::string GetPortName() const override { - return "ssl:C"; - } -}; - -} // namespace SSL -} // namespace Service diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp deleted file mode 100644 index 57172ddd6..000000000 --- a/src/core/hle/service/y2r_u.cpp +++ /dev/null @@ -1,787 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <cstring> -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/hle/ipc.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/event.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/service/y2r_u.h" -#include "core/hw/y2r.h" - -namespace Service { -namespace Y2R { - -struct ConversionParameters { - InputFormat input_format; - OutputFormat output_format; - Rotation rotation; - BlockAlignment block_alignment; - u16 input_line_width; - u16 input_lines; - StandardCoefficient standard_coefficient; - u8 padding; - u16 alpha; -}; -static_assert(sizeof(ConversionParameters) == 12, "ConversionParameters struct has incorrect size"); - -static Kernel::SharedPtr<Kernel::Event> completion_event; -static ConversionConfiguration conversion; -static DitheringWeightParams dithering_weight_params; -static u32 temporal_dithering_enabled = 0; -static u32 transfer_end_interrupt_enabled = 0; -static u32 spacial_dithering_enabled = 0; - -static const CoefficientSet standard_coefficients[4] = { - {{0x100, 0x166, 0xB6, 0x58, 0x1C5, -0x166F, 0x10EE, -0x1C5B}}, // ITU_Rec601 - {{0x100, 0x193, 0x77, 0x2F, 0x1DB, -0x1933, 0xA7C, -0x1D51}}, // ITU_Rec709 - {{0x12A, 0x198, 0xD0, 0x64, 0x204, -0x1BDE, 0x10F2, -0x229B}}, // ITU_Rec601_Scaling - {{0x12A, 0x1CA, 0x88, 0x36, 0x21C, -0x1F04, 0x99C, -0x2421}}, // ITU_Rec709_Scaling -}; - -ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) { - if (width == 0 || width > 1024 || width % 8 != 0) { - return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD - } - - // Note: The hardware uses the register value 0 to represent a width of 1024, so for a width of - // 1024 the `camera` module would set the value 0 here, but we don't need to emulate this - // internal detail. - this->input_line_width = width; - return RESULT_SUCCESS; -} - -ResultCode ConversionConfiguration::SetInputLines(u16 lines) { - if (lines == 0 || lines > 1024) { - return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD - } - - // Note: In what appears to be a bug, the `camera` module does not set the hardware register at - // all if `lines` is 1024, so the conversion uses the last value that was set. The intention - // was probably to set it to 0 like in SetInputLineWidth. - if (lines != 1024) { - this->input_lines = lines; - } - return RESULT_SUCCESS; -} - -ResultCode ConversionConfiguration::SetStandardCoefficient( - StandardCoefficient standard_coefficient) { - size_t index = static_cast<size_t>(standard_coefficient); - if (index >= ARRAY_SIZE(standard_coefficients)) { - return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::CAM, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053ED - } - - std::memcpy(coefficients.data(), standard_coefficients[index].data(), sizeof(coefficients)); - return RESULT_SUCCESS; -} - -static void SetInputFormat(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - conversion.input_format = static_cast<InputFormat>(cmd_buff[1]); - - cmd_buff[0] = IPC::MakeHeader(0x1, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called input_format=%hhu", conversion.input_format); -} - -static void GetInputFormat(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x2, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = static_cast<u32>(conversion.input_format); - - LOG_DEBUG(Service_Y2R, "called input_format=%hhu", conversion.input_format); -} - -static void SetOutputFormat(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - conversion.output_format = static_cast<OutputFormat>(cmd_buff[1]); - - cmd_buff[0] = IPC::MakeHeader(0x3, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called output_format=%hhu", conversion.output_format); -} - -static void GetOutputFormat(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x4, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = static_cast<u32>(conversion.output_format); - - LOG_DEBUG(Service_Y2R, "called output_format=%hhu", conversion.output_format); -} - -static void SetRotation(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - conversion.rotation = static_cast<Rotation>(cmd_buff[1]); - - cmd_buff[0] = IPC::MakeHeader(0x5, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called rotation=%hhu", conversion.rotation); -} - -static void GetRotation(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x6, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = static_cast<u32>(conversion.rotation); - - LOG_DEBUG(Service_Y2R, "called rotation=%hhu", conversion.rotation); -} - -static void SetBlockAlignment(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - conversion.block_alignment = static_cast<BlockAlignment>(cmd_buff[1]); - - cmd_buff[0] = IPC::MakeHeader(0x7, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called block_alignment=%hhu", conversion.block_alignment); -} - -static void GetBlockAlignment(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x8, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = static_cast<u32>(conversion.block_alignment); - - LOG_DEBUG(Service_Y2R, "called block_alignment=%hhu", conversion.block_alignment); -} - -/** - * Y2R_U::SetSpacialDithering service function - * Inputs: - * 1 : u8, 0 = Disabled, 1 = Enabled - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void SetSpacialDithering(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - spacial_dithering_enabled = cmd_buff[1] & 0xF; - - cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_Y2R, "(STUBBED) called"); -} - -/** - * Y2R_U::GetSpacialDithering service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8, 0 = Disabled, 1 = Enabled - */ -static void GetSpacialDithering(Interface* self) { - IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0xA, 2, 0); - rb.Push(RESULT_SUCCESS); - rb.Push(spacial_dithering_enabled != 0); - - LOG_WARNING(Service_Y2R, "(STUBBED) called"); -} - -/** - * Y2R_U::SetTemporalDithering service function - * Inputs: - * 1 : u8, 0 = Disabled, 1 = Enabled - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void SetTemporalDithering(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - temporal_dithering_enabled = cmd_buff[1] & 0xF; - - cmd_buff[0] = IPC::MakeHeader(0xB, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_Y2R, "(STUBBED) called"); -} - -/** - * Y2R_U::GetTemporalDithering service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8, 0 = Disabled, 1 = Enabled - */ -static void GetTemporalDithering(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0xC, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = temporal_dithering_enabled; - - LOG_WARNING(Service_Y2R, "(STUBBED) called"); -} - -/** - * Y2R_U::SetTransferEndInterrupt service function - * Inputs: - * 1 : u8, 0 = Disabled, 1 = Enabled - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void SetTransferEndInterrupt(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - transfer_end_interrupt_enabled = cmd_buff[1] & 0xf; - - cmd_buff[0] = IPC::MakeHeader(0xD, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_WARNING(Service_Y2R, "(STUBBED) called"); -} - -/** - * Y2R_U::GetTransferEndInterrupt service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8, 0 = Disabled, 1 = Enabled - */ -static void GetTransferEndInterrupt(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0xE, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = transfer_end_interrupt_enabled; - - LOG_WARNING(Service_Y2R, "(STUBBED) called"); -} - -/** - * Y2R_U::GetTransferEndEvent service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 3 : The handle of the completion event - */ -static void GetTransferEndEvent(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0xF, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).Unwrap(); - - LOG_DEBUG(Service_Y2R, "called"); -} - -static void SetSendingY(Interface* self) { - // The helper should be passed by argument to the function - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x00100102); - conversion.src_Y.address = rp.Pop<u32>(); - conversion.src_Y.image_size = rp.Pop<u32>(); - conversion.src_Y.transfer_unit = rp.Pop<u32>(); - conversion.src_Y.gap = rp.Pop<u32>(); - Kernel::Handle src_process_handle = rp.PopHandle(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " - "src_process_handle=0x%08X", - conversion.src_Y.image_size, conversion.src_Y.transfer_unit, conversion.src_Y.gap, - src_process_handle); -} - -static void SetSendingU(Interface* self) { - // The helper should be passed by argument to the function - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x00110102); - conversion.src_U.address = rp.Pop<u32>(); - conversion.src_U.image_size = rp.Pop<u32>(); - conversion.src_U.transfer_unit = rp.Pop<u32>(); - conversion.src_U.gap = rp.Pop<u32>(); - Kernel::Handle src_process_handle = rp.PopHandle(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " - "src_process_handle=0x%08X", - conversion.src_U.image_size, conversion.src_U.transfer_unit, conversion.src_U.gap, - src_process_handle); -} - -static void SetSendingV(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - conversion.src_V.address = cmd_buff[1]; - conversion.src_V.image_size = cmd_buff[2]; - conversion.src_V.transfer_unit = cmd_buff[3]; - conversion.src_V.gap = cmd_buff[4]; - - cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " - "src_process_handle=0x%08X", - conversion.src_V.image_size, conversion.src_V.transfer_unit, conversion.src_V.gap, - cmd_buff[6]); -} - -static void SetSendingYUYV(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - conversion.src_YUYV.address = cmd_buff[1]; - conversion.src_YUYV.image_size = cmd_buff[2]; - conversion.src_YUYV.transfer_unit = cmd_buff[3]; - conversion.src_YUYV.gap = cmd_buff[4]; - - cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " - "src_process_handle=0x%08X", - conversion.src_YUYV.image_size, conversion.src_YUYV.transfer_unit, - conversion.src_YUYV.gap, cmd_buff[6]); -} - -/** - * Y2R::IsFinishedSendingYuv service function - * Output: - * 1 : Result of the function, 0 on success, otherwise error code - * 2 : u8, 0 = Not Finished, 1 = Finished - */ -static void IsFinishedSendingYuv(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x14, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 1; - - LOG_WARNING(Service_Y2R, "(STUBBED) called"); -} - -/** - * Y2R::IsFinishedSendingY service function - * Output: - * 1 : Result of the function, 0 on success, otherwise error code - * 2 : u8, 0 = Not Finished, 1 = Finished - */ -static void IsFinishedSendingY(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x15, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 1; - - LOG_WARNING(Service_Y2R, "(STUBBED) called"); -} - -/** - * Y2R::IsFinishedSendingU service function - * Output: - * 1 : Result of the function, 0 on success, otherwise error code - * 2 : u8, 0 = Not Finished, 1 = Finished - */ -static void IsFinishedSendingU(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x16, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 1; - - LOG_WARNING(Service_Y2R, "(STUBBED) called"); -} - -/** - * Y2R::IsFinishedSendingV service function - * Output: - * 1 : Result of the function, 0 on success, otherwise error code - * 2 : u8, 0 = Not Finished, 1 = Finished - */ -static void IsFinishedSendingV(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x17, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 1; - - LOG_WARNING(Service_Y2R, "(STUBBED) called"); -} - -static void SetReceiving(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - conversion.dst.address = cmd_buff[1]; - conversion.dst.image_size = cmd_buff[2]; - conversion.dst.transfer_unit = cmd_buff[3]; - conversion.dst.gap = cmd_buff[4]; - - cmd_buff[0] = IPC::MakeHeader(0x18, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " - "dst_process_handle=0x%08X", - conversion.dst.image_size, conversion.dst.transfer_unit, conversion.dst.gap, - cmd_buff[6]); -} - -/** - * Y2R::IsFinishedReceiving service function - * Output: - * 1 : Result of the function, 0 on success, otherwise error code - * 2 : u8, 0 = Not Finished, 1 = Finished - */ -static void IsFinishedReceiving(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x19, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 1; - - LOG_WARNING(Service_Y2R, "(STUBBED) called"); -} - -static void SetInputLineWidth(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x1A, 1, 0); - cmd_buff[1] = conversion.SetInputLineWidth(cmd_buff[1]).raw; - - LOG_DEBUG(Service_Y2R, "called input_line_width=%u", cmd_buff[1]); -} - -static void GetInputLineWidth(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x1B, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = conversion.input_line_width; - - LOG_DEBUG(Service_Y2R, "called input_line_width=%u", conversion.input_line_width); -} - -static void SetInputLines(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x1C, 1, 0); - cmd_buff[1] = conversion.SetInputLines(cmd_buff[1]).raw; - - LOG_DEBUG(Service_Y2R, "called input_lines=%u", cmd_buff[1]); -} - -static void GetInputLines(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x1D, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = static_cast<u32>(conversion.input_lines); - - LOG_DEBUG(Service_Y2R, "called input_lines=%u", conversion.input_lines); -} - -static void SetCoefficient(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - const u16* coefficients = reinterpret_cast<const u16*>(&cmd_buff[1]); - std::memcpy(conversion.coefficients.data(), coefficients, sizeof(CoefficientSet)); - - cmd_buff[0] = IPC::MakeHeader(0x1E, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called coefficients=[%hX, %hX, %hX, %hX, %hX, %hX, %hX, %hX]", - coefficients[0], coefficients[1], coefficients[2], coefficients[3], coefficients[4], - coefficients[5], coefficients[6], coefficients[7]); -} - -static void GetCoefficient(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x1F, 5, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - std::memcpy(&cmd_buff[2], conversion.coefficients.data(), sizeof(CoefficientSet)); - - LOG_DEBUG(Service_Y2R, "called"); -} - -static void SetStandardCoefficient(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 index = cmd_buff[1]; - - cmd_buff[0] = IPC::MakeHeader(0x20, 1, 0); - cmd_buff[1] = conversion.SetStandardCoefficient((StandardCoefficient)index).raw; - - LOG_DEBUG(Service_Y2R, "called standard_coefficient=%u", index); -} - -static void GetStandardCoefficient(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - u32 index = cmd_buff[1]; - - if (index < ARRAY_SIZE(standard_coefficients)) { - cmd_buff[0] = IPC::MakeHeader(0x21, 5, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - std::memcpy(&cmd_buff[2], &standard_coefficients[index], sizeof(CoefficientSet)); - - LOG_DEBUG(Service_Y2R, "called standard_coefficient=%u ", index); - } else { - cmd_buff[0] = IPC::MakeHeader(0x21, 1, 0); - cmd_buff[1] = ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::CAM, - ErrorSummary::InvalidArgument, ErrorLevel::Usage) - .raw; - - LOG_ERROR(Service_Y2R, "called standard_coefficient=%u The argument is invalid!", index); - } -} - -static void SetAlpha(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - conversion.alpha = cmd_buff[1]; - - cmd_buff[0] = IPC::MakeHeader(0x22, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called alpha=%hu", conversion.alpha); -} - -static void GetAlpha(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x23, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = conversion.alpha; - - LOG_DEBUG(Service_Y2R, "called alpha=%hu", conversion.alpha); -} - -static void SetDitheringWeightParams(Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x24, 8, 0); // 0x240200 - rp.PopRaw(dithering_weight_params); - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_DEBUG(Service_Y2R, "called"); -} - -static void GetDitheringWeightParams(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x25, 9, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - std::memcpy(&cmd_buff[2], &dithering_weight_params, sizeof(DitheringWeightParams)); - - LOG_DEBUG(Service_Y2R, "called"); -} - -static void StartConversion(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - // dst_image_size would seem to be perfect for this, but it doesn't include the gap :( - u32 total_output_size = - conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap); - Memory::RasterizerFlushVirtualRegion(conversion.dst.address, total_output_size, - Memory::FlushMode::FlushAndInvalidate); - - HW::Y2R::PerformConversion(conversion); - - completion_event->Signal(); - - cmd_buff[0] = IPC::MakeHeader(0x26, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called"); -} - -static void StopConversion(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x27, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called"); -} - -/** - * Y2R_U::IsBusyConversion service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : 1 if there's a conversion running, otherwise 0. - */ -static void IsBusyConversion(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x28, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; // StartConversion always finishes immediately - - LOG_DEBUG(Service_Y2R, "called"); -} - -/** - * Y2R_U::SetPackageParameter service function - */ -static void SetPackageParameter(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - auto params = reinterpret_cast<const ConversionParameters*>(&cmd_buff[1]); - - conversion.input_format = params->input_format; - conversion.output_format = params->output_format; - conversion.rotation = params->rotation; - conversion.block_alignment = params->block_alignment; - - ResultCode result = conversion.SetInputLineWidth(params->input_line_width); - - if (result.IsError()) - goto cleanup; - - result = conversion.SetInputLines(params->input_lines); - - if (result.IsError()) - goto cleanup; - - result = conversion.SetStandardCoefficient(params->standard_coefficient); - - if (result.IsError()) - goto cleanup; - - conversion.padding = params->padding; - conversion.alpha = params->alpha; - -cleanup: - cmd_buff[0] = IPC::MakeHeader(0x29, 1, 0); - cmd_buff[1] = result.raw; - - LOG_DEBUG( - Service_Y2R, - "called input_format=%hhu output_format=%hhu rotation=%hhu block_alignment=%hhu " - "input_line_width=%hu input_lines=%hu standard_coefficient=%hhu reserved=%hhu alpha=%hX", - params->input_format, params->output_format, params->rotation, params->block_alignment, - params->input_line_width, params->input_lines, params->standard_coefficient, - params->padding, params->alpha); -} - -static void PingProcess(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x2A, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; - - LOG_WARNING(Service_Y2R, "(STUBBED) called"); -} - -static void DriverInitialize(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - conversion.input_format = InputFormat::YUV422_Indiv8; - conversion.output_format = OutputFormat::RGBA8; - conversion.rotation = Rotation::None; - conversion.block_alignment = BlockAlignment::Linear; - conversion.coefficients.fill(0); - conversion.SetInputLineWidth(1024); - conversion.SetInputLines(1024); - conversion.alpha = 0; - - ConversionBuffer zero_buffer = {}; - conversion.src_Y = zero_buffer; - conversion.src_U = zero_buffer; - conversion.src_V = zero_buffer; - conversion.dst = zero_buffer; - - completion_event->Clear(); - - cmd_buff[0] = IPC::MakeHeader(0x2B, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called"); -} - -static void DriverFinalize(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x2C, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_Y2R, "called"); -} - -static void GetPackageParameter(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x2D, 4, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - std::memcpy(&cmd_buff[2], &conversion, sizeof(ConversionParameters)); - - LOG_DEBUG(Service_Y2R, "called"); -} - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, SetInputFormat, "SetInputFormat"}, - {0x00020000, GetInputFormat, "GetInputFormat"}, - {0x00030040, SetOutputFormat, "SetOutputFormat"}, - {0x00040000, GetOutputFormat, "GetOutputFormat"}, - {0x00050040, SetRotation, "SetRotation"}, - {0x00060000, GetRotation, "GetRotation"}, - {0x00070040, SetBlockAlignment, "SetBlockAlignment"}, - {0x00080000, GetBlockAlignment, "GetBlockAlignment"}, - {0x00090040, SetSpacialDithering, "SetSpacialDithering"}, - {0x000A0000, GetSpacialDithering, "GetSpacialDithering"}, - {0x000B0040, SetTemporalDithering, "SetTemporalDithering"}, - {0x000C0000, GetTemporalDithering, "GetTemporalDithering"}, - {0x000D0040, SetTransferEndInterrupt, "SetTransferEndInterrupt"}, - {0x000E0000, GetTransferEndInterrupt, "GetTransferEndInterrupt"}, - {0x000F0000, GetTransferEndEvent, "GetTransferEndEvent"}, - {0x00100102, SetSendingY, "SetSendingY"}, - {0x00110102, SetSendingU, "SetSendingU"}, - {0x00120102, SetSendingV, "SetSendingV"}, - {0x00130102, SetSendingYUYV, "SetSendingYUYV"}, - {0x00140000, IsFinishedSendingYuv, "IsFinishedSendingYuv"}, - {0x00150000, IsFinishedSendingY, "IsFinishedSendingY"}, - {0x00160000, IsFinishedSendingU, "IsFinishedSendingU"}, - {0x00170000, IsFinishedSendingV, "IsFinishedSendingV"}, - {0x00180102, SetReceiving, "SetReceiving"}, - {0x00190000, IsFinishedReceiving, "IsFinishedReceiving"}, - {0x001A0040, SetInputLineWidth, "SetInputLineWidth"}, - {0x001B0000, GetInputLineWidth, "GetInputLineWidth"}, - {0x001C0040, SetInputLines, "SetInputLines"}, - {0x001D0000, GetInputLines, "GetInputLines"}, - {0x001E0100, SetCoefficient, "SetCoefficient"}, - {0x001F0000, GetCoefficient, "GetCoefficient"}, - {0x00200040, SetStandardCoefficient, "SetStandardCoefficient"}, - {0x00210040, GetStandardCoefficient, "GetStandardCoefficient"}, - {0x00220040, SetAlpha, "SetAlpha"}, - {0x00230000, GetAlpha, "GetAlpha"}, - {0x00240200, SetDitheringWeightParams, "SetDitheringWeightParams"}, - {0x00250000, GetDitheringWeightParams, "GetDitheringWeightParams"}, - {0x00260000, StartConversion, "StartConversion"}, - {0x00270000, StopConversion, "StopConversion"}, - {0x00280000, IsBusyConversion, "IsBusyConversion"}, - {0x002901C0, SetPackageParameter, "SetPackageParameter"}, - {0x002A0000, PingProcess, "PingProcess"}, - {0x002B0000, DriverInitialize, "DriverInitialize"}, - {0x002C0000, DriverFinalize, "DriverFinalize"}, - {0x002D0000, GetPackageParameter, "GetPackageParameter"}, -}; - -Y2R_U::Y2R_U() { - completion_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "Y2R:Completed"); - std::memset(&conversion, 0, sizeof(conversion)); - - Register(FunctionTable); -} - -Y2R_U::~Y2R_U() { - completion_event = nullptr; -} - -} // namespace Y2R -} // namespace Service
\ No newline at end of file diff --git a/src/core/hle/service/y2r_u.h b/src/core/hle/service/y2r_u.h deleted file mode 100644 index dddeed0be..000000000 --- a/src/core/hle/service/y2r_u.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <array> -#include <string> -#include "common/common_types.h" -#include "core/hle/result.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace Y2R { - -enum class InputFormat : u8 { - /// 8-bit input, with YUV components in separate planes and 4:2:2 subsampling. - YUV422_Indiv8 = 0, - /// 8-bit input, with YUV components in separate planes and 4:2:0 subsampling. - YUV420_Indiv8 = 1, - - /// 16-bit input (only LSB used), with YUV components in separate planes and 4:2:2 subsampling. - YUV422_Indiv16 = 2, - /// 16-bit input (only LSB used), with YUV components in separate planes and 4:2:0 subsampling. - YUV420_Indiv16 = 3, - - /// 8-bit input, with a single interleaved stream in YUYV format and 4:2:2 subsampling. - YUYV422_Interleaved = 4, -}; - -enum class OutputFormat : u8 { - RGBA8 = 0, - RGB8 = 1, - RGB5A1 = 2, - RGB565 = 3, -}; - -enum class Rotation : u8 { - None = 0, - Clockwise_90 = 1, - Clockwise_180 = 2, - Clockwise_270 = 3, -}; - -enum class BlockAlignment : u8 { - /// Image is output in linear format suitable for use as a framebuffer. - Linear = 0, - /// Image is output in tiled PICA format, suitable for use as a texture. - Block8x8 = 1, -}; - -enum class StandardCoefficient : u8 { - /// ITU Rec. BT.601 primaries, with PC ranges. - ITU_Rec601 = 0, - /// ITU Rec. BT.709 primaries, with PC ranges. - ITU_Rec709 = 1, - /// ITU Rec. BT.601 primaries, with TV ranges. - ITU_Rec601_Scaling = 2, - /// ITU Rec. BT.709 primaries, with TV ranges. - ITU_Rec709_Scaling = 3, -}; - -/** - * A set of coefficients configuring the RGB to YUV conversion. Coefficients 0-4 are unsigned 2.8 - * fixed pointer numbers representing entries on the conversion matrix, while coefficient 5-7 are - * signed 11.5 fixed point numbers added as offsets to the RGB result. - * - * The overall conversion process formula is: - * ``` - * R = trunc((c_0 * Y + c_1 * V) + c_5 + 0.75) - * G = trunc((c_0 * Y - c_3 * U - c_2 * V) + c_6 + 0.75) - * B = trunc((c_0 * Y + c_4 * U ) + c_7 + 0.75) - * ``` - */ -using CoefficientSet = std::array<s16, 8>; - -struct ConversionBuffer { - /// Current reading/writing address of this buffer. - VAddr address; - /// Remaining amount of bytes to be DMAed, does not include the inter-trasfer gap. - u32 image_size; - /// Size of a single DMA transfer. - u16 transfer_unit; - /// Amount of bytes to be skipped between copying each `transfer_unit` bytes. - u16 gap; -}; - -struct ConversionConfiguration { - InputFormat input_format; - OutputFormat output_format; - Rotation rotation; - BlockAlignment block_alignment; - u16 input_line_width; - u16 input_lines; - CoefficientSet coefficients; - u8 padding; - u16 alpha; - - /// Input parameters for the Y (luma) plane - ConversionBuffer src_Y, src_U, src_V, src_YUYV; - /// Output parameters for the conversion results - ConversionBuffer dst; - - ResultCode SetInputLineWidth(u16 width); - ResultCode SetInputLines(u16 lines); - ResultCode SetStandardCoefficient(StandardCoefficient standard_coefficient); -}; - -struct DitheringWeightParams { - u16 w0_xEven_yEven; - u16 w0_xOdd_yEven; - u16 w0_xEven_yOdd; - u16 w0_xOdd_yOdd; - u16 w1_xEven_yEven; - u16 w1_xOdd_yEven; - u16 w1_xEven_yOdd; - u16 w1_xOdd_yOdd; - u16 w2_xEven_yEven; - u16 w2_xOdd_yEven; - u16 w2_xEven_yOdd; - u16 w2_xOdd_yOdd; - u16 w3_xEven_yEven; - u16 w3_xOdd_yEven; - u16 w3_xEven_yOdd; - u16 w3_xOdd_yOdd; -}; - -class Y2R_U final : public Interface { -public: - Y2R_U(); - ~Y2R_U() override; - - std::string GetPortName() const override { - return "y2r:u"; - } -}; - -} // namespace Y2R -} // namespace Service diff --git a/src/core/hle/shared_page.cpp b/src/core/hle/shared_page.cpp index 5978ccdd4..833dc5ec9 100644 --- a/src/core/hle/shared_page.cpp +++ b/src/core/hle/shared_page.cpp @@ -6,7 +6,6 @@ #include <cstring> #include <ctime> #include "core/core_timing.h" -#include "core/hle/service/ptm/ptm.h" #include "core/hle/shared_page.h" //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -75,8 +74,6 @@ void Init() { shared_page.unknown_value = 0x1; // Set to a completely full battery - shared_page.battery_state.charge_level.Assign( - static_cast<u8>(Service::PTM::ChargeLevels::CompletelyFull)); shared_page.battery_state.is_adapter_connected.Assign(1); shared_page.battery_state.is_charging.Assign(1); diff --git a/src/core/hw/y2r.cpp b/src/core/hw/y2r.cpp deleted file mode 100644 index e697f84b3..000000000 --- a/src/core/hw/y2r.cpp +++ /dev/null @@ -1,382 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> -#include <array> -#include <cstddef> -#include <memory> -#include "common/assert.h" -#include "common/color.h" -#include "common/common_types.h" -#include "common/math_util.h" -#include "common/vector_math.h" -#include "core/hle/service/y2r_u.h" -#include "core/hw/y2r.h" -#include "core/memory.h" - -namespace HW { -namespace Y2R { - -using namespace Service::Y2R; - -static const size_t MAX_TILES = 1024 / 8; -static const size_t TILE_SIZE = 8 * 8; -using ImageTile = std::array<u32, TILE_SIZE>; - -/// Converts a image strip from the source YUV format into individual 8x8 RGB32 tiles. -static void ConvertYUVToRGB(InputFormat input_format, const u8* input_Y, const u8* input_U, - const u8* input_V, ImageTile output[], unsigned int width, - unsigned int height, const CoefficientSet& coefficients) { - - for (unsigned int y = 0; y < height; ++y) { - for (unsigned int x = 0; x < width; ++x) { - s32 Y = 0; - s32 U = 0; - s32 V = 0; - switch (input_format) { - case InputFormat::YUV422_Indiv8: - case InputFormat::YUV422_Indiv16: - Y = input_Y[y * width + x]; - U = input_U[(y * width + x) / 2]; - V = input_V[(y * width + x) / 2]; - break; - case InputFormat::YUV420_Indiv8: - case InputFormat::YUV420_Indiv16: - Y = input_Y[y * width + x]; - U = input_U[((y / 2) * width + x) / 2]; - V = input_V[((y / 2) * width + x) / 2]; - break; - case InputFormat::YUYV422_Interleaved: - Y = input_Y[(y * width + x) * 2]; - U = input_Y[(y * width + (x / 2) * 2) * 2 + 1]; - V = input_Y[(y * width + (x / 2) * 2) * 2 + 3]; - break; - } - - // This conversion process is bit-exact with hardware, as far as could be tested. - auto& c = coefficients; - s32 cY = c[0] * Y; - - s32 r = cY + c[1] * V; - s32 g = cY - c[2] * V - c[3] * U; - s32 b = cY + c[4] * U; - - const s32 rounding_offset = 0x18; - r = (r >> 3) + c[5] + rounding_offset; - g = (g >> 3) + c[6] + rounding_offset; - b = (b >> 3) + c[7] + rounding_offset; - - unsigned int tile = x / 8; - unsigned int tile_x = x % 8; - u32* out = &output[tile][y * 8 + tile_x]; - - using MathUtil::Clamp; - *out = ((u32)Clamp(r >> 5, 0, 0xFF) << 24) | ((u32)Clamp(g >> 5, 0, 0xFF) << 16) | - ((u32)Clamp(b >> 5, 0, 0xFF) << 8); - } - } -} - -/// Simulates an incoming CDMA transfer. The N parameter is used to automatically convert 16-bit -/// formats to 8-bit. -template <size_t N> -static void ReceiveData(u8* output, ConversionBuffer& buf, size_t amount_of_data) { - const u8* input = Memory::GetPointer(buf.address); - - size_t output_unit = buf.transfer_unit / N; - ASSERT(amount_of_data % output_unit == 0); - - while (amount_of_data > 0) { - for (size_t i = 0; i < output_unit; ++i) { - output[i] = input[i * N]; - } - - output += output_unit; - input += buf.transfer_unit + buf.gap; - - buf.address += buf.transfer_unit + buf.gap; - buf.image_size -= buf.transfer_unit; - amount_of_data -= output_unit; - } -} - -/// Convert intermediate RGB32 format to the final output format while simulating an outgoing CDMA -/// transfer. -static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data, - OutputFormat output_format, u8 alpha) { - - u8* output = Memory::GetPointer(buf.address); - - while (amount_of_data > 0) { - u8* unit_end = output + buf.transfer_unit; - while (output < unit_end) { - u32 color = *input++; - Math::Vec4<u8> col_vec{(u8)(color >> 24), (u8)(color >> 16), (u8)(color >> 8), alpha}; - - switch (output_format) { - case OutputFormat::RGBA8: - Color::EncodeRGBA8(col_vec, output); - output += 4; - break; - case OutputFormat::RGB8: - Color::EncodeRGB8(col_vec, output); - output += 3; - break; - case OutputFormat::RGB5A1: - Color::EncodeRGB5A1(col_vec, output); - output += 2; - break; - case OutputFormat::RGB565: - Color::EncodeRGB565(col_vec, output); - output += 2; - break; - } - - amount_of_data -= 1; - } - - output += buf.gap; - buf.address += buf.transfer_unit + buf.gap; - buf.image_size -= buf.transfer_unit; - } -} - -static const u8 linear_lut[TILE_SIZE] = { - // clang-format off - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, - // clang-format on -}; - -static const u8 morton_lut[TILE_SIZE] = { - // clang-format off - 0, 1, 4, 5, 16, 17, 20, 21, - 2, 3, 6, 7, 18, 19, 22, 23, - 8, 9, 12, 13, 24, 25, 28, 29, - 10, 11, 14, 15, 26, 27, 30, 31, - 32, 33, 36, 37, 48, 49, 52, 53, - 34, 35, 38, 39, 50, 51, 54, 55, - 40, 41, 44, 45, 56, 57, 60, 61, - 42, 43, 46, 47, 58, 59, 62, 63, - // clang-format on -}; - -static void RotateTile0(const ImageTile& input, ImageTile& output, int height, - const u8 out_map[64]) { - for (int i = 0; i < height * 8; ++i) { - output[out_map[i]] = input[i]; - } -} - -static void RotateTile90(const ImageTile& input, ImageTile& output, int height, - const u8 out_map[64]) { - int out_i = 0; - for (int x = 0; x < 8; ++x) { - for (int y = height - 1; y >= 0; --y) { - output[out_map[out_i++]] = input[y * 8 + x]; - } - } -} - -static void RotateTile180(const ImageTile& input, ImageTile& output, int height, - const u8 out_map[64]) { - int out_i = 0; - for (int i = height * 8 - 1; i >= 0; --i) { - output[out_map[out_i++]] = input[i]; - } -} - -static void RotateTile270(const ImageTile& input, ImageTile& output, int height, - const u8 out_map[64]) { - int out_i = 0; - for (int x = 8 - 1; x >= 0; --x) { - for (int y = 0; y < height; ++y) { - output[out_map[out_i++]] = input[y * 8 + x]; - } - } -} - -static void WriteTileToOutput(u32* output, const ImageTile& tile, int height, int line_stride) { - for (int y = 0; y < height; ++y) { - for (int x = 0; x < 8; ++x) { - output[y * line_stride + x] = tile[y * 8 + x]; - } - } -} - -/** - * Performs a Y2R colorspace conversion. - * - * The Y2R hardware implements hardware-accelerated YUV to RGB colorspace conversions. It is most - * commonly used for video playback or to display camera input to the screen. - * - * The conversion process is quite configurable, and can be divided in distinct steps. From - * observation, it appears that the hardware buffers a single 8-pixel tall strip of image data - * internally and converts it in one go before writing to the output and loading the next strip. - * - * The steps taken to convert one strip of image data are: - * - * - The hardware receives data via CDMA (http://3dbrew.org/wiki/Corelink_DMA_Engines), which is - * presumably stored in one or more internal buffers. This process can be done in several separate - * transfers, as long as they don't exceed the size of the internal image buffer. This allows - * flexibility in input strides. - * - The input data is decoded into a YUV tuple. Several formats are suported, see the `InputFormat` - * enum. - * - The YUV tuple is converted, using fixed point calculations, to RGB. This step can be configured - * using a set of coefficients to support different colorspace standards. See `CoefficientSet`. - * - The strip can be optionally rotated 90, 180 or 270 degrees. Since each strip is processed - * independently, this notably rotates each *strip*, not the entire image. This means that for 90 - * or 270 degree rotations, the output will be in terms of several 8 x height images, and for any - * non-zero rotation the strips will have to be re-arranged so that the parts of the image will - * not be shuffled together. This limitation makes this a feature of somewhat dubious utility. 90 - * or 270 degree rotations in images with non-even height don't seem to work properly. - * - The data is converted to the output RGB format. See the `OutputFormat` enum. - * - The data can be output either linearly line-by-line or in the swizzled 8x8 tile format used by - * the PICA. This is decided by the `BlockAlignment` enum. If 8x8 alignment is used, then the - * image must have a height divisible by 8. The image width must always be divisible by 8. - * - The final data is then CDMAed out to main memory and the next image strip is processed. This - * offers the same flexibility as the input stage. - * - * In this implementation, to avoid the combinatorial explosion of parameter combinations, common - * intermediate formats are used and where possible tables or parameters are used instead of - * diverging code paths to keep the amount of branches in check. Some steps are also merged to - * increase efficiency. - * - * Output for all valid settings combinations matches hardware, however output in some edge-cases - * differs: - * - * - `Block8x8` alignment with non-mod8 height produces different garbage patterns on the last - * strip, especially when combined with rotation. - * - Hardware, when using `Linear` alignment with a non-even height and 90 or 270 degree rotation - * produces misaligned output on the last strip. This implmentation produces output with the - * correct "expected" alignment. - * - * Hardware behaves strangely (doesn't fire the completion interrupt, for example) in these cases, - * so they are believed to be invalid configurations anyway. - */ -void PerformConversion(ConversionConfiguration& cvt) { - ASSERT(cvt.input_line_width % 8 == 0); - ASSERT(cvt.block_alignment != BlockAlignment::Block8x8 || cvt.input_lines % 8 == 0); - // Tiles per row - size_t num_tiles = cvt.input_line_width / 8; - ASSERT(num_tiles <= MAX_TILES); - - // Buffer used as a CDMA source/target. - std::unique_ptr<u8[]> data_buffer(new u8[cvt.input_line_width * 8 * 4]); - // Intermediate storage for decoded 8x8 image tiles. Always stored as RGB32. - std::unique_ptr<ImageTile[]> tiles(new ImageTile[num_tiles]); - ImageTile tmp_tile; - - // LUT used to remap writes to a tile. Used to allow linear or swizzled output without - // requiring two different code paths. - const u8* tile_remap = nullptr; - switch (cvt.block_alignment) { - case BlockAlignment::Linear: - tile_remap = linear_lut; - break; - case BlockAlignment::Block8x8: - tile_remap = morton_lut; - break; - } - - for (unsigned int y = 0; y < cvt.input_lines; y += 8) { - unsigned int row_height = std::min(cvt.input_lines - y, 8u); - - // Total size in pixels of incoming data required for this strip. - const size_t row_data_size = row_height * cvt.input_line_width; - - u8* input_Y = data_buffer.get(); - u8* input_U = input_Y + 8 * cvt.input_line_width; - u8* input_V = input_U + 8 * cvt.input_line_width / 2; - - switch (cvt.input_format) { - case InputFormat::YUV422_Indiv8: - ReceiveData<1>(input_Y, cvt.src_Y, row_data_size); - ReceiveData<1>(input_U, cvt.src_U, row_data_size / 2); - ReceiveData<1>(input_V, cvt.src_V, row_data_size / 2); - break; - case InputFormat::YUV420_Indiv8: - ReceiveData<1>(input_Y, cvt.src_Y, row_data_size); - ReceiveData<1>(input_U, cvt.src_U, row_data_size / 4); - ReceiveData<1>(input_V, cvt.src_V, row_data_size / 4); - break; - case InputFormat::YUV422_Indiv16: - ReceiveData<2>(input_Y, cvt.src_Y, row_data_size); - ReceiveData<2>(input_U, cvt.src_U, row_data_size / 2); - ReceiveData<2>(input_V, cvt.src_V, row_data_size / 2); - break; - case InputFormat::YUV420_Indiv16: - ReceiveData<2>(input_Y, cvt.src_Y, row_data_size); - ReceiveData<2>(input_U, cvt.src_U, row_data_size / 4); - ReceiveData<2>(input_V, cvt.src_V, row_data_size / 4); - break; - case InputFormat::YUYV422_Interleaved: - input_U = nullptr; - input_V = nullptr; - ReceiveData<1>(input_Y, cvt.src_YUYV, row_data_size * 2); - break; - } - - // Note(yuriks): If additional optimization is required, input_format can be moved to a - // template parameter, so that its dispatch can be moved to outside the inner loop. - ConvertYUVToRGB(cvt.input_format, input_Y, input_U, input_V, tiles.get(), - cvt.input_line_width, row_height, cvt.coefficients); - - u32* output_buffer = reinterpret_cast<u32*>(data_buffer.get()); - - for (size_t i = 0; i < num_tiles; ++i) { - int image_strip_width = 0; - int output_stride = 0; - - switch (cvt.rotation) { - case Rotation::None: - RotateTile0(tiles[i], tmp_tile, row_height, tile_remap); - image_strip_width = cvt.input_line_width; - output_stride = 8; - break; - case Rotation::Clockwise_90: - RotateTile90(tiles[i], tmp_tile, row_height, tile_remap); - image_strip_width = 8; - output_stride = 8 * row_height; - break; - case Rotation::Clockwise_180: - // For 180 and 270 degree rotations we also invert the order of tiles in the strip, - // since the rotates are done individually on each tile. - RotateTile180(tiles[num_tiles - i - 1], tmp_tile, row_height, tile_remap); - image_strip_width = cvt.input_line_width; - output_stride = 8; - break; - case Rotation::Clockwise_270: - RotateTile270(tiles[num_tiles - i - 1], tmp_tile, row_height, tile_remap); - image_strip_width = 8; - output_stride = 8 * row_height; - break; - } - - switch (cvt.block_alignment) { - case BlockAlignment::Linear: - WriteTileToOutput(output_buffer, tmp_tile, row_height, image_strip_width); - output_buffer += output_stride; - break; - case BlockAlignment::Block8x8: - WriteTileToOutput(output_buffer, tmp_tile, 8, 8); - output_buffer += TILE_SIZE; - break; - } - } - - // Note(yuriks): If additional optimization is required, output_format can be moved to a - // template parameter, so that its dispatch can be moved to outside the inner loop. - SendData(reinterpret_cast<u32*>(data_buffer.get()), cvt.dst, (int)row_data_size, - cvt.output_format, (u8)cvt.alpha); - } -} -} -} diff --git a/src/core/hw/y2r.h b/src/core/hw/y2r.h deleted file mode 100644 index 25fcd781c..000000000 --- a/src/core/hw/y2r.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service { -namespace Y2R { -struct ConversionConfiguration; -} -} - -namespace HW { -namespace Y2R { -void PerformConversion(Service::Y2R::ConversionConfiguration& cvt); -} -} diff --git a/src/core/settings.cpp b/src/core/settings.cpp index efcf1267d..012f7e6c3 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -5,7 +5,6 @@ #include "audio_core/audio_core.h" #include "core/gdbstub/gdbstub.h" #include "core/hle/service/hid/hid.h" -#include "core/hle/service/ir/ir.h" #include "core/settings.h" #include "video_core/video_core.h" @@ -33,7 +32,6 @@ void Apply() { AudioCore::EnableStretching(values.enable_audio_stretching); Service::HID::ReloadInputDevices(); - Service::IR::ReloadInputDevices(); } } // namespace Settings diff --git a/src/core/settings.h b/src/core/settings.h index 8d78cb424..912b2c885 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -7,7 +7,6 @@ #include <array> #include <string> #include "common/common_types.h" -#include "core/hle/service/cam/cam.h" namespace Settings { @@ -122,10 +121,6 @@ struct Values { bool enable_audio_stretching; std::string audio_device_id; - // Camera - std::array<std::string, Service::CAM::NumCameras> camera_name; - std::array<std::string, Service::CAM::NumCameras> camera_config; - // Debugging bool use_gdbstub; u16 gdbstub_port; |