Merge master

This commit is contained in:
PabloMK7
2023-08-23 19:58:18 +02:00
67 changed files with 3130 additions and 1343 deletions
+19 -14
View File
@@ -458,19 +458,14 @@ add_library(citra_core STATIC
mmio.h
movie.cpp
movie.h
nus_download.cpp
nus_download.h
perf_stats.cpp
perf_stats.h
precompiled_headers.h
rpc/packet.cpp
rpc/packet.h
rpc/rpc_server.cpp
rpc/rpc_server.h
rpc/server.cpp
rpc/server.h
rpc/udp_server.cpp
rpc/udp_server.h
savestate.cpp
savestate.h
savestate_data.h
system_titles.cpp
system_titles.h
telemetry_session.cpp
@@ -483,16 +478,26 @@ add_library(citra_core STATIC
create_target_directory_groups(citra_core)
target_link_libraries(citra_core PUBLIC citra_common PRIVATE audio_core network video_core)
target_link_libraries(citra_core PRIVATE Boost::boost Boost::serialization Boost::iostreams)
target_link_libraries(citra_core PRIVATE Boost::boost Boost::serialization Boost::iostreams httplib)
target_link_libraries(citra_core PUBLIC dds-ktx PRIVATE cryptopp fmt::fmt lodepng open_source_archives)
set_target_properties(citra_core PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO})
if (ENABLE_WEB_SERVICE)
target_compile_definitions(citra_core PRIVATE -DENABLE_WEB_SERVICE -DCPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(citra_core PRIVATE web_service ${OPENSSL_LIBS} httplib)
if (ANDROID)
target_link_libraries(citra_core PRIVATE ifaddrs)
endif()
target_link_libraries(citra_core PRIVATE web_service)
endif()
if (ENABLE_SCRIPTING)
target_compile_definitions(citra_core PUBLIC -DENABLE_SCRIPTING)
target_sources(citra_core PRIVATE
rpc/packet.cpp
rpc/packet.h
rpc/rpc_server.cpp
rpc/rpc_server.h
rpc/server.cpp
rpc/server.h
rpc/udp_server.cpp
rpc/udp_server.h
)
endif()
if ("x86_64" IN_LIST ARCHITECTURE OR "arm64" IN_LIST ARCHITECTURE)
+6
View File
@@ -45,7 +45,9 @@
#include "core/hw/lcd.h"
#include "core/loader/loader.h"
#include "core/movie.h"
#ifdef ENABLE_SCRIPTING
#include "core/rpc/server.h"
#endif
#include "core/telemetry_session.h"
#include "network/network.h"
#include "video_core/custom_textures/custom_tex_manager.h"
@@ -418,7 +420,9 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window,
telemetry_session = std::make_unique<Core::TelemetrySession>();
#ifdef ENABLE_SCRIPTING
rpc_server = std::make_unique<RPC::Server>(*this);
#endif
service_manager = std::make_unique<Service::SM::ServiceManager>(*this);
archive_manager = std::make_unique<Service::FS::ArchiveManager>(*this);
@@ -555,7 +559,9 @@ void System::Shutdown(bool is_deserializing) {
}
custom_tex_manager.reset();
telemetry_session.reset();
#ifdef ENABLE_SCRIPTING
rpc_server.reset();
#endif
archive_manager.reset();
service_manager.reset();
dsp_core.reset();
+2
View File
@@ -405,8 +405,10 @@ private:
/// Image interface
std::shared_ptr<Frontend::ImageInterface> registered_image_interface;
#ifdef ENABLE_SCRIPTING
/// RPC Server for scripting support
std::unique_ptr<RPC::Server> rpc_server;
#endif
std::unique_ptr<Service::FS::ArchiveManager> archive_manager;
+11
View File
@@ -151,6 +151,17 @@ void Module::Interface::RegisterDisconnectEvent(Kernel::HLERequestContext& ctx)
LOG_WARNING(Service_AC, "(STUBBED) called");
}
void Module::Interface::GetConnectingProxyEnable(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
constexpr bool proxy_enabled = false;
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
rb.Push(RESULT_SUCCESS);
rb.Push(proxy_enabled);
LOG_WARNING(Service_AC, "(STUBBED) called");
}
void Module::Interface::IsConnected(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
u32 unk = rp.Pop<u32>();
+8
View File
@@ -120,6 +120,14 @@ public:
*/
void RegisterDisconnectEvent(Kernel::HLERequestContext& ctx);
/**
* AC::GetConnectingProxyEnable service function
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2 : bool, is proxy enabled
*/
void GetConnectingProxyEnable(Kernel::HLERequestContext& ctx);
/**
* AC::IsConnected service function
* Outputs:
+1
View File
@@ -27,6 +27,7 @@ AC_I::AC_I(std::shared_ptr<Module> ac) : Module::Interface(std::move(ac), "ac:i"
{0x0027, &AC_I::GetInfraPriority, "GetInfraPriority"},
{0x002D, &AC_I::SetRequestEulaVersion, "SetRequestEulaVersion"},
{0x0030, &AC_I::RegisterDisconnectEvent, "RegisterDisconnectEvent"},
{0x0036, &AC_I::GetConnectingProxyEnable, "GetConnectingProxyEnable"},
{0x003C, nullptr, "GetAPSSIDList"},
{0x003E, &AC_I::IsConnected, "IsConnected"},
{0x0040, &AC_I::SetClientVersion, "SetClientVersion"},
+1
View File
@@ -27,6 +27,7 @@ AC_U::AC_U(std::shared_ptr<Module> ac) : Module::Interface(std::move(ac), "ac:u"
{0x0027, &AC_U::GetInfraPriority, "GetInfraPriority"},
{0x002D, &AC_U::SetRequestEulaVersion, "SetRequestEulaVersion"},
{0x0030, &AC_U::RegisterDisconnectEvent, "RegisterDisconnectEvent"},
{0x0036, &AC_U::GetConnectingProxyEnable, "GetConnectingProxyEnable"},
{0x003C, nullptr, "GetAPSSIDList"},
{0x003E, &AC_U::IsConnected, "IsConnected"},
{0x0040, &AC_U::SetClientVersion, "SetClientVersion"},
+4 -10
View File
@@ -31,9 +31,7 @@
#include "core/hle/service/fs/fs_user.h"
#include "core/loader/loader.h"
#include "core/loader/smdh.h"
#ifdef ENABLE_WEB_SERVICE
#include "web_service/nus_download.h"
#endif
#include "core/nus_download.h"
namespace Service::AM {
@@ -463,7 +461,6 @@ InstallStatus InstallCIA(const std::string& path,
}
InstallStatus InstallFromNus(u64 title_id, int version) {
#ifdef ENABLE_WEB_SERVICE
LOG_DEBUG(Service_AM, "Downloading {:X}", title_id);
CIAFile install_file{GetTitleMediaType(title_id)};
@@ -472,7 +469,7 @@ InstallStatus InstallFromNus(u64 title_id, int version) {
if (version != -1) {
path += fmt::format(".{}", version);
}
auto tmd_response = WebService::NUS::Download(path);
auto tmd_response = Core::NUS::Download(path);
if (!tmd_response) {
LOG_ERROR(Service_AM, "Failed to download tmd for {:016X}", title_id);
return InstallStatus::ErrorFileNotFound;
@@ -481,7 +478,7 @@ InstallStatus InstallFromNus(u64 title_id, int version) {
tmd.Load(*tmd_response);
path = fmt::format("/ccs/download/{:016X}/cetk", title_id);
auto cetk_response = WebService::NUS::Download(path);
auto cetk_response = Core::NUS::Download(path);
if (!cetk_response) {
LOG_ERROR(Service_AM, "Failed to download cetk for {:016X}", title_id);
return InstallStatus::ErrorFileNotFound;
@@ -492,7 +489,7 @@ InstallStatus InstallFromNus(u64 title_id, int version) {
for (std::size_t i = 0; i < content_count; ++i) {
const std::string filename = fmt::format("{:08x}", tmd.GetContentIDByIndex(i));
path = fmt::format("/ccs/download/{:016X}/{}", title_id, filename);
const auto temp_response = WebService::NUS::Download(path);
const auto temp_response = Core::NUS::Download(path);
if (!temp_response) {
LOG_ERROR(Service_AM, "Failed to download content for {:016X}", title_id);
return InstallStatus::ErrorFileNotFound;
@@ -550,9 +547,6 @@ InstallStatus InstallFromNus(u64 title_id, int version) {
return result;
}
return InstallStatus::Success;
#else
return InstallStatus::ErrorFileNotFound;
#endif
}
u64 GetTitleUpdateId(u64 title_id) {
+11 -10
View File
@@ -620,9 +620,9 @@ void Module::Interface::SetData(Kernel::HLERequestContext& ctx) {
void Module::Interface::ReadData(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
const u32 dest_buffer_size = rp.Pop<u32>();
const CecSystemInfoType info_type = rp.PopEnum<CecSystemInfoType>();
const u32 param_buffer_size = rp.Pop<u32>();
const auto dest_buffer_size = rp.Pop<u32>();
const auto info_type = rp.PopEnum<CecSystemInfoType>();
const auto param_buffer_size = rp.Pop<u32>();
auto& param_buffer = rp.PopMappedBuffer();
auto& dest_buffer = rp.PopMappedBuffer();
@@ -631,22 +631,23 @@ void Module::Interface::ReadData(Kernel::HLERequestContext& ctx) {
std::vector<u8> buffer;
switch (info_type) {
case CecSystemInfoType::EulaVersion: {
auto cfg = Service::CFG::GetModule(cecd->system);
Service::CFG::EULAVersion version = cfg->GetEULAVersion();
dest_buffer.Write(&version, 0, sizeof(version));
const auto cfg = Service::CFG::GetModule(cecd->system);
const auto version = cfg->GetEULAVersion();
buffer = {version.minor, version.major};
break;
}
case CecSystemInfoType::Eula:
buffer = {0x01}; // Eula agreed
dest_buffer.Write(buffer.data(), 0, buffer.size());
buffer = {true}; // Eula agreed
break;
case CecSystemInfoType::ParentControl:
buffer = {0x00}; // No parent control
dest_buffer.Write(buffer.data(), 0, buffer.size());
buffer = {false}; // No parent control
break;
default:
LOG_ERROR(Service_CECD, "Unknown system info type={:#x}", info_type);
buffer = {};
}
dest_buffer.Write(buffer.data(), 0,
std::min(static_cast<size_t>(dest_buffer_size), buffer.size()));
rb.Push(RESULT_SUCCESS);
rb.PushMappedBuffer(param_buffer);
+1
View File
@@ -314,6 +314,7 @@ void HTTP_C::ReceiveDataImpl(Kernel::HLERequestContext& ctx, bool timeout) {
} else {
LOG_WARNING(Service_HTTP, "(STUBBED) called");
}
[[maybe_unused]] Kernel::MappedBuffer& buffer = rp.PopMappedBuffer();
Kernel::MappedBuffer& buffer = rp.PopMappedBuffer();
-3
View File
@@ -17,12 +17,10 @@
#include <boost/serialization/unordered_map.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/weak_ptr.hpp>
#ifdef ENABLE_WEB_SERVICE
#if defined(__ANDROID__)
#include <ifaddrs.h>
#endif
#include <httplib.h>
#endif
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/service/service.h"
@@ -214,7 +212,6 @@ public:
bool uses_default_client_cert{};
#ifdef ENABLE_WEB_SERVICE
httplib::Response response;
#endif
};
struct SessionData : public Kernel::SessionRequestHandler::SessionDataBase {
+18 -9
View File
@@ -316,7 +316,7 @@ void Module::Interface::GetTagInfo2(Kernel::HLERequestContext& ctx) {
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
IPC::RequestBuilder rb = rp.MakeBuilder(26, 0);
IPC::RequestBuilder rb = rp.MakeBuilder(25, 0);
rb.Push(RESULT_SUCCESS);
rb.PushRaw<TagInfo2>({});
return;
@@ -324,7 +324,7 @@ void Module::Interface::GetTagInfo2(Kernel::HLERequestContext& ctx) {
TagInfo2 tag_info{};
const auto result = nfc->device->GetTagInfo2(tag_info);
IPC::RequestBuilder rb = rp.MakeBuilder(26, 0);
IPC::RequestBuilder rb = rp.MakeBuilder(25, 0);
rb.Push(result);
rb.PushRaw<TagInfo2>(tag_info);
}
@@ -383,10 +383,14 @@ void Module::Interface::OpenApplicationArea(Kernel::HLERequestContext& ctx) {
void Module::Interface::CreateApplicationArea(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
u32 access_id = rp.Pop<u32>();
[[maybe_unused]] u32 size = rp.Pop<u32>();
u32 size = rp.Pop<u32>();
std::vector<u8> buffer = rp.PopStaticBuffer();
LOG_CRITICAL(Service_NFC, "called, size={}", size);
LOG_INFO(Service_NFC, "called, size={}", size);
if (buffer.size() > size) {
buffer.resize(size);
}
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
@@ -402,8 +406,9 @@ void Module::Interface::CreateApplicationArea(Kernel::HLERequestContext& ctx) {
void Module::Interface::ReadApplicationArea(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
u32 size = rp.Pop<u32>();
LOG_INFO(Service_NFC, "called");
LOG_INFO(Service_NFC, "called, size={}", size);
nfc->device->RescheduleTagRemoveEvent();
@@ -413,7 +418,7 @@ void Module::Interface::ReadApplicationArea(Kernel::HLERequestContext& ctx) {
return;
}
std::vector<u8> buffer(sizeof(ApplicationArea));
std::vector<u8> buffer(size);
const auto result = nfc->device->GetApplicationArea(buffer);
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
@@ -423,11 +428,15 @@ void Module::Interface::ReadApplicationArea(Kernel::HLERequestContext& ctx) {
void Module::Interface::WriteApplicationArea(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
[[maybe_unused]] u32 size = rp.Pop<u32>();
u32 size = rp.Pop<u32>();
std::vector<u8> tag_uuid_info = rp.PopStaticBuffer();
std::vector<u8> buffer = rp.PopStaticBuffer();
LOG_CRITICAL(Service_NFC, "called, size={}", size);
LOG_INFO(Service_NFC, "called, size={}", size);
if (buffer.size() > size) {
buffer.resize(size);
}
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
@@ -540,7 +549,7 @@ void Module::Interface::GetIdentificationBlock(Kernel::HLERequestContext& ctx) {
ModelInfo model_info{};
const auto result = nfc->device->GetModelInfo(model_info);
IPC::RequestBuilder rb = rp.MakeBuilder(0x1F, 0);
IPC::RequestBuilder rb = rp.MakeBuilder(14, 0);
rb.Push(result);
rb.PushRaw<ModelInfo>(model_info);
}
+2 -2
View File
@@ -1101,8 +1101,8 @@ void NfcDevice::BuildAmiiboWithoutKeys() {
}
void NfcDevice::RescheduleTagRemoveEvent() {
/// The interval at which the amiibo will be removed automatically 1.5s
static constexpr u64 amiibo_removal_interval = nsToCycles(1500 * 1000 * 1000);
/// The interval at which the amiibo will be removed automatically 3s
static constexpr u64 amiibo_removal_interval = msToCycles(3 * 1000);
system.CoreTiming().UnscheduleEvent(remove_amiibo_event, 0);
+49
View File
@@ -0,0 +1,49 @@
// Copyright 2020 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <memory>
#include <httplib.h>
#include "common/logging/log.h"
#include "core/nus_download.h"
namespace Core::NUS {
std::optional<std::vector<u8>> Download(const std::string& path) {
constexpr auto HOST = "http://nus.cdn.c.shop.nintendowifi.net";
std::unique_ptr<httplib::Client> client = std::make_unique<httplib::Client>(HOST);
if (client == nullptr) {
LOG_ERROR(WebService, "Invalid URL {}{}", HOST, path);
return {};
}
httplib::Request request{
.method = "GET",
.path = path,
// Needed when httplib is included on android
.matches = httplib::Match(),
};
client->set_follow_location(true);
const auto result = client->send(request);
if (!result) {
LOG_ERROR(WebService, "GET to {}{} returned null", HOST, path);
return {};
}
const auto& response = result.value();
if (response.status >= 400) {
LOG_ERROR(WebService, "GET to {}{} returned error status code: {}", HOST, path,
response.status);
return {};
}
if (!response.headers.contains("content-type")) {
LOG_ERROR(WebService, "GET to {}{} returned no content", HOST, path);
return {};
}
return std::vector<u8>(response.body.begin(), response.body.end());
}
} // namespace Core::NUS
+15
View File
@@ -0,0 +1,15 @@
// Copyright 2020 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <optional>
#include <vector>
#include "common/common_types.h"
namespace Core::NUS {
std::optional<std::vector<u8>> Download(const std::string& path);
} // namespace Core::NUS
+29 -7
View File
@@ -15,18 +15,21 @@
#include "core/core.h"
#include "core/movie.h"
#include "core/savestate.h"
#include "core/savestate_data.h"
#include "network/network.h"
namespace Core {
#pragma pack(push, 1)
struct CSTHeader {
std::array<u8, 4> filetype; /// Unique Identifier to check the file type (always "CST"0x1B)
u64_le program_id; /// ID of the ROM being executed. Also called title_id
std::array<u8, 20> revision; /// Git hash of the revision this savestate was created with
u64_le time; /// The time when this save state was created
std::array<u8, 4> filetype; /// Unique Identifier to check the file type (always "CST"0x1B)
u64_le program_id; /// ID of the ROM being executed. Also called title_id
std::array<u8, 20> revision; /// Git hash of the revision this savestate was created with
u64_le time; /// The time when this save state was created
std::array<u8, 20> build_name; /// The build name (Canary/Nightly) with the version number
u32_le zero = 0; /// Should be zero, just in case.
std::array<u8, 216> reserved{}; /// Make heading 256 bytes so it has consistent size
std::array<u8, 192> reserved{}; /// Make heading 256 bytes so it has consistent size
};
static_assert(sizeof(CSTHeader) == 256, "CSTHeader should be 256 bytes");
#pragma pack(pop)
@@ -58,11 +61,26 @@ static bool ValidateSaveState(const CSTHeader& header, SaveStateInfo& info, u64
return false;
}
const std::string revision = fmt::format("{:02x}", fmt::join(header.revision, ""));
const std::string build_name =
header.zero == 0 ? reinterpret_cast<const char*>(header.build_name.data()) : "";
if (revision == Common::g_scm_rev) {
info.status = SaveStateInfo::ValidationStatus::OK;
} else {
LOG_WARNING(Core, "Save state file {} created from a different revision {}", path,
revision);
if (!build_name.empty()) {
info.build_name = build_name;
} else if (hash_to_version.find(revision) != hash_to_version.end()) {
info.build_name = hash_to_version.at(revision);
}
if (info.build_name.empty()) {
LOG_WARNING(Core, "Save state file {} created from a different revision {}", path,
revision);
} else {
LOG_WARNING(Core,
"Save state file {} created from a different build {} with revision {}",
path, info.build_name, revision);
}
info.status = SaveStateInfo::ValidationStatus::RevisionDismatch;
}
return true;
@@ -134,6 +152,10 @@ void System::SaveState(u32 slot) const {
header.time = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
const std::string build_fullname = Common::g_build_fullname;
std::memset(header.build_name.data(), 0, sizeof(header.build_name));
std::memcpy(header.build_name.data(), build_fullname.c_str(),
std::min(build_fullname.length(), sizeof(header.build_name) - 1));
if (file.WriteBytes(&header, sizeof(header)) != sizeof(header) ||
file.WriteBytes(buffer.data(), buffer.size()) != buffer.size()) {
+2
View File
@@ -4,6 +4,7 @@
#pragma once
#include <string>
#include <vector>
#include "common/common_types.h"
@@ -16,6 +17,7 @@ struct SaveStateInfo {
OK,
RevisionDismatch,
} status;
std::string build_name;
};
constexpr u32 SaveStateSlotCount = 10; // Maximum count of savestate slots
File diff suppressed because it is too large Load Diff