mirror of
https://github.com/Lime3DS/Lime3DS
synced 2025-01-09 13:43:27 +00:00
485 lines
17 KiB
C++
485 lines
17 KiB
C++
// Copyright 2015 Citra Emulator Project
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
#pragma once
|
|
|
|
#include "core/file_sys/archive_backend.h"
|
|
#include "core/hle/service/service.h"
|
|
|
|
namespace Core {
|
|
class System;
|
|
}
|
|
|
|
namespace Service::NEWS {
|
|
constexpr u32 MAX_NOTIFICATIONS = 100;
|
|
|
|
struct NewsDBHeader {
|
|
u8 valid;
|
|
u8 flags;
|
|
INSERT_PADDING_BYTES(0xE);
|
|
|
|
bool IsValid() const {
|
|
return valid == 1;
|
|
}
|
|
|
|
private:
|
|
template <class Archive>
|
|
void serialize(Archive& ar, const unsigned int) {
|
|
ar & valid;
|
|
ar & flags;
|
|
}
|
|
friend class boost::serialization::access;
|
|
};
|
|
static_assert(sizeof(NewsDBHeader) == 0x10, "News DB Header structure size is wrong");
|
|
|
|
struct NotificationHeader {
|
|
u8 flag_valid;
|
|
u8 flag_read;
|
|
u8 flag_jpeg;
|
|
u8 flag_boss;
|
|
u8 flag_optout;
|
|
u8 flag_url;
|
|
u8 flag_unk0x6;
|
|
INSERT_PADDING_BYTES(0x1);
|
|
u64_le program_id;
|
|
u32_le ns_data_id; // Only used in BOSS notifications
|
|
u32_le version; // Only used in BOSS notifications
|
|
u64_le jump_param;
|
|
INSERT_PADDING_BYTES(0x8);
|
|
u64_le date_time;
|
|
std::array<u16_le, 0x20> title;
|
|
|
|
bool IsValid() const {
|
|
return flag_valid == 1;
|
|
}
|
|
|
|
private:
|
|
template <class Archive>
|
|
void serialize(Archive& ar, const unsigned int) {
|
|
ar & flag_valid;
|
|
ar & flag_read;
|
|
ar & flag_jpeg;
|
|
ar & flag_boss;
|
|
ar & flag_optout;
|
|
ar & flag_url;
|
|
ar & flag_unk0x6;
|
|
ar & program_id;
|
|
ar & ns_data_id;
|
|
ar & version;
|
|
ar & jump_param;
|
|
ar & date_time;
|
|
ar & title;
|
|
}
|
|
friend class boost::serialization::access;
|
|
};
|
|
static_assert(sizeof(NotificationHeader) == 0x70, "Notification Header structure size is wrong");
|
|
|
|
struct NewsDB {
|
|
NewsDBHeader header;
|
|
std::array<NotificationHeader, MAX_NOTIFICATIONS> notifications;
|
|
|
|
private:
|
|
template <class Archive>
|
|
void serialize(Archive& ar, const unsigned int) {
|
|
ar & header;
|
|
ar & notifications;
|
|
}
|
|
friend class boost::serialization::access;
|
|
};
|
|
static_assert(sizeof(NewsDB) == 0x2BD0, "News DB structure size is wrong");
|
|
|
|
class Module final {
|
|
public:
|
|
explicit Module(Core::System& system_);
|
|
~Module() = default;
|
|
|
|
class Interface : public ServiceFramework<Interface> {
|
|
public:
|
|
Interface(std::shared_ptr<Module> news, const char* name, u32 max_session);
|
|
~Interface() = default;
|
|
|
|
private:
|
|
void AddNotificationImpl(Kernel::HLERequestContext& ctx, bool news_s);
|
|
|
|
protected:
|
|
/**
|
|
* AddNotification NEWS:U service function.
|
|
* Inputs:
|
|
* 0 : 0x000100C8
|
|
* 1 : Header size
|
|
* 2 : Message size
|
|
* 3 : Image size
|
|
* 4 : PID Translation Header (0x20)
|
|
* 5 : Caller PID
|
|
* 6 : Header Buffer Mapping Translation Header ((Size << 4) | 0xA)
|
|
* 7 : Header Buffer Pointer
|
|
* 8 : Message Buffer Mapping Translation Header ((Size << 4) | 0xA)
|
|
* 9 : Message Buffer Pointer
|
|
* 10 : Image Buffer Mapping Translation Header ((Size << 4) | 0xA)
|
|
* 11 : Image Buffer Pointer
|
|
* Outputs:
|
|
* 0 : 0x00010046
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
*/
|
|
void AddNotification(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* AddNotification NEWS:S service function.
|
|
* Inputs:
|
|
* 0 : 0x000100C6
|
|
* 1 : Header size
|
|
* 2 : Message size
|
|
* 3 : Image size
|
|
* 4 : Header Buffer Mapping Translation Header ((Size << 4) | 0xA)
|
|
* 5 : Header Buffer Pointer
|
|
* 6 : Message Buffer Mapping Translation Header ((Size << 4) | 0xA)
|
|
* 7 : Message Buffer Pointer
|
|
* 8 : Image Buffer Mapping Translation Header ((Size << 4) | 0xA)
|
|
* 9 : Image Buffer Pointer
|
|
* Outputs:
|
|
* 0 : 0x00010046
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
*/
|
|
void AddNotificationSystem(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* ResetNotifications service function.
|
|
* Inputs:
|
|
* 0 : 0x00040000
|
|
* Outputs:
|
|
* 0 : 0x00040040
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
*/
|
|
void ResetNotifications(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* GetTotalNotifications service function.
|
|
* Inputs:
|
|
* 0 : 0x00050000
|
|
* Outputs:
|
|
* 0 : 0x00050080
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
* 2 : Number of notifications
|
|
*/
|
|
void GetTotalNotifications(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* SetNewsDBHeader service function.
|
|
* Inputs:
|
|
* 0 : 0x00060042
|
|
* 1 : Size
|
|
* 2 : Input Buffer Mapping Translation Header ((Size << 4) | 0xA)
|
|
* 3 : Input Buffer Pointer
|
|
* Outputs:
|
|
* 0 : 0x00060042
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
*/
|
|
void SetNewsDBHeader(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* SetNotificationHeader service function.
|
|
* Inputs:
|
|
* 0 : 0x00070082
|
|
* 1 : Notification index
|
|
* 2 : Size
|
|
* 3 : Input Buffer Mapping Translation Header ((Size << 4) | 0xA)
|
|
* 4 : Input Buffer Pointer
|
|
* Outputs:
|
|
* 0 : 0x00070042
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
*/
|
|
void SetNotificationHeader(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* SetNotificationMessage service function.
|
|
* Inputs:
|
|
* 0 : 0x00080082
|
|
* 1 : Notification index
|
|
* 2 : Size
|
|
* 3 : Input Buffer Mapping Translation Header ((Size << 4) | 0xA)
|
|
* 4 : Input Buffer Pointer
|
|
* Outputs:
|
|
* 0 : 0x00080042
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
*/
|
|
void SetNotificationMessage(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* SetNotificationImage service function.
|
|
* Inputs:
|
|
* 0 : 0x00090082
|
|
* 1 : Notification index
|
|
* 2 : Size
|
|
* 3 : Input Buffer Mapping Translation Header ((Size << 4) | 0xA)
|
|
* 4 : Input Buffer Pointer
|
|
* Outputs:
|
|
* 0 : 0x00090042
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
*/
|
|
void SetNotificationImage(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* GetNewsDBHeader service function.
|
|
* Inputs:
|
|
* 0 : 0x000A0042
|
|
* 1 : Size
|
|
* 2 : Output Buffer Mapping Translation Header ((Size << 4) | 0xC)
|
|
* 3 : Output Buffer Pointer
|
|
* Outputs:
|
|
* 0 : 0x000A0082
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
* 2 : Actual Size
|
|
*/
|
|
void GetNewsDBHeader(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* GetNotificationHeader service function.
|
|
* Inputs:
|
|
* 0 : 0x000B0082
|
|
* 1 : Notification index
|
|
* 2 : Size
|
|
* 3 : Output Buffer Mapping Translation Header ((Size << 4) | 0xC)
|
|
* 4 : Output Buffer Pointer
|
|
* Outputs:
|
|
* 0 : 0x000B0082
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
* 2 : Actual Size
|
|
*/
|
|
void GetNotificationHeader(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* GetNotificationMessage service function.
|
|
* Inputs:
|
|
* 0 : 0x000C0082
|
|
* 1 : Notification index
|
|
* 2 : Size
|
|
* 3 : Output Buffer Mapping Translation Header ((Size << 4) | 0xC)
|
|
* 4 : Output Buffer Pointer
|
|
* Outputs:
|
|
* 0 : 0x000C0082
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
* 2 : Actual Size
|
|
*/
|
|
void GetNotificationMessage(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* GetNotificationImage service function.
|
|
* Inputs:
|
|
* 0 : 0x000D0082
|
|
* 1 : Notification index
|
|
* 2 : Size
|
|
* 3 : Output Buffer Mapping Translation Header ((Size << 4) | 0xC)
|
|
* 4 : Output Buffer Pointer
|
|
* Outputs:
|
|
* 0 : 0x000D0082
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
* 2 : Actual Size
|
|
*/
|
|
void GetNotificationImage(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* SetAutomaticSyncFlag service function.
|
|
* Inputs:
|
|
* 0 : 0x00110040
|
|
* 1 : Flag
|
|
* Outputs:
|
|
* 0 : 0x00110040
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
*/
|
|
void SetAutomaticSyncFlag(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* SetNotificationHeaderOther service function.
|
|
* Inputs:
|
|
* 0 : 0x00120082
|
|
* 1 : Notification index
|
|
* 2 : Size
|
|
* 3 : Input Buffer Mapping Translation Header ((Size << 4) | 0xA)
|
|
* 4 : Input Buffer Pointer
|
|
* Outputs:
|
|
* 0 : 0x00120042
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
*/
|
|
void SetNotificationHeaderOther(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* WriteNewsDBSavedata service function.
|
|
* Inputs:
|
|
* 0 : 0x00130000
|
|
* Outputs:
|
|
* 0 : 0x00130040
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
*/
|
|
void WriteNewsDBSavedata(Kernel::HLERequestContext& ctx);
|
|
|
|
/**
|
|
* GetTotalArrivedNotifications service function.
|
|
* Inputs:
|
|
* 0 : 0x00140000
|
|
* Outputs:
|
|
* 0 : 0x00140080
|
|
* 1 : Result of function, 0 on success, otherwise error code
|
|
* 2 : Number of pending notifications to be synced
|
|
*/
|
|
void GetTotalArrivedNotifications(Kernel::HLERequestContext& ctx);
|
|
|
|
protected:
|
|
std::shared_ptr<Module> news;
|
|
};
|
|
|
|
private:
|
|
/**
|
|
* Gets the total number of notifications
|
|
* @returns Number of notifications
|
|
*/
|
|
std::size_t GetTotalNotifications();
|
|
|
|
/**
|
|
* Loads the News DB into the given buffer
|
|
* @param header The header buffer
|
|
* @param size The size of the header buffer
|
|
* @returns Number of bytes read, or error code
|
|
*/
|
|
ResultVal<std::size_t> GetNewsDBHeader(NewsDBHeader* header, const std::size_t size);
|
|
|
|
/**
|
|
* Loads the header for a notification ID into the given buffer
|
|
* @param notification_index The index of the notification ID
|
|
* @param header The header buffer
|
|
* @param size The size of the header buffer
|
|
* @returns Number of bytes read, or error code
|
|
*/
|
|
ResultVal<std::size_t> GetNotificationHeader(const u32 notification_index,
|
|
NotificationHeader* header,
|
|
const std::size_t size);
|
|
|
|
/**
|
|
* Opens the message file for a notification ID and loads it to the message buffer
|
|
* @param notification_index The index of the notification ID
|
|
* @param mesasge The message buffer
|
|
* @returns Number of bytes read, or error code
|
|
*/
|
|
ResultVal<std::size_t> GetNotificationMessage(const u32 notification_index,
|
|
std::span<u8> message);
|
|
|
|
/**
|
|
* Opens the image file for a notification ID and loads it to the image buffer
|
|
* @param notification_index The index of the notification ID
|
|
* @param image The image buffer
|
|
* @returns Number of bytes read, or error code
|
|
*/
|
|
ResultVal<std::size_t> GetNotificationImage(const u32 notification_index, std::span<u8> image);
|
|
|
|
/**
|
|
* Modifies the header for the News DB in memory and saves the News DB file
|
|
* @param header The database header
|
|
* @param size The amount of bytes to copy from the header
|
|
* @returns Result indicating the result of the operation, 0 on success
|
|
*/
|
|
Result SetNewsDBHeader(const NewsDBHeader* header, const std::size_t size);
|
|
|
|
/**
|
|
* Modifies the header for a notification ID on memory and saves the News DB file
|
|
* @param notification_index The index of the notification ID
|
|
* @param header The notification header
|
|
* @param size The amount of bytes to copy from the header
|
|
* @returns Result indicating the result of the operation, 0 on success
|
|
*/
|
|
Result SetNotificationHeader(const u32 notification_index, const NotificationHeader* header,
|
|
const std::size_t size);
|
|
|
|
/**
|
|
* Modifies the header for a notification ID on memory. The News DB file isn't updated
|
|
* @param notification_index The index of the notification ID
|
|
* @param header The notification header
|
|
* @param size The amount of bytes to copy from the header
|
|
* @returns Result indicating the result of the operation, 0 on success
|
|
*/
|
|
Result SetNotificationHeaderOther(const u32 notification_index,
|
|
const NotificationHeader* header, const std::size_t size);
|
|
|
|
/**
|
|
* Sets a given message to a notification ID
|
|
* @param notification_index The index of the notification ID
|
|
* @param message The notification message
|
|
* @returns Result indicating the result of the operation, 0 on success
|
|
*/
|
|
Result SetNotificationMessage(const u32 notification_index, std::span<const u8> message);
|
|
|
|
/**
|
|
* Sets a given image to a notification ID
|
|
* @param notification_index The index of the notification ID
|
|
* @param image The notification image
|
|
* @returns Result indicating the result of the operation, 0 on success
|
|
*/
|
|
Result SetNotificationImage(const u32 notification_index, std::span<const u8> image);
|
|
|
|
/**
|
|
* Creates a new notification with the given data and saves all the contents
|
|
* @param header The notification header
|
|
* @param header_size The amount of bytes to copy from the header
|
|
* @param message The notification message
|
|
* @param image The notification image
|
|
* @returns Result indicating the result of the operation, 0 on success
|
|
*/
|
|
Result SaveNotification(const NotificationHeader* header, const std::size_t header_size,
|
|
std::span<const u8> message, std::span<const u8> image);
|
|
|
|
/**
|
|
* Deletes the given notification ID from the database
|
|
* @param notification_id The notification ID to delete
|
|
* @returns Result indicating the result of the operation, 0 on success
|
|
*/
|
|
Result DeleteNotification(const u32 notification_id);
|
|
|
|
/**
|
|
* Opens the news.db savedata file and load it to the memory buffer. If the file or the savedata
|
|
* don't exist, they are created
|
|
* @returns Result indicating the result of the operation, 0 on success
|
|
*/
|
|
Result LoadNewsDBSavedata();
|
|
|
|
/**
|
|
* Writes the news.db savedata file to the the NEWS system savedata
|
|
* @returns Result indicating the result of the operation, 0 on success
|
|
*/
|
|
Result SaveNewsDBSavedata();
|
|
|
|
/**
|
|
* Opens the file with the given filename inside the NEWS system savedata
|
|
* @param filename The file to open
|
|
* @param buffer The buffer to output the contents on
|
|
* @returns Number of bytes read, or error code
|
|
*/
|
|
ResultVal<std::size_t> LoadFileFromSavedata(std::string filename, std::span<u8> buffer);
|
|
|
|
/**
|
|
* Writes the file with the given filename inside the NEWS system savedata
|
|
* @param filename The output file
|
|
* @param buffer The buffer to read the contents from
|
|
* @returns Result indicating the result of the operation, 0 on success
|
|
*/
|
|
Result SaveFileToSavedata(std::string filename, std::span<const u8> buffer);
|
|
|
|
bool CompareNotifications(const u32 first_id, const u32 second_id);
|
|
|
|
private:
|
|
Core::System& system;
|
|
|
|
NewsDB db{};
|
|
std::array<u32, MAX_NOTIFICATIONS> notification_ids; // Notifications ordered by date time
|
|
u8 automatic_sync_flag;
|
|
std::unique_ptr<FileSys::ArchiveBackend> news_system_save_data_archive;
|
|
|
|
template <class Archive>
|
|
void serialize(Archive& ar, const unsigned int);
|
|
friend class boost::serialization::access;
|
|
};
|
|
|
|
void InstallInterfaces(Core::System& system);
|
|
|
|
} // namespace Service::NEWS
|
|
|
|
SERVICE_CONSTRUCT(Service::NEWS::Module)
|
|
BOOST_CLASS_EXPORT_KEY(Service::NEWS::Module)
|