core: Eliminate more uses of Core::System::GetInstance(). (#7313)

This commit is contained in:
Steveice10 2024-01-05 12:07:28 -08:00 committed by GitHub
parent 8e2037b3ff
commit f2ee9baec7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 416 additions and 387 deletions

View file

@ -24,16 +24,10 @@
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
SERIALIZE_EXPORT_IMPL(AudioCore::DspHle)
using InterruptType = Service::DSP::InterruptType; using InterruptType = Service::DSP::InterruptType;
namespace AudioCore { namespace AudioCore {
DspHle::DspHle()
: DspHle(Core::System::GetInstance(), Core::System::GetInstance().Memory(),
Core::System::GetInstance().CoreTiming()) {}
DspHle::DspHle(Core::System& system) : DspHle(system, system.Memory(), system.CoreTiming()) {} DspHle::DspHle(Core::System& system) : DspHle(system, system.Memory(), system.CoreTiming()) {}
template <class Archive> template <class Archive>

View file

@ -50,13 +50,9 @@ private:
friend struct Impl; friend struct Impl;
std::unique_ptr<Impl> impl; std::unique_ptr<Impl> impl;
DspHle();
template <class Archive> template <class Archive>
void serialize(Archive& ar, const unsigned int); void serialize(Archive& ar, const unsigned int);
friend class boost::serialization::access; friend class boost::serialization::access;
}; };
} // namespace AudioCore } // namespace AudioCore
BOOST_CLASS_EXPORT_KEY(AudioCore::DspHle)

View file

