aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaufeat <sahyno1996@gmail.com>2026-08-19 19:56:06 +0200
committercrueter <crueter@eden-emu.dev>2026-08-19 19:56:06 +0200
commit5c54abf353e64faf2b4d6ce433f062021801a548 (patch)
tree10c46389806db1ab6e8dd106c8f2d091030fde9f /src
parent0465292a81ed71b1f806b7107ca64edcef083e31 (diff)
[nim] unstub IShopServiceAsync (#4272)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions). - [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md) - [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability. ------------------- unstub IShopServiceAsync (but still stub Request, with empty JSON response) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4272 Reviewed-by: Samuel <lizzie@eden-emu.dev> Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/nim/nim.cpp131
1 files changed, 118 insertions, 13 deletions
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index 661da88b0c..e5f2d85dde 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -5,33 +5,136 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <chrono>
-#include <ctime>
+#include <mutex>
+#include <string>
+#include <vector>
+
#include "core/core.h"
#include "core/hle/kernel/k_event.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nim/nim.h"
+#include "core/hle/service/os/event.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"
namespace Service::NIM {
-
class IShopServiceAsync final : public ServiceFramework<IShopServiceAsync> {
public:
explicit IShopServiceAsync(Core::System& system_)
- : ServiceFramework{system_, "IShopServiceAsync"} {
+ : ServiceFramework{system_, "IShopServiceAsync"},
+ service_context{system_, "IShopServiceAsync"} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, nullptr, "Cancel"},
- {1, nullptr, "GetSize"},
- {2, nullptr, "Read"},
- {3, nullptr, "GetErrorCode"},
- {4, nullptr, "Request"},
- {5, nullptr, "Prepare"},
+ {0, D<&IShopServiceAsync::Cancel>, "Cancel"},
+ {1, D<&IShopServiceAsync::GetSize>, "GetSize"},
+ {2, D<&IShopServiceAsync::Read>, "Read"},
+ {3, D<&IShopServiceAsync::GetErrorCode>, "GetErrorCode"},
+ {4, D<&IShopServiceAsync::Request>, "Request"},
+ {5, D<&IShopServiceAsync::Prepare>, "Prepare"},
};
// clang-format on
RegisterHandlers(functions);
+
+ completion_event = service_context.CreateEvent("IShopServiceAsync:Completion");
+ }
+
+ ~IShopServiceAsync() override {
+ CancelImpl();
+ service_context.CloseEvent(completion_event);
+ }
+
+ Kernel::KReadableEvent* GetEvent() const {
+ return &completion_event->GetReadableEvent();
+ }
+
+private:
+ KernelHelpers::ServiceContext service_context;
+ Kernel::KEvent* completion_event;
+
+ std::jthread worker;
+ std::atomic<u32> error_code{0};
+
+ std::mutex data_mutex;
+ std::vector<u8> download_data;
+
+ void CancelImpl() {
+ worker.request_stop();
+ if (worker.joinable()) {
+ worker.join();
+ }
+ }
+
+ Result Cancel() {
+ LOG_DEBUG(Service_NIM, "called");
+ CancelImpl();
+ R_SUCCEED();
+ }
+
+ Result GetSize(Out<u64> out_size) {
+ LOG_DEBUG(Service_NIM, "called");
+ std::scoped_lock lock{data_mutex};
+ *out_size = download_data.size();
+ R_SUCCEED();
+ }
+
+ Result Read(Out<u64> out_size, u64 offset, OutBuffer<BufferAttr_HipcAutoSelect> out_buffer) {
+ std::scoped_lock lock{data_mutex};
+
+ u64 actual_read = 0;
+ if (offset < download_data.size()) {
+ actual_read = std::min<u64>(out_buffer.size(), download_data.size() - offset);
+ std::memcpy(out_buffer.data(), download_data.data() + offset, actual_read);
+ }
+
+ *out_size = actual_read;
+ R_SUCCEED();
+ }
+
+ Result GetErrorCode(Out<u32> out_error_code) {
+ LOG_DEBUG(Service_NIM, "called");
+ *out_error_code = error_code.load();
+ R_SUCCEED();
+ }
+
+ Result Request() {
+ LOG_DEBUG(Service_NIM, "(STUBBED) called");
+ CancelImpl();
+
+ error_code.store(0);
+ completion_event->Clear(system.Kernel());
+
+ {
+ std::scoped_lock lock{data_mutex};
+ download_data.clear();
+ }
+
+ worker = std::jthread([this](const std::stop_token& stop_token) {
+ if (stop_token.stop_requested()) {
+ error_code.store(1);
+ } else {
+ std::scoped_lock lock{data_mutex};
+ // Dummy JSON response, else it fails...
+ const std::string dummy_response = "{}";
+ download_data.assign(dummy_response.begin(), dummy_response.end());
+ error_code.store(0);
+ }
+ completion_event->Signal(system.Kernel());
+ });
+
+ R_SUCCEED();
+ }
+
+ Result Prepare(InArray<char, BufferAttr_HipcMapAlias> in_path, InArray<char, BufferAttr_HipcMapAlias> in_post) {
+ LOG_DEBUG(Service_NIM, "called");
+ if (!in_path.empty()) {
+ std::string url(in_path.data(), in_path.size());
+ LOG_INFO(Service_NIM, "Preparing request for URL: {}", url);
+ }
+ R_SUCCEED();
}
};
@@ -49,11 +152,13 @@ public:
}
private:
- void CreateAsyncInterface(HLERequestContext& ctx) {
- LOG_WARNING(Service_NIM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ void CreateAsyncInterface(HLERequestContext& ctx) {LOG_DEBUG(Service_NIM, "called");
+ auto async_interface = std::make_shared<IShopServiceAsync>(system);
+
+ IPC::ResponseBuilder rb{ctx, 2, 1, 1};
rb.Push(ResultSuccess);
- rb.PushIpcInterface<IShopServiceAsync>(ctx, system);
+ rb.PushCopyObjects(ctx, async_interface->GetEvent());
+ rb.PushIpcInterface<IShopServiceAsync>(ctx, std::move(async_interface));
}
};