Compare commits

...

26 Commits

Author SHA1 Message Date
ameerj
d52ee6d0a7 cleanup unneeded comments and newlines 2020-11-25 14:46:08 -05:00
ameerj
e87670ee48 Refactor MaxwellToSpirvComparison. Use Common::BitCast
Co-Authored-By: Rodrigo Locatti <reinuseslisp@airmail.cc>
2020-11-25 00:33:20 -05:00
ameerj
1dbf71ceb3 Address PR feedback from Rein 2020-11-24 22:46:45 -05:00
ameerj
9014861858 vulkan_renderer: Alpha Test Culling Implementation
Used by various textures in many titles, e.g.  SSBU menu.
2020-11-24 22:46:45 -05:00
bunnei
d1da7eb119 Merge pull request #4905 from german77/AnalogFromButton
Allow to dial any angle with digital joystick
2020-11-24 16:04:55 -08:00
bunnei
0832da3e40 Merge pull request #4799 from bunnei/execute-program
core: Refactor loader and implement ExecuteProgram
2020-11-24 15:27:22 -08:00
bunnei
4fbe4da911 frontend: yuzu (qt): Register a callback for ExecuteProgram. 2020-11-24 15:18:29 -08:00
bunnei
4fb5ca80c0 service: am: Implement ExecuteProgram and required stubs.
- This is used by Super Mario 3D All-Stars.
2020-11-24 15:17:43 -08:00
bunnei
5f75d97125 core: loader: Implement support for loading indexed programs. 2020-11-24 15:16:24 -08:00
bunnei
7791cc8c2e hle: services: Fix a crash with improper NVFlinger lifetime management. (#4977)
* hle: services: Fix a crash with improper NVFlinger lifetime management.

- This crash would happen when attempting to shutdown yuzu early on in boot.
2020-11-24 14:31:58 -08:00
Rodrigo Locatti
fbda5e9ec9 Merge pull request #3681 from lioncash/component
decoder/image: Fix incorrect G24R8 component sizes in GetComponentSize()
2020-11-24 04:38:03 -03:00
Rodrigo Locatti
410ed82922 Merge pull request #4942 from lioncash/system
core: Make use of [[nodiscard]] with the System class
2020-11-24 04:26:59 -03:00
Rodrigo Locatti
7afb7a9494 Merge pull request #4972 from lioncash/unused4
svc: Remove unnecessary [[maybe_unused]] tag
2020-11-24 04:25:59 -03:00
bunnei
6694e11303 input_common: Fix typo in gc_poller.cpp with [[maybe_unused]]. 2020-11-23 21:42:06 -08:00
bunnei
5ec6a265bf Merge pull request #4980 from bunnei/error-fixup
input_common: Add more missing [[maybe_unused]] from #4927.
2020-11-23 21:00:59 -08:00
bunnei
7fb7540d69 input_common: Add more missing [[maybe_unused]] from #4927. 2020-11-23 20:50:35 -08:00
bunnei
d04abd39eb Fix warnings in core/frontend/input.h with [[maybe_unused]]
Fixes build break due to #4927
2020-11-23 18:11:21 -08:00
bunnei
e371d12af6 Merge pull request #4927 from lioncash/input-error
input_common: Treat warnings as errors
2020-11-23 17:25:53 -08:00
Lioncash
874be0e3e1 svc: Remove unnecessary [[maybe_unused]] tag
The parameter is used in this function, so this suppression isn't
necessary.
2020-11-23 10:17:20 -05:00
Lioncash
5c4774e8ce input_common: Treat warnings as errors
Migrates over warnings as errors for input common to match how the
common library treats warnings as errors.
2020-11-22 04:50:03 -05:00
Lioncash
aaf262bfed core: Remove unused private Init function for the System class
This isn't used, so it can be removed.
2020-11-18 02:09:08 -05:00
Lioncash
bcaadac22c core: Make use of [[nodiscard]] with the System class
Given this is a central class, we should flag cases where the return
value of some functions not being used is likely a bug.
2020-11-18 02:06:44 -05:00
german
f5110340e6 fix minor clang error 2020-11-10 10:38:15 -06:00
german
70df449d0a Allow to dial any angle with digital joystick 2020-11-08 09:15:33 -06:00
Lioncash
24620bc4ea decode/image: Fix typo in assert in GetComponentSize() 2020-04-15 22:29:51 -04:00
Lioncash
b178c9a349 decoder/image: Fix incorrect G24R8 component sizes in GetComponentSize()
The components' sizes were mismatched. This corrects that.
2020-04-15 22:10:44 -04:00
50 changed files with 541 additions and 279 deletions

View File

@@ -145,7 +145,7 @@ struct System::Impl {
}
ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) {
LOG_DEBUG(HW_Memory, "initialized OK");
LOG_DEBUG(Core, "initialized OK");
device_memory = std::make_unique<Core::DeviceMemory>();
@@ -187,7 +187,7 @@ struct System::Impl {
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
Service::Init(service_manager, system);
services = std::make_unique<Service::Services>(service_manager, system);
GDBStub::DeferStart();
interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
@@ -208,9 +208,11 @@ struct System::Impl {
return ResultStatus::Success;
}
ResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
const std::string& filepath) {
app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath));
ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath,
std::size_t program_index) {
app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath),
program_index);
if (!app_loader) {
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
return ResultStatus::ErrorGetLoader;
@@ -296,7 +298,7 @@ struct System::Impl {
// Shutdown emulation session
GDBStub::Shutdown();
Service::Shutdown();
services.reset();
service_manager.reset();
cheat_engine.reset();
telemetry_session.reset();
@@ -306,8 +308,8 @@ struct System::Impl {
cpu_manager.Shutdown();
// Shutdown kernel and core timing
kernel.Shutdown();
core_timing.Shutdown();
kernel.Shutdown();
// Close app loader
app_loader.reset();
@@ -398,6 +400,9 @@ struct System::Impl {
/// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager;
/// Services
std::unique_ptr<Service::Services> services;
/// Telemetry session for this emulation session
std::unique_ptr<Core::TelemetrySession> telemetry_session;
@@ -413,6 +418,8 @@ struct System::Impl {
bool is_multicore{};
bool is_async_gpu{};
ExecuteProgramCallback execute_program_callback;
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{};
};
@@ -444,8 +451,13 @@ void System::InvalidateCpuInstructionCaches() {
impl->kernel.InvalidateAllInstructionCaches();
}
System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) {
return impl->Load(*this, emu_window, filepath);
void System::Shutdown() {
impl->Shutdown();
}
System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
std::size_t program_index) {
return impl->Load(*this, emu_window, filepath, program_index);
}
bool System::IsPoweredOn() const {
@@ -632,7 +644,11 @@ const std::string& System::GetStatusDetails() const {
return impl->status_details;
}
Loader::AppLoader& System::GetAppLoader() const {
Loader::AppLoader& System::GetAppLoader() {
return *impl->app_loader;
}
const Loader::AppLoader& System::GetAppLoader() const {
return *impl->app_loader;
}
@@ -748,14 +764,6 @@ const System::CurrentBuildProcessID& System::GetCurrentProcessBuildID() const {
return impl->build_id;
}
System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
return impl->Init(*this, emu_window);
}
void System::Shutdown() {
impl->Shutdown();
}
Service::SM::ServiceManager& System::ServiceManager() {
return *impl->service_manager;
}
@@ -786,4 +794,16 @@ bool System::IsMulticore() const {
return impl->is_multicore;
}
void System::RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback) {
impl->execute_program_callback = std::move(callback);
}
void System::ExecuteProgram(std::size_t program_index) {
if (impl->execute_program_callback) {
impl->execute_program_callback(program_index);
} else {
LOG_CRITICAL(Core, "execute_program_callback must be initialized by the frontend");
}
}
} // namespace Core

View File

@@ -5,6 +5,7 @@
#pragma once
#include <cstddef>
#include <functional>
#include <memory>
#include <string>
#include <vector>
@@ -144,19 +145,19 @@ public:
* Run the OS and Application
* This function will start emulation and run the relevant devices
*/
ResultStatus Run();
[[nodiscard]] ResultStatus Run();
/**
* Pause the OS and Application
* This function will pause emulation and stop the relevant devices
*/
ResultStatus Pause();
[[nodiscard]] ResultStatus Pause();
/**
* Step the CPU one instruction
* @return Result status, indicating whether or not the operation succeeded.
*/
ResultStatus SingleStep();
[[nodiscard]] ResultStatus SingleStep();
/**
* Invalidate the CPU instruction caches
@@ -173,22 +174,24 @@ public:
* @param emu_window Reference to the host-system window used for video output and keyboard
* input.
* @param filepath String path to the executable application to load on the host file system.
* @param program_index Specifies the index within the container of the program to launch.
* @returns ResultStatus code, indicating if the operation succeeded.
*/
ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath);
[[nodiscard]] ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
std::size_t program_index = 0);
/**
* Indicates if the emulated system is powered on (all subsystems initialized and able to run an
* application).
* @returns True if the emulated system is powered on, otherwise false.
*/
bool IsPoweredOn() const;
[[nodiscard]] bool IsPoweredOn() const;
/// Gets a reference to the telemetry session for this emulation session.
Core::TelemetrySession& TelemetrySession();
[[nodiscard]] Core::TelemetrySession& TelemetrySession();
/// Gets a reference to the telemetry session for this emulation session.
const Core::TelemetrySession& TelemetrySession() const;
[[nodiscard]] const Core::TelemetrySession& TelemetrySession() const;
/// Prepare the core emulation for a reschedule
void PrepareReschedule();
@@ -197,185 +200,178 @@ public:
void PrepareReschedule(u32 core_index);
/// Gets and resets core performance statistics
PerfStatsResults GetAndResetPerfStats();
[[nodiscard]] PerfStatsResults GetAndResetPerfStats();
/// Gets an ARM interface to the CPU core that is currently running
ARM_Interface& CurrentArmInterface();
[[nodiscard]] ARM_Interface& CurrentArmInterface();
/// Gets an ARM interface to the CPU core that is currently running
const ARM_Interface& CurrentArmInterface() const;
[[nodiscard]] const ARM_Interface& CurrentArmInterface() const;
/// Gets the index of the currently running CPU core
std::size_t CurrentCoreIndex() const;
[[nodiscard]] std::size_t CurrentCoreIndex() const;
/// Gets the scheduler for the CPU core that is currently running
Kernel::Scheduler& CurrentScheduler();
[[nodiscard]] Kernel::Scheduler& CurrentScheduler();
/// Gets the scheduler for the CPU core that is currently running
const Kernel::Scheduler& CurrentScheduler() const;
[[nodiscard]] const Kernel::Scheduler& CurrentScheduler() const;
/// Gets the physical core for the CPU core that is currently running
Kernel::PhysicalCore& CurrentPhysicalCore();
[[nodiscard]] Kernel::PhysicalCore& CurrentPhysicalCore();
/// Gets the physical core for the CPU core that is currently running
const Kernel::PhysicalCore& CurrentPhysicalCore() const;
[[nodiscard]] const Kernel::PhysicalCore& CurrentPhysicalCore() const;
/// Gets a reference to an ARM interface for the CPU core with the specified index
ARM_Interface& ArmInterface(std::size_t core_index);
[[nodiscard]] ARM_Interface& ArmInterface(std::size_t core_index);
/// Gets a const reference to an ARM interface from the CPU core with the specified index
const ARM_Interface& ArmInterface(std::size_t core_index) const;
[[nodiscard]] const ARM_Interface& ArmInterface(std::size_t core_index) const;
CpuManager& GetCpuManager();
/// Gets a reference to the underlying CPU manager.
[[nodiscard]] CpuManager& GetCpuManager();
const CpuManager& GetCpuManager() const;
/// Gets a const reference to the underlying CPU manager
[[nodiscard]] const CpuManager& GetCpuManager() const;
/// Gets a reference to the exclusive monitor
ExclusiveMonitor& Monitor();
[[nodiscard]] ExclusiveMonitor& Monitor();
/// Gets a constant reference to the exclusive monitor
const ExclusiveMonitor& Monitor() const;
[[nodiscard]] const ExclusiveMonitor& Monitor() const;
/// Gets a mutable reference to the system memory instance.
Core::Memory::Memory& Memory();
[[nodiscard]] Core::Memory::Memory& Memory();
/// Gets a constant reference to the system memory instance.
const Core::Memory::Memory& Memory() const;
[[nodiscard]] const Core::Memory::Memory& Memory() const;
/// Gets a mutable reference to the GPU interface
Tegra::GPU& GPU();
[[nodiscard]] Tegra::GPU& GPU();
/// Gets an immutable reference to the GPU interface.
const Tegra::GPU& GPU() const;
[[nodiscard]] const Tegra::GPU& GPU() const;
/// Gets a mutable reference to the renderer.
VideoCore::RendererBase& Renderer();
[[nodiscard]] VideoCore::RendererBase& Renderer();
/// Gets an immutable reference to the renderer.
const VideoCore::RendererBase& Renderer() const;
[[nodiscard]] const VideoCore::RendererBase& Renderer() const;
/// Gets the scheduler for the CPU core with the specified index
Kernel::Scheduler& Scheduler(std::size_t core_index);
[[nodiscard]] Kernel::Scheduler& Scheduler(std::size_t core_index);
/// Gets the scheduler for the CPU core with the specified index
const Kernel::Scheduler& Scheduler(std::size_t core_index) const;
[[nodiscard]] const Kernel::Scheduler& Scheduler(std::size_t core_index) const;
/// Gets the global scheduler
Kernel::GlobalScheduler& GlobalScheduler();
[[nodiscard]] Kernel::GlobalScheduler& GlobalScheduler();
/// Gets the global scheduler
const Kernel::GlobalScheduler& GlobalScheduler() const;
[[nodiscard]] const Kernel::GlobalScheduler& GlobalScheduler() const;
/// Gets the manager for the guest device memory
Core::DeviceMemory& DeviceMemory();
[[nodiscard]] Core::DeviceMemory& DeviceMemory();
/// Gets the manager for the guest device memory
const Core::DeviceMemory& DeviceMemory() const;
[[nodiscard]] const Core::DeviceMemory& DeviceMemory() const;
/// Provides a pointer to the current process
Kernel::Process* CurrentProcess();
[[nodiscard]] Kernel::Process* CurrentProcess();
/// Provides a constant pointer to the current process.
const Kernel::Process* CurrentProcess() const;
[[nodiscard]] const Kernel::Process* CurrentProcess() const;
/// Provides a reference to the core timing instance.
Timing::CoreTiming& CoreTiming();
[[nodiscard]] Timing::CoreTiming& CoreTiming();
/// Provides a constant reference to the core timing instance.
const Timing::CoreTiming& CoreTiming() const;
[[nodiscard]] const Timing::CoreTiming& CoreTiming() const;
/// Provides a reference to the interrupt manager instance.
Core::Hardware::InterruptManager& InterruptManager();
[[nodiscard]] Core::Hardware::InterruptManager& InterruptManager();
/// Provides a constant reference to the interrupt manager instance.
const Core::Hardware::InterruptManager& InterruptManager() const;
[[nodiscard]] const Core::Hardware::InterruptManager& InterruptManager() const;
/// Provides a reference to the kernel instance.
Kernel::KernelCore& Kernel();
[[nodiscard]] Kernel::KernelCore& Kernel();
/// Provides a constant reference to the kernel instance.
const Kernel::KernelCore& Kernel() const;
[[nodiscard]] const Kernel::KernelCore& Kernel() const;
/// Provides a reference to the internal PerfStats instance.
Core::PerfStats& GetPerfStats();
[[nodiscard]] Core::PerfStats& GetPerfStats();
/// Provides a constant reference to the internal PerfStats instance.
const Core::PerfStats& GetPerfStats() const;
[[nodiscard]] const Core::PerfStats& GetPerfStats() const;
/// Provides a reference to the frame limiter;
Core::FrameLimiter& FrameLimiter();
[[nodiscard]] Core::FrameLimiter& FrameLimiter();
/// Provides a constant referent to the frame limiter
const Core::FrameLimiter& FrameLimiter() const;
[[nodiscard]] const Core::FrameLimiter& FrameLimiter() const;
/// Gets the name of the current game
Loader::ResultStatus GetGameName(std::string& out) const;
[[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const;
void SetStatus(ResultStatus new_status, const char* details);
const std::string& GetStatusDetails() const;
[[nodiscard]] const std::string& GetStatusDetails() const;
Loader::AppLoader& GetAppLoader() const;
[[nodiscard]] Loader::AppLoader& GetAppLoader();
[[nodiscard]] const Loader::AppLoader& GetAppLoader() const;
Service::SM::ServiceManager& ServiceManager();
const Service::SM::ServiceManager& ServiceManager() const;
[[nodiscard]] Service::SM::ServiceManager& ServiceManager();
[[nodiscard]] const Service::SM::ServiceManager& ServiceManager() const;
void SetFilesystem(FileSys::VirtualFilesystem vfs);
FileSys::VirtualFilesystem GetFilesystem() const;
[[nodiscard]] FileSys::VirtualFilesystem GetFilesystem() const;
void RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
const std::array<u8, 0x20>& build_id, VAddr main_region_begin,
u64 main_region_size);
void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set);
void SetDefaultAppletFrontendSet();
Service::AM::Applets::AppletManager& GetAppletManager();
const Service::AM::Applets::AppletManager& GetAppletManager() const;
[[nodiscard]] Service::AM::Applets::AppletManager& GetAppletManager();
[[nodiscard]] const Service::AM::Applets::AppletManager& GetAppletManager() const;
void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);
FileSys::ContentProvider& GetContentProvider();
[[nodiscard]] FileSys::ContentProvider& GetContentProvider();
[[nodiscard]] const FileSys::ContentProvider& GetContentProvider() const;
const FileSys::ContentProvider& GetContentProvider() const;
Service::FileSystem::FileSystemController& GetFileSystemController();
const Service::FileSystem::FileSystemController& GetFileSystemController() const;
[[nodiscard]] Service::FileSystem::FileSystemController& GetFileSystemController();
[[nodiscard]] const Service::FileSystem::FileSystemController& GetFileSystemController() const;
void RegisterContentProvider(FileSys::ContentProviderUnionSlot slot,
FileSys::ContentProvider* provider);
void ClearContentProvider(FileSys::ContentProviderUnionSlot slot);
const Reporter& GetReporter() const;
[[nodiscard]] const Reporter& GetReporter() const;
Service::Glue::ARPManager& GetARPManager();
[[nodiscard]] Service::Glue::ARPManager& GetARPManager();
[[nodiscard]] const Service::Glue::ARPManager& GetARPManager() const;
const Service::Glue::ARPManager& GetARPManager() const;
[[nodiscard]] Service::APM::Controller& GetAPMController();
[[nodiscard]] const Service::APM::Controller& GetAPMController() const;
Service::APM::Controller& GetAPMController();
[[nodiscard]] Service::LM::Manager& GetLogManager();
[[nodiscard]] const Service::LM::Manager& GetLogManager() const;
const Service::APM::Controller& GetAPMController() const;
Service::LM::Manager& GetLogManager();
const Service::LM::Manager& GetLogManager() const;
Service::Time::TimeManager& GetTimeManager();
const Service::Time::TimeManager& GetTimeManager() const;
[[nodiscard]] Service::Time::TimeManager& GetTimeManager();
[[nodiscard]] const Service::Time::TimeManager& GetTimeManager() const;
void SetExitLock(bool locked);
bool GetExitLock() const;
[[nodiscard]] bool GetExitLock() const;
void SetCurrentProcessBuildID(const CurrentBuildProcessID& id);
const CurrentBuildProcessID& GetCurrentProcessBuildID() const;
[[nodiscard]] const CurrentBuildProcessID& GetCurrentProcessBuildID() const;
/// Register a host thread as an emulated CPU Core.
void RegisterCoreThread(std::size_t id);
@@ -390,19 +386,28 @@ public:
void ExitDynarmicProfile();
/// Tells if system is running on multicore.
bool IsMulticore() const;
[[nodiscard]] bool IsMulticore() const;
/// Type used for the frontend to designate a callback for System to re-launch the application
/// using a specified program index.
using ExecuteProgramCallback = std::function<void(std::size_t)>;
/**
* Registers a callback from the frontend for System to re-launch the application using a
* specified program index.
* @param callback Callback from the frontend to relaunch the application.
*/
void RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback);
/**
* Instructs the frontend to re-launch the application using the specified program_index.
* @param program_index Specifies the index within the application of the program to launch.
*/
void ExecuteProgram(std::size_t program_index);
private:
System();
/**
* Initialize the emulated system.
* @param emu_window Reference to the host-system window used for video output and keyboard
* input.
* @return ResultStatus code, indicating if the operation succeeded.
*/
ResultStatus Init(Frontend::EmuWindow& emu_window);
struct Impl;
std::unique_ptr<Impl> impl;

