From 909f7eb3d2d54050af667e7638171c0cc50c8f90 Mon Sep 17 00:00:00 2001
From: Narr the Reg <juangerman-13@hotmail.com>
Date: Thu, 8 Feb 2024 22:48:53 -0600
Subject: [PATCH] service: bcat: Implement news interfaces

---
 src/core/CMakeLists.txt                       | 12 ++++
 src/core/hle/service/bcat/bcat.cpp            | 12 ++++
 .../bcat/news/newly_arrived_event_holder.cpp  | 32 ++++++++++
 .../bcat/news/newly_arrived_event_holder.h    | 33 ++++++++++
 .../service/bcat/news/news_data_service.cpp   | 25 ++++++++
 .../hle/service/bcat/news/news_data_service.h | 20 ++++++
 .../bcat/news/news_database_service.cpp       | 35 +++++++++++
 .../service/bcat/news/news_database_service.h | 24 +++++++
 .../hle/service/bcat/news/news_interface.cpp  | 63 +++++++++++++++++++
 .../hle/service/bcat/news/news_interface.h    | 35 +++++++++++
 .../hle/service/bcat/news/news_service.cpp    | 46 ++++++++++++++
 src/core/hle/service/bcat/news/news_service.h | 24 +++++++
 .../bcat/news/overwrite_event_holder.cpp      | 31 +++++++++
 .../bcat/news/overwrite_event_holder.h        | 33 ++++++++++
 14 files changed, 425 insertions(+)
 create mode 100644 src/core/hle/service/bcat/news/newly_arrived_event_holder.cpp
 create mode 100644 src/core/hle/service/bcat/news/newly_arrived_event_holder.h
 create mode 100644 src/core/hle/service/bcat/news/news_data_service.cpp
 create mode 100644 src/core/hle/service/bcat/news/news_data_service.h
 create mode 100644 src/core/hle/service/bcat/news/news_database_service.cpp
 create mode 100644 src/core/hle/service/bcat/news/news_database_service.h
 create mode 100644 src/core/hle/service/bcat/news/news_interface.cpp
 create mode 100644 src/core/hle/service/bcat/news/news_interface.h
 create mode 100644 src/core/hle/service/bcat/news/news_service.cpp
 create mode 100644 src/core/hle/service/bcat/news/news_service.h
 create mode 100644 src/core/hle/service/bcat/news/overwrite_event_holder.cpp
 create mode 100644 src/core/hle/service/bcat/news/overwrite_event_holder.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 703e6050ff..539e09894b 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -512,6 +512,18 @@ add_library(core STATIC
     hle/service/audio/hwopus.h
     hle/service/bcat/backend/backend.cpp
     hle/service/bcat/backend/backend.h
+    hle/service/bcat/news/newly_arrived_event_holder.cpp
+    hle/service/bcat/news/newly_arrived_event_holder.h
+    hle/service/bcat/news/news_data_service.cpp
+    hle/service/bcat/news/news_data_service.h
+    hle/service/bcat/news/news_database_service.cpp
+    hle/service/bcat/news/news_database_service.h
+    hle/service/bcat/news/news_interface.cpp
+    hle/service/bcat/news/news_interface.h
+    hle/service/bcat/news/news_service.cpp
+    hle/service/bcat/news/news_service.h
+    hle/service/bcat/news/overwrite_event_holder.cpp
+    hle/service/bcat/news/overwrite_event_holder.h
     hle/service/bcat/bcat.cpp
     hle/service/bcat/bcat.h
     hle/service/bcat/bcat_interface.cpp
diff --git a/src/core/hle/service/bcat/bcat.cpp b/src/core/hle/service/bcat/bcat.cpp
index 31e9d8662c..02995ddeeb 100644
--- a/src/core/hle/service/bcat/bcat.cpp
+++ b/src/core/hle/service/bcat/bcat.cpp
@@ -4,6 +4,7 @@
 #include "core/hle/service/bcat/backend/backend.h"
 #include "core/hle/service/bcat/bcat.h"
 #include "core/hle/service/bcat/bcat_interface.h"
+#include "core/hle/service/bcat/news/news_interface.h"
 #include "core/hle/service/server_manager.h"
 
 namespace Service::BCAT {
@@ -20,6 +21,17 @@ void LoopProcess(Core::System& system) {
     server_manager->RegisterNamedService("bcat:s",
                                          std::make_shared<BcatInterface>(system, "bcat:s"));
 
+    server_manager->RegisterNamedService(
+        "news:a", std::make_shared<NewsInterface>(system, 0xffffffff, "news:a"));
+    server_manager->RegisterNamedService("news:p",
+                                         std::make_shared<NewsInterface>(system, 0x1, "news:p"));
+    server_manager->RegisterNamedService("news:c",
+                                         std::make_shared<NewsInterface>(system, 0x2, "news:c"));
+    server_manager->RegisterNamedService("news:v",
+                                         std::make_shared<NewsInterface>(system, 0x4, "news:v"));
+    server_manager->RegisterNamedService("news:m",
+                                         std::make_shared<NewsInterface>(system, 0xd, "news:m"));
+
     ServerManager::RunServer(std::move(server_manager));
 }
 
diff --git a/src/core/hle/service/bcat/news/newly_arrived_event_holder.cpp b/src/core/hle/service/bcat/news/newly_arrived_event_holder.cpp
new file mode 100644
index 0000000000..b3f9e46836
--- /dev/null
+++ b/src/core/hle/service/bcat/news/newly_arrived_event_holder.cpp
@@ -0,0 +1,32 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/bcat/news/newly_arrived_event_holder.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::BCAT {
+
+INewlyArrivedEventHolder::INewlyArrivedEventHolder(Core::System& system_)
+    : ServiceFramework{system_, "INewlyArrivedEventHolder"}, service_context{
+                                                                 system_,
+                                                                 "INewlyArrivedEventHolder"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, C<&INewlyArrivedEventHolder::Get>, "Get"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+    arrived_event = service_context.CreateEvent("INewlyArrivedEventHolder::ArrivedEvent");
+}
+
+INewlyArrivedEventHolder::~INewlyArrivedEventHolder() = default;
+
+Result INewlyArrivedEventHolder::Get(OutCopyHandle<Kernel::KReadableEvent> out_event) {
+    LOG_INFO(Service_BCAT, "called");
+
+    *out_event = &arrived_event->GetReadableEvent();
+    R_SUCCEED();
+}
+
+} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/news/newly_arrived_event_holder.h b/src/core/hle/service/bcat/news/newly_arrived_event_holder.h
new file mode 100644
index 0000000000..af19d81a75
--- /dev/null
+++ b/src/core/hle/service/bcat/news/newly_arrived_event_holder.h
@@ -0,0 +1,33 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.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 Kernel
+
+namespace Service::BCAT {
+
+class INewlyArrivedEventHolder final : public ServiceFramework<INewlyArrivedEventHolder> {
+public:
+    explicit INewlyArrivedEventHolder(Core::System& system_);
+    ~INewlyArrivedEventHolder() override;
+
+private:
+    Result Get(OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+    Kernel::KEvent* arrived_event;
+    KernelHelpers::ServiceContext service_context;
+};
+
+} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/news/news_data_service.cpp b/src/core/hle/service/bcat/news/news_data_service.cpp
new file mode 100644
index 0000000000..eba2e60645
--- /dev/null
+++ b/src/core/hle/service/bcat/news/news_data_service.cpp
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/bcat/news/news_data_service.h"
+
+namespace Service::BCAT {
+
+INewsDataService::INewsDataService(Core::System& system_)
+    : ServiceFramework{system_, "INewsDataService"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, nullptr, "Open"},
+        {1, nullptr, "OpenWithNewsRecordV1"},
+        {2, nullptr, "Read"},
+        {3, nullptr, "GetSize"},
+        {1001, nullptr, "OpenWithNewsRecord"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+INewsDataService::~INewsDataService() = default;
+
+} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/news/news_data_service.h b/src/core/hle/service/bcat/news/news_data_service.h
new file mode 100644
index 0000000000..441e0ea8e7
--- /dev/null
+++ b/src/core/hle/service/bcat/news/news_data_service.h
@@ -0,0 +1,20 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::BCAT {
+
+class INewsDataService final : public ServiceFramework<INewsDataService> {
+public:
+    explicit INewsDataService(Core::System& system_);
+    ~INewsDataService() override;
+};
+
+} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/news/news_database_service.cpp b/src/core/hle/service/bcat/news/news_database_service.cpp
new file mode 100644
index 0000000000..3b4b339018
--- /dev/null
+++ b/src/core/hle/service/bcat/news/news_database_service.cpp
@@ -0,0 +1,35 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/bcat/news/news_database_service.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::BCAT {
+
+INewsDatabaseService::INewsDatabaseService(Core::System& system_)
+    : ServiceFramework{system_, "INewsDatabaseService"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, nullptr, "GetListV1"},
+        {1, C<&INewsDatabaseService::Count>, "Count"},
+        {2, nullptr, "CountWithKey"},
+        {3, nullptr, "UpdateIntegerValue"},
+        {4, nullptr, "UpdateIntegerValueWithAddition"},
+        {5, nullptr, "UpdateStringValue"},
+        {1000, nullptr, "GetList"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+INewsDatabaseService::~INewsDatabaseService() = default;
+
+Result INewsDatabaseService::Count(Out<u32> out_count,
+                                   InBuffer<BufferAttr_HipcPointer> buffer_data) {
+    LOG_WARNING(Service_BCAT, "(STUBBED) called, buffer_size={}", buffer_data.size());
+    *out_count = 0;
+    R_SUCCEED();
+}
+
+} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/news/news_database_service.h b/src/core/hle/service/bcat/news/news_database_service.h
new file mode 100644
index 0000000000..dd09a16620
--- /dev/null
+++ b/src/core/hle/service/bcat/news/news_database_service.h
@@ -0,0 +1,24 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::BCAT {
+
+class INewsDatabaseService final : public ServiceFramework<INewsDatabaseService> {
+public:
+    explicit INewsDatabaseService(Core::System& system_);
+    ~INewsDatabaseService() override;
+
+private:
+    Result Count(Out<u32> out_count, InBuffer<BufferAttr_HipcPointer> buffer_data);
+};
+
+} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/news/news_interface.cpp b/src/core/hle/service/bcat/news/news_interface.cpp
new file mode 100644
index 0000000000..0eaef2ddc1
--- /dev/null
+++ b/src/core/hle/service/bcat/news/news_interface.cpp
@@ -0,0 +1,63 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/bcat/news/newly_arrived_event_holder.h"
+#include "core/hle/service/bcat/news/news_data_service.h"
+#include "core/hle/service/bcat/news/news_database_service.h"
+#include "core/hle/service/bcat/news/news_interface.h"
+#include "core/hle/service/bcat/news/news_service.h"
+#include "core/hle/service/bcat/news/overwrite_event_holder.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::BCAT {
+
+NewsInterface::NewsInterface(Core::System& system_, u32 permissions_, const char* name_)
+    : ServiceFramework{system_, name_}, permissions{permissions_} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, C<&NewsInterface::CreateNewsService>, "CreateNewsService"},
+        {1, C<&NewsInterface::CreateNewlyArrivedEventHolder>, "CreateNewlyArrivedEventHolder"},
+        {2, C<&NewsInterface::CreateNewsDataService>, "CreateNewsDataService"},
+        {3, C<&NewsInterface::CreateNewsDatabaseService>, "CreateNewsDatabaseService"},
+        {4, C<&NewsInterface::CreateOverwriteEventHolder>, "CreateOverwriteEventHolder"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+NewsInterface::~NewsInterface() = default;
+
+Result NewsInterface::CreateNewsService(OutInterface<INewsService> out_interface) {
+    LOG_INFO(Service_BCAT, "called");
+    *out_interface = std::make_shared<INewsService>(system);
+    R_SUCCEED();
+}
+
+Result NewsInterface::CreateNewlyArrivedEventHolder(
+    OutInterface<INewlyArrivedEventHolder> out_interface) {
+    LOG_INFO(Service_BCAT, "called");
+    *out_interface = std::make_shared<INewlyArrivedEventHolder>(system);
+    R_SUCCEED();
+}
+
+Result NewsInterface::CreateNewsDataService(OutInterface<INewsDataService> out_interface) {
+    LOG_INFO(Service_BCAT, "called");
+    *out_interface = std::make_shared<INewsDataService>(system);
+    R_SUCCEED();
+}
+
+Result NewsInterface::CreateNewsDatabaseService(OutInterface<INewsDatabaseService> out_interface) {
+    LOG_INFO(Service_BCAT, "called");
+    *out_interface = std::make_shared<INewsDatabaseService>(system);
+    R_SUCCEED();
+}
+
+Result NewsInterface::CreateOverwriteEventHolder(
+    OutInterface<IOverwriteEventHolder> out_interface) {
+    LOG_INFO(Service_BCAT, "called");
+    *out_interface = std::make_shared<IOverwriteEventHolder>(system);
+    R_SUCCEED();
+}
+
+} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/news/news_interface.h b/src/core/hle/service/bcat/news/news_interface.h
new file mode 100644
index 0000000000..d95edba3d5
--- /dev/null
+++ b/src/core/hle/service/bcat/news/news_interface.h
@@ -0,0 +1,35 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::BCAT {
+class INewsService;
+class INewlyArrivedEventHolder;
+class INewsDataService;
+class INewsDatabaseService;
+class IOverwriteEventHolder;
+
+class NewsInterface final : public ServiceFramework<NewsInterface> {
+public:
+    explicit NewsInterface(Core::System& system_, u32 permissions_, const char* name_);
+    ~NewsInterface() override;
+
+private:
+    Result CreateNewsService(OutInterface<INewsService> out_interface);
+    Result CreateNewlyArrivedEventHolder(OutInterface<INewlyArrivedEventHolder> out_interface);
+    Result CreateNewsDataService(OutInterface<INewsDataService> out_interface);
+    Result CreateNewsDatabaseService(OutInterface<INewsDatabaseService> out_interface);
+    Result CreateOverwriteEventHolder(OutInterface<IOverwriteEventHolder> out_interface);
+
+    u32 permissions;
+};
+
+} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/news/news_service.cpp b/src/core/hle/service/bcat/news/news_service.cpp
new file mode 100644
index 0000000000..3729373512
--- /dev/null
+++ b/src/core/hle/service/bcat/news/news_service.cpp
@@ -0,0 +1,46 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/bcat/news/news_service.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::BCAT {
+
+INewsService::INewsService(Core::System& system_) : ServiceFramework{system_, "INewsService"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {10100, nullptr, "PostLocalNews"},
+        {20100, nullptr, "SetPassphrase"},
+        {30100, C<&INewsService::GetSubscriptionStatus>, "GetSubscriptionStatus"},
+        {30101, nullptr, "GetTopicList"},
+        {30110, nullptr, "Unknown30110"},
+        {30200, nullptr, "IsSystemUpdateRequired"},
+        {30201, nullptr, "Unknown30201"},
+        {30210, nullptr, "Unknown30210"},
+        {30300, nullptr, "RequestImmediateReception"},
+        {30400, nullptr, "DecodeArchiveFile"},
+        {30500, nullptr, "Unknown30500"},
+        {30900, nullptr, "Unknown30900"},
+        {30901, nullptr, "Unknown30901"},
+        {30902, nullptr, "Unknown30902"},
+        {40100, nullptr, "SetSubscriptionStatus"},
+        {40101, nullptr, "RequestAutoSubscription"},
+        {40200, nullptr, "ClearStorage"},
+        {40201, nullptr, "ClearSubscriptionStatusAll"},
+        {90100, nullptr, "GetNewsDatabaseDump"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+INewsService::~INewsService() = default;
+
+Result INewsService::GetSubscriptionStatus(Out<u32> out_status,
+                                           InBuffer<BufferAttr_HipcPointer> buffer_data) {
+    LOG_WARNING(Service_BCAT, "(STUBBED) called, buffer_size={}", buffer_data.size());
+    *out_status = 0;
+    R_SUCCEED();
+}
+
+} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/news/news_service.h b/src/core/hle/service/bcat/news/news_service.h
new file mode 100644
index 0000000000..bb2e49848c
--- /dev/null
+++ b/src/core/hle/service/bcat/news/news_service.h
@@ -0,0 +1,24 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::BCAT {
+
+class INewsService final : public ServiceFramework<INewsService> {
+public:
+    explicit INewsService(Core::System& system_);
+    ~INewsService() override;
+
+private:
+    Result GetSubscriptionStatus(Out<u32> out_status, InBuffer<BufferAttr_HipcPointer> buffer_data);
+};
+
+} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/news/overwrite_event_holder.cpp b/src/core/hle/service/bcat/news/overwrite_event_holder.cpp
new file mode 100644
index 0000000000..4b06bfc5e9
--- /dev/null
+++ b/src/core/hle/service/bcat/news/overwrite_event_holder.cpp
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/bcat/news/overwrite_event_holder.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::BCAT {
+
+IOverwriteEventHolder::IOverwriteEventHolder(Core::System& system_)
+    : ServiceFramework{system_, "IOverwriteEventHolder"}, service_context{system_,
+                                                                          "IOverwriteEventHolder"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, C<&IOverwriteEventHolder::Get>, "Get"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+    overwrite_event = service_context.CreateEvent("IOverwriteEventHolder::OverwriteEvent");
+}
+
+IOverwriteEventHolder::~IOverwriteEventHolder() = default;
+
+Result IOverwriteEventHolder::Get(OutCopyHandle<Kernel::KReadableEvent> out_event) {
+    LOG_INFO(Service_BCAT, "called");
+
+    *out_event = &overwrite_event->GetReadableEvent();
+    R_SUCCEED();
+}
+
+} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/news/overwrite_event_holder.h b/src/core/hle/service/bcat/news/overwrite_event_holder.h
new file mode 100644
index 0000000000..4b016b2fe9
--- /dev/null
+++ b/src/core/hle/service/bcat/news/overwrite_event_holder.h
@@ -0,0 +1,33 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.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 Kernel
+
+namespace Service::BCAT {
+
+class IOverwriteEventHolder final : public ServiceFramework<IOverwriteEventHolder> {
+public:
+    explicit IOverwriteEventHolder(Core::System& system_);
+    ~IOverwriteEventHolder() override;
+
+private:
+    Result Get(OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+    Kernel::KEvent* overwrite_event;
+    KernelHelpers::ServiceContext service_context;
+};
+
+} // namespace Service::BCAT