mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	hle: Remove a large amount of 3ds-specific service code.
This commit is contained in:
		@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user