View File

@@ -29,7 +29,7 @@ constexpr std::array partition_names{
"logo",
};
XCI::XCI(VirtualFile file_)
XCI::XCI(VirtualFile file_, std::size_t program_index)
: file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA},
partitions(partition_names.size()),
partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} {
@@ -62,7 +62,8 @@ XCI::XCI(VirtualFile file_)
}
secure_partition = std::make_shared<NSP>(
main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)]));
main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)]),
program_index);
ncas = secure_partition->GetNCAsCollapsed();
program =

View File

@@ -78,7 +78,7 @@ enum class XCIPartition : u8 { Update, Normal, Secure, Logo };
class XCI : public ReadOnlyVfsDirectory {
public:
explicit XCI(VirtualFile file);
explicit XCI(VirtualFile file, std::size_t program_index = 0);
~XCI() override;
Loader::ResultStatus GetStatus() const;

View File

@@ -20,8 +20,8 @@
namespace FileSys {
NSP::NSP(VirtualFile file_)
: file(std::move(file_)), status{Loader::ResultStatus::Success},
NSP::NSP(VirtualFile file_, std::size_t program_index)
: file(std::move(file_)), program_index(program_index), status{Loader::ResultStatus::Success},
pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} {
if (pfs->GetStatus() != Loader::ResultStatus::Success) {
status = pfs->GetStatus();
@@ -146,7 +146,7 @@ std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type, TitleType
if (extracted)
LOG_WARNING(Service_FS, "called on an NSP that is of type extracted.");
const auto title_id_iter = ncas.find(title_id);
const auto title_id_iter = ncas.find(title_id + program_index);
if (title_id_iter == ncas.end())
return nullptr;

View File

@@ -27,7 +27,7 @@ enum class ContentRecordType : u8;
class NSP : public ReadOnlyVfsDirectory {
public:
explicit NSP(VirtualFile file);
explicit NSP(VirtualFile file, std::size_t program_index = 0);
~NSP() override;
Loader::ResultStatus GetStatus() const;
@@ -69,6 +69,8 @@ private:
VirtualFile file;
const std::size_t program_index;
bool extracted = false;
Loader::ResultStatus status;
std::map<u64, Loader::ResultStatus> program_status;

View File

@@ -30,10 +30,12 @@ public:
virtual StatusType GetStatus() const {
return {};
}
virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const {
virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const {
return {};
}
virtual bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const {
virtual bool SetRumblePlay([[maybe_unused]] f32 amp_low, [[maybe_unused]] f32 freq_low,
[[maybe_unused]] f32 amp_high,
[[maybe_unused]] f32 freq_high) const {
return {};
}
};

View File

@@ -681,7 +681,7 @@ static void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) {
}
/// Used to output a message on a debug hardware unit - does nothing on a retail unit
static void OutputDebugString([[maybe_unused]] Core::System& system, VAddr address, u64 len) {
static void OutputDebugString(Core::System& system, VAddr address, u64 len) {
if (len == 0) {
return;
}

View File

@@ -246,9 +246,8 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} {
IDebugFunctions::~IDebugFunctions() = default;
ISelfController::ISelfController(Core::System& system,
std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
: ServiceFramework("ISelfController"), system(system), nvflinger(std::move(nvflinger)) {
ISelfController::ISelfController(Core::System& system, NVFlinger::NVFlinger& nvflinger)
: ServiceFramework("ISelfController"), system(system), nvflinger(nvflinger) {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ISelfController::Exit, "Exit"},
@@ -458,8 +457,8 @@ void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx)
// TODO(Subv): Find out how AM determines the display to use, for now just
// create the layer in the Default display.
const auto display_id = nvflinger->OpenDisplay("Default");
const auto layer_id = nvflinger->CreateLayer(*display_id);
const auto display_id = nvflinger.OpenDisplay("Default");
const auto layer_id = nvflinger.CreateLayer(*display_id);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
@@ -476,8 +475,8 @@ void ISelfController::CreateManagedDisplaySeparableLayer(Kernel::HLERequestConte
// Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
// side effects.
// TODO: Support multiple layers
const auto display_id = nvflinger->OpenDisplay("Default");
const auto layer_id = nvflinger->CreateLayer(*display_id);
const auto display_id = nvflinger.OpenDisplay("Default");
const auto layer_id = nvflinger.CreateLayer(*display_id);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
@@ -1189,9 +1188,9 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
{102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
{110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"},
{111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"},
{120, nullptr, "ExecuteProgram"},
{121, nullptr, "ClearUserChannel"},
{122, nullptr, "UnpopToUserChannel"},
{120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"},
{121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"},
{122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"},
{123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
{124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
{130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
@@ -1562,6 +1561,34 @@ void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(Kernel::HLEReque
rb.Push<u32>(0);
}
void IApplicationFunctions::ExecuteProgram(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::RequestParser rp{ctx};
[[maybe_unused]] const auto unk_1 = rp.Pop<u32>();
[[maybe_unused]] const auto unk_2 = rp.Pop<u32>();
const auto program_index = rp.Pop<u64>();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
system.ExecuteProgram(program_index);
}
void IApplicationFunctions::ClearUserChannel(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void IApplicationFunctions::UnpopToUserChannel(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void IApplicationFunctions::GetPreviousProgramIndex(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
@@ -1586,8 +1613,8 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERe
rb.PushCopyObjects(friend_invitation_storage_channel_event.readable);
}
void InstallInterfaces(SM::ServiceManager& service_manager,
std::shared_ptr<NVFlinger::NVFlinger> nvflinger, Core::System& system) {
void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
Core::System& system) {
auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel());
// Needed on game boot
message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);

View File

@@ -121,8 +121,7 @@ public:
class ISelfController final : public ServiceFramework<ISelfController> {
public:
explicit ISelfController(Core::System& system_,
std::shared_ptr<NVFlinger::NVFlinger> nvflinger_);
explicit ISelfController(Core::System& system_, NVFlinger::NVFlinger& nvflinger_);
~ISelfController() override;
private:
@@ -156,7 +155,7 @@ private:
};
Core::System& system;
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
NVFlinger::NVFlinger& nvflinger;
Kernel::EventPair launchable_event;
Kernel::EventPair accumulated_suspended_tick_changed_event;
@@ -288,6 +287,9 @@ private:
void SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx);
void QueryApplicationPlayStatistics(Kernel::HLERequestContext& ctx);
void QueryApplicationPlayStatisticsByUid(Kernel::HLERequestContext& ctx);
void ExecuteProgram(Kernel::HLERequestContext& ctx);
void ClearUserChannel(Kernel::HLERequestContext& ctx);
void UnpopToUserChannel(Kernel::HLERequestContext& ctx);
void GetPreviousProgramIndex(Kernel::HLERequestContext& ctx);
void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx);
@@ -332,7 +334,7 @@ public:
};
/// Registers all AM services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager,
std::shared_ptr<NVFlinger::NVFlinger> nvflinger, Core::System& system);
void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
Core::System& system);
} // namespace Service::AM

View File

@@ -13,10 +13,10 @@ namespace Service::AM {
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
public:
explicit ILibraryAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
explicit ILibraryAppletProxy(NVFlinger::NVFlinger& nvflinger,
std::shared_ptr<AppletMessageQueue> msg_queue,
Core::System& system)
: ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)),
: ServiceFramework("ILibraryAppletProxy"), nvflinger(nvflinger),
msg_queue(std::move(msg_queue)), system(system) {
// clang-format off
static const FunctionInfo functions[] = {
@@ -109,16 +109,16 @@ private:
rb.PushIpcInterface<IApplicationFunctions>(system);
}
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
NVFlinger::NVFlinger& nvflinger;
std::shared_ptr<AppletMessageQueue> msg_queue;
Core::System& system;
};
class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
public:
explicit ISystemAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
explicit ISystemAppletProxy(NVFlinger::NVFlinger& nvflinger,
std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system)
: ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)),
: ServiceFramework("ISystemAppletProxy"), nvflinger(nvflinger),
msg_queue(std::move(msg_queue)), system(system) {
// clang-format off
static const FunctionInfo functions[] = {
@@ -220,7 +220,8 @@ private:
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationCreator>();
}
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
NVFlinger::NVFlinger& nvflinger;
std::shared_ptr<AppletMessageQueue> msg_queue;
Core::System& system;
};
@@ -249,10 +250,10 @@ void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) {
rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue, system);
}
AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system)
: ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)),
msg_queue(std::move(msg_queue)), system(system) {
AppletAE::AppletAE(NVFlinger::NVFlinger& nvflinger, std::shared_ptr<AppletMessageQueue> msg_queue,
Core::System& system)
: ServiceFramework("appletAE"), nvflinger(nvflinger), msg_queue(std::move(msg_queue)),
system(system) {
// clang-format off
static const FunctionInfo functions[] = {
{100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"},

View File

@@ -23,7 +23,7 @@ class AppletMessageQueue;
class AppletAE final : public ServiceFramework<AppletAE> {
public:
explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
explicit AppletAE(NVFlinger::NVFlinger& nvflinger,
std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system);
~AppletAE() override;
@@ -34,7 +34,7 @@ private:
void OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx);
void OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx);
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
NVFlinger::NVFlinger& nvflinger;
std::shared_ptr<AppletMessageQueue> msg_queue;
Core::System& system;
};

View File

@@ -12,9 +12,9 @@ namespace Service::AM {
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
public:
explicit IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
explicit IApplicationProxy(NVFlinger::NVFlinger& nvflinger,
std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system)
: ServiceFramework("IApplicationProxy"), nvflinger(std::move(nvflinger)),
: ServiceFramework("IApplicationProxy"), nvflinger(nvflinger),
msg_queue(std::move(msg_queue)), system(system) {
// clang-format off
static const FunctionInfo functions[] = {
@@ -98,7 +98,7 @@ private:
rb.PushIpcInterface<IApplicationFunctions>(system);
}
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
NVFlinger::NVFlinger& nvflinger;
std::shared_ptr<AppletMessageQueue> msg_queue;
Core::System& system;
};
@@ -111,10 +111,10 @@ void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) {
rb.PushIpcInterface<IApplicationProxy>(nvflinger, msg_queue, system);
}
AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system)
: ServiceFramework("appletOE"), nvflinger(std::move(nvflinger)),
msg_queue(std::move(msg_queue)), system(system) {
AppletOE::AppletOE(NVFlinger::NVFlinger& nvflinger, std::shared_ptr<AppletMessageQueue> msg_queue,
Core::System& system)
: ServiceFramework("appletOE"), nvflinger(nvflinger), msg_queue(std::move(msg_queue)),
system(system) {
static const FunctionInfo functions[] = {
{0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"},
};

View File

@@ -23,7 +23,7 @@ class AppletMessageQueue;
class AppletOE final : public ServiceFramework<AppletOE> {
public:
explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
explicit AppletOE(NVFlinger::NVFlinger& nvflinger,
std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system);
~AppletOE() override;
@@ -32,7 +32,7 @@ public:
private:
void OpenApplicationProxy(Kernel::HLERequestContext& ctx);
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
NVFlinger::NVFlinger& nvflinger;
std::shared_ptr<AppletMessageQueue> msg_queue;
Core::System& system;
};

View File

@@ -188,17 +188,19 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
return RESULT_SUCCESS;
}
/// Initialize ServiceManager
void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) {
/// Initialize Services
Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system)
: nv_flinger{std::make_unique<NVFlinger::NVFlinger>(system)} {
// NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
// here and pass it into the respective InstallInterfaces functions.
auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>(system);
system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false);
SM::ServiceManager::InstallInterfaces(sm, system.Kernel());
Account::InstallInterfaces(system);
AM::InstallInterfaces(*sm, nv_flinger, system);
AM::InstallInterfaces(*sm, *nv_flinger, system);
AOC::InstallInterfaces(*sm, system);
APM::InstallInterfaces(system);
Audio::InstallInterfaces(*sm, system);
@@ -246,14 +248,10 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) {
SSL::InstallInterfaces(*sm);
Time::InstallInterfaces(system);
USB::InstallInterfaces(*sm);
VI::InstallInterfaces(*sm, nv_flinger);
VI::InstallInterfaces(*sm, *nv_flinger);
WLAN::InstallInterfaces(*sm);
LOG_DEBUG(Service, "initialized OK");
}
/// Shutdown ServiceManager
void Shutdown() {
LOG_DEBUG(Service, "shutdown OK");
}
Services::~Services() = default;
} // namespace Service

View File

@@ -29,7 +29,11 @@ namespace Service {
namespace FileSystem {
class FileSystemController;
} // namespace FileSystem
}
namespace NVFlinger {
class NVFlinger;
}
namespace SM {
class ServiceManager;
@@ -181,10 +185,17 @@ private:
}
};
/// Initialize ServiceManager
void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system);
/**
* The purpose of this class is to own any objects that need to be shared across the other service
* implementations. Will be torn down when the global system instance is shutdown.
*/
class Services final {
public:
explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system);
~Services();
/// Shutdown ServiceManager
void Shutdown();
private:
std::unique_ptr<NVFlinger::NVFlinger> nv_flinger;
};
} // namespace Service

