Compare commits
37 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f93d769a1c | ||
|
|
cd4e8a989c | ||
|
|
29feece4b8 | ||
|
|
0eff775264 | ||
|
|
e453b09a61 | ||
|
|
bf310a41b8 | ||
|
|
cbec739e7b | ||
|
|
494275fd38 | ||
|
|
e7ba2a4447 | ||
|
|
cc6f22e0e4 | ||
|
|
e9a857ce82 | ||
|
|
403f8e79ea | ||
|
|
34a29ad051 | ||
|
|
8581404482 | ||
|
|
69ee9edd8d | ||
|
|
3923b0f589 | ||
|
|
8be7131033 | ||
|
|
07ae1f972d | ||
|
|
fbfa7ddd62 | ||
|
|
9289255314 | ||
|
|
ec030a542f | ||
|
|
cde9386e0f | ||
|
|
7d6653268f | ||
|
|
8538e0bc3d | ||
|
|
5750f6f046 | ||
|
|
5fb4c718cc | ||
|
|
80562aaf64 | ||
|
|
84e1c0a430 | ||
|
|
e4b7a1d160 | ||
|
|
0eefe6e4d1 | ||
|
|
3c3d5eeddf | ||
|
|
248881fa7f | ||
|
|
7e7110b3b9 | ||
|
|
aef7a15b93 | ||
|
|
656e7aab29 | ||
|
|
28669872d9 | ||
|
|
a8d8c21e00 |
@@ -169,6 +169,14 @@ add_library(core STATIC
|
||||
hle/service/service.h
|
||||
hle/service/set/set.cpp
|
||||
hle/service/set/set.h
|
||||
hle/service/set/set_cal.cpp
|
||||
hle/service/set/set_cal.h
|
||||
hle/service/set/set_fd.cpp
|
||||
hle/service/set/set_fd.h
|
||||
hle/service/set/set_sys.cpp
|
||||
hle/service/set/set_sys.h
|
||||
hle/service/set/settings.cpp
|
||||
hle/service/set/settings.h
|
||||
hle/service/sm/controller.cpp
|
||||
hle/service/sm/controller.h
|
||||
hle/service/sm/sm.cpp
|
||||
|
||||
@@ -39,8 +39,12 @@ public:
|
||||
Run(1);
|
||||
}
|
||||
|
||||
/// Maps a backing memory region for the CPU
|
||||
virtual void MapBackingMemory(VAddr address, size_t size, u8* memory,
|
||||
Kernel::VMAPermission perms) {}
|
||||
Kernel::VMAPermission perms) = 0;
|
||||
|
||||
/// Unmaps a region of memory that was previously mapped using MapBackingMemory
|
||||
virtual void UnmapMemory(VAddr address, size_t size) = 0;
|
||||
|
||||
/// Clear all instruction cache
|
||||
virtual void ClearInstructionCache() = 0;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <dynarmic/A64/config.h>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/memory.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
@@ -106,7 +107,7 @@ public:
|
||||
};
|
||||
|
||||
std::unique_ptr<Dynarmic::A64::Jit> MakeJit(const std::unique_ptr<ARM_Dynarmic_Callbacks>& cb) {
|
||||
const auto page_table = Kernel::g_current_process->vm_manager.page_table.pointers.data();
|
||||
const auto page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data();
|
||||
|
||||
Dynarmic::A64::UserConfig config;
|
||||
config.callbacks = cb.get();
|
||||
@@ -135,6 +136,10 @@ void ARM_Dynarmic::MapBackingMemory(u64 address, size_t size, u8* memory,
|
||||
inner_unicorn.MapBackingMemory(address, size, memory, perms);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::UnmapMemory(u64 address, size_t size) {
|
||||
inner_unicorn.UnmapMemory(address, size);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetPC(u64 pc) {
|
||||
jit->SetPC(pc);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
|
||||
void MapBackingMemory(VAddr address, size_t size, u8* memory,
|
||||
Kernel::VMAPermission perms) override;
|
||||
|
||||
void UnmapMemory(u64 address, size_t size) override;
|
||||
void SetPC(u64 pc) override;
|
||||
u64 GetPC() const override;
|
||||
u64 GetReg(int index) const override;
|
||||
|
||||
@@ -77,6 +77,10 @@ void ARM_Unicorn::MapBackingMemory(VAddr address, size_t size, u8* memory,
|
||||
CHECKED(uc_mem_map_ptr(uc, address, size, static_cast<u32>(perms), memory));
|
||||
}
|
||||
|
||||
void ARM_Unicorn::UnmapMemory(VAddr address, size_t size) {
|
||||
CHECKED(uc_mem_unmap(uc, address, size));
|
||||
}
|
||||
|
||||
void ARM_Unicorn::SetPC(u64 pc) {
|
||||
CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &pc));
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ public:
|
||||
~ARM_Unicorn();
|
||||
void MapBackingMemory(VAddr address, size_t size, u8* memory,
|
||||
Kernel::VMAPermission perms) override;
|
||||
void UnmapMemory(VAddr address, size_t size) override;
|
||||
void SetPC(u64 pc) override;
|
||||
u64 GetPC() const override;
|
||||
u64 GetReg(int index) const override;
|
||||
|
||||
@@ -100,7 +100,7 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
|
||||
return init_result;
|
||||
}
|
||||
|
||||
const Loader::ResultStatus load_result{app_loader->Load(Kernel::g_current_process)};
|
||||
const Loader::ResultStatus load_result{app_loader->Load(current_process)};
|
||||
if (Loader::ResultStatus::Success != load_result) {
|
||||
LOG_CRITICAL(Core, "Failed to load ROM (Error %i)!", load_result);
|
||||
System::Shutdown();
|
||||
@@ -141,6 +141,8 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
|
||||
|
||||
CoreTiming::Init();
|
||||
|
||||
current_process = Kernel::Process::Create("main");
|
||||
|
||||
switch (Settings::values.cpu_core) {
|
||||
case Settings::CpuCore::Unicorn:
|
||||
cpu_core = std::make_shared<ARM_Unicorn>();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/loader/loader.h"
|
||||
#include "core/memory.h"
|
||||
@@ -112,6 +113,10 @@ public:
|
||||
return *scheduler;
|
||||
}
|
||||
|
||||
Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
|
||||
return current_process;
|
||||
}
|
||||
|
||||
PerfStats perf_stats;
|
||||
FrameLimiter frame_limiter;
|
||||
|
||||
@@ -149,6 +154,8 @@ private:
|
||||
std::unique_ptr<Kernel::Scheduler> scheduler;
|
||||
std::unique_ptr<Tegra::GPU> gpu_core;
|
||||
|
||||
Kernel::SharedPtr<Kernel::Process> current_process;
|
||||
|
||||
/// When true, signals that a reschedule should happen
|
||||
bool reschedule_pending{};
|
||||
|
||||
@@ -169,4 +176,8 @@ inline TelemetrySession& Telemetry() {
|
||||
return System::GetInstance().TelemetrySession();
|
||||
}
|
||||
|
||||
inline Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
|
||||
return System::GetInstance().CurrentProcess();
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/disk_filesystem.h"
|
||||
#include "core/file_sys/errors.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
@@ -22,8 +23,7 @@ ResultVal<std::unique_ptr<StorageBackend>> Disk_FileSystem::OpenFile(const std::
|
||||
auto file = std::make_shared<FileUtil::IOFile>(full_path, mode == Mode::Read ? "rb" : "wb");
|
||||
|
||||
if (!file->IsOpen()) {
|
||||
// TODO(Subv): Find out the correct error code.
|
||||
return ResultCode(-1);
|
||||
return ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
return MakeResult<std::unique_ptr<StorageBackend>>(
|
||||
@@ -100,8 +100,7 @@ u64 Disk_FileSystem::GetFreeSpaceSize() const {
|
||||
ResultVal<FileSys::EntryType> Disk_FileSystem::GetEntryType(const std::string& path) const {
|
||||
std::string full_path = base_directory + path;
|
||||
if (!FileUtil::Exists(full_path)) {
|
||||
// TODO(Subv): Find out what this actually means
|
||||
return ResultCode(ErrorModule::FS, 1);
|
||||
return ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
// TODO(Subv): Find out the EntryType values
|
||||
|
||||
@@ -10,36 +10,17 @@ namespace FileSys {
|
||||
|
||||
namespace ErrCodes {
|
||||
enum {
|
||||
RomFSNotFound = 100,
|
||||
ArchiveNotMounted = 101,
|
||||
FileNotFound = 112,
|
||||
PathNotFound = 113,
|
||||
GameCardNotInserted = 141,
|
||||
NotFound = 120,
|
||||
FileAlreadyExists = 180,
|
||||
DirectoryAlreadyExists = 185,
|
||||
AlreadyExists = 190,
|
||||
InvalidOpenFlags = 230,
|
||||
DirectoryNotEmpty = 240,
|
||||
NotAFile = 250,
|
||||
NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive
|
||||
ExeFSSectionNotFound = 567,
|
||||
CommandNotAllowed = 630,
|
||||
InvalidReadFlag = 700,
|
||||
InvalidPath = 702,
|
||||
WriteBeyondEnd = 705,
|
||||
UnsupportedOpenFlags = 760,
|
||||
IncorrectExeFSReadSize = 761,
|
||||
UnexpectedFileOrDirectory = 770,
|
||||
NotFound = 1,
|
||||
};
|
||||
}
|
||||
|
||||
constexpr ResultCode ERROR_PATH_NOT_FOUND(ErrorModule::FS, ErrCodes::NotFound);
|
||||
|
||||
// TODO(bunnei): Replace these with correct errors for Switch OS
|
||||
constexpr ResultCode ERROR_INVALID_PATH(ResultCode(-1));
|
||||
constexpr ResultCode ERROR_UNSUPPORTED_OPEN_FLAGS(ResultCode(-1));
|
||||
constexpr ResultCode ERROR_INVALID_OPEN_FLAGS(ResultCode(-1));
|
||||
constexpr ResultCode ERROR_FILE_NOT_FOUND(ResultCode(-1));
|
||||
constexpr ResultCode ERROR_PATH_NOT_FOUND(ResultCode(-1));
|
||||
constexpr ResultCode ERROR_UNEXPECTED_FILE_OR_DIRECTORY(ResultCode(-1));
|
||||
constexpr ResultCode ERROR_DIRECTORY_ALREADY_EXISTS(ResultCode(-1));
|
||||
constexpr ResultCode ERROR_FILE_ALREADY_EXISTS(ResultCode(-1));
|
||||
|
||||
@@ -183,10 +183,9 @@ public:
|
||||
/**
|
||||
* Deletes the archive contents and then re-creates the base folder
|
||||
* @param path Path to the archive
|
||||
* @param format_info Format information for the new archive
|
||||
* @return ResultCode of the operation, 0 on success
|
||||
*/
|
||||
virtual ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) = 0;
|
||||
virtual ResultCode Format(const Path& path) = 0;
|
||||
|
||||
/**
|
||||
* Retrieves the format info about the archive with the specified path
|
||||
|
||||
@@ -23,7 +23,7 @@ ResultVal<std::unique_ptr<FileSystemBackend>> RomFS_Factory::Open(const Path& pa
|
||||
return MakeResult<std::unique_ptr<FileSystemBackend>>(std::move(archive));
|
||||
}
|
||||
|
||||
ResultCode RomFS_Factory::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) {
|
||||
ResultCode RomFS_Factory::Format(const Path& path) {
|
||||
LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str());
|
||||
// TODO(bunnei): Find the right error code for this
|
||||
return ResultCode(-1);
|
||||
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
return "ArchiveFactory_RomFS";
|
||||
}
|
||||
ResultVal<std::unique_ptr<FileSystemBackend>> Open(const Path& path) override;
|
||||
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
|
||||
ResultCode Format(const Path& path) override;
|
||||
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/core.h"
|
||||
#include "core/file_sys/disk_filesystem.h"
|
||||
#include "core/file_sys/savedata_factory.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
@@ -17,20 +18,26 @@ SaveData_Factory::SaveData_Factory(std::string nand_directory)
|
||||
: nand_directory(std::move(nand_directory)) {}
|
||||
|
||||
ResultVal<std::unique_ptr<FileSystemBackend>> SaveData_Factory::Open(const Path& path) {
|
||||
u64 title_id = Kernel::g_current_process->program_id;
|
||||
// TODO(Subv): Somehow obtain this value.
|
||||
u32 user = 0;
|
||||
std::string save_directory = Common::StringFromFormat("%ssave/%016" PRIX64 "/%08X",
|
||||
nand_directory.c_str(), title_id, user);
|
||||
std::string save_directory = GetFullPath();
|
||||
// Return an error if the save data doesn't actually exist.
|
||||
if (!FileUtil::IsDirectory(save_directory)) {
|
||||
// TODO(Subv): Find out correct error code.
|
||||
return ResultCode(-1);
|
||||
}
|
||||
|
||||
auto archive = std::make_unique<Disk_FileSystem>(save_directory);
|
||||
return MakeResult<std::unique_ptr<FileSystemBackend>>(std::move(archive));
|
||||
}
|
||||
|
||||
ResultCode SaveData_Factory::Format(const Path& path,
|
||||
const FileSys::ArchiveFormatInfo& format_info) {
|
||||
LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str());
|
||||
// TODO(bunnei): Find the right error code for this
|
||||
return ResultCode(-1);
|
||||
ResultCode SaveData_Factory::Format(const Path& path) {
|
||||
LOG_WARNING(Service_FS, "Format archive %s", GetName().c_str());
|
||||
// Create the save data directory.
|
||||
if (!FileUtil::CreateFullPath(GetFullPath())) {
|
||||
// TODO(Subv): Find the correct error code.
|
||||
return ResultCode(-1);
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultVal<ArchiveFormatInfo> SaveData_Factory::GetFormatInfo(const Path& path) const {
|
||||
@@ -39,4 +46,12 @@ ResultVal<ArchiveFormatInfo> SaveData_Factory::GetFormatInfo(const Path& path) c
|
||||
return ResultCode(-1);
|
||||
}
|
||||
|
||||
std::string SaveData_Factory::GetFullPath() const {
|
||||
u64 title_id = Core::CurrentProcess()->program_id;
|
||||
// TODO(Subv): Somehow obtain this value.
|
||||
u32 user = 0;
|
||||
return Common::StringFromFormat("%ssave/%016" PRIX64 "/%08X/", nand_directory.c_str(), title_id,
|
||||
user);
|
||||
}
|
||||
|
||||
} // namespace FileSys
|
||||
|
||||
@@ -21,11 +21,13 @@ public:
|
||||
return "SaveData_Factory";
|
||||
}
|
||||
ResultVal<std::unique_ptr<FileSystemBackend>> Open(const Path& path) override;
|
||||
ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
|
||||
ResultCode Format(const Path& path) override;
|
||||
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
|
||||
|
||||
private:
|
||||
std::string nand_directory;
|
||||
|
||||
std::string GetFullPath() const;
|
||||
};
|
||||
|
||||
} // namespace FileSys
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <utility>
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
@@ -77,7 +78,7 @@ SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
|
||||
if (handle == CurrentThread) {
|
||||
return GetCurrentThread();
|
||||
} else if (handle == CurrentProcess) {
|
||||
return g_current_process;
|
||||
return Core::CurrentProcess();
|
||||
}
|
||||
|
||||
if (!IsValid(handle)) {
|
||||
|
||||
@@ -41,7 +41,6 @@ void Shutdown() {
|
||||
g_object_address_table.Clear();
|
||||
|
||||
Kernel::ThreadingShutdown();
|
||||
g_current_process = nullptr;
|
||||
|
||||
Kernel::TimersShutdown();
|
||||
Kernel::ResourceLimitsShutdown();
|
||||
|
||||
@@ -33,10 +33,6 @@ enum class HandleType : u32 {
|
||||
ServerSession,
|
||||
};
|
||||
|
||||
enum {
|
||||
DEFAULT_STACK_SIZE = 0x10000,
|
||||
};
|
||||
|
||||
enum class ResetType {
|
||||
OneShot,
|
||||
Sticky,
|
||||
|
||||
@@ -31,14 +31,14 @@ CodeSet::~CodeSet() {}
|
||||
|
||||
u32 Process::next_process_id;
|
||||
|
||||
SharedPtr<Process> Process::Create(std::string&& name, u64 program_id) {
|
||||
SharedPtr<Process> Process::Create(std::string&& name) {
|
||||
SharedPtr<Process> process(new Process);
|
||||
|
||||
process->name = std::move(name);
|
||||
process->flags.raw = 0;
|
||||
process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
|
||||
process->status = ProcessStatus::Created;
|
||||
process->program_id = program_id;
|
||||
process->program_id = 0;
|
||||
|
||||
process_list.push_back(process);
|
||||
return process;
|
||||
@@ -117,11 +117,12 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
|
||||
}
|
||||
|
||||
void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
|
||||
// Allocate and map stack
|
||||
// Allocate and map the main thread stack
|
||||
// TODO(bunnei): This is heap area that should be allocated by the kernel and not mapped as part
|
||||
// of the user address space.
|
||||
vm_manager
|
||||
.MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size,
|
||||
std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size,
|
||||
MemoryState::Heap)
|
||||
.MapMemoryBlock(Memory::STACK_VADDR, std::make_shared<std::vector<u8>>(stack_size, 0), 0,
|
||||
stack_size, MemoryState::Mapped)
|
||||
.Unwrap();
|
||||
misc_memory_used += stack_size;
|
||||
memory_region->used += stack_size;
|
||||
@@ -153,9 +154,9 @@ void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) {
|
||||
};
|
||||
|
||||
// Map CodeSet segments
|
||||
MapSegment(module_->code, VMAPermission::ReadExecute, MemoryState::Code);
|
||||
MapSegment(module_->rodata, VMAPermission::Read, MemoryState::Static);
|
||||
MapSegment(module_->data, VMAPermission::ReadWrite, MemoryState::Static);
|
||||
MapSegment(module_->code, VMAPermission::ReadExecute, MemoryState::CodeStatic);
|
||||
MapSegment(module_->rodata, VMAPermission::Read, MemoryState::CodeMutable);
|
||||
MapSegment(module_->data, VMAPermission::ReadWrite, MemoryState::CodeMutable);
|
||||
}
|
||||
|
||||
VAddr Process::GetLinearHeapAreaAddress() const {
|
||||
@@ -182,6 +183,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission per
|
||||
// Initialize heap
|
||||
heap_memory = std::make_shared<std::vector<u8>>();
|
||||
heap_start = heap_end = target;
|
||||
} else {
|
||||
vm_manager.UnmapRange(heap_start, heap_end - heap_start);
|
||||
}
|
||||
|
||||
// If necessary, expand backing vector to cover new heap extents.
|
||||
@@ -201,7 +204,7 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission per
|
||||
size, MemoryState::Heap));
|
||||
vm_manager.Reprotect(vma, perms);
|
||||
|
||||
heap_used += size;
|
||||
heap_used = size;
|
||||
memory_region->used += size;
|
||||
|
||||
return MakeResult<VAddr>(heap_end - size);
|
||||
@@ -288,7 +291,7 @@ ResultCode Process::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
|
||||
|
||||
CASCADE_RESULT(auto new_vma,
|
||||
vm_manager.MapMemoryBlock(dst_addr, backing_block, backing_block_offset, size,
|
||||
vma->second.meminfo_state));
|
||||
MemoryState::Mapped));
|
||||
// Protect mirror with permissions from old region
|
||||
vm_manager.Reprotect(new_vma, vma->second.permissions);
|
||||
// Remove permissions from old region
|
||||
@@ -319,5 +322,4 @@ SharedPtr<Process> GetProcessById(u32 process_id) {
|
||||
return *itr;
|
||||
}
|
||||
|
||||
SharedPtr<Process> g_current_process;
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -95,7 +95,7 @@ private:
|
||||
|
||||
class Process final : public Object {
|
||||
public:
|
||||
static SharedPtr<Process> Create(std::string&& name, u64 program_id);
|
||||
static SharedPtr<Process> Create(std::string&& name);
|
||||
|
||||
std::string GetTypeName() const override {
|
||||
return "Process";
|
||||
@@ -203,5 +203,4 @@ void ClearProcessList();
|
||||
/// Retrieves a process from the current list of processes.
|
||||
SharedPtr<Process> GetProcessById(u32 process_id);
|
||||
|
||||
extern SharedPtr<Process> g_current_process;
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
@@ -67,7 +68,7 @@ void Scheduler::SwitchContext(Thread* new_thread) {
|
||||
// Cancel any outstanding wakeup events for this thread
|
||||
new_thread->CancelWakeupTimer();
|
||||
|
||||
auto previous_process = Kernel::g_current_process;
|
||||
auto previous_process = Core::CurrentProcess();
|
||||
|
||||
current_thread = new_thread;
|
||||
|
||||
@@ -75,8 +76,8 @@ void Scheduler::SwitchContext(Thread* new_thread) {
|
||||
new_thread->status = THREADSTATUS_RUNNING;
|
||||
|
||||
if (previous_process != current_thread->owner_process) {
|
||||
Kernel::g_current_process = current_thread->owner_process;
|
||||
SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table);
|
||||
Core::CurrentProcess() = current_thread->owner_process;
|
||||
SetCurrentPageTable(&Core::CurrentProcess()->vm_manager.page_table);
|
||||
}
|
||||
|
||||
cpu_core->LoadContext(new_thread->context);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/kernel/client_session.h"
|
||||
@@ -91,7 +92,7 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
|
||||
|
||||
Kernel::HLERequestContext context(this);
|
||||
u32* cmd_buf = (u32*)Memory::GetPointer(thread->GetTLSAddress());
|
||||
context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process,
|
||||
context.PopulateFromIncomingCommandBuffer(cmd_buf, *Core::CurrentProcess(),
|
||||
Kernel::g_handle_table);
|
||||
|
||||
ResultCode result = RESULT_SUCCESS;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <cstring>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/memory.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
@@ -51,8 +52,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
|
||||
}
|
||||
|
||||
// Refresh the address mappings for the current process.
|
||||
if (Kernel::g_current_process != nullptr) {
|
||||
Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
|
||||
if (Core::CurrentProcess() != nullptr) {
|
||||
Core::CurrentProcess()->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
|
||||
}
|
||||
} else {
|
||||
auto& vm_manager = shared_memory->owner_process->vm_manager;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/kernel/client_session.h"
|
||||
@@ -31,7 +32,7 @@ namespace Kernel {
|
||||
/// Set the process heap to a given Size. It can both extend and shrink the heap.
|
||||
static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
|
||||
LOG_TRACE(Kernel_SVC, "called, heap_size=0x%llx", heap_size);
|
||||
auto& process = *g_current_process;
|
||||
auto& process = *Core::CurrentProcess();
|
||||
CASCADE_RESULT(*heap_addr,
|
||||
process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite));
|
||||
return RESULT_SUCCESS;
|
||||
@@ -46,14 +47,14 @@ static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state
|
||||
static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
|
||||
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x%llx, src_addr=0x%llx, size=0x%llx", dst_addr,
|
||||
src_addr, size);
|
||||
return g_current_process->MirrorMemory(dst_addr, src_addr, size);
|
||||
return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size);
|
||||
}
|
||||
|
||||
/// Unmaps a region that was previously mapped with svcMapMemory
|
||||
static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
|
||||
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x%llx, src_addr=0x%llx, size=0x%llx", dst_addr,
|
||||
src_addr, size);
|
||||
return g_current_process->UnmapMemory(dst_addr, src_addr, size);
|
||||
return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size);
|
||||
}
|
||||
|
||||
/// Connect to an OS service given the port name, returns the handle to the port to out
|
||||
@@ -306,23 +307,23 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
|
||||
LOG_TRACE(Kernel_SVC, "called info_id=0x%X, info_sub_id=0x%X, handle=0x%08X", info_id,
|
||||
info_sub_id, handle);
|
||||
|
||||
auto& vm_manager = g_current_process->vm_manager;
|
||||
auto& vm_manager = Core::CurrentProcess()->vm_manager;
|
||||
|
||||
switch (static_cast<GetInfoType>(info_id)) {
|
||||
case GetInfoType::AllowedCpuIdBitmask:
|
||||
*result = g_current_process->allowed_processor_mask;
|
||||
*result = Core::CurrentProcess()->allowed_processor_mask;
|
||||
break;
|
||||
case GetInfoType::AllowedThreadPrioBitmask:
|
||||
*result = g_current_process->allowed_thread_priority_mask;
|
||||
*result = Core::CurrentProcess()->allowed_thread_priority_mask;
|
||||
break;
|
||||
case GetInfoType::MapRegionBaseAddr:
|
||||
*result = vm_manager.GetMapRegionBaseAddr();
|
||||
*result = Memory::MAP_REGION_VADDR;
|
||||
break;
|
||||
case GetInfoType::MapRegionSize:
|
||||
*result = vm_manager.GetAddressSpaceSize();
|
||||
*result = Memory::MAP_REGION_SIZE;
|
||||
break;
|
||||
case GetInfoType::HeapRegionBaseAddr:
|
||||
*result = vm_manager.GetNewMapRegionBaseAddr() + vm_manager.GetNewMapRegionSize();
|
||||
*result = Memory::HEAP_VADDR;
|
||||
break;
|
||||
case GetInfoType::HeapRegionSize:
|
||||
*result = Memory::HEAP_SIZE;
|
||||
@@ -346,13 +347,13 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
|
||||
*result = vm_manager.GetAddressSpaceSize();
|
||||
break;
|
||||
case GetInfoType::NewMapRegionBaseAddr:
|
||||
*result = vm_manager.GetNewMapRegionBaseAddr();
|
||||
*result = Memory::NEW_MAP_REGION_VADDR;
|
||||
break;
|
||||
case GetInfoType::NewMapRegionSize:
|
||||
*result = vm_manager.GetNewMapRegionSize();
|
||||
*result = Memory::NEW_MAP_REGION_SIZE;
|
||||
break;
|
||||
case GetInfoType::IsVirtualAddressMemoryEnabled:
|
||||
*result = g_current_process->is_virtual_address_memory_enabled;
|
||||
*result = Core::CurrentProcess()->is_virtual_address_memory_enabled;
|
||||
break;
|
||||
case GetInfoType::TitleId:
|
||||
LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0");
|
||||
@@ -392,7 +393,7 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
|
||||
|
||||
// Note: The kernel uses the current process's resource limit instead of
|
||||
// the one from the thread owner's resource limit.
|
||||
SharedPtr<ResourceLimit>& resource_limit = g_current_process->resource_limit;
|
||||
SharedPtr<ResourceLimit>& resource_limit = Core::CurrentProcess()->resource_limit;
|
||||
if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) {
|
||||
return ERR_NOT_AUTHORIZED;
|
||||
}
|
||||
@@ -435,7 +436,7 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
|
||||
case MemoryPermission::WriteExecute:
|
||||
case MemoryPermission::ReadWriteExecute:
|
||||
case MemoryPermission::DontCare:
|
||||
return shared_memory->Map(g_current_process.get(), addr, permissions_type,
|
||||
return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type,
|
||||
MemoryPermission::DontCare);
|
||||
default:
|
||||
LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
|
||||
@@ -451,7 +452,7 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64
|
||||
|
||||
SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle);
|
||||
|
||||
return shared_memory->Unmap(g_current_process.get(), addr);
|
||||
return shared_memory->Unmap(Core::CurrentProcess().get(), addr);
|
||||
}
|
||||
|
||||
/// Query process memory
|
||||
@@ -463,11 +464,11 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_i
|
||||
}
|
||||
auto vma = process->vm_manager.FindVMA(addr);
|
||||
memory_info->attributes = 0;
|
||||
if (vma == g_current_process->vm_manager.vma_map.end()) {
|
||||
if (vma == Core::CurrentProcess()->vm_manager.vma_map.end()) {
|
||||
memory_info->base_address = 0;
|
||||
memory_info->permission = static_cast<u32>(VMAPermission::None);
|
||||
memory_info->size = 0;
|
||||
memory_info->type = static_cast<u32>(MemoryState::Free);
|
||||
memory_info->type = static_cast<u32>(MemoryState::Unmapped);
|
||||
} else {
|
||||
memory_info->base_address = vma->second.base;
|
||||
memory_info->permission = static_cast<u32>(vma->second.permissions);
|
||||
@@ -487,16 +488,17 @@ static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAdd
|
||||
|
||||
/// Exits the current process
|
||||
static void ExitProcess() {
|
||||
LOG_INFO(Kernel_SVC, "Process %u exiting", g_current_process->process_id);
|
||||
LOG_INFO(Kernel_SVC, "Process %u exiting", Core::CurrentProcess()->process_id);
|
||||
|
||||
ASSERT_MSG(g_current_process->status == ProcessStatus::Running, "Process has already exited");
|
||||
ASSERT_MSG(Core::CurrentProcess()->status == ProcessStatus::Running,
|
||||
"Process has already exited");
|
||||
|
||||
g_current_process->status = ProcessStatus::Exited;
|
||||
Core::CurrentProcess()->status = ProcessStatus::Exited;
|
||||
|
||||
// Stop all the process threads that are currently waiting for objects.
|
||||
auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList();
|
||||
for (auto& thread : thread_list) {
|
||||
if (thread->owner_process != g_current_process)
|
||||
if (thread->owner_process != Core::CurrentProcess())
|
||||
continue;
|
||||
|
||||
if (thread == GetCurrentThread())
|
||||
@@ -525,14 +527,14 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
|
||||
return ERR_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
SharedPtr<ResourceLimit>& resource_limit = g_current_process->resource_limit;
|
||||
SharedPtr<ResourceLimit>& resource_limit = Core::CurrentProcess()->resource_limit;
|
||||
if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) {
|
||||
return ERR_NOT_AUTHORIZED;
|
||||
}
|
||||
|
||||
if (processor_id == THREADPROCESSORID_DEFAULT) {
|
||||
// Set the target CPU to the one specified in the process' exheader.
|
||||
processor_id = g_current_process->ideal_processor;
|
||||
processor_id = Core::CurrentProcess()->ideal_processor;
|
||||
ASSERT(processor_id != THREADPROCESSORID_DEFAULT);
|
||||
}
|
||||
|
||||
@@ -554,7 +556,7 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
|
||||
|
||||
CASCADE_RESULT(SharedPtr<Thread> thread,
|
||||
Thread::Create(name, entry_point, priority, arg, processor_id, stack_top,
|
||||
g_current_process));
|
||||
Core::CurrentProcess()));
|
||||
CASCADE_RESULT(thread->guest_handle, g_handle_table.Create(thread));
|
||||
*out_handle = thread->guest_handle;
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ void Thread::Stop() {
|
||||
u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
|
||||
u64 tls_slot =
|
||||
((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE;
|
||||
Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot);
|
||||
Core::CurrentProcess()->tls_slots[tls_page].reset(tls_slot);
|
||||
}
|
||||
|
||||
void WaitCurrentThread_Sleep() {
|
||||
@@ -314,7 +314,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
|
||||
// TODO(Subv): Find the correct MemoryState for this region.
|
||||
vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE,
|
||||
linheap_memory, offset, Memory::PAGE_SIZE,
|
||||
MemoryState::ThreadLocalStorage);
|
||||
MemoryState::ThreadLocal);
|
||||
}
|
||||
|
||||
// Mark the slot as used
|
||||
@@ -353,11 +353,11 @@ void Thread::BoostPriority(u32 priority) {
|
||||
SharedPtr<Thread> SetupMainThread(VAddr entry_point, u32 priority,
|
||||
SharedPtr<Process> owner_process) {
|
||||
// Setup page table so we can write to memory
|
||||
SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table);
|
||||
SetCurrentPageTable(&Core::CurrentProcess()->vm_manager.page_table);
|
||||
|
||||
// Initialize new "main" thread
|
||||
auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0,
|
||||
Memory::HEAP_VADDR_END, owner_process);
|
||||
Memory::STACK_VADDR_END, owner_process);
|
||||
|
||||
SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
|
||||
|
||||
|
||||
@@ -18,8 +18,26 @@ namespace Kernel {
|
||||
|
||||
static const char* GetMemoryStateName(MemoryState state) {
|
||||
static const char* names[] = {
|
||||
"Free", "Reserved", "IO", "Static", "Code", "Private",
|
||||
"Shared", "Continuous", "Aliased", "Alias", "AliasCode", "Locked",
|
||||
"Unmapped",
|
||||
"Io",
|
||||
"Normal",
|
||||
"CodeStatic",
|
||||
"CodeMutable",
|
||||
"Heap",
|
||||
"Shared",
|
||||
"Unknown1"
|
||||
"ModuleCodeStatic",
|
||||
"ModuleCodeMutable",
|
||||
"IpcBuffer0",
|
||||
"Mapped",
|
||||
"ThreadLocal",
|
||||
"TransferMemoryIsolated",
|
||||
"TransferMemory",
|
||||
"ProcessMemory",
|
||||
"Unknown2"
|
||||
"IpcBuffer1",
|
||||
"IpcBuffer3",
|
||||
"KernelStack",
|
||||
};
|
||||
|
||||
return names[(int)state];
|
||||
@@ -142,7 +160,7 @@ VMManager::VMAIter VMManager::Unmap(VMAIter vma_handle) {
|
||||
VirtualMemoryArea& vma = vma_handle->second;
|
||||
vma.type = VMAType::Free;
|
||||
vma.permissions = VMAPermission::None;
|
||||
vma.meminfo_state = MemoryState::Free;
|
||||
vma.meminfo_state = MemoryState::Unmapped;
|
||||
|
||||
vma.backing_block = nullptr;
|
||||
vma.offset = 0;
|
||||
@@ -166,6 +184,9 @@ ResultCode VMManager::UnmapRange(VAddr target, u64 size) {
|
||||
}
|
||||
|
||||
ASSERT(FindVMA(target)->second.size >= size);
|
||||
|
||||
Core::CPU().UnmapMemory(target, size);
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -377,19 +398,4 @@ u64 VMManager::GetAddressSpaceSize() {
|
||||
return MAX_ADDRESS;
|
||||
}
|
||||
|
||||
VAddr VMManager::GetMapRegionBaseAddr() {
|
||||
LOG_WARNING(Kernel, "(STUBBED) called");
|
||||
return Memory::HEAP_VADDR;
|
||||
}
|
||||
|
||||
VAddr VMManager::GetNewMapRegionBaseAddr() {
|
||||
LOG_WARNING(Kernel, "(STUBBED) called");
|
||||
return 0x8000000;
|
||||
}
|
||||
|
||||
u64 VMManager::GetNewMapRegionSize() {
|
||||
LOG_WARNING(Kernel, "(STUBBED) called");
|
||||
return 0x8000000;
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -41,15 +41,24 @@ enum class VMAPermission : u8 {
|
||||
|
||||
/// Set of values returned in MemoryInfo.state by svcQueryMemory.
|
||||
enum class MemoryState : u32 {
|
||||
Free = 0,
|
||||
IO = 1,
|
||||
Normal = 2,
|
||||
Code = 3,
|
||||
Static = 4,
|
||||
Heap = 5,
|
||||
Shared = 6,
|
||||
Mapped = 6,
|
||||
ThreadLocalStorage = 12,
|
||||
Unmapped = 0x0,
|
||||
Io = 0x1,
|
||||
Normal = 0x2,
|
||||
CodeStatic = 0x3,
|
||||
CodeMutable = 0x4,
|
||||
Heap = 0x5,
|
||||
Shared = 0x6,
|
||||
ModuleCodeStatic = 0x8,
|
||||
ModuleCodeMutable = 0x9,
|
||||
IpcBuffer0 = 0xA,
|
||||
Mapped = 0xB,
|
||||
ThreadLocal = 0xC,
|
||||
TransferMemoryIsolated = 0xD,
|
||||
TransferMemory = 0xE,
|
||||
ProcessMemory = 0xF,
|
||||
IpcBuffer1 = 0x11,
|
||||
IpcBuffer3 = 0x12,
|
||||
KernelStack = 0x13,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -66,7 +75,7 @@ struct VirtualMemoryArea {
|
||||
VMAType type = VMAType::Free;
|
||||
VMAPermission permissions = VMAPermission::None;
|
||||
/// Tag returned by svcQueryMemory. Not otherwise used.
|
||||
MemoryState meminfo_state = MemoryState::Free;
|
||||
MemoryState meminfo_state = MemoryState::Unmapped;
|
||||
|
||||
// Settings for type = AllocatedMemoryBlock
|
||||
/// Memory block backing this VMA.
|
||||
@@ -192,15 +201,6 @@ public:
|
||||
/// Gets the total address space address size, used by svcGetInfo
|
||||
u64 GetAddressSpaceSize();
|
||||
|
||||
/// Gets the map region base address, used by svcGetInfo
|
||||
VAddr GetMapRegionBaseAddr();
|
||||
|
||||
/// Gets the base address for a new memory region, used by svcGetInfo
|
||||
VAddr GetNewMapRegionBaseAddr();
|
||||
|
||||
/// Gets the size for a new memory region, used by svcGetInfo
|
||||
u64 GetNewMapRegionSize();
|
||||
|
||||
/// Each VMManager has its own page table, which is set as the main one when the owning process
|
||||
/// is scheduled.
|
||||
Memory::PageTable page_table;
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cinttypes>
|
||||
#include "core/file_sys/filesystem.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/event.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applet_ae.h"
|
||||
#include "core/hle/service/am/applet_oe.h"
|
||||
#include "core/hle/service/apm/apm.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/nvflinger/nvflinger.h"
|
||||
|
||||
namespace Service {
|
||||
@@ -416,9 +419,24 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
|
||||
}
|
||||
|
||||
void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service, "(STUBBED) called");
|
||||
IPC::RequestParser rp{ctx};
|
||||
u128 uid = rp.PopRaw<u128>();
|
||||
|
||||
LOG_WARNING(Service, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
FileSys::Path unused;
|
||||
auto savedata = FileSystem::OpenFileSystem(FileSystem::Type::SaveData, unused);
|
||||
if (savedata.Failed()) {
|
||||
// Create the save data and return an error indicating that the operation was performed.
|
||||
FileSystem::FormatFileSystem(FileSystem::Type::SaveData);
|
||||
// TODO(Subv): Find out the correct error code for this.
|
||||
rb.Push(ResultCode(ErrorModule::FS, 40));
|
||||
} else {
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
rb.Push<u64>(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,9 @@ public:
|
||||
CoreTiming::ScheduleEvent(audio_ticks, audio_event);
|
||||
}
|
||||
|
||||
~IAudioOut() = default;
|
||||
~IAudioOut() {
|
||||
CoreTiming::UnscheduleEvent(audio_event, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
void StartAudioOut(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
@@ -45,7 +45,9 @@ public:
|
||||
// Start the audio event
|
||||
CoreTiming::ScheduleEvent(audio_ticks, audio_event);
|
||||
}
|
||||
~IAudioRenderer() = default;
|
||||
~IAudioRenderer() {
|
||||
CoreTiming::UnscheduleEvent(audio_event, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
void UpdateAudioCallback() {
|
||||
|
||||
@@ -43,6 +43,19 @@ ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
|
||||
return itr->second->Open(path);
|
||||
}
|
||||
|
||||
ResultCode FormatFileSystem(Type type) {
|
||||
LOG_TRACE(Service_FS, "Formatting FileSystem with type=%d", type);
|
||||
|
||||
auto itr = filesystem_map.find(type);
|
||||
if (itr == filesystem_map.end()) {
|
||||
// TODO(bunnei): Find a better error code for this
|
||||
return ResultCode(-1);
|
||||
}
|
||||
|
||||
FileSys::Path unused;
|
||||
return itr->second->Format(unused);
|
||||
}
|
||||
|
||||
void RegisterFileSystems() {
|
||||
filesystem_map.clear();
|
||||
|
||||
|
||||
@@ -44,6 +44,13 @@ ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& fact
|
||||
ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
|
||||
FileSys::Path& path);
|
||||
|
||||
/**
|
||||
* Formats a file system
|
||||
* @param type Type of the file system to format
|
||||
* @return ResultCode of the operation
|
||||
*/
|
||||
ResultCode FormatFileSystem(Type type);
|
||||
|
||||
/// Registers all Filesystem services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager);
|
||||
|
||||
|
||||
@@ -245,6 +245,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, &FSP_SRV::Initalize, "Initalize"},
|
||||
{18, &FSP_SRV::MountSdCard, "MountSdCard"},
|
||||
{22, &FSP_SRV::CreateSaveData, "CreateSaveData"},
|
||||
{51, &FSP_SRV::MountSaveData, "MountSaveData"},
|
||||
{200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"},
|
||||
{202, nullptr, "OpenDataStorageByDataId"},
|
||||
@@ -279,6 +280,19 @@ void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) {
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
|
||||
auto save_struct = rp.PopRaw<std::array<u8, 0x40>>();
|
||||
auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>();
|
||||
u128 uid = rp.PopRaw<u128>();
|
||||
|
||||
LOG_WARNING(Service_FS, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_FS, "(STUBBED) called");
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ private:
|
||||
|
||||
void Initalize(Kernel::HLERequestContext& ctx);
|
||||
void MountSdCard(Kernel::HLERequestContext& ctx);
|
||||
void CreateSaveData(Kernel::HLERequestContext& ctx);
|
||||
void MountSaveData(Kernel::HLERequestContext& ctx);
|
||||
void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
|
||||
void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
|
||||
|
||||
@@ -45,6 +45,10 @@ public:
|
||||
CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event);
|
||||
}
|
||||
|
||||
~IAppletResource() {
|
||||
CoreTiming::UnscheduleEvent(pad_update_event, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
{0, &IRequest::GetRequestState, "GetRequestState"},
|
||||
{1, &IRequest::GetResult, "GetResult"},
|
||||
{2, &IRequest::GetSystemEventReadableHandles, "GetSystemEventReadableHandles"},
|
||||
{3, nullptr, "Cancel"},
|
||||
{3, &IRequest::Cancel, "Cancel"},
|
||||
{4, nullptr, "Submit"},
|
||||
{5, nullptr, "SetRequirement"},
|
||||
{6, nullptr, "SetRequirementPreset"},
|
||||
@@ -80,6 +80,11 @@ private:
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushCopyObjects(event1, event2);
|
||||
}
|
||||
void Cancel(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
Kernel::SharedPtr<Kernel::Event> event1, event2;
|
||||
};
|
||||
@@ -96,13 +101,56 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class IGeneralService final : public ServiceFramework<IGeneralService> {
|
||||
public:
|
||||
IGeneralService();
|
||||
|
||||
private:
|
||||
void GetClientId(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u64>(0);
|
||||
}
|
||||
void CreateScanRequest(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IScanRequest>();
|
||||
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
void CreateRequest(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IRequest>();
|
||||
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<INetworkProfile>();
|
||||
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
};
|
||||
|
||||
IGeneralService::IGeneralService() : ServiceFramework("IGeneralService") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, &IGeneralService::GetClientId, "GetClientId"},
|
||||
{2, &IGeneralService::CreateScanRequest, "CreateScanRequest"},
|
||||
{4, &IGeneralService::CreateRequest, "CreateRequest"},
|
||||
{6, nullptr, "GetCurrentNetworkProfile"},
|
||||
{7, nullptr, "EnumerateNetworkInterfaces"},
|
||||
{5, nullptr, "GetCurrentNetworkProfile"},
|
||||
{6, nullptr, "EnumerateNetworkInterfaces"},
|
||||
{7, nullptr, "EnumerateNetworkProfiles"},
|
||||
{8, nullptr, "GetNetworkProfile"},
|
||||
{9, nullptr, "SetNetworkProfile"},
|
||||
{10, &IGeneralService::RemoveNetworkProfile, "RemoveNetworkProfile"},
|
||||
@@ -137,50 +185,28 @@ IGeneralService::IGeneralService() : ServiceFramework("IGeneralService") {
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void IGeneralService::GetClientId(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u64>(0);
|
||||
}
|
||||
|
||||
void IGeneralService::CreateScanRequest(Kernel::HLERequestContext& ctx) {
|
||||
void Module::Interface::CreateGeneralServiceOld(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IScanRequest>();
|
||||
|
||||
rb.PushIpcInterface<IGeneralService>();
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
|
||||
void IGeneralService::CreateRequest(Kernel::HLERequestContext& ctx) {
|
||||
void Module::Interface::CreateGeneralService(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IRequest>();
|
||||
|
||||
rb.PushIpcInterface<IGeneralService>();
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
|
||||
void IGeneralService::RemoveNetworkProfile(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void IGeneralService::CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<INetworkProfile>();
|
||||
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
|
||||
: ServiceFramework(name), module(std::move(module)) {}
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
std::make_shared<NIFM_A>()->InstallAsService(service_manager);
|
||||
std::make_shared<NIFM_S>()->InstallAsService(service_manager);
|
||||
std::make_shared<NIFM_U>()->InstallAsService(service_manager);
|
||||
auto module = std::make_shared<Module>();
|
||||
std::make_shared<NIFM_A>(module)->InstallAsService(service_manager);
|
||||
std::make_shared<NIFM_S>(module)->InstallAsService(service_manager);
|
||||
std::make_shared<NIFM_U>(module)->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace NIFM
|
||||
|
||||
@@ -9,16 +9,18 @@
|
||||
namespace Service {
|
||||
namespace NIFM {
|
||||
|
||||
class IGeneralService final : public ServiceFramework<IGeneralService> {
|
||||
class Module final {
|
||||
public:
|
||||
IGeneralService();
|
||||
class Interface : public ServiceFramework<Interface> {
|
||||
public:
|
||||
Interface(std::shared_ptr<Module> module, const char* name);
|
||||
|
||||
private:
|
||||
void GetClientId(Kernel::HLERequestContext& ctx);
|
||||
void CreateScanRequest(Kernel::HLERequestContext& ctx);
|
||||
void CreateRequest(Kernel::HLERequestContext& ctx);
|
||||
void RemoveNetworkProfile(Kernel::HLERequestContext& ctx);
|
||||
void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx);
|
||||
void CreateGeneralServiceOld(Kernel::HLERequestContext& ctx);
|
||||
void CreateGeneralService(Kernel::HLERequestContext& ctx);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Module> module;
|
||||
};
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager);
|
||||
|
||||
@@ -2,29 +2,12 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
#include "core/hle/service/nifm/nifm_a.h"
|
||||
|
||||
namespace Service {
|
||||
namespace NIFM {
|
||||
|
||||
void NIFM_A::CreateGeneralServiceOld(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IGeneralService>();
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
|
||||
void NIFM_A::CreateGeneralService(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IGeneralService>();
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
|
||||
NIFM_A::NIFM_A() : ServiceFramework("nifm:a") {
|
||||
NIFM_A::NIFM_A(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:a") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{4, &NIFM_A::CreateGeneralServiceOld, "CreateGeneralServiceOld"},
|
||||
{5, &NIFM_A::CreateGeneralService, "CreateGeneralService"},
|
||||
|
||||
@@ -4,20 +4,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
|
||||
namespace Service {
|
||||
namespace NIFM {
|
||||
|
||||
class NIFM_A final : public ServiceFramework<NIFM_A> {
|
||||
class NIFM_A final : public Module::Interface {
|
||||
public:
|
||||
NIFM_A();
|
||||
~NIFM_A() = default;
|
||||
|
||||
private:
|
||||
void CreateGeneralServiceOld(Kernel::HLERequestContext& ctx);
|
||||
void CreateGeneralService(Kernel::HLERequestContext& ctx);
|
||||
explicit NIFM_A(std::shared_ptr<Module> module);
|
||||
};
|
||||
|
||||
} // namespace NIFM
|
||||
|
||||
@@ -2,29 +2,12 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
#include "core/hle/service/nifm/nifm_s.h"
|
||||
|
||||
namespace Service {
|
||||
namespace NIFM {
|
||||
|
||||
void NIFM_S::CreateGeneralServiceOld(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IGeneralService>();
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
|
||||
void NIFM_S::CreateGeneralService(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IGeneralService>();
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
|
||||
NIFM_S::NIFM_S() : ServiceFramework("nifm:s") {
|
||||
NIFM_S::NIFM_S(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:s") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{4, &NIFM_S::CreateGeneralServiceOld, "CreateGeneralServiceOld"},
|
||||
{5, &NIFM_S::CreateGeneralService, "CreateGeneralService"},
|
||||
|
||||
@@ -4,20 +4,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
|
||||
namespace Service {
|
||||
namespace NIFM {
|
||||
|
||||
class NIFM_S final : public ServiceFramework<NIFM_S> {
|
||||
class NIFM_S final : public Module::Interface {
|
||||
public:
|
||||
NIFM_S();
|
||||
~NIFM_S() = default;
|
||||
|
||||
private:
|
||||
void CreateGeneralServiceOld(Kernel::HLERequestContext& ctx);
|
||||
void CreateGeneralService(Kernel::HLERequestContext& ctx);
|
||||
explicit NIFM_S(std::shared_ptr<Module> module);
|
||||
};
|
||||
|
||||
} // namespace NIFM
|
||||
|
||||
@@ -2,29 +2,12 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
#include "core/hle/service/nifm/nifm_u.h"
|
||||
|
||||
namespace Service {
|
||||
namespace NIFM {
|
||||
|
||||
void NIFM_U::CreateGeneralServiceOld(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IGeneralService>();
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
|
||||
void NIFM_U::CreateGeneralService(Kernel::HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IGeneralService>();
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
}
|
||||
|
||||
NIFM_U::NIFM_U() : ServiceFramework("nifm:u") {
|
||||
NIFM_U::NIFM_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:u") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{4, &NIFM_U::CreateGeneralServiceOld, "CreateGeneralServiceOld"},
|
||||
{5, &NIFM_U::CreateGeneralService, "CreateGeneralService"},
|
||||
|
||||
@@ -4,20 +4,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
|
||||
namespace Service {
|
||||
namespace NIFM {
|
||||
|
||||
class NIFM_U final : public ServiceFramework<NIFM_U> {
|
||||
class NIFM_U final : public Module::Interface {
|
||||
public:
|
||||
NIFM_U();
|
||||
~NIFM_U() = default;
|
||||
|
||||
private:
|
||||
void CreateGeneralServiceOld(Kernel::HLERequestContext& ctx);
|
||||
void CreateGeneralService(Kernel::HLERequestContext& ctx);
|
||||
explicit NIFM_U(std::shared_ptr<Module> module);
|
||||
};
|
||||
|
||||
} // namespace NIFM
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "common/common_paths.h"
|
||||
#include "common/file_util.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/ns/pl_u.h"
|
||||
|
||||
@@ -90,13 +91,13 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
|
||||
// dump. In the future, we need to replace this with a more robust solution.
|
||||
|
||||
// Map backing memory for the font data
|
||||
Kernel::g_current_process->vm_manager.MapMemoryBlock(SHARED_FONT_MEM_VADDR, shared_font, 0,
|
||||
SHARED_FONT_MEM_SIZE,
|
||||
Kernel::MemoryState::Shared);
|
||||
Core::CurrentProcess()->vm_manager.MapMemoryBlock(SHARED_FONT_MEM_VADDR, shared_font, 0,
|
||||
SHARED_FONT_MEM_SIZE,
|
||||
Kernel::MemoryState::Shared);
|
||||
|
||||
// Create shared font memory object
|
||||
shared_font_mem = Kernel::SharedMemory::Create(
|
||||
Kernel::g_current_process, SHARED_FONT_MEM_SIZE, Kernel::MemoryPermission::ReadWrite,
|
||||
Core::CurrentProcess(), SHARED_FONT_MEM_SIZE, Kernel::MemoryPermission::ReadWrite,
|
||||
Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE,
|
||||
"PL_U:shared_font_mem");
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector
|
||||
void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height,
|
||||
u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform) {
|
||||
VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle);
|
||||
//LOG_WARNING(Service,
|
||||
// "Drawing from address %llx offset %08X Width %u Height %u Stride %u Format %u",
|
||||
// addr, offset, width, height, stride, format);
|
||||
LOG_WARNING(Service,
|
||||
"Drawing from address %llx offset %08X Width %u Height %u Stride %u Format %u",
|
||||
addr, offset, width, height, stride, format);
|
||||
|
||||
using PixelFormat = RendererBase::FramebufferInfo::PixelFormat;
|
||||
using Flags = NVFlinger::BufferQueue::BufferTransformFlags;
|
||||
|
||||
@@ -36,9 +36,7 @@ u32 BufferQueue::DequeueBuffer(u32 pixel_format, u32 width, u32 height) {
|
||||
return false;
|
||||
|
||||
// Make sure that the parameters match.
|
||||
auto& igbp_buffer = buffer.igbp_buffer;
|
||||
return igbp_buffer.format == pixel_format && igbp_buffer.width == width &&
|
||||
igbp_buffer.height == height;
|
||||
return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height;
|
||||
});
|
||||
if (itr == queue.end()) {
|
||||
LOG_CRITICAL(Service_NVDRV, "no free buffers for pixel_format=%d, width=%d, height=%d",
|
||||
|
||||
@@ -21,10 +21,6 @@ namespace NVFlinger {
|
||||
constexpr size_t SCREEN_REFRESH_RATE = 60;
|
||||
constexpr u64 frame_ticks = static_cast<u64>(BASE_CLOCK_RATE / SCREEN_REFRESH_RATE);
|
||||
|
||||
// libnx "GfxMode_TiledSingle" hack. libnx does not use queue/dequeue buffer
|
||||
// in GfxMode_TiledSingle mode, we maintain a pointer to the last queued buffer
|
||||
static BufferQueue::Buffer nxBuffer{};
|
||||
|
||||
NVFlinger::NVFlinger() {
|
||||
// Add the different displays to the list of displays.
|
||||
Display default_{0, "Default"};
|
||||
@@ -132,50 +128,31 @@ void NVFlinger::Compose() {
|
||||
// Search for a queued buffer and acquire it
|
||||
auto buffer = buffer_queue->AcquireBuffer();
|
||||
|
||||
if (buffer == boost::none && nxBuffer.status == BufferQueue::Buffer::Status::Free) {
|
||||
if (buffer == boost::none) {
|
||||
// There was no queued buffer to draw, render previous frame
|
||||
Core::System::GetInstance().perf_stats.EndGameFrame();
|
||||
VideoCore::g_renderer->SwapBuffers({});
|
||||
continue;
|
||||
} else if(nxBuffer.status == BufferQueue::Buffer::Status::Free) {
|
||||
nxBuffer.slot = buffer->slot;
|
||||
nxBuffer.status = BufferQueue::Buffer::Status::Queued;
|
||||
memcpy(&nxBuffer.igbp_buffer, &buffer->igbp_buffer, sizeof(IGBPBuffer));
|
||||
memcpy(&nxBuffer.transform, &buffer->transform, sizeof(BufferQueue::BufferTransformFlags));
|
||||
}
|
||||
|
||||
if(buffer == boost::none && nxBuffer.status != BufferQueue::Buffer::Status::Free) {
|
||||
auto &igbp_buffer = nxBuffer.igbp_buffer;
|
||||
auto& igbp_buffer = buffer->igbp_buffer;
|
||||
|
||||
// Now send the buffer to the GPU for drawing.
|
||||
auto nvdrv = Nvidia::nvdrv.lock();
|
||||
ASSERT(nvdrv);
|
||||
// Now send the buffer to the GPU for drawing.
|
||||
auto nvdrv = Nvidia::nvdrv.lock();
|
||||
ASSERT(nvdrv);
|
||||
|
||||
// TODO(Subv): Support more than just disp0. The display device selection is probably based
|
||||
// on which display we're drawing (Default, Internal, External, etc)
|
||||
auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");
|
||||
ASSERT(nvdisp);
|
||||
// TODO(Subv): Support more than just disp0. The display device selection is probably based
|
||||
// on which display we're drawing (Default, Internal, External, etc)
|
||||
auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");
|
||||
ASSERT(nvdisp);
|
||||
|
||||
nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format,
|
||||
igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, nxBuffer.transform);
|
||||
nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format,
|
||||
igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->transform);
|
||||
|
||||
} else {
|
||||
auto &igbp_buffer = buffer->igbp_buffer;
|
||||
buffer_queue->ReleaseBuffer(buffer->slot);
|
||||
|
||||
// Now send the buffer to the GPU for drawing.
|
||||
auto nvdrv = Nvidia::nvdrv.lock();
|
||||
ASSERT(nvdrv);
|
||||
|
||||
// TODO(Subv): Support more than just disp0. The display device selection is probably based
|
||||
// on which display we're drawing (Default, Internal, External, etc)
|
||||
auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");
|
||||
ASSERT(nvdisp);
|
||||
|
||||
nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format,
|
||||
igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->transform);
|
||||
|
||||
buffer_queue->ReleaseBuffer(buffer->slot);
|
||||
}
|
||||
// TODO(Subv): Figure out when we should actually signal this event.
|
||||
buffer_queue->GetNativeHandle()->Signal();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
@@ -28,7 +29,7 @@
|
||||
#include "core/hle/service/nvdrv/nvdrv.h"
|
||||
#include "core/hle/service/pctl/pctl.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/set/set.h"
|
||||
#include "core/hle/service/set/settings.h"
|
||||
#include "core/hle/service/sm/controller.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
#include "core/hle/service/sockets/sockets.h"
|
||||
@@ -152,8 +153,7 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
|
||||
}
|
||||
|
||||
u32* cmd_buf = (u32*)Memory::GetPointer(Kernel::GetCurrentThread()->GetTLSAddress());
|
||||
context.WriteToOutgoingCommandBuffer(cmd_buf, *Kernel::g_current_process,
|
||||
Kernel::g_handle_table);
|
||||
context.WriteToOutgoingCommandBuffer(cmd_buf, *Core::CurrentProcess(), Kernel::g_handle_table);
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -26,16 +26,19 @@ void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called");
|
||||
}
|
||||
|
||||
SET::SET(const char* name) : ServiceFramework(name) {
|
||||
SET::SET() : ServiceFramework("set") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetLanguageCode"},
|
||||
{1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
|
||||
{2, nullptr, "MakeLanguageCode"},
|
||||
{3, nullptr, "GetAvailableLanguageCodeCount"},
|
||||
{4, nullptr, "GetRegionCode"},
|
||||
{5, nullptr, "GetAvailableLanguageCodes2"},
|
||||
{6, nullptr, "GetAvailableLanguageCodeCount2"},
|
||||
{7, nullptr, "GetKeyCodeMap"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
std::make_shared<SET>("set")->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace Set
|
||||
} // namespace Service
|
||||
|
||||
@@ -11,15 +11,12 @@ namespace Set {
|
||||
|
||||
class SET final : public ServiceFramework<SET> {
|
||||
public:
|
||||
explicit SET(const char* name);
|
||||
explicit SET();
|
||||
~SET() = default;
|
||||
|
||||
private:
|
||||
void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
/// Registers all Set services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager);
|
||||
|
||||
} // namespace Set
|
||||
} // namespace Service
|
||||
|
||||
40
src/core/hle/service/set/set_cal.cpp
Normal file
40
src/core/hle/service/set/set_cal.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/set/set_cal.h"
|
||||
|
||||
namespace Service {
|
||||
namespace Set {
|
||||
|
||||
SET_CAL::SET_CAL() : ServiceFramework("set:cal") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetBluetoothBdAddress"},
|
||||
{1, nullptr, "GetConfigurationId1"},
|
||||
{2, nullptr, "GetAccelerometerOffset"},
|
||||
{3, nullptr, "GetAccelerometerScale"},
|
||||
{4, nullptr, "GetGyroscopeOffset"},
|
||||
{5, nullptr, "GetGyroscopeScale"},
|
||||
{6, nullptr, "GetWirelessLanMacAddress"},
|
||||
{7, nullptr, "GetWirelessLanCountryCodeCount"},
|
||||
{8, nullptr, "GetWirelessLanCountryCodes"},
|
||||
{9, nullptr, "GetSerialNumber"},
|
||||
{10, nullptr, "SetInitialSystemAppletProgramId"},
|
||||
{11, nullptr, "SetOverlayDispProgramId"},
|
||||
{12, nullptr, "GetBatteryLot"},
|
||||
{14, nullptr, "GetEciDeviceCertificate"},
|
||||
{15, nullptr, "GetEticketDeviceCertificate"},
|
||||
{16, nullptr, "GetSslKey"},
|
||||
{17, nullptr, "GetSslCertificate"},
|
||||
{18, nullptr, "GetGameCardKey"},
|
||||
{19, nullptr, "GetGameCardCertificate"},
|
||||
{20, nullptr, "GetEciDeviceKey"},
|
||||
{21, nullptr, "GetEticketDeviceKey"},
|
||||
{22, nullptr, "GetSpeakerParameter"},
|
||||
{23, nullptr, "GetLcdVendorId"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Set
|
||||
} // namespace Service
|
||||
19
src/core/hle/service/set/set_cal.h
Normal file
19
src/core/hle/service/set/set_cal.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service {
|
||||
namespace Set {
|
||||
|
||||
class SET_CAL final : public ServiceFramework<SET_CAL> {
|
||||
public:
|
||||
explicit SET_CAL();
|
||||
~SET_CAL() = default;
|
||||
};
|
||||
|
||||
} // namespace Set
|
||||
} // namespace Service
|
||||
25
src/core/hle/service/set/set_fd.cpp
Normal file
25
src/core/hle/service/set/set_fd.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/set/set_fd.h"
|
||||
|
||||
namespace Service {
|
||||
namespace Set {
|
||||
|
||||
SET_FD::SET_FD() : ServiceFramework("set:fd") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{2, nullptr, "SetSettingsItemValue"},
|
||||
{3, nullptr, "ResetSettingsItemValue"},
|
||||
{4, nullptr, "CreateSettingsItemKeyIterator"},
|
||||
{10, nullptr, "ReadSettings"},
|
||||
{11, nullptr, "ResetSettings"},
|
||||
{20, nullptr, "SetWebInspectorFlag"},
|
||||
{21, nullptr, "SetAllowedSslHosts"},
|
||||
{22, nullptr, "SetHostFsMountPoint"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Set
|
||||
} // namespace Service
|
||||
19
src/core/hle/service/set/set_fd.h
Normal file
19
src/core/hle/service/set/set_fd.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service {
|
||||
namespace Set {
|
||||
|
||||
class SET_FD final : public ServiceFramework<SET_FD> {
|
||||
public:
|
||||
explicit SET_FD();
|
||||
~SET_FD() = default;
|
||||
};
|
||||
|
||||
} // namespace Set
|
||||
} // namespace Service
|
||||
167
src/core/hle/service/set/set_sys.cpp
Normal file
167
src/core/hle/service/set/set_sys.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/service/set/set_sys.h"
|
||||
|
||||
namespace Service {
|
||||
namespace Set {
|
||||
|
||||
void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u32>(0);
|
||||
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called");
|
||||
}
|
||||
|
||||
SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "SetLanguageCode"},
|
||||
{1, nullptr, "SetNetworkSettings"},
|
||||
{2, nullptr, "GetNetworkSettings"},
|
||||
{3, nullptr, "GetFirmwareVersion"},
|
||||
{4, nullptr, "GetFirmwareVersion2"},
|
||||
{7, nullptr, "GetLockScreenFlag"},
|
||||
{8, nullptr, "SetLockScreenFlag"},
|
||||
{9, nullptr, "GetBacklightSettings"},
|
||||
{10, nullptr, "SetBacklightSettings"},
|
||||
{11, nullptr, "SetBluetoothDevicesSettings"},
|
||||
{12, nullptr, "GetBluetoothDevicesSettings"},
|
||||
{13, nullptr, "GetExternalSteadyClockSourceId"},
|
||||
{14, nullptr, "SetExternalSteadyClockSourceId"},
|
||||
{15, nullptr, "GetUserSystemClockContext"},
|
||||
{16, nullptr, "SetUserSystemClockContext"},
|
||||
{17, nullptr, "GetAccountSettings"},
|
||||
{18, nullptr, "SetAccountSettings"},
|
||||
{19, nullptr, "GetAudioVolume"},
|
||||
{20, nullptr, "SetAudioVolume"},
|
||||
{21, nullptr, "GetEulaVersions"},
|
||||
{22, nullptr, "SetEulaVersions"},
|
||||
{23, &SET_SYS::GetColorSetId, "GetColorSetId"},
|
||||
{24, nullptr, "SetColorSetId"},
|
||||
{25, nullptr, "GetConsoleInformationUploadFlag"},
|
||||
{26, nullptr, "SetConsoleInformationUploadFlag"},
|
||||
{27, nullptr, "GetAutomaticApplicationDownloadFlag"},
|
||||
{28, nullptr, "SetAutomaticApplicationDownloadFlag"},
|
||||
{29, nullptr, "GetNotificationSettings"},
|
||||
{30, nullptr, "SetNotificationSettings"},
|
||||
{31, nullptr, "GetAccountNotificationSettings"},
|
||||
{32, nullptr, "SetAccountNotificationSettings"},
|
||||
{35, nullptr, "GetVibrationMasterVolume"},
|
||||
{36, nullptr, "SetVibrationMasterVolume"},
|
||||
{37, nullptr, "GetSettingsItemValueSize"},
|
||||
{38, nullptr, "GetSettingsItemValue"},
|
||||
{39, nullptr, "GetTvSettings"},
|
||||
{40, nullptr, "SetTvSettings"},
|
||||
{41, nullptr, "GetEdid"},
|
||||
{42, nullptr, "SetEdid"},
|
||||
{43, nullptr, "GetAudioOutputMode"},
|
||||
{44, nullptr, "SetAudioOutputMode"},
|
||||
{45, nullptr, "IsForceMuteOnHeadphoneRemoved"},
|
||||
{46, nullptr, "SetForceMuteOnHeadphoneRemoved"},
|
||||
{47, nullptr, "GetQuestFlag"},
|
||||
{48, nullptr, "SetQuestFlag"},
|
||||
{49, nullptr, "GetDataDeletionSettings"},
|
||||
{50, nullptr, "SetDataDeletionSettings"},
|
||||
{51, nullptr, "GetInitialSystemAppletProgramId"},
|
||||
{52, nullptr, "GetOverlayDispProgramId"},
|
||||
{53, nullptr, "GetDeviceTimeZoneLocationName"},
|
||||
{54, nullptr, "SetDeviceTimeZoneLocationName"},
|
||||
{55, nullptr, "GetWirelessCertificationFileSize"},
|
||||
{56, nullptr, "GetWirelessCertificationFile"},
|
||||
{57, nullptr, "SetRegionCode"},
|
||||
{58, nullptr, "GetNetworkSystemClockContext"},
|
||||
{59, nullptr, "SetNetworkSystemClockContext"},
|
||||
{60, nullptr, "IsUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{61, nullptr, "SetUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{62, nullptr, "GetDebugModeFlag"},
|
||||
{63, nullptr, "GetPrimaryAlbumStorage"},
|
||||
{64, nullptr, "SetPrimaryAlbumStorage"},
|
||||
{65, nullptr, "GetUsb30EnableFlag"},
|
||||
{66, nullptr, "SetUsb30EnableFlag"},
|
||||
{67, nullptr, "GetBatteryLot"},
|
||||
{68, nullptr, "GetSerialNumber"},
|
||||
{69, nullptr, "GetNfcEnableFlag"},
|
||||
{70, nullptr, "SetNfcEnableFlag"},
|
||||
{71, nullptr, "GetSleepSettings"},
|
||||
{72, nullptr, "SetSleepSettings"},
|
||||
{73, nullptr, "GetWirelessLanEnableFlag"},
|
||||
{74, nullptr, "SetWirelessLanEnableFlag"},
|
||||
{75, nullptr, "GetInitialLaunchSettings"},
|
||||
{76, nullptr, "SetInitialLaunchSettings"},
|
||||
{77, nullptr, "GetDeviceNickName"},
|
||||
{78, nullptr, "SetDeviceNickName"},
|
||||
{79, nullptr, "GetProductModel"},
|
||||
{80, nullptr, "GetLdnChannel"},
|
||||
{81, nullptr, "SetLdnChannel"},
|
||||
{82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"},
|
||||
{83, nullptr, "GetTelemetryDirtyFlags"},
|
||||
{84, nullptr, "GetPtmBatteryLot"},
|
||||
{85, nullptr, "SetPtmBatteryLot"},
|
||||
{86, nullptr, "GetPtmFuelGaugeParameter"},
|
||||
{87, nullptr, "SetPtmFuelGaugeParameter"},
|
||||
{88, nullptr, "GetBluetoothEnableFlag"},
|
||||
{89, nullptr, "SetBluetoothEnableFlag"},
|
||||
{90, nullptr, "GetMiiAuthorId"},
|
||||
{91, nullptr, "SetShutdownRtcValue"},
|
||||
{92, nullptr, "GetShutdownRtcValue"},
|
||||
{93, nullptr, "AcquireFatalDirtyFlagEventHandle"},
|
||||
{94, nullptr, "GetFatalDirtyFlags"},
|
||||
{95, nullptr, "GetAutoUpdateEnableFlag"},
|
||||
{96, nullptr, "SetAutoUpdateEnableFlag"},
|
||||
{97, nullptr, "GetNxControllerSettings"},
|
||||
{98, nullptr, "SetNxControllerSettings"},
|
||||
{99, nullptr, "GetBatteryPercentageFlag"},
|
||||
{100, nullptr, "SetBatteryPercentageFlag"},
|
||||
{101, nullptr, "GetExternalRtcResetFlag"},
|
||||
{102, nullptr, "SetExternalRtcResetFlag"},
|
||||
{103, nullptr, "GetUsbFullKeyEnableFlag"},
|
||||
{104, nullptr, "SetUsbFullKeyEnableFlag"},
|
||||
{105, nullptr, "SetExternalSteadyClockInternalOffset"},
|
||||
{106, nullptr, "GetExternalSteadyClockInternalOffset"},
|
||||
{107, nullptr, "GetBacklightSettingsEx"},
|
||||
{108, nullptr, "SetBacklightSettingsEx"},
|
||||
{109, nullptr, "GetHeadphoneVolumeWarningCount"},
|
||||
{110, nullptr, "SetHeadphoneVolumeWarningCount"},
|
||||
{111, nullptr, "GetBluetoothAfhEnableFlag"},
|
||||
{112, nullptr, "SetBluetoothAfhEnableFlag"},
|
||||
{113, nullptr, "GetBluetoothBoostEnableFlag"},
|
||||
{114, nullptr, "SetBluetoothBoostEnableFlag"},
|
||||
{115, nullptr, "GetInRepairProcessEnableFlag"},
|
||||
{116, nullptr, "SetInRepairProcessEnableFlag"},
|
||||
{117, nullptr, "GetHeadphoneVolumeUpdateFlag"},
|
||||
{118, nullptr, "SetHeadphoneVolumeUpdateFlag"},
|
||||
{119, nullptr, "NeedsToUpdateHeadphoneVolume"},
|
||||
{120, nullptr, "GetPushNotificationActivityModeOnSleep"},
|
||||
{121, nullptr, "SetPushNotificationActivityModeOnSleep"},
|
||||
{122, nullptr, "GetServiceDiscoveryControlSettings"},
|
||||
{123, nullptr, "SetServiceDiscoveryControlSettings"},
|
||||
{124, nullptr, "GetErrorReportSharePermission"},
|
||||
{125, nullptr, "SetErrorReportSharePermission"},
|
||||
{126, nullptr, "GetAppletLaunchFlags"},
|
||||
{127, nullptr, "SetAppletLaunchFlags"},
|
||||
{128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"},
|
||||
{129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"},
|
||||
{130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"},
|
||||
{131, nullptr, "SetConsoleSixAxisSensorAngularVelocityBias"},
|
||||
{132, nullptr, "GetConsoleSixAxisSensorAccelerationGain"},
|
||||
{133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"},
|
||||
{134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"},
|
||||
{135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"},
|
||||
{136, nullptr, "GetKeyboardLayout"},
|
||||
{137, nullptr, "SetKeyboardLayout"},
|
||||
{138, nullptr, "GetWebInspectorFlag"},
|
||||
{139, nullptr, "GetAllowedSslHosts"},
|
||||
{140, nullptr, "GetHostFsMountPoint"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Set
|
||||
} // namespace Service
|
||||
22
src/core/hle/service/set/set_sys.h
Normal file
22
src/core/hle/service/set/set_sys.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service {
|
||||
namespace Set {
|
||||
|
||||
class SET_SYS final : public ServiceFramework<SET_SYS> {
|
||||
public:
|
||||
explicit SET_SYS();
|
||||
~SET_SYS() = default;
|
||||
|
||||
private:
|
||||
void GetColorSetId(Kernel::HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
} // namespace Set
|
||||
} // namespace Service
|
||||
22
src/core/hle/service/set/settings.cpp
Normal file
22
src/core/hle/service/set/settings.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/set/set.h"
|
||||
#include "core/hle/service/set/set_cal.h"
|
||||
#include "core/hle/service/set/set_fd.h"
|
||||
#include "core/hle/service/set/set_sys.h"
|
||||
#include "core/hle/service/set/settings.h"
|
||||
|
||||
namespace Service {
|
||||
namespace Set {
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||
std::make_shared<SET>()->InstallAsService(service_manager);
|
||||
std::make_shared<SET_CAL>()->InstallAsService(service_manager);
|
||||
std::make_shared<SET_FD>()->InstallAsService(service_manager);
|
||||
std::make_shared<SET_SYS>()->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
} // namespace Set
|
||||
} // namespace Service
|
||||
16
src/core/hle/service/set/settings.h
Normal file
16
src/core/hle/service/set/settings.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service {
|
||||
namespace Set {
|
||||
|
||||
/// Registers all Settings services with the specified service manager.
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager);
|
||||
|
||||
} // namespace Set
|
||||
} // namespace Service
|
||||
@@ -119,8 +119,6 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
|
||||
}
|
||||
metadata.Print();
|
||||
|
||||
process = Kernel::Process::Create("main", metadata.GetTitleID());
|
||||
|
||||
// Load NSO modules
|
||||
VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR};
|
||||
for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
|
||||
@@ -135,6 +133,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
|
||||
}
|
||||
}
|
||||
|
||||
process->program_id = metadata.GetTitleID();
|
||||
process->svc_access_mask.set();
|
||||
process->address_mappings = default_address_mappings;
|
||||
process->resource_limit =
|
||||
|
||||
@@ -406,7 +406,6 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) {
|
||||
SharedPtr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR);
|
||||
codeset->name = filename;
|
||||
|
||||
process = Kernel::Process::Create("main", 0);
|
||||
process->LoadModule(codeset, codeset->entrypoint);
|
||||
process->svc_access_mask.set();
|
||||
process->address_mappings = default_address_mappings;
|
||||
@@ -415,7 +414,7 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) {
|
||||
process->resource_limit =
|
||||
Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
|
||||
|
||||
process->Run(codeset->entrypoint, 48, Kernel::DEFAULT_STACK_SIZE);
|
||||
process->Run(codeset->entrypoint, 48, Memory::STACK_SIZE);
|
||||
|
||||
is_loaded = true;
|
||||
return ResultStatus::Success;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "common/file_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/resource_limit.h"
|
||||
#include "core/loader/nro.h"
|
||||
@@ -112,7 +113,7 @@ bool AppLoader_NRO::LoadNro(const std::string& path, VAddr load_base) {
|
||||
// Load codeset for current process
|
||||
codeset->name = path;
|
||||
codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
|
||||
Kernel::g_current_process->LoadModule(codeset, load_base);
|
||||
Core::CurrentProcess()->LoadModule(codeset, load_base);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -125,8 +126,6 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
|
||||
return ResultStatus::Error;
|
||||
}
|
||||
|
||||
process = Kernel::Process::Create("main", 0);
|
||||
|
||||
// Load NRO
|
||||
static constexpr VAddr base_addr{Memory::PROCESS_IMAGE_VADDR};
|
||||
|
||||
@@ -138,7 +137,7 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
|
||||
process->address_mappings = default_address_mappings;
|
||||
process->resource_limit =
|
||||
Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
|
||||
process->Run(base_addr, 48, Kernel::DEFAULT_STACK_SIZE);
|
||||
process->Run(base_addr, 48, Memory::STACK_SIZE);
|
||||
|
||||
is_loaded = true;
|
||||
return ResultStatus::Success;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "common/file_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/resource_limit.h"
|
||||
#include "core/loader/nso.h"
|
||||
@@ -142,7 +143,7 @@ VAddr AppLoader_NSO::LoadModule(const std::string& path, VAddr load_base) {
|
||||
// Load codeset for current process
|
||||
codeset->name = path;
|
||||
codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
|
||||
Kernel::g_current_process->LoadModule(codeset, load_base);
|
||||
Core::CurrentProcess()->LoadModule(codeset, load_base);
|
||||
|
||||
return load_base + image_size;
|
||||
}
|
||||
@@ -155,8 +156,6 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
|
||||
return ResultStatus::Error;
|
||||
}
|
||||
|
||||
process = Kernel::Process::Create("main", 0);
|
||||
|
||||
// Load module
|
||||
LoadModule(filepath, Memory::PROCESS_IMAGE_VADDR);
|
||||
LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, filepath.c_str(),
|
||||
@@ -166,7 +165,7 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
|
||||
process->address_mappings = default_address_mappings;
|
||||
process->resource_limit =
|
||||
Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
|
||||
process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE);
|
||||
process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Memory::STACK_SIZE);
|
||||
|
||||
is_loaded = true;
|
||||
return ResultStatus::Success;
|
||||
|
||||
@@ -109,7 +109,7 @@ static std::set<MemoryHookPointer> GetSpecialHandlers(const PageTable& page_tabl
|
||||
}
|
||||
|
||||
static std::set<MemoryHookPointer> GetSpecialHandlers(VAddr vaddr, u64 size) {
|
||||
const PageTable& page_table = Kernel::g_current_process->vm_manager.page_table;
|
||||
const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table;
|
||||
return GetSpecialHandlers(page_table, vaddr, size);
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) {
|
||||
}
|
||||
|
||||
bool IsValidVirtualAddress(const VAddr vaddr) {
|
||||
return IsValidVirtualAddress(*Kernel::g_current_process, vaddr);
|
||||
return IsValidVirtualAddress(*Core::CurrentProcess(), vaddr);
|
||||
}
|
||||
|
||||
bool IsValidPhysicalAddress(const PAddr paddr) {
|
||||
@@ -364,7 +364,7 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_
|
||||
}
|
||||
|
||||
void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) {
|
||||
ReadBlock(*Kernel::g_current_process, src_addr, dest_buffer, size);
|
||||
ReadBlock(*Core::CurrentProcess(), src_addr, dest_buffer, size);
|
||||
}
|
||||
|
||||
void Write8(const VAddr addr, const u8 data) {
|
||||
@@ -435,11 +435,11 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi
|
||||
}
|
||||
|
||||
void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size) {
|
||||
WriteBlock(*Kernel::g_current_process, dest_addr, src_buffer, size);
|
||||
WriteBlock(*Core::CurrentProcess(), dest_addr, src_buffer, size);
|
||||
}
|
||||
|
||||
void ZeroBlock(const VAddr dest_addr, const size_t size) {
|
||||
const auto& process = *Kernel::g_current_process;
|
||||
const auto& process = *Core::CurrentProcess();
|
||||
|
||||
size_t remaining_size = size;
|
||||
size_t page_index = dest_addr >> PAGE_BITS;
|
||||
@@ -480,7 +480,7 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
|
||||
}
|
||||
|
||||
void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
|
||||
const auto& process = *Kernel::g_current_process;
|
||||
const auto& process = *Core::CurrentProcess();
|
||||
|
||||
size_t remaining_size = size;
|
||||
size_t page_index = src_addr >> PAGE_BITS;
|
||||
@@ -526,7 +526,7 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
|
||||
|
||||
template <>
|
||||
boost::optional<u8> ReadSpecial<u8>(VAddr addr) {
|
||||
const PageTable& page_table = Kernel::g_current_process->vm_manager.page_table;
|
||||
const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table;
|
||||
for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u8)))
|
||||
if (auto result = handler->Read8(addr))
|
||||
return *result;
|
||||
@@ -535,7 +535,7 @@ boost::optional<u8> ReadSpecial<u8>(VAddr addr) {
|
||||
|
||||
template <>
|
||||
boost::optional<u16> ReadSpecial<u16>(VAddr addr) {
|
||||
const PageTable& page_table = Kernel::g_current_process->vm_manager.page_table;
|
||||
const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table;
|
||||
for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u16)))
|
||||
if (auto result = handler->Read16(addr))
|
||||
return *result;
|
||||
@@ -544,7 +544,7 @@ boost::optional<u16> ReadSpecial<u16>(VAddr addr) {
|
||||
|
||||
template <>
|
||||
boost::optional<u32> ReadSpecial<u32>(VAddr addr) {
|
||||
const PageTable& page_table = Kernel::g_current_process->vm_manager.page_table;
|
||||
const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table;
|
||||
for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u32)))
|
||||
if (auto result = handler->Read32(addr))
|
||||
return *result;
|
||||
@@ -553,7 +553,7 @@ boost::optional<u32> ReadSpecial<u32>(VAddr addr) {
|
||||
|
||||
template <>
|
||||
boost::optional<u64> ReadSpecial<u64>(VAddr addr) {
|
||||
const PageTable& page_table = Kernel::g_current_process->vm_manager.page_table;
|
||||
const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table;
|
||||
for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u64)))
|
||||
if (auto result = handler->Read64(addr))
|
||||
return *result;
|
||||
@@ -562,7 +562,7 @@ boost::optional<u64> ReadSpecial<u64>(VAddr addr) {
|
||||
|
||||
template <>
|
||||
bool WriteSpecial<u8>(VAddr addr, const u8 data) {
|
||||
const PageTable& page_table = Kernel::g_current_process->vm_manager.page_table;
|
||||
const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table;
|
||||
for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u8)))
|
||||
if (handler->Write8(addr, data))
|
||||
return true;
|
||||
@@ -571,7 +571,7 @@ bool WriteSpecial<u8>(VAddr addr, const u8 data) {
|
||||
|
||||
template <>
|
||||
bool WriteSpecial<u16>(VAddr addr, const u16 data) {
|
||||
const PageTable& page_table = Kernel::g_current_process->vm_manager.page_table;
|
||||
const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table;
|
||||
for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u16)))
|
||||
if (handler->Write16(addr, data))
|
||||
return true;
|
||||
@@ -580,7 +580,7 @@ bool WriteSpecial<u16>(VAddr addr, const u16 data) {
|
||||
|
||||
template <>
|
||||
bool WriteSpecial<u32>(VAddr addr, const u32 data) {
|
||||
const PageTable& page_table = Kernel::g_current_process->vm_manager.page_table;
|
||||
const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table;
|
||||
for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u32)))
|
||||
if (handler->Write32(addr, data))
|
||||
return true;
|
||||
@@ -589,7 +589,7 @@ bool WriteSpecial<u32>(VAddr addr, const u32 data) {
|
||||
|
||||
template <>
|
||||
bool WriteSpecial<u64>(VAddr addr, const u64 data) {
|
||||
const PageTable& page_table = Kernel::g_current_process->vm_manager.page_table;
|
||||
const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table;
|
||||
for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u64)))
|
||||
if (handler->Write64(addr, data))
|
||||
return true;
|
||||
@@ -632,7 +632,7 @@ boost::optional<VAddr> PhysicalToVirtualAddress(const PAddr addr) {
|
||||
} else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
|
||||
return addr - VRAM_PADDR + VRAM_VADDR;
|
||||
} else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) {
|
||||
return addr - FCRAM_PADDR + Kernel::g_current_process->GetLinearHeapAreaAddress();
|
||||
return addr - FCRAM_PADDR + Core::CurrentProcess()->GetLinearHeapAreaAddress();
|
||||
} else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) {
|
||||
return addr - DSP_RAM_PADDR + DSP_RAM_VADDR;
|
||||
} else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) {
|
||||
|
||||
@@ -129,21 +129,6 @@ enum : VAddr {
|
||||
PROCESS_IMAGE_MAX_SIZE = 0x08000000,
|
||||
PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE,
|
||||
|
||||
/// Area where IPC buffers are mapped onto.
|
||||
IPC_MAPPING_VADDR = 0x04000000,
|
||||
IPC_MAPPING_SIZE = 0x04000000,
|
||||
IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE,
|
||||
|
||||
/// Application heap (includes stack).
|
||||
HEAP_VADDR = 0x108000000,
|
||||
HEAP_SIZE = 0xF0000000,
|
||||
HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE,
|
||||
|
||||
/// Area where shared memory buffers are mapped onto.
|
||||
SHARED_MEMORY_VADDR = 0x10000000,
|
||||
SHARED_MEMORY_SIZE = 0x04000000,
|
||||
SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE,
|
||||
|
||||
/// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical
|
||||
/// memory.
|
||||
LINEAR_HEAP_VADDR = 0x14000000,
|
||||
@@ -176,14 +161,39 @@ enum : VAddr {
|
||||
SHARED_PAGE_SIZE = 0x00001000,
|
||||
SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE,
|
||||
|
||||
/// Area where TLS (Thread-Local Storage) buffers are allocated.
|
||||
TLS_AREA_VADDR = 0x228000000,
|
||||
TLS_ENTRY_SIZE = 0x200,
|
||||
|
||||
/// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS.
|
||||
NEW_LINEAR_HEAP_VADDR = 0x30000000,
|
||||
NEW_LINEAR_HEAP_SIZE = 0x10000000,
|
||||
NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE,
|
||||
|
||||
/// Area where TLS (Thread-Local Storage) buffers are allocated.
|
||||
TLS_AREA_VADDR = NEW_LINEAR_HEAP_VADDR_END,
|
||||
TLS_ENTRY_SIZE = 0x200,
|
||||
TLS_AREA_SIZE = 0x10000000,
|
||||
TLS_ADREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE,
|
||||
|
||||
/// Application stack
|
||||
STACK_VADDR = TLS_ADREA_VADDR_END,
|
||||
STACK_SIZE = 0x10000,
|
||||
STACK_VADDR_END = STACK_VADDR + STACK_SIZE,
|
||||
|
||||
/// Application heap
|
||||
/// Size is confirmed to be a static value on fw 3.0.0
|
||||
HEAP_VADDR = 0x108000000,
|
||||
HEAP_SIZE = 0x180000000,
|
||||
HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE,
|
||||
|
||||
/// New map region
|
||||
/// Size is confirmed to be a static value on fw 3.0.0
|
||||
NEW_MAP_REGION_VADDR = HEAP_VADDR_END,
|
||||
NEW_MAP_REGION_SIZE = 0x80000000,
|
||||
NEW_MAP_REGION_VADDR_END = NEW_MAP_REGION_VADDR + NEW_MAP_REGION_SIZE,
|
||||
|
||||
/// Map region
|
||||
/// Size is confirmed to be a static value on fw 3.0.0
|
||||
MAP_REGION_VADDR = NEW_MAP_REGION_VADDR_END,
|
||||
MAP_REGION_SIZE = 0x1000000000,
|
||||
MAP_REGION_VADDR_END = MAP_REGION_VADDR + MAP_REGION_SIZE,
|
||||
};
|
||||
|
||||
/// Currently active page table
|
||||
|
||||
@@ -15,8 +15,8 @@ static Memory::PageTable* page_table = nullptr;
|
||||
TestEnvironment::TestEnvironment(bool mutable_memory_)
|
||||
: mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) {
|
||||
|
||||
Kernel::g_current_process = Kernel::Process::Create("", 0);
|
||||
page_table = &Kernel::g_current_process->vm_manager.page_table;
|
||||
Core::CurrentProcess() = Kernel::Process::Create("");
|
||||
page_table = &Core::CurrentProcess()->vm_manager.page_table;
|
||||
|
||||
page_table->pointers.fill(nullptr);
|
||||
page_table->special_regions.clear();
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory][!hide]") {
|
||||
SECTION("these regions should not be mapped on an empty process") {
|
||||
auto process = Kernel::Process::Create("", 0);
|
||||
auto process = Kernel::Process::Create("");
|
||||
CHECK(Memory::IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false);
|
||||
CHECK(Memory::IsValidVirtualAddress(*process, Memory::HEAP_VADDR) == false);
|
||||
CHECK(Memory::IsValidVirtualAddress(*process, Memory::LINEAR_HEAP_VADDR) == false);
|
||||
@@ -20,14 +20,14 @@ TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory][!hide]") {
|
||||
}
|
||||
|
||||
SECTION("CONFIG_MEMORY_VADDR and SHARED_PAGE_VADDR should be valid after mapping them") {
|
||||
auto process = Kernel::Process::Create("", 0);
|
||||
auto process = Kernel::Process::Create("");
|
||||
Kernel::MapSharedPages(process->vm_manager);
|
||||
CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == true);
|
||||
CHECK(Memory::IsValidVirtualAddress(*process, Memory::SHARED_PAGE_VADDR) == true);
|
||||
}
|
||||
|
||||
SECTION("special regions should be valid after mapping them") {
|
||||
auto process = Kernel::Process::Create("", 0);
|
||||
auto process = Kernel::Process::Create("");
|
||||
SECTION("VRAM") {
|
||||
Kernel::HandleSpecialMapping(process->vm_manager,
|
||||
{Memory::VRAM_VADDR, Memory::VRAM_SIZE, false, false});
|
||||
@@ -48,7 +48,7 @@ TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory][!hide]") {
|
||||
}
|
||||
|
||||
SECTION("Unmapping a VAddr should make it invalid") {
|
||||
auto process = Kernel::Process::Create("", 0);
|
||||
auto process = Kernel::Process::Create("");
|
||||
Kernel::MapSharedPages(process->vm_manager);
|
||||
process->vm_manager.UnmapRange(Memory::CONFIG_MEMORY_VADDR, Memory::CONFIG_MEMORY_SIZE);
|
||||
CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == false);
|
||||
|
||||
@@ -64,6 +64,35 @@ void GPU::WriteReg(u32 method, u32 subchannel, u32 value) {
|
||||
}
|
||||
}
|
||||
|
||||
void GPU::CallMethod(u32 method, u32 subchannel, const std::vector<u32>& parameters) {
|
||||
LOG_WARNING(HW_GPU, "Processing method %08X on subchannel %u num params %zu", method,
|
||||
subchannel, parameters.size());
|
||||
|
||||
if (method < static_cast<u32>(BufferMethods::CountBufferMethods)) {
|
||||
// TODO(Subv): Research and implement these methods.
|
||||
LOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented");
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(bound_engines.find(subchannel) != bound_engines.end());
|
||||
|
||||
const EngineID engine = bound_engines[subchannel];
|
||||
|
||||
switch (engine) {
|
||||
case EngineID::FERMI_TWOD_A:
|
||||
fermi_2d->CallMethod(method, parameters);
|
||||
break;
|
||||
case EngineID::MAXWELL_B:
|
||||
maxwell_3d->CallMethod(method, parameters);
|
||||
break;
|
||||
case EngineID::MAXWELL_COMPUTE_B:
|
||||
maxwell_compute->CallMethod(method, parameters);
|
||||
break;
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
}
|
||||
|
||||
void GPU::ProcessCommandList(GPUVAddr address, u32 size) {
|
||||
// TODO(Subv): PhysicalToVirtualAddress is a misnomer, it converts a GPU VAddr into an
|
||||
// application VAddr.
|
||||
@@ -96,13 +125,17 @@ void GPU::ProcessCommandList(GPUVAddr address, u32 size) {
|
||||
ASSERT(header.arg_count.Value() >= 1);
|
||||
// Use the original method for the first argument and then the next method for all other
|
||||
// arguments.
|
||||
WriteReg(header.method, header.subchannel, Memory::Read32(current_addr));
|
||||
current_addr += sizeof(u32);
|
||||
// Use the same method value for all arguments.
|
||||
for (unsigned i = 1; i < header.arg_count; ++i) {
|
||||
WriteReg(header.method + 1, header.subchannel, Memory::Read32(current_addr));
|
||||
|
||||
// Process this command as a method call instead of a register write. Gather
|
||||
// all the parameters first and then pass them at once to the CallMethod function.
|
||||
std::vector<u32> parameters(header.arg_count);
|
||||
|
||||
for (unsigned i = 0; i < header.arg_count; ++i) {
|
||||
parameters[i] = Memory::Read32(current_addr);
|
||||
current_addr += sizeof(u32);
|
||||
}
|
||||
|
||||
CallMethod(header.method, header.subchannel, parameters);
|
||||
break;
|
||||
}
|
||||
case SubmissionMode::Inline: {
|
||||
|
||||
@@ -34,6 +34,4 @@ static_assert(std::is_standard_layout<CommandHeader>::value == true,
|
||||
"CommandHeader does not use standard layout");
|
||||
static_assert(sizeof(CommandHeader) == sizeof(u32), "CommandHeader has incorrect size!");
|
||||
|
||||
void ProcessCommandList(VAddr address, u32 size);
|
||||
|
||||
} // namespace Tegra
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Tegra {
|
||||
namespace Engines {
|
||||
|
||||
void Fermi2D::WriteReg(u32 method, u32 value) {}
|
||||
void Fermi2D::CallMethod(u32 method, const std::vector<u32>& parameters) {}
|
||||
|
||||
} // namespace Engines
|
||||
} // namespace Tegra
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Tegra {
|
||||
@@ -16,6 +17,13 @@ public:
|
||||
|
||||
/// Write the value to the register identified by method.
|
||||
void WriteReg(u32 method, u32 value);
|
||||
|
||||
/**
|
||||
* Handles a method call to this engine.
|
||||
* @param method Method to call
|
||||
* @param parameters Arguments to the method call
|
||||
*/
|
||||
void CallMethod(u32 method, const std::vector<u32>& parameters);
|
||||
};
|
||||
|
||||
} // namespace Engines
|
||||
|
||||
@@ -8,8 +8,23 @@
|
||||
namespace Tegra {
|
||||
namespace Engines {
|
||||
|
||||
const std::unordered_map<u32, Maxwell3D::MethodInfo> Maxwell3D::method_handlers = {
|
||||
{0xE24, {"SetShader", 5, &Maxwell3D::SetShader}},
|
||||
};
|
||||
|
||||
Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {}
|
||||
|
||||
void Maxwell3D::CallMethod(u32 method, const std::vector<u32>& parameters) {
|
||||
auto itr = method_handlers.find(method);
|
||||
if (itr == method_handlers.end()) {
|
||||
LOG_ERROR(HW_GPU, "Unhandled method call %08X", method);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(itr->second.arguments == parameters.size());
|
||||
(this->*itr->second.handler)(parameters);
|
||||
}
|
||||
|
||||
void Maxwell3D::WriteReg(u32 method, u32 value) {
|
||||
ASSERT_MSG(method < Regs::NUM_REGS,
|
||||
"Invalid Maxwell3D register, increase the size of the Regs structure");
|
||||
@@ -19,6 +34,18 @@ void Maxwell3D::WriteReg(u32 method, u32 value) {
|
||||
#define MAXWELL3D_REG_INDEX(field_name) (offsetof(Regs, field_name) / sizeof(u32))
|
||||
|
||||
switch (method) {
|
||||
case MAXWELL3D_REG_INDEX(code_address.code_address_high):
|
||||
case MAXWELL3D_REG_INDEX(code_address.code_address_low): {
|
||||
// Note: For some reason games (like Puyo Puyo Tetris) seem to write 0 to the CODE_ADDRESS
|
||||
// register, we do not currently know if that's intended or a bug, so we assert it lest
|
||||
// stuff breaks in other places (like the shader address calculation).
|
||||
ASSERT_MSG(regs.code_address.CodeAddress() == 0, "Unexpected CODE_ADDRESS register value.");
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(draw.vertex_end_gl): {
|
||||
DrawArrays();
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(query.query_get): {
|
||||
ProcessQueryGet();
|
||||
break;
|
||||
@@ -47,5 +74,32 @@ void Maxwell3D::ProcessQueryGet() {
|
||||
UNIMPLEMENTED_MSG("Query mode %u not implemented", regs.query.query_get.mode.Value());
|
||||
}
|
||||
}
|
||||
|
||||
void Maxwell3D::DrawArrays() {
|
||||
LOG_WARNING(HW_GPU, "Game requested a DrawArrays, ignoring");
|
||||
}
|
||||
|
||||
void Maxwell3D::SetShader(const std::vector<u32>& parameters) {
|
||||
/**
|
||||
* Parameters description:
|
||||
* [0] = Shader Program.
|
||||
* [1] = Unknown.
|
||||
* [2] = Offset to the start of the shader, after the 0x30 bytes header.
|
||||
* [3] = Shader Type.
|
||||
* [4] = Shader End Address >> 8.
|
||||
*/
|
||||
auto shader_program = static_cast<Regs::ShaderProgram>(parameters[0]);
|
||||
// TODO(Subv): This address is probably an offset from the CODE_ADDRESS register.
|
||||
GPUVAddr begin_address = parameters[2];
|
||||
auto shader_type = static_cast<Regs::ShaderType>(parameters[3]);
|
||||
GPUVAddr end_address = parameters[4] << 8;
|
||||
|
||||
auto& shader = state.shaders[static_cast<size_t>(shader_program)];
|
||||
shader.program = shader_program;
|
||||
shader.type = shader_type;
|
||||
shader.begin_address = begin_address;
|
||||
shader.end_address = end_address;
|
||||
}
|
||||
|
||||
} // namespace Engines
|
||||
} // namespace Tegra
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "common/bit_field.h"
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
@@ -20,6 +23,13 @@ public:
|
||||
/// Write the value to the register identified by method.
|
||||
void WriteReg(u32 method, u32 value);
|
||||
|
||||
/**
|
||||
* Handles a method call to this engine.
|
||||
* @param method Method to call
|
||||
* @param parameters Arguments to the method call
|
||||
*/
|
||||
void CallMethod(u32 method, const std::vector<u32>& parameters);
|
||||
|
||||
/// Register structure of the Maxwell3D engine.
|
||||
/// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
|
||||
struct Regs {
|
||||
@@ -30,9 +40,42 @@ public:
|
||||
Sync = 1,
|
||||
};
|
||||
|
||||
static constexpr size_t MaxShaderProgram = 6;
|
||||
enum class ShaderProgram : u32 {
|
||||
VertexA = 0,
|
||||
VertexB = 1,
|
||||
TesselationControl = 2,
|
||||
TesselationEval = 3,
|
||||
Geometry = 4,
|
||||
Fragment = 5,
|
||||
};
|
||||
|
||||
enum class ShaderType : u32 {
|
||||
Vertex = 0,
|
||||
TesselationControl = 1,
|
||||
TesselationEval = 2,
|
||||
Geometry = 3,
|
||||
Fragment = 4,
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
INSERT_PADDING_WORDS(0x6C0);
|
||||
INSERT_PADDING_WORDS(0x582);
|
||||
struct {
|
||||
u32 code_address_high;
|
||||
u32 code_address_low;
|
||||
|
||||
GPUVAddr CodeAddress() const {
|
||||
return static_cast<GPUVAddr>(
|
||||
(static_cast<GPUVAddr>(code_address_high) << 32) | code_address_low);
|
||||
}
|
||||
} code_address;
|
||||
INSERT_PADDING_WORDS(1);
|
||||
struct {
|
||||
u32 vertex_end_gl;
|
||||
u32 vertex_begin_gl;
|
||||
} draw;
|
||||
INSERT_PADDING_WORDS(0x139);
|
||||
struct {
|
||||
u32 query_address_high;
|
||||
u32 query_address_low;
|
||||
@@ -49,7 +92,28 @@ public:
|
||||
(static_cast<GPUVAddr>(query_address_high) << 32) | query_address_low);
|
||||
}
|
||||
} query;
|
||||
INSERT_PADDING_WORDS(0x772);
|
||||
|
||||
INSERT_PADDING_WORDS(0x13C);
|
||||
|
||||
struct {
|
||||
union {
|
||||
BitField<0, 1, u32> enable;
|
||||
BitField<4, 4, ShaderProgram> program;
|
||||
};
|
||||
u32 start_id;
|
||||
INSERT_PADDING_WORDS(1);
|
||||
u32 gpr_alloc;
|
||||
ShaderType type;
|
||||
INSERT_PADDING_WORDS(9);
|
||||
} shader_config[MaxShaderProgram];
|
||||
|
||||
INSERT_PADDING_WORDS(0x5D0);
|
||||
|
||||
struct {
|
||||
u32 shader_code_call;
|
||||
u32 shader_code_args;
|
||||
} shader_code;
|
||||
INSERT_PADDING_WORDS(0x10);
|
||||
};
|
||||
std::array<u32, NUM_REGS> reg_array;
|
||||
};
|
||||
@@ -57,18 +121,49 @@ public:
|
||||
|
||||
static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size");
|
||||
|
||||
struct State {
|
||||
struct ShaderInfo {
|
||||
Regs::ShaderType type;
|
||||
Regs::ShaderProgram program;
|
||||
GPUVAddr begin_address;
|
||||
GPUVAddr end_address;
|
||||
};
|
||||
|
||||
std::array<ShaderInfo, Regs::MaxShaderProgram> shaders;
|
||||
};
|
||||
|
||||
State state;
|
||||
|
||||
private:
|
||||
MemoryManager& memory_manager;
|
||||
|
||||
/// Handles a write to the QUERY_GET register.
|
||||
void ProcessQueryGet();
|
||||
|
||||
MemoryManager& memory_manager;
|
||||
/// Handles a write to the VERTEX_END_GL register, triggering a draw.
|
||||
void DrawArrays();
|
||||
|
||||
/// Method call handlers
|
||||
void SetShader(const std::vector<u32>& parameters);
|
||||
|
||||
struct MethodInfo {
|
||||
const char* name;
|
||||
u32 arguments;
|
||||
void (Maxwell3D::*handler)(const std::vector<u32>& parameters);
|
||||
};
|
||||
|
||||
static const std::unordered_map<u32, MethodInfo> method_handlers;
|
||||
};
|
||||
|
||||
#define ASSERT_REG_POSITION(field_name, position) \
|
||||
static_assert(offsetof(Maxwell3D::Regs, field_name) == position * 4, \
|
||||
"Field " #field_name " has invalid position")
|
||||
|
||||
ASSERT_REG_POSITION(code_address, 0x582);
|
||||
ASSERT_REG_POSITION(draw, 0x585);
|
||||
ASSERT_REG_POSITION(query, 0x6C0);
|
||||
ASSERT_REG_POSITION(shader_config[0], 0x800);
|
||||
ASSERT_REG_POSITION(shader_code, 0xE24);
|
||||
|
||||
#undef ASSERT_REG_POSITION
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Tegra {
|
||||
namespace Engines {
|
||||
|
||||
void MaxwellCompute::WriteReg(u32 method, u32 value) {}
|
||||
void MaxwellCompute::CallMethod(u32 method, const std::vector<u32>& parameters) {}
|
||||
|
||||
} // namespace Engines
|
||||
} // namespace Tegra
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Tegra {
|
||||
@@ -16,6 +17,13 @@ public:
|
||||
|
||||
/// Write the value to the register identified by method.
|
||||
void WriteReg(u32 method, u32 value);
|
||||
|
||||
/**
|
||||
* Handles a method call to this engine.
|
||||
* @param method Method to call
|
||||
* @param parameters Arguments to the method call
|
||||
*/
|
||||
void CallMethod(u32 method, const std::vector<u32>& parameters);
|
||||
};
|
||||
|
||||
} // namespace Engines
|
||||
|
||||
@@ -41,6 +41,9 @@ private:
|
||||
/// Writes a single register in the engine bound to the specified subchannel
|
||||
void WriteReg(u32 method, u32 subchannel, u32 value);
|
||||
|
||||
/// Calls a method in the engine bound to the specified subchannel with the input parameters.
|
||||
void CallMethod(u32 method, u32 subchannel, const std::vector<u32>& parameters);
|
||||
|
||||
/// Mapping of command subchannels to their bound engine ids.
|
||||
std::unordered_map<u32, EngineID> bound_engines;
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ void Config::ReadValues() {
|
||||
|
||||
qt_config->beginGroup("Core");
|
||||
Settings::values.cpu_core =
|
||||
static_cast<Settings::CpuCore>(qt_config->value("cpu_core", 0).toInt());
|
||||
static_cast<Settings::CpuCore>(qt_config->value("cpu_core", 1).toInt());
|
||||
qt_config->endGroup();
|
||||
|
||||
qt_config->beginGroup("Renderer");
|
||||
|
||||
Reference in New Issue
Block a user