@ -24,8 +24,8 @@ namespace {
constexpr std::array input_details = { constexpr std::array input_details = {
#ifdef HAVE_CUBEB #ifdef HAVE_CUBEB
InputDetails{InputType::Cubeb, "Real Device (Cubeb)", true, InputDetails{InputType::Cubeb, "Real Device (Cubeb)", true,
[](std::string_view device_id) -> std::unique_ptr<Input> { [](Core::System& system, std::string_view device_id) -> std::unique_ptr<Input> {
if (!Core::System::GetInstance().HasMicPermission()) { if (!system.HasMicPermission()) {
LOG_WARNING(Audio, LOG_WARNING(Audio,
"Microphone permission denied, falling back to null input."); "Microphone permission denied, falling back to null input.");
return std::make_unique<NullInput>(); return std::make_unique<NullInput>();
@ -36,8 +36,8 @@ constexpr std::array input_details = {
#endif #endif
#ifdef HAVE_OPENAL #ifdef HAVE_OPENAL
InputDetails{InputType::OpenAL, "Real Device (OpenAL)", true, InputDetails{InputType::OpenAL, "Real Device (OpenAL)", true,
[](std::string_view device_id) -> std::unique_ptr<Input> { [](Core::System& system, std::string_view device_id) -> std::unique_ptr<Input> {
if (!Core::System::GetInstance().HasMicPermission()) { if (!system.HasMicPermission()) {
LOG_WARNING(Audio, LOG_WARNING(Audio,
"Microphone permission denied, falling back to null input."); "Microphone permission denied, falling back to null input.");
return std::make_unique<NullInput>(); return std::make_unique<NullInput>();
@ -47,12 +47,12 @@ constexpr std::array input_details = {
&ListOpenALInputDevices}, &ListOpenALInputDevices},
#endif #endif
InputDetails{InputType::Static, "Static Noise", false, InputDetails{InputType::Static, "Static Noise", false,
[](std::string_view device_id) -> std::unique_ptr<Input> { [](Core::System& system, std::string_view device_id) -> std::unique_ptr<Input> {
return std::make_unique<StaticInput>(); return std::make_unique<StaticInput>();
}, },
[] { return std::vector<std::string>{"Static Noise"}; }}, [] { return std::vector<std::string>{"Static Noise"}; }},
InputDetails{InputType::Null, "None", false, InputDetails{InputType::Null, "None", false,
[](std::string_view device_id) -> std::unique_ptr<Input> { [](Core::System& system, std::string_view device_id) -> std::unique_ptr<Input> {
return std::make_unique<NullInput>(); return std::make_unique<NullInput>();
}, },
[] { return std::vector<std::string>{"None"}; }}, [] { return std::vector<std::string>{"None"}; }},

View file

@ -10,6 +10,10 @@
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
namespace Core {
class System;
}
namespace AudioCore { namespace AudioCore {
class Input; class Input;
@ -23,7 +27,7 @@ enum class InputType : u32 {
}; };
struct InputDetails { struct InputDetails {
using FactoryFn = std::unique_ptr<Input> (*)(std::string_view device_id); using FactoryFn = std::unique_ptr<Input> (*)(Core::System& system, std::string_view device_id);
using ListDevicesFn = std::vector<std::string> (*)(); using ListDevicesFn = std::vector<std::string> (*)();
/// Type of this input. /// Type of this input.

View file

@ -666,9 +666,11 @@ void System::ApplySettings() {
Service::MIC::ReloadMic(*this); Service::MIC::ReloadMic(*this);
} }
Service::PLGLDR::PLG_LDR::SetEnabled(Settings::values.plugin_loader_enabled.GetValue()); auto plg_ldr = Service::PLGLDR::GetService(*this);
Service::PLGLDR::PLG_LDR::SetAllowGameChangeState( if (plg_ldr) {
Settings::values.allow_plugin_loader.GetValue()); plg_ldr->SetEnabled(Settings::values.plugin_loader_enabled.GetValue());
plg_ldr->SetAllowGameChangeState(Settings::values.allow_plugin_loader.GetValue());
}
} }
template <class Archive> template <class Archive>

View file

@ -65,7 +65,7 @@ static bool ReadSection(std::vector<u8>& data_out, FileUtil::IOFile& file, std::
Loader::ResultStatus FileSys::Plugin3GXLoader::Load( Loader::ResultStatus FileSys::Plugin3GXLoader::Load(
Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, Kernel::Process& process, Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, Kernel::Process& process,
Kernel::KernelSystem& kernel) { Kernel::KernelSystem& kernel, Service::PLGLDR::PLG_LDR& plg_ldr) {
FileUtil::IOFile file(plg_context.plugin_path, "rb"); FileUtil::IOFile file(plg_context.plugin_path, "rb");
if (!file.IsOpen()) { if (!file.IsOpen()) {
LOG_ERROR(Service_PLGLDR, "Failed to load 3GX plugin. Not found: {}", LOG_ERROR(Service_PLGLDR, "Failed to load 3GX plugin. Not found: {}",
@ -158,12 +158,12 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Load(
return Loader::ResultStatus::Error; return Loader::ResultStatus::Error;
} }
return Map(plg_context, process, kernel); return Map(plg_context, process, kernel, plg_ldr);
} }
Loader::ResultStatus FileSys::Plugin3GXLoader::Map( Loader::ResultStatus FileSys::Plugin3GXLoader::Map(
Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, Kernel::Process& process, Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, Kernel::Process& process,
Kernel::KernelSystem& kernel) { Kernel::KernelSystem& kernel, Service::PLGLDR::PLG_LDR& plg_ldr) {
// Verify exe load checksum function is available // Verify exe load checksum function is available
if (exe_load_func.empty() && plg_context.load_exe_func.empty()) { if (exe_load_func.empty() && plg_context.load_exe_func.empty()) {
@ -195,7 +195,7 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Map(
return Loader::ResultStatus::ErrorMemoryAllocationFailed; return Loader::ResultStatus::ErrorMemoryAllocationFailed;
} }
auto backing_memory_fb = kernel.memory.GetFCRAMRef(*offset_fb); auto backing_memory_fb = kernel.memory.GetFCRAMRef(*offset_fb);
Service::PLGLDR::PLG_LDR::SetPluginFBAddr(Memory::FCRAM_PADDR + *offset_fb); plg_ldr.SetPluginFBAddr(Memory::FCRAM_PADDR + *offset_fb);
std::fill(backing_memory_fb.GetPtr(), backing_memory_fb.GetPtr() + _3GX_fb_size, 0); std::fill(backing_memory_fb.GetPtr(), backing_memory_fb.GetPtr() + _3GX_fb_size, 0);
auto vma_heap_fb = process.vm_manager.MapBackingMemory( auto vma_heap_fb = process.vm_manager.MapBackingMemory(

View file

@ -43,7 +43,8 @@ class FileBackend;
class Plugin3GXLoader { class Plugin3GXLoader {
public: public:
Loader::ResultStatus Load(Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, Loader::ResultStatus Load(Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context,
Kernel::Process& process, Kernel::KernelSystem& kernel); Kernel::Process& process, Kernel::KernelSystem& kernel,
Service::PLGLDR::PLG_LDR& plg_ldr);
struct PluginHeader { struct PluginHeader {
u32_le magic; u32_le magic;
@ -68,7 +69,8 @@ public:
private: private:
Loader::ResultStatus Map(Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, Loader::ResultStatus Map(Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context,
Kernel::Process& process, Kernel::KernelSystem& kernel); Kernel::Process& process, Kernel::KernelSystem& kernel,
Service::PLGLDR::PLG_LDR& plg_ldr);
static constexpr size_t bootloader_memory_size = 0x1000; static constexpr size_t bootloader_memory_size = 0x1000;
static void MapBootloader(Kernel::Process& process, Kernel::KernelSystem& kernel, static void MapBootloader(Kernel::Process& process, Kernel::KernelSystem& kernel,

View file

@ -9,7 +9,7 @@
namespace Frontend { namespace Frontend {
void RegisterDefaultApplets(Core::System& system) { void RegisterDefaultApplets(Core::System& system) {
system.RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>()); system.RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>(system));
system.RegisterMiiSelector(std::make_shared<DefaultMiiSelector>()); system.RegisterMiiSelector(std::make_shared<DefaultMiiSelector>());
} }
} // namespace Frontend } // namespace Frontend

View file

@ -144,10 +144,12 @@ const KeyboardData& SoftwareKeyboard::ReceiveData() {
return data; return data;
} }
DefaultKeyboard::DefaultKeyboard(Core::System& system_) : system(system_) {}
void DefaultKeyboard::Execute(const Frontend::KeyboardConfig& config_) { void DefaultKeyboard::Execute(const Frontend::KeyboardConfig& config_) {
SoftwareKeyboard::Execute(config_); SoftwareKeyboard::Execute(config_);
auto cfg = Service::CFG::GetModule(Core::System::GetInstance()); auto cfg = Service::CFG::GetModule(system);
std::string username = Common::UTF16ToUTF8(cfg->GetUsername()); std::string username = Common::UTF16ToUTF8(cfg->GetUsername());
switch (this->config.button_config) { switch (this->config.button_config) {
case ButtonConfig::None: case ButtonConfig::None:

View file

@ -8,6 +8,10 @@
#include <vector> #include <vector>
#include "common/assert.h" #include "common/assert.h"
namespace Core {
class System;
}
namespace Frontend { namespace Frontend {
enum class AcceptedInput { enum class AcceptedInput {
@ -137,8 +141,12 @@ protected:
class DefaultKeyboard final : public SoftwareKeyboard { class DefaultKeyboard final : public SoftwareKeyboard {
public: public:
explicit DefaultKeyboard(Core::System& system_);
void Execute(const KeyboardConfig& config) override; void Execute(const KeyboardConfig& config) override;
void ShowError(const std::string& error) override; void ShowError(const std::string& error) override;
private:
Core::System& system;
}; };
} // namespace Frontend } // namespace Frontend

View file

@ -5,97 +5,16 @@
#include <cstddef> #include <cstddef>
#include <memory> #include <memory>
#include <type_traits> #include <type_traits>
#include <unordered_map>
#include <utility> #include <utility>
#include "common/assert.h" #include "common/assert.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/applets/applet.h" #include "core/hle/applets/applet.h"
#include "core/hle/applets/erreula.h"
#include "core/hle/applets/mii_selector.h"
#include "core/hle/applets/mint.h"
#include "core/hle/applets/swkbd.h"
#include "core/hle/result.h" #include "core/hle/result.h"
namespace HLE::Applets { namespace HLE::Applets {
static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets;
/// The CoreTiming event identifier for the Applet update callback.
static Core::TimingEventType* applet_update_event = nullptr;
/// The interval at which the Applet update callback will be called, 16.6ms
static const u64 applet_update_interval_us = 16666;
Result Applet::Create(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload,
const std::shared_ptr<Service::APT::AppletManager>& manager) {
switch (id) {
case Service::APT::AppletId::SoftwareKeyboard1:
case Service::APT::AppletId::SoftwareKeyboard2:
applets[id] = std::make_shared<SoftwareKeyboard>(id, parent, preload, manager);
break;
case Service::APT::AppletId::Ed1:
case Service::APT::AppletId::Ed2:
applets[id] = std::make_shared<MiiSelector>(id, parent, preload, manager);
break;
case Service::APT::AppletId::Error:
case Service::APT::AppletId::Error2:
applets[id] = std::make_shared<ErrEula>(id, parent, preload, manager);
break;
case Service::APT::AppletId::Mint:
case Service::APT::AppletId::Mint2:
applets[id] = std::make_shared<Mint>(id, parent, preload, manager);
break;
default:
LOG_ERROR(Service_APT, "Could not create applet {}", id);
// TODO(Subv): Find the right error code
return Result(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported,
ErrorLevel::Permanent);
}
Service::APT::AppletAttributes attributes;
attributes.applet_pos.Assign(Service::APT::AppletPos::AutoLibrary);
attributes.is_home_menu.Assign(false);
const auto lock_handle_data = manager->GetLockHandle(attributes);
manager->Initialize(id, lock_handle_data->corrected_attributes);
manager->Enable(lock_handle_data->corrected_attributes);
if (preload) {
manager->FinishPreloadingLibraryApplet(id);
}
// Schedule the update event
Core::System::GetInstance().CoreTiming().ScheduleEvent(
usToCycles(applet_update_interval_us), applet_update_event, static_cast<u64>(id));
return ResultSuccess;
}
std::shared_ptr<Applet> Applet::Get(Service::APT::AppletId id) {
auto itr = applets.find(id);
if (itr != applets.end())
return itr->second;
return nullptr;
}
/// Handles updating the current Applet every time it's called.
static void AppletUpdateEvent(u64 applet_id, s64 cycles_late) {
const auto id = static_cast<Service::APT::AppletId>(applet_id);
const auto applet = Applet::Get(id);
ASSERT_MSG(applet != nullptr, "Applet doesn't exist! applet_id={:08X}", id);
if (applet->IsActive()) {
applet->Update();
}
// If the applet is still running after the last update, reschedule the event
if (applet->IsRunning()) {
Core::System::GetInstance().CoreTiming().ScheduleEvent(
usToCycles(applet_update_interval_us) - cycles_late, applet_update_event, applet_id);
} else {
// Otherwise the applet has terminated, in which case we should clean it up
applets[id] = nullptr;
}
}
bool Applet::IsRunning() const { bool Applet::IsRunning() const {
return is_running; return is_running;
} }
@ -140,13 +59,4 @@ void Applet::CloseApplet(std::shared_ptr<Kernel::Object> object, const std::vect
is_running = false; is_running = false;
} }
void Init() {
// Register the applet update callback
applet_update_event = Core::System::GetInstance().CoreTiming().RegisterEvent(
"HLE Applet Update Event", AppletUpdateEvent);
}
void Shutdown() {
Core::System::GetInstance().CoreTiming().RemoveEvent(applet_update_event);
}
} // namespace HLE::Applets } // namespace HLE::Applets

View file

@ -14,24 +14,6 @@ class Applet {
public: public:
virtual ~Applet() = default; virtual ~Applet() = default;
/**
* Creates an instance of the Applet subclass identified by the parameter.
* and stores it in a global map.
* @param id Id of the applet to create.
* @param parent Id of the applet's parent.
* @param preload Whether the applet is being preloaded.
* @returns Result Whether the operation was successful or not.
*/
static Result Create(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload,
const std::shared_ptr<Service::APT::AppletManager>& manager);
/**
* Retrieves the Applet instance identified by the specified id.
* @param id Id of the Applet to retrieve.
* @returns Requested Applet or nullptr if not found.
*/
static std::shared_ptr<Applet> Get(Service::APT::AppletId id);
/** /**
* Handles a parameter from the application. * Handles a parameter from the application.
* @param parameter Parameter data to handle. * @param parameter Parameter data to handle.
@ -55,9 +37,9 @@ public:
virtual void Update() = 0; virtual void Update() = 0;
protected: protected:
Applet(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, Applet(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent,
std::weak_ptr<Service::APT::AppletManager> manager) bool preload, std::weak_ptr<Service::APT::AppletManager> manager)
: id(id), parent(parent), preload(preload), manager(std::move(manager)) {} : system(system), id(id), parent(parent), preload(preload), manager(std::move(manager)) {}
/** /**
* Handles a parameter from the application. * Handles a parameter from the application.
@ -79,6 +61,8 @@ protected:
*/ */
virtual Result Finalize() = 0; virtual Result Finalize() = 0;
Core::System& system;
Service::APT::AppletId id; ///< Id of this Applet Service::APT::AppletId id; ///< Id of this Applet
Service::APT::AppletId parent; ///< Id of this Applet's parent Service::APT::AppletId parent; ///< Id of this Applet's parent
bool preload; ///< Whether the Applet is being preloaded. bool preload; ///< Whether the Applet is being preloaded.
@ -97,9 +81,4 @@ private:
std::weak_ptr<Service::APT::AppletManager> manager; std::weak_ptr<Service::APT::AppletManager> manager;
}; };
/// Initializes the HLE applets
void Init();
/// Shuts down the HLE applets
void Shutdown();
} // namespace HLE::Applets } // namespace HLE::Applets

View file

@ -28,7 +28,7 @@ Result ErrEula::ReceiveParameterImpl(const Service::APT::MessageParameter& param
// TODO: allocated memory never released // TODO: allocated memory never released
using Kernel::MemoryPermission; using Kernel::MemoryPermission;
// Create a SharedMemory that directly points to this heap block. // Create a SharedMemory that directly points to this heap block.
framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet( framebuffer_memory = system.Kernel().CreateSharedMemoryForApplet(
0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
"ErrEula Memory"); "ErrEula Memory");

View file

@ -11,9 +11,9 @@ namespace HLE::Applets {
class ErrEula final : public Applet { class ErrEula final : public Applet {
public: public:
explicit ErrEula(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, explicit ErrEula(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent,
std::weak_ptr<Service::APT::AppletManager> manager) bool preload, std::weak_ptr<Service::APT::AppletManager> manager)
: Applet(id, parent, preload, std::move(manager)) {} : Applet(system, id, parent, preload, std::move(manager)) {}
Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override;
Result Start(const Service::APT::MessageParameter& parameter) override; Result Start(const Service::APT::MessageParameter& parameter) override;

View file

@ -35,7 +35,7 @@ Result MiiSelector::ReceiveParameterImpl(const Service::APT::MessageParameter& p
using Kernel::MemoryPermission; using Kernel::MemoryPermission;
// Create a SharedMemory that directly points to this heap block. // Create a SharedMemory that directly points to this heap block.
framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet( framebuffer_memory = system.Kernel().CreateSharedMemoryForApplet(
0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
"MiiSelector Memory"); "MiiSelector Memory");
@ -57,7 +57,7 @@ Result MiiSelector::Start(const Service::APT::MessageParameter& parameter) {
std::memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); std::memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
using namespace Frontend; using namespace Frontend;
frontend_applet = Core::System::GetInstance().GetMiiSelector(); frontend_applet = system.GetMiiSelector();
ASSERT(frontend_applet); ASSERT(frontend_applet);
MiiSelectorConfig frontend_config = ToFrontendConfig(config); MiiSelectorConfig frontend_config = ToFrontendConfig(config);

View file

@ -62,9 +62,9 @@ ASSERT_REG_POSITION(guest_mii_name, 0x6C);
class MiiSelector final : public Applet { class MiiSelector final : public Applet {
public: public:
MiiSelector(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, MiiSelector(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent,
std::weak_ptr<Service::APT::AppletManager> manager) bool preload, std::weak_ptr<Service::APT::AppletManager> manager)
: Applet(id, parent, preload, std::move(manager)) {} : Applet(system, id, parent, preload, std::move(manager)) {}
Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override;
Result Start(const Service::APT::MessageParameter& parameter) override; Result Start(const Service::APT::MessageParameter& parameter) override;

View file

@ -28,7 +28,7 @@ Result Mint::ReceiveParameterImpl(const Service::APT::MessageParameter& paramete
// TODO: allocated memory never released // TODO: allocated memory never released
using Kernel::MemoryPermission; using Kernel::MemoryPermission;
// Create a SharedMemory that directly points to this heap block. // Create a SharedMemory that directly points to this heap block.
framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet( framebuffer_memory = system.Kernel().CreateSharedMemoryForApplet(
0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
"Mint Memory"); "Mint Memory");

View file

@ -11,9 +11,9 @@ namespace HLE::Applets {
class Mint final : public Applet { class Mint final : public Applet {
public: public:
explicit Mint(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, explicit Mint(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent,
std::weak_ptr<Service::APT::AppletManager> manager) bool preload, std::weak_ptr<Service::APT::AppletManager> manager)
: Applet(id, parent, preload, std::move(manager)) {} : Applet(system, id, parent, preload, std::move(manager)) {}
Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override;
Result Start(const Service::APT::MessageParameter& parameter) override; Result Start(const Service::APT::MessageParameter& parameter) override;

View file

@ -32,7 +32,7 @@ Result SoftwareKeyboard::ReceiveParameterImpl(Service::APT::MessageParameter con
using Kernel::MemoryPermission; using Kernel::MemoryPermission;
// Create a SharedMemory that directly points to this heap block. // Create a SharedMemory that directly points to this heap block.
framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet( framebuffer_memory = system.Kernel().CreateSharedMemoryForApplet(
0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
"SoftwareKeyboard Memory"); "SoftwareKeyboard Memory");
@ -99,7 +99,7 @@ Result SoftwareKeyboard::Start(Service::APT::MessageParameter const& parameter)
DrawScreenKeyboard(); DrawScreenKeyboard();
using namespace Frontend; using namespace Frontend;
frontend_applet = Core::System::GetInstance().GetSoftwareKeyboard(); frontend_applet = system.GetSoftwareKeyboard();
ASSERT(frontend_applet); ASSERT(frontend_applet);
frontend_applet->Execute(ToFrontendConfig(config)); frontend_applet->Execute(ToFrontendConfig(config));

View file

@ -175,9 +175,9 @@ static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config
class SoftwareKeyboard final : public Applet { class SoftwareKeyboard final : public Applet {
public: public:
SoftwareKeyboard(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload, SoftwareKeyboard(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent,
std::weak_ptr<Service::APT::AppletManager> manager) bool preload, std::weak_ptr<Service::APT::AppletManager> manager)
: Applet(id, parent, preload, std::move(manager)) {} : Applet(system, id, parent, preload, std::move(manager)) {}
Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override; Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override;
Result Start(const Service::APT::MessageParameter& parameter) override; Result Start(const Service::APT::MessageParameter& parameter) override;

View file

@ -20,6 +20,9 @@
#include "core/hle/service/soc/soc_u.h" #include "core/hle/service/soc/soc_u.h"
#include "core/memory.h" #include "core/memory.h"
SERIALIZE_EXPORT_IMPL(Service::AC::Module)
SERVICE_CONSTRUCT_IMPL(Service::AC::Module)
namespace Service::AC { namespace Service::AC {
void Module::Interface::CreateDefaultConfig(Kernel::HLERequestContext& ctx) { void Module::Interface::CreateDefaultConfig(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
@ -96,7 +99,7 @@ void Module::Interface::GetWifiStatus(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
bool can_reach_internet = false; bool can_reach_internet = false;
std::shared_ptr<SOC::SOC_U> socu_module = SOC::GetService(Core::System::GetInstance()); std::shared_ptr<SOC::SOC_U> socu_module = SOC::GetService(ac->system);
if (socu_module) { if (socu_module) {
can_reach_internet = socu_module->GetDefaultInterfaceInfo().has_value(); can_reach_internet = socu_module->GetDefaultInterfaceInfo().has_value();
} }
@ -194,11 +197,13 @@ Module::Interface::Interface(std::shared_ptr<Module> ac, const char* name, u32 m
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
auto ac = std::make_shared<Module>(); auto ac = std::make_shared<Module>(system);
std::make_shared<AC_I>(ac)->InstallAsService(service_manager); std::make_shared<AC_I>(ac)->InstallAsService(service_manager);
std::make_shared<AC_U>(ac)->InstallAsService(service_manager); std::make_shared<AC_U>(ac)->InstallAsService(service_manager);
} }
Module::Module(Core::System& system_) : system(system_) {}
template <class Archive> template <class Archive>
void Module::serialize(Archive& ar, const unsigned int) { void Module::serialize(Archive& ar, const unsigned int) {
ar& ac_connected; ar& ac_connected;
@ -207,7 +212,6 @@ void Module::serialize(Archive& ar, const unsigned int) {
ar& disconnect_event; ar& disconnect_event;
// default_config is never written to // default_config is never written to
} }
SERIALIZE_IMPL(Module)
} // namespace Service::AC } // namespace Service::AC
SERIALIZE_IMPL(Service::AC::Module)

View file

@ -19,6 +19,9 @@ class Event;
namespace Service::AC { namespace Service::AC {
class Module final { class Module final {
public: public:
explicit Module(Core::System& system_);
~Module() = default;
class Interface : public ServiceFramework<Interface> { class Interface : public ServiceFramework<Interface> {
public: public:
Interface(std::shared_ptr<Module> ac, const char* name, u32 max_session); Interface(std::shared_ptr<Module> ac, const char* name, u32 max_session);
@ -169,11 +172,16 @@ protected:
std::shared_ptr<Kernel::Event> disconnect_event; std::shared_ptr<Kernel::Event> disconnect_event;
private: private:
Core::System& system;
template <class Archive> template <class Archive>
void serialize(Archive& ar, const unsigned int file_version); void serialize(Archive& ar, const unsigned int);
friend class boost::serialization::access; friend class boost::serialization::access;
}; };
void InstallInterfaces(Core::System& system); void InstallInterfaces(Core::System& system);
} // namespace Service::AC } // namespace Service::AC
BOOST_CLASS_EXPORT_KEY(Service::AC::Module)
SERVICE_CONSTRUCT(Service::AC::Module)

View file

@ -9,6 +9,7 @@
#include <cryptopp/modes.h> #include <cryptopp/modes.h>
#include <fmt/format.h> #include <fmt/format.h>
#include "common/alignment.h" #include "common/alignment.h"
#include "common/archives.h"
#include "common/common_paths.h" #include "common/common_paths.h"
#include "common/file_util.h" #include "common/file_util.h"
#include "common/logging/log.h" #include "common/logging/log.h"
@ -33,6 +34,9 @@
#include "core/loader/smdh.h" #include "core/loader/smdh.h"
#include "core/nus_download.h" #include "core/nus_download.h"
SERIALIZE_EXPORT_IMPL(Service::AM::Module)
SERVICE_CONSTRUCT_IMPL(Service::AM::Module)
namespace Service::AM { namespace Service::AM {
constexpr u16 PLATFORM_CTR = 0x0004; constexpr u16 PLATFORM_CTR = 0x0004;
@ -81,8 +85,9 @@ public:
std::vector<CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption> content; std::vector<CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption> content;
}; };
CIAFile::CIAFile(Service::FS::MediaType media_type) CIAFile::CIAFile(Core::System& system_, Service::FS::MediaType media_type)
: media_type(media_type), decryption_state(std::make_unique<DecryptionState>()) {} : system(system_), media_type(media_type),
decryption_state(std::make_unique<DecryptionState>()) {}
CIAFile::~CIAFile() { CIAFile::~CIAFile() {
Close(); Close();
@ -361,8 +366,7 @@ bool CIAFile::Close() const {
// are closed. // are closed.
std::string to_delete = std::string to_delete =
GetTitleContentPath(media_type, old_tmd.GetTitleID(), old_index); GetTitleContentPath(media_type, old_tmd.GetTitleID(), old_index);
if (!(Core::System::GetInstance().IsPoweredOn() && if (!system.IsPoweredOn() || !system.SetSelfDelete(to_delete)) {
Core::System::GetInstance().SetSelfDelete(to_delete))) {
FileUtil::Delete(to_delete); FileUtil::Delete(to_delete);
} }
} }
@ -425,6 +429,7 @@ InstallStatus InstallCIA(const std::string& path,
FileSys::CIAContainer container; FileSys::CIAContainer container;
if (container.Load(path) == Loader::ResultStatus::Success) { if (container.Load(path) == Loader::ResultStatus::Success) {
Service::AM::CIAFile installFile( Service::AM::CIAFile installFile(
Core::System::GetInstance(),
Service::AM::GetTitleMediaType(container.GetTitleMetadata().GetTitleID())); Service::AM::GetTitleMediaType(container.GetTitleMetadata().GetTitleID()));
bool title_key_available = container.GetTicket().GetTitleKey().has_value(); bool title_key_available = container.GetTicket().GetTitleKey().has_value();
@ -502,7 +507,7 @@ InstallStatus InstallCIA(const std::string& path,
InstallStatus InstallFromNus(u64 title_id, int version) { InstallStatus InstallFromNus(u64 title_id, int version) {
LOG_DEBUG(Service_AM, "Downloading {:X}", title_id); LOG_DEBUG(Service_AM, "Downloading {:X}", title_id);
CIAFile install_file{GetTitleMediaType(title_id)}; CIAFile install_file{Core::System::GetInstance(), GetTitleMediaType(title_id)};
std::string path = fmt::format("/ccs/download/{:016X}/tmd", title_id); std::string path = fmt::format("/ccs/download/{:016X}/tmd", title_id);
if (version != -1) { if (version != -1) {
@ -1327,7 +1332,7 @@ void Module::Interface::BeginImportProgram(Kernel::HLERequestContext& ctx) {
// Citra will store contents out to sdmc/nand // Citra will store contents out to sdmc/nand
const FileSys::Path cia_path = {}; const FileSys::Path cia_path = {};
auto file = std::make_shared<Service::FS::File>( auto file = std::make_shared<Service::FS::File>(
am->kernel, std::make_unique<CIAFile>(media_type), cia_path); am->system.Kernel(), std::make_unique<CIAFile>(am->system, media_type), cia_path);
am->cia_installing = true; am->cia_installing = true;
@ -1354,7 +1359,7 @@ void Module::Interface::BeginImportProgramTemporarily(Kernel::HLERequestContext&
// contents out to sdmc/nand // contents out to sdmc/nand
const FileSys::Path cia_path = {}; const FileSys::Path cia_path = {};
auto file = std::make_shared<Service::FS::File>( auto file = std::make_shared<Service::FS::File>(
am->kernel, std::make_unique<CIAFile>(FS::MediaType::NAND), cia_path); am->system.Kernel(), std::make_unique<CIAFile>(am->system, FS::MediaType::NAND), cia_path);
am->cia_installing = true; am->cia_installing = true;
@ -1769,8 +1774,8 @@ void Module::Interface::BeginImportTicket(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
// Create our TicketFile handle for the app to write to // Create our TicketFile handle for the app to write to
auto file = std::make_shared<Service::FS::File>(am->kernel, std::make_unique<TicketFile>(), auto file = std::make_shared<Service::FS::File>(
FileSys::Path{}); am->system.Kernel(), std::make_unique<TicketFile>(), FileSys::Path{});
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(ResultSuccess); // No error rb.Push(ResultSuccess); // No error
@ -1789,13 +1794,19 @@ void Module::Interface::EndImportTicket(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called"); LOG_WARNING(Service_AM, "(STUBBED) called");
} }
Module::Module(Core::System& system) : kernel(system.Kernel()) { template <class Archive>
void Module::serialize(Archive& ar, const unsigned int) {
ar& cia_installing;
ar& am_title_list;
ar& system_updater_mutex;
}
SERIALIZE_IMPL(Module)
Module::Module(Core::System& system) : system(system) {
ScanForAllTitles(); ScanForAllTitles();
system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex"); system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex");
} }
Module::Module(Kernel::KernelSystem& kernel) : kernel(kernel) {}
Module::~Module() = default; Module::~Module() = default;
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {

View file

@ -11,7 +11,6 @@
#include <vector> #include <vector>
#include <boost/serialization/array.hpp> #include <boost/serialization/array.hpp>
#include <boost/serialization/shared_ptr.hpp> #include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/vector.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/construct.h" #include "common/construct.h"
#include "common/swap.h" #include "common/swap.h"
@ -80,7 +79,7 @@ using ProgressCallback = void(std::size_t, std::size_t);
// A file handled returned for CIAs to be written into and subsequently installed. // A file handled returned for CIAs to be written into and subsequently installed.
class CIAFile final : public FileSys::FileBackend { class CIAFile final : public FileSys::FileBackend {
public: public:
explicit CIAFile(Service::FS::MediaType media_type); explicit CIAFile(Core::System& system_, Service::FS::MediaType media_type);
~CIAFile(); ~CIAFile();
ResultVal<std::size_t> Read(u64 offset, std::size_t length, u8* buffer) const override; ResultVal<std::size_t> Read(u64 offset, std::size_t length, u8* buffer) const override;
@ -95,6 +94,8 @@ public:
void Flush() const override; void Flush() const override;
private: private:
Core::System& system;
// Whether it's installing an update, and what step of installation it is at // Whether it's installing an update, and what step of installation it is at
bool is_update = false; bool is_update = false;
CIAInstallState install_state = CIAInstallState::InstallStarted; CIAInstallState install_state = CIAInstallState::InstallStarted;
@ -706,8 +707,6 @@ public:
}; };
private: private:
explicit Module(Kernel::KernelSystem& kernel);
/** /**
* Scans the for titles in a storage medium for listing. * Scans the for titles in a storage medium for listing.
* @param media_type the storage medium to scan * @param media_type the storage medium to scan
@ -719,27 +718,13 @@ private:
*/ */
void ScanForAllTitles(); void ScanForAllTitles();
Kernel::KernelSystem& kernel; Core::System& system;
bool cia_installing = false; bool cia_installing = false;
std::array<std::vector<u64_le>, 3> am_title_list; std::array<std::vector<u64_le>, 3> am_title_list;
std::shared_ptr<Kernel::Mutex> system_updater_mutex; std::shared_ptr<Kernel::Mutex> system_updater_mutex;
template <class Archive> template <class Archive>
void serialize(Archive& ar, const unsigned int) { void serialize(Archive& ar, const unsigned int);
ar& cia_installing;
ar& am_title_list;
ar& system_updater_mutex;
}
template <class Archive>
static void load_construct(Archive& ar, Module* t, const unsigned int file_version) {
::new (t) Module(Core::Global<Kernel::KernelSystem>());
}
template <class Archive>
void save_construct(Archive& ar, const unsigned int file_version) const {}
friend class ::construct_access;
friend class boost::serialization::access; friend class boost::serialization::access;
}; };
@ -747,4 +732,5 @@ void InstallInterfaces(Core::System& system);
} // namespace Service::AM } // namespace Service::AM
BOOST_SERIALIZATION_CONSTRUCT(Service::AM::Module); BOOST_CLASS_EXPORT_KEY(Service::AM::Module)
SERVICE_CONSTRUCT(Service::AM::Module)

View file

@ -8,6 +8,10 @@
#include "core/core.h" #include "core/core.h"
#include "core/frontend/input.h" #include "core/frontend/input.h"
#include "core/hle/applets/applet.h" #include "core/hle/applets/applet.h"
#include "core/hle/applets/erreula.h"
#include "core/hle/applets/mii_selector.h"
#include "core/hle/applets/mint.h"
#include "core/hle/applets/swkbd.h"
#include "core/hle/service/am/am.h" #include "core/hle/service/am/am.h"
#include "core/hle/service/apt/applet_manager.h" #include "core/hle/service/apt/applet_manager.h"
#include "core/hle/service/apt/errors.h" #include "core/hle/service/apt/errors.h"
@ -22,6 +26,8 @@ namespace Service::APT {
/// The interval at which the home button update callback will be called, 16.6ms /// The interval at which the home button update callback will be called, 16.6ms
static constexpr u64 button_update_interval_us = 16666; static constexpr u64 button_update_interval_us = 16666;
/// The interval at which the HLE Applet update callback will be called, 16.6ms.
static constexpr u64 hle_applet_update_interval_us = 16666;
struct AppletTitleData { struct AppletTitleData {
// There are two possible applet ids for each applet. // There are two possible applet ids for each applet.
@ -222,8 +228,8 @@ void AppletManager::CancelAndSendParameter(const MessageParameter& parameter) {
parameter.sender_id, parameter.destination_id, parameter.signal, parameter.buffer.size()); parameter.sender_id, parameter.destination_id, parameter.signal, parameter.buffer.size());
// If the applet is being HLEd, send directly to the applet. // If the applet is being HLEd, send directly to the applet.
if (auto dest_applet = HLE::Applets::Applet::Get(parameter.destination_id)) { if (hle_applets.contains(parameter.destination_id)) {
dest_applet->ReceiveParameter(parameter); hle_applets[parameter.destination_id]->ReceiveParameter(parameter);
} else { } else {
// Otherwise, send the parameter the LLE way. // Otherwise, send the parameter the LLE way.
next_parameter = parameter; next_parameter = parameter;
@ -497,6 +503,52 @@ void AppletManager::SendNotificationToAll(Notification notification) {
} }
} }
Result AppletManager::CreateHLEApplet(AppletId id, AppletId parent, bool preload) {
switch (id) {
case AppletId::SoftwareKeyboard1:
case AppletId::SoftwareKeyboard2:
hle_applets[id] = std::make_shared<HLE::Applets::SoftwareKeyboard>(
system, id, parent, preload, shared_from_this());
break;
case AppletId::Ed1:
case AppletId::Ed2:
hle_applets[id] = std::make_shared<HLE::Applets::MiiSelector>(system, id, parent, preload,
shared_from_this());
break;
case AppletId::Error:
case AppletId::Error2:
hle_applets[id] = std::make_shared<HLE::Applets::ErrEula>(system, id, parent, preload,
shared_from_this());
break;
case AppletId::Mint:
case AppletId::Mint2:
hle_applets[id] =
std::make_shared<HLE::Applets::Mint>(system, id, parent, preload, shared_from_this());
break;
default:
LOG_ERROR(Service_APT, "Could not create applet {}", id);
// TODO(Subv): Find the right error code
return Result(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported,
ErrorLevel::Permanent);
}
AppletAttributes attributes;
attributes.applet_pos.Assign(AppletPos::AutoLibrary);
attributes.is_home_menu.Assign(false);
const auto lock_handle_data = GetLockHandle(attributes);
Initialize(id, lock_handle_data->corrected_attributes);
Enable(lock_handle_data->corrected_attributes);
if (preload) {
FinishPreloadingLibraryApplet(id);
}
// Schedule the update event
system.CoreTiming().ScheduleEvent(usToCycles(hle_applet_update_interval_us),
hle_applet_update_event, static_cast<u64>(id));
return ResultSuccess;
}
Result AppletManager::PrepareToStartLibraryApplet(AppletId applet_id) { Result AppletManager::PrepareToStartLibraryApplet(AppletId applet_id) {
// The real APT service returns an error if there's a pending APT parameter when this function // The real APT service returns an error if there's a pending APT parameter when this function
// is called. // is called.
@ -523,14 +575,13 @@ Result AppletManager::PrepareToStartLibraryApplet(AppletId applet_id) {
} }
// If we weren't able to load the native applet title, try to fallback to an HLE implementation. // If we weren't able to load the native applet title, try to fallback to an HLE implementation.
auto applet = HLE::Applets::Applet::Get(applet_id); if (hle_applets.contains(applet_id)) {
if (applet) { LOG_WARNING(Service_APT, "Applet has already been started id={:03X}", applet_id);
LOG_WARNING(Service_APT, "applet has already been started id={:03X}", applet_id);
return ResultSuccess; return ResultSuccess;
} else { } else {
auto parent = GetAppletSlotId(last_library_launcher_slot); auto parent = GetAppletSlotId(last_library_launcher_slot);
LOG_DEBUG(Service_APT, "Creating HLE applet {:03X} with parent {:03X}", applet_id, parent); LOG_DEBUG(Service_APT, "Creating HLE applet {:03X} with parent {:03X}", applet_id, parent);
return HLE::Applets::Applet::Create(applet_id, parent, false, shared_from_this()); return CreateHLEApplet(applet_id, parent, false);
} }
} }
@ -551,14 +602,13 @@ Result AppletManager::PreloadLibraryApplet(AppletId applet_id) {
} }
// If we weren't able to load the native applet title, try to fallback to an HLE implementation. // If we weren't able to load the native applet title, try to fallback to an HLE implementation.
auto applet = HLE::Applets::Applet::Get(applet_id); if (hle_applets.contains(applet_id)) {
if (applet) { LOG_WARNING(Service_APT, "Applet has already been started id={:08X}", applet_id);
LOG_WARNING(Service_APT, "applet has already been started id={:08X}", applet_id);
return ResultSuccess; return ResultSuccess;
} else { } else {
auto parent = GetAppletSlotId(last_library_launcher_slot); auto parent = GetAppletSlotId(last_library_launcher_slot);
LOG_DEBUG(Service_APT, "Creating HLE applet {:03X} with parent {:03X}", applet_id, parent); LOG_DEBUG(Service_APT, "Creating HLE applet {:03X} with parent {:03X}", applet_id, parent);
return HLE::Applets::Applet::Create(applet_id, parent, true, shared_from_this()); return CreateHLEApplet(applet_id, parent, true);
} }
} }
@ -1387,7 +1437,7 @@ static void CaptureFrameBuffer(Core::System& system, u32 capture_offset, VAddr s
return; return;
} }
Memory::RasterizerFlushVirtualRegion(src, GSP::FRAMEBUFFER_WIDTH * height * bpp, system.Memory().RasterizerFlushVirtualRegion(src, GSP::FRAMEBUFFER_WIDTH * height * bpp,
Memory::FlushMode::Flush); Memory::FlushMode::Flush);
// Address in VRAM that APT copies framebuffer captures to. // Address in VRAM that APT copies framebuffer captures to.
@ -1416,8 +1466,8 @@ static void CaptureFrameBuffer(Core::System& system, u32 capture_offset, VAddr s
} }
} }
Memory::RasterizerFlushVirtualRegion(dst_vaddr, GSP::FRAMEBUFFER_WIDTH_POW2 * height * bpp, system.Memory().RasterizerFlushVirtualRegion(
Memory::FlushMode::Invalidate); dst_vaddr, GSP::FRAMEBUFFER_WIDTH_POW2 * height * bpp, Memory::FlushMode::Invalidate);
} }
void AppletManager::CaptureFrameBuffers() { void AppletManager::CaptureFrameBuffers() {
@ -1441,6 +1491,30 @@ void AppletManager::LoadInputDevices() {
Settings::values.current_input_profile.buttons[Settings::NativeButton::Power]); Settings::values.current_input_profile.buttons[Settings::NativeButton::Power]);
} }
/// Handles updating the current Applet every time it's called.
void AppletManager::HLEAppletUpdateEvent(std::uintptr_t user_data, s64 cycles_late) {
const auto id = static_cast<AppletId>(user_data);
if (!hle_applets.contains(id)) {
// Dead applet, exit event loop.
LOG_WARNING(Service_APT, "Attempted to update dead applet id={:03X}", id);
return;
}
const auto applet = hle_applets[id];
if (applet->IsActive()) {
applet->Update();
}
// If the applet is still running after the last update, reschedule the event
if (applet->IsRunning()) {
system.CoreTiming().ScheduleEvent(usToCycles(hle_applet_update_interval_us) - cycles_late,
hle_applet_update_event, user_data);
} else {
// Otherwise the applet has terminated, in which case we should clean it up
hle_applets[id] = nullptr;
}
}
void AppletManager::ButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late) { void AppletManager::ButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late) {
if (is_device_reload_pending.exchange(false)) { if (is_device_reload_pending.exchange(false)) {
LoadInputDevices(); LoadInputDevices();
@ -1485,7 +1559,10 @@ AppletManager::AppletManager(Core::System& system) : system(system) {
slot_data.parameter_event = slot_data.parameter_event =
system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "APT:Parameter"); system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "APT:Parameter");
} }
HLE::Applets::Init(); hle_applet_update_event = system.CoreTiming().RegisterEvent(
"HLE Applet Update Event", [this](std::uintptr_t user_data, s64 cycles_late) {
HLEAppletUpdateEvent(user_data, cycles_late);
});
button_update_event = system.CoreTiming().RegisterEvent( button_update_event = system.CoreTiming().RegisterEvent(
"APT Button Update Event", [this](std::uintptr_t user_data, s64 cycles_late) { "APT Button Update Event", [this](std::uintptr_t user_data, s64 cycles_late) {
ButtonUpdateEvent(user_data, cycles_late); ButtonUpdateEvent(user_data, cycles_late);
@ -1494,7 +1571,8 @@ AppletManager::AppletManager(Core::System& system) : system(system) {
} }
AppletManager::~AppletManager() { AppletManager::~AppletManager() {
HLE::Applets::Shutdown(); system.CoreTiming().RemoveEvent(hle_applet_update_event);
system.CoreTiming().RemoveEvent(button_update_event);
} }
void AppletManager::ReloadInputDevices() { void AppletManager::ReloadInputDevices() {

View file

@ -23,6 +23,10 @@ namespace Core {
class System; class System;
} }
namespace HLE::Applets {
class Applet;
}
namespace Service::APT { namespace Service::APT {
/// Signals used by APT functions /// Signals used by APT functions
@ -291,7 +295,6 @@ public:
ResultVal<Notification> InquireNotification(AppletId app_id); ResultVal<Notification> InquireNotification(AppletId app_id);
Result SendNotification(Notification notification); Result SendNotification(Notification notification);
void SendNotificationToAll(Notification notification);
Result PrepareToStartLibraryApplet(AppletId applet_id); Result PrepareToStartLibraryApplet(AppletId applet_id);
Result PreloadLibraryApplet(AppletId applet_id); Result PreloadLibraryApplet(AppletId applet_id);
@ -481,6 +484,9 @@ private:
// It also affects the results of APT:GetTargetPlatform and APT:GetApplicationRunningMode. // It also affects the results of APT:GetTargetPlatform and APT:GetApplicationRunningMode.
bool new_3ds_mode_blocked = false; bool new_3ds_mode_blocked = false;
std::unordered_map<AppletId, std::shared_ptr<HLE::Applets::Applet>> hle_applets;
Core::TimingEventType* hle_applet_update_event;
Core::TimingEventType* button_update_event; Core::TimingEventType* button_update_event;
std::atomic<bool> is_device_reload_pending{true}; std::atomic<bool> is_device_reload_pending{true};
std::unique_ptr<Input::ButtonDevice> home_button; std::unique_ptr<Input::ButtonDevice> home_button;
@ -506,10 +512,15 @@ private:
/// otherwise it queues for sending when the application registers itself with APT::Enable. /// otherwise it queues for sending when the application registers itself with APT::Enable.
void SendApplicationParameterAfterRegistration(const MessageParameter& parameter); void SendApplicationParameterAfterRegistration(const MessageParameter& parameter);
void SendNotificationToAll(Notification notification);
void EnsureHomeMenuLoaded(); void EnsureHomeMenuLoaded();
void CaptureFrameBuffers(); void CaptureFrameBuffers();
Result CreateHLEApplet(AppletId id, AppletId parent, bool preload);
void HLEAppletUpdateEvent(std::uintptr_t user_data, s64 cycles_late);
void LoadInputDevices(); void LoadInputDevices();
void ButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late); void ButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late);

View file

@ -1133,8 +1133,7 @@ void Module::APTInterface::GetProgramId(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
auto fs_user = auto fs_user = apt->system.ServiceManager().GetService<Service::FS::FS_USER>("fs:USER");
Core::System::GetInstance().ServiceManager().GetService<Service::FS::FS_USER>("fs:USER");
ASSERT_MSG(fs_user != nullptr, "fs:USER service is missing."); ASSERT_MSG(fs_user != nullptr, "fs:USER service is missing.");
auto program_info_result = fs_user->GetProgramLaunchInfo(process_id); auto program_info_result = fs_user->GetProgramLaunchInfo(process_id);

View file

@ -517,7 +517,7 @@ void Y2R_U::StartConversion(Kernel::HLERequestContext& ctx) {
// dst_image_size would seem to be perfect for this, but it doesn't include the gap :( // dst_image_size would seem to be perfect for this, but it doesn't include the gap :(
u32 total_output_size = u32 total_output_size =
conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap); conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap);
Memory::RasterizerFlushVirtualRegion(conversion.dst.address, total_output_size, system.Memory().RasterizerFlushVirtualRegion(conversion.dst.address, total_output_size,
Memory::FlushMode::FlushAndInvalidate); Memory::FlushMode::FlushAndInvalidate);
HW::Y2R::PerformConversion(system.Memory(), conversion); HW::Y2R::PerformConversion(system.Memory(), conversion);

View file

@ -477,9 +477,10 @@ static void CopyFrameBuffer(Core::System& system, VAddr dst, VAddr src, u32 stri
return; return;
} }
Memory::RasterizerFlushVirtualRegion(src, stride * lines, Memory::FlushMode::Flush); system.Memory().RasterizerFlushVirtualRegion(src, stride * lines, Memory::FlushMode::Flush);
std::memcpy(dst_ptr, src_ptr, stride * lines); std::memcpy(dst_ptr, src_ptr, stride * lines);
Memory::RasterizerFlushVirtualRegion(dst, stride * lines, Memory::FlushMode::Invalidate); system.Memory().RasterizerFlushVirtualRegion(dst, stride * lines,
Memory::FlushMode::Invalidate);
} }
void GSP_GPU::SaveVramSysArea(Kernel::HLERequestContext& ctx) { void GSP_GPU::SaveVramSysArea(Kernel::HLERequestContext& ctx) {
@ -497,7 +498,7 @@ void GSP_GPU::SaveVramSysArea(Kernel::HLERequestContext& ctx) {
LOG_INFO(Service_GSP, "called"); LOG_INFO(Service_GSP, "called");
// TODO: This should also save LCD register state. // TODO: This should also save LCD register state.
Memory::RasterizerFlushVirtualRegion(Memory::VRAM_VADDR, Memory::VRAM_SIZE, system.Memory().RasterizerFlushVirtualRegion(Memory::VRAM_VADDR, Memory::VRAM_SIZE,
Memory::FlushMode::Flush); Memory::FlushMode::Flush);
const auto vram = system.Memory().GetPointer(Memory::VRAM_VADDR); const auto vram = system.Memory().GetPointer(Memory::VRAM_VADDR);
saved_vram.emplace(std::vector<u8>(Memory::VRAM_SIZE)); saved_vram.emplace(std::vector<u8>(Memory::VRAM_SIZE));
@ -548,7 +549,7 @@ void GSP_GPU::RestoreVramSysArea(Kernel::HLERequestContext& ctx) {
// TODO: This should also restore LCD register state. // TODO: This should also restore LCD register state.
auto vram = system.Memory().GetPointer(Memory::VRAM_VADDR); auto vram = system.Memory().GetPointer(Memory::VRAM_VADDR);
std::memcpy(vram, saved_vram.get().data(), Memory::VRAM_SIZE); std::memcpy(vram, saved_vram.get().data(), Memory::VRAM_SIZE);
Memory::RasterizerFlushVirtualRegion(Memory::VRAM_VADDR, Memory::VRAM_SIZE, system.Memory().RasterizerFlushVirtualRegion(Memory::VRAM_VADDR, Memory::VRAM_SIZE,
Memory::FlushMode::Invalidate); Memory::FlushMode::Invalidate);
} }

View file

@ -135,7 +135,7 @@ private:
}; };
struct MIC_U::Impl { struct MIC_U::Impl {
explicit Impl(Core::System& system) : timing(system.CoreTiming()) { explicit Impl(Core::System& system) : system(system), timing(system.CoreTiming()) {
buffer_full_event = buffer_full_event =
system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "MIC_U::buffer_full_event"); system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "MIC_U::buffer_full_event");
buffer_write_event = timing.RegisterEvent( buffer_write_event = timing.RegisterEvent(
@ -376,7 +376,7 @@ struct MIC_U::Impl {
} }
mic = AudioCore::GetInputDetails(Settings::values.input_type.GetValue()) mic = AudioCore::GetInputDetails(Settings::values.input_type.GetValue())
.create_input(Settings::values.input_device.GetValue()); .create_input(system, Settings::values.input_device.GetValue());
if (was_sampling) { if (was_sampling) {
StartSampling(); StartSampling();
} }
@ -392,6 +392,7 @@ struct MIC_U::Impl {
bool allow_shell_closed = false; bool allow_shell_closed = false;
bool clamp = false; bool clamp = false;
std::unique_ptr<AudioCore::Input> mic; std::unique_ptr<AudioCore::Input> mic;
Core::System& system;
Core::Timing& timing; Core::Timing& timing;
State state{}; State state{};
Encoding encoding{}; Encoding encoding{};

View file

@ -36,15 +36,13 @@
#include "core/loader/loader.h" #include "core/loader/loader.h"
SERIALIZE_EXPORT_IMPL(Service::PLGLDR::PLG_LDR) SERIALIZE_EXPORT_IMPL(Service::PLGLDR::PLG_LDR)
SERVICE_CONSTRUCT_IMPL(Service::PLGLDR::PLG_LDR)
namespace Service::PLGLDR { namespace Service::PLGLDR {
const Kernel::CoreVersion PLG_LDR::plgldr_version = Kernel::CoreVersion(1, 0, 0); static const Kernel::CoreVersion plgldr_version = Kernel::CoreVersion(1, 0, 0);
PLG_LDR::PluginLoaderContext PLG_LDR::plgldr_context;
bool PLG_LDR::allow_game_change = true;
PAddr PLG_LDR::plugin_fb_addr = 0;
PLG_LDR::PLG_LDR() : ServiceFramework{"plg:ldr", 1} { PLG_LDR::PLG_LDR(Core::System& system_) : ServiceFramework{"plg:ldr", 1}, system(system_) {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
// clang-format off // clang-format off
{0x0001, nullptr, "LoadPlugin"}, {0x0001, nullptr, "LoadPlugin"},
@ -67,6 +65,33 @@ PLG_LDR::PLG_LDR() : ServiceFramework{"plg:ldr", 1} {
plgldr_context.plugin_loaded = false; plgldr_context.plugin_loaded = false;
} }
template <class Archive>
void PLG_LDR::PluginLoaderContext::serialize(Archive& ar, const unsigned int) {
ar& is_enabled;
ar& plugin_loaded;
ar& is_default_path;
ar& plugin_path;
ar& use_user_load_parameters;
ar& user_load_parameters;
ar& plg_event;
ar& plg_reply;
ar& memory_changed_handle;
ar& is_exe_load_function_set;
ar& exe_load_checksum;
ar& load_exe_func;
ar& load_exe_args;
}
SERIALIZE_IMPL(PLG_LDR::PluginLoaderContext)
template <class Archive>
void PLG_LDR::serialize(Archive& ar, const unsigned int) {
ar& boost::serialization::base_object<Kernel::SessionRequestHandler>(*this);
ar& plgldr_context;
ar& plugin_fb_addr;
ar& allow_game_change;
}
SERIALIZE_IMPL(PLG_LDR)
void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kernel) { void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kernel) {
if (!plgldr_context.is_enabled || plgldr_context.plugin_loaded) { if (!plgldr_context.is_enabled || plgldr_context.plugin_loaded) {
return; return;
@ -91,7 +116,7 @@ void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kerne
std::string(plgldr_context.user_load_parameters.path + 1); std::string(plgldr_context.user_load_parameters.path + 1);
plgldr_context.is_default_path = false; plgldr_context.is_default_path = false;
plgldr_context.plugin_path = plugin_file; plgldr_context.plugin_path = plugin_file;
plugin_loader.Load(plgldr_context, process, kernel); plugin_loader.Load(plgldr_context, process, kernel, *this);
} else { } else {
const std::string plugin_root = const std::string plugin_root =
FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "luma/plugins/"; FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "luma/plugins/";
@ -103,7 +128,7 @@ void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kerne
if (!child.isDirectory && child.physicalName.ends_with(".3gx")) { if (!child.isDirectory && child.physicalName.ends_with(".3gx")) {
plgldr_context.is_default_path = false; plgldr_context.is_default_path = false;
plgldr_context.plugin_path = child.physicalName; plgldr_context.plugin_path = child.physicalName;
if (plugin_loader.Load(plgldr_context, process, kernel) == if (plugin_loader.Load(plgldr_context, process, kernel, *this) ==
Loader::ResultStatus::Success) { Loader::ResultStatus::Success) {
return; return;
} }
@ -114,7 +139,7 @@ void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kerne
if (FileUtil::Exists(default_path)) { if (FileUtil::Exists(default_path)) {
plgldr_context.is_default_path = true; plgldr_context.is_default_path = true;
plgldr_context.plugin_path = default_path; plgldr_context.plugin_path = default_path;
plugin_loader.Load(plgldr_context, process, kernel); plugin_loader.Load(plgldr_context, process, kernel, *this);
} }
} }
} }
@ -134,9 +159,9 @@ ResultVal<Kernel::Handle> PLG_LDR::GetMemoryChangedHandle(Kernel::KernelSystem&
return plgldr_context.memory_changed_handle; return plgldr_context.memory_changed_handle;
} }
std::shared_ptr<Kernel::Event> evt = kernel.CreateEvent( std::shared_ptr<Kernel::Event> evt =
Kernel::ResetType::OneShot, kernel.CreateEvent(Kernel::ResetType::OneShot,
fmt::format("event-{:08x}", Core::System::GetInstance().GetRunningCore().GetReg(14))); fmt::format("event-{:08x}", system.GetRunningCore().GetReg(14)));
R_TRY(kernel.GetCurrentProcess()->handle_table.Create( R_TRY(kernel.GetCurrentProcess()->handle_table.Create(
std::addressof(plgldr_context.memory_changed_handle), std::move(evt))); std::addressof(plgldr_context.memory_changed_handle), std::move(evt)));
return plgldr_context.memory_changed_handle; return plgldr_context.memory_changed_handle;
@ -274,7 +299,7 @@ std::shared_ptr<PLG_LDR> GetService(Core::System& system) {
} }
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
std::make_shared<PLG_LDR>()->InstallAsNamedPort(system.Kernel()); std::make_shared<PLG_LDR>(system)->InstallAsNamedPort(system.Kernel());
} }
} // namespace Service::PLGLDR } // namespace Service::PLGLDR

View file

@ -22,7 +22,7 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <boost/serialization/version.hpp> #include <boost/serialization/export.hpp>
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Core { namespace Core {
@ -70,25 +70,11 @@ public:
u32_le load_exe_args[4] = {0}; u32_le load_exe_args[4] = {0};
template <class Archive> template <class Archive>
void serialize(Archive& ar, const unsigned int) { void serialize(Archive& ar, const unsigned int);
ar& is_enabled;
ar& plugin_loaded;
ar& is_default_path;
ar& plugin_path;
ar& use_user_load_parameters;
ar& user_load_parameters;
ar& plg_event;
ar& plg_reply;
ar& memory_changed_handle;
ar& is_exe_load_function_set;
ar& exe_load_checksum;
ar& load_exe_func;
ar& load_exe_args;
}
friend class boost::serialization::access; friend class boost::serialization::access;
}; };
PLG_LDR(); PLG_LDR(Core::System& system_);
~PLG_LDR() {} ~PLG_LDR() {}
void OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kernel); void OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kernel);
@ -96,31 +82,31 @@ public:
ResultVal<Kernel::Handle> GetMemoryChangedHandle(Kernel::KernelSystem& kernel); ResultVal<Kernel::Handle> GetMemoryChangedHandle(Kernel::KernelSystem& kernel);
void OnMemoryChanged(Kernel::Process& process, Kernel::KernelSystem& kernel); void OnMemoryChanged(Kernel::Process& process, Kernel::KernelSystem& kernel);
static void SetEnabled(bool enabled) { void SetEnabled(bool enabled) {
plgldr_context.is_enabled = enabled; plgldr_context.is_enabled = enabled;
} }
static bool GetEnabled() { bool GetEnabled() {
return plgldr_context.is_enabled; return plgldr_context.is_enabled;
} }
static void SetAllowGameChangeState(bool allow) { void SetAllowGameChangeState(bool allow) {
allow_game_change = allow; allow_game_change = allow;
} }
static bool GetAllowGameChangeState() { bool GetAllowGameChangeState() {
return allow_game_change; return allow_game_change;
} }
static void SetPluginFBAddr(PAddr addr) { void SetPluginFBAddr(PAddr addr) {
plugin_fb_addr = addr; plugin_fb_addr = addr;
} }
static PAddr GetPluginFBAddr() { PAddr GetPluginFBAddr() {
return plugin_fb_addr; return plugin_fb_addr;
} }
private: private:
static const Kernel::CoreVersion plgldr_version; Core::System& system;
static PluginLoaderContext plgldr_context; PluginLoaderContext plgldr_context;
static PAddr plugin_fb_addr; PAddr plugin_fb_addr = 0;
static bool allow_game_change; bool allow_game_change = true;
void IsEnabled(Kernel::HLERequestContext& ctx); void IsEnabled(Kernel::HLERequestContext& ctx);
void SetEnabled(Kernel::HLERequestContext& ctx); void SetEnabled(Kernel::HLERequestContext& ctx);
@ -131,12 +117,7 @@ private:
void GetPluginPath(Kernel::HLERequestContext& ctx); void GetPluginPath(Kernel::HLERequestContext& ctx);
template <class Archive> template <class Archive>
void serialize(Archive& ar, const unsigned int) { void serialize(Archive& ar, const unsigned int);
ar& boost::serialization::base_object<Kernel::SessionRequestHandler>(*this);
ar& plgldr_context;
ar& plugin_fb_addr;
ar& allow_game_change;
}
friend class boost::serialization::access; friend class boost::serialization::access;
}; };
@ -147,3 +128,4 @@ void InstallInterfaces(Core::System& system);
} // namespace Service::PLGLDR } // namespace Service::PLGLDR
BOOST_CLASS_EXPORT_KEY(Service::PLGLDR::PLG_LDR) BOOST_CLASS_EXPORT_KEY(Service::PLGLDR::PLG_LDR)
SERVICE_CONSTRUCT(Service::PLGLDR::PLG_LDR)

View file

@ -20,6 +20,7 @@
#include "core/hle/service/ptm/ptm_u.h" #include "core/hle/service/ptm/ptm_u.h"
SERIALIZE_EXPORT_IMPL(Service::PTM::Module) SERIALIZE_EXPORT_IMPL(Service::PTM::Module)
SERVICE_CONSTRUCT_IMPL(Service::PTM::Module)
namespace Service::PTM { namespace Service::PTM {
@ -136,7 +137,7 @@ void Module::Interface::CheckNew3DS(Kernel::HLERequestContext& ctx) {
void Module::Interface::GetSystemTime(Kernel::HLERequestContext& ctx) { void Module::Interface::GetSystemTime(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
auto& share_page = Core::System::GetInstance().Kernel().GetSharedPageHandler(); auto& share_page = ptm->system.Kernel().GetSharedPageHandler();
const u64 console_time = share_page.GetSystemTimeSince2000(); const u64 console_time = share_page.GetSystemTimeSince2000();
IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
@ -207,7 +208,7 @@ static GameCoin ReadGameCoinData() {
return gamecoin_data; return gamecoin_data;
} }
Module::Module() { Module::Module(Core::System& system_) : system(system_) {
// Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't // Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't
// exist // exist
const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir);
@ -221,6 +222,14 @@ Module::Module() {
} }
} }
template <class Archive>
void Module::serialize(Archive& ar, const unsigned int) {
ar& shell_open;
ar& battery_is_charging;
ar& pedometer_is_counting;
}
SERIALIZE_IMPL(Module)
u16 Module::GetPlayCoins() { u16 Module::GetPlayCoins() {
return ReadGameCoinData().total_coins; return ReadGameCoinData().total_coins;
} }
@ -238,7 +247,7 @@ Module::Interface::Interface(std::shared_ptr<Module> ptm, const char* name, u32
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
auto ptm = std::make_shared<Module>(); auto ptm = std::make_shared<Module>(system);
std::make_shared<PTM_Gets>(ptm)->InstallAsService(service_manager); std::make_shared<PTM_Gets>(ptm)->InstallAsService(service_manager);
std::make_shared<PTM_Play>(ptm)->InstallAsService(service_manager); std::make_shared<PTM_Play>(ptm)->InstallAsService(service_manager);
std::make_shared<PTM_Sets>(ptm)->InstallAsService(service_manager); std::make_shared<PTM_Sets>(ptm)->InstallAsService(service_manager);

View file

@ -47,7 +47,9 @@ void CheckNew3DS(IPC::RequestBuilder& rb);
class Module final { class Module final {
public: public:
Module(); explicit Module(Core::System& system_);
~Module() = default;
static u16 GetPlayCoins(); static u16 GetPlayCoins();
static void SetPlayCoins(u16 play_coins); static void SetPlayCoins(u16 play_coins);
@ -150,16 +152,14 @@ public:
}; };
private: private:
Core::System& system;
bool shell_open = true; bool shell_open = true;
bool battery_is_charging = true; bool battery_is_charging = true;
bool pedometer_is_counting = false; bool pedometer_is_counting = false;
template <class Archive> template <class Archive>
void serialize(Archive& ar, const unsigned int) { void serialize(Archive& ar, const unsigned int);
ar& shell_open;
ar& battery_is_charging;
ar& pedometer_is_counting;
}
friend class boost::serialization::access; friend class boost::serialization::access;
}; };
@ -168,3 +168,4 @@ void InstallInterfaces(Core::System& system);
} // namespace Service::PTM } // namespace Service::PTM
BOOST_CLASS_EXPORT_KEY(Service::PTM::Module) BOOST_CLASS_EXPORT_KEY(Service::PTM::Module)
SERVICE_CONSTRUCT(Service::PTM::Module)

View file

@ -249,7 +249,7 @@ void SRV::PublishToSubscriber(Kernel::HLERequestContext& ctx) {
// console. Normally, this is handled by NS. If notification handling is properly implemented, // console. Normally, this is handled by NS. If notification handling is properly implemented,
// this piece of code should be removed, and handled by subscribing from NS instead. // this piece of code should be removed, and handled by subscribing from NS instead.
if (notification_id == 0x203) { if (notification_id == 0x203) {
Core::System::GetInstance().RequestShutdown(); system.RequestShutdown();
} else { } else {
LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x{:X}, flags={}", LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x{:X}, flags={}",
notification_id, flags); notification_id, flags);

View file

@ -94,7 +94,7 @@ static u32 TranslateAddr(u32 addr, const THREEloadinfo* loadinfo, u32* offsets)
using Kernel::CodeSet; using Kernel::CodeSet;
static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, static THREEDSX_Error Load3DSXFile(Core::System& system, FileUtil::IOFile& file, u32 base_addr,
std::shared_ptr<CodeSet>* out_codeset) { std::shared_ptr<CodeSet>* out_codeset) {
if (!file.IsOpen()) if (!file.IsOpen())
return ERROR_FILE; return ERROR_FILE;
@ -222,7 +222,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
} }
// Create the CodeSet // Create the CodeSet
std::shared_ptr<CodeSet> code_set = Core::System::GetInstance().Kernel().CreateCodeSet("", 0); std::shared_ptr<CodeSet> code_set = system.Kernel().CreateCodeSet("", 0);
code_set->CodeSegment().offset = loadinfo.seg_ptrs[0] - program_image.data(); code_set->CodeSegment().offset = loadinfo.seg_ptrs[0] - program_image.data();
code_set->CodeSegment().addr = loadinfo.seg_addrs[0]; code_set->CodeSegment().addr = loadinfo.seg_addrs[0];
@ -268,25 +268,24 @@ ResultStatus AppLoader_THREEDSX::Load(std::shared_ptr<Kernel::Process>& process)
return ResultStatus::Error; return ResultStatus::Error;
std::shared_ptr<CodeSet> codeset; std::shared_ptr<CodeSet> codeset;
if (Load3DSXFile(file, Memory::PROCESS_IMAGE_VADDR, &codeset) != ERROR_NONE) if (Load3DSXFile(system, file, Memory::PROCESS_IMAGE_VADDR, &codeset) != ERROR_NONE)
return ResultStatus::Error; return ResultStatus::Error;
codeset->name = filename; codeset->name = filename;
process = Core::System::GetInstance().Kernel().CreateProcess(std::move(codeset)); process = system.Kernel().CreateProcess(std::move(codeset));
process->Set3dsxKernelCaps(); process->Set3dsxKernelCaps();
// Attach the default resource limit (APPLICATION) to the process // Attach the default resource limit (APPLICATION) to the process
process->resource_limit = Core::System::GetInstance().Kernel().ResourceLimit().GetForCategory( process->resource_limit =
Kernel::ResourceLimitCategory::Application); system.Kernel().ResourceLimit().GetForCategory(Kernel::ResourceLimitCategory::Application);
// On real HW this is done with FS:Reg, but we can be lazy // On real HW this is done with FS:Reg, but we can be lazy
auto fs_user = auto fs_user = system.ServiceManager().GetService<Service::FS::FS_USER>("fs:USER");
Core::System::GetInstance().ServiceManager().GetService<Service::FS::FS_USER>("fs:USER");
fs_user->RegisterProgramInfo(process->GetObjectId(), process->codeset->program_id, filepath); fs_user->RegisterProgramInfo(process->GetObjectId(), process->codeset->program_id, filepath);
process->Run(48, Kernel::DEFAULT_STACK_SIZE); process->Run(48, Kernel::DEFAULT_STACK_SIZE);
Core::System::GetInstance().ArchiveManager().RegisterSelfNCCH(*this); system.ArchiveManager().RegisterSelfNCCH(*this);
is_loaded = true; is_loaded = true;
return ResultStatus::Success; return ResultStatus::Success;

View file

@ -14,9 +14,9 @@ namespace Loader {
/// Loads an 3DSX file /// Loads an 3DSX file
class AppLoader_THREEDSX final : public AppLoader { class AppLoader_THREEDSX final : public AppLoader {
public: public:
AppLoader_THREEDSX(FileUtil::IOFile&& file, const std::string& filename, AppLoader_THREEDSX(Core::System& system_, FileUtil::IOFile&& file, const std::string& filename,
const std::string& filepath) const std::string& filepath)
: AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) {} : AppLoader(system_, std::move(file)), filename(std::move(filename)), filepath(filepath) {}
/** /**
* Returns the type of the file * Returns the type of the file

View file

@ -199,7 +199,7 @@ public:
u32 GetFlags() const { u32 GetFlags() const {
return (u32)(header->e_flags); return (u32)(header->e_flags);
} }
std::shared_ptr<CodeSet> LoadInto(u32 vaddr); std::shared_ptr<CodeSet> LoadInto(Core::System& system, u32 vaddr);
int GetNumSegments() const { int GetNumSegments() const {
return (int)(header->e_phnum); return (int)(header->e_phnum);
@ -262,7 +262,7 @@ const char* ElfReader::GetSectionName(int section) const {
return nullptr; return nullptr;
} }
std::shared_ptr<CodeSet> ElfReader::LoadInto(u32 vaddr) { std::shared_ptr<CodeSet> ElfReader::LoadInto(Core::System& system, u32 vaddr) {
LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx); LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx);
// Should we relocate? // Should we relocate?
@ -290,7 +290,7 @@ std::shared_ptr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
std::vector<u8> program_image(total_image_size); std::vector<u8> program_image(total_image_size);
std::size_t current_image_position = 0; std::size_t current_image_position = 0;
std::shared_ptr<CodeSet> codeset = Core::System::GetInstance().Kernel().CreateCodeSet("", 0); std::shared_ptr<CodeSet> codeset = system.Kernel().CreateCodeSet("", 0);
for (unsigned int i = 0; i < header->e_phnum; ++i) { for (unsigned int i = 0; i < header->e_phnum; ++i) {
Elf32_Phdr* p = &segments[i]; Elf32_Phdr* p = &segments[i];
@ -380,15 +380,15 @@ ResultStatus AppLoader_ELF::Load(std::shared_ptr<Kernel::Process>& process) {
return ResultStatus::Error; return ResultStatus::Error;
ElfReader elf_reader(&buffer[0]); ElfReader elf_reader(&buffer[0]);
std::shared_ptr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR); std::shared_ptr<CodeSet> codeset = elf_reader.LoadInto(system, Memory::PROCESS_IMAGE_VADDR);
codeset->name = filename; codeset->name = filename;
process = Core::System::GetInstance().Kernel().CreateProcess(std::move(codeset)); process = system.Kernel().CreateProcess(std::move(codeset));
process->Set3dsxKernelCaps(); process->Set3dsxKernelCaps();
// Attach the default resource limit (APPLICATION) to the process // Attach the default resource limit (APPLICATION) to the process
process->resource_limit = Core::System::GetInstance().Kernel().ResourceLimit().GetForCategory( process->resource_limit =
Kernel::ResourceLimitCategory::Application); system.Kernel().ResourceLimit().GetForCategory(Kernel::ResourceLimitCategory::Application);
process->Run(48, Kernel::DEFAULT_STACK_SIZE); process->Run(48, Kernel::DEFAULT_STACK_SIZE);

View file

@ -14,8 +14,8 @@ namespace Loader {
/// Loads an ELF/AXF file /// Loads an ELF/AXF file
class AppLoader_ELF final : public AppLoader { class AppLoader_ELF final : public AppLoader {
public: public:
AppLoader_ELF(FileUtil::IOFile&& file, std::string filename) AppLoader_ELF(Core::System& system_, FileUtil::IOFile&& file, std::string filename)
: AppLoader(std::move(file)), filename(std::move(filename)) {} : AppLoader(system_, std::move(file)), filename(std::move(filename)) {}
/** /**
* Returns the type of the file * Returns the type of the file

View file

@ -6,6 +6,7 @@
#include <string> #include <string>
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "core/core.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
#include "core/loader/3dsx.h" #include "core/loader/3dsx.h"
#include "core/loader/elf.h" #include "core/loader/elf.h"
@ -89,23 +90,23 @@ const char* GetFileTypeString(FileType type) {
* @param filepath the file full path (with name) * @param filepath the file full path (with name)
* @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type
*/ */
static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileType type, static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileUtil::IOFile&& file,
const std::string& filename, FileType type, const std::string& filename,
const std::string& filepath) { const std::string& filepath) {
switch (type) { switch (type) {
// 3DSX file format. // 3DSX file format.
case FileType::THREEDSX: case FileType::THREEDSX:
return std::make_unique<AppLoader_THREEDSX>(std::move(file), filename, filepath); return std::make_unique<AppLoader_THREEDSX>(system, std::move(file), filename, filepath);
// Standard ELF file format. // Standard ELF file format.
case FileType::ELF: case FileType::ELF:
return std::make_unique<AppLoader_ELF>(std::move(file), filename); return std::make_unique<AppLoader_ELF>(system, std::move(file), filename);
// NCCH/NCSD container formats. // NCCH/NCSD container formats.
case FileType::CXI: case FileType::CXI:
case FileType::CCI: case FileType::CCI:
return std::make_unique<AppLoader_NCCH>(std::move(file), filepath); return std::make_unique<AppLoader_NCCH>(system, std::move(file), filepath);
default: default:
return nullptr; return nullptr;
@ -133,7 +134,8 @@ std::unique_ptr<AppLoader> GetLoader(const std::string& filename) {
LOG_DEBUG(Loader, "Loading file {} as {}...", filename, GetFileTypeString(type)); LOG_DEBUG(Loader, "Loading file {} as {}...", filename, GetFileTypeString(type));
return GetFileLoader(std::move(file), type, filename_filename, filename); auto& system = Core::System::GetInstance();
return GetFileLoader(system, std::move(file), type, filename_filename, filename);
} }
} // namespace Loader } // namespace Loader

View file

@ -82,7 +82,8 @@ constexpr u32 MakeMagic(char a, char b, char c, char d) {
/// Interface for loading an application /// Interface for loading an application
class AppLoader : NonCopyable { class AppLoader : NonCopyable {
public: public:
explicit AppLoader(FileUtil::IOFile&& file) : file(std::move(file)) {} explicit AppLoader(Core::System& system_, FileUtil::IOFile&& file)
: system(system_), file(std::move(file)) {}
virtual ~AppLoader() {} virtual ~AppLoader() {}
/** /**
@ -253,6 +254,7 @@ public:
} }
protected: protected:
Core::System& system;
FileUtil::IOFile file; FileUtil::IOFile file;
bool is_loaded = false; bool is_loaded = false;
}; };

View file

@ -113,8 +113,7 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process)
std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( std::string process_name = Common::StringFromFixedZeroTerminatedBuffer(
(const char*)overlay_ncch->exheader_header.codeset_info.name, 8); (const char*)overlay_ncch->exheader_header.codeset_info.name, 8);
std::shared_ptr<CodeSet> codeset = std::shared_ptr<CodeSet> codeset = system.Kernel().CreateCodeSet(process_name, program_id);
Core::System::GetInstance().Kernel().CreateCodeSet(process_name, program_id);
codeset->CodeSegment().offset = 0; codeset->CodeSegment().offset = 0;
codeset->CodeSegment().addr = overlay_ncch->exheader_header.codeset_info.text.address; codeset->CodeSegment().addr = overlay_ncch->exheader_header.codeset_info.text.address;
@ -148,7 +147,6 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process)
codeset->entrypoint = codeset->CodeSegment().addr; codeset->entrypoint = codeset->CodeSegment().addr;
codeset->memory = std::move(code); codeset->memory = std::move(code);
auto& system = Core::System::GetInstance();
process = system.Kernel().CreateProcess(std::move(codeset)); process = system.Kernel().CreateProcess(std::move(codeset));
// Attach a resource limit to the process based on the resource limit category // Attach a resource limit to the process based on the resource limit category
@ -276,7 +274,6 @@ ResultStatus AppLoader_NCCH::Load(std::shared_ptr<Kernel::Process>& process) {
overlay_ncch = &update_ncch; overlay_ncch = &update_ncch;
} }
auto& system = Core::System::GetInstance();
system.TelemetrySession().AddField(Common::Telemetry::FieldType::Session, "ProgramId", system.TelemetrySession().AddField(Common::Telemetry::FieldType::Session, "ProgramId",
program_id); program_id);

View file

@ -15,8 +15,8 @@ namespace Loader {
/// Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI) /// Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI)
class AppLoader_NCCH final : public AppLoader { class AppLoader_NCCH final : public AppLoader {
public: public:
AppLoader_NCCH(FileUtil::IOFile&& file, const std::string& filepath) AppLoader_NCCH(Core::System& system_, FileUtil::IOFile&& file, const std::string& filepath)
: AppLoader(std::move(file)), base_ncch(filepath), overlay_ncch(&base_ncch), : AppLoader(system_, std::move(file)), base_ncch(filepath), overlay_ncch(&base_ncch),
filepath(filepath) {} filepath(filepath) {}
/** /**

View file

@ -264,14 +264,55 @@ public:
return {vram_mem, addr - VRAM_VADDR}; return {vram_mem, addr - VRAM_VADDR};
} }
if (addr >= PLUGIN_3GX_FB_VADDR && addr < PLUGIN_3GX_FB_VADDR_END) { if (addr >= PLUGIN_3GX_FB_VADDR && addr < PLUGIN_3GX_FB_VADDR_END) {
return {fcram_mem, addr - PLUGIN_3GX_FB_VADDR + auto plg_ldr = Service::PLGLDR::GetService(system);
Service::PLGLDR::PLG_LDR::GetPluginFBAddr() - FCRAM_PADDR}; if (plg_ldr) {
return {fcram_mem,
addr - PLUGIN_3GX_FB_VADDR + plg_ldr->GetPluginFBAddr() - FCRAM_PADDR};
}
} }
UNREACHABLE(); UNREACHABLE();
return MemoryRef{}; return MemoryRef{};
} }
void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) {
const VAddr end = start + size;
auto CheckRegion = [&](VAddr region_start, VAddr region_end, PAddr paddr_region_start) {
if (start >= region_end || end <= region_start) {
// No overlap with region
return;
}
auto& renderer = system.GPU().Renderer();
VAddr overlap_start = std::max(start, region_start);
VAddr overlap_end = std::min(end, region_end);
PAddr physical_start = paddr_region_start + (overlap_start - region_start);
u32 overlap_size = overlap_end - overlap_start;
auto* rasterizer = renderer.Rasterizer();
switch (mode) {
case FlushMode::Flush:
rasterizer->FlushRegion(physical_start, overlap_size);
break;
case FlushMode::Invalidate:
rasterizer->InvalidateRegion(physical_start, overlap_size);
break;
case FlushMode::FlushAndInvalidate:
rasterizer->FlushAndInvalidateRegion(physical_start, overlap_size);
break;
}
};
CheckRegion(LINEAR_HEAP_VADDR, LINEAR_HEAP_VADDR_END, FCRAM_PADDR);
CheckRegion(NEW_LINEAR_HEAP_VADDR, NEW_LINEAR_HEAP_VADDR_END, FCRAM_PADDR);
CheckRegion(VRAM_VADDR, VRAM_VADDR_END, VRAM_PADDR);
auto plg_ldr = Service::PLGLDR::GetService(system);
if (plg_ldr && plg_ldr->GetPluginFBAddr()) {
CheckRegion(PLUGIN_3GX_FB_VADDR, PLUGIN_3GX_FB_VADDR_END, plg_ldr->GetPluginFBAddr());
}
}
private: private:
friend class boost::serialization::access; friend class boost::serialization::access;
template <class Archive> template <class Archive>
@ -345,41 +386,8 @@ std::shared_ptr<PageTable> MemorySystem::GetCurrentPageTable() const {
return impl->current_page_table; return impl->current_page_table;
} }
void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) { void MemorySystem::RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) {
const VAddr end = start + size; impl->RasterizerFlushVirtualRegion(start, size, mode);
auto CheckRegion = [&](VAddr region_start, VAddr region_end, PAddr paddr_region_start) {
if (start >= region_end || end <= region_start) {
// No overlap with region
return;
}
auto& renderer = Core::System::GetInstance().GPU().Renderer();
VAddr overlap_start = std::max(start, region_start);
VAddr overlap_end = std::min(end, region_end);
PAddr physical_start = paddr_region_start + (overlap_start - region_start);
u32 overlap_size = overlap_end - overlap_start;
auto* rasterizer = renderer.Rasterizer();
switch (mode) {
case FlushMode::Flush:
rasterizer->FlushRegion(physical_start, overlap_size);
break;
case FlushMode::Invalidate:
rasterizer->InvalidateRegion(physical_start, overlap_size);
break;
case FlushMode::FlushAndInvalidate:
rasterizer->FlushAndInvalidateRegion(physical_start, overlap_size);
break;
}
};
CheckRegion(LINEAR_HEAP_VADDR, LINEAR_HEAP_VADDR_END, FCRAM_PADDR);
CheckRegion(NEW_LINEAR_HEAP_VADDR, NEW_LINEAR_HEAP_VADDR_END, FCRAM_PADDR);
CheckRegion(VRAM_VADDR, VRAM_VADDR_END, VRAM_PADDR);
if (Service::PLGLDR::PLG_LDR::GetPluginFBAddr())
CheckRegion(PLUGIN_3GX_FB_VADDR, PLUGIN_3GX_FB_VADDR_END,
Service::PLGLDR::PLG_LDR::GetPluginFBAddr());
} }
void MemorySystem::MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, void MemorySystem::MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory,
@ -683,16 +691,19 @@ std::vector<VAddr> MemorySystem::PhysicalToVirtualAddressForRasterizer(PAddr add
if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
return {addr - VRAM_PADDR + VRAM_VADDR}; return {addr - VRAM_PADDR + VRAM_VADDR};
} }
if (addr >= Service::PLGLDR::PLG_LDR::GetPluginFBAddr() &&
addr < Service::PLGLDR::PLG_LDR::GetPluginFBAddr() + PLUGIN_3GX_FB_SIZE) {
return {addr - Service::PLGLDR::PLG_LDR::GetPluginFBAddr() + PLUGIN_3GX_FB_VADDR};
}
if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) { if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) {
return {addr - FCRAM_PADDR + LINEAR_HEAP_VADDR, addr - FCRAM_PADDR + NEW_LINEAR_HEAP_VADDR}; return {addr - FCRAM_PADDR + LINEAR_HEAP_VADDR, addr - FCRAM_PADDR + NEW_LINEAR_HEAP_VADDR};
} }
if (addr >= FCRAM_PADDR_END && addr < FCRAM_N3DS_PADDR_END) { if (addr >= FCRAM_PADDR_END && addr < FCRAM_N3DS_PADDR_END) {
return {addr - FCRAM_PADDR + NEW_LINEAR_HEAP_VADDR}; return {addr - FCRAM_PADDR + NEW_LINEAR_HEAP_VADDR};
} }
auto plg_ldr = Service::PLGLDR::GetService(impl->system);
if (plg_ldr) {
auto fb_addr = plg_ldr->GetPluginFBAddr();
if (addr >= fb_addr && addr < fb_addr + PLUGIN_3GX_FB_SIZE) {
return {addr - fb_addr + PLUGIN_3GX_FB_VADDR};
}
}
// While the physical <-> virtual mapping is 1:1 for the regions supported by the cache, // While the physical <-> virtual mapping is 1:1 for the regions supported by the cache,
// some games (like Pokemon Super Mystery Dungeon) will try to use textures that go beyond // some games (like Pokemon Super Mystery Dungeon) will try to use textures that go beyond
// the end address of VRAM, causing the Virtual->Physical translation to fail when flushing // the end address of VRAM, causing the Virtual->Physical translation to fail when flushing

View file

@ -235,8 +235,6 @@ enum class FlushMode {
FlushAndInvalidate, FlushAndInvalidate,
}; };
void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode);
class MemorySystem { class MemorySystem {
public: public:
explicit MemorySystem(Core::System& system); explicit MemorySystem(Core::System& system);
@ -553,6 +551,8 @@ public:
void SetDSP(AudioCore::DspInterface& dsp); void SetDSP(AudioCore::DspInterface& dsp);
void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode);
private: private:
template <typename T> template <typename T>
T Read(const VAddr vaddr); T Read(const VAddr vaddr);

View file

@ -22,28 +22,6 @@ namespace VideoCore {
constexpr VAddr VADDR_LCD = 0x1ED02000; constexpr VAddr VADDR_LCD = 0x1ED02000;
constexpr VAddr VADDR_GPU = 0x1EF00000; constexpr VAddr VADDR_GPU = 0x1EF00000;
static PAddr VirtualToPhysicalAddress(VAddr addr) {
if (addr == 0) {
return 0;
}
if (addr >= Memory::VRAM_VADDR && addr <= Memory::VRAM_VADDR_END) {
return addr - Memory::VRAM_VADDR + Memory::VRAM_PADDR;
}
if (addr >= Memory::LINEAR_HEAP_VADDR && addr <= Memory::LINEAR_HEAP_VADDR_END) {
return addr - Memory::LINEAR_HEAP_VADDR + Memory::FCRAM_PADDR;
}
if (addr >= Memory::NEW_LINEAR_HEAP_VADDR && addr <= Memory::NEW_LINEAR_HEAP_VADDR_END) {
return addr - Memory::NEW_LINEAR_HEAP_VADDR + Memory::FCRAM_PADDR;
}
if (addr >= Memory::PLUGIN_3GX_FB_VADDR && addr <= Memory::PLUGIN_3GX_FB_VADDR_END) {
return addr - Memory::PLUGIN_3GX_FB_VADDR + Service::PLGLDR::PLG_LDR::GetPluginFBAddr();
}
LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x{:08X}", addr);
return addr;
}
MICROPROFILE_DEFINE(GPU_DisplayTransfer, "GPU", "DisplayTransfer", MP_RGB(100, 100, 255)); MICROPROFILE_DEFINE(GPU_DisplayTransfer, "GPU", "DisplayTransfer", MP_RGB(100, 100, 255));
MICROPROFILE_DEFINE(GPU_CmdlistProcessing, "GPU", "Cmdlist Processing", MP_RGB(100, 255, 100)); MICROPROFILE_DEFINE(GPU_CmdlistProcessing, "GPU", "Cmdlist Processing", MP_RGB(100, 255, 100));
@ -84,6 +62,31 @@ GPU::GPU(Core::System& system, Frontend::EmuWindow& emu_window,
GPU::~GPU() = default; GPU::~GPU() = default;
PAddr GPU::VirtualToPhysicalAddress(VAddr addr) {
if (addr == 0) {
return 0;
}
if (addr >= Memory::VRAM_VADDR && addr <= Memory::VRAM_VADDR_END) {
return addr - Memory::VRAM_VADDR + Memory::VRAM_PADDR;
}
if (addr >= Memory::LINEAR_HEAP_VADDR && addr <= Memory::LINEAR_HEAP_VADDR_END) {
return addr - Memory::LINEAR_HEAP_VADDR + Memory::FCRAM_PADDR;
}
if (addr >= Memory::NEW_LINEAR_HEAP_VADDR && addr <= Memory::NEW_LINEAR_HEAP_VADDR_END) {
return addr - Memory::NEW_LINEAR_HEAP_VADDR + Memory::FCRAM_PADDR;
}
if (addr >= Memory::PLUGIN_3GX_FB_VADDR && addr <= Memory::PLUGIN_3GX_FB_VADDR_END) {
auto plg_ldr = Service::PLGLDR::GetService(impl->system);
if (plg_ldr) {
return addr - Memory::PLUGIN_3GX_FB_VADDR + plg_ldr->GetPluginFBAddr();
}
}
LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x{:08X}", addr);
return addr;
}
void GPU::SetInterruptHandler(Service::GSP::InterruptHandler handler) { void GPU::SetInterruptHandler(Service::GSP::InterruptHandler handler) {
impl->signal_interrupt = handler; impl->signal_interrupt = handler;
impl->pica.SetInterruptHandler(handler); impl->pica.SetInterruptHandler(handler);
@ -107,9 +110,9 @@ void GPU::Execute(const Service::GSP::Command& command) {
switch (command.id) { switch (command.id) {
case CommandId::RequestDma: { case CommandId::RequestDma: {
Memory::RasterizerFlushVirtualRegion(command.dma_request.source_address, impl->system.Memory().RasterizerFlushVirtualRegion(
command.dma_request.size, Memory::FlushMode::Flush); command.dma_request.source_address, command.dma_request.size, Memory::FlushMode::Flush);
Memory::RasterizerFlushVirtualRegion(command.dma_request.dest_address, impl->system.Memory().RasterizerFlushVirtualRegion(command.dma_request.dest_address,
command.dma_request.size, command.dma_request.size,
Memory::FlushMode::Invalidate); Memory::FlushMode::Invalidate);

View file

@ -108,6 +108,8 @@ private:
private: private:
struct Impl; struct Impl;
std::unique_ptr<Impl> impl; std::unique_ptr<Impl> impl;
PAddr VirtualToPhysicalAddress(VAddr addr);
}; };
} // namespace VideoCore } // namespace VideoCore