View File

@@ -492,8 +492,8 @@ private:
class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
public:
explicit IHOSBinderDriver(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
: ServiceFramework("IHOSBinderDriver"), nv_flinger(std::move(nv_flinger)) {
explicit IHOSBinderDriver(NVFlinger::NVFlinger& nv_flinger)
: ServiceFramework("IHOSBinderDriver"), nv_flinger(nv_flinger) {
static const FunctionInfo functions[] = {
{0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
{1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},
@@ -530,8 +530,8 @@ private:
LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
static_cast<u32>(transaction), flags);
const auto guard = nv_flinger->Lock();
auto& buffer_queue = nv_flinger->FindBufferQueue(id);
const auto guard = nv_flinger.Lock();
auto& buffer_queue = nv_flinger.FindBufferQueue(id);
switch (transaction) {
case TransactionId::Connect: {
@@ -570,8 +570,8 @@ private:
[=, this](std::shared_ptr<Kernel::Thread> thread,
Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) {
// Repeat TransactParcel DequeueBuffer when a buffer is available
const auto guard = nv_flinger->Lock();
auto& buffer_queue = nv_flinger->FindBufferQueue(id);
const auto guard = nv_flinger.Lock();
auto& buffer_queue = nv_flinger.FindBufferQueue(id);
auto result = buffer_queue.DequeueBuffer(width, height);
ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer.");
@@ -676,7 +676,7 @@ private:
LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
const auto& buffer_queue = nv_flinger->FindBufferQueue(id);
const auto& buffer_queue = nv_flinger.FindBufferQueue(id);
// TODO(Subv): Find out what this actually is.
IPC::ResponseBuilder rb{ctx, 2, 1};
@@ -684,8 +684,8 @@ private:
rb.PushCopyObjects(buffer_queue.GetBufferWaitEvent());
}
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
}; // namespace VI
NVFlinger::NVFlinger& nv_flinger;
};
class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
public:
@@ -790,8 +790,8 @@ private:
class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
public:
explicit IManagerDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
: ServiceFramework("IManagerDisplayService"), nv_flinger(std::move(nv_flinger)) {
explicit IManagerDisplayService(NVFlinger::NVFlinger& nv_flinger)
: ServiceFramework("IManagerDisplayService"), nv_flinger(nv_flinger) {
// clang-format off
static const FunctionInfo functions[] = {
{200, nullptr, "AllocateProcessHeapBlock"},
@@ -893,7 +893,7 @@ private:
"(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}",
unknown, display, aruid);
const auto layer_id = nv_flinger->CreateLayer(display);
const auto layer_id = nv_flinger.CreateLayer(display);
if (!layer_id) {
LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display);
IPC::ResponseBuilder rb{ctx, 2};
@@ -930,12 +930,12 @@ private:
rb.Push(RESULT_SUCCESS);
}
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
NVFlinger::NVFlinger& nv_flinger;
};
class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
public:
explicit IApplicationDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
explicit IApplicationDisplayService(NVFlinger::NVFlinger& nv_flinger);
private:
enum class ConvertedScaleMode : u64 {
@@ -1010,7 +1010,7 @@ private:
ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet");
const auto display_id = nv_flinger->OpenDisplay(name);
const auto display_id = nv_flinger.OpenDisplay(name);
if (!display_id) {
LOG_ERROR(Service_VI, "Display not found! display_name={}", name);
IPC::ResponseBuilder rb{ctx, 2};
@@ -1110,7 +1110,7 @@ private:
LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid);
const auto display_id = nv_flinger->OpenDisplay(display_name);
const auto display_id = nv_flinger.OpenDisplay(display_name);
if (!display_id) {
LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id);
IPC::ResponseBuilder rb{ctx, 2};
@@ -1118,7 +1118,7 @@ private:
return;
}
const auto buffer_queue_id = nv_flinger->FindBufferQueueId(*display_id, layer_id);
const auto buffer_queue_id = nv_flinger.FindBufferQueueId(*display_id, layer_id);
if (!buffer_queue_id) {
LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id);
IPC::ResponseBuilder rb{ctx, 2};
@@ -1138,7 +1138,7 @@ private:
LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id);
nv_flinger->CloseLayer(layer_id);
nv_flinger.CloseLayer(layer_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -1154,7 +1154,7 @@ private:
// TODO(Subv): What's the difference between a Stray and a Managed layer?
const auto layer_id = nv_flinger->CreateLayer(display_id);
const auto layer_id = nv_flinger.CreateLayer(display_id);
if (!layer_id) {
LOG_ERROR(Service_VI, "Layer not found! layer_id={}", *layer_id);
IPC::ResponseBuilder rb{ctx, 2};
@@ -1162,7 +1162,7 @@ private:
return;
}
const auto buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, *layer_id);
const auto buffer_queue_id = nv_flinger.FindBufferQueueId(display_id, *layer_id);
if (!buffer_queue_id) {
LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
IPC::ResponseBuilder rb{ctx, 2};
@@ -1193,7 +1193,7 @@ private:
LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id);
const auto vsync_event = nv_flinger->FindVsyncEvent(display_id);
const auto vsync_event = nv_flinger.FindVsyncEvent(display_id);
if (!vsync_event) {
LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
IPC::ResponseBuilder rb{ctx, 2};
@@ -1258,12 +1258,11 @@ private:
}
}
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
NVFlinger::NVFlinger& nv_flinger;
};
IApplicationDisplayService::IApplicationDisplayService(
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
: ServiceFramework("IApplicationDisplayService"), nv_flinger(std::move(nv_flinger)) {
IApplicationDisplayService::IApplicationDisplayService(NVFlinger::NVFlinger& nv_flinger)
: ServiceFramework("IApplicationDisplayService"), nv_flinger(nv_flinger) {
static const FunctionInfo functions[] = {
{100, &IApplicationDisplayService::GetRelayService, "GetRelayService"},
{101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"},
@@ -1304,8 +1303,7 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) {
return false;
}
void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx,
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger,
void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, NVFlinger::NVFlinger& nv_flinger,
Permission permission) {
IPC::RequestParser rp{ctx};
const auto policy = rp.PopEnum<Policy>();
@@ -1319,11 +1317,10 @@ void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx,
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationDisplayService>(std::move(nv_flinger));
rb.PushIpcInterface<IApplicationDisplayService>(nv_flinger);
}
void InstallInterfaces(SM::ServiceManager& service_manager,
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) {
void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nv_flinger) {
std::make_shared<VI_M>(nv_flinger)->InstallAsService(service_manager);
std::make_shared<VI_S>(nv_flinger)->InstallAsService(service_manager);
std::make_shared<VI_U>(nv_flinger)->InstallAsService(service_manager);

View File

@@ -43,12 +43,11 @@ enum class Policy {
};
namespace detail {
void GetDisplayServiceImpl(Kernel::HLERequestContext& ctx,
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger, Permission permission);
void GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, NVFlinger::NVFlinger& nv_flinger,
Permission permission);
} // namespace detail
/// Registers all VI services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager,
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nv_flinger);
} // namespace Service::VI

View File

@@ -8,8 +8,7 @@
namespace Service::VI {
VI_M::VI_M(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
: ServiceFramework{"vi:m"}, nv_flinger{std::move(nv_flinger)} {
VI_M::VI_M(NVFlinger::NVFlinger& nv_flinger) : ServiceFramework{"vi:m"}, nv_flinger{nv_flinger} {
static const FunctionInfo functions[] = {
{2, &VI_M::GetDisplayService, "GetDisplayService"},
{3, nullptr, "GetDisplayServiceWithProxyNameExchange"},

View File

@@ -18,13 +18,13 @@ namespace Service::VI {
class VI_M final : public ServiceFramework<VI_M> {
public:
explicit VI_M(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
explicit VI_M(NVFlinger::NVFlinger& nv_flinger);
~VI_M() override;
private:
void GetDisplayService(Kernel::HLERequestContext& ctx);
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
NVFlinger::NVFlinger& nv_flinger;
};
} // namespace Service::VI

View File

@@ -8,8 +8,7 @@
namespace Service::VI {
VI_S::VI_S(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
: ServiceFramework{"vi:s"}, nv_flinger{std::move(nv_flinger)} {
VI_S::VI_S(NVFlinger::NVFlinger& nv_flinger) : ServiceFramework{"vi:s"}, nv_flinger{nv_flinger} {
static const FunctionInfo functions[] = {
{1, &VI_S::GetDisplayService, "GetDisplayService"},
{3, nullptr, "GetDisplayServiceWithProxyNameExchange"},

View File

@@ -18,13 +18,13 @@ namespace Service::VI {
class VI_S final : public ServiceFramework<VI_S> {
public:
explicit VI_S(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
explicit VI_S(NVFlinger::NVFlinger& nv_flinger);
~VI_S() override;
private:
void GetDisplayService(Kernel::HLERequestContext& ctx);
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
NVFlinger::NVFlinger& nv_flinger;
};
} // namespace Service::VI

View File

@@ -8,8 +8,7 @@
namespace Service::VI {
VI_U::VI_U(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
: ServiceFramework{"vi:u"}, nv_flinger{std::move(nv_flinger)} {
VI_U::VI_U(NVFlinger::NVFlinger& nv_flinger) : ServiceFramework{"vi:u"}, nv_flinger{nv_flinger} {
static const FunctionInfo functions[] = {
{0, &VI_U::GetDisplayService, "GetDisplayService"},
{1, nullptr, "GetDisplayServiceWithProxyNameExchange"},

View File

@@ -18,13 +18,13 @@ namespace Service::VI {
class VI_U final : public ServiceFramework<VI_U> {
public:
explicit VI_U(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
explicit VI_U(NVFlinger::NVFlinger& nv_flinger);
~VI_U() override;
private:
void GetDisplayService(Kernel::HLERequestContext& ctx);
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
NVFlinger::NVFlinger& nv_flinger;
};
} // namespace Service::VI

View File

@@ -198,10 +198,11 @@ AppLoader::~AppLoader() = default;
* @param system The system context to use.
* @param file The file to retrieve the loader for
* @param type The file type
* @param program_index Specifies the index within the container of the program to launch.
* @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type
*/
static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::VirtualFile file,
FileType type) {
FileType type, std::size_t program_index) {
switch (type) {
// Standard ELF file format.
case FileType::ELF:
@@ -222,7 +223,7 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V
// NX XCI (nX Card Image) file format.
case FileType::XCI:
return std::make_unique<AppLoader_XCI>(std::move(file), system.GetFileSystemController(),
system.GetContentProvider());
system.GetContentProvider(), program_index);
// NX NAX (NintendoAesXts) file format.
case FileType::NAX:
@@ -231,7 +232,7 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V
// NX NSP (Nintendo Submission Package) file format
case FileType::NSP:
return std::make_unique<AppLoader_NSP>(std::move(file), system.GetFileSystemController(),
system.GetContentProvider());
system.GetContentProvider(), program_index);
// NX KIP (Kernel Internal Process) file format
case FileType::KIP:
@@ -246,7 +247,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V
}
}
std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file) {
std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file,
std::size_t program_index) {
FileType type = IdentifyFile(file);
const FileType filename_type = GuessFromFilename(file->GetName());
@@ -260,7 +262,7 @@ std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile
LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type));
return GetFileLoader(system, std::move(file), type);
return GetFileLoader(system, std::move(file), type, program_index);
}
} // namespace Loader

View File

@@ -293,9 +293,11 @@ protected:
*
* @param system The system context.
* @param file The bootable file.
* @param program_index Specifies the index within the container of the program to launch.
*
* @return the best loader for this file.
*/
std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file);
std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file,
std::size_t program_index = 0);
} // namespace Loader

View File

@@ -23,8 +23,9 @@ namespace Loader {
AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file,
const Service::FileSystem::FileSystemController& fsc,
const FileSys::ContentProvider& content_provider)
: AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file)),
const FileSys::ContentProvider& content_provider,
std::size_t program_index)
: AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file, program_index)),
title_id(nsp->GetProgramTitleID()) {
if (nsp->GetStatus() != ResultStatus::Success) {

View File

@@ -28,7 +28,8 @@ class AppLoader_NSP final : public AppLoader {
public:
explicit AppLoader_NSP(FileSys::VirtualFile file,
const Service::FileSystem::FileSystemController& fsc,
const FileSys::ContentProvider& content_provider);
const FileSys::ContentProvider& content_provider,
std::size_t program_index);
~AppLoader_NSP() override;
/**

View File

@@ -22,8 +22,9 @@ namespace Loader {
AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file,
const Service::FileSystem::FileSystemController& fsc,
const FileSys::ContentProvider& content_provider)
: AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)),
const FileSys::ContentProvider& content_provider,
std::size_t program_index)
: AppLoader(file), xci(std::make_unique<FileSys::XCI>(file, program_index)),
nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) {
if (xci->GetStatus() != ResultStatus::Success) {
return;

View File

@@ -28,7 +28,8 @@ class AppLoader_XCI final : public AppLoader {
public:
explicit AppLoader_XCI(FileSys::VirtualFile file,
const Service::FileSystem::FileSystemController& fsc,
const FileSys::ContentProvider& content_provider);
const FileSys::ContentProvider& content_provider,
std::size_t program_index);
~AppLoader_XCI() override;
/**

View File

@@ -31,6 +31,9 @@ add_library(input_common STATIC
if (MSVC)
target_compile_options(input_common PRIVATE
/W4
/WX
# 'expression' : signed/unsigned mismatch
/we4018
# 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point)
@@ -46,6 +49,7 @@ if (MSVC)
)
else()
target_compile_options(input_common PRIVATE
-Werror
-Werror=conversion
-Werror=ignored-qualifiers
-Werror=implicit-fallthrough

View File

@@ -2,6 +2,10 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <chrono>
#include <cmath>
#include <thread>
#include "common/math_util.h"
#include "input_common/analog_from_button.h"
namespace InputCommon {
@@ -11,31 +15,104 @@ public:
using Button = std::unique_ptr<Input::ButtonDevice>;
Analog(Button up_, Button down_, Button left_, Button right_, Button modifier_,
float modifier_scale_)
float modifier_scale_, float modifier_angle_)
: up(std::move(up_)), down(std::move(down_)), left(std::move(left_)),
right(std::move(right_)), modifier(std::move(modifier_)),
modifier_scale(modifier_scale_) {}
right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_),
modifier_angle(modifier_angle_) {
update_thread = std::thread(&Analog::UpdateStatus, this);
}
~Analog() override {
update_thread_running = false;
if (update_thread.joinable()) {
update_thread.join();
}
}
void MoveToDirection(bool enable, float to_angle) {
if (!enable) {
return;
}
constexpr float TAU = Common::PI * 2.0f;
// Use wider angle to ease the transition.
constexpr float aperture = TAU * 0.15f;
const float top_limit = to_angle + aperture;
const float bottom_limit = to_angle - aperture;
if ((angle > to_angle && angle <= top_limit) ||
(angle + TAU > to_angle && angle + TAU <= top_limit)) {
angle -= modifier_angle;
if (angle < 0) {
angle += TAU;
}
} else if ((angle >= bottom_limit && angle < to_angle) ||
(angle - TAU >= bottom_limit && angle - TAU < to_angle)) {
angle += modifier_angle;
if (angle >= TAU) {
angle -= TAU;
}
} else {
angle = to_angle;
}
}
void UpdateStatus() {
while (update_thread_running) {
const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
bool r = right->GetStatus();
bool l = left->GetStatus();
bool u = up->GetStatus();
bool d = down->GetStatus();
// Eliminate contradictory movements
if (r && l) {
r = false;
l = false;
}
if (u && d) {
u = false;
d = false;
}
// Move to the right
MoveToDirection(r && !u && !d, 0.0f);
// Move to the upper right
MoveToDirection(r && u && !d, Common::PI * 0.25f);
// Move up
MoveToDirection(u && !l && !r, Common::PI * 0.5f);
// Move to the upper left
MoveToDirection(l && u && !d, Common::PI * 0.75f);
// Move to the left
MoveToDirection(l && !u && !d, Common::PI);
// Move to the bottom left
MoveToDirection(l && !u && d, Common::PI * 1.25f);
// Move down
MoveToDirection(d && !l && !r, Common::PI * 1.5f);
// Move to the bottom right
MoveToDirection(r && !u && d, Common::PI * 1.75f);
// Move if a key is pressed
if (r || l || u || d) {
amplitude = coef;
} else {
amplitude = 0;
}
// Delay the update rate to 100hz
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
std::tuple<float, float> GetStatus() const override {
constexpr float SQRT_HALF = 0.707106781f;
int x = 0, y = 0;
if (right->GetStatus()) {
++x;
}
if (left->GetStatus()) {
--x;
}
if (up->GetStatus()) {
++y;
}
if (down->GetStatus()) {
--y;
}
const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
return std::make_tuple(static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF),
static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF));
return std::make_tuple(std::cos(angle) * amplitude, std::sin(angle) * amplitude);
}
bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
@@ -59,6 +136,11 @@ private:
Button right;
Button modifier;
float modifier_scale;
float modifier_angle;
float angle{};
float amplitude{};
std::thread update_thread;
bool update_thread_running{true};
};
std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::ParamPackage& params) {
@@ -69,8 +151,10 @@ std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::Para
auto right = Input::CreateDevice<Input::ButtonDevice>(params.Get("right", null_engine));
auto modifier = Input::CreateDevice<Input::ButtonDevice>(params.Get("modifier", null_engine));
auto modifier_scale = params.Get("modifier_scale", 0.5f);
auto modifier_angle = params.Get("modifier_angle", 0.035f);
return std::make_unique<Analog>(std::move(up), std::move(down), std::move(left),
std::move(right), std::move(modifier), modifier_scale);
std::move(right), std::move(modifier), modifier_scale,
modifier_angle);
}
} // namespace InputCommon

View File

@@ -96,7 +96,6 @@ std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::Param
adapter.get());
}
UNREACHABLE();
return nullptr;
}
@@ -300,7 +299,8 @@ public:
return gcadapter->RumblePlay(port, 0);
}
bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override {
bool SetRumblePlay(f32 amp_low, [[maybe_unused]] f32 freq_low, f32 amp_high,
[[maybe_unused]] f32 freq_high) const override {
const auto mean_amplitude = (amp_low + amp_high) * 0.5f;
const auto processed_amplitude =
static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8);

View File

@@ -23,7 +23,7 @@ public:
/// Unregisters SDL device factories and shut them down.
virtual ~State() = default;
virtual Pollers GetPollers(Polling::DeviceType type) {
virtual Pollers GetPollers(Polling::DeviceType) {
return {};
}

View File

@@ -400,7 +400,8 @@ public:
return joystick->RumblePlay(0, 0);
}
bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override {
bool SetRumblePlay(f32 amp_low, [[maybe_unused]] f32 freq_low, f32 amp_high,
[[maybe_unused]] f32 freq_high) const override {
const auto process_amplitude = [](f32 amplitude) {
return static_cast<u16>((amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF);
};
@@ -864,6 +865,8 @@ Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Eve
Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid,
const SDL_GameControllerButtonBind& binding) {
switch (binding.bindType) {
case SDL_CONTROLLER_BINDTYPE_NONE:
break;
case SDL_CONTROLLER_BINDTYPE_AXIS:
return BuildAnalogParamPackageForButton(port, guid, binding.value.axis);
case SDL_CONTROLLER_BINDTYPE_BUTTON:
@@ -984,7 +987,7 @@ class SDLPoller : public InputCommon::Polling::DevicePoller {
public:
explicit SDLPoller(SDLState& state_) : state(state_) {}
void Start(const std::string& device_id) override {
void Start([[maybe_unused]] const std::string& device_id) override {
state.event_queue.Clear();
state.polling = true;
}

View File

@@ -44,8 +44,7 @@ private:
std::vector<std::tuple<std::unique_ptr<Input::ButtonDevice>, int, int>> map;
};
std::unique_ptr<Input::TouchDevice> TouchFromButtonFactory::Create(
const Common::ParamPackage& params) {
std::unique_ptr<Input::TouchDevice> TouchFromButtonFactory::Create(const Common::ParamPackage&) {
return std::make_unique<TouchFromButtonDevice>();
}

View File

@@ -63,7 +63,7 @@ public:
}
private:
void HandleReceive(const boost::system::error_code& error, std::size_t bytes_transferred) {
void HandleReceive(const boost::system::error_code&, std::size_t bytes_transferred) {
if (auto type = Response::Validate(receive_buffer.data(), bytes_transferred)) {
switch (*type) {
case Type::Version: {
@@ -90,7 +90,7 @@ private:
StartReceive();
}
void HandleSend(const boost::system::error_code& error) {
void HandleSend(const boost::system::error_code&) {
boost::system::error_code _ignored{};
// Send a request for getting port info for the pad
const Request::PortInfo port_info{1, {static_cast<u8>(pad_index), 0, 0, 0}};
@@ -189,11 +189,11 @@ void Client::ReloadSocket(const std::string& host, u16 port, std::size_t pad_ind
StartCommunication(client, host, port, pad_index, client_id);
}
void Client::OnVersion(Response::Version data) {
void Client::OnVersion([[maybe_unused]] Response::Version data) {
LOG_TRACE(Input, "Version packet received: {}", data.version);
}
void Client::OnPortInfo(Response::PortInfo data) {
void Client::OnPortInfo([[maybe_unused]] Response::PortInfo data) {
LOG_TRACE(Input, "PortInfo packet received: {}", data.model);
}
@@ -369,7 +369,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
u16 max_y{};
Status current_status{Status::Initialized};
SocketCallback callback{[](Response::Version version) {}, [](Response::PortInfo info) {},
SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {},
[&](Response::PadData data) {
if (current_status == Status::Initialized) {
// Receiving data means the communication is ready now

View File

@@ -7,7 +7,16 @@
#include <array>
#include <optional>
#include <type_traits>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4701)
#endif
#include <boost/crc.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "common/bit_field.h"
#include "common/swap.h"
@@ -93,7 +102,7 @@ static_assert(std::is_trivially_copyable_v<PadData>,
/**
* Creates a message with the proper header data that can be sent to the server.
* @param T data Request body to send
* @param data Request body to send
* @param client_id ID of the udp client (usually not checked on the server)
*/
template <typename T>

View File

@@ -8,6 +8,7 @@
#include <boost/functional/hash.hpp>
#include "common/bit_cast.h"
#include "common/cityhash.h"
#include "common/common_types.h"
#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
@@ -60,7 +61,13 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta
rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0);
topology.Assign(regs.draw.topology);
std::memcpy(&point_size, &regs.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast
alpha_raw = 0;
const auto test_func =
regs.alpha_test_enabled == 1 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always;
alpha_test_func.Assign(PackComparisonOp(test_func));
alpha_test_ref = Common::BitCast<u32>(regs.alpha_test_ref);
point_size = Common::BitCast<u32>(regs.point_size);
for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
binding_divisors[index] =

View File

@@ -187,6 +187,13 @@ struct FixedPipelineState {
BitField<23, 1, u32> rasterize_enable;
BitField<24, 4, Maxwell::PrimitiveTopology> topology;
};
u32 alpha_test_ref; ///< Alpha test reference value
union {
u32 alpha_raw;
BitField<0, 3, u32> alpha_test_func;
};
u32 point_size;
std::array<u32, Maxwell::NumVertexArrays> binding_divisors;
std::array<VertexAttribute, Maxwell::NumVertexAttributes> attributes;

View File

@@ -7,6 +7,7 @@
#include <memory>
#include <vector>
#include "common/bit_cast.h"
#include "common/microprofile.h"
#include "core/core.h"
#include "core/memory.h"
@@ -344,6 +345,11 @@ VKPipelineCache::DecompileShaders(const FixedPipelineState& fixed_state) {
}
specialization.ndc_minus_one_to_one = fixed_state.ndc_minus_one_to_one;
// Alpha test
specialization.alpha_test_func =
FixedPipelineState::UnpackComparisonOp(fixed_state.alpha_test_func.Value());
specialization.alpha_test_ref = Common::BitCast<float>(fixed_state.alpha_test_ref);
SPIRVProgram program;
std::vector<VkDescriptorSetLayoutBinding> bindings;

View File

@@ -2075,6 +2075,45 @@ private:
return {};
}
Id MaxwellToSpirvComparison(Maxwell::ComparisonOp compare_op, Id operand_1, Id operand_2) {
using Compare = Maxwell::ComparisonOp;
switch (compare_op) {
case Compare::NeverOld:
return v_false; // Never let the test pass
case Compare::LessOld:
return OpFOrdLessThan(t_bool, operand_1, operand_2);
case Compare::EqualOld:
return OpFOrdEqual(t_bool, operand_1, operand_2);
case Compare::LessEqualOld:
return OpFOrdLessThanEqual(t_bool, operand_1, operand_2);
case Compare::GreaterOld:
return OpFOrdGreaterThan(t_bool, operand_1, operand_2);
case Compare::NotEqualOld:
return OpFOrdNotEqual(t_bool, operand_1, operand_2);
case Compare::GreaterEqualOld:
return OpFOrdGreaterThanEqual(t_bool, operand_1, operand_2);
default:
UNREACHABLE();
}
}
void AlphaTest(Id pointer) {
if (specialization.alpha_test_func == Maxwell::ComparisonOp::AlwaysOld) {
return;
}
const Id true_label = OpLabel();
const Id discard_label = OpLabel();
const Id alpha_reference = Constant(t_float, specialization.alpha_test_ref);
const Id alpha_value = OpLoad(t_float, pointer);
const Id condition =
MaxwellToSpirvComparison(specialization.alpha_test_func, alpha_value, alpha_reference);
OpBranchConditional(condition, true_label, discard_label);
AddLabel(discard_label);
OpKill();
AddLabel(true_label);
}
void PreExit() {
if (stage == ShaderType::Vertex && specialization.ndc_minus_one_to_one) {
const u32 position_index = out_indices.position.value();
@@ -2097,8 +2136,6 @@ private:
UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0,
"Sample mask write is unimplemented");
// TODO(Rodrigo): Alpha testing
// Write the color outputs using the data in the shader registers, disabled
// rendertargets/components are skipped in the register assignment.
u32 current_reg = 0;
@@ -2110,6 +2147,9 @@ private:
}
const Id pointer = AccessElement(t_out_float, frag_colors[rt], component);
OpStore(pointer, SafeGetRegister(current_reg));
if (rt == 0 && component == 3) {
AlphaTest(pointer);
}
++current_reg;
}
}

View File

@@ -95,6 +95,8 @@ struct Specialization final {
std::bitset<Maxwell::NumVertexAttributes> enabled_attributes;
std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{};
bool ndc_minus_one_to_one{};
float alpha_test_ref{};
Maxwell::ComparisonOp alpha_test_func{};
};
// Old gcc versions don't consider this trivially copyable.
// static_assert(std::is_trivially_copyable_v<Specialization>);

View File

@@ -212,10 +212,10 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) {
return 0;
case TextureFormat::R8G24:
if (component == 0) {
return 8;
return 24;
}
if (component == 1) {
return 24;
return 8;
}
return 0;
case TextureFormat::R8G8:

View File

@@ -302,6 +302,12 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
this->setMouseTracking(true);
connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete);
connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram,
Qt::QueuedConnection);
}
void GRenderWindow::ExecuteProgram(std::size_t program_index) {
emit ExecuteProgramSignal(program_index);
}
GRenderWindow::~GRenderWindow() {

View File

@@ -166,6 +166,12 @@ public:
std::pair<u32, u32> ScaleTouch(const QPointF& pos) const;
/**
* Instructs the window to re-launch the application using the specified program_index.
* @param program_index Specifies the index within the application of the program to launch.
*/
void ExecuteProgram(std::size_t program_index);
public slots:
void OnEmulationStarting(EmuThread* emu_thread);
void OnEmulationStopping();
@@ -175,6 +181,7 @@ signals:
/// Emitted when the window is closed
void Closed();
void FirstFrameDisplayed();
void ExecuteProgramSignal(std::size_t program_index);
private:
void TouchBeginEvent(const QTouchEvent* event);

View File

@@ -978,7 +978,7 @@ void GMainWindow::AllowOSSleep() {
#endif
}
bool GMainWindow::LoadROM(const QString& filename) {
bool GMainWindow::LoadROM(const QString& filename, std::size_t program_index) {
// Shutdown previous session if the emu thread is still active...
if (emu_thread != nullptr)
ShutdownGame();
@@ -1003,7 +1003,8 @@ bool GMainWindow::LoadROM(const QString& filename) {
system.RegisterHostThread();
const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())};
const Core::System::ResultStatus result{
system.Load(*render_window, filename.toStdString(), program_index)};
const auto drd_callout =
(UISettings::values.callout_flags & static_cast<u32>(CalloutFlag::DRDDeprecation)) == 0;
@@ -1085,14 +1086,18 @@ void GMainWindow::SelectAndSetCurrentUser() {
Settings::values.current_user = dialog.GetIndex();
}
void GMainWindow::BootGame(const QString& filename) {
void GMainWindow::BootGame(const QString& filename, std::size_t program_index) {
LOG_INFO(Frontend, "yuzu starting...");
StoreRecentFile(filename); // Put the filename on top of the list
u64 title_id{0};
last_filename_booted = filename;
auto& system = Core::System::GetInstance();
const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData());
const auto loader = Loader::GetLoader(system, v_file);
const auto loader = Loader::GetLoader(system, v_file, program_index);
if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) {
// Load per game settings
Config per_game_config(fmt::format("{:016X}", title_id), Config::ConfigType::PerGameConfig);
@@ -1106,7 +1111,7 @@ void GMainWindow::BootGame(const QString& filename) {
SelectAndSetCurrentUser();
}
if (!LoadROM(filename))
if (!LoadROM(filename, program_index))
return;
// Create and start the emulation thread
@@ -1114,6 +1119,10 @@ void GMainWindow::BootGame(const QString& filename) {
emit EmulationStarting(emu_thread.get());
emu_thread->start();
// Register an ExecuteProgram callback such that Core can execute a sub-program
system.RegisterExecuteProgramCallback(
[this](std::size_t program_index) { render_window->ExecuteProgram(program_index); });
connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame);
// BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views
// before the CPU continues
@@ -2136,6 +2145,11 @@ void GMainWindow::OnLoadComplete() {
loading_screen->OnLoadComplete();
}
void GMainWindow::OnExecuteProgram(std::size_t program_index) {
ShutdownGame();
BootGame(last_filename_booted, program_index);
}
void GMainWindow::ErrorDisplayDisplayError(QString body) {
QMessageBox::critical(this, tr("Error Display"), body);
emit ErrorDisplayFinished();

View File

@@ -131,6 +131,7 @@ signals:
public slots:
void OnLoadComplete();
void OnExecuteProgram(std::size_t program_index);
void ControllerSelectorReconfigureControllers(
const Core::Frontend::ControllerParameters& parameters);
void ErrorDisplayDisplayError(QString body);
@@ -154,8 +155,8 @@ private:
void PreventOSSleep();
void AllowOSSleep();
bool LoadROM(const QString& filename);
void BootGame(const QString& filename);
bool LoadROM(const QString& filename, std::size_t program_index);
void BootGame(const QString& filename, std::size_t program_index = 0);
void ShutdownGame();
void ShowTelemetryCallout();
@@ -317,6 +318,9 @@ private:
// Install progress dialog
QProgressDialog* install_progress;
// Last game booted, used for multi-process apps
QString last_filename_booted;
protected:
void dropEvent(QDropEvent* event) override;
void dragEnterEvent(QDragEnterEvent* event) override;

View File

@@ -240,11 +240,11 @@ int main(int argc, char** argv) {
system.CurrentProcess()->GetTitleID(), false,
[](VideoCore::LoadCallbackStage, size_t value, size_t total) {});
system.Run();
void(system.Run());
while (emu_window->IsOpen()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
system.Pause();
void(system.Pause());
system.Shutdown();
detached_tasks.WaitForAllTasks();

View File

@@ -256,11 +256,11 @@ int main(int argc, char** argv) {
system.GPU().Start();
system.Run();
void(system.Run());
while (!finished) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
system.Pause();
void(system.Pause());
detached_tasks.WaitForAllTasks();
return return_value;