mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-24 04:33:44 +00:00
Merge branch 'aoc-add-new-functions-services' into 'master'
feat(service/aoc): Implement IContentsServiceManager See merge request citron/rewrite!23
This commit is contained in:
@@ -505,6 +505,8 @@ add_library(core STATIC
|
||||
hle/service/am/window_system.h
|
||||
hle/service/aoc/addon_content_manager.cpp
|
||||
hle/service/aoc/addon_content_manager.h
|
||||
hle/service/aoc/contents_service_manager.cpp
|
||||
hle/service/aoc/contents_service_manager.h
|
||||
hle/service/aoc/purchase_event_manager.cpp
|
||||
hle/service/aoc/purchase_event_manager.h
|
||||
hle/service/apm/apm.cpp
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
@@ -16,6 +17,7 @@
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/service/aoc/addon_content_manager.h"
|
||||
#include "core/hle/service/aoc/contents_service_manager.h"
|
||||
#include "core/hle/service/aoc/purchase_event_manager.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
@@ -68,7 +70,7 @@ IAddOnContentManager::IAddOnContentManager(Core::System& system_)
|
||||
{50, D<&IAddOnContentManager::CheckAddOnContentMountStatus>, "CheckAddOnContentMountStatus"},
|
||||
{100, D<&IAddOnContentManager::CreateEcPurchasedEventManager>, "CreateEcPurchasedEventManager"},
|
||||
{101, D<&IAddOnContentManager::CreatePermanentEcPurchasedEventManager>, "CreatePermanentEcPurchasedEventManager"},
|
||||
{110, nullptr, "CreateContentsServiceManager"},
|
||||
{110, D<&IAddOnContentManager::CreateContentsServiceManager>, "CreateContentsServiceManager"},
|
||||
{200, nullptr, "SetRequiredAddOnContentsOnContentsAvailabilityTransition"},
|
||||
{300, nullptr, "SetupHostAddOnContent"},
|
||||
{301, nullptr, "GetRegisteredAddOnContentPath"},
|
||||
@@ -214,6 +216,15 @@ Result IAddOnContentManager::CreatePermanentEcPurchasedEventManager(
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAddOnContentManager::CreateContentsServiceManager(
|
||||
OutInterface<IContentsServiceManager> out_interface) {
|
||||
LOG_WARNING(Service_AOC, "(STUBBED) called");
|
||||
|
||||
*out_interface = std::make_shared<IContentsServiceManager>(system);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void LoopProcess(Core::System& system) {
|
||||
auto server_manager = std::make_unique<ServerManager>(system);
|
||||
server_manager->RegisterNamedService("aoc:u", std::make_shared<IAddOnContentManager>(system));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
@@ -18,6 +19,7 @@ class KEvent;
|
||||
namespace Service::AOC {
|
||||
|
||||
class IPurchaseEventManager;
|
||||
class IContentsServiceManager;
|
||||
|
||||
class IAddOnContentManager final : public ServiceFramework<IAddOnContentManager> {
|
||||
public:
|
||||
@@ -38,6 +40,7 @@ public:
|
||||
Result CreateEcPurchasedEventManager(OutInterface<IPurchaseEventManager> out_interface);
|
||||
Result CreatePermanentEcPurchasedEventManager(
|
||||
OutInterface<IPurchaseEventManager> out_interface);
|
||||
Result CreateContentsServiceManager(OutInterface<IContentsServiceManager> out_interface);
|
||||
|
||||
private:
|
||||
std::vector<u64> add_on_content;
|
||||
|
||||
103
src/core/hle/service/aoc/contents_service_manager.cpp
Normal file
103
src/core/hle/service/aoc/contents_service_manager.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/aoc/contents_service_manager.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
namespace Service::AOC {
|
||||
|
||||
IContentsServiceManager::IContentsServiceManager(Core::System& system_)
|
||||
: ServiceFramework{system_, "IContentsServiceManager"},
|
||||
service_context{system_, "IContentsServiceManager"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IContentsServiceManager::RequestContentsAuthorizationToken>, "RequestContentsAuthorizationToken"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IContentsServiceManager::~IContentsServiceManager() = default;
|
||||
|
||||
Result IContentsServiceManager::RequestContentsAuthorizationToken(OutInterface<IAsyncData> out_async_data,
|
||||
u64 unknown,
|
||||
InBuffer<BufferAttr_HipcMapAlias> in_buffer) {
|
||||
LOG_WARNING(Service_AOC, "(STUBBED) called with unknown={:016X}, buffer_size={}", unknown, in_buffer.size());
|
||||
|
||||
// Create a new IAsyncData interface to handle the authorization token request
|
||||
*out_async_data = std::make_shared<IAsyncData>(system);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
IAsyncData::IAsyncData(Core::System& system_)
|
||||
: ServiceFramework{system_, "IAsyncData"},
|
||||
service_context{system_, "IAsyncData"},
|
||||
is_complete{false} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IAsyncData::GetSize>, "GetSize"},
|
||||
{1, D<&IAsyncData::Read>, "Read"},
|
||||
{2, D<&IAsyncData::Cancel>, "Cancel"},
|
||||
{3, D<&IAsyncData::GetSystemEvent>, "GetSystemEvent"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
async_event = service_context.CreateEvent("IAsyncData:AsyncEvent");
|
||||
|
||||
// Simulate completion immediately for stub
|
||||
data_buffer.resize(0x100, 0);
|
||||
is_complete = true;
|
||||
async_event->Signal();
|
||||
}
|
||||
|
||||
IAsyncData::~IAsyncData() {
|
||||
service_context.CloseEvent(async_event);
|
||||
}
|
||||
|
||||
Result IAsyncData::GetSize(Out<u64> out_size) {
|
||||
LOG_DEBUG(Service_AOC, "called");
|
||||
|
||||
*out_size = data_buffer.size();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAsyncData::Read(OutBuffer<BufferAttr_HipcMapAlias> out_buffer, u64 offset, u64 size) {
|
||||
LOG_DEBUG(Service_AOC, "called with offset={:016X}, size={:016X}", offset, size);
|
||||
|
||||
if (offset >= data_buffer.size()) {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
const u64 read_size = std::min(size, static_cast<u64>(data_buffer.size() - offset));
|
||||
const u64 copy_size = std::min(read_size, out_buffer.size());
|
||||
|
||||
std::memcpy(out_buffer.data(), data_buffer.data() + offset, copy_size);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAsyncData::Cancel() {
|
||||
LOG_WARNING(Service_AOC, "(STUBBED) called");
|
||||
|
||||
is_complete = false;
|
||||
async_event->Clear();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAsyncData::GetSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_AOC, "called");
|
||||
|
||||
*out_event = &async_event->GetReadableEvent();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::AOC
|
||||
53
src/core/hle/service/aoc/contents_service_manager.h
Normal file
53
src/core/hle/service/aoc/contents_service_manager.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Kernel {
|
||||
class KEvent;
|
||||
class KReadableEvent;
|
||||
}
|
||||
|
||||
namespace Service::AOC {
|
||||
|
||||
class IAsyncData;
|
||||
|
||||
class IContentsServiceManager final : public ServiceFramework<IContentsServiceManager> {
|
||||
public:
|
||||
explicit IContentsServiceManager(Core::System& system_);
|
||||
~IContentsServiceManager() override;
|
||||
|
||||
Result RequestContentsAuthorizationToken(OutInterface<IAsyncData> out_async_data,
|
||||
u64 unknown,
|
||||
InBuffer<BufferAttr_HipcMapAlias> in_buffer);
|
||||
|
||||
private:
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
};
|
||||
|
||||
class IAsyncData final : public ServiceFramework<IAsyncData> {
|
||||
public:
|
||||
explicit IAsyncData(Core::System& system_);
|
||||
~IAsyncData() override;
|
||||
|
||||
Result GetSize(Out<u64> out_size);
|
||||
Result Read(OutBuffer<BufferAttr_HipcMapAlias> out_buffer, u64 offset, u64 size);
|
||||
Result Cancel();
|
||||
Result GetSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
|
||||
private:
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Kernel::KEvent* async_event;
|
||||
std::vector<u8> data_buffer;
|
||||
bool is_complete;
|
||||
};
|
||||
|
||||
} // namespace Service::AOC
|
||||
Reference in New Issue
Block a user